From: Ben Pfaff Date: Mon, 15 Nov 2004 09:51:22 +0000 (+0000) Subject: Instead of making system or portable file readers responsible for X-Git-Tag: v0.4.0~230 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b321086267ad1014dc5d09886396cde30f094437;p=pspp-builds.git Instead of making system or portable file readers responsible for dropping and reordering variables, make them read full cases and let the caller take care of any changes. Instead of providing a system or portable file writer with a raw case in the format needed for output, provide it with a regular case. The writer takes care of any needed translation. Instead of treating `struct file_handle' as a class to subclass into data files, system files, and portable files, instead use it as a helper that coordinates access. Now it is opaque, too. Break dictionary functions into separate header file. Get rid of procedure-specific union in struct variable, using instead a void * pointer and a destructor function. --- diff --git a/po/en_GB.po b/po/en_GB.po index c74f702a..aec2bf56 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PSPP 0.3.1\n" "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n" -"POT-Creation-Date: 2004-11-09 08:18+0800\n" +"POT-Creation-Date: 2004-11-15 00:28-0800\n" "PO-Revision-Date: 2004-01-23 13:04+0800\n" "Last-Translator: John Darrington \n" "Language-Team: John Darrington \n" @@ -16,91 +16,91 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -#: src/aggregate.c:188 src/aggregate.c:223 src/data-list.c:1437 -#: src/data-list.c:1472 src/data-list.c:1485 src/data-list.c:1498 -#: src/data-list.c:1531 +#: src/aggregate.c:187 src/aggregate.c:220 src/data-list.c:1421 +#: src/data-list.c:1456 src/data-list.c:1469 src/data-list.c:1482 +#: src/data-list.c:1515 #, c-format msgid "%s subcommand given multiple times." msgstr "" -#: src/aggregate.c:208 +#: src/aggregate.c:205 msgid "while expecting COLUMNWISE" msgstr "" -#: src/aggregate.c:246 +#: src/aggregate.c:243 msgid "BREAK subcommand not specified." msgstr "" -#: src/aggregate.c:416 +#: src/aggregate.c:397 msgid "expecting aggregation function" msgstr "" -#: src/aggregate.c:432 +#: src/aggregate.c:413 #, c-format msgid "Unknown aggregation function %s." msgstr "" -#: src/aggregate.c:447 +#: src/aggregate.c:428 msgid "expecting `('" msgstr "" -#: src/aggregate.c:482 +#: src/aggregate.c:463 #, c-format msgid "Missing argument %d to %s." msgstr "" -#: src/aggregate.c:490 +#: src/aggregate.c:471 #, c-format msgid "Arguments to %s must be of same type as source variables." msgstr "" -#: src/aggregate.c:500 src/expr-prs.c:626 +#: src/aggregate.c:481 src/expr-prs.c:627 msgid "expecting `)'" msgstr "" -#: src/aggregate.c:512 +#: src/aggregate.c:493 #, c-format msgid "" "Number of source variables (%d) does not match number of target variables (%" "d)." msgstr "" -#: src/aggregate.c:581 +#: src/aggregate.c:562 #, c-format msgid "" "Variable name %s is not unique within the aggregate file dictionary, which " "contains the aggregate variables and the break variables." msgstr "" -#: src/apply-dict.c:65 +#: src/apply-dict.c:68 #, c-format msgid "Variable %s is %s in target file, but %s in source file." msgstr "" -#: src/apply-dict.c:68 src/apply-dict.c:69 src/expr-prs.c:1288 -#: src/expr-prs.c:1304 src/formats.c:96 src/pfm-read.c:636 src/print.c:689 -#: src/sfm-read.c:927 src/sfm-read.c:1057 src/sfm-read.c:1058 +#: src/apply-dict.c:71 src/apply-dict.c:72 src/expr-prs.c:1289 +#: src/expr-prs.c:1305 src/formats.c:96 src/pfm-read.c:604 src/print.c:695 +#: src/sfm-read.c:888 src/sfm-read.c:1017 src/sfm-read.c:1018 msgid "string" msgstr "" -#: src/apply-dict.c:68 src/apply-dict.c:69 src/expr-prs.c:1285 -#: src/expr-prs.c:1302 src/formats.c:96 src/pfm-read.c:636 src/print.c:689 -#: src/sfm-read.c:927 src/sfm-read.c:1057 src/sfm-read.c:1058 +#: src/apply-dict.c:71 src/apply-dict.c:72 src/expr-prs.c:1286 +#: src/expr-prs.c:1303 src/formats.c:96 src/pfm-read.c:604 src/print.c:695 +#: src/sfm-read.c:888 src/sfm-read.c:1017 src/sfm-read.c:1018 msgid "numeric" msgstr "" -#: src/apply-dict.c:81 +#: src/apply-dict.c:84 #, c-format msgid "Cannot add value labels from source file to long string variable %s." msgstr "" -#: src/apply-dict.c:127 +#: src/apply-dict.c:130 #, c-format msgid "" "Cannot apply missing values from source file to long string variable %s." msgstr "" -#: src/apply-dict.c:160 +#: src/apply-dict.c:163 msgid "No matching variables found between the source and target files." msgstr "" @@ -219,65 +219,65 @@ msgstr "" msgid "%s - Page %d" msgstr "" -#: src/autorecode.c:121 +#: src/autorecode.c:122 #, c-format msgid "Source variable count (%d) does not match target variable count (%d)." msgstr "" -#: src/autorecode.c:138 src/command.c:738 src/compute.c:293 -#: src/data-list.c:406 src/data-list.c:903 src/data-list.c:1764 -#: src/do-if.c:253 src/get.c:351 src/lexer.c:412 src/loop.c:240 -#: src/matrix-data.c:504 src/print.c:329 src/print.c:1039 src/recode.c:404 -#: src/sel-if.c:53 src/sel-if.c:130 src/vector.c:192 src/file-handle.q:141 +#: src/autorecode.c:139 src/command.c:739 src/compute.c:294 +#: src/data-list.c:407 src/data-list.c:897 src/data-list.c:1748 +#: src/do-if.c:253 src/get.c:405 src/lexer.c:412 src/loop.c:241 +#: src/matrix-data.c:527 src/print.c:335 src/print.c:1045 src/recode.c:405 +#: src/sel-if.c:54 src/sel-if.c:131 src/vector.c:193 src/file-handle.q:138 msgid "expecting end of command" msgstr "" -#: src/autorecode.c:148 +#: src/autorecode.c:149 #, c-format msgid "Target variable %s duplicates existing variable %s." msgstr "" -#: src/autorecode.c:155 +#: src/autorecode.c:156 #, c-format msgid "Duplicate variable name %s among target variables." msgstr "" -#: src/casefile.c:184 +#: src/casefile.c:182 #, c-format msgid "%s: Removing temporary file: %s." msgstr "" -#: src/casefile.c:329 +#: src/casefile.c:328 #, c-format msgid "Error writing temporary file: %s." msgstr "" -#: src/casefile.c:356 +#: src/casefile.c:355 #, c-format msgid "%s: Creating temporary file: %s." msgstr "" -#: src/casefile.c:500 +#: src/casefile.c:498 #, c-format msgid "%s: Opening temporary file: %s." msgstr "" -#: src/casefile.c:526 +#: src/casefile.c:524 #, c-format msgid "%s: Seeking temporary file: %s." msgstr "" -#: src/casefile.c:541 +#: src/casefile.c:540 #, c-format msgid "%s: Reading temporary file: %s." msgstr "" -#: src/casefile.c:544 +#: src/casefile.c:543 #, c-format msgid "%s: Temporary file ended unexpectedly." msgstr "" -#: src/cmdline.c:141 src/cmdline.c:160 src/cmdline.c:172 src/command.c:160 +#: src/cmdline.c:141 src/cmdline.c:160 src/cmdline.c:172 src/command.c:161 #: src/set.q:414 src/set.q:416 src/set.q:956 #, c-format msgid "%s is not yet implemented." @@ -350,25 +350,25 @@ msgid "" "Report bugs to <%s>.\n" msgstr "" -#: src/command.c:98 +#: src/command.c:99 #, c-format msgid "%s not allowed inside FILE TYPE/END FILE TYPE." msgstr "" -#: src/command.c:102 +#: src/command.c:103 #, c-format msgid "%s not allowed inside FILE TYPE GROUPED/END FILE TYPE." msgstr "" -#: src/command.c:105 +#: src/command.c:106 msgid "RECORD TYPE must be the first command inside a FILE TYPE structure." msgstr "" -#: src/command.c:150 +#: src/command.c:151 msgid "expecting command name" msgstr "" -#: src/command.c:179 +#: src/command.c:180 #, c-format msgid "" "%s is not allowed (1) before a command to specify the input program, such as " @@ -376,83 +376,83 @@ msgid "" "PROGRAM and END INPUT PROGRAM." msgstr "" -#: src/command.c:183 +#: src/command.c:184 #, c-format msgid "%s is not allowed within an input program." msgstr "" -#: src/command.c:184 src/command.c:185 +#: src/command.c:185 src/command.c:186 #, c-format msgid "%s is only allowed within an input program." msgstr "" -#: src/command.c:464 +#: src/command.c:465 #, c-format msgid "Unknown command %s." msgstr "" -#: src/command.c:564 +#: src/command.c:565 msgid "" "This command is not accepted in a syntax file. Instead, use FINISH to " "terminate a syntax file." msgstr "" -#: src/command.c:582 +#: src/command.c:583 msgid "" "This command is not executed in interactive mode. Instead, PSPP drops down " "to the command prompt. Use EXIT if you really want to quit." msgstr "" -#: src/command.c:625 src/command.c:756 +#: src/command.c:626 src/command.c:757 msgid "This command not allowed when the SAFER option is set." msgstr "" -#: src/command.c:637 +#: src/command.c:638 #, c-format msgid "Error removing `%s': %s." msgstr "" -#: src/command.c:687 +#: src/command.c:688 #, c-format msgid "Couldn't fork: %s." msgstr "" -#: src/command.c:729 +#: src/command.c:730 #, c-format msgid "Error executing command: %s." msgstr "" -#: src/command.c:777 +#: src/command.c:778 msgid "No operating system support for this command." msgstr "" -#: src/command.c:800 +#: src/command.c:801 msgid "This command is not valid in a syntax file." msgstr "" -#: src/compute.c:145 src/compute.c:209 +#: src/compute.c:146 src/compute.c:210 #, c-format msgid "" "When executing COMPUTE: SYSMIS is not a valid value as an index into vector %" "s." msgstr "" -#: src/compute.c:148 src/compute.c:213 +#: src/compute.c:149 src/compute.c:214 #, c-format msgid "" "When executing COMPUTE: %g is not a valid value as an index into vector %s." msgstr "" -#: src/compute.c:355 +#: src/compute.c:356 #, c-format msgid "There is no vector named %s." msgstr "" -#: src/count.c:155 +#: src/count.c:156 msgid "Destination cannot be a string variable." msgstr "" -#: src/count.c:262 +#: src/count.c:263 #, c-format msgid "" "%g THRU %g is not a valid range. The number following THRU must be at least " @@ -654,259 +654,259 @@ msgstr "" msgid "Only one of FIXED, FREE, or LIST may be specified." msgstr "" -#: src/data-list.c:353 src/print.c:290 +#: src/data-list.c:354 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:382 src/data-list.c:1753 +#: src/data-list.c:383 src/data-list.c:1737 msgid "" "SPSS-like or FORTRAN-like format specification expected after variable names." msgstr "" -#: src/data-list.c:393 +#: src/data-list.c:394 msgid "At least one variable must be specified." msgstr "" -#: src/data-list.c:398 src/print.c:322 +#: src/data-list.c:399 src/print.c:328 msgid "" "Variables are specified on records that should not exist according to " "RECORDS subcommand." msgstr "" -#: src/data-list.c:436 src/data-list.c:450 src/print.c:499 src/print.c:512 +#: src/data-list.c:437 src/data-list.c:451 src/print.c:505 src/print.c:518 msgid "Column positions for fields must be positive." msgstr "" -#: src/data-list.c:455 +#: src/data-list.c:456 msgid "The ending column for a field must be greater than the starting column." msgstr "" -#: src/data-list.c:469 src/print.c:589 +#: src/data-list.c:470 src/print.c:595 #, c-format msgid "The %d columns %d-%d can't be evenly divided into %d fields." msgstr "" -#: src/data-list.c:489 src/print.c:540 +#: src/data-list.c:490 src/print.c:546 msgid "A format specifier on this line has extra characters on the end." msgstr "" -#: src/data-list.c:504 src/print.c:556 +#: src/data-list.c:505 src/print.c:562 msgid "The value for number of decimal places must be at least 1." msgstr "" -#: src/data-list.c:518 src/print.c:569 +#: src/data-list.c:519 src/print.c:575 #, c-format msgid "Input format %s doesn't accept decimal places." msgstr "" -#: src/data-list.c:565 src/data-list.c:661 src/data-list.c:882 +#: src/data-list.c:566 src/data-list.c:662 src/data-list.c:876 #, c-format msgid "%s is a duplicate variable name." msgstr "" -#: src/data-list.c:570 +#: src/data-list.c:571 #, c-format msgid "There is already a variable %s of a different type." msgstr "" -#: src/data-list.c:577 +#: src/data-list.c:578 #, c-format msgid "There is already a string variable %s of a different width." msgstr "" -#: src/data-list.c:652 +#: src/data-list.c:653 msgid "" "The number of format specifications exceeds the given number of variable " "names." msgstr "" -#: src/data-list.c:765 src/print.c:762 +#: src/data-list.c:766 src/print.c:768 msgid "" "There aren't enough format specifications to match the number of variable " "names given." msgstr "" -#: src/data-list.c:794 src/data-list.c:924 src/descript.c:879 src/print.c:793 -#: src/sysfile-info.c:132 src/sysfile-info.c:365 src/vfm.c:874 +#: src/data-list.c:793 src/data-list.c:919 src/descript.c:880 src/print.c:799 +#: src/sysfile-info.c:134 src/sysfile-info.c:367 src/vfm.c:875 msgid "Variable" msgstr "" -#: src/data-list.c:795 src/print.c:794 +#: src/data-list.c:794 src/print.c:800 msgid "Record" msgstr "" -#: src/data-list.c:796 src/print.c:795 +#: src/data-list.c:795 src/print.c:801 msgid "Columns" msgstr "" -#: src/data-list.c:797 src/data-list.c:925 src/print.c:796 +#: src/data-list.c:796 src/data-list.c:920 src/print.c:802 msgid "Format" msgstr "" -#: src/data-list.c:817 +#: src/data-list.c:812 #, c-format msgid "Reading %d record from file %s." msgid_plural "Reading %d records from file %s." msgstr[0] "" msgstr[1] "" -#: src/data-list.c:819 +#: src/data-list.c:816 #, 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:948 +#: src/data-list.c:936 #, c-format msgid "Reading free-form data from file %s." msgstr "" -#: src/data-list.c:949 +#: src/data-list.c:939 msgid "Reading free-form data from the command file." msgstr "" -#: src/data-list.c:1002 +#: src/data-list.c:990 #, c-format msgid "Quoted string missing terminating `%c'." msgstr "" -#: src/data-list.c:1111 +#: src/data-list.c:1099 #, c-format msgid "Partial case of %d of %d records discarded." msgstr "" -#: src/data-list.c:1165 +#: src/data-list.c:1153 #, c-format msgid "Partial case discarded. The first variable missing was %s." msgstr "" -#: src/data-list.c:1209 +#: src/data-list.c:1197 #, 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:1287 +#: src/data-list.c:1275 msgid "Attempt to read past end of file." msgstr "" -#: src/data-list.c:1427 +#: src/data-list.c:1411 msgid "" "REPEATING DATA must use the same file as its corresponding DATA LIST or FILE " "TYPE." msgstr "" -#: src/data-list.c:1461 +#: src/data-list.c:1445 #, c-format msgid "STARTS beginning column (%d) exceeds STARTS ending column (%d)." msgstr "" -#: src/data-list.c:1517 +#: src/data-list.c:1501 #, c-format msgid "CONTINUED beginning column (%d) exceeds CONTINUED ending column (%d)." msgstr "" -#: src/data-list.c:1540 +#: src/data-list.c:1524 #, c-format msgid "ID beginning column (%ld) must be positive." msgstr "" -#: src/data-list.c:1555 +#: src/data-list.c:1539 #, c-format msgid "ID ending column (%ld) must be positive." msgstr "" -#: src/data-list.c:1561 +#: src/data-list.c:1545 #, c-format msgid "ID ending column (%ld) cannot be less than ID beginning column (%d)." msgstr "" -#: src/data-list.c:1601 +#: src/data-list.c:1585 msgid "Missing required specification STARTS." msgstr "" -#: src/data-list.c:1603 +#: src/data-list.c:1587 msgid "Missing required specification OCCURS." msgstr "" -#: src/data-list.c:1610 +#: src/data-list.c:1594 msgid "ID specified without CONTINUED." msgstr "" -#: src/data-list.c:1702 +#: src/data-list.c:1686 msgid "String variable not allowed here." msgstr "" -#: src/data-list.c:1712 +#: src/data-list.c:1696 #, c-format msgid "%s (%d) must be at least 1." msgstr "" -#: src/data-list.c:1718 +#: src/data-list.c:1702 #, c-format msgid "Variable or integer expected for %s." msgstr "" -#: src/data-list.c:1856 +#: src/data-list.c:1840 #, c-format msgid "Encountered mismatched record ID \"%s\" expecting \"%s\"." msgstr "" -#: src/data-list.c:1888 +#: src/data-list.c:1872 #, c-format msgid "" "Variable %s starting in column %d extends beyond physical record length of %" "d." msgstr "" -#: src/data-list.c:1956 +#: src/data-list.c:1940 #, c-format msgid "Invalid value %d for OCCURS." msgstr "" -#: src/data-list.c:1962 +#: src/data-list.c:1946 #, c-format msgid "Beginning column for STARTS (%d) must be at least 1." msgstr "" -#: src/data-list.c:1970 +#: src/data-list.c:1954 #, c-format msgid "Ending column for STARTS (%d) is less than beginning column (%d)." msgstr "" -#: src/data-list.c:1978 +#: src/data-list.c:1962 #, c-format msgid "Invalid value %d for LENGTH." msgstr "" -#: src/data-list.c:1985 +#: src/data-list.c:1969 #, c-format msgid "Beginning column for CONTINUED (%d) must be at least 1." msgstr "" -#: src/data-list.c:1993 +#: src/data-list.c:1977 #, c-format msgid "Ending column for CONTINUED (%d) is less than beginning column (%d)." msgstr "" -#: src/data-list.c:2025 +#: src/data-list.c:2009 #, 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:2043 +#: src/data-list.c:2027 #, c-format msgid "Unexpected end of file with %d repetitions remaining out of %d." msgstr "" -#: src/data-out.c:235 src/sfm-read.c:466 src/sysfile-info.c:113 +#: src/data-out.c:235 src/sfm-read.c:432 src/sysfile-info.c:115 msgid "Unknown" msgstr "" @@ -957,99 +957,99 @@ msgstr "" msgid "Only USE ALL is currently implemented." msgstr "" -#: src/descript.c:98 src/examine.q:584 src/frequencies.q:100 src/oneway.q:394 -#: src/t-test.q:681 src/t-test.q:704 src/t-test.q:827 src/t-test.q:1165 +#: src/descript.c:99 src/examine.q:631 src/frequencies.q:110 src/oneway.q:396 +#: src/t-test.q:683 src/t-test.q:706 src/t-test.q:829 src/t-test.q:1166 msgid "Mean" msgstr "" -#: src/descript.c:99 +#: src/descript.c:100 msgid "S E Mean" msgstr "" -#: src/descript.c:100 src/frequencies.q:104 +#: src/descript.c:101 src/frequencies.q:114 msgid "Std Dev" msgstr "" -#: src/descript.c:101 src/examine.q:641 src/frequencies.q:105 +#: src/descript.c:102 src/examine.q:694 src/frequencies.q:115 msgid "Variance" msgstr "" -#: src/descript.c:102 src/examine.q:711 src/frequencies.q:106 +#: src/descript.c:103 src/examine.q:764 src/frequencies.q:116 msgid "Kurtosis" msgstr "" -#: src/descript.c:103 +#: src/descript.c:104 msgid "S E Kurt" msgstr "" -#: src/descript.c:104 src/examine.q:706 src/frequencies.q:108 +#: src/descript.c:105 src/examine.q:759 src/frequencies.q:118 msgid "Skewness" msgstr "" -#: src/descript.c:105 +#: src/descript.c:106 msgid "S E Skew" msgstr "" -#: src/descript.c:106 src/examine.q:689 src/frequencies.q:110 +#: src/descript.c:107 src/examine.q:742 src/frequencies.q:120 msgid "Range" msgstr "" -#: src/descript.c:107 src/examine.q:666 src/frequencies.q:111 src/oneway.q:406 +#: src/descript.c:108 src/examine.q:719 src/frequencies.q:121 src/oneway.q:408 msgid "Minimum" msgstr "" -#: src/descript.c:108 src/examine.q:677 src/frequencies.q:112 src/oneway.q:407 +#: src/descript.c:109 src/examine.q:730 src/frequencies.q:122 src/oneway.q:409 msgid "Maximum" msgstr "" -#: src/descript.c:109 src/frequencies.q:113 +#: src/descript.c:110 src/frequencies.q:123 msgid "Sum" msgstr "" -#: src/descript.c:332 +#: src/descript.c:333 #, c-format msgid "Z-score variable name %s would be a duplicate variable name." msgstr "" -#: src/descript.c:350 src/list.q:140 +#: src/descript.c:351 src/list.q:142 msgid "No variables specified." msgstr "" -#: src/descript.c:434 +#: src/descript.c:435 msgid "expecting statistic name: reverting to default" msgstr "" -#: src/descript.c:507 +#: src/descript.c:508 msgid "" "Ran out of generic names for Z-score variables. There are only 126 generic " "names: ZSC001-ZSC0999, STDZ01-STDZ09, ZZZZ01-ZZZZ09, ZQZQ01-ZQZQ09." msgstr "" -#: src/descript.c:538 +#: src/descript.c:539 msgid "Mapping of variables to corresponding Z-scores." msgstr "" -#: src/descript.c:543 +#: src/descript.c:544 msgid "Source" msgstr "" -#: src/descript.c:544 +#: src/descript.c:545 msgid "Target" msgstr "" -#: src/descript.c:663 src/descript.c:669 +#: src/descript.c:664 src/descript.c:670 msgid "Z-score of " msgstr "" -#: src/descript.c:882 +#: src/descript.c:883 msgid "Valid N" msgstr "" -#: src/descript.c:883 +#: src/descript.c:884 msgid "Missing N" msgstr "" -#: src/descript.c:909 +#: src/descript.c:910 #, c-format msgid "Valid cases = %g; cases with missing value(s) = %g." msgstr "" @@ -1074,99 +1074,58 @@ msgstr "" msgid "Cannot open first page on DEVIND device %s." msgstr "" -#: src/dfm.c:88 src/dfm.c:565 -#, c-format -msgid "%s: Closing data-file handle %s." -msgstr "" - -#: src/dfm.c:115 -#, c-format -msgid "Cannot read from file %s already opened for %s." -msgstr "" - -#: src/dfm.c:129 -#, c-format -msgid "%s: Opening data-file handle %s for reading." -msgstr "" - -#: src/dfm.c:144 +#: src/dfm-read.c:153 #, c-format msgid "Could not open \"%s\" for reading as a data file: %s." msgstr "" -#: src/dfm.c:186 src/dfm.c:204 +#: src/dfm-read.c:186 src/dfm-read.c:204 msgid "BEGIN DATA expected." msgstr "" -#: src/dfm.c:213 +#: src/dfm-read.c:213 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.c:241 src/dfm.c:261 +#: src/dfm-read.c:246 src/dfm-read.c:266 #, c-format msgid "Error reading file %s: %s." msgstr "" -#: src/dfm.c:264 +#: src/dfm-read.c:269 #, c-format msgid "%s: Partial record at end of file." msgstr "" -#: src/dfm.c:300 +#: src/dfm-read.c:312 #, c-format msgid "Attempt to read beyond end-of-file on file %s." msgstr "" -#: src/dfm.c:446 -msgid "reading as a data file" -msgstr "" - -#: src/dfm.c:472 -#, c-format -msgid "Cannot write to file %s already opened for %s." -msgstr "" - -#: src/dfm.c:485 -#, c-format -msgid "%s: Opening data-file handle %s for writing." +#: src/dfm-read.c:315 +msgid "Attempt to read beyond END DATA." msgstr "" -#: src/dfm.c:491 -msgid "Cannot open the inline file for writing." +#: src/dfm-read.c:462 +msgid "" +"This command is not valid here since the current input program does not " +"access the inline file." msgstr "" -#: src/dfm.c:505 +#: src/dfm-write.c:67 #, c-format msgid "An error occurred while opening \"%s\" for writing as a data file: %s." msgstr "" -#: src/dfm.c:547 +#: src/dfm-write.c:103 #, c-format msgid "Error writing file %s: %s." msgstr "" -#: src/dfm.c:581 -msgid "writing as a data file" -msgstr "" - -#: src/dfm.c:598 -msgid "" -"This command is not valid here since the current input program does not " -"access the inline file." -msgstr "" - -#: src/dfm.c:605 -msgid "inline file: Opening for reading." -msgstr "" - -#: src/dfm.c:618 -msgid "Skipping remaining inline data." -msgstr "" - -#: src/dictionary.c:583 +#: src/dictionary.c:603 msgid "" "At least one case in the data file had a weight value that was user-missing, " "system-missing, zero, or negative. These case(s) were ignored." @@ -1235,7 +1194,7 @@ msgstr "" msgid "fatal" msgstr "" -#: src/error.c:259 src/error.c:266 src/error.c:269 src/expr-prs.c:1279 +#: src/error.c:259 src/error.c:266 src/error.c:269 src/expr-prs.c:1280 msgid "error" msgstr "" @@ -1251,54 +1210,54 @@ msgstr "" msgid "installation error" msgstr "" -#: src/expr-evl.c:633 +#: src/expr-evl.c:634 msgid "TIME.HMS cannot mix positive and negative in its arguments." msgstr "" -#: src/expr-evl.c:697 +#: src/expr-evl.c:698 #, fuzzy msgid "Week argument to WKYR must be in range 0 to 53." msgstr "Text colour must be in range 0-15." -#: src/expr-evl.c:848 src/expr-evl.c:904 +#: src/expr-evl.c:849 src/expr-evl.c:905 msgid "Argument 3 of RINDEX may not be system-missing." msgstr "" -#: src/expr-evl.c:858 src/expr-evl.c:914 +#: src/expr-evl.c:859 src/expr-evl.c:915 msgid "" "Argument 3 of RINDEX must be between 1 and the length of argument 2, and it " "must evenly divide the length of argument 2." msgstr "" -#: src/expr-evl.c:1100 +#: src/expr-evl.c:1101 msgid "" "A number being treated as a Boolean in an expression was found to have a " "value other than 0 (false), 1 (true), or the system-missing value. The " "result was forced to 0." msgstr "" -#: src/expr-evl.c:1141 +#: src/expr-evl.c:1142 #, c-format msgid "" "SYSMIS is not a valid index value for vector %s. The result will be set to " "SYSMIS." msgstr "" -#: src/expr-evl.c:1145 +#: src/expr-evl.c:1146 #, c-format msgid "" "%g is not a valid index value for vector %s. The result will be set to " "SYSMIS." msgstr "" -#: src/expr-evl.c:1164 +#: src/expr-evl.c:1165 #, c-format msgid "" "SYSMIS is not a valid index value for vector %s. The result will be set to " "the empty string." msgstr "" -#: src/expr-evl.c:1169 +#: src/expr-evl.c:1170 #, c-format msgid "" "%g is not a valid index value for vector %s. The result will be set to the " @@ -1311,29 +1270,29 @@ msgid "" "Boolean value was found to have a constant value other than 0, 1, or SYSMIS." msgstr "" -#: src/expr-prs.c:137 +#: src/expr-prs.c:138 msgid "" "Type mismatch: expression has string type, but a numeric value is required " "here." msgstr "" -#: src/expr-prs.c:148 +#: src/expr-prs.c:149 msgid "" "Type mismatch: expression has numeric type, but a string value is required " "here." msgstr "" -#: src/expr-prs.c:207 +#: src/expr-prs.c:208 #, c-format msgid "Type mismatch: operands of %s operator must be strings." msgstr "" -#: src/expr-prs.c:210 +#: src/expr-prs.c:211 #, c-format msgid "Type mismatch: operands of %s operator must be numeric." msgstr "" -#: src/expr-prs.c:391 +#: src/expr-prs.c:392 msgid "" "Chaining relational operators (e.g. \"a < b < c\") will not produce the " "mathematically expected result. Use the AND logical operator to fix the " @@ -1341,336 +1300,336 @@ msgid "" "parentheses will disable this warning (e.g. \"(a < b) < c\".)" msgstr "" -#: src/expr-prs.c:471 +#: src/expr-prs.c:472 msgid "" "The exponentiation operator (\"**\") is left-associative, even though right-" "associative semantics are more useful. That is, \"a**b**c\" equals \"(a**b)" "**c\", not as \"a**(b**c)\". To disable this warning, insert parentheses." msgstr "" -#: src/expr-prs.c:552 +#: src/expr-prs.c:553 #, c-format msgid "Unknown system variable %s." msgstr "" -#: src/expr-prs.c:591 +#: src/expr-prs.c:592 msgid "expecting variable name" msgstr "" -#: src/expr-prs.c:634 +#: src/expr-prs.c:635 msgid "in expression" msgstr "" -#: src/expr-prs.c:730 +#: src/expr-prs.c:731 msgid "Argument 2 to LAG must be a small positive integer constant." msgstr "" -#: src/expr-prs.c:811 src/expr-prs.c:850 +#: src/expr-prs.c:812 src/expr-prs.c:851 #, c-format msgid "" "Type mismatch in argument %d of %s, which was expected to be of %s type. It " "was actually of %s type. " msgstr "" -#: src/expr-prs.c:837 +#: src/expr-prs.c:838 #, c-format msgid "%s cannot take Boolean operands." msgstr "" -#: src/expr-prs.c:869 +#: src/expr-prs.c:870 msgid "in function call" msgstr "" -#: src/expr-prs.c:883 +#: src/expr-prs.c:884 msgid "RANGE requires an odd number of arguments, but at least three." msgstr "" -#: src/expr-prs.c:893 +#: src/expr-prs.c:894 #, c-format msgid "%s requires at least two arguments." msgstr "" -#: src/expr-prs.c:908 +#: src/expr-prs.c:909 #, c-format msgid "%s.%d requires at least %d arguments." msgstr "" -#: src/expr-prs.c:973 +#: src/expr-prs.c:974 #, c-format msgid "" "Argument %d to CONCAT is type %s. All arguments to CONCAT must be strings." msgstr "" -#: src/expr-prs.c:1070 +#: src/expr-prs.c:1071 #, c-format msgid "" "Argument %d to %s was expected to be of %s type. It was actually of type %s." msgstr "" -#: src/expr-prs.c:1087 +#: src/expr-prs.c:1088 #, c-format msgid "%s is not a numeric format." msgstr "" -#: src/expr-prs.c:1125 +#: src/expr-prs.c:1126 #, c-format msgid "Too few arguments to function %s." msgstr "" -#: src/expr-prs.c:1158 +#: src/expr-prs.c:1159 #, c-format msgid "" "Type mismatch in argument %d of %s. A string expression was supplied where " "only a numeric expression is allowed." msgstr "" -#: src/expr-prs.c:1168 +#: src/expr-prs.c:1169 #, c-format msgid "Missing comma following argument %d of %s." msgstr "" -#: src/expr-prs.c:1206 +#: src/expr-prs.c:1207 msgid "The index value after a vector name must be numeric." msgstr "" -#: src/expr-prs.c:1213 +#: src/expr-prs.c:1214 msgid "`)' expected after a vector index value." msgstr "" -#: src/expr-prs.c:1246 +#: src/expr-prs.c:1247 #, c-format msgid "There is no function named %s." msgstr "" -#: src/expr-prs.c:1251 +#: src/expr-prs.c:1252 #, c-format msgid "Function %s may not be given a minimum number of arguments." msgstr "" -#: src/expr-prs.c:1260 +#: src/expr-prs.c:1261 #, c-format msgid "expecting `)' after %s function" msgstr "" -#: src/expr-prs.c:1282 +#: src/expr-prs.c:1283 msgid "Boolean" msgstr "" -#: src/filename.c:221 -#, c-format -msgid "Searching for `%s'..." -msgstr "" - -#: src/filename.c:229 src/filename.c:261 -msgid "Search unsuccessful!" -msgstr "" - -#: src/filename.c:254 -#, c-format -msgid "Found `%s'." -msgstr "" - -#: src/filename.c:686 -#, c-format -msgid "Not opening pipe file `%s' because SAFER option set." -msgstr "" - -#: src/file-type.c:127 +#: src/file-type.c:129 msgid "MIXED, GROUPED, or NESTED expected." msgstr "" -#: src/file-type.c:150 +#: src/file-type.c:152 msgid "The CASE subcommand is not valid on FILE TYPE MIXED." msgstr "" -#: src/file-type.c:168 +#: src/file-type.c:170 msgid "WARN or NOWARN expected after WILD." msgstr "" -#: src/file-type.c:176 +#: src/file-type.c:178 msgid "The DUPLICATE subcommand is not valid on FILE TYPE MIXED." msgstr "" -#: src/file-type.c:190 +#: src/file-type.c:192 msgid "DUPLICATE=CASE is only valid on FILE TYPE NESTED." msgstr "" -#: src/file-type.c:199 +#: src/file-type.c:201 #, c-format msgid "WARN%s expected after DUPLICATE." msgstr "" -#: src/file-type.c:200 +#: src/file-type.c:202 msgid ", NOWARN, or CASE" msgstr "" -#: src/file-type.c:201 +#: src/file-type.c:203 msgid " or NOWARN" msgstr "" -#: src/file-type.c:209 +#: src/file-type.c:211 msgid "The MISSING subcommand is not valid on FILE TYPE MIXED." msgstr "" -#: src/file-type.c:221 +#: src/file-type.c:223 msgid "WARN or NOWARN after MISSING." msgstr "" -#: src/file-type.c:229 +#: src/file-type.c:231 msgid "ORDERED is only valid on FILE TYPE GROUPED." msgstr "" -#: src/file-type.c:240 +#: src/file-type.c:242 msgid "YES or NO expected after ORDERED." msgstr "" -#: src/file-type.c:246 src/file-type.c:540 src/get.c:335 +#: src/file-type.c:248 src/file-type.c:543 src/get.c:389 msgid "while expecting a valid subcommand" msgstr "" -#: src/file-type.c:253 +#: src/file-type.c:255 msgid "The required RECORD subcommand was not present." msgstr "" -#: src/file-type.c:261 +#: src/file-type.c:263 msgid "The required CASE subcommand was not present." msgstr "" -#: src/file-type.c:267 +#: src/file-type.c:269 msgid "CASE and RECORD must specify different variable names." msgstr "" -#: src/file-type.c:324 +#: src/file-type.c:327 msgid "Column value must be positive." msgstr "" -#: src/file-type.c:340 +#: src/file-type.c:343 msgid "Ending column precedes beginning column." msgstr "" -#: src/file-type.c:360 +#: src/file-type.c:363 msgid "Bad format specifier name." msgstr "" -#: src/file-type.c:389 src/file-type.c:577 +#: src/file-type.c:392 src/file-type.c:580 msgid "" "This command may only appear within a FILE TYPE/END FILE TYPE structure." msgstr "" -#: src/file-type.c:412 +#: src/file-type.c:415 msgid "OTHER may appear only on the last RECORD TYPE command." msgstr "" -#: src/file-type.c:422 +#: src/file-type.c:425 msgid "No input commands (DATA LIST, REPEATING DATA) for above RECORD TYPE." msgstr "" -#: src/file-type.c:473 +#: src/file-type.c:476 msgid "" "The CASE subcommand is not allowed on the RECORD TYPE command for FILE TYPE " "MIXED." msgstr "" -#: src/file-type.c:483 +#: src/file-type.c:486 msgid "" "No variable name may be specified for the CASE subcommand on RECORD TYPE." msgstr "" -#: src/file-type.c:491 +#: src/file-type.c:494 msgid "" "The CASE column specification on RECORD TYPE must give a format specifier " "that is the same type as that of the CASE column specification given on FILE " "TYPE." msgstr "" -#: src/file-type.c:507 +#: src/file-type.c:510 msgid "WARN or NOWARN expected on DUPLICATE subcommand." msgstr "" -#: src/file-type.c:521 +#: src/file-type.c:524 msgid "WARN or NOWARN expected on MISSING subcommand." msgstr "" -#: src/file-type.c:534 +#: src/file-type.c:537 msgid "YES or NO expected on SPREAD subcommand." msgstr "" -#: src/file-type.c:590 +#: src/file-type.c:593 msgid "No input commands (DATA LIST, REPEATING DATA) on above RECORD TYPE." msgstr "" -#: src/file-type.c:597 +#: src/file-type.c:600 msgid "No commands between FILE TYPE and END FILE TYPE." msgstr "" -#: src/file-type.c:666 +#: src/file-type.c:669 #, c-format msgid "Unknown record type \"%.*s\"." msgstr "" -#: src/file-type.c:690 +#: src/file-type.c:693 #, c-format msgid "Unknown record type %g." msgstr "" -#: src/flip.c:77 +#: src/filename.c:221 +#, c-format +msgid "Searching for `%s'..." +msgstr "" + +#: src/filename.c:229 src/filename.c:261 +msgid "Search unsuccessful!" +msgstr "" + +#: src/filename.c:254 +#, c-format +msgid "Found `%s'." +msgstr "" + +#: src/filename.c:686 +#, c-format +msgid "Not opening pipe file `%s' because SAFER option set." +msgstr "" + +#: src/flip.c:78 msgid "" "FLIP ignores TEMPORARY. Temporary transformations will be made permanent." msgstr "" -#: src/flip.c:217 +#: src/flip.c:218 #, c-format msgid "Could not create acceptable variant for variable %s." msgstr "" -#: src/flip.c:233 +#: src/flip.c:234 msgid "Cannot create more than 99999 variable names." msgstr "" -#: src/flip.c:277 +#: src/flip.c:278 msgid "Could not create temporary file for FLIP." msgstr "" -#: src/flip.c:284 src/flip.c:352 +#: src/flip.c:285 src/flip.c:353 #, c-format msgid "Error writing FLIP file: %s." msgstr "" -#: src/flip.c:394 +#: src/flip.c:395 #, c-format msgid "Error rewinding FLIP file: %s." msgstr "" -#: src/flip.c:398 +#: src/flip.c:399 msgid "Error creating FLIP source file." msgstr "" -#: src/flip.c:407 +#: src/flip.c:408 #, c-format msgid "Error reading FLIP file: %s." msgstr "" -#: src/flip.c:424 +#: src/flip.c:425 #, c-format msgid "Error seeking FLIP source file: %s." msgstr "" -#: src/flip.c:429 +#: src/flip.c:430 #, c-format msgid "Error writing FLIP source file: %s." msgstr "" -#: src/flip.c:440 +#: src/flip.c:441 #, c-format msgid "Error rewind FLIP source file: %s." msgstr "" -#: src/flip.c:492 +#: src/flip.c:493 #, c-format msgid "Error reading FLIP temporary file: %s." msgstr "" -#: src/flip.c:495 +#: src/flip.c:496 msgid "Unexpected end of file reading FLIP temporary file." msgstr "" @@ -1765,15 +1724,15 @@ msgstr "" msgid "Format %s may not be assigned to a %s variable." msgstr "" -#: src/formats.c:116 src/numeric.c:64 src/numeric.c:135 +#: src/formats.c:116 src/numeric.c:65 src/numeric.c:136 msgid "`)' expected after output format." msgstr "" -#: src/get.c:341 +#: src/get.c:395 msgid "All variables deleted from system file dictionary." msgstr "" -#: src/get.c:388 +#: src/get.c:445 #, c-format msgid "" "Cannot rename %s as %s because there already exists a variable named %s. To " @@ -1781,78 +1740,78 @@ msgid "" "as \"/RENAME (A=B)(B=C)(C=A)\", or equivalently, \"/RENAME (A B C=B C A)\"." msgstr "" -#: src/get.c:413 +#: src/get.c:470 msgid "`=' expected after variable list." msgstr "" -#: src/get.c:420 +#: src/get.c:477 #, 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:433 +#: src/get.c:490 #, c-format msgid "Requested renaming duplicates variable name %s." msgstr "" -#: src/get.c:564 +#: src/get.c:674 msgid "The BY subcommand may be given once at most." msgstr "" -#: src/get.c:631 +#: src/get.c:746 msgid "The active file may not be specified more than once." msgstr "" -#: src/get.c:640 +#: src/get.c:755 msgid "Cannot specify the active file since no active file has been defined." msgstr "" -#: src/get.c:648 +#: src/get.c:763 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:682 +#: src/get.c:793 msgid "" "IN, FIRST, and LAST subcommands may not occur before the first FILE or TABLE." msgstr "" -#: src/get.c:717 +#: src/get.c:828 #, c-format msgid "Multiple %s subcommands for a single FILE or TABLE." msgstr "" -#: src/get.c:727 +#: src/get.c:838 #, c-format msgid "Duplicate variable name %s while creating %s variable." msgstr "" -#: src/get.c:741 +#: src/get.c:850 msgid "" "RENAME, KEEP, and DROP subcommands may not occur before the first FILE or " "TABLE." msgstr "" -#: src/get.c:765 +#: src/get.c:877 msgid "The BY subcommand is required when a TABLE subcommand is given." msgstr "" -#: src/get.c:786 +#: src/get.c:896 #, c-format msgid "File %s lacks BY variable %s." msgstr "" -#: src/get.c:1282 +#: src/get.c:1390 #, 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:1330 +#: src/get.c:1468 msgid "expecting COMM or TAPE" msgstr "" @@ -2073,7 +2032,7 @@ msgstr "" msgid "HTML output driver: %s: %s" msgstr "" -#: src/html.c:403 src/list.q:250 +#: src/html.c:403 src/list.q:252 #, c-format msgid "Cannot open first page on HTML device %s." msgstr "" @@ -2082,27 +2041,27 @@ msgstr "" msgid "expecting filename" msgstr "" -#: src/inpt-pgm.c:81 +#: src/inpt-pgm.c:82 msgid "No matching INPUT PROGRAM command." msgstr "" -#: src/inpt-pgm.c:86 +#: src/inpt-pgm.c:87 msgid "" "No data-input or transformation commands specified between INPUT PROGRAM and " "END INPUT PROGRAM." msgstr "" -#: src/inpt-pgm.c:287 src/inpt-pgm.c:420 +#: src/inpt-pgm.c:288 src/inpt-pgm.c:418 msgid "" "This command may only be executed between INPUT PROGRAM and END INPUT " "PROGRAM." msgstr "" -#: src/inpt-pgm.c:342 +#: src/inpt-pgm.c:338 msgid "COLUMN subcommand multiply specified." msgstr "" -#: src/inpt-pgm.c:395 +#: src/inpt-pgm.c:391 msgid "" "REREAD: Column numbers must be positive finite numbers. Column set to 1." msgstr "" @@ -2166,7 +2125,7 @@ msgstr "" msgid "" msgstr "" -#: src/lexer.c:993 src/pfm-read.c:136 src/repeat.c:213 +#: src/lexer.c:993 src/pfm-read.c:134 src/repeat.c:214 msgid "Unexpected end of file." msgstr "" @@ -2207,232 +2166,232 @@ msgid "" "spaces." msgstr "" -#: src/loop.c:193 +#: src/loop.c:194 msgid "The index variable may not be a string variable." msgstr "" -#: src/loop.c:299 +#: src/loop.c:300 msgid "There is no LOOP command that corresponds to this END LOOP." msgstr "" -#: src/loop.c:493 +#: src/loop.c:494 msgid "" "This command may only appear enclosed in a LOOP/END LOOP control structure." msgstr "" -#: src/loop.c:499 +#: src/loop.c:500 msgid "BREAK not enclosed in DO IF structure." msgstr "" -#: src/loop.c:577 +#: src/loop.c:578 #, c-format msgid "%s without %s." msgstr "" -#: src/main.c:74 +#: src/main.c:76 msgid "Error initializing output drivers." msgstr "" -#: src/main.c:140 +#: src/main.c:146 msgid "This command not executed." msgstr "" -#: src/main.c:144 +#: src/main.c:150 msgid "" "Skipping the rest of this command. Part of this command may have been " "executed." msgstr "" -#: src/main.c:149 +#: src/main.c:155 msgid "" "Skipping the rest of this command. This command was fully executed up to " "this point." msgstr "" -#: src/main.c:154 +#: src/main.c:160 msgid "" "Trailing garbage was encountered following this command. The command was " "fully executed to this point." msgstr "" -#: src/main.c:171 +#: src/main.c:177 msgid "The rest of this command has been discarded." msgstr "" -#: src/matrix-data.c:185 +#: src/matrix-data.c:208 msgid "VARIABLES subcommand multiply specified." msgstr "" -#: src/matrix-data.c:200 +#: src/matrix-data.c:223 msgid "VARNAME_ cannot be explicitly specified on VARIABLES." msgstr "" -#: src/matrix-data.c:265 +#: src/matrix-data.c:284 msgid "in FORMAT subcommand" msgstr "" -#: src/matrix-data.c:276 +#: src/matrix-data.c:295 msgid "SPLIT subcommand multiply specified." msgstr "" -#: src/matrix-data.c:283 +#: src/matrix-data.c:302 msgid "in SPLIT subcommand" msgstr "" -#: src/matrix-data.c:292 +#: src/matrix-data.c:311 msgid "Split variable may not be named ROWTYPE_ or VARNAME_." msgstr "" -#: src/matrix-data.c:325 +#: src/matrix-data.c:345 #, c-format msgid "Split variable %s is already another type." msgstr "" -#: src/matrix-data.c:340 +#: src/matrix-data.c:360 msgid "FACTORS subcommand multiply specified." msgstr "" -#: src/matrix-data.c:355 +#: src/matrix-data.c:378 #, c-format msgid "Factor variable %s is already another type." msgstr "" -#: src/matrix-data.c:370 +#: src/matrix-data.c:393 msgid "CELLS subcommand multiply specified." msgstr "" -#: src/matrix-data.c:376 src/matrix-data.c:395 +#: src/matrix-data.c:399 src/matrix-data.c:418 msgid "expecting positive integer" msgstr "" -#: src/matrix-data.c:389 +#: src/matrix-data.c:412 msgid "N subcommand multiply specified." msgstr "" -#: src/matrix-data.c:410 +#: src/matrix-data.c:433 msgid "CONTENTS subcommand multiply specified." msgstr "" -#: src/matrix-data.c:430 +#: src/matrix-data.c:453 msgid "Nested parentheses not allowed." msgstr "" -#: src/matrix-data.c:440 +#: src/matrix-data.c:463 msgid "Mismatched right parenthesis (`(')." msgstr "" -#: src/matrix-data.c:445 +#: src/matrix-data.c:468 msgid "Empty parentheses not allowed." msgstr "" -#: src/matrix-data.c:458 src/matrix-data.c:466 +#: src/matrix-data.c:481 src/matrix-data.c:489 msgid "in CONTENTS subcommand" msgstr "" -#: src/matrix-data.c:473 +#: src/matrix-data.c:496 #, c-format msgid "Content multiply specified for %s." msgstr "" -#: src/matrix-data.c:490 +#: src/matrix-data.c:513 msgid "Missing right parenthesis." msgstr "" -#: src/matrix-data.c:510 +#: src/matrix-data.c:533 msgid "Missing VARIABLES subcommand." msgstr "" -#: src/matrix-data.c:516 +#: src/matrix-data.c:539 msgid "" "CONTENTS subcommand not specified: assuming file contains only CORR matrix." msgstr "" -#: src/matrix-data.c:526 +#: src/matrix-data.c:549 msgid "" "Missing CELLS subcommand. CELLS is required when ROWTYPE_ is not given in " "the data and factors are present." msgstr "" -#: src/matrix-data.c:534 +#: src/matrix-data.c:557 msgid "Split file values must be present in the data when ROWTYPE_ is present." msgstr "" -#: src/matrix-data.c:589 +#: src/matrix-data.c:610 msgid "No continuous variables specified." msgstr "" -#: src/matrix-data.c:815 +#: src/matrix-data.c:853 msgid "Scope of string exceeds line." msgstr "" -#: src/matrix-data.c:882 +#: src/matrix-data.c:920 #, c-format msgid "End of line expected %s while reading %s." msgstr "" -#: src/matrix-data.c:1070 +#: src/matrix-data.c:1106 #, c-format msgid "expecting value for %s %s" msgstr "" -#: src/matrix-data.c:1232 +#: src/matrix-data.c:1270 #, c-format msgid "Syntax error expecting SPLIT FILE value %s." msgstr "" -#: src/matrix-data.c:1241 +#: src/matrix-data.c:1279 #, c-format msgid "Expecting value %g for %s." msgstr "" -#: src/matrix-data.c:1282 src/matrix-data.c:1750 +#: src/matrix-data.c:1320 src/matrix-data.c:1787 #, c-format msgid "Syntax error expecting factor value %s." msgstr "" -#: src/matrix-data.c:1291 +#: src/matrix-data.c:1329 #, c-format msgid "Syntax error expecting value %g for %s %s." msgstr "" -#: src/matrix-data.c:1527 +#: src/matrix-data.c:1564 #, c-format msgid "Syntax error %s expecting SPLIT FILE value." msgstr "" -#: src/matrix-data.c:1657 +#: src/matrix-data.c:1694 #, c-format msgid "" "Expected %d lines of data for %s content; actually saw %d lines. No data " "will be output for this content." msgstr "" -#: src/matrix-data.c:1692 +#: src/matrix-data.c:1729 #, c-format msgid "Multiply specified ROWTYPE_ %s." msgstr "" -#: src/matrix-data.c:1697 +#: src/matrix-data.c:1734 #, c-format msgid "Syntax error %s expecting ROWTYPE_ string." msgstr "" -#: src/matrix-data.c:1717 +#: src/matrix-data.c:1754 #, c-format msgid "Syntax error %s." msgstr "" -#: src/matrix-data.c:1867 +#: src/matrix-data.c:1904 #, c-format msgid "Duplicate specification for %s." msgstr "" -#: src/matrix-data.c:1879 +#: src/matrix-data.c:1916 #, c-format msgid "Too many rows of matrix data for %s." msgstr "" -#: src/matrix-data.c:1927 +#: src/matrix-data.c:1964 #, c-format msgid "Syntax error expecting value for %s %s." msgstr "" @@ -2475,79 +2434,79 @@ msgstr "" msgid "String is not of proper length." msgstr "" -#: src/mis-val.c:316 src/repeat.c:459 +#: src/mis-val.c:316 src/repeat.c:460 msgid "String expected." msgstr "" -#: src/modify-vars.c:88 +#: src/modify-vars.c:89 msgid "" "MODIFY VARS may not be used after TEMPORARY. Temporary transformations will " "be made permanent." msgstr "" -#: src/modify-vars.c:112 +#: src/modify-vars.c:113 msgid "REORDER subcommand may be given at most once." msgstr "" -#: src/modify-vars.c:135 +#: src/modify-vars.c:136 msgid "Cannot specify ALL after specifying a set of variables." msgstr "" -#: src/modify-vars.c:145 +#: src/modify-vars.c:146 msgid "`(' expected on REORDER subcommand." msgstr "" -#: src/modify-vars.c:157 +#: src/modify-vars.c:158 msgid "`)' expected following variable names on REORDER subcommand." msgstr "" -#: src/modify-vars.c:175 +#: src/modify-vars.c:176 msgid "RENAME subcommand may be given at most once." msgstr "" -#: src/modify-vars.c:188 +#: src/modify-vars.c:189 msgid "`(' expected on RENAME subcommand." msgstr "" -#: src/modify-vars.c:196 +#: src/modify-vars.c:197 msgid "" "`=' expected between lists of new and old variable names on RENAME " "subcommand." msgstr "" -#: src/modify-vars.c:204 src/rename-vars.c:74 +#: src/modify-vars.c:205 src/rename-vars.c:75 #, c-format msgid "" "Differing number of variables in old name list (%d) and in new name list (%" "d)." msgstr "" -#: src/modify-vars.c:215 +#: src/modify-vars.c:216 msgid "`)' expected after variable lists on RENAME subcommand." msgstr "" -#: src/modify-vars.c:229 +#: src/modify-vars.c:230 msgid "" "KEEP subcommand may be given at most once. It may notbe given in " "conjunction with the DROP subcommand." msgstr "" -#: src/modify-vars.c:271 +#: src/modify-vars.c:272 msgid "" "DROP subcommand may be given at most once. It may not be given in " "conjunction with the KEEP subcommand." msgstr "" -#: src/modify-vars.c:297 +#: src/modify-vars.c:298 #, c-format msgid "Unrecognized subcommand name `%s'." msgstr "" -#: src/modify-vars.c:299 +#: src/modify-vars.c:300 msgid "Subcommand name expected." msgstr "" -#: src/modify-vars.c:307 +#: src/modify-vars.c:308 msgid "`/' or `.' expected." msgstr "" @@ -2555,17 +2514,17 @@ msgstr "" msgid "expecting weight value" msgstr "" -#: src/numeric.c:57 +#: src/numeric.c:58 #, c-format msgid "Format type %s may not be used with a numeric variable." msgstr "" -#: src/numeric.c:76 src/numeric.c:158 src/vector.c:155 +#: src/numeric.c:77 src/numeric.c:159 src/vector.c:156 #, c-format msgid "There is already a variable named %s." msgstr "" -#: src/numeric.c:128 +#: src/numeric.c:129 #, c-format msgid "Format type %s may not be used with a string variable." msgstr "" @@ -2750,223 +2709,179 @@ msgstr "" msgid "portable file %s corrupt at offset %ld: " msgstr "" -#: src/pfm-read.c:111 src/pfm-write.c:504 +#: src/pfm-read.c:114 src/pfm-write.c:490 #, c-format msgid "%s: Closing portable file: %s." msgstr "" -#: src/pfm-read.c:144 +#: src/pfm-read.c:142 msgid "Bad line end." msgstr "" -#: src/pfm-read.c:225 -#, c-format -msgid "Cannot read file %s as portable file: already opened for %s." -msgstr "" - -#: src/pfm-read.c:231 -#, c-format -msgid "%s: Opening portable-file handle %s for reading." -msgstr "" - -#: src/pfm-read.c:239 +#: src/pfm-read.c:233 #, c-format msgid "" "An error occurred while opening \"%s\" for reading as a portable file: %s." msgstr "" -#: src/pfm-read.c:274 +#: src/pfm-read.c:256 msgid "Data record expected." msgstr "" -#: src/pfm-read.c:276 -msgid "Read portable-file dictionary successfully." -msgstr "" - -#: src/pfm-read.c:282 -msgid "Error reading portable-file dictionary." -msgstr "" - -#: src/pfm-read.c:380 +#: src/pfm-read.c:353 msgid "Missing numeric terminator." msgstr "" -#: src/pfm-read.c:417 +#: src/pfm-read.c:390 msgid "Bad integer format." msgstr "" -#: src/pfm-read.c:447 +#: src/pfm-read.c:419 #, c-format msgid "Bad string length %d." msgstr "" -#: src/pfm-read.c:546 +#: src/pfm-read.c:514 #, c-format msgid "Bad date string length %d." msgstr "" -#: src/pfm-read.c:550 +#: src/pfm-read.c:518 msgid "Bad character in date." msgstr "" -#: src/pfm-read.c:570 +#: src/pfm-read.c:538 #, c-format msgid "Bad time string length %d." msgstr "" -#: src/pfm-read.c:574 +#: src/pfm-read.c:542 msgid "Bad character in time." msgstr "" -#: src/pfm-read.c:624 src/pfm-read.c:631 src/sfm-read.c:912 src/sfm-read.c:920 +#: src/pfm-read.c:592 src/pfm-read.c:599 src/sfm-read.c:873 src/sfm-read.c:881 #, c-format msgid "%s: Bad format specifier byte (%d)." msgstr "" -#: src/pfm-read.c:633 +#: src/pfm-read.c:601 #, c-format msgid "%s variable %s has %s format specifier %s." msgstr "" -#: src/pfm-read.c:634 src/print.c:601 src/sfm-read.c:925 +#: src/pfm-read.c:602 src/print.c:607 src/sfm-read.c:886 msgid "String" msgstr "" -#: src/pfm-read.c:634 src/print.c:601 src/sfm-read.c:925 +#: src/pfm-read.c:602 src/print.c:607 src/sfm-read.c:886 msgid "Numeric" msgstr "" -#: src/pfm-read.c:673 +#: src/pfm-read.c:640 msgid "Expected variable count record." msgstr "" -#: src/pfm-read.c:677 +#: src/pfm-read.c:644 #, c-format msgid "Invalid number of variables %d." msgstr "" -#: src/pfm-read.c:687 +#: src/pfm-read.c:654 #, c-format msgid "Unexpected flag value %d." msgstr "" -#: src/pfm-read.c:701 +#: src/pfm-read.c:666 #, c-format msgid "Weight variable name (%s) truncated." msgstr "" -#: src/pfm-read.c:716 +#: src/pfm-read.c:681 msgid "Expected variable record." msgstr "" -#: src/pfm-read.c:722 +#: src/pfm-read.c:687 #, c-format msgid "Invalid variable width %d." msgstr "" -#: src/pfm-read.c:740 +#: src/pfm-read.c:705 #, c-format msgid "position %d: Variable name has %u characters." msgstr "" -#: src/pfm-read.c:744 +#: src/pfm-read.c:709 #, c-format msgid "position %d: Variable name begins with invalid character." msgstr "" -#: src/pfm-read.c:748 +#: src/pfm-read.c:713 #, c-format msgid "position %d: Variable name begins with lowercase letter %c." msgstr "" -#: src/pfm-read.c:761 +#: src/pfm-read.c:726 #, c-format msgid "position %d: Variable name character %d is lowercase letter %c." msgstr "" -#: src/pfm-read.c:771 +#: src/pfm-read.c:736 #, c-format msgid "position %d: character `\\%03o' is not valid in a variable name." msgstr "" -#: src/pfm-read.c:782 +#: src/pfm-read.c:748 #, c-format msgid "Duplicate variable name %s." msgstr "" -#: src/pfm-read.c:826 +#: src/pfm-read.c:792 #, c-format msgid "Bad missing values for %s." msgstr "" -#: src/pfm-read.c:849 +#: src/pfm-read.c:815 #, c-format msgid "Weighting variable %s not present in dictionary." msgstr "" -#: src/pfm-read.c:922 +#: src/pfm-read.c:886 #, c-format msgid "Unknown variable %s while parsing value labels." msgstr "" -#: src/pfm-read.c:925 +#: src/pfm-read.c:889 #, c-format msgid "" "Cannot assign value labels to %s and %s, which have different variable types " "or widths." msgstr "" -#: src/pfm-read.c:958 +#: src/pfm-read.c:922 #, c-format msgid "Duplicate label for value %g for variable %s." msgstr "" -#: src/pfm-read.c:961 +#: src/pfm-read.c:925 #, c-format msgid "Duplicate label for value `%.*s' for variable %s." msgstr "" -#: src/pfm-read.c:1032 +#: src/pfm-read.c:978 msgid "End of file midway through case." msgstr "" -#: src/pfm-read.c:1042 -msgid "reading as a portable file" -msgstr "" - -#: src/pfm-write.c:71 -#, c-format -msgid "Cannot write file %s as portable file: already opened for %s." -msgstr "" - -#: src/pfm-write.c:77 -#, c-format -msgid "%s: Opening portable-file handle %s for writing." -msgstr "" - -#: src/pfm-write.c:87 +#: src/pfm-write.c:92 #, c-format msgid "" "An error occurred while opening \"%s\" for writing as a portable file: %s." msgstr "" -#: src/pfm-write.c:124 -msgid "Wrote portable-file header successfully." -msgstr "" - -#: src/pfm-write.c:129 -msgid "Error writing portable-file header." -msgstr "" - -#: src/pfm-write.c:170 +#: src/pfm-write.c:154 #, c-format msgid "%s: Writing portable file: %s." msgstr "" -#: src/pfm-write.c:514 -msgid "writing as a portable file" -msgstr "" - #: src/postscript.c:323 #, c-format msgid "PostScript driver initializing as `%s'..." @@ -3098,80 +3013,80 @@ msgstr "" msgid "PostScript driver: Cannot find encoding `%s' for PostScript font `%s'." msgstr "" -#: src/print.c:180 +#: src/print.c:179 msgid "expecting a valid subcommand" msgstr "" -#: src/print.c:359 src/print.c:376 +#: src/print.c:365 src/print.c:382 #, c-format msgid "%g is not a valid column location." msgstr "" -#: src/print.c:370 +#: src/print.c:376 #, c-format msgid "Column location expected following `%d-'." msgstr "" -#: src/print.c:381 +#: src/print.c:387 #, c-format msgid "" "%d-%ld is not a valid column range. The second column must be greater than " "or equal to the first." msgstr "" -#: src/print.c:487 +#: src/print.c:493 #, c-format msgid "" "%s is not of the same type as %s. To specify variables of different types " "in the same variable list, use a FORTRAN-like format specifier." msgstr "" -#: src/print.c:517 +#: src/print.c:523 msgid "" "The ending column for a field must not be less than the starting column." msgstr "" -#: src/print.c:600 +#: src/print.c:606 #, c-format msgid "%s variables cannot be displayed with format %s." msgstr "" -#: src/print.c:678 +#: src/print.c:684 msgid "" "The number of format specifications exceeds the number of variable names " "given." msgstr "" -#: src/print.c:687 +#: src/print.c:693 #, c-format msgid "Display format %s may not be used with a %s variable." msgstr "" -#: src/print.c:835 +#: src/print.c:841 #, c-format msgid "Writing %d record(s) to file %s." msgstr "" -#: src/print.c:838 +#: src/print.c:844 #, c-format msgid "Writing %d record(s) to the listing file." msgstr "" -#: src/print.c:1080 +#: src/print.c:1092 #, c-format msgid "" "The expression on PRINT SPACE evaluated to %d. It's not possible to PRINT " "SPACE a negative number of lines." msgstr "" -#: src/recode.c:282 +#: src/recode.c:283 #, c-format msgid "" "%d variable(s) cannot be recoded into %d variable(s). Specify the same " "number of variables as input and output variables." msgstr "" -#: src/recode.c:296 +#: src/recode.c:297 #, c-format msgid "" "There is no string variable named %s. (All string variables specified on " @@ -3179,83 +3094,83 @@ msgid "" "variable.)" msgstr "" -#: src/recode.c:305 +#: src/recode.c:306 #, c-format msgid "" "Type mismatch between input and output variables. Output variable %s is not " "a string variable, but all the input variables are string variables." msgstr "" -#: src/recode.c:324 +#: src/recode.c:325 #, c-format msgid "Type mismatch after INTO: %s is not a numeric variable." msgstr "" -#: src/recode.c:354 +#: src/recode.c:355 msgid "" "INTO must be used when the input values are numeric and output values are " "string." msgstr "" -#: src/recode.c:362 +#: src/recode.c:363 msgid "" "INTO must be used when the input values are string and output values are " "numeric." msgstr "" -#: src/recode.c:485 +#: src/recode.c:486 msgid "expecting output value" msgstr "" -#: src/recode.c:499 +#: src/recode.c:500 msgid "" "Inconsistent output types. The output values must be all numeric or all " "string." msgstr "" -#: src/recode.c:550 +#: src/recode.c:551 msgid "following LO THRU" msgstr "" -#: src/recode.c:566 src/recode.c:595 +#: src/recode.c:567 src/recode.c:596 msgid "in source value" msgstr "" -#: src/recode.c:608 +#: src/recode.c:609 msgid "" "Keyword CONVERT may only be used with string input values and numeric output " "values." msgstr "" -#: src/rename-vars.c:47 +#: src/rename-vars.c:48 msgid "" "RENAME VARS may not be used after TEMPORARY. Temporary transformations will " "be made permanent." msgstr "" -#: src/rename-vars.c:59 +#: src/rename-vars.c:60 msgid "`(' expected." msgstr "" -#: src/rename-vars.c:67 +#: src/rename-vars.c:68 msgid "`=' expected between lists of new and old variable names." msgstr "" -#: src/rename-vars.c:85 +#: src/rename-vars.c:86 msgid "`)' expected after variable names." msgstr "" -#: src/rename-vars.c:95 +#: src/rename-vars.c:96 #, c-format msgid "Renaming would duplicate variable name %s." msgstr "" -#: src/repeat.c:150 +#: src/repeat.c:151 #, c-format msgid "Identifier %s is given twice." msgstr "" -#: src/repeat.c:193 +#: src/repeat.c:194 #, c-format msgid "" "There must be the same number of substitutions for each dummy variable " @@ -3263,11 +3178,11 @@ msgid "" "s as well, but %d were specified." msgstr "" -#: src/repeat.c:298 +#: src/repeat.c:299 msgid "No commands in scope." msgstr "" -#: src/repeat.c:486 +#: src/repeat.c:487 msgid "No matching DO REPEAT." msgstr "" @@ -3280,129 +3195,111 @@ msgstr "" msgid "Cannot sample %d observations from a population of %d." msgstr "" -#: src/sel-if.c:99 +#: src/sel-if.c:100 msgid "The filter variable must be numeric." msgstr "" -#: src/sel-if.c:105 +#: src/sel-if.c:106 msgid "The filter variable may not be scratch." msgstr "" -#: src/sel-if.c:136 +#: src/sel-if.c:137 msgid "Only last instance of this command is in effect." msgstr "" -#: src/sfm-read.c:147 +#: src/sfm-read.c:140 msgid "corrupt system file: " msgstr "" -#: src/sfm-read.c:163 src/sfm-write.c:743 +#: src/sfm-read.c:157 src/sfm-write.c:808 #, c-format msgid "%s: Closing system file: %s." msgstr "" -#: src/sfm-read.c:237 -#, c-format -msgid "Cannot read file %s as system file: already opened for %s." -msgstr "" - -#: src/sfm-read.c:242 -#, c-format -msgid "%s: Opening system-file handle %s for reading." -msgstr "" - -#: src/sfm-read.c:250 +#: src/sfm-read.c:240 #, c-format msgid "" "An error occurred while opening \"%s\" for reading as a system file: %s." msgstr "" -#: src/sfm-read.c:285 +#: src/sfm-read.c:258 #, c-format msgid "" "%s: Weighting variable may not be a continuation of a long string variable." msgstr "" -#: src/sfm-read.c:288 +#: src/sfm-read.c:261 #, c-format msgid "%s: Weighting variable may not be a string variable." msgstr "" -#: src/sfm-read.c:313 +#: src/sfm-read.c:286 #, 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:362 +#: src/sfm-read.c:335 #, c-format msgid "%s: Unrecognized record type 7, subtype %d encountered in system file." msgstr "" -#: src/sfm-read.c:387 +#: src/sfm-read.c:360 #, c-format msgid "%s: Unrecognized record type %d." msgstr "" -#: src/sfm-read.c:394 -msgid "Read system-file dictionary successfully." -msgstr "" - -#: src/sfm-read.c:401 -msgid "Error reading system-file header." -msgstr "" - -#: src/sfm-read.c:425 +#: src/sfm-read.c:392 #, 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:437 +#: src/sfm-read.c:403 #, 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:453 +#: src/sfm-read.c:419 #, c-format msgid "" "%s: File-indicated endianness (%s) does not match endianness intuited from " "file header (%s)." msgstr "" -#: src/sfm-read.c:456 src/sfm-read.c:457 +#: src/sfm-read.c:422 src/sfm-read.c:423 msgid "big-endian" msgstr "" -#: src/sfm-read.c:456 src/sfm-read.c:457 +#: src/sfm-read.c:422 src/sfm-read.c:423 msgid "little-endian" msgstr "" -#: src/sfm-read.c:458 +#: src/sfm-read.c:424 msgid "unknown" msgstr "" -#: src/sfm-read.c:462 +#: src/sfm-read.c:428 #, c-format msgid "%s: File-indicated character representation code (%s) is not ASCII." msgstr "" -#: src/sfm-read.c:466 +#: src/sfm-read.c:432 msgid "DEC Kanji" msgstr "" -#: src/sfm-read.c:485 +#: src/sfm-read.c:448 #, 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:500 +#: src/sfm-read.c:463 #, c-format msgid "" "%s: File-indicated value is different from internal value for at least one " @@ -3410,263 +3307,236 @@ msgid "" "%g; LOWEST: %g, %g." msgstr "" -#: src/sfm-read.c:531 +#: src/sfm-read.c:490 #, 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:574 +#: src/sfm-read.c:532 #, 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:590 +#: src/sfm-read.c:548 #, c-format msgid "%s: Number of elements per case (%d) is not between 1 and %d." msgstr "" -#: src/sfm-read.c:599 +#: src/sfm-read.c:557 #, 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:605 +#: src/sfm-read.c:564 #, c-format msgid "%s: Number of cases in file (%ld) is not between -1 and %d." msgstr "" -#: src/sfm-read.c:610 +#: src/sfm-read.c:569 #, c-format msgid "%s: Compression bias (%g) is not the usual value of 100." msgstr "" -#: src/sfm-read.c:704 +#: src/sfm-read.c:662 #, c-format msgid "%s: position %d: Bad record type (%d); the expected value was 2." msgstr "" -#: src/sfm-read.c:714 +#: src/sfm-read.c:672 #, c-format msgid "" "%s: position %d: String variable does not have proper number of continuation " "records." msgstr "" -#: src/sfm-read.c:723 +#: src/sfm-read.c:681 #, c-format msgid "%s: position %d: Superfluous long string continuation record." msgstr "" -#: src/sfm-read.c:729 +#: src/sfm-read.c:687 #, c-format msgid "%s: position %d: Bad variable type code %d." msgstr "" -#: src/sfm-read.c:732 +#: src/sfm-read.c:690 #, c-format msgid "%s: position %d: Variable label indicator field is not 0 or 1." msgstr "" -#: src/sfm-read.c:736 +#: src/sfm-read.c:694 #, c-format msgid "" "%s: position %d: Missing value indicator field is not -3, -2, 0, 1, 2, or 3." msgstr "" -#: src/sfm-read.c:742 +#: src/sfm-read.c:700 #, c-format msgid "%s: position %d: Variable name begins with invalid character." msgstr "" -#: src/sfm-read.c:746 +#: src/sfm-read.c:704 #, c-format msgid "%s: position %d: Variable name begins with lowercase letter %c." msgstr "" -#: src/sfm-read.c:750 +#: src/sfm-read.c:708 #, c-format msgid "" "%s: position %d: Variable name begins with octothorpe (`#'). Scratch " "variables should not appear in system files." msgstr "" -#: src/sfm-read.c:765 +#: src/sfm-read.c:723 #, c-format msgid "%s: position %d: Variable name character %d is lowercase letter %c." msgstr "" -#: src/sfm-read.c:774 +#: src/sfm-read.c:732 #, c-format msgid "" "%s: position %d: character `\\%03o' (%c) is not valid in a variable name." msgstr "" -#: src/sfm-read.c:783 +#: src/sfm-read.c:741 #, c-format msgid "%s: Duplicate variable name `%s' within system file." msgstr "" -#: src/sfm-read.c:808 +#: src/sfm-read.c:762 #, c-format msgid "%s: Variable %s indicates variable label of invalid length %d." msgstr "" -#: src/sfm-read.c:825 +#: src/sfm-read.c:779 #, c-format msgid "%s: Long string variable %s may not have missing values." msgstr "" -#: src/sfm-read.c:850 +#: src/sfm-read.c:804 #, c-format msgid "" "%s: String variable %s may not have missing values specified as a range." msgstr "" -#: src/sfm-read.c:888 +#: src/sfm-read.c:852 #, c-format msgid "%s: Long string continuation records omitted at end of dictionary." msgstr "" -#: src/sfm-read.c:892 +#: src/sfm-read.c:856 #, c-format msgid "" "%s: System file header indicates %d variable positions but %d were read from " "file." msgstr "" -#: src/sfm-read.c:923 +#: src/sfm-read.c:884 #, c-format msgid "%s: %s variable %s has %s format specifier %s." msgstr "" -#: src/sfm-read.c:1003 +#: src/sfm-read.c:963 #, 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:1014 +#: src/sfm-read.c:974 #, 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:1030 +#: src/sfm-read.c:990 #, 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:1037 +#: src/sfm-read.c:997 #, 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:1042 +#: src/sfm-read.c:1002 #, c-format msgid "%s: Value labels are not allowed on long string variables (%s)." msgstr "" -#: src/sfm-read.c:1053 +#: src/sfm-read.c:1013 #, 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:1094 +#: src/sfm-read.c:1054 #, c-format msgid "%s: File contains duplicate label for value %g for variable %s." msgstr "" -#: src/sfm-read.c:1098 +#: src/sfm-read.c:1058 #, c-format msgid "%s: File contains duplicate label for value `%.*s' for variable %s." msgstr "" -#: src/sfm-read.c:1135 src/sfm-read.c:1338 +#: src/sfm-read.c:1093 src/sfm-read.c:1357 #, c-format msgid "%s: Reading system file: %s." msgstr "" -#: src/sfm-read.c:1138 src/sfm-read.c:1245 src/sfm-read.c:1287 +#: src/sfm-read.c:1096 src/sfm-read.c:1198 src/sfm-read.c:1240 #, c-format msgid "%s: Unexpected end of file." msgstr "" -#: src/sfm-read.c:1157 +#: src/sfm-read.c:1113 #, c-format msgid "%s: System file contains multiple type 6 (document) records." msgstr "" -#: src/sfm-read.c:1163 +#: src/sfm-read.c:1119 #, c-format msgid "%s: Number of document lines (%ld) must be greater than 0." msgstr "" -#: src/sfm-read.c:1196 +#: src/sfm-read.c:1151 #, c-format msgid "%s: Error reading file: %s." msgstr "" -#: src/sfm-read.c:1235 +#: src/sfm-read.c:1188 #, c-format msgid "%s: Compressed data is corrupted. Data ends in partial case." msgstr "" -#: src/sfm-read.c:1341 +#: src/sfm-read.c:1360 #, c-format msgid "%s: Partial record at end of system file." msgstr "" -#: src/sfm-read.c:1380 -msgid "reading as a system file" -msgstr "" - -#: src/sfm-write.c:95 -#, c-format -msgid "Cannot write file %s as system file: already opened for %s." -msgstr "" - -#: src/sfm-write.c:101 -#, c-format -msgid "%s: Opening system-file handle %s for writing." -msgstr "" - -#: src/sfm-write.c:111 +#: src/sfm-write.c:143 #, c-format -msgid "" -"An error occurred while opening \"%s\" for writing as a system file: %s." -msgstr "" - -#: src/sfm-write.c:165 -msgid "Wrote system-file header successfully." +msgid "Error opening \"%s\" for writing as a system file: %s." msgstr "" -#: src/sfm-write.c:170 -msgid "Error writing system-file header." -msgstr "" - -#: src/sfm-write.c:606 +#: src/sfm-write.c:628 #, c-format msgid "%s: Writing system file: %s." msgstr "" -#: src/sfm-write.c:754 -msgid "writing as a system file" -msgstr "" - #: src/sort.c:197 msgid "`A' or `D' expected inside parentheses." msgstr "" @@ -3682,141 +3552,141 @@ msgid "" "each. (PSPP workspace is currently restricted to a maximum of %d KB.)" msgstr "" -#: src/sysfile-info.c:94 +#: src/sysfile-info.c:96 msgid "File:" msgstr "" -#: src/sysfile-info.c:96 +#: src/sysfile-info.c:98 msgid "Label:" msgstr "" -#: src/sysfile-info.c:100 +#: src/sysfile-info.c:102 msgid "No label." msgstr "" -#: src/sysfile-info.c:103 +#: src/sysfile-info.c:105 msgid "Created:" msgstr "" -#: src/sysfile-info.c:106 +#: src/sysfile-info.c:108 msgid "Endian:" msgstr "" -#: src/sysfile-info.c:107 +#: src/sysfile-info.c:109 msgid "Big." msgstr "" -#: src/sysfile-info.c:107 +#: src/sysfile-info.c:109 msgid "Little." msgstr "" -#: src/sysfile-info.c:108 +#: src/sysfile-info.c:110 msgid "Variables:" msgstr "" -#: src/sysfile-info.c:111 +#: src/sysfile-info.c:113 msgid "Cases:" msgstr "" -#: src/sysfile-info.c:114 +#: src/sysfile-info.c:116 msgid "Type:" msgstr "" -#: src/sysfile-info.c:115 +#: src/sysfile-info.c:117 msgid "System File." msgstr "" -#: src/sysfile-info.c:116 +#: src/sysfile-info.c:118 msgid "Weight:" msgstr "" -#: src/sysfile-info.c:120 +#: src/sysfile-info.c:122 msgid "Not weighted." msgstr "" -#: src/sysfile-info.c:122 +#: src/sysfile-info.c:124 msgid "Mode:" msgstr "" -#: src/sysfile-info.c:124 +#: src/sysfile-info.c:126 #, c-format msgid "Compression %s." msgstr "" -#: src/sysfile-info.c:124 +#: src/sysfile-info.c:126 msgid "on" msgstr "" -#: src/sysfile-info.c:124 +#: src/sysfile-info.c:126 msgid "off" msgstr "" -#: src/sysfile-info.c:133 src/sysfile-info.c:370 +#: src/sysfile-info.c:135 src/sysfile-info.c:372 msgid "Description" msgstr "" -#: src/sysfile-info.c:134 src/sysfile-info.c:368 +#: src/sysfile-info.c:136 src/sysfile-info.c:370 msgid "Position" msgstr "" -#: src/sysfile-info.c:191 +#: src/sysfile-info.c:193 msgid "The active file does not have a file label." msgstr "" -#: src/sysfile-info.c:194 +#: src/sysfile-info.c:196 msgid "File label:" msgstr "" -#: src/sysfile-info.c:256 +#: src/sysfile-info.c:258 msgid "No variables to display." msgstr "" -#: src/sysfile-info.c:275 +#: src/sysfile-info.c:277 msgid "Macros not supported." msgstr "" -#: src/sysfile-info.c:285 +#: src/sysfile-info.c:287 msgid "The active file dictionary does not contain any documents." msgstr "" -#: src/sysfile-info.c:294 +#: src/sysfile-info.c:296 msgid "Documents in the active file:" msgstr "" -#: src/sysfile-info.c:372 src/sysfile-info.c:530 src/vfm.c:876 +#: src/sysfile-info.c:374 src/sysfile-info.c:532 src/vfm.c:877 msgid "Label" msgstr "" -#: src/sysfile-info.c:444 +#: src/sysfile-info.c:446 #, c-format msgid "Format: %s" msgstr "" -#: src/sysfile-info.c:451 +#: src/sysfile-info.c:453 #, c-format msgid "Print Format: %s" msgstr "" -#: src/sysfile-info.c:454 +#: src/sysfile-info.c:456 #, c-format msgid "Write Format: %s" msgstr "" -#: src/sysfile-info.c:462 +#: src/sysfile-info.c:464 msgid "Missing Values: " msgstr "" -#: src/sysfile-info.c:529 src/vfm.c:875 src/crosstabs.q:1068 -#: src/crosstabs.q:1095 src/crosstabs.q:1115 src/crosstabs.q:1137 -#: src/examine.q:1125 src/frequencies.q:1056 src/frequencies.q:1174 +#: src/sysfile-info.c:531 src/vfm.c:876 src/crosstabs.q:1099 +#: src/crosstabs.q:1126 src/crosstabs.q:1146 src/crosstabs.q:1168 +#: src/examine.q:1179 src/frequencies.q:1083 src/frequencies.q:1204 msgid "Value" msgstr "" -#: src/sysfile-info.c:586 +#: src/sysfile-info.c:588 msgid "No vectors defined." msgstr "" -#: src/sysfile-info.c:601 +#: src/sysfile-info.c:603 msgid "Vector" msgstr "" @@ -3831,36 +3701,36 @@ 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:45 +#: src/temporary.c:46 msgid "This command is not valid inside DO IF or LOOP." msgstr "" -#: src/temporary.c:52 +#: src/temporary.c:53 msgid "" "This command may only appear once between procedures and procedure-like " "commands." msgstr "" -#: src/title.c:55 +#: src/title.c:56 #, c-format msgid "%s before: %s\n" msgstr "" -#: src/title.c:55 +#: src/title.c:56 msgid "" msgstr "" -#: src/title.c:67 +#: src/title.c:68 #, c-format msgid "%s: `.' expected after string." msgstr "" -#: src/title.c:83 +#: src/title.c:84 #, c-format msgid "%s after: %s\n" msgstr "" -#: src/title.c:139 +#: src/title.c:140 #, c-format msgid "Document entered %s %02d:%02d:%02d by %s (%s):" msgstr "" @@ -3889,29 +3759,29 @@ msgstr "" msgid "Truncating variable label to 255 characters." msgstr "" -#: src/vars-prs.c:48 +#: src/vars-prs.c:49 #, c-format msgid "%s is not a variable name." msgstr "" -#: src/vars-prs.c:100 +#: src/vars-prs.c:101 msgid "ordinary" msgstr "" -#: src/vars-prs.c:102 +#: src/vars-prs.c:103 msgid "system" msgstr "" -#: src/vars-prs.c:104 +#: src/vars-prs.c:105 msgid "scratch" msgstr "" -#: src/vars-prs.c:209 +#: src/vars-prs.c:210 #, c-format msgid "%s TO %s is not valid syntax since %s precedes %s in the dictionary." msgstr "" -#: src/vars-prs.c:219 +#: src/vars-prs.c:220 #, c-format msgid "" "When using the TO keyword to specify several variables, both variables must " @@ -3919,700 +3789,706 @@ msgid "" "system variables. %s is a %s variable, whereas %s is %s." msgstr "" -#: src/vars-prs.c:237 +#: src/vars-prs.c:238 #, c-format msgid "Scratch variables (such as %s) are not allowed here." msgstr "" -#: src/vars-prs.c:260 +#: src/vars-prs.c:261 #, c-format msgid "" "%s is not a numeric variable. It will not be included in the variable list." msgstr "" -#: src/vars-prs.c:263 +#: src/vars-prs.c:264 #, c-format msgid "" "%s is not a string variable. It will not be included in the variable list." msgstr "" -#: src/vars-prs.c:267 +#: src/vars-prs.c:268 #, c-format msgid "" "%s and %s are not the same type. All variables in this variable list must " "be of the same type. %s will be omitted from list." msgstr "" -#: src/vars-prs.c:272 +#: src/vars-prs.c:273 #, c-format msgid "Variable %s appears twice in variable list." msgstr "" -#: src/vars-prs.c:352 +#: src/vars-prs.c:353 msgid "incorrect use of TO convention" msgstr "" -#: src/vars-prs.c:399 +#: src/vars-prs.c:400 msgid "Scratch variables not allowed here." msgstr "" -#: src/vars-prs.c:421 +#: src/vars-prs.c:422 msgid "Prefixes don't match in use of TO convention." msgstr "" -#: src/vars-prs.c:426 +#: src/vars-prs.c:427 msgid "Bad bounds in use of TO convention." msgstr "" -#: src/vector.c:66 +#: src/vector.c:67 #, c-format msgid "Vector name %s is given twice." msgstr "" -#: src/vector.c:72 +#: src/vector.c:73 #, c-format msgid "There is already a vector with name %s." msgstr "" -#: src/vector.c:93 +#: src/vector.c:94 msgid "" "A slash must be used to separate each vector specification when using the " "long form. Commands such as VECTOR A,B=Q1 TO Q20 are not supported." msgstr "" -#: src/vector.c:127 +#: src/vector.c:128 msgid "Vectors must have at least one element." msgstr "" -#: src/vector.c:141 +#: src/vector.c:142 #, c-format msgid "%s%d is too long for a variable name." msgstr "" -#: src/vector.c:179 +#: src/vector.c:180 msgid "" "The syntax for this command does not match the expected syntax for either " "the long form or the short form of VECTOR." msgstr "" -#: src/weight.c:52 +#: src/weight.c:53 msgid "The weighting variable must be numeric." msgstr "" -#: src/weight.c:57 +#: src/weight.c:58 msgid "The weighting variable may not be scratch." msgstr "" -#: src/crosstabs.q:241 +#: src/crosstabs.q:261 msgid "" "Missing mode REPORT not allowed in general mode. Assuming MISSING=TABLE." msgstr "" -#: src/crosstabs.q:251 +#: src/crosstabs.q:271 msgid "Write mode ALL not allowed in general mode. Assuming WRITE=CELLS." msgstr "" -#: src/crosstabs.q:312 +#: src/crosstabs.q:332 msgid "expecting BY" msgstr "" -#: src/crosstabs.q:379 +#: src/crosstabs.q:399 msgid "VARIABLES must be specified before TABLES." msgstr "" -#: src/crosstabs.q:416 +#: src/crosstabs.q:436 #, c-format msgid "Maximum value (%ld) less than minimum value (%ld)." msgstr "" -#: src/crosstabs.q:769 +#: src/crosstabs.q:800 msgid "Summary." msgstr "" -#: src/crosstabs.q:771 src/examine.q:784 +#: src/crosstabs.q:802 src/examine.q:837 msgid "Cases" msgstr "" -#: src/crosstabs.q:772 src/examine.q:722 src/frequencies.q:1054 -#: src/frequencies.q:1421 +#: src/crosstabs.q:803 src/examine.q:775 src/frequencies.q:1081 +#: src/frequencies.q:1454 msgid "Valid" msgstr "" -#: src/crosstabs.q:773 src/examine.q:723 src/frequencies.q:1121 -#: src/frequencies.q:1422 +#: src/crosstabs.q:804 src/examine.q:776 src/frequencies.q:1149 +#: src/frequencies.q:1455 msgid "Missing" msgstr "" -#: src/crosstabs.q:774 src/crosstabs.q:977 src/crosstabs.q:1690 -#: src/examine.q:724 src/frequencies.q:1130 src/oneway.q:306 src/oneway.q:483 +#: src/crosstabs.q:805 src/crosstabs.q:1008 src/crosstabs.q:1722 +#: src/examine.q:777 src/frequencies.q:1158 src/oneway.q:307 src/oneway.q:486 msgid "Total" msgstr "" -#: src/crosstabs.q:784 src/examine.q:805 src/frequencies.q:1420 -#: src/oneway.q:393 src/t-test.q:680 src/t-test.q:703 src/t-test.q:828 +#: src/crosstabs.q:815 src/examine.q:858 src/frequencies.q:1453 +#: src/oneway.q:395 src/t-test.q:682 src/t-test.q:705 src/t-test.q:830 #: src/t-test.q:1365 msgid "N" msgstr "" -#: src/crosstabs.q:785 src/examine.q:807 src/frequencies.q:1058 -#: src/frequencies.q:1059 src/frequencies.q:1060 +#: src/crosstabs.q:816 src/examine.q:860 src/frequencies.q:1085 +#: src/frequencies.q:1086 src/frequencies.q:1087 msgid "Percent" msgstr "" -#: src/crosstabs.q:1027 +#: src/crosstabs.q:1058 msgid "count" msgstr "" -#: src/crosstabs.q:1028 +#: src/crosstabs.q:1059 msgid "row %" msgstr "" -#: src/crosstabs.q:1029 +#: src/crosstabs.q:1060 msgid "column %" msgstr "" -#: src/crosstabs.q:1030 +#: src/crosstabs.q:1061 msgid "total %" msgstr "" -#: src/crosstabs.q:1031 +#: src/crosstabs.q:1062 msgid "expected" msgstr "" -#: src/crosstabs.q:1032 +#: src/crosstabs.q:1063 msgid "residual" msgstr "" -#: src/crosstabs.q:1033 +#: src/crosstabs.q:1064 msgid "std. resid." msgstr "" -#: src/crosstabs.q:1034 +#: src/crosstabs.q:1065 msgid "adj. resid." msgstr "" -#: src/crosstabs.q:1067 src/crosstabs.q:1094 src/crosstabs.q:1114 -#: src/crosstabs.q:1135 src/examine.q:448 +#: src/crosstabs.q:1098 src/crosstabs.q:1125 src/crosstabs.q:1145 +#: src/crosstabs.q:1166 src/examine.q:495 msgid "Statistic" msgstr "" -#: src/crosstabs.q:1069 src/oneway.q:276 src/oneway.q:711 src/t-test.q:979 -#: src/t-test.q:1171 src/t-test.q:1263 +#: src/crosstabs.q:1100 src/oneway.q:278 src/oneway.q:707 src/t-test.q:980 +#: src/t-test.q:1172 src/t-test.q:1264 msgid "df" msgstr "" -#: src/crosstabs.q:1071 +#: src/crosstabs.q:1102 msgid "Asymp. Sig. (2-sided)" msgstr "" -#: src/crosstabs.q:1073 +#: src/crosstabs.q:1104 msgid "Exact. Sig. (2-sided)" msgstr "" -#: src/crosstabs.q:1075 +#: src/crosstabs.q:1106 msgid "Exact. Sig. (1-sided)" msgstr "" -#: src/crosstabs.q:1093 src/crosstabs.q:1134 +#: src/crosstabs.q:1124 src/crosstabs.q:1165 msgid "Category" msgstr "" -#: src/crosstabs.q:1096 src/crosstabs.q:1138 +#: src/crosstabs.q:1127 src/crosstabs.q:1169 msgid "Asymp. Std. Error" msgstr "" -#: src/crosstabs.q:1097 src/crosstabs.q:1139 +#: src/crosstabs.q:1128 src/crosstabs.q:1170 msgid "Approx. T" msgstr "" -#: src/crosstabs.q:1098 src/crosstabs.q:1140 +#: src/crosstabs.q:1129 src/crosstabs.q:1171 msgid "Approx. Sig." msgstr "" -#: src/crosstabs.q:1113 +#: src/crosstabs.q:1144 #, c-format msgid " 95%% Confidence Interval" msgstr "" -#: src/crosstabs.q:1116 src/t-test.q:983 src/t-test.q:1168 src/t-test.q:1266 +#: src/crosstabs.q:1147 src/t-test.q:984 src/t-test.q:1169 src/t-test.q:1267 msgid "Lower" msgstr "" -#: src/crosstabs.q:1117 src/t-test.q:984 src/t-test.q:1169 src/t-test.q:1267 +#: src/crosstabs.q:1148 src/t-test.q:985 src/t-test.q:1170 src/t-test.q:1268 msgid "Upper" msgstr "" -#: src/crosstabs.q:1136 +#: src/crosstabs.q:1167 msgid "Type" msgstr "" -#: src/crosstabs.q:1884 +#: src/crosstabs.q:1916 msgid "Pearson Chi-Square" msgstr "" -#: src/crosstabs.q:1885 +#: src/crosstabs.q:1917 msgid "Likelihood Ratio" msgstr "" -#: src/crosstabs.q:1886 +#: src/crosstabs.q:1918 msgid "Fisher's Exact Test" msgstr "" -#: src/crosstabs.q:1887 +#: src/crosstabs.q:1919 msgid "Continuity Correction" msgstr "" -#: src/crosstabs.q:1888 +#: src/crosstabs.q:1920 msgid "Linear-by-Linear Association" msgstr "" -#: src/crosstabs.q:1925 src/crosstabs.q:1995 src/crosstabs.q:2054 +#: src/crosstabs.q:1957 src/crosstabs.q:2027 src/crosstabs.q:2086 msgid "N of Valid Cases" msgstr "" -#: src/crosstabs.q:1941 src/crosstabs.q:2070 +#: src/crosstabs.q:1973 src/crosstabs.q:2102 msgid "Nominal by Nominal" msgstr "" -#: src/crosstabs.q:1942 src/crosstabs.q:2071 +#: src/crosstabs.q:1974 src/crosstabs.q:2103 msgid "Ordinal by Ordinal" msgstr "" -#: src/crosstabs.q:1943 +#: src/crosstabs.q:1975 msgid "Interval by Interval" msgstr "" -#: src/crosstabs.q:1944 +#: src/crosstabs.q:1976 msgid "Measure of Agreement" msgstr "" -#: src/crosstabs.q:1949 +#: src/crosstabs.q:1981 msgid "Phi" msgstr "" -#: src/crosstabs.q:1950 +#: src/crosstabs.q:1982 msgid "Cramer's V" msgstr "" -#: src/crosstabs.q:1951 +#: src/crosstabs.q:1983 msgid "Contingency Coefficient" msgstr "" -#: src/crosstabs.q:1952 +#: src/crosstabs.q:1984 msgid "Kendall's tau-b" msgstr "" -#: src/crosstabs.q:1953 +#: src/crosstabs.q:1985 msgid "Kendall's tau-c" msgstr "" -#: src/crosstabs.q:1954 +#: src/crosstabs.q:1986 msgid "Gamma" msgstr "" -#: src/crosstabs.q:1955 +#: src/crosstabs.q:1987 msgid "Spearman Correlation" msgstr "" -#: src/crosstabs.q:1956 +#: src/crosstabs.q:1988 msgid "Pearson's R" msgstr "" -#: src/crosstabs.q:1957 +#: src/crosstabs.q:1989 msgid "Kappa" msgstr "" -#: src/crosstabs.q:2027 +#: src/crosstabs.q:2059 #, c-format msgid "Odds Ratio for %s (%g / %g)" msgstr "" -#: src/crosstabs.q:2030 +#: src/crosstabs.q:2062 #, c-format msgid "Odds Ratio for %s (%.*s / %.*s)" msgstr "" -#: src/crosstabs.q:2038 +#: src/crosstabs.q:2070 #, c-format msgid "For cohort %s = %g" msgstr "" -#: src/crosstabs.q:2041 +#: src/crosstabs.q:2073 #, c-format msgid "For cohort %s = %.*s" msgstr "" -#: src/crosstabs.q:2072 +#: src/crosstabs.q:2104 msgid "Nominal by Interval" msgstr "" -#: src/crosstabs.q:2077 +#: src/crosstabs.q:2109 msgid "Lambda" msgstr "" -#: src/crosstabs.q:2078 +#: src/crosstabs.q:2110 msgid "Goodman and Kruskal tau" msgstr "" -#: src/crosstabs.q:2079 +#: src/crosstabs.q:2111 msgid "Uncertainty Coefficient" msgstr "" -#: src/crosstabs.q:2080 +#: src/crosstabs.q:2112 msgid "Somers' d" msgstr "" -#: src/crosstabs.q:2081 +#: src/crosstabs.q:2113 msgid "Eta" msgstr "" -#: src/crosstabs.q:2086 +#: src/crosstabs.q:2118 msgid "Symmetric" msgstr "" -#: src/crosstabs.q:2087 src/crosstabs.q:2088 +#: src/crosstabs.q:2119 src/crosstabs.q:2120 #, c-format msgid "%s Dependent" msgstr "" -#: src/examine.q:217 src/examine.q:229 +#: src/examine.q:264 src/examine.q:276 #, c-format msgid "%s and %s are mutually exclusive" msgstr "" -#: src/examine.q:449 src/oneway.q:396 src/oneway.q:709 +#: src/examine.q:496 src/oneway.q:398 src/oneway.q:705 msgid "Std. Error" msgstr "" -#: src/examine.q:563 src/oneway.q:410 +#: src/examine.q:610 src/oneway.q:412 msgid "Descriptives" msgstr "" -#: src/examine.q:602 src/oneway.q:401 +#: src/examine.q:649 src/oneway.q:403 #, c-format msgid "%g%% Confidence Interval for Mean" msgstr "" -#: src/examine.q:608 src/oneway.q:403 +#: src/examine.q:655 src/oneway.q:405 msgid "Lower Bound" msgstr "" -#: src/examine.q:619 src/oneway.q:404 +#: src/examine.q:666 src/oneway.q:406 msgid "Upper Bound" msgstr "" -#: src/examine.q:631 +#: src/examine.q:678 msgid "5% Trimmed Mean" msgstr "" -#: src/examine.q:636 src/frequencies.q:102 +#: src/examine.q:689 src/frequencies.q:112 msgid "Median" msgstr "" -#: src/examine.q:653 src/oneway.q:395 src/t-test.q:682 src/t-test.q:705 -#: src/t-test.q:829 src/t-test.q:1166 +#: src/examine.q:706 src/oneway.q:397 src/t-test.q:684 src/t-test.q:707 +#: src/t-test.q:831 src/t-test.q:1167 msgid "Std. Deviation" msgstr "" -#: src/examine.q:701 +#: src/examine.q:754 msgid "Interquartile Range" msgstr "" -#: src/examine.q:778 +#: src/examine.q:831 msgid "Case Processing Summary" msgstr "" -#: src/examine.q:1103 +#: src/examine.q:1157 msgid "Extreme Values" msgstr "" -#: src/examine.q:1126 +#: src/examine.q:1180 msgid "Case Number" msgstr "" -#: src/examine.q:1252 +#: src/examine.q:1306 msgid "Highest" msgstr "" -#: src/examine.q:1257 +#: src/examine.q:1311 msgid "Lowest" msgstr "" -#: src/file-handle.q:125 +#: src/examine.q:1350 +#, c-format +msgid "Normal Q-Q Plot of %s" +msgstr "" + +#: src/examine.q:1351 src/examine.q:1357 +msgid "Observed Value" +msgstr "" + +#: src/examine.q:1352 +msgid "Expected Normal" +msgstr "" + +#: src/examine.q:1355 +#, c-format +msgid "Detrended Normal Q-Q Plot of %s" +msgstr "" + +#: src/examine.q:1358 +msgid "Dev from Normal" +msgstr "" + +#: src/file-handle.q:122 #, c-format msgid "" "File handle %s already refers to file %s. File handle cannot be redefined " "within a session." msgstr "" -#: src/file-handle.q:147 +#: src/file-handle.q:144 msgid "The FILE HANDLE required subcommand NAME is not present." msgstr "" -#: src/file-handle.q:166 +#: src/file-handle.q:163 msgid "" "Fixed-length records were specified on /RECFORM, but record length was not " "specified on /LRECL. Assuming 1024-character records." msgstr "" -#: src/file-handle.q:173 +#: src/file-handle.q:170 #, c-format msgid "" "Record length (%ld) must be at least one byte. 1-character records will be " "assumed." msgstr "" -#: src/file-handle.q:247 -msgid "" +#: src/file-handle.q:260 +#, c-format +msgid "Can't open %s as a %s because it is already open as a %s" +msgstr "" + +#: src/file-handle.q:264 +#, c-format +msgid "Can't open %s as a %s for %s because it is already open for %s" +msgstr "" + +#: src/file-handle.q:269 +#, c-format +msgid "Can't re-open %s as a %s for %s" msgstr "" -#: src/file-handle.q:262 +#: src/file-handle.q:317 msgid "expecting a file name or handle name" msgstr "" -#: src/frequencies.q:101 +#: src/frequencies.q:111 msgid "S.E. Mean" msgstr "" -#: src/frequencies.q:103 +#: src/frequencies.q:113 msgid "Mode" msgstr "" -#: src/frequencies.q:107 +#: src/frequencies.q:117 msgid "S.E. Kurt" msgstr "" -#: src/frequencies.q:109 +#: src/frequencies.q:119 msgid "S.E. Skew" msgstr "" -#: src/frequencies.q:315 +#: src/frequencies.q:340 msgid "" "At most one of BARCHART, HISTOGRAM, or HBAR should be given. HBAR will be " "assumed. Argument values will be given precedence increasing along the " "order given." msgstr "" -#: src/frequencies.q:398 +#: src/frequencies.q:423 #, c-format msgid "" "MAX must be greater than or equal to MIN, if both are specified. However, " "MIN was specified as %g and MAX as %g. MIN and MAX will be ignored." msgstr "" -#: src/frequencies.q:722 +#: src/frequencies.q:747 msgid "" "Upper limit of integer mode value range must be greater than lower limit." msgstr "" -#: src/frequencies.q:734 +#: src/frequencies.q:760 #, c-format msgid "Variable %s specified multiple times on VARIABLES subcommand." msgstr "" -#: src/frequencies.q:747 +#: src/frequencies.q:766 #, c-format msgid "Integer mode specified, but %s is not a numeric variable." msgstr "" -#: src/frequencies.q:809 +#: src/frequencies.q:832 msgid "`)' expected after GROUPED interval list." msgstr "" -#: src/frequencies.q:822 +#: src/frequencies.q:844 #, c-format msgid "Variables %s specified on GROUPED but not on VARIABLES." msgstr "" -#: src/frequencies.q:825 +#: src/frequencies.q:851 #, c-format msgid "Variables %s specified multiple times on GROUPED subcommand." msgstr "" -#: src/frequencies.q:1055 src/frequencies.q:1146 src/frequencies.q:1147 -#: src/frequencies.q:1177 +#: src/frequencies.q:1082 src/frequencies.q:1174 src/frequencies.q:1175 +#: src/frequencies.q:1207 msgid "Cum" msgstr "" -#: src/frequencies.q:1057 +#: src/frequencies.q:1084 msgid "Frequency" msgstr "" -#: src/frequencies.q:1076 +#: src/frequencies.q:1104 msgid "Value Label" msgstr "" -#: src/frequencies.q:1175 +#: src/frequencies.q:1205 msgid "Freq" msgstr "" -#: src/frequencies.q:1176 src/frequencies.q:1178 +#: src/frequencies.q:1206 src/frequencies.q:1208 msgid "Pct" msgstr "" -#: src/frequencies.q:1394 +#: src/frequencies.q:1427 #, c-format msgid "No valid data for variable %s; statistics not displayed." msgstr "" -#: src/frequencies.q:1433 +#: src/frequencies.q:1465 msgid "Percentiles" msgstr "" -#: src/list.q:148 +#: src/list.q:150 #, c-format msgid "" "The first case (%ld) specified precedes the last case (%ld) specified. The " "values will be swapped." msgstr "" -#: src/list.q:156 +#: src/list.q:158 #, c-format msgid "" "The first case (%ld) to list is less than 1. The value is being reset to 1." msgstr "" -#: src/list.q:162 +#: src/list.q:164 #, c-format msgid "" "The last case (%ld) to list is less than 1. The value is being reset to 1." msgstr "" -#: src/list.q:168 +#: src/list.q:170 #, c-format msgid "The step value %ld is less than 1. The value is being reset to 1." msgstr "" -#: src/list.q:195 +#: src/list.q:197 msgid "`/FORMAT WEIGHT' specified, but weighting is not on." msgstr "" -#: src/list.q:436 +#: src/list.q:438 msgid "Line" msgstr "" -#: src/means.q:101 +#: src/means.q:100 msgid "Missing required subcommand TABLES." msgstr "" -#: src/means.q:135 -msgid "TABLES or CROSSBREAK subcommand may not appear more than once." -msgstr "" - -#: src/means.q:172 -#, c-format -msgid "" -"Variable %s specified on TABLES or CROSSBREAK, but not specified on " -"VARIABLES." -msgstr "" - -#: src/means.q:186 -#, c-format -msgid "LOWEST and HIGHEST may not be used for independent variables (%s)." -msgstr "" - -#: src/means.q:194 -#, c-format -msgid "" -"Independent variables (%s) may not have noninteger endpoints in their ranges." -msgstr "" - -#: src/means.q:227 -msgid "VARIABLES must precede TABLES." -msgstr "" - -#: src/means.q:284 -#, c-format -msgid "Upper value (%g) is less than lower value (%g) on VARIABLES subcommand." +#: src/means.q:134 +msgid "TABLES subcommand may not appear more than once." msgstr "" -#: src/oneway.q:166 +#: src/oneway.q:168 msgid "Number of contrast coefficients must equal the number of groups" msgstr "" -#: src/oneway.q:175 +#: src/oneway.q:177 #, c-format msgid "Coefficients for contrast %d do not total zero" msgstr "" -#: src/oneway.q:240 src/t-test.q:364 src/t-test.q:449 +#: src/oneway.q:242 src/t-test.q:366 src/t-test.q:451 #, c-format msgid "`%s' is not a variable name" msgstr "" -#: src/oneway.q:275 +#: src/oneway.q:277 msgid "Sum of Squares" msgstr "" -#: src/oneway.q:277 +#: src/oneway.q:279 msgid "Mean Square" msgstr "" -#: src/oneway.q:278 src/t-test.q:976 +#: src/oneway.q:280 src/t-test.q:977 msgid "F" msgstr "" -#: src/oneway.q:279 src/oneway.q:549 +#: src/oneway.q:281 src/oneway.q:552 msgid "Significance" msgstr "" -#: src/oneway.q:304 +#: src/oneway.q:305 msgid "Between Groups" msgstr "" -#: src/oneway.q:305 +#: src/oneway.q:306 msgid "Within Groups" msgstr "" -#: src/oneway.q:351 +#: src/oneway.q:353 msgid "ANOVA" msgstr "" -#: src/oneway.q:546 +#: src/oneway.q:549 msgid "Levene Statistic" msgstr "" -#: src/oneway.q:547 +#: src/oneway.q:550 msgid "df1" msgstr "" -#: src/oneway.q:548 +#: src/oneway.q:551 msgid "df2" msgstr "" -#: src/oneway.q:552 +#: src/oneway.q:555 msgid "Test of Homogeneity of Variances" msgstr "" -#: src/oneway.q:628 +#: src/oneway.q:631 msgid "Contrast Coefficients" msgstr "" -#: src/oneway.q:630 src/oneway.q:707 +#: src/oneway.q:633 src/oneway.q:703 msgid "Contrast" msgstr "" -#: src/oneway.q:705 +#: src/oneway.q:701 msgid "Contrast Tests" msgstr "" -#: src/oneway.q:708 +#: src/oneway.q:704 msgid "Value of Contrast" msgstr "" -#: src/oneway.q:710 src/t-test.q:978 src/t-test.q:1170 src/t-test.q:1262 +#: src/oneway.q:706 src/t-test.q:979 src/t-test.q:1171 src/t-test.q:1263 msgid "t" msgstr "" -#: src/oneway.q:712 src/t-test.q:980 src/t-test.q:1172 src/t-test.q:1264 +#: src/oneway.q:708 src/t-test.q:981 src/t-test.q:1173 src/t-test.q:1265 msgid "Sig. (2-tailed)" msgstr "" -#: src/oneway.q:760 +#: src/oneway.q:754 msgid "Assume equal variances" msgstr "" -#: src/oneway.q:764 +#: src/oneway.q:758 msgid "Does not assume equal" msgstr "" @@ -4748,115 +4624,115 @@ msgstr "" msgid "data> " msgstr "" -#: src/t-test.q:266 +#: src/t-test.q:268 msgid "TESTVAL, GROUPS and PAIRS subcommands are mutually exclusive." msgstr "" -#: src/t-test.q:283 +#: src/t-test.q:285 msgid "VARIABLES subcommand is not appropriate with PAIRS" msgstr "" -#: src/t-test.q:320 +#: src/t-test.q:322 msgid "One or more VARIABLES must be specified." msgstr "" -#: src/t-test.q:377 +#: src/t-test.q:379 #, c-format msgid "Long string variable %s is not valid here." msgstr "" -#: src/t-test.q:397 +#: src/t-test.q:399 msgid "" "When applying GROUPS to a string variable, at least one value must be " "specified." msgstr "" -#: src/t-test.q:484 +#: src/t-test.q:486 #, c-format msgid "" "PAIRED was specified but the number of variables preceding WITH (%d) did not " "match the number following (%d)." msgstr "" -#: src/t-test.q:501 +#: src/t-test.q:503 msgid "At least two variables must be specified on PAIRS." msgstr "" -#: src/t-test.q:678 +#: src/t-test.q:680 msgid "One-Sample Statistics" msgstr "" -#: src/t-test.q:683 src/t-test.q:706 src/t-test.q:830 +#: src/t-test.q:685 src/t-test.q:708 src/t-test.q:832 msgid "SE. Mean" msgstr "" -#: src/t-test.q:700 +#: src/t-test.q:702 msgid "Group Statistics" msgstr "" -#: src/t-test.q:824 +#: src/t-test.q:826 msgid "Paired Sample Statistics" msgstr "" -#: src/t-test.q:846 src/t-test.q:1191 src/t-test.q:1382 +#: src/t-test.q:848 src/t-test.q:1192 src/t-test.q:1382 #, c-format msgid "Pair %d" msgstr "" -#: src/t-test.q:964 +#: src/t-test.q:965 msgid "Independent Samples Test" msgstr "" -#: src/t-test.q:972 +#: src/t-test.q:973 msgid "Levene's Test for Equality of Variances" msgstr "" -#: src/t-test.q:974 +#: src/t-test.q:975 msgid "t-test for Equality of Means" msgstr "" -#: src/t-test.q:977 src/t-test.q:1367 +#: src/t-test.q:978 src/t-test.q:1367 msgid "Sig." msgstr "" -#: src/t-test.q:981 src/t-test.q:1265 +#: src/t-test.q:982 src/t-test.q:1266 msgid "Mean Difference" msgstr "" -#: src/t-test.q:982 +#: src/t-test.q:983 msgid "Std. Error Difference" msgstr "" -#: src/t-test.q:987 src/t-test.q:1162 src/t-test.q:1257 +#: src/t-test.q:988 src/t-test.q:1163 src/t-test.q:1258 #, c-format msgid "%g%% Confidence Interval of the Difference" msgstr "" -#: src/t-test.q:1041 +#: src/t-test.q:1043 msgid "Equal variances assumed" msgstr "" -#: src/t-test.q:1094 +#: src/t-test.q:1095 msgid "Equal variances not assumed" msgstr "" -#: src/t-test.q:1152 +#: src/t-test.q:1153 msgid "Paired Samples Test" msgstr "" -#: src/t-test.q:1155 +#: src/t-test.q:1156 msgid "Paired Differences" msgstr "" -#: src/t-test.q:1167 +#: src/t-test.q:1168 msgid "Std. Error Mean" msgstr "" -#: src/t-test.q:1246 +#: src/t-test.q:1247 msgid "One-Sample Test" msgstr "" -#: src/t-test.q:1251 +#: src/t-test.q:1252 #, c-format msgid "Test Value = %f" msgstr "" diff --git a/po/pspp.pot b/po/pspp.pot index d10649f3..21887e86 100644 --- a/po/pspp.pot +++ b/po/pspp.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n" -"POT-Creation-Date: 2004-11-09 08:18+0800\n" +"POT-Creation-Date: 2004-11-15 00:28-0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,91 +17,91 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: src/aggregate.c:188 src/aggregate.c:223 src/data-list.c:1437 -#: src/data-list.c:1472 src/data-list.c:1485 src/data-list.c:1498 -#: src/data-list.c:1531 +#: src/aggregate.c:187 src/aggregate.c:220 src/data-list.c:1421 +#: src/data-list.c:1456 src/data-list.c:1469 src/data-list.c:1482 +#: src/data-list.c:1515 #, c-format msgid "%s subcommand given multiple times." msgstr "" -#: src/aggregate.c:208 +#: src/aggregate.c:205 msgid "while expecting COLUMNWISE" msgstr "" -#: src/aggregate.c:246 +#: src/aggregate.c:243 msgid "BREAK subcommand not specified." msgstr "" -#: src/aggregate.c:416 +#: src/aggregate.c:397 msgid "expecting aggregation function" msgstr "" -#: src/aggregate.c:432 +#: src/aggregate.c:413 #, c-format msgid "Unknown aggregation function %s." msgstr "" -#: src/aggregate.c:447 +#: src/aggregate.c:428 msgid "expecting `('" msgstr "" -#: src/aggregate.c:482 +#: src/aggregate.c:463 #, c-format msgid "Missing argument %d to %s." msgstr "" -#: src/aggregate.c:490 +#: src/aggregate.c:471 #, c-format msgid "Arguments to %s must be of same type as source variables." msgstr "" -#: src/aggregate.c:500 src/expr-prs.c:626 +#: src/aggregate.c:481 src/expr-prs.c:627 msgid "expecting `)'" msgstr "" -#: src/aggregate.c:512 +#: src/aggregate.c:493 #, c-format msgid "" "Number of source variables (%d) does not match number of target variables (%" "d)." msgstr "" -#: src/aggregate.c:581 +#: src/aggregate.c:562 #, c-format msgid "" "Variable name %s is not unique within the aggregate file dictionary, which " "contains the aggregate variables and the break variables." msgstr "" -#: src/apply-dict.c:65 +#: src/apply-dict.c:68 #, c-format msgid "Variable %s is %s in target file, but %s in source file." msgstr "" -#: src/apply-dict.c:68 src/apply-dict.c:69 src/expr-prs.c:1288 -#: src/expr-prs.c:1304 src/formats.c:96 src/pfm-read.c:636 src/print.c:689 -#: src/sfm-read.c:927 src/sfm-read.c:1057 src/sfm-read.c:1058 +#: src/apply-dict.c:71 src/apply-dict.c:72 src/expr-prs.c:1289 +#: src/expr-prs.c:1305 src/formats.c:96 src/pfm-read.c:604 src/print.c:695 +#: src/sfm-read.c:888 src/sfm-read.c:1017 src/sfm-read.c:1018 msgid "string" msgstr "" -#: src/apply-dict.c:68 src/apply-dict.c:69 src/expr-prs.c:1285 -#: src/expr-prs.c:1302 src/formats.c:96 src/pfm-read.c:636 src/print.c:689 -#: src/sfm-read.c:927 src/sfm-read.c:1057 src/sfm-read.c:1058 +#: src/apply-dict.c:71 src/apply-dict.c:72 src/expr-prs.c:1286 +#: src/expr-prs.c:1303 src/formats.c:96 src/pfm-read.c:604 src/print.c:695 +#: src/sfm-read.c:888 src/sfm-read.c:1017 src/sfm-read.c:1018 msgid "numeric" msgstr "" -#: src/apply-dict.c:81 +#: src/apply-dict.c:84 #, c-format msgid "Cannot add value labels from source file to long string variable %s." msgstr "" -#: src/apply-dict.c:127 +#: src/apply-dict.c:130 #, c-format msgid "" "Cannot apply missing values from source file to long string variable %s." msgstr "" -#: src/apply-dict.c:160 +#: src/apply-dict.c:163 msgid "No matching variables found between the source and target files." msgstr "" @@ -220,65 +220,65 @@ msgstr "" msgid "%s - Page %d" msgstr "" -#: src/autorecode.c:121 +#: src/autorecode.c:122 #, c-format msgid "Source variable count (%d) does not match target variable count (%d)." msgstr "" -#: src/autorecode.c:138 src/command.c:738 src/compute.c:293 -#: src/data-list.c:406 src/data-list.c:903 src/data-list.c:1764 -#: src/do-if.c:253 src/get.c:351 src/lexer.c:412 src/loop.c:240 -#: src/matrix-data.c:504 src/print.c:329 src/print.c:1039 src/recode.c:404 -#: src/sel-if.c:53 src/sel-if.c:130 src/vector.c:192 src/file-handle.q:141 +#: src/autorecode.c:139 src/command.c:739 src/compute.c:294 +#: src/data-list.c:407 src/data-list.c:897 src/data-list.c:1748 +#: src/do-if.c:253 src/get.c:405 src/lexer.c:412 src/loop.c:241 +#: src/matrix-data.c:527 src/print.c:335 src/print.c:1045 src/recode.c:405 +#: src/sel-if.c:54 src/sel-if.c:131 src/vector.c:193 src/file-handle.q:138 msgid "expecting end of command" msgstr "" -#: src/autorecode.c:148 +#: src/autorecode.c:149 #, c-format msgid "Target variable %s duplicates existing variable %s." msgstr "" -#: src/autorecode.c:155 +#: src/autorecode.c:156 #, c-format msgid "Duplicate variable name %s among target variables." msgstr "" -#: src/casefile.c:184 +#: src/casefile.c:182 #, c-format msgid "%s: Removing temporary file: %s." msgstr "" -#: src/casefile.c:329 +#: src/casefile.c:328 #, c-format msgid "Error writing temporary file: %s." msgstr "" -#: src/casefile.c:356 +#: src/casefile.c:355 #, c-format msgid "%s: Creating temporary file: %s." msgstr "" -#: src/casefile.c:500 +#: src/casefile.c:498 #, c-format msgid "%s: Opening temporary file: %s." msgstr "" -#: src/casefile.c:526 +#: src/casefile.c:524 #, c-format msgid "%s: Seeking temporary file: %s." msgstr "" -#: src/casefile.c:541 +#: src/casefile.c:540 #, c-format msgid "%s: Reading temporary file: %s." msgstr "" -#: src/casefile.c:544 +#: src/casefile.c:543 #, c-format msgid "%s: Temporary file ended unexpectedly." msgstr "" -#: src/cmdline.c:141 src/cmdline.c:160 src/cmdline.c:172 src/command.c:160 +#: src/cmdline.c:141 src/cmdline.c:160 src/cmdline.c:172 src/command.c:161 #: src/set.q:414 src/set.q:416 src/set.q:956 #, c-format msgid "%s is not yet implemented." @@ -351,25 +351,25 @@ msgid "" "Report bugs to <%s>.\n" msgstr "" -#: src/command.c:98 +#: src/command.c:99 #, c-format msgid "%s not allowed inside FILE TYPE/END FILE TYPE." msgstr "" -#: src/command.c:102 +#: src/command.c:103 #, c-format msgid "%s not allowed inside FILE TYPE GROUPED/END FILE TYPE." msgstr "" -#: src/command.c:105 +#: src/command.c:106 msgid "RECORD TYPE must be the first command inside a FILE TYPE structure." msgstr "" -#: src/command.c:150 +#: src/command.c:151 msgid "expecting command name" msgstr "" -#: src/command.c:179 +#: src/command.c:180 #, c-format msgid "" "%s is not allowed (1) before a command to specify the input program, such as " @@ -377,83 +377,83 @@ msgid "" "PROGRAM and END INPUT PROGRAM." msgstr "" -#: src/command.c:183 +#: src/command.c:184 #, c-format msgid "%s is not allowed within an input program." msgstr "" -#: src/command.c:184 src/command.c:185 +#: src/command.c:185 src/command.c:186 #, c-format msgid "%s is only allowed within an input program." msgstr "" -#: src/command.c:464 +#: src/command.c:465 #, c-format msgid "Unknown command %s." msgstr "" -#: src/command.c:564 +#: src/command.c:565 msgid "" "This command is not accepted in a syntax file. Instead, use FINISH to " "terminate a syntax file." msgstr "" -#: src/command.c:582 +#: src/command.c:583 msgid "" "This command is not executed in interactive mode. Instead, PSPP drops down " "to the command prompt. Use EXIT if you really want to quit." msgstr "" -#: src/command.c:625 src/command.c:756 +#: src/command.c:626 src/command.c:757 msgid "This command not allowed when the SAFER option is set." msgstr "" -#: src/command.c:637 +#: src/command.c:638 #, c-format msgid "Error removing `%s': %s." msgstr "" -#: src/command.c:687 +#: src/command.c:688 #, c-format msgid "Couldn't fork: %s." msgstr "" -#: src/command.c:729 +#: src/command.c:730 #, c-format msgid "Error executing command: %s." msgstr "" -#: src/command.c:777 +#: src/command.c:778 msgid "No operating system support for this command." msgstr "" -#: src/command.c:800 +#: src/command.c:801 msgid "This command is not valid in a syntax file." msgstr "" -#: src/compute.c:145 src/compute.c:209 +#: src/compute.c:146 src/compute.c:210 #, c-format msgid "" "When executing COMPUTE: SYSMIS is not a valid value as an index into vector %" "s." msgstr "" -#: src/compute.c:148 src/compute.c:213 +#: src/compute.c:149 src/compute.c:214 #, c-format msgid "" "When executing COMPUTE: %g is not a valid value as an index into vector %s." msgstr "" -#: src/compute.c:355 +#: src/compute.c:356 #, c-format msgid "There is no vector named %s." msgstr "" -#: src/count.c:155 +#: src/count.c:156 msgid "Destination cannot be a string variable." msgstr "" -#: src/count.c:262 +#: src/count.c:263 #, c-format msgid "" "%g THRU %g is not a valid range. The number following THRU must be at least " @@ -655,259 +655,259 @@ msgstr "" msgid "Only one of FIXED, FREE, or LIST may be specified." msgstr "" -#: src/data-list.c:353 src/print.c:290 +#: src/data-list.c:354 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:382 src/data-list.c:1753 +#: src/data-list.c:383 src/data-list.c:1737 msgid "" "SPSS-like or FORTRAN-like format specification expected after variable names." msgstr "" -#: src/data-list.c:393 +#: src/data-list.c:394 msgid "At least one variable must be specified." msgstr "" -#: src/data-list.c:398 src/print.c:322 +#: src/data-list.c:399 src/print.c:328 msgid "" "Variables are specified on records that should not exist according to " "RECORDS subcommand." msgstr "" -#: src/data-list.c:436 src/data-list.c:450 src/print.c:499 src/print.c:512 +#: src/data-list.c:437 src/data-list.c:451 src/print.c:505 src/print.c:518 msgid "Column positions for fields must be positive." msgstr "" -#: src/data-list.c:455 +#: src/data-list.c:456 msgid "The ending column for a field must be greater than the starting column." msgstr "" -#: src/data-list.c:469 src/print.c:589 +#: src/data-list.c:470 src/print.c:595 #, c-format msgid "The %d columns %d-%d can't be evenly divided into %d fields." msgstr "" -#: src/data-list.c:489 src/print.c:540 +#: src/data-list.c:490 src/print.c:546 msgid "A format specifier on this line has extra characters on the end." msgstr "" -#: src/data-list.c:504 src/print.c:556 +#: src/data-list.c:505 src/print.c:562 msgid "The value for number of decimal places must be at least 1." msgstr "" -#: src/data-list.c:518 src/print.c:569 +#: src/data-list.c:519 src/print.c:575 #, c-format msgid "Input format %s doesn't accept decimal places." msgstr "" -#: src/data-list.c:565 src/data-list.c:661 src/data-list.c:882 +#: src/data-list.c:566 src/data-list.c:662 src/data-list.c:876 #, c-format msgid "%s is a duplicate variable name." msgstr "" -#: src/data-list.c:570 +#: src/data-list.c:571 #, c-format msgid "There is already a variable %s of a different type." msgstr "" -#: src/data-list.c:577 +#: src/data-list.c:578 #, c-format msgid "There is already a string variable %s of a different width." msgstr "" -#: src/data-list.c:652 +#: src/data-list.c:653 msgid "" "The number of format specifications exceeds the given number of variable " "names." msgstr "" -#: src/data-list.c:765 src/print.c:762 +#: src/data-list.c:766 src/print.c:768 msgid "" "There aren't enough format specifications to match the number of variable " "names given." msgstr "" -#: src/data-list.c:794 src/data-list.c:924 src/descript.c:879 src/print.c:793 -#: src/sysfile-info.c:132 src/sysfile-info.c:365 src/vfm.c:874 +#: src/data-list.c:793 src/data-list.c:919 src/descript.c:880 src/print.c:799 +#: src/sysfile-info.c:134 src/sysfile-info.c:367 src/vfm.c:875 msgid "Variable" msgstr "" -#: src/data-list.c:795 src/print.c:794 +#: src/data-list.c:794 src/print.c:800 msgid "Record" msgstr "" -#: src/data-list.c:796 src/print.c:795 +#: src/data-list.c:795 src/print.c:801 msgid "Columns" msgstr "" -#: src/data-list.c:797 src/data-list.c:925 src/print.c:796 +#: src/data-list.c:796 src/data-list.c:920 src/print.c:802 msgid "Format" msgstr "" -#: src/data-list.c:817 +#: src/data-list.c:812 #, c-format msgid "Reading %d record from file %s." msgid_plural "Reading %d records from file %s." msgstr[0] "" msgstr[1] "" -#: src/data-list.c:819 +#: src/data-list.c:816 #, 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:948 +#: src/data-list.c:936 #, c-format msgid "Reading free-form data from file %s." msgstr "" -#: src/data-list.c:949 +#: src/data-list.c:939 msgid "Reading free-form data from the command file." msgstr "" -#: src/data-list.c:1002 +#: src/data-list.c:990 #, c-format msgid "Quoted string missing terminating `%c'." msgstr "" -#: src/data-list.c:1111 +#: src/data-list.c:1099 #, c-format msgid "Partial case of %d of %d records discarded." msgstr "" -#: src/data-list.c:1165 +#: src/data-list.c:1153 #, c-format msgid "Partial case discarded. The first variable missing was %s." msgstr "" -#: src/data-list.c:1209 +#: src/data-list.c:1197 #, 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:1287 +#: src/data-list.c:1275 msgid "Attempt to read past end of file." msgstr "" -#: src/data-list.c:1427 +#: src/data-list.c:1411 msgid "" "REPEATING DATA must use the same file as its corresponding DATA LIST or FILE " "TYPE." msgstr "" -#: src/data-list.c:1461 +#: src/data-list.c:1445 #, c-format msgid "STARTS beginning column (%d) exceeds STARTS ending column (%d)." msgstr "" -#: src/data-list.c:1517 +#: src/data-list.c:1501 #, c-format msgid "CONTINUED beginning column (%d) exceeds CONTINUED ending column (%d)." msgstr "" -#: src/data-list.c:1540 +#: src/data-list.c:1524 #, c-format msgid "ID beginning column (%ld) must be positive." msgstr "" -#: src/data-list.c:1555 +#: src/data-list.c:1539 #, c-format msgid "ID ending column (%ld) must be positive." msgstr "" -#: src/data-list.c:1561 +#: src/data-list.c:1545 #, c-format msgid "ID ending column (%ld) cannot be less than ID beginning column (%d)." msgstr "" -#: src/data-list.c:1601 +#: src/data-list.c:1585 msgid "Missing required specification STARTS." msgstr "" -#: src/data-list.c:1603 +#: src/data-list.c:1587 msgid "Missing required specification OCCURS." msgstr "" -#: src/data-list.c:1610 +#: src/data-list.c:1594 msgid "ID specified without CONTINUED." msgstr "" -#: src/data-list.c:1702 +#: src/data-list.c:1686 msgid "String variable not allowed here." msgstr "" -#: src/data-list.c:1712 +#: src/data-list.c:1696 #, c-format msgid "%s (%d) must be at least 1." msgstr "" -#: src/data-list.c:1718 +#: src/data-list.c:1702 #, c-format msgid "Variable or integer expected for %s." msgstr "" -#: src/data-list.c:1856 +#: src/data-list.c:1840 #, c-format msgid "Encountered mismatched record ID \"%s\" expecting \"%s\"." msgstr "" -#: src/data-list.c:1888 +#: src/data-list.c:1872 #, c-format msgid "" "Variable %s starting in column %d extends beyond physical record length of %" "d." msgstr "" -#: src/data-list.c:1956 +#: src/data-list.c:1940 #, c-format msgid "Invalid value %d for OCCURS." msgstr "" -#: src/data-list.c:1962 +#: src/data-list.c:1946 #, c-format msgid "Beginning column for STARTS (%d) must be at least 1." msgstr "" -#: src/data-list.c:1970 +#: src/data-list.c:1954 #, c-format msgid "Ending column for STARTS (%d) is less than beginning column (%d)." msgstr "" -#: src/data-list.c:1978 +#: src/data-list.c:1962 #, c-format msgid "Invalid value %d for LENGTH." msgstr "" -#: src/data-list.c:1985 +#: src/data-list.c:1969 #, c-format msgid "Beginning column for CONTINUED (%d) must be at least 1." msgstr "" -#: src/data-list.c:1993 +#: src/data-list.c:1977 #, c-format msgid "Ending column for CONTINUED (%d) is less than beginning column (%d)." msgstr "" -#: src/data-list.c:2025 +#: src/data-list.c:2009 #, 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:2043 +#: src/data-list.c:2027 #, c-format msgid "Unexpected end of file with %d repetitions remaining out of %d." msgstr "" -#: src/data-out.c:235 src/sfm-read.c:466 src/sysfile-info.c:113 +#: src/data-out.c:235 src/sfm-read.c:432 src/sysfile-info.c:115 msgid "Unknown" msgstr "" @@ -958,99 +958,99 @@ msgstr "" msgid "Only USE ALL is currently implemented." msgstr "" -#: src/descript.c:98 src/examine.q:584 src/frequencies.q:100 src/oneway.q:394 -#: src/t-test.q:681 src/t-test.q:704 src/t-test.q:827 src/t-test.q:1165 +#: src/descript.c:99 src/examine.q:631 src/frequencies.q:110 src/oneway.q:396 +#: src/t-test.q:683 src/t-test.q:706 src/t-test.q:829 src/t-test.q:1166 msgid "Mean" msgstr "" -#: src/descript.c:99 +#: src/descript.c:100 msgid "S E Mean" msgstr "" -#: src/descript.c:100 src/frequencies.q:104 +#: src/descript.c:101 src/frequencies.q:114 msgid "Std Dev" msgstr "" -#: src/descript.c:101 src/examine.q:641 src/frequencies.q:105 +#: src/descript.c:102 src/examine.q:694 src/frequencies.q:115 msgid "Variance" msgstr "" -#: src/descript.c:102 src/examine.q:711 src/frequencies.q:106 +#: src/descript.c:103 src/examine.q:764 src/frequencies.q:116 msgid "Kurtosis" msgstr "" -#: src/descript.c:103 +#: src/descript.c:104 msgid "S E Kurt" msgstr "" -#: src/descript.c:104 src/examine.q:706 src/frequencies.q:108 +#: src/descript.c:105 src/examine.q:759 src/frequencies.q:118 msgid "Skewness" msgstr "" -#: src/descript.c:105 +#: src/descript.c:106 msgid "S E Skew" msgstr "" -#: src/descript.c:106 src/examine.q:689 src/frequencies.q:110 +#: src/descript.c:107 src/examine.q:742 src/frequencies.q:120 msgid "Range" msgstr "" -#: src/descript.c:107 src/examine.q:666 src/frequencies.q:111 src/oneway.q:406 +#: src/descript.c:108 src/examine.q:719 src/frequencies.q:121 src/oneway.q:408 msgid "Minimum" msgstr "" -#: src/descript.c:108 src/examine.q:677 src/frequencies.q:112 src/oneway.q:407 +#: src/descript.c:109 src/examine.q:730 src/frequencies.q:122 src/oneway.q:409 msgid "Maximum" msgstr "" -#: src/descript.c:109 src/frequencies.q:113 +#: src/descript.c:110 src/frequencies.q:123 msgid "Sum" msgstr "" -#: src/descript.c:332 +#: src/descript.c:333 #, c-format msgid "Z-score variable name %s would be a duplicate variable name." msgstr "" -#: src/descript.c:350 src/list.q:140 +#: src/descript.c:351 src/list.q:142 msgid "No variables specified." msgstr "" -#: src/descript.c:434 +#: src/descript.c:435 msgid "expecting statistic name: reverting to default" msgstr "" -#: src/descript.c:507 +#: src/descript.c:508 msgid "" "Ran out of generic names for Z-score variables. There are only 126 generic " "names: ZSC001-ZSC0999, STDZ01-STDZ09, ZZZZ01-ZZZZ09, ZQZQ01-ZQZQ09." msgstr "" -#: src/descript.c:538 +#: src/descript.c:539 msgid "Mapping of variables to corresponding Z-scores." msgstr "" -#: src/descript.c:543 +#: src/descript.c:544 msgid "Source" msgstr "" -#: src/descript.c:544 +#: src/descript.c:545 msgid "Target" msgstr "" -#: src/descript.c:663 src/descript.c:669 +#: src/descript.c:664 src/descript.c:670 msgid "Z-score of " msgstr "" -#: src/descript.c:882 +#: src/descript.c:883 msgid "Valid N" msgstr "" -#: src/descript.c:883 +#: src/descript.c:884 msgid "Missing N" msgstr "" -#: src/descript.c:909 +#: src/descript.c:910 #, c-format msgid "Valid cases = %g; cases with missing value(s) = %g." msgstr "" @@ -1075,99 +1075,58 @@ msgstr "" msgid "Cannot open first page on DEVIND device %s." msgstr "" -#: src/dfm.c:88 src/dfm.c:565 -#, c-format -msgid "%s: Closing data-file handle %s." -msgstr "" - -#: src/dfm.c:115 -#, c-format -msgid "Cannot read from file %s already opened for %s." -msgstr "" - -#: src/dfm.c:129 -#, c-format -msgid "%s: Opening data-file handle %s for reading." -msgstr "" - -#: src/dfm.c:144 +#: src/dfm-read.c:153 #, c-format msgid "Could not open \"%s\" for reading as a data file: %s." msgstr "" -#: src/dfm.c:186 src/dfm.c:204 +#: src/dfm-read.c:186 src/dfm-read.c:204 msgid "BEGIN DATA expected." msgstr "" -#: src/dfm.c:213 +#: src/dfm-read.c:213 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.c:241 src/dfm.c:261 +#: src/dfm-read.c:246 src/dfm-read.c:266 #, c-format msgid "Error reading file %s: %s." msgstr "" -#: src/dfm.c:264 +#: src/dfm-read.c:269 #, c-format msgid "%s: Partial record at end of file." msgstr "" -#: src/dfm.c:300 +#: src/dfm-read.c:312 #, c-format msgid "Attempt to read beyond end-of-file on file %s." msgstr "" -#: src/dfm.c:446 -msgid "reading as a data file" -msgstr "" - -#: src/dfm.c:472 -#, c-format -msgid "Cannot write to file %s already opened for %s." -msgstr "" - -#: src/dfm.c:485 -#, c-format -msgid "%s: Opening data-file handle %s for writing." +#: src/dfm-read.c:315 +msgid "Attempt to read beyond END DATA." msgstr "" -#: src/dfm.c:491 -msgid "Cannot open the inline file for writing." +#: src/dfm-read.c:462 +msgid "" +"This command is not valid here since the current input program does not " +"access the inline file." msgstr "" -#: src/dfm.c:505 +#: src/dfm-write.c:67 #, c-format msgid "An error occurred while opening \"%s\" for writing as a data file: %s." msgstr "" -#: src/dfm.c:547 +#: src/dfm-write.c:103 #, c-format msgid "Error writing file %s: %s." msgstr "" -#: src/dfm.c:581 -msgid "writing as a data file" -msgstr "" - -#: src/dfm.c:598 -msgid "" -"This command is not valid here since the current input program does not " -"access the inline file." -msgstr "" - -#: src/dfm.c:605 -msgid "inline file: Opening for reading." -msgstr "" - -#: src/dfm.c:618 -msgid "Skipping remaining inline data." -msgstr "" - -#: src/dictionary.c:583 +#: src/dictionary.c:603 msgid "" "At least one case in the data file had a weight value that was user-missing, " "system-missing, zero, or negative. These case(s) were ignored." @@ -1236,7 +1195,7 @@ msgstr "" msgid "fatal" msgstr "" -#: src/error.c:259 src/error.c:266 src/error.c:269 src/expr-prs.c:1279 +#: src/error.c:259 src/error.c:266 src/error.c:269 src/expr-prs.c:1280 msgid "error" msgstr "" @@ -1252,53 +1211,53 @@ msgstr "" msgid "installation error" msgstr "" -#: src/expr-evl.c:633 +#: src/expr-evl.c:634 msgid "TIME.HMS cannot mix positive and negative in its arguments." msgstr "" -#: src/expr-evl.c:697 +#: src/expr-evl.c:698 msgid "Week argument to WKYR must be in range 0 to 53." msgstr "" -#: src/expr-evl.c:848 src/expr-evl.c:904 +#: src/expr-evl.c:849 src/expr-evl.c:905 msgid "Argument 3 of RINDEX may not be system-missing." msgstr "" -#: src/expr-evl.c:858 src/expr-evl.c:914 +#: src/expr-evl.c:859 src/expr-evl.c:915 msgid "" "Argument 3 of RINDEX must be between 1 and the length of argument 2, and it " "must evenly divide the length of argument 2." msgstr "" -#: src/expr-evl.c:1100 +#: src/expr-evl.c:1101 msgid "" "A number being treated as a Boolean in an expression was found to have a " "value other than 0 (false), 1 (true), or the system-missing value. The " "result was forced to 0." msgstr "" -#: src/expr-evl.c:1141 +#: src/expr-evl.c:1142 #, c-format msgid "" "SYSMIS is not a valid index value for vector %s. The result will be set to " "SYSMIS." msgstr "" -#: src/expr-evl.c:1145 +#: src/expr-evl.c:1146 #, c-format msgid "" "%g is not a valid index value for vector %s. The result will be set to " "SYSMIS." msgstr "" -#: src/expr-evl.c:1164 +#: src/expr-evl.c:1165 #, c-format msgid "" "SYSMIS is not a valid index value for vector %s. The result will be set to " "the empty string." msgstr "" -#: src/expr-evl.c:1169 +#: src/expr-evl.c:1170 #, c-format msgid "" "%g is not a valid index value for vector %s. The result will be set to the " @@ -1311,29 +1270,29 @@ msgid "" "Boolean value was found to have a constant value other than 0, 1, or SYSMIS." msgstr "" -#: src/expr-prs.c:137 +#: src/expr-prs.c:138 msgid "" "Type mismatch: expression has string type, but a numeric value is required " "here." msgstr "" -#: src/expr-prs.c:148 +#: src/expr-prs.c:149 msgid "" "Type mismatch: expression has numeric type, but a string value is required " "here." msgstr "" -#: src/expr-prs.c:207 +#: src/expr-prs.c:208 #, c-format msgid "Type mismatch: operands of %s operator must be strings." msgstr "" -#: src/expr-prs.c:210 +#: src/expr-prs.c:211 #, c-format msgid "Type mismatch: operands of %s operator must be numeric." msgstr "" -#: src/expr-prs.c:391 +#: src/expr-prs.c:392 msgid "" "Chaining relational operators (e.g. \"a < b < c\") will not produce the " "mathematically expected result. Use the AND logical operator to fix the " @@ -1341,336 +1300,336 @@ msgid "" "parentheses will disable this warning (e.g. \"(a < b) < c\".)" msgstr "" -#: src/expr-prs.c:471 +#: src/expr-prs.c:472 msgid "" "The exponentiation operator (\"**\") is left-associative, even though right-" "associative semantics are more useful. That is, \"a**b**c\" equals \"(a**b)" "**c\", not as \"a**(b**c)\". To disable this warning, insert parentheses." msgstr "" -#: src/expr-prs.c:552 +#: src/expr-prs.c:553 #, c-format msgid "Unknown system variable %s." msgstr "" -#: src/expr-prs.c:591 +#: src/expr-prs.c:592 msgid "expecting variable name" msgstr "" -#: src/expr-prs.c:634 +#: src/expr-prs.c:635 msgid "in expression" msgstr "" -#: src/expr-prs.c:730 +#: src/expr-prs.c:731 msgid "Argument 2 to LAG must be a small positive integer constant." msgstr "" -#: src/expr-prs.c:811 src/expr-prs.c:850 +#: src/expr-prs.c:812 src/expr-prs.c:851 #, c-format msgid "" "Type mismatch in argument %d of %s, which was expected to be of %s type. It " "was actually of %s type. " msgstr "" -#: src/expr-prs.c:837 +#: src/expr-prs.c:838 #, c-format msgid "%s cannot take Boolean operands." msgstr "" -#: src/expr-prs.c:869 +#: src/expr-prs.c:870 msgid "in function call" msgstr "" -#: src/expr-prs.c:883 +#: src/expr-prs.c:884 msgid "RANGE requires an odd number of arguments, but at least three." msgstr "" -#: src/expr-prs.c:893 +#: src/expr-prs.c:894 #, c-format msgid "%s requires at least two arguments." msgstr "" -#: src/expr-prs.c:908 +#: src/expr-prs.c:909 #, c-format msgid "%s.%d requires at least %d arguments." msgstr "" -#: src/expr-prs.c:973 +#: src/expr-prs.c:974 #, c-format msgid "" "Argument %d to CONCAT is type %s. All arguments to CONCAT must be strings." msgstr "" -#: src/expr-prs.c:1070 +#: src/expr-prs.c:1071 #, c-format msgid "" "Argument %d to %s was expected to be of %s type. It was actually of type %s." msgstr "" -#: src/expr-prs.c:1087 +#: src/expr-prs.c:1088 #, c-format msgid "%s is not a numeric format." msgstr "" -#: src/expr-prs.c:1125 +#: src/expr-prs.c:1126 #, c-format msgid "Too few arguments to function %s." msgstr "" -#: src/expr-prs.c:1158 +#: src/expr-prs.c:1159 #, c-format msgid "" "Type mismatch in argument %d of %s. A string expression was supplied where " "only a numeric expression is allowed." msgstr "" -#: src/expr-prs.c:1168 +#: src/expr-prs.c:1169 #, c-format msgid "Missing comma following argument %d of %s." msgstr "" -#: src/expr-prs.c:1206 +#: src/expr-prs.c:1207 msgid "The index value after a vector name must be numeric." msgstr "" -#: src/expr-prs.c:1213 +#: src/expr-prs.c:1214 msgid "`)' expected after a vector index value." msgstr "" -#: src/expr-prs.c:1246 +#: src/expr-prs.c:1247 #, c-format msgid "There is no function named %s." msgstr "" -#: src/expr-prs.c:1251 +#: src/expr-prs.c:1252 #, c-format msgid "Function %s may not be given a minimum number of arguments." msgstr "" -#: src/expr-prs.c:1260 +#: src/expr-prs.c:1261 #, c-format msgid "expecting `)' after %s function" msgstr "" -#: src/expr-prs.c:1282 +#: src/expr-prs.c:1283 msgid "Boolean" msgstr "" -#: src/filename.c:221 -#, c-format -msgid "Searching for `%s'..." -msgstr "" - -#: src/filename.c:229 src/filename.c:261 -msgid "Search unsuccessful!" -msgstr "" - -#: src/filename.c:254 -#, c-format -msgid "Found `%s'." -msgstr "" - -#: src/filename.c:686 -#, c-format -msgid "Not opening pipe file `%s' because SAFER option set." -msgstr "" - -#: src/file-type.c:127 +#: src/file-type.c:129 msgid "MIXED, GROUPED, or NESTED expected." msgstr "" -#: src/file-type.c:150 +#: src/file-type.c:152 msgid "The CASE subcommand is not valid on FILE TYPE MIXED." msgstr "" -#: src/file-type.c:168 +#: src/file-type.c:170 msgid "WARN or NOWARN expected after WILD." msgstr "" -#: src/file-type.c:176 +#: src/file-type.c:178 msgid "The DUPLICATE subcommand is not valid on FILE TYPE MIXED." msgstr "" -#: src/file-type.c:190 +#: src/file-type.c:192 msgid "DUPLICATE=CASE is only valid on FILE TYPE NESTED." msgstr "" -#: src/file-type.c:199 +#: src/file-type.c:201 #, c-format msgid "WARN%s expected after DUPLICATE." msgstr "" -#: src/file-type.c:200 +#: src/file-type.c:202 msgid ", NOWARN, or CASE" msgstr "" -#: src/file-type.c:201 +#: src/file-type.c:203 msgid " or NOWARN" msgstr "" -#: src/file-type.c:209 +#: src/file-type.c:211 msgid "The MISSING subcommand is not valid on FILE TYPE MIXED." msgstr "" -#: src/file-type.c:221 +#: src/file-type.c:223 msgid "WARN or NOWARN after MISSING." msgstr "" -#: src/file-type.c:229 +#: src/file-type.c:231 msgid "ORDERED is only valid on FILE TYPE GROUPED." msgstr "" -#: src/file-type.c:240 +#: src/file-type.c:242 msgid "YES or NO expected after ORDERED." msgstr "" -#: src/file-type.c:246 src/file-type.c:540 src/get.c:335 +#: src/file-type.c:248 src/file-type.c:543 src/get.c:389 msgid "while expecting a valid subcommand" msgstr "" -#: src/file-type.c:253 +#: src/file-type.c:255 msgid "The required RECORD subcommand was not present." msgstr "" -#: src/file-type.c:261 +#: src/file-type.c:263 msgid "The required CASE subcommand was not present." msgstr "" -#: src/file-type.c:267 +#: src/file-type.c:269 msgid "CASE and RECORD must specify different variable names." msgstr "" -#: src/file-type.c:324 +#: src/file-type.c:327 msgid "Column value must be positive." msgstr "" -#: src/file-type.c:340 +#: src/file-type.c:343 msgid "Ending column precedes beginning column." msgstr "" -#: src/file-type.c:360 +#: src/file-type.c:363 msgid "Bad format specifier name." msgstr "" -#: src/file-type.c:389 src/file-type.c:577 +#: src/file-type.c:392 src/file-type.c:580 msgid "" "This command may only appear within a FILE TYPE/END FILE TYPE structure." msgstr "" -#: src/file-type.c:412 +#: src/file-type.c:415 msgid "OTHER may appear only on the last RECORD TYPE command." msgstr "" -#: src/file-type.c:422 +#: src/file-type.c:425 msgid "No input commands (DATA LIST, REPEATING DATA) for above RECORD TYPE." msgstr "" -#: src/file-type.c:473 +#: src/file-type.c:476 msgid "" "The CASE subcommand is not allowed on the RECORD TYPE command for FILE TYPE " "MIXED." msgstr "" -#: src/file-type.c:483 +#: src/file-type.c:486 msgid "" "No variable name may be specified for the CASE subcommand on RECORD TYPE." msgstr "" -#: src/file-type.c:491 +#: src/file-type.c:494 msgid "" "The CASE column specification on RECORD TYPE must give a format specifier " "that is the same type as that of the CASE column specification given on FILE " "TYPE." msgstr "" -#: src/file-type.c:507 +#: src/file-type.c:510 msgid "WARN or NOWARN expected on DUPLICATE subcommand." msgstr "" -#: src/file-type.c:521 +#: src/file-type.c:524 msgid "WARN or NOWARN expected on MISSING subcommand." msgstr "" -#: src/file-type.c:534 +#: src/file-type.c:537 msgid "YES or NO expected on SPREAD subcommand." msgstr "" -#: src/file-type.c:590 +#: src/file-type.c:593 msgid "No input commands (DATA LIST, REPEATING DATA) on above RECORD TYPE." msgstr "" -#: src/file-type.c:597 +#: src/file-type.c:600 msgid "No commands between FILE TYPE and END FILE TYPE." msgstr "" -#: src/file-type.c:666 +#: src/file-type.c:669 #, c-format msgid "Unknown record type \"%.*s\"." msgstr "" -#: src/file-type.c:690 +#: src/file-type.c:693 #, c-format msgid "Unknown record type %g." msgstr "" -#: src/flip.c:77 +#: src/filename.c:221 +#, c-format +msgid "Searching for `%s'..." +msgstr "" + +#: src/filename.c:229 src/filename.c:261 +msgid "Search unsuccessful!" +msgstr "" + +#: src/filename.c:254 +#, c-format +msgid "Found `%s'." +msgstr "" + +#: src/filename.c:686 +#, c-format +msgid "Not opening pipe file `%s' because SAFER option set." +msgstr "" + +#: src/flip.c:78 msgid "" "FLIP ignores TEMPORARY. Temporary transformations will be made permanent." msgstr "" -#: src/flip.c:217 +#: src/flip.c:218 #, c-format msgid "Could not create acceptable variant for variable %s." msgstr "" -#: src/flip.c:233 +#: src/flip.c:234 msgid "Cannot create more than 99999 variable names." msgstr "" -#: src/flip.c:277 +#: src/flip.c:278 msgid "Could not create temporary file for FLIP." msgstr "" -#: src/flip.c:284 src/flip.c:352 +#: src/flip.c:285 src/flip.c:353 #, c-format msgid "Error writing FLIP file: %s." msgstr "" -#: src/flip.c:394 +#: src/flip.c:395 #, c-format msgid "Error rewinding FLIP file: %s." msgstr "" -#: src/flip.c:398 +#: src/flip.c:399 msgid "Error creating FLIP source file." msgstr "" -#: src/flip.c:407 +#: src/flip.c:408 #, c-format msgid "Error reading FLIP file: %s." msgstr "" -#: src/flip.c:424 +#: src/flip.c:425 #, c-format msgid "Error seeking FLIP source file: %s." msgstr "" -#: src/flip.c:429 +#: src/flip.c:430 #, c-format msgid "Error writing FLIP source file: %s." msgstr "" -#: src/flip.c:440 +#: src/flip.c:441 #, c-format msgid "Error rewind FLIP source file: %s." msgstr "" -#: src/flip.c:492 +#: src/flip.c:493 #, c-format msgid "Error reading FLIP temporary file: %s." msgstr "" -#: src/flip.c:495 +#: src/flip.c:496 msgid "Unexpected end of file reading FLIP temporary file." msgstr "" @@ -1765,15 +1724,15 @@ msgstr "" msgid "Format %s may not be assigned to a %s variable." msgstr "" -#: src/formats.c:116 src/numeric.c:64 src/numeric.c:135 +#: src/formats.c:116 src/numeric.c:65 src/numeric.c:136 msgid "`)' expected after output format." msgstr "" -#: src/get.c:341 +#: src/get.c:395 msgid "All variables deleted from system file dictionary." msgstr "" -#: src/get.c:388 +#: src/get.c:445 #, c-format msgid "" "Cannot rename %s as %s because there already exists a variable named %s. To " @@ -1781,78 +1740,78 @@ msgid "" "as \"/RENAME (A=B)(B=C)(C=A)\", or equivalently, \"/RENAME (A B C=B C A)\"." msgstr "" -#: src/get.c:413 +#: src/get.c:470 msgid "`=' expected after variable list." msgstr "" -#: src/get.c:420 +#: src/get.c:477 #, 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:433 +#: src/get.c:490 #, c-format msgid "Requested renaming duplicates variable name %s." msgstr "" -#: src/get.c:564 +#: src/get.c:674 msgid "The BY subcommand may be given once at most." msgstr "" -#: src/get.c:631 +#: src/get.c:746 msgid "The active file may not be specified more than once." msgstr "" -#: src/get.c:640 +#: src/get.c:755 msgid "Cannot specify the active file since no active file has been defined." msgstr "" -#: src/get.c:648 +#: src/get.c:763 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:682 +#: src/get.c:793 msgid "" "IN, FIRST, and LAST subcommands may not occur before the first FILE or TABLE." msgstr "" -#: src/get.c:717 +#: src/get.c:828 #, c-format msgid "Multiple %s subcommands for a single FILE or TABLE." msgstr "" -#: src/get.c:727 +#: src/get.c:838 #, c-format msgid "Duplicate variable name %s while creating %s variable." msgstr "" -#: src/get.c:741 +#: src/get.c:850 msgid "" "RENAME, KEEP, and DROP subcommands may not occur before the first FILE or " "TABLE." msgstr "" -#: src/get.c:765 +#: src/get.c:877 msgid "The BY subcommand is required when a TABLE subcommand is given." msgstr "" -#: src/get.c:786 +#: src/get.c:896 #, c-format msgid "File %s lacks BY variable %s." msgstr "" -#: src/get.c:1282 +#: src/get.c:1390 #, 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:1330 +#: src/get.c:1468 msgid "expecting COMM or TAPE" msgstr "" @@ -2073,7 +2032,7 @@ msgstr "" msgid "HTML output driver: %s: %s" msgstr "" -#: src/html.c:403 src/list.q:250 +#: src/html.c:403 src/list.q:252 #, c-format msgid "Cannot open first page on HTML device %s." msgstr "" @@ -2082,27 +2041,27 @@ msgstr "" msgid "expecting filename" msgstr "" -#: src/inpt-pgm.c:81 +#: src/inpt-pgm.c:82 msgid "No matching INPUT PROGRAM command." msgstr "" -#: src/inpt-pgm.c:86 +#: src/inpt-pgm.c:87 msgid "" "No data-input or transformation commands specified between INPUT PROGRAM and " "END INPUT PROGRAM." msgstr "" -#: src/inpt-pgm.c:287 src/inpt-pgm.c:420 +#: src/inpt-pgm.c:288 src/inpt-pgm.c:418 msgid "" "This command may only be executed between INPUT PROGRAM and END INPUT " "PROGRAM." msgstr "" -#: src/inpt-pgm.c:342 +#: src/inpt-pgm.c:338 msgid "COLUMN subcommand multiply specified." msgstr "" -#: src/inpt-pgm.c:395 +#: src/inpt-pgm.c:391 msgid "" "REREAD: Column numbers must be positive finite numbers. Column set to 1." msgstr "" @@ -2166,7 +2125,7 @@ msgstr "" msgid "" msgstr "" -#: src/lexer.c:993 src/pfm-read.c:136 src/repeat.c:213 +#: src/lexer.c:993 src/pfm-read.c:134 src/repeat.c:214 msgid "Unexpected end of file." msgstr "" @@ -2207,232 +2166,232 @@ msgid "" "spaces." msgstr "" -#: src/loop.c:193 +#: src/loop.c:194 msgid "The index variable may not be a string variable." msgstr "" -#: src/loop.c:299 +#: src/loop.c:300 msgid "There is no LOOP command that corresponds to this END LOOP." msgstr "" -#: src/loop.c:493 +#: src/loop.c:494 msgid "" "This command may only appear enclosed in a LOOP/END LOOP control structure." msgstr "" -#: src/loop.c:499 +#: src/loop.c:500 msgid "BREAK not enclosed in DO IF structure." msgstr "" -#: src/loop.c:577 +#: src/loop.c:578 #, c-format msgid "%s without %s." msgstr "" -#: src/main.c:74 +#: src/main.c:76 msgid "Error initializing output drivers." msgstr "" -#: src/main.c:140 +#: src/main.c:146 msgid "This command not executed." msgstr "" -#: src/main.c:144 +#: src/main.c:150 msgid "" "Skipping the rest of this command. Part of this command may have been " "executed." msgstr "" -#: src/main.c:149 +#: src/main.c:155 msgid "" "Skipping the rest of this command. This command was fully executed up to " "this point." msgstr "" -#: src/main.c:154 +#: src/main.c:160 msgid "" "Trailing garbage was encountered following this command. The command was " "fully executed to this point." msgstr "" -#: src/main.c:171 +#: src/main.c:177 msgid "The rest of this command has been discarded." msgstr "" -#: src/matrix-data.c:185 +#: src/matrix-data.c:208 msgid "VARIABLES subcommand multiply specified." msgstr "" -#: src/matrix-data.c:200 +#: src/matrix-data.c:223 msgid "VARNAME_ cannot be explicitly specified on VARIABLES." msgstr "" -#: src/matrix-data.c:265 +#: src/matrix-data.c:284 msgid "in FORMAT subcommand" msgstr "" -#: src/matrix-data.c:276 +#: src/matrix-data.c:295 msgid "SPLIT subcommand multiply specified." msgstr "" -#: src/matrix-data.c:283 +#: src/matrix-data.c:302 msgid "in SPLIT subcommand" msgstr "" -#: src/matrix-data.c:292 +#: src/matrix-data.c:311 msgid "Split variable may not be named ROWTYPE_ or VARNAME_." msgstr "" -#: src/matrix-data.c:325 +#: src/matrix-data.c:345 #, c-format msgid "Split variable %s is already another type." msgstr "" -#: src/matrix-data.c:340 +#: src/matrix-data.c:360 msgid "FACTORS subcommand multiply specified." msgstr "" -#: src/matrix-data.c:355 +#: src/matrix-data.c:378 #, c-format msgid "Factor variable %s is already another type." msgstr "" -#: src/matrix-data.c:370 +#: src/matrix-data.c:393 msgid "CELLS subcommand multiply specified." msgstr "" -#: src/matrix-data.c:376 src/matrix-data.c:395 +#: src/matrix-data.c:399 src/matrix-data.c:418 msgid "expecting positive integer" msgstr "" -#: src/matrix-data.c:389 +#: src/matrix-data.c:412 msgid "N subcommand multiply specified." msgstr "" -#: src/matrix-data.c:410 +#: src/matrix-data.c:433 msgid "CONTENTS subcommand multiply specified." msgstr "" -#: src/matrix-data.c:430 +#: src/matrix-data.c:453 msgid "Nested parentheses not allowed." msgstr "" -#: src/matrix-data.c:440 +#: src/matrix-data.c:463 msgid "Mismatched right parenthesis (`(')." msgstr "" -#: src/matrix-data.c:445 +#: src/matrix-data.c:468 msgid "Empty parentheses not allowed." msgstr "" -#: src/matrix-data.c:458 src/matrix-data.c:466 +#: src/matrix-data.c:481 src/matrix-data.c:489 msgid "in CONTENTS subcommand" msgstr "" -#: src/matrix-data.c:473 +#: src/matrix-data.c:496 #, c-format msgid "Content multiply specified for %s." msgstr "" -#: src/matrix-data.c:490 +#: src/matrix-data.c:513 msgid "Missing right parenthesis." msgstr "" -#: src/matrix-data.c:510 +#: src/matrix-data.c:533 msgid "Missing VARIABLES subcommand." msgstr "" -#: src/matrix-data.c:516 +#: src/matrix-data.c:539 msgid "" "CONTENTS subcommand not specified: assuming file contains only CORR matrix." msgstr "" -#: src/matrix-data.c:526 +#: src/matrix-data.c:549 msgid "" "Missing CELLS subcommand. CELLS is required when ROWTYPE_ is not given in " "the data and factors are present." msgstr "" -#: src/matrix-data.c:534 +#: src/matrix-data.c:557 msgid "Split file values must be present in the data when ROWTYPE_ is present." msgstr "" -#: src/matrix-data.c:589 +#: src/matrix-data.c:610 msgid "No continuous variables specified." msgstr "" -#: src/matrix-data.c:815 +#: src/matrix-data.c:853 msgid "Scope of string exceeds line." msgstr "" -#: src/matrix-data.c:882 +#: src/matrix-data.c:920 #, c-format msgid "End of line expected %s while reading %s." msgstr "" -#: src/matrix-data.c:1070 +#: src/matrix-data.c:1106 #, c-format msgid "expecting value for %s %s" msgstr "" -#: src/matrix-data.c:1232 +#: src/matrix-data.c:1270 #, c-format msgid "Syntax error expecting SPLIT FILE value %s." msgstr "" -#: src/matrix-data.c:1241 +#: src/matrix-data.c:1279 #, c-format msgid "Expecting value %g for %s." msgstr "" -#: src/matrix-data.c:1282 src/matrix-data.c:1750 +#: src/matrix-data.c:1320 src/matrix-data.c:1787 #, c-format msgid "Syntax error expecting factor value %s." msgstr "" -#: src/matrix-data.c:1291 +#: src/matrix-data.c:1329 #, c-format msgid "Syntax error expecting value %g for %s %s." msgstr "" -#: src/matrix-data.c:1527 +#: src/matrix-data.c:1564 #, c-format msgid "Syntax error %s expecting SPLIT FILE value." msgstr "" -#: src/matrix-data.c:1657 +#: src/matrix-data.c:1694 #, c-format msgid "" "Expected %d lines of data for %s content; actually saw %d lines. No data " "will be output for this content." msgstr "" -#: src/matrix-data.c:1692 +#: src/matrix-data.c:1729 #, c-format msgid "Multiply specified ROWTYPE_ %s." msgstr "" -#: src/matrix-data.c:1697 +#: src/matrix-data.c:1734 #, c-format msgid "Syntax error %s expecting ROWTYPE_ string." msgstr "" -#: src/matrix-data.c:1717 +#: src/matrix-data.c:1754 #, c-format msgid "Syntax error %s." msgstr "" -#: src/matrix-data.c:1867 +#: src/matrix-data.c:1904 #, c-format msgid "Duplicate specification for %s." msgstr "" -#: src/matrix-data.c:1879 +#: src/matrix-data.c:1916 #, c-format msgid "Too many rows of matrix data for %s." msgstr "" -#: src/matrix-data.c:1927 +#: src/matrix-data.c:1964 #, c-format msgid "Syntax error expecting value for %s %s." msgstr "" @@ -2475,79 +2434,79 @@ msgstr "" msgid "String is not of proper length." msgstr "" -#: src/mis-val.c:316 src/repeat.c:459 +#: src/mis-val.c:316 src/repeat.c:460 msgid "String expected." msgstr "" -#: src/modify-vars.c:88 +#: src/modify-vars.c:89 msgid "" "MODIFY VARS may not be used after TEMPORARY. Temporary transformations will " "be made permanent." msgstr "" -#: src/modify-vars.c:112 +#: src/modify-vars.c:113 msgid "REORDER subcommand may be given at most once." msgstr "" -#: src/modify-vars.c:135 +#: src/modify-vars.c:136 msgid "Cannot specify ALL after specifying a set of variables." msgstr "" -#: src/modify-vars.c:145 +#: src/modify-vars.c:146 msgid "`(' expected on REORDER subcommand." msgstr "" -#: src/modify-vars.c:157 +#: src/modify-vars.c:158 msgid "`)' expected following variable names on REORDER subcommand." msgstr "" -#: src/modify-vars.c:175 +#: src/modify-vars.c:176 msgid "RENAME subcommand may be given at most once." msgstr "" -#: src/modify-vars.c:188 +#: src/modify-vars.c:189 msgid "`(' expected on RENAME subcommand." msgstr "" -#: src/modify-vars.c:196 +#: src/modify-vars.c:197 msgid "" "`=' expected between lists of new and old variable names on RENAME " "subcommand." msgstr "" -#: src/modify-vars.c:204 src/rename-vars.c:74 +#: src/modify-vars.c:205 src/rename-vars.c:75 #, c-format msgid "" "Differing number of variables in old name list (%d) and in new name list (%" "d)." msgstr "" -#: src/modify-vars.c:215 +#: src/modify-vars.c:216 msgid "`)' expected after variable lists on RENAME subcommand." msgstr "" -#: src/modify-vars.c:229 +#: src/modify-vars.c:230 msgid "" "KEEP subcommand may be given at most once. It may notbe given in " "conjunction with the DROP subcommand." msgstr "" -#: src/modify-vars.c:271 +#: src/modify-vars.c:272 msgid "" "DROP subcommand may be given at most once. It may not be given in " "conjunction with the KEEP subcommand." msgstr "" -#: src/modify-vars.c:297 +#: src/modify-vars.c:298 #, c-format msgid "Unrecognized subcommand name `%s'." msgstr "" -#: src/modify-vars.c:299 +#: src/modify-vars.c:300 msgid "Subcommand name expected." msgstr "" -#: src/modify-vars.c:307 +#: src/modify-vars.c:308 msgid "`/' or `.' expected." msgstr "" @@ -2555,17 +2514,17 @@ msgstr "" msgid "expecting weight value" msgstr "" -#: src/numeric.c:57 +#: src/numeric.c:58 #, c-format msgid "Format type %s may not be used with a numeric variable." msgstr "" -#: src/numeric.c:76 src/numeric.c:158 src/vector.c:155 +#: src/numeric.c:77 src/numeric.c:159 src/vector.c:156 #, c-format msgid "There is already a variable named %s." msgstr "" -#: src/numeric.c:128 +#: src/numeric.c:129 #, c-format msgid "Format type %s may not be used with a string variable." msgstr "" @@ -2750,223 +2709,179 @@ msgstr "" msgid "portable file %s corrupt at offset %ld: " msgstr "" -#: src/pfm-read.c:111 src/pfm-write.c:504 +#: src/pfm-read.c:114 src/pfm-write.c:490 #, c-format msgid "%s: Closing portable file: %s." msgstr "" -#: src/pfm-read.c:144 +#: src/pfm-read.c:142 msgid "Bad line end." msgstr "" -#: src/pfm-read.c:225 -#, c-format -msgid "Cannot read file %s as portable file: already opened for %s." -msgstr "" - -#: src/pfm-read.c:231 -#, c-format -msgid "%s: Opening portable-file handle %s for reading." -msgstr "" - -#: src/pfm-read.c:239 +#: src/pfm-read.c:233 #, c-format msgid "" "An error occurred while opening \"%s\" for reading as a portable file: %s." msgstr "" -#: src/pfm-read.c:274 +#: src/pfm-read.c:256 msgid "Data record expected." msgstr "" -#: src/pfm-read.c:276 -msgid "Read portable-file dictionary successfully." -msgstr "" - -#: src/pfm-read.c:282 -msgid "Error reading portable-file dictionary." -msgstr "" - -#: src/pfm-read.c:380 +#: src/pfm-read.c:353 msgid "Missing numeric terminator." msgstr "" -#: src/pfm-read.c:417 +#: src/pfm-read.c:390 msgid "Bad integer format." msgstr "" -#: src/pfm-read.c:447 +#: src/pfm-read.c:419 #, c-format msgid "Bad string length %d." msgstr "" -#: src/pfm-read.c:546 +#: src/pfm-read.c:514 #, c-format msgid "Bad date string length %d." msgstr "" -#: src/pfm-read.c:550 +#: src/pfm-read.c:518 msgid "Bad character in date." msgstr "" -#: src/pfm-read.c:570 +#: src/pfm-read.c:538 #, c-format msgid "Bad time string length %d." msgstr "" -#: src/pfm-read.c:574 +#: src/pfm-read.c:542 msgid "Bad character in time." msgstr "" -#: src/pfm-read.c:624 src/pfm-read.c:631 src/sfm-read.c:912 src/sfm-read.c:920 +#: src/pfm-read.c:592 src/pfm-read.c:599 src/sfm-read.c:873 src/sfm-read.c:881 #, c-format msgid "%s: Bad format specifier byte (%d)." msgstr "" -#: src/pfm-read.c:633 +#: src/pfm-read.c:601 #, c-format msgid "%s variable %s has %s format specifier %s." msgstr "" -#: src/pfm-read.c:634 src/print.c:601 src/sfm-read.c:925 +#: src/pfm-read.c:602 src/print.c:607 src/sfm-read.c:886 msgid "String" msgstr "" -#: src/pfm-read.c:634 src/print.c:601 src/sfm-read.c:925 +#: src/pfm-read.c:602 src/print.c:607 src/sfm-read.c:886 msgid "Numeric" msgstr "" -#: src/pfm-read.c:673 +#: src/pfm-read.c:640 msgid "Expected variable count record." msgstr "" -#: src/pfm-read.c:677 +#: src/pfm-read.c:644 #, c-format msgid "Invalid number of variables %d." msgstr "" -#: src/pfm-read.c:687 +#: src/pfm-read.c:654 #, c-format msgid "Unexpected flag value %d." msgstr "" -#: src/pfm-read.c:701 +#: src/pfm-read.c:666 #, c-format msgid "Weight variable name (%s) truncated." msgstr "" -#: src/pfm-read.c:716 +#: src/pfm-read.c:681 msgid "Expected variable record." msgstr "" -#: src/pfm-read.c:722 +#: src/pfm-read.c:687 #, c-format msgid "Invalid variable width %d." msgstr "" -#: src/pfm-read.c:740 +#: src/pfm-read.c:705 #, c-format msgid "position %d: Variable name has %u characters." msgstr "" -#: src/pfm-read.c:744 +#: src/pfm-read.c:709 #, c-format msgid "position %d: Variable name begins with invalid character." msgstr "" -#: src/pfm-read.c:748 +#: src/pfm-read.c:713 #, c-format msgid "position %d: Variable name begins with lowercase letter %c." msgstr "" -#: src/pfm-read.c:761 +#: src/pfm-read.c:726 #, c-format msgid "position %d: Variable name character %d is lowercase letter %c." msgstr "" -#: src/pfm-read.c:771 +#: src/pfm-read.c:736 #, c-format msgid "position %d: character `\\%03o' is not valid in a variable name." msgstr "" -#: src/pfm-read.c:782 +#: src/pfm-read.c:748 #, c-format msgid "Duplicate variable name %s." msgstr "" -#: src/pfm-read.c:826 +#: src/pfm-read.c:792 #, c-format msgid "Bad missing values for %s." msgstr "" -#: src/pfm-read.c:849 +#: src/pfm-read.c:815 #, c-format msgid "Weighting variable %s not present in dictionary." msgstr "" -#: src/pfm-read.c:922 +#: src/pfm-read.c:886 #, c-format msgid "Unknown variable %s while parsing value labels." msgstr "" -#: src/pfm-read.c:925 +#: src/pfm-read.c:889 #, c-format msgid "" "Cannot assign value labels to %s and %s, which have different variable types " "or widths." msgstr "" -#: src/pfm-read.c:958 +#: src/pfm-read.c:922 #, c-format msgid "Duplicate label for value %g for variable %s." msgstr "" -#: src/pfm-read.c:961 +#: src/pfm-read.c:925 #, c-format msgid "Duplicate label for value `%.*s' for variable %s." msgstr "" -#: src/pfm-read.c:1032 +#: src/pfm-read.c:978 msgid "End of file midway through case." msgstr "" -#: src/pfm-read.c:1042 -msgid "reading as a portable file" -msgstr "" - -#: src/pfm-write.c:71 -#, c-format -msgid "Cannot write file %s as portable file: already opened for %s." -msgstr "" - -#: src/pfm-write.c:77 -#, c-format -msgid "%s: Opening portable-file handle %s for writing." -msgstr "" - -#: src/pfm-write.c:87 +#: src/pfm-write.c:92 #, c-format msgid "" "An error occurred while opening \"%s\" for writing as a portable file: %s." msgstr "" -#: src/pfm-write.c:124 -msgid "Wrote portable-file header successfully." -msgstr "" - -#: src/pfm-write.c:129 -msgid "Error writing portable-file header." -msgstr "" - -#: src/pfm-write.c:170 +#: src/pfm-write.c:154 #, c-format msgid "%s: Writing portable file: %s." msgstr "" -#: src/pfm-write.c:514 -msgid "writing as a portable file" -msgstr "" - #: src/postscript.c:323 #, c-format msgid "PostScript driver initializing as `%s'..." @@ -3098,80 +3013,80 @@ msgstr "" msgid "PostScript driver: Cannot find encoding `%s' for PostScript font `%s'." msgstr "" -#: src/print.c:180 +#: src/print.c:179 msgid "expecting a valid subcommand" msgstr "" -#: src/print.c:359 src/print.c:376 +#: src/print.c:365 src/print.c:382 #, c-format msgid "%g is not a valid column location." msgstr "" -#: src/print.c:370 +#: src/print.c:376 #, c-format msgid "Column location expected following `%d-'." msgstr "" -#: src/print.c:381 +#: src/print.c:387 #, c-format msgid "" "%d-%ld is not a valid column range. The second column must be greater than " "or equal to the first." msgstr "" -#: src/print.c:487 +#: src/print.c:493 #, c-format msgid "" "%s is not of the same type as %s. To specify variables of different types " "in the same variable list, use a FORTRAN-like format specifier." msgstr "" -#: src/print.c:517 +#: src/print.c:523 msgid "" "The ending column for a field must not be less than the starting column." msgstr "" -#: src/print.c:600 +#: src/print.c:606 #, c-format msgid "%s variables cannot be displayed with format %s." msgstr "" -#: src/print.c:678 +#: src/print.c:684 msgid "" "The number of format specifications exceeds the number of variable names " "given." msgstr "" -#: src/print.c:687 +#: src/print.c:693 #, c-format msgid "Display format %s may not be used with a %s variable." msgstr "" -#: src/print.c:835 +#: src/print.c:841 #, c-format msgid "Writing %d record(s) to file %s." msgstr "" -#: src/print.c:838 +#: src/print.c:844 #, c-format msgid "Writing %d record(s) to the listing file." msgstr "" -#: src/print.c:1080 +#: src/print.c:1092 #, c-format msgid "" "The expression on PRINT SPACE evaluated to %d. It's not possible to PRINT " "SPACE a negative number of lines." msgstr "" -#: src/recode.c:282 +#: src/recode.c:283 #, c-format msgid "" "%d variable(s) cannot be recoded into %d variable(s). Specify the same " "number of variables as input and output variables." msgstr "" -#: src/recode.c:296 +#: src/recode.c:297 #, c-format msgid "" "There is no string variable named %s. (All string variables specified on " @@ -3179,83 +3094,83 @@ msgid "" "variable.)" msgstr "" -#: src/recode.c:305 +#: src/recode.c:306 #, c-format msgid "" "Type mismatch between input and output variables. Output variable %s is not " "a string variable, but all the input variables are string variables." msgstr "" -#: src/recode.c:324 +#: src/recode.c:325 #, c-format msgid "Type mismatch after INTO: %s is not a numeric variable." msgstr "" -#: src/recode.c:354 +#: src/recode.c:355 msgid "" "INTO must be used when the input values are numeric and output values are " "string." msgstr "" -#: src/recode.c:362 +#: src/recode.c:363 msgid "" "INTO must be used when the input values are string and output values are " "numeric." msgstr "" -#: src/recode.c:485 +#: src/recode.c:486 msgid "expecting output value" msgstr "" -#: src/recode.c:499 +#: src/recode.c:500 msgid "" "Inconsistent output types. The output values must be all numeric or all " "string." msgstr "" -#: src/recode.c:550 +#: src/recode.c:551 msgid "following LO THRU" msgstr "" -#: src/recode.c:566 src/recode.c:595 +#: src/recode.c:567 src/recode.c:596 msgid "in source value" msgstr "" -#: src/recode.c:608 +#: src/recode.c:609 msgid "" "Keyword CONVERT may only be used with string input values and numeric output " "values." msgstr "" -#: src/rename-vars.c:47 +#: src/rename-vars.c:48 msgid "" "RENAME VARS may not be used after TEMPORARY. Temporary transformations will " "be made permanent." msgstr "" -#: src/rename-vars.c:59 +#: src/rename-vars.c:60 msgid "`(' expected." msgstr "" -#: src/rename-vars.c:67 +#: src/rename-vars.c:68 msgid "`=' expected between lists of new and old variable names." msgstr "" -#: src/rename-vars.c:85 +#: src/rename-vars.c:86 msgid "`)' expected after variable names." msgstr "" -#: src/rename-vars.c:95 +#: src/rename-vars.c:96 #, c-format msgid "Renaming would duplicate variable name %s." msgstr "" -#: src/repeat.c:150 +#: src/repeat.c:151 #, c-format msgid "Identifier %s is given twice." msgstr "" -#: src/repeat.c:193 +#: src/repeat.c:194 #, c-format msgid "" "There must be the same number of substitutions for each dummy variable " @@ -3263,11 +3178,11 @@ msgid "" "s as well, but %d were specified." msgstr "" -#: src/repeat.c:298 +#: src/repeat.c:299 msgid "No commands in scope." msgstr "" -#: src/repeat.c:486 +#: src/repeat.c:487 msgid "No matching DO REPEAT." msgstr "" @@ -3280,129 +3195,111 @@ msgstr "" msgid "Cannot sample %d observations from a population of %d." msgstr "" -#: src/sel-if.c:99 +#: src/sel-if.c:100 msgid "The filter variable must be numeric." msgstr "" -#: src/sel-if.c:105 +#: src/sel-if.c:106 msgid "The filter variable may not be scratch." msgstr "" -#: src/sel-if.c:136 +#: src/sel-if.c:137 msgid "Only last instance of this command is in effect." msgstr "" -#: src/sfm-read.c:147 +#: src/sfm-read.c:140 msgid "corrupt system file: " msgstr "" -#: src/sfm-read.c:163 src/sfm-write.c:743 +#: src/sfm-read.c:157 src/sfm-write.c:808 #, c-format msgid "%s: Closing system file: %s." msgstr "" -#: src/sfm-read.c:237 -#, c-format -msgid "Cannot read file %s as system file: already opened for %s." -msgstr "" - -#: src/sfm-read.c:242 -#, c-format -msgid "%s: Opening system-file handle %s for reading." -msgstr "" - -#: src/sfm-read.c:250 +#: src/sfm-read.c:240 #, c-format msgid "" "An error occurred while opening \"%s\" for reading as a system file: %s." msgstr "" -#: src/sfm-read.c:285 +#: src/sfm-read.c:258 #, c-format msgid "" "%s: Weighting variable may not be a continuation of a long string variable." msgstr "" -#: src/sfm-read.c:288 +#: src/sfm-read.c:261 #, c-format msgid "%s: Weighting variable may not be a string variable." msgstr "" -#: src/sfm-read.c:313 +#: src/sfm-read.c:286 #, 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:362 +#: src/sfm-read.c:335 #, c-format msgid "%s: Unrecognized record type 7, subtype %d encountered in system file." msgstr "" -#: src/sfm-read.c:387 +#: src/sfm-read.c:360 #, c-format msgid "%s: Unrecognized record type %d." msgstr "" -#: src/sfm-read.c:394 -msgid "Read system-file dictionary successfully." -msgstr "" - -#: src/sfm-read.c:401 -msgid "Error reading system-file header." -msgstr "" - -#: src/sfm-read.c:425 +#: src/sfm-read.c:392 #, 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:437 +#: src/sfm-read.c:403 #, 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:453 +#: src/sfm-read.c:419 #, c-format msgid "" "%s: File-indicated endianness (%s) does not match endianness intuited from " "file header (%s)." msgstr "" -#: src/sfm-read.c:456 src/sfm-read.c:457 +#: src/sfm-read.c:422 src/sfm-read.c:423 msgid "big-endian" msgstr "" -#: src/sfm-read.c:456 src/sfm-read.c:457 +#: src/sfm-read.c:422 src/sfm-read.c:423 msgid "little-endian" msgstr "" -#: src/sfm-read.c:458 +#: src/sfm-read.c:424 msgid "unknown" msgstr "" -#: src/sfm-read.c:462 +#: src/sfm-read.c:428 #, c-format msgid "%s: File-indicated character representation code (%s) is not ASCII." msgstr "" -#: src/sfm-read.c:466 +#: src/sfm-read.c:432 msgid "DEC Kanji" msgstr "" -#: src/sfm-read.c:485 +#: src/sfm-read.c:448 #, 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:500 +#: src/sfm-read.c:463 #, c-format msgid "" "%s: File-indicated value is different from internal value for at least one " @@ -3410,263 +3307,236 @@ msgid "" "%g; LOWEST: %g, %g." msgstr "" -#: src/sfm-read.c:531 +#: src/sfm-read.c:490 #, 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:574 +#: src/sfm-read.c:532 #, 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:590 +#: src/sfm-read.c:548 #, c-format msgid "%s: Number of elements per case (%d) is not between 1 and %d." msgstr "" -#: src/sfm-read.c:599 +#: src/sfm-read.c:557 #, 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:605 +#: src/sfm-read.c:564 #, c-format msgid "%s: Number of cases in file (%ld) is not between -1 and %d." msgstr "" -#: src/sfm-read.c:610 +#: src/sfm-read.c:569 #, c-format msgid "%s: Compression bias (%g) is not the usual value of 100." msgstr "" -#: src/sfm-read.c:704 +#: src/sfm-read.c:662 #, c-format msgid "%s: position %d: Bad record type (%d); the expected value was 2." msgstr "" -#: src/sfm-read.c:714 +#: src/sfm-read.c:672 #, c-format msgid "" "%s: position %d: String variable does not have proper number of continuation " "records." msgstr "" -#: src/sfm-read.c:723 +#: src/sfm-read.c:681 #, c-format msgid "%s: position %d: Superfluous long string continuation record." msgstr "" -#: src/sfm-read.c:729 +#: src/sfm-read.c:687 #, c-format msgid "%s: position %d: Bad variable type code %d." msgstr "" -#: src/sfm-read.c:732 +#: src/sfm-read.c:690 #, c-format msgid "%s: position %d: Variable label indicator field is not 0 or 1." msgstr "" -#: src/sfm-read.c:736 +#: src/sfm-read.c:694 #, c-format msgid "" "%s: position %d: Missing value indicator field is not -3, -2, 0, 1, 2, or 3." msgstr "" -#: src/sfm-read.c:742 +#: src/sfm-read.c:700 #, c-format msgid "%s: position %d: Variable name begins with invalid character." msgstr "" -#: src/sfm-read.c:746 +#: src/sfm-read.c:704 #, c-format msgid "%s: position %d: Variable name begins with lowercase letter %c." msgstr "" -#: src/sfm-read.c:750 +#: src/sfm-read.c:708 #, c-format msgid "" "%s: position %d: Variable name begins with octothorpe (`#'). Scratch " "variables should not appear in system files." msgstr "" -#: src/sfm-read.c:765 +#: src/sfm-read.c:723 #, c-format msgid "%s: position %d: Variable name character %d is lowercase letter %c." msgstr "" -#: src/sfm-read.c:774 +#: src/sfm-read.c:732 #, c-format msgid "" "%s: position %d: character `\\%03o' (%c) is not valid in a variable name." msgstr "" -#: src/sfm-read.c:783 +#: src/sfm-read.c:741 #, c-format msgid "%s: Duplicate variable name `%s' within system file." msgstr "" -#: src/sfm-read.c:808 +#: src/sfm-read.c:762 #, c-format msgid "%s: Variable %s indicates variable label of invalid length %d." msgstr "" -#: src/sfm-read.c:825 +#: src/sfm-read.c:779 #, c-format msgid "%s: Long string variable %s may not have missing values." msgstr "" -#: src/sfm-read.c:850 +#: src/sfm-read.c:804 #, c-format msgid "" "%s: String variable %s may not have missing values specified as a range." msgstr "" -#: src/sfm-read.c:888 +#: src/sfm-read.c:852 #, c-format msgid "%s: Long string continuation records omitted at end of dictionary." msgstr "" -#: src/sfm-read.c:892 +#: src/sfm-read.c:856 #, c-format msgid "" "%s: System file header indicates %d variable positions but %d were read from " "file." msgstr "" -#: src/sfm-read.c:923 +#: src/sfm-read.c:884 #, c-format msgid "%s: %s variable %s has %s format specifier %s." msgstr "" -#: src/sfm-read.c:1003 +#: src/sfm-read.c:963 #, 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:1014 +#: src/sfm-read.c:974 #, 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:1030 +#: src/sfm-read.c:990 #, 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:1037 +#: src/sfm-read.c:997 #, 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:1042 +#: src/sfm-read.c:1002 #, c-format msgid "%s: Value labels are not allowed on long string variables (%s)." msgstr "" -#: src/sfm-read.c:1053 +#: src/sfm-read.c:1013 #, 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:1094 +#: src/sfm-read.c:1054 #, c-format msgid "%s: File contains duplicate label for value %g for variable %s." msgstr "" -#: src/sfm-read.c:1098 +#: src/sfm-read.c:1058 #, c-format msgid "%s: File contains duplicate label for value `%.*s' for variable %s." msgstr "" -#: src/sfm-read.c:1135 src/sfm-read.c:1338 +#: src/sfm-read.c:1093 src/sfm-read.c:1357 #, c-format msgid "%s: Reading system file: %s." msgstr "" -#: src/sfm-read.c:1138 src/sfm-read.c:1245 src/sfm-read.c:1287 +#: src/sfm-read.c:1096 src/sfm-read.c:1198 src/sfm-read.c:1240 #, c-format msgid "%s: Unexpected end of file." msgstr "" -#: src/sfm-read.c:1157 +#: src/sfm-read.c:1113 #, c-format msgid "%s: System file contains multiple type 6 (document) records." msgstr "" -#: src/sfm-read.c:1163 +#: src/sfm-read.c:1119 #, c-format msgid "%s: Number of document lines (%ld) must be greater than 0." msgstr "" -#: src/sfm-read.c:1196 +#: src/sfm-read.c:1151 #, c-format msgid "%s: Error reading file: %s." msgstr "" -#: src/sfm-read.c:1235 +#: src/sfm-read.c:1188 #, c-format msgid "%s: Compressed data is corrupted. Data ends in partial case." msgstr "" -#: src/sfm-read.c:1341 +#: src/sfm-read.c:1360 #, c-format msgid "%s: Partial record at end of system file." msgstr "" -#: src/sfm-read.c:1380 -msgid "reading as a system file" -msgstr "" - -#: src/sfm-write.c:95 -#, c-format -msgid "Cannot write file %s as system file: already opened for %s." -msgstr "" - -#: src/sfm-write.c:101 -#, c-format -msgid "%s: Opening system-file handle %s for writing." -msgstr "" - -#: src/sfm-write.c:111 +#: src/sfm-write.c:143 #, c-format -msgid "" -"An error occurred while opening \"%s\" for writing as a system file: %s." -msgstr "" - -#: src/sfm-write.c:165 -msgid "Wrote system-file header successfully." +msgid "Error opening \"%s\" for writing as a system file: %s." msgstr "" -#: src/sfm-write.c:170 -msgid "Error writing system-file header." -msgstr "" - -#: src/sfm-write.c:606 +#: src/sfm-write.c:628 #, c-format msgid "%s: Writing system file: %s." msgstr "" -#: src/sfm-write.c:754 -msgid "writing as a system file" -msgstr "" - #: src/sort.c:197 msgid "`A' or `D' expected inside parentheses." msgstr "" @@ -3682,141 +3552,141 @@ msgid "" "each. (PSPP workspace is currently restricted to a maximum of %d KB.)" msgstr "" -#: src/sysfile-info.c:94 +#: src/sysfile-info.c:96 msgid "File:" msgstr "" -#: src/sysfile-info.c:96 +#: src/sysfile-info.c:98 msgid "Label:" msgstr "" -#: src/sysfile-info.c:100 +#: src/sysfile-info.c:102 msgid "No label." msgstr "" -#: src/sysfile-info.c:103 +#: src/sysfile-info.c:105 msgid "Created:" msgstr "" -#: src/sysfile-info.c:106 +#: src/sysfile-info.c:108 msgid "Endian:" msgstr "" -#: src/sysfile-info.c:107 +#: src/sysfile-info.c:109 msgid "Big." msgstr "" -#: src/sysfile-info.c:107 +#: src/sysfile-info.c:109 msgid "Little." msgstr "" -#: src/sysfile-info.c:108 +#: src/sysfile-info.c:110 msgid "Variables:" msgstr "" -#: src/sysfile-info.c:111 +#: src/sysfile-info.c:113 msgid "Cases:" msgstr "" -#: src/sysfile-info.c:114 +#: src/sysfile-info.c:116 msgid "Type:" msgstr "" -#: src/sysfile-info.c:115 +#: src/sysfile-info.c:117 msgid "System File." msgstr "" -#: src/sysfile-info.c:116 +#: src/sysfile-info.c:118 msgid "Weight:" msgstr "" -#: src/sysfile-info.c:120 +#: src/sysfile-info.c:122 msgid "Not weighted." msgstr "" -#: src/sysfile-info.c:122 +#: src/sysfile-info.c:124 msgid "Mode:" msgstr "" -#: src/sysfile-info.c:124 +#: src/sysfile-info.c:126 #, c-format msgid "Compression %s." msgstr "" -#: src/sysfile-info.c:124 +#: src/sysfile-info.c:126 msgid "on" msgstr "" -#: src/sysfile-info.c:124 +#: src/sysfile-info.c:126 msgid "off" msgstr "" -#: src/sysfile-info.c:133 src/sysfile-info.c:370 +#: src/sysfile-info.c:135 src/sysfile-info.c:372 msgid "Description" msgstr "" -#: src/sysfile-info.c:134 src/sysfile-info.c:368 +#: src/sysfile-info.c:136 src/sysfile-info.c:370 msgid "Position" msgstr "" -#: src/sysfile-info.c:191 +#: src/sysfile-info.c:193 msgid "The active file does not have a file label." msgstr "" -#: src/sysfile-info.c:194 +#: src/sysfile-info.c:196 msgid "File label:" msgstr "" -#: src/sysfile-info.c:256 +#: src/sysfile-info.c:258 msgid "No variables to display." msgstr "" -#: src/sysfile-info.c:275 +#: src/sysfile-info.c:277 msgid "Macros not supported." msgstr "" -#: src/sysfile-info.c:285 +#: src/sysfile-info.c:287 msgid "The active file dictionary does not contain any documents." msgstr "" -#: src/sysfile-info.c:294 +#: src/sysfile-info.c:296 msgid "Documents in the active file:" msgstr "" -#: src/sysfile-info.c:372 src/sysfile-info.c:530 src/vfm.c:876 +#: src/sysfile-info.c:374 src/sysfile-info.c:532 src/vfm.c:877 msgid "Label" msgstr "" -#: src/sysfile-info.c:444 +#: src/sysfile-info.c:446 #, c-format msgid "Format: %s" msgstr "" -#: src/sysfile-info.c:451 +#: src/sysfile-info.c:453 #, c-format msgid "Print Format: %s" msgstr "" -#: src/sysfile-info.c:454 +#: src/sysfile-info.c:456 #, c-format msgid "Write Format: %s" msgstr "" -#: src/sysfile-info.c:462 +#: src/sysfile-info.c:464 msgid "Missing Values: " msgstr "" -#: src/sysfile-info.c:529 src/vfm.c:875 src/crosstabs.q:1068 -#: src/crosstabs.q:1095 src/crosstabs.q:1115 src/crosstabs.q:1137 -#: src/examine.q:1125 src/frequencies.q:1056 src/frequencies.q:1174 +#: src/sysfile-info.c:531 src/vfm.c:876 src/crosstabs.q:1099 +#: src/crosstabs.q:1126 src/crosstabs.q:1146 src/crosstabs.q:1168 +#: src/examine.q:1179 src/frequencies.q:1083 src/frequencies.q:1204 msgid "Value" msgstr "" -#: src/sysfile-info.c:586 +#: src/sysfile-info.c:588 msgid "No vectors defined." msgstr "" -#: src/sysfile-info.c:601 +#: src/sysfile-info.c:603 msgid "Vector" msgstr "" @@ -3831,36 +3701,36 @@ 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:45 +#: src/temporary.c:46 msgid "This command is not valid inside DO IF or LOOP." msgstr "" -#: src/temporary.c:52 +#: src/temporary.c:53 msgid "" "This command may only appear once between procedures and procedure-like " "commands." msgstr "" -#: src/title.c:55 +#: src/title.c:56 #, c-format msgid "%s before: %s\n" msgstr "" -#: src/title.c:55 +#: src/title.c:56 msgid "" msgstr "" -#: src/title.c:67 +#: src/title.c:68 #, c-format msgid "%s: `.' expected after string." msgstr "" -#: src/title.c:83 +#: src/title.c:84 #, c-format msgid "%s after: %s\n" msgstr "" -#: src/title.c:139 +#: src/title.c:140 #, c-format msgid "Document entered %s %02d:%02d:%02d by %s (%s):" msgstr "" @@ -3889,29 +3759,29 @@ msgstr "" msgid "Truncating variable label to 255 characters." msgstr "" -#: src/vars-prs.c:48 +#: src/vars-prs.c:49 #, c-format msgid "%s is not a variable name." msgstr "" -#: src/vars-prs.c:100 +#: src/vars-prs.c:101 msgid "ordinary" msgstr "" -#: src/vars-prs.c:102 +#: src/vars-prs.c:103 msgid "system" msgstr "" -#: src/vars-prs.c:104 +#: src/vars-prs.c:105 msgid "scratch" msgstr "" -#: src/vars-prs.c:209 +#: src/vars-prs.c:210 #, c-format msgid "%s TO %s is not valid syntax since %s precedes %s in the dictionary." msgstr "" -#: src/vars-prs.c:219 +#: src/vars-prs.c:220 #, c-format msgid "" "When using the TO keyword to specify several variables, both variables must " @@ -3919,700 +3789,706 @@ msgid "" "system variables. %s is a %s variable, whereas %s is %s." msgstr "" -#: src/vars-prs.c:237 +#: src/vars-prs.c:238 #, c-format msgid "Scratch variables (such as %s) are not allowed here." msgstr "" -#: src/vars-prs.c:260 +#: src/vars-prs.c:261 #, c-format msgid "" "%s is not a numeric variable. It will not be included in the variable list." msgstr "" -#: src/vars-prs.c:263 +#: src/vars-prs.c:264 #, c-format msgid "" "%s is not a string variable. It will not be included in the variable list." msgstr "" -#: src/vars-prs.c:267 +#: src/vars-prs.c:268 #, c-format msgid "" "%s and %s are not the same type. All variables in this variable list must " "be of the same type. %s will be omitted from list." msgstr "" -#: src/vars-prs.c:272 +#: src/vars-prs.c:273 #, c-format msgid "Variable %s appears twice in variable list." msgstr "" -#: src/vars-prs.c:352 +#: src/vars-prs.c:353 msgid "incorrect use of TO convention" msgstr "" -#: src/vars-prs.c:399 +#: src/vars-prs.c:400 msgid "Scratch variables not allowed here." msgstr "" -#: src/vars-prs.c:421 +#: src/vars-prs.c:422 msgid "Prefixes don't match in use of TO convention." msgstr "" -#: src/vars-prs.c:426 +#: src/vars-prs.c:427 msgid "Bad bounds in use of TO convention." msgstr "" -#: src/vector.c:66 +#: src/vector.c:67 #, c-format msgid "Vector name %s is given twice." msgstr "" -#: src/vector.c:72 +#: src/vector.c:73 #, c-format msgid "There is already a vector with name %s." msgstr "" -#: src/vector.c:93 +#: src/vector.c:94 msgid "" "A slash must be used to separate each vector specification when using the " "long form. Commands such as VECTOR A,B=Q1 TO Q20 are not supported." msgstr "" -#: src/vector.c:127 +#: src/vector.c:128 msgid "Vectors must have at least one element." msgstr "" -#: src/vector.c:141 +#: src/vector.c:142 #, c-format msgid "%s%d is too long for a variable name." msgstr "" -#: src/vector.c:179 +#: src/vector.c:180 msgid "" "The syntax for this command does not match the expected syntax for either " "the long form or the short form of VECTOR." msgstr "" -#: src/weight.c:52 +#: src/weight.c:53 msgid "The weighting variable must be numeric." msgstr "" -#: src/weight.c:57 +#: src/weight.c:58 msgid "The weighting variable may not be scratch." msgstr "" -#: src/crosstabs.q:241 +#: src/crosstabs.q:261 msgid "" "Missing mode REPORT not allowed in general mode. Assuming MISSING=TABLE." msgstr "" -#: src/crosstabs.q:251 +#: src/crosstabs.q:271 msgid "Write mode ALL not allowed in general mode. Assuming WRITE=CELLS." msgstr "" -#: src/crosstabs.q:312 +#: src/crosstabs.q:332 msgid "expecting BY" msgstr "" -#: src/crosstabs.q:379 +#: src/crosstabs.q:399 msgid "VARIABLES must be specified before TABLES." msgstr "" -#: src/crosstabs.q:416 +#: src/crosstabs.q:436 #, c-format msgid "Maximum value (%ld) less than minimum value (%ld)." msgstr "" -#: src/crosstabs.q:769 +#: src/crosstabs.q:800 msgid "Summary." msgstr "" -#: src/crosstabs.q:771 src/examine.q:784 +#: src/crosstabs.q:802 src/examine.q:837 msgid "Cases" msgstr "" -#: src/crosstabs.q:772 src/examine.q:722 src/frequencies.q:1054 -#: src/frequencies.q:1421 +#: src/crosstabs.q:803 src/examine.q:775 src/frequencies.q:1081 +#: src/frequencies.q:1454 msgid "Valid" msgstr "" -#: src/crosstabs.q:773 src/examine.q:723 src/frequencies.q:1121 -#: src/frequencies.q:1422 +#: src/crosstabs.q:804 src/examine.q:776 src/frequencies.q:1149 +#: src/frequencies.q:1455 msgid "Missing" msgstr "" -#: src/crosstabs.q:774 src/crosstabs.q:977 src/crosstabs.q:1690 -#: src/examine.q:724 src/frequencies.q:1130 src/oneway.q:306 src/oneway.q:483 +#: src/crosstabs.q:805 src/crosstabs.q:1008 src/crosstabs.q:1722 +#: src/examine.q:777 src/frequencies.q:1158 src/oneway.q:307 src/oneway.q:486 msgid "Total" msgstr "" -#: src/crosstabs.q:784 src/examine.q:805 src/frequencies.q:1420 -#: src/oneway.q:393 src/t-test.q:680 src/t-test.q:703 src/t-test.q:828 +#: src/crosstabs.q:815 src/examine.q:858 src/frequencies.q:1453 +#: src/oneway.q:395 src/t-test.q:682 src/t-test.q:705 src/t-test.q:830 #: src/t-test.q:1365 msgid "N" msgstr "" -#: src/crosstabs.q:785 src/examine.q:807 src/frequencies.q:1058 -#: src/frequencies.q:1059 src/frequencies.q:1060 +#: src/crosstabs.q:816 src/examine.q:860 src/frequencies.q:1085 +#: src/frequencies.q:1086 src/frequencies.q:1087 msgid "Percent" msgstr "" -#: src/crosstabs.q:1027 +#: src/crosstabs.q:1058 msgid "count" msgstr "" -#: src/crosstabs.q:1028 +#: src/crosstabs.q:1059 msgid "row %" msgstr "" -#: src/crosstabs.q:1029 +#: src/crosstabs.q:1060 msgid "column %" msgstr "" -#: src/crosstabs.q:1030 +#: src/crosstabs.q:1061 msgid "total %" msgstr "" -#: src/crosstabs.q:1031 +#: src/crosstabs.q:1062 msgid "expected" msgstr "" -#: src/crosstabs.q:1032 +#: src/crosstabs.q:1063 msgid "residual" msgstr "" -#: src/crosstabs.q:1033 +#: src/crosstabs.q:1064 msgid "std. resid." msgstr "" -#: src/crosstabs.q:1034 +#: src/crosstabs.q:1065 msgid "adj. resid." msgstr "" -#: src/crosstabs.q:1067 src/crosstabs.q:1094 src/crosstabs.q:1114 -#: src/crosstabs.q:1135 src/examine.q:448 +#: src/crosstabs.q:1098 src/crosstabs.q:1125 src/crosstabs.q:1145 +#: src/crosstabs.q:1166 src/examine.q:495 msgid "Statistic" msgstr "" -#: src/crosstabs.q:1069 src/oneway.q:276 src/oneway.q:711 src/t-test.q:979 -#: src/t-test.q:1171 src/t-test.q:1263 +#: src/crosstabs.q:1100 src/oneway.q:278 src/oneway.q:707 src/t-test.q:980 +#: src/t-test.q:1172 src/t-test.q:1264 msgid "df" msgstr "" -#: src/crosstabs.q:1071 +#: src/crosstabs.q:1102 msgid "Asymp. Sig. (2-sided)" msgstr "" -#: src/crosstabs.q:1073 +#: src/crosstabs.q:1104 msgid "Exact. Sig. (2-sided)" msgstr "" -#: src/crosstabs.q:1075 +#: src/crosstabs.q:1106 msgid "Exact. Sig. (1-sided)" msgstr "" -#: src/crosstabs.q:1093 src/crosstabs.q:1134 +#: src/crosstabs.q:1124 src/crosstabs.q:1165 msgid "Category" msgstr "" -#: src/crosstabs.q:1096 src/crosstabs.q:1138 +#: src/crosstabs.q:1127 src/crosstabs.q:1169 msgid "Asymp. Std. Error" msgstr "" -#: src/crosstabs.q:1097 src/crosstabs.q:1139 +#: src/crosstabs.q:1128 src/crosstabs.q:1170 msgid "Approx. T" msgstr "" -#: src/crosstabs.q:1098 src/crosstabs.q:1140 +#: src/crosstabs.q:1129 src/crosstabs.q:1171 msgid "Approx. Sig." msgstr "" -#: src/crosstabs.q:1113 +#: src/crosstabs.q:1144 #, c-format msgid " 95%% Confidence Interval" msgstr "" -#: src/crosstabs.q:1116 src/t-test.q:983 src/t-test.q:1168 src/t-test.q:1266 +#: src/crosstabs.q:1147 src/t-test.q:984 src/t-test.q:1169 src/t-test.q:1267 msgid "Lower" msgstr "" -#: src/crosstabs.q:1117 src/t-test.q:984 src/t-test.q:1169 src/t-test.q:1267 +#: src/crosstabs.q:1148 src/t-test.q:985 src/t-test.q:1170 src/t-test.q:1268 msgid "Upper" msgstr "" -#: src/crosstabs.q:1136 +#: src/crosstabs.q:1167 msgid "Type" msgstr "" -#: src/crosstabs.q:1884 +#: src/crosstabs.q:1916 msgid "Pearson Chi-Square" msgstr "" -#: src/crosstabs.q:1885 +#: src/crosstabs.q:1917 msgid "Likelihood Ratio" msgstr "" -#: src/crosstabs.q:1886 +#: src/crosstabs.q:1918 msgid "Fisher's Exact Test" msgstr "" -#: src/crosstabs.q:1887 +#: src/crosstabs.q:1919 msgid "Continuity Correction" msgstr "" -#: src/crosstabs.q:1888 +#: src/crosstabs.q:1920 msgid "Linear-by-Linear Association" msgstr "" -#: src/crosstabs.q:1925 src/crosstabs.q:1995 src/crosstabs.q:2054 +#: src/crosstabs.q:1957 src/crosstabs.q:2027 src/crosstabs.q:2086 msgid "N of Valid Cases" msgstr "" -#: src/crosstabs.q:1941 src/crosstabs.q:2070 +#: src/crosstabs.q:1973 src/crosstabs.q:2102 msgid "Nominal by Nominal" msgstr "" -#: src/crosstabs.q:1942 src/crosstabs.q:2071 +#: src/crosstabs.q:1974 src/crosstabs.q:2103 msgid "Ordinal by Ordinal" msgstr "" -#: src/crosstabs.q:1943 +#: src/crosstabs.q:1975 msgid "Interval by Interval" msgstr "" -#: src/crosstabs.q:1944 +#: src/crosstabs.q:1976 msgid "Measure of Agreement" msgstr "" -#: src/crosstabs.q:1949 +#: src/crosstabs.q:1981 msgid "Phi" msgstr "" -#: src/crosstabs.q:1950 +#: src/crosstabs.q:1982 msgid "Cramer's V" msgstr "" -#: src/crosstabs.q:1951 +#: src/crosstabs.q:1983 msgid "Contingency Coefficient" msgstr "" -#: src/crosstabs.q:1952 +#: src/crosstabs.q:1984 msgid "Kendall's tau-b" msgstr "" -#: src/crosstabs.q:1953 +#: src/crosstabs.q:1985 msgid "Kendall's tau-c" msgstr "" -#: src/crosstabs.q:1954 +#: src/crosstabs.q:1986 msgid "Gamma" msgstr "" -#: src/crosstabs.q:1955 +#: src/crosstabs.q:1987 msgid "Spearman Correlation" msgstr "" -#: src/crosstabs.q:1956 +#: src/crosstabs.q:1988 msgid "Pearson's R" msgstr "" -#: src/crosstabs.q:1957 +#: src/crosstabs.q:1989 msgid "Kappa" msgstr "" -#: src/crosstabs.q:2027 +#: src/crosstabs.q:2059 #, c-format msgid "Odds Ratio for %s (%g / %g)" msgstr "" -#: src/crosstabs.q:2030 +#: src/crosstabs.q:2062 #, c-format msgid "Odds Ratio for %s (%.*s / %.*s)" msgstr "" -#: src/crosstabs.q:2038 +#: src/crosstabs.q:2070 #, c-format msgid "For cohort %s = %g" msgstr "" -#: src/crosstabs.q:2041 +#: src/crosstabs.q:2073 #, c-format msgid "For cohort %s = %.*s" msgstr "" -#: src/crosstabs.q:2072 +#: src/crosstabs.q:2104 msgid "Nominal by Interval" msgstr "" -#: src/crosstabs.q:2077 +#: src/crosstabs.q:2109 msgid "Lambda" msgstr "" -#: src/crosstabs.q:2078 +#: src/crosstabs.q:2110 msgid "Goodman and Kruskal tau" msgstr "" -#: src/crosstabs.q:2079 +#: src/crosstabs.q:2111 msgid "Uncertainty Coefficient" msgstr "" -#: src/crosstabs.q:2080 +#: src/crosstabs.q:2112 msgid "Somers' d" msgstr "" -#: src/crosstabs.q:2081 +#: src/crosstabs.q:2113 msgid "Eta" msgstr "" -#: src/crosstabs.q:2086 +#: src/crosstabs.q:2118 msgid "Symmetric" msgstr "" -#: src/crosstabs.q:2087 src/crosstabs.q:2088 +#: src/crosstabs.q:2119 src/crosstabs.q:2120 #, c-format msgid "%s Dependent" msgstr "" -#: src/examine.q:217 src/examine.q:229 +#: src/examine.q:264 src/examine.q:276 #, c-format msgid "%s and %s are mutually exclusive" msgstr "" -#: src/examine.q:449 src/oneway.q:396 src/oneway.q:709 +#: src/examine.q:496 src/oneway.q:398 src/oneway.q:705 msgid "Std. Error" msgstr "" -#: src/examine.q:563 src/oneway.q:410 +#: src/examine.q:610 src/oneway.q:412 msgid "Descriptives" msgstr "" -#: src/examine.q:602 src/oneway.q:401 +#: src/examine.q:649 src/oneway.q:403 #, c-format msgid "%g%% Confidence Interval for Mean" msgstr "" -#: src/examine.q:608 src/oneway.q:403 +#: src/examine.q:655 src/oneway.q:405 msgid "Lower Bound" msgstr "" -#: src/examine.q:619 src/oneway.q:404 +#: src/examine.q:666 src/oneway.q:406 msgid "Upper Bound" msgstr "" -#: src/examine.q:631 +#: src/examine.q:678 msgid "5% Trimmed Mean" msgstr "" -#: src/examine.q:636 src/frequencies.q:102 +#: src/examine.q:689 src/frequencies.q:112 msgid "Median" msgstr "" -#: src/examine.q:653 src/oneway.q:395 src/t-test.q:682 src/t-test.q:705 -#: src/t-test.q:829 src/t-test.q:1166 +#: src/examine.q:706 src/oneway.q:397 src/t-test.q:684 src/t-test.q:707 +#: src/t-test.q:831 src/t-test.q:1167 msgid "Std. Deviation" msgstr "" -#: src/examine.q:701 +#: src/examine.q:754 msgid "Interquartile Range" msgstr "" -#: src/examine.q:778 +#: src/examine.q:831 msgid "Case Processing Summary" msgstr "" -#: src/examine.q:1103 +#: src/examine.q:1157 msgid "Extreme Values" msgstr "" -#: src/examine.q:1126 +#: src/examine.q:1180 msgid "Case Number" msgstr "" -#: src/examine.q:1252 +#: src/examine.q:1306 msgid "Highest" msgstr "" -#: src/examine.q:1257 +#: src/examine.q:1311 msgid "Lowest" msgstr "" -#: src/file-handle.q:125 +#: src/examine.q:1350 +#, c-format +msgid "Normal Q-Q Plot of %s" +msgstr "" + +#: src/examine.q:1351 src/examine.q:1357 +msgid "Observed Value" +msgstr "" + +#: src/examine.q:1352 +msgid "Expected Normal" +msgstr "" + +#: src/examine.q:1355 +#, c-format +msgid "Detrended Normal Q-Q Plot of %s" +msgstr "" + +#: src/examine.q:1358 +msgid "Dev from Normal" +msgstr "" + +#: src/file-handle.q:122 #, c-format msgid "" "File handle %s already refers to file %s. File handle cannot be redefined " "within a session." msgstr "" -#: src/file-handle.q:147 +#: src/file-handle.q:144 msgid "The FILE HANDLE required subcommand NAME is not present." msgstr "" -#: src/file-handle.q:166 +#: src/file-handle.q:163 msgid "" "Fixed-length records were specified on /RECFORM, but record length was not " "specified on /LRECL. Assuming 1024-character records." msgstr "" -#: src/file-handle.q:173 +#: src/file-handle.q:170 #, c-format msgid "" "Record length (%ld) must be at least one byte. 1-character records will be " "assumed." msgstr "" -#: src/file-handle.q:247 -msgid "" +#: src/file-handle.q:260 +#, c-format +msgid "Can't open %s as a %s because it is already open as a %s" +msgstr "" + +#: src/file-handle.q:264 +#, c-format +msgid "Can't open %s as a %s for %s because it is already open for %s" +msgstr "" + +#: src/file-handle.q:269 +#, c-format +msgid "Can't re-open %s as a %s for %s" msgstr "" -#: src/file-handle.q:262 +#: src/file-handle.q:317 msgid "expecting a file name or handle name" msgstr "" -#: src/frequencies.q:101 +#: src/frequencies.q:111 msgid "S.E. Mean" msgstr "" -#: src/frequencies.q:103 +#: src/frequencies.q:113 msgid "Mode" msgstr "" -#: src/frequencies.q:107 +#: src/frequencies.q:117 msgid "S.E. Kurt" msgstr "" -#: src/frequencies.q:109 +#: src/frequencies.q:119 msgid "S.E. Skew" msgstr "" -#: src/frequencies.q:315 +#: src/frequencies.q:340 msgid "" "At most one of BARCHART, HISTOGRAM, or HBAR should be given. HBAR will be " "assumed. Argument values will be given precedence increasing along the " "order given." msgstr "" -#: src/frequencies.q:398 +#: src/frequencies.q:423 #, c-format msgid "" "MAX must be greater than or equal to MIN, if both are specified. However, " "MIN was specified as %g and MAX as %g. MIN and MAX will be ignored." msgstr "" -#: src/frequencies.q:722 +#: src/frequencies.q:747 msgid "" "Upper limit of integer mode value range must be greater than lower limit." msgstr "" -#: src/frequencies.q:734 +#: src/frequencies.q:760 #, c-format msgid "Variable %s specified multiple times on VARIABLES subcommand." msgstr "" -#: src/frequencies.q:747 +#: src/frequencies.q:766 #, c-format msgid "Integer mode specified, but %s is not a numeric variable." msgstr "" -#: src/frequencies.q:809 +#: src/frequencies.q:832 msgid "`)' expected after GROUPED interval list." msgstr "" -#: src/frequencies.q:822 +#: src/frequencies.q:844 #, c-format msgid "Variables %s specified on GROUPED but not on VARIABLES." msgstr "" -#: src/frequencies.q:825 +#: src/frequencies.q:851 #, c-format msgid "Variables %s specified multiple times on GROUPED subcommand." msgstr "" -#: src/frequencies.q:1055 src/frequencies.q:1146 src/frequencies.q:1147 -#: src/frequencies.q:1177 +#: src/frequencies.q:1082 src/frequencies.q:1174 src/frequencies.q:1175 +#: src/frequencies.q:1207 msgid "Cum" msgstr "" -#: src/frequencies.q:1057 +#: src/frequencies.q:1084 msgid "Frequency" msgstr "" -#: src/frequencies.q:1076 +#: src/frequencies.q:1104 msgid "Value Label" msgstr "" -#: src/frequencies.q:1175 +#: src/frequencies.q:1205 msgid "Freq" msgstr "" -#: src/frequencies.q:1176 src/frequencies.q:1178 +#: src/frequencies.q:1206 src/frequencies.q:1208 msgid "Pct" msgstr "" -#: src/frequencies.q:1394 +#: src/frequencies.q:1427 #, c-format msgid "No valid data for variable %s; statistics not displayed." msgstr "" -#: src/frequencies.q:1433 +#: src/frequencies.q:1465 msgid "Percentiles" msgstr "" -#: src/list.q:148 +#: src/list.q:150 #, c-format msgid "" "The first case (%ld) specified precedes the last case (%ld) specified. The " "values will be swapped." msgstr "" -#: src/list.q:156 +#: src/list.q:158 #, c-format msgid "" "The first case (%ld) to list is less than 1. The value is being reset to 1." msgstr "" -#: src/list.q:162 +#: src/list.q:164 #, c-format msgid "" "The last case (%ld) to list is less than 1. The value is being reset to 1." msgstr "" -#: src/list.q:168 +#: src/list.q:170 #, c-format msgid "The step value %ld is less than 1. The value is being reset to 1." msgstr "" -#: src/list.q:195 +#: src/list.q:197 msgid "`/FORMAT WEIGHT' specified, but weighting is not on." msgstr "" -#: src/list.q:436 +#: src/list.q:438 msgid "Line" msgstr "" -#: src/means.q:101 +#: src/means.q:100 msgid "Missing required subcommand TABLES." msgstr "" -#: src/means.q:135 -msgid "TABLES or CROSSBREAK subcommand may not appear more than once." -msgstr "" - -#: src/means.q:172 -#, c-format -msgid "" -"Variable %s specified on TABLES or CROSSBREAK, but not specified on " -"VARIABLES." -msgstr "" - -#: src/means.q:186 -#, c-format -msgid "LOWEST and HIGHEST may not be used for independent variables (%s)." -msgstr "" - -#: src/means.q:194 -#, c-format -msgid "" -"Independent variables (%s) may not have noninteger endpoints in their ranges." -msgstr "" - -#: src/means.q:227 -msgid "VARIABLES must precede TABLES." -msgstr "" - -#: src/means.q:284 -#, c-format -msgid "Upper value (%g) is less than lower value (%g) on VARIABLES subcommand." +#: src/means.q:134 +msgid "TABLES subcommand may not appear more than once." msgstr "" -#: src/oneway.q:166 +#: src/oneway.q:168 msgid "Number of contrast coefficients must equal the number of groups" msgstr "" -#: src/oneway.q:175 +#: src/oneway.q:177 #, c-format msgid "Coefficients for contrast %d do not total zero" msgstr "" -#: src/oneway.q:240 src/t-test.q:364 src/t-test.q:449 +#: src/oneway.q:242 src/t-test.q:366 src/t-test.q:451 #, c-format msgid "`%s' is not a variable name" msgstr "" -#: src/oneway.q:275 +#: src/oneway.q:277 msgid "Sum of Squares" msgstr "" -#: src/oneway.q:277 +#: src/oneway.q:279 msgid "Mean Square" msgstr "" -#: src/oneway.q:278 src/t-test.q:976 +#: src/oneway.q:280 src/t-test.q:977 msgid "F" msgstr "" -#: src/oneway.q:279 src/oneway.q:549 +#: src/oneway.q:281 src/oneway.q:552 msgid "Significance" msgstr "" -#: src/oneway.q:304 +#: src/oneway.q:305 msgid "Between Groups" msgstr "" -#: src/oneway.q:305 +#: src/oneway.q:306 msgid "Within Groups" msgstr "" -#: src/oneway.q:351 +#: src/oneway.q:353 msgid "ANOVA" msgstr "" -#: src/oneway.q:546 +#: src/oneway.q:549 msgid "Levene Statistic" msgstr "" -#: src/oneway.q:547 +#: src/oneway.q:550 msgid "df1" msgstr "" -#: src/oneway.q:548 +#: src/oneway.q:551 msgid "df2" msgstr "" -#: src/oneway.q:552 +#: src/oneway.q:555 msgid "Test of Homogeneity of Variances" msgstr "" -#: src/oneway.q:628 +#: src/oneway.q:631 msgid "Contrast Coefficients" msgstr "" -#: src/oneway.q:630 src/oneway.q:707 +#: src/oneway.q:633 src/oneway.q:703 msgid "Contrast" msgstr "" -#: src/oneway.q:705 +#: src/oneway.q:701 msgid "Contrast Tests" msgstr "" -#: src/oneway.q:708 +#: src/oneway.q:704 msgid "Value of Contrast" msgstr "" -#: src/oneway.q:710 src/t-test.q:978 src/t-test.q:1170 src/t-test.q:1262 +#: src/oneway.q:706 src/t-test.q:979 src/t-test.q:1171 src/t-test.q:1263 msgid "t" msgstr "" -#: src/oneway.q:712 src/t-test.q:980 src/t-test.q:1172 src/t-test.q:1264 +#: src/oneway.q:708 src/t-test.q:981 src/t-test.q:1173 src/t-test.q:1265 msgid "Sig. (2-tailed)" msgstr "" -#: src/oneway.q:760 +#: src/oneway.q:754 msgid "Assume equal variances" msgstr "" -#: src/oneway.q:764 +#: src/oneway.q:758 msgid "Does not assume equal" msgstr "" @@ -4748,115 +4624,115 @@ msgstr "" msgid "data> " msgstr "" -#: src/t-test.q:266 +#: src/t-test.q:268 msgid "TESTVAL, GROUPS and PAIRS subcommands are mutually exclusive." msgstr "" -#: src/t-test.q:283 +#: src/t-test.q:285 msgid "VARIABLES subcommand is not appropriate with PAIRS" msgstr "" -#: src/t-test.q:320 +#: src/t-test.q:322 msgid "One or more VARIABLES must be specified." msgstr "" -#: src/t-test.q:377 +#: src/t-test.q:379 #, c-format msgid "Long string variable %s is not valid here." msgstr "" -#: src/t-test.q:397 +#: src/t-test.q:399 msgid "" "When applying GROUPS to a string variable, at least one value must be " "specified." msgstr "" -#: src/t-test.q:484 +#: src/t-test.q:486 #, c-format msgid "" "PAIRED was specified but the number of variables preceding WITH (%d) did not " "match the number following (%d)." msgstr "" -#: src/t-test.q:501 +#: src/t-test.q:503 msgid "At least two variables must be specified on PAIRS." msgstr "" -#: src/t-test.q:678 +#: src/t-test.q:680 msgid "One-Sample Statistics" msgstr "" -#: src/t-test.q:683 src/t-test.q:706 src/t-test.q:830 +#: src/t-test.q:685 src/t-test.q:708 src/t-test.q:832 msgid "SE. Mean" msgstr "" -#: src/t-test.q:700 +#: src/t-test.q:702 msgid "Group Statistics" msgstr "" -#: src/t-test.q:824 +#: src/t-test.q:826 msgid "Paired Sample Statistics" msgstr "" -#: src/t-test.q:846 src/t-test.q:1191 src/t-test.q:1382 +#: src/t-test.q:848 src/t-test.q:1192 src/t-test.q:1382 #, c-format msgid "Pair %d" msgstr "" -#: src/t-test.q:964 +#: src/t-test.q:965 msgid "Independent Samples Test" msgstr "" -#: src/t-test.q:972 +#: src/t-test.q:973 msgid "Levene's Test for Equality of Variances" msgstr "" -#: src/t-test.q:974 +#: src/t-test.q:975 msgid "t-test for Equality of Means" msgstr "" -#: src/t-test.q:977 src/t-test.q:1367 +#: src/t-test.q:978 src/t-test.q:1367 msgid "Sig." msgstr "" -#: src/t-test.q:981 src/t-test.q:1265 +#: src/t-test.q:982 src/t-test.q:1266 msgid "Mean Difference" msgstr "" -#: src/t-test.q:982 +#: src/t-test.q:983 msgid "Std. Error Difference" msgstr "" -#: src/t-test.q:987 src/t-test.q:1162 src/t-test.q:1257 +#: src/t-test.q:988 src/t-test.q:1163 src/t-test.q:1258 #, c-format msgid "%g%% Confidence Interval of the Difference" msgstr "" -#: src/t-test.q:1041 +#: src/t-test.q:1043 msgid "Equal variances assumed" msgstr "" -#: src/t-test.q:1094 +#: src/t-test.q:1095 msgid "Equal variances not assumed" msgstr "" -#: src/t-test.q:1152 +#: src/t-test.q:1153 msgid "Paired Samples Test" msgstr "" -#: src/t-test.q:1155 +#: src/t-test.q:1156 msgid "Paired Differences" msgstr "" -#: src/t-test.q:1167 +#: src/t-test.q:1168 msgid "Std. Error Mean" msgstr "" -#: src/t-test.q:1246 +#: src/t-test.q:1247 msgid "One-Sample Test" msgstr "" -#: src/t-test.q:1251 +#: src/t-test.q:1252 #, c-format msgid "Test Value = %f" msgstr "" diff --git a/src/.cvsignore b/src/.cvsignore index 87780b84..3f30425b 100644 --- a/src/.cvsignore +++ b/src/.cvsignore @@ -2,10 +2,12 @@ Makefile Makefile.in correlations.c crosstabs.c +examine.c file-handle.c frequencies.c list.c means.c +oneway.c pspp q2c set.c diff --git a/src/ChangeLog b/src/ChangeLog index 6adfe8d6..1ba99e1a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,229 @@ +Mon Nov 15 01:33:32 2004 Ben Pfaff + + * q2c.c: (dump_header) Don't try to emit #includes at very top of + output file because that will precede #include , which + is bad. + (main) Add needed headers to /* (header) */ code. + +Mon Nov 15 01:21:36 2004 Ben Pfaff + + Instead of making system or portable file readers responsible for + dropping and reordering variables, make them read full cases and + let the caller take care of any changes. + + * get.c: New "case map" structure to handle this. Use for GET, + IMPORT, MATCH FILES. Essentially rewrite the whole file. + + * pfm-read.c: (pfm_read_case) Read into provided case. Signature + changed appropriately. + + * sfm-read.c: (sfm_read_case) Ditto. + +Mon Nov 15 00:47:45 2004 Ben Pfaff + + Decided that case_serialize() and case_unserialize() were too + abstract. Also we need a couple more functions to avoid excessive + copying for data in/out fast paths. + + * case.c: (case_serial_size) Removed. + (case_serialize) Rename case_to_values() and make its argument + explicitly an array of union values. + (case_unserialize) Rename case_from_values() and make its argument + explicitly an array of union values. + (case_data_all) New function. + (case_data_all_rw) New function. + + * casefile.c: (struct casefile) Change buffer from array of + unsigned char to array of union value for better accuracy. + Redefine buffer_used and buffer_size in terms of values, not + bytes. Remove case_size because it is now redundant with + value_cnt. Fix up all references to these members. + +Mon Nov 15 00:45:46 2004 Ben Pfaff + + * barchart.c: (struct subcat) Make `label' member const to silence + GCC warning with -Wwrite-strings. + + * cartesian.c: (struct dataset) Ditto. + + * case.c: Don't re-define NDEBUG if already defined. + Add lots of comments. + + * str.c: Fix includes. + + * crosstabs.q: Fix includes. + + * examine.q: Fix includes. Fix GCC warning about unused + variables. + + * frequencies.q: (stat macro) Removed and replaced where used by + its expansion. + + * list.q: Fix includes. + + * oneway.q: Fix includes. + + * piechart.c: Fix includes. Only define M_PI if not already + defined. + + * sfm-read.c: (bswap) New function. + (bswap_int32) Write in terms of bswap. + (bswap_flt64) Ditto. + + * str.c: (ds_data) Add external definition here, needed because + str.h has only an `extern inline' version. + + * value-labels.c: Fix includes. + +Mon Nov 15 00:40:55 2004 Ben Pfaff + + Instead of providing a system or portable file writer with a raw + case in the format needed for output, provide it with a regular + case. The writer takes care of any needed translation. + + * aggregate.c: Adopt new scheme for AGGREGATE. + (struct agr_proc) sfm_agr_case member removed. + (write_case_to_sfm) Removed because the new interface is easier to + use. + + * get.c: Adopt new scheme for SAVE, XSAVE, EXPORT. + + * pfm-write.c: Implement new scheme. + + * sfm-write.c: Ditto. + +Mon Nov 15 00:32:24 2004 Ben Pfaff + + Instead of treating `struct file_handle' as a class to subclass + into data files, system files, and portable files, instead use it + as a helper that coordinates access. Now it is opaque, too. + + This means that most references to a struct file_handle are now + changed into references to one of struct dfm_reader, struct + dfm_writer, struct sfm_reader, struct sfm_writer, struct + pfm_reader, or struct pfm_writer, according to what's being read + or written. + + Most related changes are only worth summarizing briefly. + + * dictionary.c: (dict_clear) Destroy aux data in deleted + variables. + (dict_clear_aux) New function. + (dict_create_var) Initialize aux, aux_dtor. + (dict_delete_var) Destroy aux data in deleted variable. + + * file-handle.h: (struct fh_ext_class) Removed. + (struct file_handle) Removed. + (fh_init_files) Removed. + + * file-handle.q: Changed references to a handle's `private' member + to direct references. + (struct private_file_handle) Renamed file_handle. + Add next, open_cnt, type, open_mode, aux members. + (struct file_handle_list) Removed. + (extern var inline_file) Removed. + (static var file_handles) Changed from file_handle_list * to + file_handle *. + (create_file_handle) Initialize new members. + (fh_close_handle) Removed. + (mode_name) New function. + (fh_open) New function. + (fh_close) New function. + (fh_parse_file_handle) Renamed fh_parse(). + + * glob.c: (init_glob) Remove fh_init_files() call. + + * aggregate.c: use sfm_writer. + (create_sysfile) Removed because the new interface is simpler. + + * apply-dict.c: Use sfm_reader. + + * data-list.c: Use dfm_reader. + + * file-type.c: Use dfm_reader. + + * get.c: Use sfm_reader, sfm_writer, pfm_reader, pfm_writer. + + * inpt-pgm.c: Use dfm_reader. + + * print.c: Use dfm_writer. + + * sysfile-info: Use sfm_reader. + + * dfm-read.c: Adopt new file handle infrastructure. + + * dfm-write.c: Ditto. + + * pfm-read.c: Ditto. + + * pfm-write.c: Ditto. + + * sfm-read.c: Ditto. + + * sfm-write.c: Ditto. + +Mon Nov 15 00:31:44 2004 Ben Pfaff + + Break dictionary functions into separate header file. + + * dictionary.h: New file. + + * var.h: Moved dict_*() functions to dictionary.h. + +Mon Nov 15 00:30:33 2004 Ben Pfaff + + Get rid of procedure-specific union in struct variable, using + instead a void * pointer and a destructor function. + + Most related changes are only worth brief summaries. + + * crosstabs.q: Fix includes. Use new struct var_range in lieu of + old p.crs member in struct variable. + + * frequencies.q: Fix includes. Use new struct var_freqs in lieu + of old p.frq member in struct variable. + + * histogram.c: (draw_histogram) Takes new freq_tab arg because + it's no longer possible to grab this from var->p.frq. + + * piechart.c: (draw_piechart) Ditto. + + * group.c: (group_proc_get) New function. + + * levene.c: Use group_proc_get() in lieu of old p.grp_data member + in struct variable. + + * oneway.q: Ditto. + + * t-test.q: Ditto. + + * main.c: (execute_command) Clear aux data in default_dict after + each command. (It's debatable whether this should be done.) + + * matrix-data.c: Use new struct mxd_var in lieu of old p.mxd + member in struct variable. + + * means.q: Get rid of integer mode, which is not included in + recent SPSS and was the only code that wanted per-variable private + data. + + * var.h: (struct crosstab_proc) Removed. + (struct frequencies_proc) Removed. + (struct list_proc) Removed. + (struct get_proc) Removed. + (struct means_proc) Removed. + (struct matrix_data_proc) Removed. + (struct match_files_proc) Removed. + (lots of enums) Removed. + (struct variable) Removed members `p', `get'. Add member + `aux_dtor'. + + * vars-atr.c: (var_attach_aux) New function. + (var_detach_aux) New function. + (var_clear_aux) New function. + (var_dtor_free) New function. + (discard_variables) Use NULL instead of inline_file. + Fri Nov 12 10:07:11 WST 2004 John Darrington * value-labs.c Fixed the implmentation of value_to_string, so diff --git a/src/Makefile.am b/src/Makefile.am index 0320792f..ec5ce0ae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,7 +54,8 @@ case.c case.h \ casefile.c casefile.h cmdline.c cmdline.h command.c command.def \ command.h compute.c copyleft.c copyleft.h count.c data-in.c data-in.h \ data-list.c data-list.h data-out.c date.c debug-print.h descript.c \ -devind.c devind.h dfm.c dfm.h dictionary.c do-if.c do-ifP.h error.c \ +devind.c devind.h dfm-read.c dfm-read.h dfm-write.c dfm-write.h \ +dictionary.c dictionary.h do-if.c do-ifP.h error.c \ error.h expr-evl.c expr-opt.c expr-prs.c expr.h exprP.h expr.def \ factor_stats.c factor_stats.h file-handle.h \ file-type.c filename.c filename.h flip.c font.h format.c format.def \ @@ -63,10 +64,12 @@ groff-font.c group.c group.h group_proc.h \ hash.c hash.h html.c htmlP.h include.c inpt-pgm.c lexer.c \ lexer.h levene.c levene.h log.h loop.c magic.c magic.h main.c main.h \ matrix-data.c mis-val.c misc.c misc.h modify-vars.c \ -moments.c moments.h numeric.c output.c output.h pfm-read.c pfm-write.c \ -pfm.h pool.c pool.h postscript.c print.c random.c random.h recode.c \ +moments.c moments.h numeric.c output.c output.h pfm-read.c pfm-read.h \ +pfm-write.c pfm-write.h \ +pool.c pool.h postscript.c print.c random.c random.h recode.c \ rename-vars.c repeat.c repeat.h sample.c sel-if.c settings.h \ -sfm-read.c sfm-write.c sfm.h sfmP.h som.c som.h sort.c sort.h \ +sfm-read.c sfm-read.h sfm-write.c sfm-write.h sfmP.h som.c som.h \ +sort.c sort.h \ split-file.c str.c str.h subclist.c subclist.h \ sysfile-info.c tab.c tab.h temporary.c stat.h \ title.c val.h val-labs.c value-labels.c value-labels.h \ diff --git a/src/aggregate.c b/src/aggregate.c index ec601dbf..ffd29166 100644 --- a/src/aggregate.c +++ b/src/aggregate.c @@ -24,6 +24,7 @@ #include "case.h" #include "casefile.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "file-handle.h" #include "lexer.h" @@ -31,7 +32,7 @@ #include "moments.h" #include "pool.h" #include "settings.h" -#include "sfm.h" +#include "sfm-write.h" #include "sort.h" #include "str.h" #include "var.h" @@ -116,7 +117,7 @@ enum missing_treatment struct agr_proc { /* We have either an output file or a sink. */ - struct file_handle *out_file; /* Output file, or null if none. */ + struct sfm_writer *writer; /* Output file, or null if none. */ struct case_sink *sink; /* Sink, or null if none. */ /* Break variables. */ @@ -130,7 +131,6 @@ struct agr_proc struct dictionary *dict; /* Aggregate dictionary. */ int case_cnt; /* Counts aggregated cases. */ struct ccase agr_case; /* Aggregate case for output. */ - flt64 *sfm_agr_case; /* Aggregate case in SFM format. */ }; static void initialize_aggregate_info (struct agr_proc *); @@ -142,13 +142,11 @@ static int aggregate_single_case (struct agr_proc *agr, const struct ccase *input, struct ccase *output); static void dump_aggregate_info (struct agr_proc *agr, struct ccase *output); -static int create_sysfile (struct agr_proc *); /* Aggregating to the active file. */ static int agr_to_active_file (struct ccase *, void *aux); /* Aggregating to a system file. */ -static void write_case_to_sfm (struct agr_proc *agr); static int presorted_agr_to_sysfile (struct ccase *, void *aux); /* Parsing. */ @@ -158,11 +156,12 @@ int cmd_aggregate (void) { struct agr_proc agr; + struct file_handle *out_file = NULL; /* Have we seen these subcommands? */ unsigned seen = 0; - agr.out_file = NULL; + agr.writer = NULL; agr.sink = NULL; agr.missing = ITEMWISE; agr.sort = NULL; @@ -186,18 +185,16 @@ cmd_aggregate (void) if (seen & 1) { msg (SE, _("%s subcommand given multiple times."),"OUTFILE"); - goto lossage; + goto error; } seen |= 1; lex_match ('='); - if (lex_match ('*')) - agr.out_file = NULL; - else + if (!lex_match ('*')) { - agr.out_file = fh_parse_file_handle (); - if (agr.out_file == NULL) - goto lossage; + out_file = fh_parse (); + if (out_file == NULL) + goto error; } } else if (lex_match_id ("MISSING")) @@ -206,7 +203,7 @@ cmd_aggregate (void) if (!lex_match_id ("COLUMNWISE")) { lex_error (_("while expecting COLUMNWISE")); - goto lossage; + goto error; } agr.missing = COLUMNWISE; } @@ -221,7 +218,7 @@ cmd_aggregate (void) if (seen & 8) { msg (SE, _("%s subcommand given multiple times."),"BREAK"); - goto lossage; + goto error; } seen |= 8; @@ -229,7 +226,7 @@ cmd_aggregate (void) agr.sort = sort_parse_criteria (default_dict, &agr.break_vars, &agr.break_var_cnt); if (agr.sort == NULL) - goto lossage; + goto error; for (i = 0; i < agr.break_var_cnt; i++) { @@ -247,7 +244,7 @@ cmd_aggregate (void) /* Read in the aggregate functions. */ if (!parse_aggregate_functions (&agr)) - goto lossage; + goto error; /* Delete documents. */ if (!(seen & 2)) @@ -262,7 +259,7 @@ cmd_aggregate (void) initialize_aggregate_info (&agr); /* Output to active file or external file? */ - if (agr.out_file == NULL) + if (out_file == NULL) { /* The active file will be replaced by the aggregated data, so TEMPORARY is moot. */ @@ -289,9 +286,10 @@ cmd_aggregate (void) } else { - if (!create_sysfile (&agr)) - goto lossage; - + agr.writer = sfm_open_writer (out_file, agr.dict, get_scompression ()); + if (agr.writer == NULL) + goto error; + if (agr.sort != NULL && (seen & 4) == 0) { /* Sorting is needed. */ @@ -301,12 +299,12 @@ cmd_aggregate (void) dst = sort_active_file_to_casefile (agr.sort); if (dst == NULL) - goto lossage; + goto error; reader = casefile_get_destructive_reader (dst); while (casereader_read_xfer (reader, &c)) { if (aggregate_single_case (&agr, &c, &agr.agr_case)) - write_case_to_sfm (&agr); + sfm_write_case (agr.writer, &agr.agr_case); case_destroy (&c); } casereader_destroy (reader); @@ -321,36 +319,18 @@ cmd_aggregate (void) if (agr.case_cnt > 0) { dump_aggregate_info (&agr, &agr.agr_case); - write_case_to_sfm (&agr); + sfm_write_case (agr.writer, &agr.agr_case); } - fh_close_handle (agr.out_file); } agr_destroy (&agr); return CMD_SUCCESS; -lossage: +error: agr_destroy (&agr); return CMD_FAILURE; } -/* Create a system file for use in aggregation to an external - file. */ -static int -create_sysfile (struct agr_proc *agr) -{ - struct sfm_write_info w; - w.h = agr->out_file; - w.dict = agr->dict; - w.compress = get_scompression(); - if (!sfm_write_dictionary (&w)) - return 0; - - agr->sfm_agr_case = xmalloc (sizeof *agr->sfm_agr_case * w.case_size); - - return 1; -} - /* Parse all the aggregate functions. */ static int parse_aggregate_functions (struct agr_proc *agr) @@ -390,8 +370,9 @@ parse_aggregate_functions (struct agr_proc *agr) { int n_dest_prev = n_dest; - if (!parse_DATA_LIST_vars (&dest, &n_dest, PV_APPEND | PV_SINGLE | PV_NO_SCRATCH)) - goto lossage; + if (!parse_DATA_LIST_vars (&dest, &n_dest, + PV_APPEND | PV_SINGLE | PV_NO_SCRATCH)) + goto error; /* Assign empty labels. */ { @@ -414,7 +395,7 @@ parse_aggregate_functions (struct agr_proc *agr) if (token != T_ID) { lex_error (_("expecting aggregation function")); - goto lossage; + goto error; } include_missing = 0; @@ -430,7 +411,7 @@ parse_aggregate_functions (struct agr_proc *agr) if (NULL == function->name) { msg (SE, _("Unknown aggregation function %s."), tokid); - goto lossage; + goto error; } func_index = function - agr_func_tab; lex_get (); @@ -445,7 +426,7 @@ parse_aggregate_functions (struct agr_proc *agr) else { lex_error (_("expecting `('")); - goto lossage; + goto error; } } else { /* Parse list of source variables. */ @@ -458,7 +439,7 @@ parse_aggregate_functions (struct agr_proc *agr) pv_opts |= PV_SAME_TYPE; if (!parse_variables (default_dict, &src, &n_src, pv_opts)) - goto lossage; + goto error; } /* Parse function arguments, for those functions that @@ -480,7 +461,7 @@ parse_aggregate_functions (struct agr_proc *agr) type = NUMERIC; } else { msg (SE, _("Missing argument %d to %s."), i + 1, function->name); - goto lossage; + goto error; } lex_get (); @@ -490,7 +471,7 @@ parse_aggregate_functions (struct agr_proc *agr) msg (SE, _("Arguments to %s must be of same type as " "source variables."), function->name); - goto lossage; + goto error; } } @@ -498,7 +479,7 @@ parse_aggregate_functions (struct agr_proc *agr) if (!lex_match(')')) { lex_error (_("expecting `)'")); - goto lossage; + goto error; } /* Now check that the number of source variables match the @@ -512,7 +493,7 @@ parse_aggregate_functions (struct agr_proc *agr) msg (SE, _("Number of source variables (%d) does not match " "number of target variables (%d)."), n_src, n_dest); - goto lossage; + goto error; } } @@ -584,7 +565,7 @@ parse_aggregate_functions (struct agr_proc *agr) "variables."), dest[i]); free (dest[i]); - goto lossage; + goto error; } free (dest[i]); @@ -636,7 +617,7 @@ parse_aggregate_functions (struct agr_proc *agr) } continue; - lossage: + error: for (i = 0; i < n_dest; i++) { free (dest[i]); @@ -664,11 +645,11 @@ agr_destroy (struct agr_proc *agr) { struct agr_var *iter, *next; - if (agr->dict != NULL) - dict_destroy (agr->dict); + sfm_close_writer (agr->writer); if (agr->sort != NULL) sort_destroy_criteria (agr->sort); free (agr->break_vars); + free (agr->prev_break); for (iter = agr->agr_vars; iter; iter = next) { next = iter->next; @@ -687,7 +668,8 @@ agr_destroy (struct agr_proc *agr) moments1_destroy (iter->moments); free (iter); } - free (agr->prev_break); + if (agr->dict != NULL) + dict_destroy (agr->dict); case_destroy (&agr->agr_case); } @@ -1143,38 +1125,6 @@ agr_to_active_file (struct ccase *c, void *agr_) return 1; } -/* Writes AGR->agr_case to AGR->out_file. */ -static void -write_case_to_sfm (struct agr_proc *agr) -{ - flt64 *p; - int i; - - p = agr->sfm_agr_case; - for (i = 0; i < dict_get_var_cnt (agr->dict); i++) - { - struct variable *v = dict_get_var (agr->dict, i); - - if (v->type == NUMERIC) - { - double src = case_num (&agr->agr_case, v->fv); - if (src == SYSMIS) - *p++ = -FLT64_MAX; - else - *p++ = src; - } - else - { - memcpy (p, case_str (&agr->agr_case, v->fv), v->width); - memset (&((char *) p)[v->width], ' ', - REM_RND_UP (v->width, sizeof (flt64))); - p += DIV_RND_UP (v->width, sizeof (flt64)); - } - } - - sfm_write_case (agr->out_file, agr->sfm_agr_case, p - agr->sfm_agr_case); -} - /* Aggregate the current case and output it if we passed a breakpoint. */ static int @@ -1183,7 +1133,7 @@ presorted_agr_to_sysfile (struct ccase *c, void *agr_) struct agr_proc *agr = agr_; if (aggregate_single_case (agr, c, &agr->agr_case)) - write_case_to_sfm (agr); + sfm_write_case (agr->writer, &agr->agr_case); return 1; } diff --git a/src/alloc.c b/src/alloc.c index 1aaba305..a0c2fbac 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -19,9 +19,9 @@ #include #include "alloc.h" -#include "error.h" #include #include +#include "error.h" #include "str.h" /* Public functions. */ diff --git a/src/apply-dict.c b/src/apply-dict.c index 9f6867cc..4cc8c103 100644 --- a/src/apply-dict.c +++ b/src/apply-dict.c @@ -20,11 +20,12 @@ #include #include #include "command.h" +#include "dictionary.h" #include "error.h" #include "file-handle.h" #include "hash.h" #include "lexer.h" -#include "sfm.h" +#include "sfm-read.h" #include "str.h" #include "value-labels.h" #include "var.h" @@ -36,6 +37,7 @@ int cmd_apply_dictionary (void) { struct file_handle *handle; + struct sfm_reader *reader; struct dictionary *dict; int n_matched = 0; @@ -44,13 +46,14 @@ cmd_apply_dictionary (void) lex_match_id ("FROM"); lex_match ('='); - handle = fh_parse_file_handle (); + handle = fh_parse (); if (!handle) return CMD_FAILURE; - dict = sfm_read_dictionary (handle, NULL); + reader = sfm_open_reader (handle, &dict, NULL); if (dict == NULL) return CMD_FAILURE; + sfm_close_reader (reader); for (i = 0; i < dict_get_var_cnt (dict); i++) { @@ -170,7 +173,7 @@ cmd_apply_dictionary (void) dict_set_weight (default_dict, new_weight); } - sfm_maybe_close (handle); + sfm_close_reader (reader); return lex_end_of_command (); } diff --git a/src/autorecode.c b/src/autorecode.c index 5bf12bc0..a28b13bd 100644 --- a/src/autorecode.c +++ b/src/autorecode.c @@ -23,6 +23,7 @@ #include "alloc.h" #include "case.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "hash.h" #include "lexer.h" diff --git a/src/barchart.c b/src/barchart.c index e47a541a..26fdfb5e 100644 --- a/src/barchart.c +++ b/src/barchart.c @@ -89,7 +89,7 @@ static const char subcat_name[]="Gender"; struct subcat { const double *data; - char *label; + const char *label; }; static const struct subcat sub_catagory[SUB_CATAGORIES] = diff --git a/src/cartesian.c b/src/cartesian.c index a2396abc..34e1a3dd 100644 --- a/src/cartesian.c +++ b/src/cartesian.c @@ -27,7 +27,7 @@ struct dataset { int n_data; - char *label; + const char *label; }; diff --git a/src/case.c b/src/case.c index 6c427df5..21fb0bdb 100644 --- a/src/case.c +++ b/src/case.c @@ -28,10 +28,17 @@ #ifdef GLOBAL_DEBUGGING #undef NDEBUG #else +#ifndef NDEBUG #define NDEBUG #endif +#endif #include +/* Changes C not to share data with any other case. + C must be a case with a reference count greater than 1. + There should be no reason for external code to call this + function explicitly. It will be called automatically when + needed. */ void case_unshare (struct ccase *c) { @@ -49,6 +56,8 @@ case_unshare (struct ccase *c) sizeof *cd->values * cd->value_cnt); } +/* Returns the number of bytes needed by a case with VALUE_CNT + values. */ static inline size_t case_size (size_t value_cnt) { @@ -57,6 +66,7 @@ case_size (size_t value_cnt) } #ifdef GLOBAL_DEBUGGING +/* Initializes C as a null case. */ void case_nullify (struct ccase *c) { @@ -66,6 +76,7 @@ case_nullify (struct ccase *c) #endif /* GLOBAL_DEBUGGING */ #ifdef GLOBAL_DEBUGGING +/* Returns true iff C is a null case. */ int case_is_null (const struct ccase *c) { @@ -73,6 +84,9 @@ case_is_null (const struct ccase *c) } #endif /* GLOBAL_DEBUGGING */ +/* Initializes C as a new case that can store VALUE_CNT values. + The values have indeterminate contents until explicitly + written. */ void case_create (struct ccase *c, size_t value_cnt) { @@ -81,6 +95,7 @@ case_create (struct ccase *c, size_t value_cnt) } #ifdef GLOBAL_DEBUGGING +/* Initializes CLONE as a copy of ORIG. */ void case_clone (struct ccase *clone, const struct ccase *orig) { @@ -100,6 +115,8 @@ case_clone (struct ccase *clone, const struct ccase *orig) #endif /* GLOBAL_DEBUGGING */ #ifdef GLOBAL_DEBUGGING +/* Replaces DST by SRC and nullifies SRC. + DST and SRC must be initialized cases at entry. */ void case_move (struct ccase *dst, struct ccase *src) { @@ -116,6 +133,7 @@ case_move (struct ccase *dst, struct ccase *src) #endif /* GLOBAL_DEBUGGING */ #ifdef GLOBAL_DEBUGGING +/* Destroys case C. */ void case_destroy (struct ccase *c) { @@ -134,6 +152,9 @@ case_destroy (struct ccase *c) } #endif /* GLOBAL_DEBUGGING */ +/* Attempts to create C as a new case that holds VALUE_CNT + values. Returns nonzero if successful, zero if memory + allocation failed. */ int case_try_create (struct ccase *c, size_t value_cnt) { @@ -156,6 +177,9 @@ case_try_create (struct ccase *c, size_t value_cnt) } } +/* Tries to initialize CLONE as a copy of ORIG. + Returns nonzero if successful, zero if memory allocation + failed. */ int case_try_clone (struct ccase *clone, const struct ccase *orig) { @@ -164,6 +188,8 @@ case_try_clone (struct ccase *clone, const struct ccase *orig) } #ifdef GLOBAL_DEBUGGING +/* Copies VALUE_CNT values from SRC (starting at SRC_IDX) to DST + (starting at DST_IDX). */ void case_copy (struct ccase *dst, size_t dst_idx, const struct ccase *src, size_t src_idx, @@ -191,50 +217,51 @@ case_copy (struct ccase *dst, size_t dst_idx, #endif /* GLOBAL_DEBUGGING */ #ifdef GLOBAL_DEBUGGING -size_t -case_serial_size (size_t value_cnt) -{ - return value_cnt * sizeof (union value); -} -#endif /* GLOBAL_DEBUGGING */ - -#ifdef GLOBAL_DEBUGGING +/* Copies case C to OUTPUT. + OUTPUT_SIZE is the number of `union values' in OUTPUT, + which must match the number of `union values' in C. */ void -case_serialize (const struct ccase *c, void *output, +case_to_values (const struct ccase *c, union value *output, size_t output_size UNUSED) { assert (c != NULL); assert (c->this == c); assert (c->case_data != NULL); assert (c->case_data->ref_cnt > 0); - assert (output_size == case_serial_size (c->case_data->value_cnt)); + assert (output_size == c->case_data->value_cnt); assert (output != NULL || output_size == 0); memcpy (output, c->case_data->values, - case_serial_size (c->case_data->value_cnt)); + c->case_data->value_cnt * sizeof *output); } #endif /* GLOBAL_DEBUGGING */ #ifdef GLOBAL_DEBUGGING +/* Copies INPUT into case C. + INPUT_SIZE is the number of `union values' in INPUT, + which must match the number of `union values' in C. */ void -case_unserialize (struct ccase *c, const void *input, +case_from_values (struct ccase *c, const union value *input, size_t input_size UNUSED) { assert (c != NULL); assert (c->this == c); assert (c->case_data != NULL); assert (c->case_data->ref_cnt > 0); - assert (input_size == case_serial_size (c->case_data->value_cnt)); + assert (input_size == c->case_data->value_cnt); assert (input != NULL || input_size == 0); if (c->case_data->ref_cnt > 1) case_unshare (c); memcpy (c->case_data->values, input, - case_serial_size (c->case_data->value_cnt)); + c->case_data->value_cnt * sizeof *input); } #endif /* GLOBAL_DEBUGGING */ #ifdef GLOBAL_DEBUGGING +/* Returns a pointer to the `union value' used for the + element of C numbered IDX. + The caller must not modify the returned data. */ const union value * case_data (const struct ccase *c, size_t idx) { @@ -249,6 +276,8 @@ case_data (const struct ccase *c, size_t idx) #endif /* GLOBAL_DEBUGGING */ #ifdef GLOBAL_DEBUGGING +/* Returns the numeric value of the `union value' in C numbered + IDX. */ double case_num (const struct ccase *c, size_t idx) { @@ -263,6 +292,10 @@ case_num (const struct ccase *c, size_t idx) #endif /* GLOBAL_DEBUGGING */ #ifdef GLOBAL_DEBUGGING +/* Returns the string value of the `union value' in C numbered + IDX. + (Note that the value is not null-terminated.) + The caller must not modify the return value. */ const char * case_str (const struct ccase *c, size_t idx) { @@ -277,6 +310,9 @@ case_str (const struct ccase *c, size_t idx) #endif /* GLOBAL_DEBUGGING */ #ifdef GLOBAL_DEBUGGING +/* Returns a pointer to the `union value' used for the + element of C numbered IDX. + The caller is allowed to modify the returned data. */ union value * case_data_rw (struct ccase *c, size_t idx) { @@ -291,3 +327,37 @@ case_data_rw (struct ccase *c, size_t idx) return &c->case_data->values[idx]; } #endif /* GLOBAL_DEBUGGING */ + +/* Returns a pointer to the array of `union value's used for C. + The caller must *not* modify the returned data. + + NOTE: This function breaks the case abstraction. It should + *not* be used often. Prefer the other case functions. */ +const union value * +case_data_all (const struct ccase *c) +{ + assert (c != NULL); + assert (c->this == c); + assert (c->case_data != NULL); + assert (c->case_data->ref_cnt > 0); + + return c->case_data->values; +} + +/* Returns a pointer to the array of `union value's used for C. + The caller is allowed to modify the returned data. + + NOTE: This function breaks the case abstraction. It should + *not* be used often. Prefer the other case functions. */ +union value * +case_data_all_rw (struct ccase *c) +{ + assert (c != NULL); + assert (c->this == c); + assert (c->case_data != NULL); + assert (c->case_data->ref_cnt > 0); + + if (c->case_data->ref_cnt > 1) + case_unshare (c); + return c->case_data->values; +} diff --git a/src/case.h b/src/case.h index 9e8b6e4f..7312aa94 100644 --- a/src/case.h +++ b/src/case.h @@ -28,18 +28,18 @@ case_move() or case_clone() instead of copying. */ struct ccase { - struct case_data *case_data; + struct case_data *case_data; /* Actual data. */ #if GLOBAL_DEBUGGING - struct ccase *this; + struct ccase *this; /* Detects unauthorized move/copy. */ #endif }; /* Invisible to user code. */ struct case_data { - size_t value_cnt; - unsigned ref_cnt; - union value values[1]; + size_t value_cnt; /* Number of values. */ + unsigned ref_cnt; /* Reference count. */ + union value values[1]; /* Values. */ }; #ifdef GLOBAL_DEBUGGING @@ -63,9 +63,9 @@ CASE_INLINE void case_copy (struct ccase *dst, size_t dst_idx, const struct ccase *src, size_t src_idx, size_t cnt); -CASE_INLINE size_t case_serial_size (size_t value_cnt); -CASE_INLINE void case_serialize (const struct ccase *, void *, size_t); -CASE_INLINE void case_unserialize (struct ccase *, const void *, size_t); +CASE_INLINE void case_to_values (const struct ccase *, union value *, size_t); +CASE_INLINE void case_from_values (struct ccase *, + const union value *, size_t); CASE_INLINE const union value *case_data (const struct ccase *, size_t idx); CASE_INLINE double case_num (const struct ccase *, size_t idx); @@ -73,6 +73,9 @@ CASE_INLINE const char *case_str (const struct ccase *, size_t idx); CASE_INLINE union value *case_data_rw (struct ccase *, size_t idx); +const union value *case_data_all (const struct ccase *); +union value *case_data_all_rw (struct ccase *); + void case_unshare (struct ccase *); #ifndef GLOBAL_DEBUGGING @@ -126,28 +129,22 @@ case_copy (struct ccase *dst, size_t dst_idx, sizeof *dst->case_data->values * value_cnt); } -static inline size_t -case_serial_size (size_t value_cnt) -{ - return value_cnt * sizeof (union value); -} - static inline void -case_serialize (const struct ccase *c, void *output, +case_to_values (const struct ccase *c, union value *output, size_t output_size UNUSED) { memcpy (output, c->case_data->values, - case_serial_size (c->case_data->value_cnt)); + c->case_data->value_cnt * sizeof *output); } static inline void -case_unserialize (struct ccase *c, const void *input, +case_from_values (struct ccase *c, const union value *input, size_t input_size UNUSED) { if (c->case_data->ref_cnt > 1) case_unshare (c); memcpy (c->case_data->values, input, - case_serial_size (c->case_data->value_cnt)); + c->case_data->value_cnt * sizeof *input); } static inline const union value * diff --git a/src/casefile.c b/src/casefile.c index 2ff3a574..03828b71 100644 --- a/src/casefile.c +++ b/src/casefile.c @@ -37,7 +37,7 @@ #include #endif -#define IO_BUF_SIZE 8192 +#define IO_BUF_SIZE (8192 / sizeof (union value)) /* A casefile is a sequentially accessible array of immutable cases. It may be stored in memory or on disk as workspace @@ -57,7 +57,6 @@ struct casefile /* Basic data. */ struct casefile *next, *prev; /* Next, prev in global list. */ size_t value_cnt; /* Case size in `union value's. */ - size_t case_size; /* Case size in bytes. */ size_t case_acct_size; /* Case size for accounting. */ unsigned long case_cnt; /* Number of cases stored. */ enum { MEMORY, DISK } storage; /* Where cases are stored. */ @@ -71,9 +70,9 @@ struct casefile /* Disk storage. */ int fd; /* File descriptor, -1 if none. */ char *filename; /* Filename. */ - unsigned char *buffer; /* I/O buffer, NULL if none. */ - size_t buffer_used; /* Number of bytes used in buffer. */ - size_t buffer_size; /* Buffer size in bytes. */ + union value *buffer; /* I/O buffer, NULL if none. */ + size_t buffer_used; /* Number of values used in buffer. */ + size_t buffer_size; /* Buffer size in values. */ }; /* For reading out the cases in a casefile. */ @@ -86,8 +85,8 @@ struct casereader /* Disk storage. */ int fd; /* File descriptor. */ - unsigned char *buffer; /* I/O buffer. */ - size_t buffer_pos; /* Byte offset of buffer position. */ + union value *buffer; /* I/O buffer. */ + size_t buffer_pos; /* Offset of buffer position. */ struct ccase c; /* Current case. */ }; @@ -107,8 +106,8 @@ static void fill_buffer (struct casereader *reader); static int safe_open (const char *filename, int flags); static int safe_close (int fd); -static int full_read (int fd, char *buffer, size_t size); -static int full_write (int fd, const char *buffer, size_t size); +static int full_read (int fd, void *buffer, size_t size); +static int full_write (int fd, const void *buffer, size_t size); /* Creates and returns a casefile to store cases of VALUE_CNT `union value's each. */ @@ -122,8 +121,7 @@ casefile_create (size_t value_cnt) cf->next->prev = cf; casefiles = cf; cf->value_cnt = value_cnt; - cf->case_size = case_serial_size (value_cnt); - cf->case_acct_size = cf->case_size + 4 * sizeof (void *); + cf->case_acct_size = (cf->value_cnt + 4) * sizeof *cf->buffer; cf->case_cnt = 0; cf->storage = MEMORY; cf->mode = WRITE; @@ -133,9 +131,9 @@ casefile_create (size_t value_cnt) cf->fd = -1; cf->filename = NULL; cf->buffer = NULL; - cf->buffer_size = ROUND_UP (cf->case_size, IO_BUF_SIZE); - if (cf->case_size > 0 && cf->buffer_size % cf->case_size > 512) - cf->buffer_size = cf->case_size; + cf->buffer_size = ROUND_UP (cf->value_cnt, IO_BUF_SIZE); + if (cf->value_cnt > 0 && cf->buffer_size % cf->value_cnt > 64) + cf->buffer_size = cf->value_cnt; cf->buffer_used = 0; register_atexit (); return cf; @@ -312,9 +310,9 @@ casefile_append_xfer (struct casefile *cf, struct ccase *c) static void write_case_to_disk (struct casefile *cf, const struct ccase *c) { - case_serialize (c, cf->buffer + cf->buffer_used, cf->case_size); - cf->buffer_used += cf->case_size; - if (cf->buffer_used + cf->case_size > cf->buffer_size) + case_to_values (c, cf->buffer + cf->buffer_used, cf->value_cnt); + cf->buffer_used += cf->value_cnt; + if (cf->buffer_used + cf->value_cnt > cf->buffer_size) flush_buffer (cf); } @@ -325,7 +323,8 @@ flush_buffer (struct casefile *cf) { if (cf->buffer_used > 0) { - if (!full_write (cf->fd, cf->buffer, cf->buffer_size)) + if (!full_write (cf->fd, cf->buffer, + cf->buffer_size * sizeof *cf->buffer)) msg (FE, _("Error writing temporary file: %s."), strerror (errno)); cf->buffer_used = 0; @@ -371,7 +370,7 @@ casefile_to_disk (const struct casefile *cf_) struct casereader *reader; assert (cf != NULL); - + if (cf->storage == MEMORY) { size_t idx, block_cnt; @@ -383,8 +382,8 @@ casefile_to_disk (const struct casefile *cf_) cf->storage = DISK; if (!make_temp_file (&cf->fd, &cf->filename)) err_failure (); - cf->buffer = xmalloc (cf->buffer_size); - memset (cf->buffer, 0, cf->buffer_size); + cf->buffer = xmalloc (cf->buffer_size * sizeof *cf->buffer); + memset (cf->buffer, 0, cf->buffer_size * sizeof *cf->buffer); case_bytes -= cf->case_cnt * cf->case_acct_size; for (idx = 0; idx < cf->case_cnt; idx++) @@ -482,7 +481,6 @@ static void reader_open_file (struct casereader *reader) { struct casefile *cf = reader->cf; - size_t buffer_case_cnt; off_t file_ofs; if (reader->case_idx >= cf->case_cnt) @@ -508,17 +506,17 @@ reader_open_file (struct casereader *reader) } else { - reader->buffer = xmalloc (cf->buffer_size); - memset (reader->buffer, 0, cf->buffer_size); + reader->buffer = xmalloc (cf->buffer_size * sizeof *cf->buffer); + memset (reader->buffer, 0, cf->buffer_size * sizeof *cf->buffer); } - if (cf->case_size != 0) + if (cf->value_cnt != 0) { - buffer_case_cnt = cf->buffer_size / cf->case_size; - file_ofs = ((off_t) reader->case_idx - / buffer_case_cnt * cf->buffer_size); + size_t buffer_case_cnt = cf->buffer_size / cf->value_cnt; + file_ofs = ((off_t) reader->case_idx / buffer_case_cnt + * cf->buffer_size * sizeof *cf->buffer); reader->buffer_pos = (reader->case_idx % buffer_case_cnt - * cf->case_size); + * cf->value_cnt); } else file_ofs = 0; @@ -526,7 +524,7 @@ reader_open_file (struct casereader *reader) msg (FE, _("%s: Seeking temporary file: %s."), cf->filename, strerror (errno)); - if (cf->case_cnt > 0 && cf->case_size > 0) + if (cf->case_cnt > 0 && cf->value_cnt > 0) fill_buffer (reader); case_create (&reader->c, cf->value_cnt); @@ -536,11 +534,12 @@ reader_open_file (struct casereader *reader) static void fill_buffer (struct casereader *reader) { - int retval = full_read (reader->fd, reader->buffer, reader->cf->buffer_size); + int retval = full_read (reader->fd, reader->buffer, + reader->cf->buffer_size * sizeof *reader->buffer); if (retval < 0) msg (FE, _("%s: Reading temporary file: %s."), reader->cf->filename, strerror (errno)); - else if (retval != reader->cf->buffer_size) + else if (retval != reader->cf->buffer_size * sizeof *reader->buffer) msg (FE, _("%s: Temporary file ended unexpectedly."), reader->cf->filename); } @@ -575,15 +574,15 @@ casereader_read (struct casereader *reader, struct ccase *c) } else { - if (reader->buffer_pos + reader->cf->case_size > reader->cf->buffer_size) + if (reader->buffer_pos + reader->cf->value_cnt > reader->cf->buffer_size) { fill_buffer (reader); reader->buffer_pos = 0; } - case_unserialize (&reader->c, reader->buffer + reader->buffer_pos, - reader->cf->case_size); - reader->buffer_pos += reader->cf->case_size; + case_from_values (&reader->c, reader->buffer + reader->buffer_pos, + reader->cf->value_cnt); + reader->buffer_pos += reader->cf->value_cnt; reader->case_idx++; case_clone (c, &reader->c); @@ -679,8 +678,9 @@ static int safe_close (int fd) /* Calls read(), passing FD, BUFFER, and SIZE, repeating as necessary to deal with interrupted calls. */ static int -full_read (int fd, char *buffer, size_t size) +full_read (int fd, void *buffer_, size_t size) { + char *buffer = buffer_; size_t bytes_read = 0; while (bytes_read < size) @@ -700,8 +700,9 @@ full_read (int fd, char *buffer, size_t size) /* Calls write(), passing FD, BUFFER, and SIZE, repeating as necessary to deal with interrupted calls. */ static int -full_write (int fd, const char *buffer, size_t size) +full_write (int fd, const void *buffer_, size_t size) { + const char *buffer = buffer_; size_t bytes_written = 0; while (bytes_written < size) @@ -830,8 +831,8 @@ test_casefile (int pattern, size_t value_cnt, size_t case_cnt) for (i = j = 0; i < case_cnt; i++) { read_and_verify_random_case (cf, r1, i); - if (rng_get_int (rng) % pattern == 0) - read_and_verify_random_case (cf, r2, j++); + if (rng_get_int (rng) % pattern == 0) + read_and_verify_random_case (cf, r2, j++); if (i == case_cnt / 2) casefile_to_disk (cf); } diff --git a/src/chart.c b/src/chart.c index c550edf1..34527e41 100644 --- a/src/chart.c +++ b/src/chart.c @@ -17,7 +17,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - +#include #include #include #include @@ -28,6 +28,7 @@ #include #include "chart.h" +#include "str.h" const char *data_colour[] = { diff --git a/src/chart.h b/src/chart.h index aaf7abc8..d4a8dd74 100644 --- a/src/chart.h +++ b/src/chart.h @@ -115,6 +115,7 @@ struct normal_curve void draw_histogram(struct chart *ch, const struct variable *v, + const struct freq_tab *frq_tab, const char *title, struct normal_curve *norm, int show_normal); @@ -123,7 +124,8 @@ void draw_histogram(struct chart *ch, double chart_rounded_tick(double tick); -void draw_piechart(struct chart *ch, const struct variable *v); +void draw_piechart(struct chart *ch, const struct variable *v, + const struct freq_tab *); void draw_scatterplot(struct chart *ch); diff --git a/src/command.c b/src/command.c index 5ff4f0de..5e4e1a5f 100644 --- a/src/command.c +++ b/src/command.c @@ -25,6 +25,7 @@ #include #include #include "alloc.h" +#include "dictionary.h" #include "error.h" #include "getline.h" #include "lexer.h" diff --git a/src/compute.c b/src/compute.c index f30d7b1f..6556e8be 100644 --- a/src/compute.c +++ b/src/compute.c @@ -23,6 +23,7 @@ #include "alloc.h" #include "case.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "expr.h" #include "lexer.h" diff --git a/src/correlations.q b/src/correlations.q index 4c9f74b7..4bde9a06 100644 --- a/src/correlations.q +++ b/src/correlations.q @@ -20,6 +20,7 @@ #include #include #include "alloc.h" +#include "dictionary.h" #include "file-handle.h" #include "command.h" #include "lexer.h" @@ -133,12 +134,13 @@ cor_custom_matrix (struct cmd_correlations *cmd UNUSED) return 0; if (lex_match ('*')) - matrix_file = inline_file; - else - matrix_file = fh_parse_file_handle (); - - if (!matrix_file) - return 0; + matrix_file = NULL; + else + { + matrix_file = fh_parse (); + if (matrix_file == NULL) + return 0; + } if (!lex_force_match (')')) return 0; diff --git a/src/count.c b/src/count.c index a6e70616..35021f09 100644 --- a/src/count.c +++ b/src/count.c @@ -23,6 +23,7 @@ #include "alloc.h" #include "case.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "lexer.h" #include "str.h" diff --git a/src/crosstabs.q b/src/crosstabs.q index 0a1e891f..9c17ed02 100644 --- a/src/crosstabs.q +++ b/src/crosstabs.q @@ -38,6 +38,7 @@ #include "algorithm.h" #include "alloc.h" #include "case.h" +#include "dictionary.h" #include "hash.h" #include "pool.h" #include "command.h" @@ -46,11 +47,14 @@ #include "magic.h" #include "misc.h" #include "output.h" +#include "str.h" #include "tab.h" #include "value-labels.h" #include "var.h" #include "vfm.h" +/* (headers) */ + #include "debug-print.h" /* (specification) @@ -105,6 +109,22 @@ struct crosstab larger indices first. */ }; +/* Integer mode variable info. */ +struct var_range + { + int min; /* Minimum value. */ + int max; /* Maximum value + 1. */ + int count; /* max - min. */ + }; + +static inline struct var_range * +get_var_range (struct variable *v) +{ + assert (v != NULL); + assert (v->aux != NULL); + return v->aux; +} + /* Indexes into crosstab.v. */ enum { @@ -426,11 +446,13 @@ crs_custom_variables (struct cmd_crosstabs *cmd UNUSED) } lex_get (); - for (i = orig_nv; i < variables_cnt; i++) - { - variables[i]->p.crs.min = min; - variables[i]->p.crs.max = max + 1.; - variables[i]->p.crs.count = max - min + 1; + for (i = orig_nv; i < variables_cnt; i++) + { + struct var_range *vr = xmalloc (sizeof *vr); + vr->min = min; + vr->max = max + 1.; + vr->count = max - min + 1; + var_attach_aux (variables[i], vr, var_dtor_free); } if (token == '/') @@ -475,14 +497,14 @@ precalc (void *aux UNUSED) x->ofs = n_sorted_tab; - for (j = 2; j < x->nvar; j++) - count *= x->vars[j - 2]->p.crs.count; - + for (j = 2; j < x->nvar; j++) + count *= get_var_range (x->vars[j - 2])->count; + sorted_tab = xrealloc (sorted_tab, sizeof *sorted_tab * (n_sorted_tab + count)); v = local_alloc (sizeof *v * x->nvar); - for (j = 2; j < x->nvar; j++) - v[j] = x->vars[j]->p.crs.min; + for (j = 2; j < x->nvar; j++) + v[j] = get_var_range (x->vars[j])->min; for (j = 0; j < count; j++) { struct table_entry *te; @@ -493,8 +515,9 @@ precalc (void *aux UNUSED) te->table = i; { - const int mat_size = (x->vars[0]->p.crs.count - * x->vars[1]->p.crs.count); + int row_cnt = get_var_range (x->vars[0])->count; + int col_cnt = get_var_range (x->vars[1])->count; + const int mat_size = row_cnt * col_cnt; int m; te->u.data = xmalloc (sizeof *te->u.data * mat_size); @@ -504,11 +527,14 @@ precalc (void *aux UNUSED) for (k = 2; k < x->nvar; k++) te->values[k].f = v[k]; - for (k = 2; k < x->nvar; k++) - if (++v[k] >= x->vars[k]->p.crs.max) - v[k] = x->vars[k]->p.crs.min; - else - break; + for (k = 2; k < x->nvar; k++) + { + struct var_range *vr = get_var_range (x->vars[k]); + if (++v[k] >= vr->max) + v[k] = vr->min; + else + break; + } } local_free (v); } @@ -615,10 +641,11 @@ calc_integer (struct ccase *c, void *aux UNUSED) for (i = 0; i < x->nvar; i++) { struct variable *const v = x->vars[i]; + struct var_range *vr = get_var_range (v); double value = case_num (c, v->fv); /* Note that the first test also rules out SYSMIS. */ - if ((value < v->p.crs.min || value >= v->p.crs.max) + if ((value < vr->min || value >= vr->max) || (cmd.miss == CRS_TABLE && is_num_user_missing (value, v))) { x->missing += weight; @@ -627,15 +654,19 @@ calc_integer (struct ccase *c, void *aux UNUSED) if (i > 1) { - ofs += fact * ((int) value - v->p.crs.min); - fact *= v->p.crs.count; + ofs += fact * ((int) value - vr->min); + fact *= vr->count; } } { - const int row = case_num (c, x->vars[ROW_VAR]->fv) - x->vars[ROW_VAR]->p.crs.min; - const int col = case_num (c, x->vars[COL_VAR]->fv) - x->vars[COL_VAR]->p.crs.min; - const int col_dim = x->vars[COL_VAR]->p.crs.count; + struct variable *row_var = x->vars[ROW_VAR]; + const int row = case_num (c, row_var->fv) - get_var_range (row_var)->min; + + struct variable *col_var = x->vars[COL_VAR]; + const int col = case_num (c, col_var->fv) - get_var_range (col_var)->min; + + const int col_dim = get_var_range (col_var)->count; sorted_tab[ofs]->u.data[col + row * col_dim] += weight; } @@ -804,8 +835,8 @@ make_summary_table (void) else { const struct crosstab *const x = xtab[(*pb)->table]; - const int n_cols = x->vars[COL_VAR]->p.crs.count; - const int n_rows = x->vars[ROW_VAR]->p.crs.count; + const int n_cols = get_var_range (x->vars[COL_VAR])->count; + const int n_rows = get_var_range (x->vars[ROW_VAR])->count; const int count = n_cols * n_rows; for (valid = 0.; pb < pe; pb++) @@ -1569,7 +1600,7 @@ compare_value (const void *a_, const void *b_, void *width_) /* Given an array of ENTRY_CNT table_entry structures starting at ENTRIES, creates a sorted list of the values that the variable - with index VAR_INDEX takes on. The values are returned as a + with index VAR_IDX takes on. The values are returned as a malloc()'darray stored in *VALUES, with the number of values stored in *VALUE_CNT. */ @@ -1577,9 +1608,11 @@ static void enum_var_values (struct table_entry **entries, int entry_cnt, int var_idx, union value **values, int *value_cnt) { + struct variable *v = xtab[(*entries)->table]->vars[var_idx]; + if (mode == GENERAL) { - int width = xtab[(*entries)->table]->vars[var_idx]->width; + int width = v->width; int i; *values = xmalloc (sizeof **values * entry_cnt); @@ -1590,15 +1623,14 @@ enum_var_values (struct table_entry **entries, int entry_cnt, int var_idx, } else { - struct crosstab_proc *crs - = &xtab[(*entries)->table]->vars[var_idx]->p.crs; + struct var_range *vr = get_var_range (v); int i; assert (mode == INTEGER); - *values = xmalloc (sizeof **values * crs->count); - for (i = 0; i < crs->count; i++) - (*values)[i].f = i + crs->min; - *value_cnt = crs->count; + *values = xmalloc (sizeof **values * vr->count); + for (i = 0; i < vr->count; i++) + (*values)[i].f = i + vr->min; + *value_cnt = vr->count; } } diff --git a/src/data-list.c b/src/data-list.c index a3e6c67a..7328f65e 100644 --- a/src/data-list.c +++ b/src/data-list.c @@ -29,7 +29,8 @@ #include "command.h" #include "data-in.h" #include "debug-print.h" -#include "dfm.h" +#include "dfm-read.h" +#include "dictionary.h" #include "error.h" #include "file-handle.h" #include "format.h" @@ -82,12 +83,12 @@ struct data_list_pgm struct trns_header h; struct dls_var_spec *first, *last; /* Variable parsing specifications. */ - struct file_handle *handle; /* Input file, never NULL. */ + struct dfm_reader *reader; /* Data file reader. */ int type; /* A DLS_* constant. */ struct variable *end; /* Variable specified on END subcommand. */ int eof; /* End of file encountered. */ - int nrec; /* Number of records. */ + int rec_cnt; /* Number of records. */ size_t case_size; /* Case size in bytes. */ char *delims; /* Delimiters if any; not null-terminated. */ size_t delim_cnt; /* Number of delimiter, or 0 for spaces. */ @@ -95,9 +96,10 @@ struct data_list_pgm 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 *specs, - const struct file_handle *handle, int nrec); -static void dump_free_table (const struct data_list_pgm *); +static void dump_fixed_table (const struct dls_var_spec *, + const struct file_handle *, int rec_cnt); +static void dump_free_table (const struct data_list_pgm *, + const struct file_handle *); static void destroy_dls_var_spec (struct dls_var_spec *); static trns_free_func data_list_trns_free; static trns_proc_func data_list_trns_proc; @@ -108,21 +110,19 @@ static trns_proc_func data_list_trns_proc; int cmd_data_list (void) { - /* DATA LIST program under construction. */ - struct data_list_pgm *dls; - - /* 0=print no table, 1=print table. (TABLE subcommand.) */ - int table = -1; + struct data_list_pgm *dls; /* DATA LIST program under construction. */ + int table = -1; /* Print table if nonzero, -1=undecided. */ + struct file_handle *fh = NULL; /* File handle of source, NULL=inline file. */ if (!case_source_is_complex (vfm_source)) discard_variables (); dls = xmalloc (sizeof *dls); - dls->handle = default_handle; + dls->reader = NULL; dls->type = -1; dls->end = NULL; dls->eof = 0; - dls->nrec = 0; + dls->rec_cnt = 0; dls->delims = NULL; dls->delim_cnt = 0; dls->first = dls->last = NULL; @@ -132,11 +132,11 @@ cmd_data_list (void) if (lex_match_id ("FILE")) { lex_match ('='); - dls->handle = fh_parse_file_handle (); - if (!dls->handle) + fh = fh_parse (); + if (fh == NULL) goto error; if (case_source_is_class (vfm_source, &file_type_source_class) - && dls->handle != default_handle) + && fh != default_handle) { msg (SE, _("DATA LIST may not use a different file from " "that specified on its surrounding FILE TYPE.")); @@ -149,7 +149,7 @@ cmd_data_list (void) lex_match ('('); if (!lex_force_int ()) goto error; - dls->nrec = lex_integer (); + dls->rec_cnt = lex_integer (); lex_get (); lex_match (')'); } @@ -231,7 +231,7 @@ cmd_data_list (void) } dls->case_size = dict_get_case_size (default_dict); - default_handle = dls->handle; + default_handle = fh; if (dls->type == -1) dls->type = DLS_FIXED; @@ -249,17 +249,18 @@ cmd_data_list (void) if (!parse_fixed (dls)) goto error; if (table) - dump_fixed_table (dls->first, dls->handle, dls->nrec); + dump_fixed_table (dls->first, fh, dls->rec_cnt); } else { if (!parse_free (&dls->first, &dls->last)) goto error; if (table) - dump_free_table (dls); + dump_free_table (dls, fh); } - if (!dfm_open_for_reading (dls->handle)) + dls->reader = dfm_open_reader (fh); + if (dls->reader == NULL) goto error; if (vfm_source != NULL) @@ -393,14 +394,14 @@ parse_fixed (struct data_list_pgm *dls) msg (SE, _("At least one variable must be specified.")); return 0; } - if (dls->nrec && dls->last->rec > dls->nrec) + if (dls->rec_cnt && dls->last->rec > dls->rec_cnt) { msg (SE, _("Variables are specified on records that " "should not exist according to RECORDS subcommand.")); return 0; } - else if (!dls->nrec) - dls->nrec = dls->last->rec; + else if (!dls->rec_cnt) + dls->rec_cnt = dls->last->rec; if (token != '.') { lex_error (_("expecting end of command")); @@ -778,12 +779,10 @@ fixed_parse_fortran (struct fixed_parsing_state *fx, ending column. */ static void dump_fixed_table (const struct dls_var_spec *specs, - const struct file_handle *handle, int nrec) + const struct file_handle *fh, int rec_cnt) { const struct dls_var_spec *spec; struct tab_table *t; - char *buf; - const char *filename; int i; for (i = 0, spec = specs; spec; spec = spec->next) @@ -809,21 +808,16 @@ dump_fixed_table (const struct dls_var_spec *specs, fmt_to_string (&spec->input)); } - filename = handle_get_filename (handle); - if (filename == NULL) - filename = ""; - buf = local_alloc (strlen (filename) + INT_DIGITS + 80); - sprintf (buf, (handle != inline_file - ? ngettext ("Reading %d record from file %s.", - "Reading %d records from file %s.", nrec) - : ngettext ("Reading %d record from the command file.", - "Reading %d records from the command file.", - nrec)), - nrec, filename); - - tab_title (t, 0, buf); + if (fh != NULL) + tab_title (t, 1, ngettext ("Reading %d record from file %s.", + "Reading %d records from file %s.", rec_cnt), + rec_cnt, handle_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_submit (t); - local_free (buf); } /* Free-format parsing. */ @@ -907,7 +901,8 @@ parse_free (struct dls_var_spec **first, struct dls_var_spec **last) /* Displays a table giving information on free-format variable parsing on DATA LIST. */ static void -dump_free_table (const struct data_list_pgm *dls) +dump_free_table (const struct data_list_pgm *dls, + const struct file_handle *fh) { struct tab_table *t; int i; @@ -936,19 +931,12 @@ dump_free_table (const struct data_list_pgm *dls) tab_text (t, 1, i, TAB_LEFT | TAT_FIX, fmt_to_string (&spec->input)); } } - - { - const char *filename; - - filename = handle_get_filename (dls->handle); - if (filename == NULL) - filename = ""; - tab_title (t, 1, - (dls->handle != inline_file - ? _("Reading free-form data from file %s.") - : _("Reading free-form data from the command file.")), - filename); - } + + if (fh != NULL) + tab_title (t, 1, _("Reading free-form data from file %s."), + handle_get_filename (fh)); + else + tab_title (t, 1, _("Reading free-form data from the command file.")); tab_submit (t); } @@ -972,11 +960,11 @@ cut_field (const struct data_list_pgm *dls, struct len_string *field, char *cp; size_t column_start; - if (dfm_eof (dls->handle)) + if (dfm_eof (dls->reader)) return 0; if (dls->delim_cnt == 0) - dfm_expand_tabs (dls->handle); - dfm_get_record (dls->handle, &line); + dfm_expand_tabs (dls->reader); + dfm_get_record (dls->reader, &line); cp = ls_c_str (&line); if (dls->delim_cnt == 0) @@ -1020,7 +1008,7 @@ cut_field (const struct data_list_pgm *dls, struct len_string *field, { if (cp >= ls_end (&line)) { - int column = dfm_column_start (dls->handle); + int column = dfm_column_start (dls->reader); /* A blank line or a line that ends in \t has a trailing blank field. */ if (column == 1 || (column > 1 && cp[-1] == '\t')) @@ -1030,7 +1018,7 @@ cut_field (const struct data_list_pgm *dls, struct len_string *field, *end_blank = 1; field->string = ls_end (&line); field->length = 0; - dfm_forward_record (dls->handle); + dfm_forward_record (dls->reader); return column; } else @@ -1054,10 +1042,10 @@ cut_field (const struct data_list_pgm *dls, struct len_string *field, } } - dfm_forward_columns (dls->handle, field->string - line.string); - column_start = dfm_column_start (dls->handle); + dfm_forward_columns (dls->reader, field->string - line.string); + column_start = dfm_column_start (dls->reader); - dfm_forward_columns (dls->handle, cp - field->string); + dfm_forward_columns (dls->reader, cp - field->string); return column_start; } @@ -1099,21 +1087,21 @@ read_from_data_list_fixed (const struct data_list_pgm *dls, struct dls_var_spec *var_spec = dls->first; int i; - if (dfm_eof (dls->handle)) + if (dfm_eof (dls->reader)) return -2; - for (i = 1; i <= dls->nrec; i++) + for (i = 1; i <= dls->rec_cnt; i++) { struct len_string line; - if (dfm_eof (dls->handle)) + if (dfm_eof (dls->reader)) { /* Note that this can't occur on the first record. */ msg (SW, _("Partial case of %d of %d records discarded."), - i - 1, dls->nrec); + i - 1, dls->rec_cnt); return -2; } - dfm_expand_tabs (dls->handle); - dfm_get_record (dls->handle, &line); + dfm_expand_tabs (dls->reader); + dfm_get_record (dls->reader, &line); for (; var_spec && i == var_spec->rec; var_spec = var_spec->next) { @@ -1129,7 +1117,7 @@ read_from_data_list_fixed (const struct data_list_pgm *dls, data_in (&di); } - dfm_forward_record (dls->handle); + dfm_forward_record (dls->reader); } return -1; @@ -1157,9 +1145,9 @@ read_from_data_list_free (const struct data_list_pgm *dls, if (column != 0) break; - if (!dfm_eof (dls->handle)) - dfm_forward_record (dls->handle); - if (dfm_eof (dls->handle)) + if (!dfm_eof (dls->reader)) + dfm_forward_record (dls->reader); + if (dfm_eof (dls->reader)) { if (var_spec != dls->first) msg (SW, _("Partial case discarded. The first variable " @@ -1193,7 +1181,7 @@ read_from_data_list_list (const struct data_list_pgm *dls, struct dls_var_spec *var_spec; int end_blank = 0; - if (dfm_eof (dls->handle)) + if (dfm_eof (dls->reader)) return -2; for (var_spec = dls->first; var_spec; var_spec = var_spec->next) @@ -1234,7 +1222,7 @@ read_from_data_list_list (const struct data_list_pgm *dls, } } - dfm_forward_record (dls->handle); + dfm_forward_record (dls->reader); return -1; } @@ -1259,7 +1247,7 @@ data_list_trns_free (struct trns_header *pgm) struct data_list_pgm *dls = (struct data_list_pgm *) pgm; free (dls->delims); destroy_dls_var_spec (dls->first); - fh_close_handle (dls->handle); + dfm_close_reader (dls->reader); free (pgm); } @@ -1272,7 +1260,7 @@ data_list_trns_proc (struct trns_header *t, struct ccase *c, data_list_read_func *read_func; int retval; - dfm_push (dls->handle); + dfm_push (dls->reader); read_func = get_data_list_read_func (dls); retval = read_func (dls, c); @@ -1286,7 +1274,7 @@ data_list_trns_proc (struct trns_header *t, struct ccase *c, { msg (SE, _("Attempt to read past end of file.")); err_failure (); - dfm_pop (dls->handle); + dfm_pop (dls->reader); return -2; } @@ -1308,7 +1296,7 @@ data_list_trns_proc (struct trns_header *t, struct ccase *c, case_data_rw (c, dls->end->fv)->f = 0.0; } - dfm_pop (dls->handle); + dfm_pop (dls->reader); return retval; } @@ -1323,13 +1311,11 @@ data_list_source_read (struct case_source *source, struct data_list_pgm *dls = source->aux; data_list_read_func *read_func = get_data_list_read_func (dls); - dfm_push (dls->handle); + dfm_push (dls->reader); while (read_func (dls, c) != -2) if (!write_case (wc_data)) break; - dfm_pop (dls->handle); - - fh_close_handle (dls->handle); + dfm_pop (dls->reader); } /* Destroys the source's internal data. */ @@ -1361,7 +1347,7 @@ struct repeating_data_trns { struct trns_header h; struct dls_var_spec *first, *last; /* Variable parsing specifications. */ - struct file_handle *handle; /* Input file, never NULL. */ + struct dfm_reader *reader; /* Input file, never NULL. */ struct rpd_num_or_var starts_beg; /* STARTS=, before the dash. */ struct rpd_num_or_var starts_end; /* STARTS=, after the dash. */ @@ -1392,17 +1378,14 @@ int cmd_repeating_data (void) { struct repeating_data_trns *rpd; - - /* 0=print no table, 1=print table. (TABLE subcommand.) */ - int table = 1; - - /* Bits are set when a particular subcommand has been seen. */ - unsigned seen = 0; + int table = 1; /* Print table? */ + unsigned seen = 0; /* Mark subcommands as already seen. */ + struct file_handle *const fh = default_handle; assert (case_source_is_complex (vfm_source)); rpd = xmalloc (sizeof *rpd); - rpd->handle = default_handle; + rpd->reader = dfm_open_reader (default_handle); rpd->first = rpd->last = NULL; rpd->starts_beg.num = 0; rpd->starts_beg.var = NULL; @@ -1418,11 +1401,12 @@ cmd_repeating_data (void) { if (lex_match_id ("FILE")) { + struct file_handle *file; lex_match ('='); - rpd->handle = fh_parse_file_handle (); - if (!rpd->handle) + file = fh_parse (); + if (file == NULL) goto error; - if (rpd->handle != default_handle) + if (file != fh) { msg (SE, _("REPEATING DATA must use the same file as its " "corresponding DATA LIST or FILE TYPE.")); @@ -1613,9 +1597,9 @@ cmd_repeating_data (void) /* Calculate starts_end, cont_end if necessary. */ if (rpd->starts_end.num == 0 && rpd->starts_end.var == NULL) - rpd->starts_end.num = handle_get_record_width (rpd->handle); + rpd->starts_end.num = handle_get_record_width (fh); if (rpd->cont_end.num == 0 && rpd->starts_end.var == NULL) - rpd->cont_end.num = handle_get_record_width (rpd->handle); + rpd->cont_end.num = handle_get_record_width (fh); /* Calculate length if possible. */ if ((seen & 4) == 0) @@ -1635,7 +1619,7 @@ cmd_repeating_data (void) goto error; if (table) - dump_fixed_table (rpd->first, rpd->handle, rpd->last->rec); + dump_fixed_table (rpd->first, fh, rpd->last->rec); { struct repeating_data_trns *new_trns; @@ -1939,15 +1923,15 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, int skip_first_record = 0; - dfm_push (t->handle); + dfm_push (t->reader); /* Read the current record. */ - dfm_reread_record (t->handle, 1); - dfm_expand_tabs (t->handle); - if (dfm_eof (t->handle)) + dfm_reread_record (t->reader, 1); + dfm_expand_tabs (t->reader); + if (dfm_eof (t->reader)) return -2; - dfm_get_record (t->handle, &line); - dfm_forward_record (t->handle); + dfm_get_record (t->reader, &line); + dfm_forward_record (t->reader); /* Calculate occurs, length. */ occurs_left = occurs = realize_value (&t->occurs, c); @@ -2037,7 +2021,7 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, assert (occurs_left >= 0); /* Read in another record. */ - if (dfm_eof (t->handle)) + if (dfm_eof (t->reader)) { tmsg (SE, RPD_ERR, _("Unexpected end of file with %d repetitions " @@ -2045,9 +2029,9 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, occurs_left, occurs); return -2; } - dfm_expand_tabs (t->handle); - dfm_get_record (t->handle, &line); - dfm_forward_record (t->handle); + dfm_expand_tabs (t->reader); + dfm_get_record (t->reader, &line); + dfm_forward_record (t->reader); /* Parse this record. */ info.trns = t; @@ -2065,7 +2049,7 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, occurs_left -= code; } - dfm_pop (t->handle); + dfm_pop (t->reader); /* FIXME: This is a kluge until we've implemented multiplexing of transformations. */ @@ -2079,7 +2063,7 @@ repeating_data_trns_free (struct trns_header *rpd_) struct repeating_data_trns *rpd = (struct repeating_data_trns *) rpd_; destroy_dls_var_spec (rpd->first); - fh_close_handle (rpd->handle); + dfm_close_reader (rpd->reader); free (rpd->id_value); } diff --git a/src/descript.c b/src/descript.c index e05c9292..e84733ac 100644 --- a/src/descript.c +++ b/src/descript.c @@ -29,6 +29,7 @@ #include "case.h" #include "casefile.h" #include "command.h" +#include "dictionary.h" #include "lexer.h" #include "error.h" #include "magic.h" diff --git a/src/dfm-read.c b/src/dfm-read.c new file mode 100644 index 00000000..e12864ac --- /dev/null +++ b/src/dfm-read.c @@ -0,0 +1,479 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-2004 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include +#include "dfm-read.h" +#include +#include +#include +#include +#include "alloc.h" +#include "command.h" +#include "error.h" +#include "file-handle.h" +#include "filename.h" +#include "getline.h" +#include "lexer.h" +#include "str.h" +#include "vfm.h" + +#include "debug-print.h" + +/* Flags for DFM readers. */ +enum dfm_reader_flags + { + DFM_EOF = 001, /* At end-of-file? */ + DFM_ADVANCE = 002, /* Read next line on dfm_get_record() call? */ + DFM_SAW_BEGIN_DATA = 004, /* For inline_file only, whether we've + already read a BEGIN DATA line. */ + DFM_TABS_EXPANDED = 010, /* Tabs have been expanded. */ + }; + +/* Data file reader. */ +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_*. */ + }; + +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(). */ +void +dfm_close_reader (struct dfm_reader *r) +{ + int still_open; + + 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. */ + while ((r->flags & DFM_EOF) == 0) + read_record (r); + inline_file = NULL; + } + } + if (still_open) + return; + + if (r->fh != NULL && r->file.file) + { + fn_close_ext (&r->file); + free (r->file.filename); + r->file.filename = NULL; + } + 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 + "inline file", that is, data included inline in the command + file between BEGIN FILE and END FILE. Returns nonzero only if + successful. */ +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; + } + + r = xmalloc (sizeof *r); + r->fh = fh; + if (fh != NULL) + { + r->where.filename = handle_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) + { + r->file.filename = xstrdup (handle_get_filename (r->fh)); + r->file.mode = "rb"; + r->file.file = NULL; + r->file.sequence_no = NULL; + r->file.param = 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."), + handle_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; + + return r; +} + +static int +read_inline_record (struct dfm_reader *r) +{ + if ((r->flags & DFM_SAW_BEGIN_DATA) == 0) + { + char *s; + + r->flags |= DFM_SAW_BEGIN_DATA; + + /* FIXME: WTF can't this just be done with tokens? + Is this really a special case? */ + do + { + char *cp; + + if (!getl_read_line ()) + { + msg (SE, _("BEGIN DATA expected.")); + err_failure (); + } + + /* Skip leading whitespace, separate out first + word, so that S points to a single word reduced + to lowercase. */ + s = ds_c_str (&getl_buf); + while (isspace ((unsigned char) *s)) + s++; + for (cp = s; isalpha ((unsigned char) *cp); cp++) + *cp = tolower ((unsigned char) (*cp)); + ds_truncate (&getl_buf, cp - s); + } + while (*s == '\0'); + + if (!lex_id_match_len ("begin", 5, s, strcspn (s, " \t\r\v\n"))) + { + msg (SE, _("BEGIN DATA expected.")); + lex_preprocess_line (); + return 0; + } + getl_prompt = GETL_PRPT_DATA; + } + + if (!getl_read_line ()) + { + msg (SE, _("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.")); + 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; + } + + ds_replace (&r->line, ds_c_str (&getl_buf)); + return 1; +} + +static int +read_file_record (struct dfm_reader *r) +{ + assert (r->fh != NULL); + if (handle_get_mode (r->fh) == MODE_TEXT) + { + ds_clear (&r->line); + if (!ds_gets (&r->line, r->file.file)) + { + if (ferror (r->file.file)) + { + msg (ME, _("Error reading file %s: %s."), + handle_get_name (r->fh), strerror (errno)); + err_cond_fail (); + } + return 0; + } + } + else if (handle_get_mode (r->fh) == MODE_BINARY) + { + size_t record_width = handle_get_record_width (r->fh); + size_t amt; + + if (ds_length (&r->line) < record_width) + ds_rpad (&r->line, record_width, 0); + + amt = fread (ds_c_str (&r->line), 1, record_width, + r->file.file); + if (record_width != amt) + { + if (ferror (r->file.file)) + msg (ME, _("Error reading file %s: %s."), + handle_get_name (r->fh), strerror (errno)); + else if (amt != 0) + msg (ME, _("%s: Partial record at end of file."), + handle_get_name (r->fh)); + else + return 0; + + err_cond_fail (); + return 0; + } + } + else + assert (0); + + r->where.line_number++; + + return 1; +} + +/* Reads a record from R, setting the current position to the + start of the line. If an error occurs or end-of-file is + encountered, the current line is set to null. */ +static void +read_record (struct dfm_reader *r) +{ + int success = r->fh != NULL ? read_file_record (r) : read_inline_record (r); + if (success) + r->pos = 0; + else + r->flags |= DFM_EOF; +} + +/* Returns nonzero if end of file has been reached on HANDLE. + Reads forward in HANDLE's file, if necessary to tell. */ +int +dfm_eof (struct dfm_reader *r) +{ + if (r->flags & DFM_ADVANCE) + { + r->flags &= ~DFM_ADVANCE; + if ((r->flags & DFM_EOF) == 0) + read_record (r); + else + { + if (r->fh != NULL) + msg (SE, _("Attempt to read beyond end-of-file on file %s."), + handle_get_name (r->fh)); + else + msg (SE, _("Attempt to read beyond END DATA.")); + err_cond_fail (); + } + } + + return (r->flags & DFM_EOF) != 0; +} + +/* Returns the current record in the file corresponding to + HANDLE. Aborts if reading from the file is necessary or at + end of file, so call dfm_eof() first. Sets *LINE to the line, + which is not null-terminated. The caller must not free or + modify the returned string. */ +void +dfm_get_record (struct dfm_reader *r, struct len_string *line) +{ + assert ((r->flags & DFM_ADVANCE) == 0); + assert ((r->flags & DFM_EOF) == 0); + assert (r->pos <= ds_length (&r->line)); + + line->string = ds_data (&r->line) + r->pos; + line->length = ds_length (&r->line) - r->pos; +} + +/* Expands tabs in the current line into the equivalent number of + spaces, if appropriate for this kind of file. Aborts if + reading from the file is necessary or at end of file, so call + dfm_eof() first.*/ +void +dfm_expand_tabs (struct dfm_reader *r) +{ + struct string temp; + size_t ofs, new_pos, tab_width; + + assert ((r->flags & DFM_ADVANCE) == 0); + assert ((r->flags & DFM_EOF) == 0); + assert (r->pos <= ds_length (&r->line)); + + if (r->flags & DFM_TABS_EXPANDED) + return; + r->flags |= DFM_TABS_EXPANDED; + + if (r->fh != NULL + && (handle_get_mode (r->fh) == MODE_BINARY + || handle_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 ? handle_get_tab_width (r->fh) : 8; + ds_clear (&r->scratch); + new_pos = 0; + for (ofs = 0; ofs < ds_length (&r->line); ofs++) + { + unsigned char c; + + if (ofs == r->pos) + new_pos = ds_length (&r->scratch); + + c = ds_c_str (&r->line)[ofs]; + if (c != '\t') + ds_putc (&r->scratch, c); + else + { + do + ds_putc (&r->scratch, ' '); + while (ds_length (&r->scratch) % tab_width != 0); + } + } + + /* Swap r->line and r->scratch and set new r->pos. */ + temp = r->line; + r->line = r->scratch; + r->scratch = temp; + r->pos = new_pos; +} + +/* Causes dfm_get_record() to read in the next record the next time it + is executed on file HANDLE. */ +void +dfm_forward_record (struct dfm_reader *r) +{ + r->flags |= DFM_ADVANCE; +} + +/* Cancels the effect of any previous dfm_fwd_record() executed + on file HANDLE. Sets the current line to begin in the 1-based + column COLUMN. */ +void +dfm_reread_record (struct dfm_reader *r, size_t column) +{ + r->flags &= ~DFM_ADVANCE; + if (column < 1) + r->pos = 0; + else if (column > ds_length (&r->line)) + r->pos = ds_length (&r->line); + else + r->pos = column - 1; +} + +/* Sets the current line to begin COLUMNS characters following + the current start. */ +void +dfm_forward_columns (struct dfm_reader *r, size_t columns) +{ + dfm_reread_record (r, (r->pos + 1) + columns); +} + +/* Returns the 1-based column to which the line pointer in HANDLE + is set. Unless dfm_reread_record() or dfm_forward_columns() + have been called, this is 1. */ +size_t +dfm_column_start (struct dfm_reader *r) +{ + return r->pos + 1; +} + +/* Pushes the filename and line number on the fn/ln stack. */ +void +dfm_push (struct dfm_reader *r) +{ + if (r->fh != NULL) + err_push_file_locator (&r->where); +} + +/* Pops the filename and line number from the fn/ln stack. */ +void +dfm_pop (struct dfm_reader *r) +{ + if (r->fh != NULL) + err_pop_file_locator (&r->where); +} + +/* BEGIN DATA...END DATA procedure. */ + +/* Perform BEGIN DATA...END DATA as a procedure in itself. */ +int +cmd_begin_data (void) +{ + 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)) + { + msg (SE, _("This command is not valid here since the current " + "input program does not access the inline file.")); + err_cond_fail (); + return CMD_FAILURE; + } + + /* Open inline file. */ + r = dfm_open_reader (NULL); + r->flags |= DFM_SAW_BEGIN_DATA; + + /* Input procedure reads from inline file. */ + getl_prompt = GETL_PRPT_DATA; + procedure (NULL, NULL); + + dfm_close_reader (r); + + return CMD_SUCCESS; +} diff --git a/src/dfm-read.h b/src/dfm-read.h new file mode 100644 index 00000000..f8833752 --- /dev/null +++ b/src/dfm-read.h @@ -0,0 +1,51 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef DFM_READ_H +#define DFM_READ_H + +/* Data file manager (dfm). + + This module is in charge of reading and writing data files (other + than system files). dfm is an fhuser, so see file-handle.h for the + fhuser interface. */ + +#include + +struct file_handle; +struct len_string; + +/* Input. */ +struct dfm_reader *dfm_open_reader (struct file_handle *); +void dfm_close_reader (struct dfm_reader *); +int dfm_eof (struct dfm_reader *); +void dfm_get_record (struct dfm_reader *, struct len_string *); +void dfm_expand_tabs (struct dfm_reader *); + +/* Line control. */ +void dfm_forward_record (struct dfm_reader *); +void dfm_reread_record (struct dfm_reader *, size_t column); +void dfm_forward_columns (struct dfm_reader *, size_t columns); +size_t dfm_column_start (struct dfm_reader *); + +/* File stack. */ +void dfm_push (struct dfm_reader *); +void dfm_pop (struct dfm_reader *); + +#endif /* dfm-read.h */ diff --git a/src/dfm-write.c b/src/dfm-write.c new file mode 100644 index 00000000..762a5349 --- /dev/null +++ b/src/dfm-write.c @@ -0,0 +1,127 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-2004 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include +#include "dfm-write.h" +#include +#include +#include +#include "alloc.h" +#include "error.h" +#include "file-handle.h" +#include "filename.h" +#include "str.h" + +/* Data file writer. */ +struct dfm_writer + { + struct file_handle *fh; /* File handle. */ + struct file_ext file; /* Associated file. */ + char *bounce; /* Bounce buffer for fixed-size fields. */ + }; + +/* Opens a file handle for writing as a data file. */ +struct dfm_writer * +dfm_open_writer (struct file_handle *fh) +{ + struct dfm_writer *w; + void **aux; + + aux = fh_open (fh, "data file", "ws"); + if (aux == NULL) + return NULL; + if (*aux != NULL) + return *aux; + + w = *aux = xmalloc (sizeof *w); + w->fh = fh; + w->file.file = NULL; + w->bounce = NULL; + + w->file.filename = xstrdup (handle_get_filename (w->fh)); + w->file.mode = "wb"; + w->file.file = NULL; + w->file.sequence_no = NULL; + w->file.param = NULL; + w->file.postopen = NULL; + w->file.preclose = NULL; + + if (!fn_open_ext (&w->file)) + { + msg (ME, _("An error occurred while opening \"%s\" for writing " + "as a data file: %s."), + handle_get_filename (w->fh), strerror (errno)); + goto error; + } + + return w; + + error: + err_cond_fail (); + dfm_close_writer (w); + return NULL; +} + +/* Writes record REC having length LEN to the file corresponding to + HANDLE. REC is not null-terminated. Returns nonzero on success, + zero on failure. */ +int +dfm_put_record (struct dfm_writer *w, const char *rec, size_t len) +{ + assert (w != NULL); + + if (handle_get_mode (w->fh) == MODE_BINARY + && len < handle_get_record_width (w->fh)) + { + size_t rec_width = handle_get_record_width (w->fh); + if (w->bounce == NULL) + w->bounce = xmalloc (rec_width); + memcpy (w->bounce, rec, len); + memset (&w->bounce[len], 0, rec_width - len); + rec = w->bounce; + len = rec_width; + } + + if (fwrite (rec, len, 1, w->file.file) != 1) + { + msg (ME, _("Error writing file %s: %s."), + handle_get_name (w->fh), strerror (errno)); + err_cond_fail (); + return 0; + } + + return 1; +} + +/* Closes data file writer W. */ +void +dfm_close_writer (struct dfm_writer *w) +{ + if (fh_close (w->fh, "data file", "ws")) + return; + + if (w->file.file) + { + fn_close_ext (&w->file); + free (w->file.filename); + w->file.filename = NULL; + } + free (w->bounce); + free (w); +} diff --git a/src/dfm-write.h b/src/dfm-write.h new file mode 100644 index 00000000..88b57688 --- /dev/null +++ b/src/dfm-write.h @@ -0,0 +1,32 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef DFM_WRITE_H +#define DFM_WRITE_H + +/* Writing data files. */ + +#include + +struct file_handle; +struct dfm_writer *dfm_open_writer (struct file_handle *); +void dfm_close_writer (struct dfm_writer *); +int dfm_put_record (struct dfm_writer *, const char *rec, size_t len); + +#endif /* dfm-write.h */ diff --git a/src/dfm.c b/src/dfm.c deleted file mode 100644 index 8216079b..00000000 --- a/src/dfm.c +++ /dev/null @@ -1,625 +0,0 @@ -/* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . - - 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -#include -#include "error.h" -#include "dfm.h" -#include -#include -#include -#include "alloc.h" -#include "command.h" -#include "error.h" -#include "file-handle.h" -#include "filename.h" -#include "getline.h" -#include "lexer.h" -#include "misc.h" -#include "str.h" -#include "vfm.h" - -#include "debug-print.h" - -/* Flags for DFM readers. */ -enum dfm_reader_flags - { - DFM_EOF = 001, /* At end-of-file? */ - DFM_ADVANCE = 002, /* Read next line on dfm_get_record() call? */ - DFM_SAW_BEGIN_DATA = 004, /* For inline_file only, whether we've - already read a BEGIN DATA line. */ - DFM_TABS_EXPANDED = 010, /* Tabs have been expanded. */ - }; - -/* file_handle extension structure. */ -struct dfm_reader_ext - { - 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_*. */ - }; - -static struct fh_ext_class dfm_r_class; - -static void read_record (struct file_handle *h); - -/* Asserts that H represents a DFM reader and returns H->ext - converted to a struct dfm_reader_ext *. */ -static inline struct dfm_reader_ext * -get_reader (struct file_handle *h) -{ - assert (h != NULL); - assert (h->class == &dfm_r_class); - assert (h->ext != NULL); - - return h->ext; -} - -/* Closes file handle H opened by dfm_open_for_reading(). */ -static void -close_reader (struct file_handle *h) -{ - struct dfm_reader_ext *ext = get_reader (h); - - /* Skip any remaining data on the inline file. */ - if (h == inline_file) - while ((ext->flags & DFM_EOF) == 0) - read_record (h); - - msg (VM (2), _("%s: Closing data-file handle %s."), - handle_get_filename (h), handle_get_name (h)); - assert (h->class == &dfm_r_class); - if (ext->file.file) - { - fn_close_ext (&ext->file); - free (ext->file.filename); - ext->file.filename = NULL; - } - ds_destroy (&ext->line); - ds_destroy (&ext->scratch); - free (ext); -} - -/* Opens a file handle for reading as a data file. Returns - nonzero only if successful. */ -int -dfm_open_for_reading (struct file_handle *h) -{ - struct dfm_reader_ext *ext; - - if (h->class != NULL) - { - if (h->class == &dfm_r_class) - return 1; - else - { - msg (ME, _("Cannot read from file %s already opened for %s."), - handle_get_name (h), gettext (h->class->name)); - return 0; - } - } - - ext = xmalloc (sizeof *ext); - ext->where.filename = handle_get_filename (h); - ext->where.line_number = 0; - ext->file.file = NULL; - ds_init (&ext->line, 64); - ds_init (&ext->scratch, 0); - ext->flags = DFM_ADVANCE; - - msg (VM (1), _("%s: Opening data-file handle %s for reading."), - handle_get_filename (h), handle_get_name (h)); - - assert (h != NULL); - if (h != inline_file) - { - ext->file.filename = xstrdup (handle_get_filename (h)); - ext->file.mode = "rb"; - ext->file.file = NULL; - ext->file.sequence_no = NULL; - ext->file.param = NULL; - ext->file.postopen = NULL; - ext->file.preclose = NULL; - if (!fn_open_ext (&ext->file)) - { - msg (ME, _("Could not open \"%s\" for reading " - "as a data file: %s."), - handle_get_filename (h), strerror (errno)); - goto error; - } - } - - h->class = &dfm_r_class; - h->ext = ext; - return 1; - - error: - err_cond_fail (); - free (ext); - return 0; -} - -/* Reads a record from H->EXT->FILE into H->EXT->LINE, setting - H->EXT->PTR to H->EXT->LINE, and setting H->EXT-LEN to the length - of the line. The line is not null-terminated. If an error occurs - or end-of-file is encountered, H->EXT->LINE is set to NULL. */ -static void -read_record (struct file_handle *h) -{ - struct dfm_reader_ext *ext = get_reader (h); - - if (h == inline_file) - { - if ((ext->flags & DFM_SAW_BEGIN_DATA) == 0) - { - char *s; - - ext->flags |= DFM_SAW_BEGIN_DATA; - - /* FIXME: WTF can't this just be done with tokens? - Is this really a special case? */ - do - { - char *cp; - - if (!getl_read_line ()) - { - msg (SE, _("BEGIN DATA expected.")); - err_failure (); - } - - /* Skip leading whitespace, separate out first - word, so that S points to a single word reduced - to lowercase. */ - s = ds_c_str (&getl_buf); - while (isspace ((unsigned char) *s)) - s++; - for (cp = s; isalpha ((unsigned char) *cp); cp++) - *cp = tolower ((unsigned char) (*cp)); - ds_truncate (&getl_buf, cp - s); - } - while (*s == '\0'); - - if (!lex_id_match_len ("begin", 5, s, strcspn (s, " \t\r\v\n"))) - { - msg (SE, _("BEGIN DATA expected.")); - lex_preprocess_line (); - goto eof; - } - getl_prompt = GETL_PRPT_DATA; - } - - if (!getl_read_line ()) - { - msg (SE, _("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.")); - err_failure (); - } - - ext->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)); - goto eof; - } - - ds_replace (&ext->line, ds_c_str (&getl_buf)); - } - else - { - if (handle_get_mode (h) == MODE_TEXT) - { - ds_clear (&ext->line); - if (!ds_gets (&ext->line, ext->file.file)) - { - if (ferror (ext->file.file)) - { - msg (ME, _("Error reading file %s: %s."), - handle_get_name (h), strerror (errno)); - err_cond_fail (); - } - goto eof; - } - } - else if (handle_get_mode (h) == MODE_BINARY) - { - size_t record_width = handle_get_record_width (h); - size_t amt; - - if (ds_length (&ext->line) < record_width) - ds_rpad (&ext->line, record_width, 0); - - amt = fread (ds_c_str (&ext->line), 1, record_width, - ext->file.file); - if (record_width != amt) - { - if (ferror (ext->file.file)) - msg (ME, _("Error reading file %s: %s."), - handle_get_name (h), strerror (errno)); - else if (amt != 0) - msg (ME, _("%s: Partial record at end of file."), - handle_get_name (h)); - else - goto eof; - - err_cond_fail (); - goto eof; - } - } - else - assert (0); - - ext->where.line_number++; - } - - ext->pos = 0; - return; - -eof: - /* Hit eof or an error, clean up everything. */ - ext->flags |= DFM_EOF; -} - -/* Returns nonzero if end of file has been reached on HANDLE. - Reads forward in HANDLE's file, if necessary to tell. */ -int -dfm_eof (struct file_handle *h) -{ - struct dfm_reader_ext *ext = get_reader (h); - if (ext->flags & DFM_ADVANCE) - { - ext->flags &= ~DFM_ADVANCE; - if ((ext->flags & DFM_EOF) == 0) - read_record (h); - else - { - msg (SE, _("Attempt to read beyond end-of-file on file %s."), - handle_get_name (h)); - err_cond_fail (); - } - } - - return (ext->flags & DFM_EOF) != 0; -} - -/* Returns the current record in the file corresponding to - HANDLE. Aborts if reading from the file is necessary or at - end of file, so call dfm_eof() first. Sets *LINE to the line, - which is not null-terminated. The caller must not free or - modify the returned string. */ -void -dfm_get_record (struct file_handle *h, struct len_string *line) -{ - struct dfm_reader_ext *ext = get_reader (h); - assert ((ext->flags & DFM_ADVANCE) == 0); - assert ((ext->flags & DFM_EOF) == 0); - assert (ext->pos <= ds_length (&ext->line)); - - line->string = ds_data (&ext->line) + ext->pos; - line->length = ds_length (&ext->line) - ext->pos; -} - -/* Expands tabs in the current line into the equivalent number of - spaces, if appropriate for this kind of file. Aborts if - reading from the file is necessary or at end of file, so call - dfm_eof() first.*/ -void -dfm_expand_tabs (struct file_handle *h) -{ - struct dfm_reader_ext *ext = get_reader (h); - struct string temp; - size_t ofs, new_pos, tab_width; - - assert ((ext->flags & DFM_ADVANCE) == 0); - assert ((ext->flags & DFM_EOF) == 0); - assert (ext->pos <= ds_length (&ext->line)); - - if (ext->flags & DFM_TABS_EXPANDED) - return; - ext->flags |= DFM_TABS_EXPANDED; - - if (handle_get_mode (h) == MODE_BINARY - || handle_get_tab_width (h) == 0 - || memchr (ds_c_str (&ext->line), '\t', ds_length (&ext->line)) == NULL) - return; - - /* Expand tabs from ext->line into ext->scratch, and figure out - new value for ext->pos. */ - tab_width = handle_get_tab_width (h); - ds_clear (&ext->scratch); - new_pos = 0; - for (ofs = 0; ofs < ds_length (&ext->line); ofs++) - { - unsigned char c; - - if (ofs == ext->pos) - new_pos = ds_length (&ext->scratch); - - c = ds_c_str (&ext->line)[ofs]; - if (c != '\t') - ds_putc (&ext->scratch, c); - else - { - do - ds_putc (&ext->scratch, ' '); - while (ds_length (&ext->scratch) % tab_width != 0); - } - } - - /* Swap ext->line and ext->scratch and set new ext->pos. */ - temp = ext->line; - ext->line = ext->scratch; - ext->scratch = temp; - ext->pos = new_pos; -} - -/* Causes dfm_get_record() to read in the next record the next time it - is executed on file HANDLE. */ -void -dfm_forward_record (struct file_handle *h) -{ - struct dfm_reader_ext *ext = get_reader (h); - ext->flags |= DFM_ADVANCE; -} - -/* Cancels the effect of any previous dfm_fwd_record() executed - on file HANDLE. Sets the current line to begin in the 1-based - column COLUMN. */ -void -dfm_reread_record (struct file_handle *h, size_t column) -{ - struct dfm_reader_ext *ext = get_reader (h); - ext->flags &= ~DFM_ADVANCE; - if (column < 1) - ext->pos = 0; - else if (column > ds_length (&ext->line)) - ext->pos = ds_length (&ext->line); - else - ext->pos = column - 1; -} - -/* Sets the current line to begin COLUMNS characters following - the current start. */ -void -dfm_forward_columns (struct file_handle *h, size_t columns) -{ - struct dfm_reader_ext *ext = get_reader (h); - dfm_reread_record (h, (ext->pos + 1) + columns); -} - -/* Returns the 1-based column to which the line pointer in HANDLE - is set. Unless dfm_reread_record() or dfm_forward_columns() - have been called, this is 1. */ -size_t -dfm_column_start (struct file_handle *h) -{ - struct dfm_reader_ext *ext = get_reader (h); - return ext->pos + 1; -} - -/* Pushes the filename and line number on the fn/ln stack. */ -void -dfm_push (struct file_handle *h) -{ - struct dfm_reader_ext *ext = get_reader (h); - if (h != inline_file) - err_push_file_locator (&ext->where); -} - -/* Pops the filename and line number from the fn/ln stack. */ -void -dfm_pop (struct file_handle *h) -{ - struct dfm_reader_ext *ext = get_reader (h); - if (h != inline_file) - err_pop_file_locator (&ext->where); -} - -/* DFM reader class. */ -static struct fh_ext_class dfm_r_class = -{ - 1, - N_("reading as a data file"), - close_reader, -}; - -/* file_handle extension structure. */ -struct dfm_writer_ext - { - struct file_ext file; /* Associated file. */ - struct file_locator where; /* Current location in data file. */ - char *bounce; /* Bounce buffer for fixed-size fields. */ - }; - -static struct fh_ext_class dfm_w_class; - -/* Opens a file handle for writing as a data file. */ -int -dfm_open_for_writing (struct file_handle *h) -{ - struct dfm_writer_ext *ext; - - if (h->class != NULL) - { - if (h->class == &dfm_w_class) - return 1; - else - { - msg (ME, _("Cannot write to file %s already opened for %s."), - handle_get_name (h), gettext (h->class->name)); - err_cond_fail (); - return 0; - } - } - - ext = xmalloc (sizeof *ext); - ext->where.filename = handle_get_filename (h); - ext->where.line_number = 0; - ext->file.file = NULL; - ext->bounce = NULL; - - msg (VM (1), _("%s: Opening data-file handle %s for writing."), - handle_get_filename (h), handle_get_name (h)); - - assert (h != NULL); - if (h == inline_file) - { - msg (ME, _("Cannot open the inline file for writing.")); - goto error; - } - - ext->file.filename = xstrdup (handle_get_filename (h)); - ext->file.mode = "wb"; - ext->file.file = NULL; - ext->file.sequence_no = NULL; - ext->file.param = NULL; - ext->file.postopen = NULL; - ext->file.preclose = NULL; - - if (!fn_open_ext (&ext->file)) - { - msg (ME, _("An error occurred while opening \"%s\" for writing " - "as a data file: %s."), - handle_get_filename (h), strerror (errno)); - goto error; - } - - h->class = &dfm_w_class; - h->ext = ext; - return 1; - - error: - free (ext); - err_cond_fail (); - return 0; -} - -/* Writes record REC having length LEN to the file corresponding to - HANDLE. REC is not null-terminated. Returns nonzero on success, - zero on failure. */ -int -dfm_put_record (struct file_handle *h, const char *rec, size_t len) -{ - struct dfm_writer_ext *ext; - - assert (h != NULL); - assert (h->class == &dfm_w_class); - assert (h->ext != NULL); - - ext = h->ext; - if (handle_get_mode (h) == MODE_BINARY && len < handle_get_record_width (h)) - { - size_t rec_width = handle_get_record_width (h); - if (ext->bounce == NULL) - ext->bounce = xmalloc (rec_width); - memcpy (ext->bounce, rec, len); - memset (&ext->bounce[len], 0, rec_width - len); - rec = ext->bounce; - len = rec_width; - } - - if (fwrite (rec, len, 1, ext->file.file) != 1) - { - msg (ME, _("Error writing file %s: %s."), - handle_get_name (h), strerror (errno)); - err_cond_fail (); - return 0; - } - - return 1; -} - -/* Closes file handle H opened by dfm_open_for_writing(). */ -static void -close_writer (struct file_handle *h) -{ - struct dfm_writer_ext *ext; - - assert (h->class == &dfm_w_class); - ext = h->ext; - - msg (VM (2), _("%s: Closing data-file handle %s."), - handle_get_filename (h), handle_get_name (h)); - if (ext->file.file) - { - fn_close_ext (&ext->file); - free (ext->file.filename); - ext->file.filename = NULL; - } - free (ext->bounce); - free (ext); -} - -/* DFM writer class. */ -static struct fh_ext_class dfm_w_class = -{ - 2, - N_("writing as a data file"), - close_writer, -}; - -/* BEGIN DATA...END DATA procedure. */ - -/* Perform BEGIN DATA...END DATA as a procedure in itself. */ -int -cmd_begin_data (void) -{ - struct dfm_reader_ext *ext; - - /* FIXME: figure out the *exact* conditions, not these really - lenient conditions. */ - if (vfm_source == NULL - || case_source_is_class (vfm_source, &storage_source_class)) - { - msg (SE, _("This command is not valid here since the current " - "input program does not access the inline file.")); - err_cond_fail (); - return CMD_FAILURE; - } - - /* Initialize inline_file. */ - msg (VM (1), _("inline file: Opening for reading.")); - dfm_open_for_reading (inline_file); - ext = inline_file->ext; - ext->flags |= DFM_SAW_BEGIN_DATA; - - /* We don't actually read from the inline file. The input procedure - is what reads from it. */ - getl_prompt = GETL_PRPT_DATA; - procedure (NULL, NULL); - - ext = inline_file->ext; - if (ext && (ext->flags & DFM_EOF) == 0) - { - msg (MW, _("Skipping remaining inline data.")); - while ((ext->flags & DFM_EOF) == 0) - read_record (inline_file); - } - assert (inline_file->ext == NULL); - - return CMD_SUCCESS; -} diff --git a/src/dfm.h b/src/dfm.h deleted file mode 100644 index df2307c8..00000000 --- a/src/dfm.h +++ /dev/null @@ -1,53 +0,0 @@ -/* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . - - 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -#if !dfm_h -#define dfm_h 1 - -/* Data file manager (dfm). - - This module is in charge of reading and writing data files (other - than system files). dfm is an fhuser, so see file-handle.h for the - fhuser interface. */ - -#include - -struct file_handle; -struct len_string; - -/* Input. */ -int dfm_open_for_reading (struct file_handle *); -int dfm_eof (struct file_handle *); -void dfm_get_record (struct file_handle *, struct len_string *); -void dfm_expand_tabs (struct file_handle *); - -void dfm_forward_record (struct file_handle *); -void dfm_reread_record (struct file_handle *, size_t column); -void dfm_forward_columns (struct file_handle *, size_t columns); -size_t dfm_column_start (struct file_handle *); - -/* Output. */ -int dfm_open_for_writing (struct file_handle *); -int dfm_put_record (struct file_handle *, const char *rec, size_t len); - -/* File stack. */ -void dfm_push (struct file_handle *); -void dfm_pop (struct file_handle *); - -#endif /* dfm_h */ diff --git a/src/dictionary.c b/src/dictionary.c index 20d64bc5..f1c5f462 100644 --- a/src/dictionary.c +++ b/src/dictionary.c @@ -18,11 +18,12 @@ 02111-1307, USA. */ #include -#include "error.h" +#include "dictionary.h" #include #include "algorithm.h" #include "alloc.h" #include "case.h" +#include "error.h" #include "hash.h" #include "misc.h" #include "str.h" @@ -124,6 +125,7 @@ dict_clear (struct dictionary *d) for (i = 0; i < d->var_cnt; i++) { struct variable *v = d->var[i]; + var_clear_aux (v); val_labs_destroy (v->val_labs); free (v->label); free (v); @@ -146,6 +148,19 @@ dict_clear (struct dictionary *d) dict_clear_vectors (d); } +/* Destroys the aux data for every variable in D, by calling + var_clear_aux() for each variable. */ +void +dict_clear_aux (struct dictionary *d) +{ + int i; + + assert (d != NULL); + + for (i = 0; i < d->var_cnt; i++) + var_clear_aux (d->var[i]); +} + /* Clears a dictionary and destroys it. */ void dict_destroy (struct dictionary *d) @@ -254,6 +269,8 @@ dict_create_var (struct dictionary *d, const char *name, int width) v->write = v->print; v->val_labs = val_labs_create (v->width); v->label = NULL; + v->aux = NULL; + v->aux_dtor = NULL; /* Update dictionary. */ if (d->var_cnt >= d->var_cap) @@ -410,7 +427,10 @@ dict_delete_var (struct dictionary *d, struct variable *v) assert (dict_contains_var (d, v)); assert (d->var[v->index] == v); - /* Remove v from splits, weight, filter variables. */ + /* Delete aux data. */ + var_clear_aux (v); + + /* Remove V from splits, weight, filter variables. */ d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split, &v, compare_variable_dblptrs, NULL); @@ -420,7 +440,7 @@ dict_delete_var (struct dictionary *d, struct variable *v) d->filter = NULL; dict_clear_vectors (d); - /* Remove v from var array. */ + /* Remove V from var array. */ d->var_cnt--; memmove (d->var + v->index, d->var + v->index + 1, (d->var_cnt - v->index) * sizeof *d->var); diff --git a/src/dictionary.h b/src/dictionary.h new file mode 100644 index 00000000..abe1bb7f --- /dev/null +++ b/src/dictionary.h @@ -0,0 +1,101 @@ +/* PSPP - computes sample statistics. + Copyright (C) 2004 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef DICTIONARY_H +#define DICTIONARY_H + +#include + +/* Dictionary. */ + +struct variable; +struct dictionary *dict_create (void); +struct dictionary *dict_clone (const struct dictionary *); +void dict_clear (struct dictionary *); +void dict_clear_aux (struct dictionary *); +void dict_destroy (struct dictionary *); + +size_t dict_get_var_cnt (const struct dictionary *); +struct variable *dict_get_var (const struct dictionary *, size_t idx); +void dict_get_vars (const struct dictionary *, + struct variable ***vars, size_t *cnt, + unsigned exclude_classes); + +struct variable *dict_create_var (struct dictionary *, const char *, + int width); +struct variable *dict_create_var_assert (struct dictionary *, const char *, + int width); +struct variable *dict_clone_var (struct dictionary *, const struct variable *, + const char *); +void dict_rename_var (struct dictionary *, struct variable *, const char *); + +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 *); +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); +int 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 *); +double dict_get_case_weight (const struct dictionary *, + const struct ccase *, int *); +void dict_set_weight (struct dictionary *, struct variable *); + +struct variable *dict_get_filter (const struct dictionary *); +void dict_set_filter (struct dictionary *, struct variable *); + +int dict_get_case_limit (const struct dictionary *); +void dict_set_case_limit (struct dictionary *, int); + +int dict_get_next_value_idx (const struct dictionary *); +size_t dict_get_case_size (const struct dictionary *); + +void dict_compact_values (struct dictionary *); +size_t dict_get_compacted_value_cnt (const struct dictionary *); +int *dict_get_compacted_idx_to_fv (const struct dictionary *); + +struct variable *const *dict_get_split_vars (const struct dictionary *); +size_t dict_get_split_cnt (const struct dictionary *); +void dict_set_split_vars (struct dictionary *, + struct variable *const *, size_t cnt); + +const char *dict_get_label (const struct dictionary *); +void dict_set_label (struct dictionary *, const char *); + +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); +const struct vector *dict_get_vector (const struct dictionary *, + size_t idx); +size_t dict_get_vector_cnt (const struct dictionary *); +const struct vector *dict_lookup_vector (const struct dictionary *, + const char *name); +void dict_clear_vectors (struct dictionary *); + +#endif /* dictionary.h */ diff --git a/src/examine.q b/src/examine.q index 844542ad..e9e0ca7e 100644 --- a/src/examine.q +++ b/src/examine.q @@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "alloc.h" #include "str.h" #include "case.h" +#include "dictionary.h" #include "command.h" #include "lexer.h" #include "error.h" @@ -40,6 +41,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "hash.h" #include "casefile.h" #include "factor_stats.h" +/* (headers) */ #include "chart.h" /* (specification) @@ -125,7 +127,7 @@ void np_plot(const struct metrics *m, const char *varname); /* Per Split function */ -static void run_examine(const struct casefile *cf, void *cmd_); +static void run_examine(const struct casefile *cf, void *); static void output_examine(void); @@ -152,7 +154,7 @@ cmd_examine(void) totals->stats = xmalloc(sizeof ( struct metrics ) * n_dependent_vars); - multipass_procedure_with_splits (run_examine, &cmd); + multipass_procedure_with_splits (run_examine, NULL); hsh_destroy(hash_table_factors); @@ -942,7 +944,7 @@ static int bad_weight_warn = 1; static void -run_examine(const struct casefile *cf, void *cmd_) +run_examine(const struct casefile *cf, void *aux UNUSED) { struct hsh_iterator hi; struct factor *fctr; @@ -951,8 +953,6 @@ run_examine(const struct casefile *cf, void *cmd_) struct ccase c; int v; - const struct cmd_examine *cmd = (struct cmd_examine *) cmd_; - /* Make sure we haven't got rubbish left over from a previous split */ if ( hash_table_factors ) diff --git a/src/expr-evl.c b/src/expr-evl.c index 2ddefec7..04327658 100644 --- a/src/expr-evl.c +++ b/src/expr-evl.c @@ -39,6 +39,7 @@ #include #include "case.h" #include "data-in.h" +#include "dictionary.h" #include "error.h" #include "julcal/julcal.h" #include "magic.h" diff --git a/src/expr-prs.c b/src/expr-prs.c index da475783..183d5b0f 100644 --- a/src/expr-prs.c +++ b/src/expr-prs.c @@ -18,6 +18,7 @@ 02111-1307, USA. */ #include +#include "dictionary.h" #include "expr.h" #include "exprP.h" #include "error.h" diff --git a/src/file-handle.h b/src/file-handle.h index 5f18202a..00a79109 100644 --- a/src/file-handle.h +++ b/src/file-handle.h @@ -20,34 +20,9 @@ #if !file_handle_h #define file_handle_h 1 -/* File handle provider (fhp). - - This module provides file handles in the form of file_handle - structures to the dfm and sfm modules, which are known as file - handle users (fhusers). fhp does not know anything about file - contents. */ +/* File handles. */ #include -#include "error.h" - -struct file_handle; - -/* Services that fhusers provide to fhp. */ -struct fh_ext_class - { - int magic; /* Magic identifier for fhuser. */ - const char *name; /* String identifier for fhuser. */ - - void (*close) (struct file_handle *); /* Closes the file. */ - }; - -/* Mostly-opaque structure. */ -struct file_handle - { - struct private_file_handle *private; - const struct fh_ext_class *class; /* Polymorphism support. */ - void *ext; /* Extension struct for fhuser use. */ - }; /* File modes. */ enum file_handle_mode @@ -56,20 +31,16 @@ enum file_handle_mode MODE_BINARY /* Fixed-length records. */ }; -/* Pointer to the file handle that corresponds to data in the command - file entered via BEGIN DATA/END DATA. */ -extern struct file_handle *inline_file; - -/* Initialization. */ -void fh_init_files (void); +/* Parsing handles. */ +struct file_handle *fh_parse (void); /* Opening and closing handles. */ -struct file_handle *fh_parse_file_handle (void); -void fh_close_handle (struct file_handle *handle); +void **fh_open (struct file_handle *, const char *type, const char *mode); +int fh_close (struct file_handle *, const char *type, const char *mode); /* Handle info. */ -const char *handle_get_name (const struct file_handle *handle); -const char *handle_get_filename (const struct file_handle *handle); +const char *handle_get_name (const struct file_handle *); +const char *handle_get_filename (const struct file_handle *); enum file_handle_mode handle_get_mode (const struct file_handle *); size_t handle_get_record_width (const struct file_handle *); size_t handle_get_tab_width (const struct file_handle *); diff --git a/src/file-handle.q b/src/file-handle.q index 96aa9486..9c3a81a3 100644 --- a/src/file-handle.q +++ b/src/file-handle.q @@ -32,9 +32,10 @@ #include "var.h" /* (headers) */ -/* File handle private data. */ -struct private_file_handle +/* File handle. */ +struct file_handle { + struct file_handle *next; /* Next in global list. */ char *name; /* File handle identifier. */ char *filename; /* Filename as provided by user. */ struct file_identity *identity; /* For checking file identity. */ @@ -42,17 +43,14 @@ struct private_file_handle enum file_handle_mode mode; /* File mode. */ size_t length; /* Length of fixed-format records. */ size_t tab_width; /* Tab width, 0=do not expand tabs. */ - }; -/* Linked list of file handles. */ -struct file_handle_list - { - struct file_handle *handle; - struct file_handle_list *next; + int open_cnt; /* 0=not open, otherwise # of openers. */ + const char *type; /* If open, type of file. */ + const char *open_mode; /* "[rw][se]". */ + void *aux; /* Aux data pointer for owner if any. */ }; -static struct file_handle_list *file_handles; -struct file_handle *inline_file; +static struct file_handle *file_handles; static struct file_handle *create_file_handle (const char *handle_name, const char *filename); @@ -70,11 +68,11 @@ static struct file_handle *create_file_handle (const char *handle_name, static struct file_handle * get_handle_with_name (const char *handle_name) { - struct file_handle_list *iter; + struct file_handle *iter; for (iter = file_handles; iter != NULL; iter = iter->next) - if (!strcmp (handle_name, iter->handle->private->name)) - return iter->handle; + if (!strcmp (handle_name, iter->name)) + return iter; return NULL; } @@ -82,27 +80,26 @@ static struct file_handle * get_handle_for_filename (const char *filename) { struct file_identity *identity; - struct file_handle_list *iter; + struct file_handle *iter; /* First check for a file with the same identity. */ identity = fn_get_identity (filename); if (identity != NULL) { for (iter = file_handles; iter != NULL; iter = iter->next) - if (iter->handle->private->identity != NULL - && !fn_compare_file_identities (identity, - iter->handle->private->identity)) + if (iter->identity != NULL + && !fn_compare_file_identities (identity, iter->identity)) { fn_free_identity (identity); - return iter->handle; + return iter; } 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->handle->private->filename)) - return iter->handle; + if (!strcmp (filename, iter->filename)) + return iter; return NULL; } @@ -125,7 +122,7 @@ cmd_file_handle (void) msg (SE, _("File handle %s already refers to " "file %s. File handle cannot be redefined within a " "session."), - tokid, handle->private->filename); + tokid, handle->filename); return CMD_FAILURE; } @@ -153,29 +150,29 @@ cmd_file_handle (void) switch (cmd.mode) { case FH_CHARACTER: - handle->private->mode = MODE_TEXT; + handle->mode = MODE_TEXT; if (cmd.sbc_tabwidth) - handle->private->tab_width = cmd.n_tabwidth; + handle->tab_width = cmd.n_tabwidth[0]; else - handle->private->tab_width = 4; + handle->tab_width = 4; break; case FH_IMAGE: - handle->private->mode = MODE_BINARY; - if (cmd.n_lrecl == NOT_LONG) + handle->mode = 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. " "Assuming 1024-character records.")); - handle->private->length = 1024; + handle->length = 1024; } - else if (cmd.n_lrecl < 1) + else if (cmd.n_lrecl[0] < 1) { msg (SE, _("Record length (%ld) must be at least one byte. " "1-character records will be assumed."), cmd.n_lrecl); - handle->private->length = 1; + handle->length = 1; } else - handle->private->length = cmd.n_lrecl; + handle->length = cmd.n_lrecl[0]; break; default: assert (0); @@ -197,63 +194,121 @@ static struct file_handle * create_file_handle (const char *handle_name, const char *filename) { struct file_handle *handle; - struct file_handle_list *list; /* Create and initialize file handle. */ handle = xmalloc (sizeof *handle); - handle->private = xmalloc (sizeof *handle->private); - handle->private->name = xstrdup (handle_name); - handle->private->filename = xstrdup (filename); - handle->private->identity = fn_get_identity (filename); - handle->private->where.filename = handle->private->filename; - handle->private->where.line_number = 0; - handle->private->mode = MODE_TEXT; - handle->private->length = 1024; - handle->private->tab_width = 4; - handle->ext = NULL; - handle->class = NULL; - - /* Add file handle to global list. */ - list = xmalloc (sizeof *list); - list->handle = handle; - list->next = file_handles; - file_handles = list; + handle->next = file_handles; + handle->name = xstrdup (handle_name); + handle->filename = xstrdup (filename); + handle->identity = fn_get_identity (filename); + handle->where.filename = handle->filename; + handle->where.line_number = 0; + handle->mode = MODE_TEXT; + handle->length = 1024; + handle->tab_width = 4; + handle->open_cnt = 0; + handle->type = NULL; + handle->open_mode = NULL; + handle->aux = NULL; + file_handles = handle; return handle; } -/* Closes the stdio FILE associated with handle H. Frees internal - buffers associated with that file. Does *not* destroy the file - handle H. (File handles are permanent during a session.) */ -void -fh_close_handle (struct file_handle *h) +static const char * +mode_name (const char *mode) +{ + assert (mode != NULL); + assert (mode[0] == 'r' || mode[0] == 'w'); + + return mode[0] == 'r' ? "reading" : "writing"; +} + + +/* Tries to open FILE with the given TYPE and MODE. + + 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. + + MODE combines the read or write mode with the sharing mode. + The first character is 'r' for read, 'w' for write. The + second character is 's' to permit sharing, 'e' to require + exclusive access. + + Returns the address of a void * that the caller can use for + data specific to the file handle if successful, or a null + pointer on failure. For exclusive access modes the void * + will always be a null pointer at return. In shared access + modes the void * will necessarily be null only if no other + sharers are active. + + If successful, references to type and mode are retained, so + they should probably be string literals. */ +void ** +fh_open (struct file_handle *h, const char *type, const char *mode) { - if (h == NULL) - return; + assert (h != NULL); + assert (type != NULL); + assert (mode != NULL); + assert (mode[0] == 'r' || mode[0] == 'w'); + assert (mode[1] == 's' || mode[1] == 'e'); + assert (mode[2] == '\0'); + + if (h->open_cnt != 0) + { + if (strcmp (h->type, type)) + msg (SE, _("Can't open %s as a %s because it is " + "already open as a %s"), + handle_get_name (h), type, h->type); + 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"), + handle_get_name (h), type, + mode_name (mode), mode_name (h->open_mode)); + else if (h->open_mode[1] == 'e') + msg (SE, _("Can't re-open %s as a %s for %s"), + handle_get_name (h), type, mode_name (mode)); + } + else + { + h->type = type; + h->open_mode = mode; + assert (h->aux == NULL); + } + h->open_cnt++; - if (h->class != NULL) - h->class->close (h); - h->class = NULL; - h->ext = NULL; + return &h->aux; } -/* Initialize the hash of file handles; inserts the "inline file" - inline_file. */ -void -fh_init_files (void) +/* 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. */ +int +fh_close (struct file_handle *h, const char *type, const char *mode) { - if (inline_file == NULL) + assert (h != NULL); + assert (h->open_cnt > 0); + assert (type != NULL); + assert (!strcmp (type, h->type)); + assert (mode != NULL); + assert (!strcmp (mode, h->open_mode)); + + h->open_cnt--; + if (h->open_cnt == 0) { - inline_file = create_file_handle ("INLINE", _("")); - inline_file->private->length = 80; + h->type = NULL; + h->open_mode = NULL; + h->aux = NULL; } + return h->open_cnt; } /* 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_file_handle (void) +fh_parse (void) { struct file_handle *handle; @@ -292,14 +347,16 @@ fh_parse_file_handle (void) const char * handle_get_name (const struct file_handle *handle) { - return handle->private->name; + assert (handle != NULL); + return handle->name; } /* Returns the name of the file associated with HANDLE. */ const char * handle_get_filename (const struct file_handle *handle) { - return handle->private->filename; + assert (handle != NULL); + return handle->filename; } /* Returns the mode of HANDLE. */ @@ -307,7 +364,7 @@ enum file_handle_mode handle_get_mode (const struct file_handle *handle) { assert (handle != NULL); - return handle->private->mode; + return handle->mode; } /* Returns the width of a logical record on HANDLE. Applicable @@ -316,7 +373,7 @@ size_t handle_get_record_width (const struct file_handle *handle) { assert (handle != NULL); - return handle->private->length; + return handle->length; } /* Returns the number of characters per tab stop for HANDLE, or @@ -326,7 +383,7 @@ size_t handle_get_tab_width (const struct file_handle *handle) { assert (handle != NULL); - return handle->private->tab_width; + return handle->tab_width; } /* diff --git a/src/file-type.c b/src/file-type.c index ec076146..fee9ee5a 100644 --- a/src/file-type.c +++ b/src/file-type.c @@ -18,13 +18,14 @@ 02111-1307, USA. */ #include -#include "error.h" #include #include "alloc.h" #include "case.h" #include "command.h" #include "data-in.h" -#include "dfm.h" +#include "dfm-read.h" +#include "dictionary.h" +#include "error.h" #include "file-handle.h" #include "format.h" #include "lexer.h" @@ -75,7 +76,7 @@ struct record_type struct file_type_pgm { int type; /* One of the FTY_* constants. */ - struct file_handle *handle; /* File handle of input file. */ + struct dfm_reader *reader; /* Data file to read. */ struct col_spec record; /* RECORD subcommand. */ struct col_spec case_sbc; /* CASE subcommand. */ int wild; /* 0=NOWARN, 1=WARN. */ @@ -97,13 +98,14 @@ static void create_col_var (struct col_spec *c); int cmd_file_type (void) { - static struct file_type_pgm *fty; + static struct file_type_pgm *fty; /* FIXME: static? WTF? */ + struct file_handle *fh = NULL; /* Initialize. */ discard_variables (); fty = xmalloc (sizeof *fty); - fty->handle = inline_file; + fty->reader = NULL; fty->record.name[0] = 0; fty->case_sbc.name[0] = 0; fty->wild = fty->duplicate = fty->missing = fty->ordered = 0; @@ -133,8 +135,8 @@ cmd_file_type (void) if (lex_match_id ("FILE")) { lex_match ('='); - fty->handle = fh_parse_file_handle (); - if (!fty->handle) + fh = fh_parse (); + if (fh == NULL) goto error; } else if (lex_match_id ("RECORD")) @@ -270,9 +272,10 @@ cmd_file_type (void) } } - if (!dfm_open_for_reading (fty->handle)) + fty->reader = dfm_open_reader (fh); + if (fty->reader == NULL) goto error; - default_handle = fty->handle; + default_handle = fh; create_col_var (&fty->record); if (fty->case_sbc.name[0]) @@ -626,20 +629,20 @@ file_type_source_read (struct case_source *source, struct file_type_pgm *fty = source->aux; struct fmt_spec format; - dfm_push (fty->handle); + dfm_push (fty->reader); format.type = fty->record.fmt; format.w = fty->record.nc; format.d = 0; - while (!dfm_eof (fty->handle)) + while (!dfm_eof (fty->reader)) { struct len_string line; struct record_type *iter; union value v; int i; - dfm_expand_tabs (fty->handle); - dfm_get_record (fty->handle, &line); + dfm_expand_tabs (fty->reader); + dfm_get_record (fty->reader, &line); if (formats[fty->record.fmt].cat & FCAT_STRING) { struct data_in di; @@ -689,13 +692,13 @@ file_type_source_read (struct case_source *source, if (fty->wild) msg (SW, _("Unknown record type %g."), v.f); } - dfm_forward_record (fty->handle); + dfm_forward_record (fty->reader); continue; found: /* Arrive here if there is a matching record_type, which is in iter. */ - dfm_forward_record (fty->handle); + dfm_forward_record (fty->reader); } /* switch(fty->type) @@ -706,7 +709,7 @@ file_type_source_read (struct case_source *source, default: assert(0); } */ - dfm_pop (fty->handle); + dfm_pop (fty->reader); } static void @@ -716,6 +719,7 @@ file_type_source_destroy (struct case_source *source) struct record_type *iter, *next; cancel_transformations (); + dfm_close_reader (fty->reader); for (iter = fty->recs_head; iter; iter = next) { next = iter->next; diff --git a/src/flip.c b/src/flip.c index f9162522..b4f908df 100644 --- a/src/flip.c +++ b/src/flip.c @@ -27,6 +27,7 @@ #include "alloc.h" #include "case.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "lexer.h" #include "misc.h" diff --git a/src/frequencies.q b/src/frequencies.q index 9a69e972..8393819c 100644 --- a/src/frequencies.q +++ b/src/frequencies.q @@ -30,6 +30,7 @@ #include "alloc.h" #include "bitvector.h" #include "case.h" +#include "dictionary.h" #include "hash.h" #include "pool.h" #include "command.h" @@ -48,6 +49,7 @@ #include "vfm.h" #include "settings.h" #include "chart.h" +/* (headers) */ #include "debug-print.h" @@ -87,6 +89,14 @@ /* (declarations) */ /* (functions) */ +/* Statistics. */ +enum + { + frq_mean = 0, frq_semean, frq_median, frq_mode, frq_stddev, frq_variance, + frq_kurt, frq_sekurt, frq_skew, frq_seskew, frq_range, frq_min, frq_max, + frq_sum, frq_n_stats + }; + /* Description of a statistic. */ struct frq_info { @@ -129,7 +139,6 @@ struct percentile static void add_percentile (double x) ; - static struct percentile *percentiles; static int n_percentiles; @@ -179,12 +188,31 @@ static struct variable **v_variables; static struct pool *int_pool; /* Integer mode. */ static struct pool *gen_pool; /* General mode. */ -/* Easier access to a_statistics. */ -#define stat cmd.a_statistics +/* Per-variable frequency data. */ +struct var_freqs + { + /* Freqency table. */ + struct freq_tab tab; /* Frequencies table to use. */ + + /* Percentiles. */ + int n_groups; /* Number of groups. */ + double *groups; /* Groups. */ + + /* Statistics. */ + double stat[frq_n_stats]; + }; + +static inline struct var_freqs * +get_var_freqs (struct variable *v) +{ + assert (v != NULL); + assert (v->aux != NULL); + return v->aux; +} static void determine_charts (void); -static void calc_stats (struct variable * v, double d[frq_n_stats]); +static void calc_stats (struct variable *v, double d[frq_n_stats]); static void precalc (void *); static int calc (struct ccase *, void *); @@ -233,9 +261,6 @@ internal_cmd_frequencies (void) n_variables = 0; v_variables = NULL; - for (i = 0; i < dict_get_var_cnt (default_dict); i++) - dict_get_var(default_dict, i)->p.frq.used = 0; - if (!parse_frequencies (&cmd)) return CMD_FAILURE; @@ -244,14 +269,14 @@ internal_cmd_frequencies (void) /* Figure out statistics to calculate. */ stats = 0; - if (stat[FRQ_ST_DEFAULT] || !cmd.sbc_statistics) + if (cmd.a_statistics[FRQ_ST_DEFAULT] || !cmd.sbc_statistics) stats |= frq_default; - if (stat[FRQ_ST_ALL]) + if (cmd.a_statistics[FRQ_ST_ALL]) stats |= frq_all; if (cmd.sort != FRQ_AVALUE && cmd.sort != FRQ_DVALUE) stats &= ~frq_median; for (i = 0; i < frq_n_stats; i++) - if (stat[st_name[i].st_indx]) + if (cmd.a_statistics[st_name[i].st_indx]) stats |= BIT_INDEX (i); if (stats & frq_kurt) stats |= frq_sekurt; @@ -416,9 +441,9 @@ calc (struct ccase *c, void *aux UNUSED) { struct variable *v = v_variables[i]; const union value *val = case_data (c, v->fv); - struct freq_tab *ft = &v->p.frq.tab; + struct freq_tab *ft = &get_var_freqs (v)->tab; - switch (v->p.frq.tab.mode) + switch (ft->mode) { case FRQM_GENERAL: { @@ -439,15 +464,15 @@ calc (struct ccase *c, void *aux UNUSED) case FRQM_INTEGER: /* Integer mode. */ if (val->f == SYSMIS) - v->p.frq.tab.sysmis += weight; + ft->sysmis += weight; else if (val->f > INT_MIN+1 && val->f < INT_MAX-1) { int i = val->f; - if (i >= v->p.frq.tab.min && i <= v->p.frq.tab.max) - v->p.frq.tab.vector[i - v->p.frq.tab.min] += weight; + if (i >= ft->min && i <= ft->max) + ft->vector[i - ft->min] += weight; } else - v->p.frq.tab.out_of_range += weight; + ft->out_of_range += weight; break; default: assert (0); @@ -469,8 +494,9 @@ precalc (void *aux UNUSED) for (i = 0; i < n_variables; i++) { struct variable *v = v_variables[i]; + struct freq_tab *ft = &get_var_freqs (v)->tab; - if (v->p.frq.tab.mode == FRQM_GENERAL) + if (ft->mode == FRQM_GENERAL) { hsh_hash_func *hash; hsh_compare_func *compare; @@ -485,16 +511,16 @@ precalc (void *aux UNUSED) hash = hash_value_alpha; compare = compare_value_alpha_a; } - v->p.frq.tab.data = hsh_create (16, compare, hash, NULL, v); + ft->data = hsh_create (16, compare, hash, NULL, v); } else { int j; - for (j = (v->p.frq.tab.max - v->p.frq.tab.min); j >= 0; j--) - v->p.frq.tab.vector[j] = 0.0; - v->p.frq.tab.out_of_range = 0.0; - v->p.frq.tab.sysmis = 0.0; + for (j = (ft->max - ft->min); j >= 0; j--) + ft->vector[j] = 0.0; + ft->out_of_range = 0.0; + ft->sysmis = 0.0; } } } @@ -509,13 +535,15 @@ postcalc (void *aux UNUSED) for (i = 0; i < n_variables; i++) { struct variable *v = v_variables[i]; + struct var_freqs *vf = get_var_freqs (v); + struct freq_tab *ft = &vf->tab; int n_categories; int dumped_freq_tab = 1; postprocess_freq_tab (v); /* Frequencies tables. */ - n_categories = v->p.frq.tab.n_valid + v->p.frq.tab.n_missing; + n_categories = ft->n_valid + ft->n_missing; if (cmd.table == FRQ_TABLE || (cmd.table == FRQ_LIMIT && n_categories <= cmd.limit)) switch (cmd.cond) @@ -547,17 +575,16 @@ postcalc (void *aux UNUSED) { struct chart ch; double d[frq_n_stats]; - struct frequencies_proc *frq = &v->p.frq; struct normal_curve norm; - norm.N = frq->tab.total_cases ; + norm.N = vf->tab.total_cases; calc_stats(v,d); norm.mean = d[frq_mean]; norm.stddev = d[frq_stddev]; chart_initialise(&ch); - draw_histogram(&ch, v_variables[i], "HISTOGRAM",&norm,normal); + draw_histogram(&ch, v_variables[i], ft, "HISTOGRAM",&norm,normal); chart_finalise(&ch); } @@ -568,7 +595,7 @@ postcalc (void *aux UNUSED) chart_initialise(&ch); - draw_piechart(&ch, v_variables[i]); + draw_piechart(&ch, v_variables[i], ft); chart_finalise(&ch); } @@ -624,9 +651,9 @@ postprocess_freq_tab (struct variable *v) struct freq *freqs, *f; size_t i; - assert (v->p.frq.tab.mode == FRQM_GENERAL); + ft = &get_var_freqs (v)->tab; + assert (ft->mode == FRQM_GENERAL); compare = get_freq_comparator (cmd.sort, v->type); - ft = &v->p.frq.tab; /* Extract data from hash table. */ count = hsh_count (ft->data); @@ -672,9 +699,10 @@ postprocess_freq_tab (struct variable *v) static void cleanup_freq_tab (struct variable *v) { - assert (v->p.frq.tab.mode == FRQM_GENERAL); - free (v->p.frq.tab.valid); - hsh_destroy (v->p.frq.tab.data); + struct freq_tab *ft = &get_var_freqs (v)->tab; + assert (ft->mode == FRQM_GENERAL); + free (ft->valid); + hsh_destroy (ft->data); } /* Parses the VARIABLES subcommand, adding to @@ -697,9 +725,6 @@ frq_custom_variables (struct cmd_frequencies *cmd UNUSED) PV_APPEND | PV_NO_SCRATCH)) return 0; - for (i = old_n_variables; i < n_variables; i++) - v_variables[i]->p.frq.tab.mode = FRQM_GENERAL; - if (!lex_match ('(')) mode = FRQM_GENERAL; else @@ -728,42 +753,40 @@ frq_custom_variables (struct cmd_frequencies *cmd UNUSED) for (i = old_n_variables; i < n_variables; i++) { struct variable *v = v_variables[i]; + struct var_freqs *vf; - if (v->p.frq.used != 0) + if (v->aux != NULL) { msg (SE, _("Variable %s specified multiple times on VARIABLES " "subcommand."), v->name); return 0; } - - v->p.frq.used = 1; /* Used simply as a marker. */ - - v->p.frq.tab.valid = v->p.frq.tab.missing = NULL; + if (mode == FRQM_INTEGER && v->type != NUMERIC) + { + msg (SE, _("Integer mode specified, but %s is not a numeric " + "variable."), v->name); + return 0; + } + vf = var_attach_aux (v, xmalloc (sizeof *vf), var_dtor_free); + vf->tab.mode = mode; + vf->tab.valid = vf->tab.missing = NULL; if (mode == FRQM_INTEGER) { - if (v->type != NUMERIC) - { - msg (SE, _("Integer mode specified, but %s is not a numeric " - "variable."), v->name); - return 0; - } - - v->p.frq.tab.min = min; - v->p.frq.tab.max = max; - v->p.frq.tab.vector = pool_alloc (int_pool, - sizeof (struct freq) * (max - min + 1)); + vf->tab.min = min; + vf->tab.max = max; + vf->tab.vector = pool_alloc (int_pool, + sizeof (struct freq) * (max - min + 1)); } else - v->p.frq.tab.vector = NULL; - - v->p.frq.n_groups = 0; - v->p.frq.groups = NULL; + vf->tab.vector = NULL; + vf->n_groups = 0; + vf->groups = NULL; } return 1; } -/* Parses the GROUPED subcommand, setting the frq.{n_grouped,grouped} +/* Parses the GROUPED subcommand, setting the n_grouped, grouped fields of specified variables. */ static int frq_custom_grouped (struct cmd_frequencies *cmd UNUSED) @@ -817,19 +840,22 @@ frq_custom_grouped (struct cmd_frequencies *cmd UNUSED) } for (i = 0; i < n; i++) - { - if (v[i]->p.frq.used == 0) - msg (SE, _("Variables %s specified on GROUPED but not on " - "VARIABLES."), v[i]->name); - if (v[i]->p.frq.groups != NULL) - msg (SE, _("Variables %s specified multiple times on GROUPED " - "subcommand."), v[i]->name); - else - { - v[i]->p.frq.n_groups = nl; - v[i]->p.frq.groups = dl; - } - } + if (v[i]->aux == NULL) + msg (SE, _("Variables %s specified on GROUPED but not on " + "VARIABLES."), v[i]->name); + else + { + struct var_freqs *vf = get_var_freqs (v[i]); + + if (vf->groups != NULL) + msg (SE, _("Variables %s specified multiple times on GROUPED " + "subcommand."), v[i]->name); + else + { + vf->n_groups = nl; + vf->groups = dl; + } + } free (v); if (!lex_match ('/')) break; @@ -1032,9 +1058,10 @@ full_dim (struct tab_table *t, struct outp_driver *d) /* Displays a full frequency table for variable V. */ static void -dump_full (struct variable * v) +dump_full (struct variable *v) { int n_categories; + struct freq_tab *ft; struct freq *f; struct tab_table *t; int r; @@ -1067,7 +1094,8 @@ dump_full (struct variable * v) int lab = cmd.labels == FRQ_LABELS; - n_categories = v->p.frq.tab.n_valid + v->p.frq.tab.n_missing; + ft = &get_var_freqs (v)->tab; + n_categories = ft->n_valid + ft->n_missing; t = tab_create (5 + lab, n_categories + 3, 0); tab_headers (t, 0, 0, 2, 0); tab_dim (t, full_dim); @@ -1079,14 +1107,14 @@ dump_full (struct variable * v) TAB_CENTER | TAT_TITLE, gettext (p->s)); r = 2; - for (f = v->p.frq.tab.valid; f < v->p.frq.tab.missing; f++) + for (f = ft->valid; f < ft->missing; f++) { double percent, valid_percent; cum_freq += f->c; - percent = f->c / v->p.frq.tab.total_cases * 100.0; - valid_percent = f->c / v->p.frq.tab.valid_cases * 100.0; + percent = f->c / ft->total_cases * 100.0; + valid_percent = f->c / ft->valid_cases * 100.0; cum_total += valid_percent; if (lab) @@ -1103,7 +1131,7 @@ dump_full (struct variable * v) tab_float (t, 4 + lab, r, TAB_NONE, cum_total, 5, 1); r++; } - for (; f < &v->p.frq.tab.valid[n_categories]; f++) + for (; f < &ft->valid[n_categories]; f++) { cum_freq += f->c; @@ -1117,7 +1145,7 @@ dump_full (struct variable * v) tab_value (t, 0 + lab, r, TAB_NONE, &f->v, &v->print); tab_float (t, 1 + lab, r, TAB_NONE, f->c, 8, 0); tab_float (t, 2 + lab, r, TAB_NONE, - f->c / v->p.frq.tab.total_cases * 100.0, 5, 1); + f->c / ft->total_cases * 100.0, 5, 1); tab_text (t, 3 + lab, r, TAB_NONE, _("Missing")); r++; } @@ -1159,15 +1187,17 @@ condensed_dim (struct tab_table *t, struct outp_driver *d) /* Display condensed frequency table for variable V. */ static void -dump_condensed (struct variable * v) +dump_condensed (struct variable *v) { int n_categories; + struct freq_tab *ft; struct freq *f; struct tab_table *t; int r; double cum_total = 0.0; - n_categories = v->p.frq.tab.n_valid + v->p.frq.tab.n_missing; + ft = &get_var_freqs (v)->tab; + n_categories = ft->n_valid + ft->n_missing; t = tab_create (4, n_categories + 2, 0); tab_headers (t, 0, 0, 2, 0); @@ -1179,12 +1209,12 @@ dump_condensed (struct variable * v) tab_dim (t, condensed_dim); r = 2; - for (f = v->p.frq.tab.valid; f < v->p.frq.tab.missing; f++) + for (f = ft->valid; f < ft->missing; f++) { double percent; - percent = f->c / v->p.frq.tab.total_cases * 100.0; - cum_total += f->c / v->p.frq.tab.valid_cases * 100.0; + percent = f->c / ft->total_cases * 100.0; + cum_total += f->c / ft->valid_cases * 100.0; tab_value (t, 0, r, TAB_NONE, &f->v, &v->print); tab_float (t, 1, r, TAB_NONE, f->c, 8, 0); @@ -1192,12 +1222,12 @@ dump_condensed (struct variable * v) tab_float (t, 3, r, TAB_NONE, cum_total, 3, 0); r++; } - for (; f < &v->p.frq.tab.valid[n_categories]; f++) + for (; f < &ft->valid[n_categories]; f++) { tab_value (t, 0, r, TAB_NONE, &f->v, &v->print); tab_float (t, 1, r, TAB_NONE, f->c, 8, 0); tab_float (t, 2, r, TAB_NONE, - f->c / v->p.frq.tab.total_cases * 100.0, 3, 0); + f->c / ft->total_cases * 100.0, 3, 0); r++; } @@ -1215,9 +1245,10 @@ dump_condensed (struct variable * v) /* Calculates all the pertinent statistics for variable V, putting them in array D[]. FIXME: This could be made much more optimal. */ static void -calc_stats (struct variable * v, double d[frq_n_stats]) +calc_stats (struct variable *v, double d[frq_n_stats]) { - double W = v->p.frq.tab.valid_cases; + struct freq_tab *ft = &get_var_freqs (v)->tab; + double W = ft->valid_cases; struct moments *m; struct freq *f=0; int most_often; @@ -1255,10 +1286,10 @@ calc_stats (struct variable * v, double d[frq_n_stats]) } rank = 0; - for (idx = 0; idx < v->p.frq.tab.n_valid; ++idx) + for (idx = 0; idx < ft->n_valid; ++idx) { static double prev_value = SYSMIS; - f = &v->p.frq.tab.valid[idx]; + f = &ft->valid[idx]; rank += f->c ; for (i = 0; i < n_percentiles; i++) { @@ -1267,10 +1298,10 @@ calc_stats (struct variable * v, double d[frq_n_stats]) if ( get_algorithm() != COMPATIBLE ) tp = - (v->p.frq.tab.valid_cases - 1) * percentiles[i].p; + (ft->valid_cases - 1) * percentiles[i].p; else tp = - (v->p.frq.tab.valid_cases + 1) * percentiles[i].p - 1; + (ft->valid_cases + 1) * percentiles[i].p - 1; if ( percentiles[i].flag ) { @@ -1312,17 +1343,17 @@ calc_stats (struct variable * v, double d[frq_n_stats]) for (i = 0; i < n_percentiles; i++) { - struct freq_tab *ft = &v->p.frq.tab; + struct freq_tab *ft = &get_var_freqs (v)->tab; double s; double dummy; if ( get_algorithm() != COMPATIBLE ) { - s = modf((ft->valid_cases - 1) * percentiles[i].p , &dummy); + s = modf((ft->valid_cases - 1) * percentiles[i].p , &dummy); } else { - s = modf((ft->valid_cases + 1) * percentiles[i].p -1, &dummy); + s = modf((ft->valid_cases + 1) * percentiles[i].p -1, &dummy); } percentiles[i].value = percentiles[i].x1 + @@ -1336,7 +1367,7 @@ calc_stats (struct variable * v, double d[frq_n_stats]) /* Calculate the mode. */ most_often = -1; X_mode = SYSMIS; - for (f = v->p.frq.tab.valid; f < v->p.frq.tab.missing; f++) + for (f = ft->valid; f < ft->missing; f++) { if (most_often < f->c) { @@ -1353,17 +1384,17 @@ calc_stats (struct variable * v, double d[frq_n_stats]) /* Calculate moments. */ m = moments_create (MOMENT_KURTOSIS); - for (f = v->p.frq.tab.valid; f < v->p.frq.tab.missing; f++) + for (f = ft->valid; f < ft->missing; f++) moments_pass_one (m, f->v.f, f->c); - for (f = v->p.frq.tab.valid; f < v->p.frq.tab.missing; f++) + for (f = ft->valid; f < ft->missing; f++) moments_pass_two (m, f->v.f, f->c); moments_calculate (m, NULL, &d[frq_mean], &d[frq_variance], &d[frq_skew], &d[frq_kurt]); moments_destroy (m); /* Formulas below are taken from _SPSS Statistical Algorithms_. */ - d[frq_min] = v->p.frq.tab.valid[0].v.f; - d[frq_max] = v->p.frq.tab.valid[v->p.frq.tab.n_valid - 1].v.f; + d[frq_min] = ft->valid[0].v.f; + d[frq_max] = ft->valid[ft->n_valid - 1].v.f; d[frq_mode] = X_mode; d[frq_range] = d[frq_max] - d[frq_min]; d[frq_median] = *median_value; @@ -1376,8 +1407,9 @@ calc_stats (struct variable * v, double d[frq_n_stats]) /* Displays a table of all the statistics requested for variable V. */ static void -dump_statistics (struct variable * v, int show_varname) +dump_statistics (struct variable *v, int show_varname) { + struct freq_tab *ft; double stat_value[frq_n_stats]; struct tab_table *t; int i, r; @@ -1389,7 +1421,8 @@ dump_statistics (struct variable * v, int show_varname) if (v->type == ALPHA) return; - if (v->p.frq.tab.n_valid == 0) + ft = &get_var_freqs (v)->tab; + if (ft->n_valid == 0) { msg (SW, _("No valid data for variable %s; statistics not displayed."), v->name); @@ -1421,9 +1454,8 @@ dump_statistics (struct variable * v, int show_varname) tab_text (t, 1, 0, TAB_LEFT | TAT_TITLE, _("Valid")); tab_text (t, 1, 1, TAB_LEFT | TAT_TITLE, _("Missing")); - tab_float(t, 2, 0, TAB_NONE, v->p.frq.tab.valid_cases, 11, 0); - tab_float(t, 2, 1, TAB_NONE, - v->p.frq.tab.total_cases - v->p.frq.tab.valid_cases, 11, 0); + tab_float(t, 2, 0, TAB_NONE, ft->valid_cases, 11, 0); + tab_float(t, 2, 1, TAB_NONE, ft->total_cases - ft->valid_cases, 11, 0); for (i = 0; i < n_explicit_percentiles; i++, r++) diff --git a/src/get.c b/src/get.c index dc16d7a5..8f98dea4 100644 --- a/src/get.c +++ b/src/get.c @@ -23,14 +23,17 @@ #include "alloc.h" #include "case.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "file-handle.h" #include "hash.h" #include "lexer.h" #include "misc.h" -#include "pfm.h" +#include "pfm-read.h" +#include "pfm-write.h" #include "settings.h" -#include "sfm.h" +#include "sfm-read.h" +#include "sfm-write.h" #include "str.h" #include "value-labels.h" #include "var.h" @@ -39,192 +42,237 @@ #include "debug-print.h" -/* GET or IMPORT input program. */ -struct get_pgm +/* Rearranging and reducing a dictionary. */ +static void start_case_map (struct dictionary *); +static struct case_map *finish_case_map (struct dictionary *); +static void map_case (const struct case_map *, + const struct ccase *, struct ccase *); +static void destroy_case_map (struct case_map *); + +/* Operation type. */ +enum operation { - struct file_handle *handle; /* File to GET or IMPORT from. */ - size_t case_size; /* Case size in bytes. */ + OP_READ, /* GET or IMPORT. */ + OP_SAVE, /* SAVE or XSAVE. */ + OP_EXPORT, /* EXPORT. */ + OP_MATCH /* MATCH FILES. */ }; -/* XSAVE transformation (and related SAVE, EXPORT procedures). */ -struct save_trns +static int trim_dictionary (struct dictionary *, + enum operation, int *compress); + +/* GET input program. */ +struct get_pgm { - struct trns_header h; - struct file_handle *f; /* Associated system file. */ - int nvar; /* Number of variables. */ - struct variable **var; /* Variables. */ - flt64 *case_buf; /* Case transfer buffer. */ + struct sfm_reader *reader; /* System file reader. */ + struct case_map *map; /* Map from system file to active file dict. */ + struct ccase bounce; /* Bounce buffer. */ }; -/* Options bits set by trim_dictionary(). */ -#define GTSV_OPT_COMPRESSED 001 /* Compression; (X)SAVE only. */ -#define GTSV_OPT_SAVE 002 /* The SAVE/XSAVE/EXPORT procedures. */ -#define GTSV_OPT_MATCH_FILES 004 /* The MATCH FILES procedure. */ -#define GTSV_OPT_NONE 0 - -static int trim_dictionary (struct dictionary * dict, int *options); -static int save_write_case_func (struct ccase *, void *); -static trns_proc_func save_trns_proc; -static trns_free_func save_trns_free; +static void get_pgm_free (struct get_pgm *); /* Parses the GET command. */ int cmd_get (void) { - struct file_handle *handle; - struct dictionary *dict; - struct get_pgm *pgm; - int options = GTSV_OPT_NONE; + struct get_pgm *pgm = NULL; + struct file_handle *fh; + struct dictionary *dict = NULL; + + pgm = xmalloc (sizeof *pgm); + pgm->reader = NULL; + pgm->map = NULL; + case_nullify (&pgm->bounce); discard_variables (); lex_match ('/'); if (lex_match_id ("FILE")) lex_match ('='); + fh = fh_parse (); + if (fh == NULL) + goto error; - handle = fh_parse_file_handle (); - if (handle == NULL) - return CMD_FAILURE; - - dict = sfm_read_dictionary (handle, NULL); - if (dict == NULL) - return CMD_FAILURE; - - if (0 == trim_dictionary (dict, &options)) - { - fh_close_handle (handle); - return CMD_FAILURE; - } + pgm->reader = sfm_open_reader (fh, &dict, NULL); + if (pgm->reader == NULL) + goto error; + case_create (&pgm->bounce, dict_get_next_value_idx (dict)); - dict_compact_values (dict); + start_case_map (dict); + if (!trim_dictionary (dict, OP_READ, NULL)) + goto error; + pgm->map = finish_case_map (dict); dict_destroy (default_dict); default_dict = dict; - pgm = xmalloc (sizeof *pgm); - pgm->handle = handle; - pgm->case_size = dict_get_case_size (default_dict); vfm_source = create_case_source (&get_source_class, default_dict, pgm); return CMD_SUCCESS; + + error: + get_pgm_free (pgm); + if (dict != NULL) + dict_destroy (dict); + return CMD_FAILURE; } -/* SAVE or XSAVE command? */ -enum save_cmd - { - CMD_SAVE, - CMD_XSAVE - }; +/* Frees a struct get_pgm. */ +static void +get_pgm_free (struct get_pgm *pgm) +{ + if (pgm != NULL) + { + sfm_close_reader (pgm->reader); + destroy_case_map (pgm->map); + case_destroy (&pgm->bounce); + free (pgm); + } +} -/* Parses the SAVE and XSAVE commands. */ -static int -cmd_save_internal (enum save_cmd save_cmd) +/* Clears internal state related to GET input procedure. */ +static void +get_source_destroy (struct case_source *source) { - struct file_handle *handle; - struct dictionary *dict; - int options = GTSV_OPT_SAVE; + struct get_pgm *pgm = source->aux; + get_pgm_free (pgm); +} - struct save_trns *t; - struct sfm_write_info inf; +/* 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) +{ + struct get_pgm *pgm = source->aux; + int ok; - int i; + do + { + if (pgm->map == NULL) + ok = sfm_read_case (pgm->reader, c); + else + { + ok = sfm_read_case (pgm->reader, &pgm->bounce); + if (ok) + map_case (pgm->map, &pgm->bounce, c); + } - lex_match ('/'); - if (lex_match_id ("OUTFILE")) - lex_match ('='); + if (ok) + ok = write_case (wc_data); + } + while (ok); +} - handle = fh_parse_file_handle (); - if (handle == NULL) - return CMD_FAILURE; +const struct case_source_class get_source_class = + { + "GET", + NULL, + get_source_read, + get_source_destroy, + }; + +/* XSAVE transformation and SAVE procedure. */ +struct save_trns + { + struct trns_header h; + struct sfm_writer *writer; /* System file writer. */ + struct case_map *map; /* Map from active file to system file dict. */ + struct ccase bounce; /* Bounce buffer. */ + }; - dict = dict_clone (default_dict); - for (i = 0; i < dict_get_var_cnt (dict); i++) - dict_get_var (dict, i)->aux = dict_get_var (default_dict, i); - if (0 == trim_dictionary (dict, &options)) - { - fh_close_handle (handle); - return CMD_FAILURE; - } +static int save_write_case_func (struct ccase *, void *); +static trns_proc_func save_trns_proc; +static trns_free_func save_trns_free; - /* Write dictionary. */ - inf.h = handle; - inf.dict = dict; - inf.compress = !!(options & GTSV_OPT_COMPRESSED); - if (!sfm_write_dictionary (&inf)) - { - dict_destroy (dict); - fh_close_handle (handle); - return CMD_FAILURE; - } +/* Parses the SAVE or XSAVE command + and returns the parsed transformation. */ +static struct save_trns * +cmd_save_internal (void) +{ + struct file_handle *fh; + struct dictionary *dict = NULL; + struct save_trns *t = NULL; + int compress = get_scompression (); - /* Fill in transformation structure. */ t = xmalloc (sizeof *t); t->h.proc = save_trns_proc; t->h.free = save_trns_free; - t->f = handle; - t->nvar = dict_get_var_cnt (dict); - t->var = xmalloc (sizeof *t->var * t->nvar); - for (i = 0; i < t->nvar; i++) - t->var[i] = dict_get_var (dict, i)->aux; - t->case_buf = xmalloc (sizeof *t->case_buf * inf.case_size); + t->writer = NULL; + t->map = NULL; + case_nullify (&t->bounce); + + lex_match ('/'); + if (lex_match_id ("OUTFILE")) + lex_match ('='); + fh = fh_parse (); + if (fh == NULL) + goto error; + + dict = dict_clone (default_dict); + start_case_map (dict); + if (!trim_dictionary (dict, OP_SAVE, &compress)) + goto error; + t->map = finish_case_map (dict); + if (t->map != NULL) + case_create (&t->bounce, dict_get_next_value_idx (dict)); + + t->writer = sfm_open_writer (fh, dict, compress); + if (t->writer == NULL) + goto error; + dict_destroy (dict); - if (save_cmd == CMD_SAVE) - { - procedure (save_write_case_func, t); - save_trns_free (&t->h); - } - else - { - assert (save_cmd == CMD_XSAVE); - add_transformation (&t->h); - } + return t; - return CMD_SUCCESS; + error: + assert (t != NULL); + dict_destroy (dict); + save_trns_free (&t->h); + return NULL; } /* Parses and performs the SAVE procedure. */ int cmd_save (void) { - return cmd_save_internal (CMD_SAVE); + struct save_trns *t = cmd_save_internal (); + if (t != NULL) + { + procedure (save_write_case_func, t); + save_trns_free (&t->h); + return CMD_SUCCESS; + } + else + return CMD_FAILURE; } /* Parses the XSAVE transformation command. */ int cmd_xsave (void) { - return cmd_save_internal (CMD_XSAVE); + struct save_trns *t = cmd_save_internal (); + if (t != NULL) + { + add_transformation (&t->h); + return CMD_SUCCESS; + } + else + return CMD_FAILURE; } /* Writes the given C to the file specified by T. */ static void do_write_case (struct save_trns *t, struct ccase *c) { - flt64 *p = t->case_buf; - int i; - - for (i = 0; i < t->nvar; i++) + if (t->map == NULL) + sfm_write_case (t->writer, c); + else { - struct variable *v = t->var[i]; - if (v->type == NUMERIC) - { - double src = case_num (c, v->fv); - if (src == SYSMIS) - *p++ = -FLT64_MAX; - else - *p++ = src; - } - else - { - memcpy (p, case_str (c, v->fv), v->width); - memset (&((char *) p)[v->width], ' ', - REM_RND_UP (v->width, sizeof *p)); - p += DIV_RND_UP (v->width, sizeof *p); - } + map_case (t->map, c, &t->bounce); + sfm_write_case (t->writer, &t->bounce); } - - sfm_write_case (t->f, t->case_buf, p - t->case_buf); } /* Writes case C to the system file specified on SAVE. */ @@ -246,33 +294,39 @@ save_trns_proc (struct trns_header *h, struct ccase *c, int case_num UNUSED) /* Frees a SAVE transformation. */ static void -save_trns_free (struct trns_header *pt) +save_trns_free (struct trns_header *t_) { - struct save_trns *t = (struct save_trns *) pt; + struct save_trns *t = (struct save_trns *) t_; - fh_close_handle (t->f); - free (t->var); - free (t->case_buf); - free (t); + if (t != NULL) + { + sfm_close_writer (t->writer); + destroy_case_map (t->map); + case_destroy (&t->bounce); + } } -static int rename_variables (struct dictionary * dict); +static int rename_variables (struct dictionary *dict); + +/* Commands that read and write system files share a great deal + of common syntactic structure for rearranging and dropping + variables. This function parses this syntax and modifies DICT + appropriately. -/* The GET and SAVE commands have a common structure after the - FILE/OUTFILE subcommand. This function parses this structure and - returns nonzero on success, zero on failure. It both reads - *OPTIONS, for the GTSV_OPT_SAVE bit, and writes it, for the - GTSV_OPT_COMPRESSED bit. */ + OP is the operation being performed. For operations that + write a system file, *COMPRESS is set to 1 if the system file + should be compressed, 0 otherwise. + + Returns nonzero on success, zero on failure. */ /* FIXME: IN, FIRST, LAST, MAP. */ -/* FIXME? Should we call dict_compact_values() on dict as a - final step? */ static int -trim_dictionary (struct dictionary *dict, int *options) +trim_dictionary (struct dictionary *dict, enum operation op, int *compress) { + assert ((compress != NULL) == (op == OP_SAVE)); if (get_scompression()) - *options |= GTSV_OPT_COMPRESSED; + *compress = 1; - if (*options & GTSV_OPT_SAVE) + if (op == OP_SAVE || op == OP_EXPORT) { /* Delete all the scratch variables. */ struct variable **v; @@ -288,12 +342,12 @@ trim_dictionary (struct dictionary *dict, int *options) free (v); } - while ((*options & GTSV_OPT_MATCH_FILES) || lex_match ('/')) + while (op == OP_MATCH || lex_match ('/')) { - if (!(*options & GTSV_OPT_MATCH_FILES) && lex_match_id ("COMPRESSED")) - *options |= GTSV_OPT_COMPRESSED; - else if (!(*options & GTSV_OPT_MATCH_FILES) && lex_match_id ("UNCOMPRESSED")) - *options &= ~GTSV_OPT_COMPRESSED; + if (op == OP_SAVE && lex_match_id ("COMPRESSED")) + *compress = 1; + else if (op == OP_SAVE && lex_match_id ("UNCOMPRESSED")) + *compress = 0; else if (lex_match_id ("DROP")) { struct variable **v; @@ -342,8 +396,8 @@ trim_dictionary (struct dictionary *dict, int *options) return 0; } - if (*options & GTSV_OPT_MATCH_FILES) - return 1; + if (op == OP_MATCH) + goto success; } if (token != '.') @@ -351,13 +405,16 @@ trim_dictionary (struct dictionary *dict, int *options) lex_error (_("expecting end of command")); return 0; } - + + success: + if (op != OP_MATCH) + dict_compact_values (dict); return 1; } /* Parses and performs the RENAME subcommand of GET and SAVE. */ static int -rename_variables (struct dictionary * dict) +rename_variables (struct dictionary *dict) { int i; @@ -444,40 +501,88 @@ done: return success; } -/* Clears internal state related to GET input procedure. */ -static void -get_source_destroy (struct case_source *source) +/* EXPORT procedure. */ +struct export_proc + { + struct pfm_writer *writer; /* System file writer. */ + struct case_map *map; /* Map from active file to system file dict. */ + struct ccase bounce; /* Bounce buffer. */ + }; + +static int export_write_case_func (struct ccase *, void *); +static void export_proc_free (struct export_proc *); + +/* Parses the EXPORT command. */ +/* FIXME: same as cmd_save_internal(). */ +int +cmd_export (void) { - struct get_pgm *pgm = source->aux; + struct file_handle *fh; + struct dictionary *dict; + struct export_proc *proc; - /* It is not necessary to destroy the dictionary because if we get - to this point then the dictionary is default_dict. */ - fh_close_handle (pgm->handle); - free (pgm); -} + proc = xmalloc (sizeof *proc); + proc->writer = NULL; + proc->map = NULL; + case_nullify (&proc->bounce); -/* 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) -{ - struct get_pgm *pgm = source->aux; + lex_match ('/'); + if (lex_match_id ("OUTFILE")) + lex_match ('='); + fh = fh_parse (); + if (fh == NULL) + return CMD_FAILURE; - while (sfm_read_case (pgm->handle, c, default_dict) - && write_case (wc_data)) - ; + dict = dict_clone (default_dict); + start_case_map (dict); + if (!trim_dictionary (dict, OP_EXPORT, NULL)) + goto error; + proc->map = finish_case_map (dict); + if (proc->map != NULL) + case_create (&proc->bounce, dict_get_next_value_idx (dict)); + + proc->writer = pfm_open_writer (fh, dict); + if (proc->writer == NULL) + goto error; + + dict_destroy (dict); + + procedure (export_write_case_func, proc); + export_proc_free (proc); + + return CMD_SUCCESS; + + error: + dict_destroy (dict); + export_proc_free (proc); + return CMD_FAILURE; } -const struct case_source_class get_source_class = - { - "GET", - NULL, - get_source_read, - get_source_destroy, - }; +/* Writes case C to the EXPORT file. */ +static int +export_write_case_func (struct ccase *c, void *aux) +{ + struct export_proc *proc = aux; + if (proc->map == NULL) + pfm_write_case (proc->writer, c); + else + { + map_case (proc->map, c, &proc->bounce); + pfm_write_case (proc->writer, &proc->bounce); + } + return 1; +} +static void +export_proc_free (struct export_proc *proc) +{ + if (proc != NULL) + { + pfm_close_writer (proc->writer); + destroy_case_map (proc->map); + case_destroy (&proc->bounce); + } +} /* MATCH FILES. */ @@ -499,7 +604,8 @@ struct mtf_file int type; /* One of MTF_*. */ struct variable **by; /* List of BY variables for this file. */ - struct file_handle *handle; /* File handle for the file. */ + struct file_handle *handle; /* File handle. */ + struct sfm_reader *reader; /* System file reader. */ struct dictionary *dict; /* Dictionary from system file. */ char in[9]; /* Name of the variable from IN=. */ char first[9], last[9]; /* Name of the variables from FIRST=, LAST=. */ @@ -534,12 +640,16 @@ static int mtf_processing (struct ccase *, void *); static char *var_type_description (struct variable *); +static void set_master (struct variable *, struct variable *master); +static struct variable *get_master (struct variable *); + /* Parse and execute the MATCH FILES command. */ int cmd_match_files (void) { struct mtf_proc mtf; struct mtf_file *first_table = NULL; + struct mtf_file *iter; int seen = 0; @@ -562,29 +672,24 @@ cmd_match_files (void) if (seen & 1) { msg (SE, _("The BY subcommand may be given once at most.")); - goto lossage; + goto error; } seen |= 1; lex_match ('='); if (!parse_variables (mtf.dict, &mtf.by, &mtf.by_cnt, PV_NO_DUPLICATE | PV_NO_SCRATCH)) - goto lossage; + goto error; } else if (token != T_ID) { lex_error (NULL); - goto lossage; + goto error; } else if (lex_id_match ("FILE", tokid) || lex_id_match ("TABLE", tokid)) { struct mtf_file *file = xmalloc (sizeof *file); - file->in[0] = file->first[0] = file->last[0] = '\0'; - file->dict = NULL; - file->by = NULL; - case_nullify (&file->input); - if (lex_match_id ("FILE")) file->type = MTF_FILE; else if (lex_match_id ("TABLE")) @@ -595,6 +700,15 @@ cmd_match_files (void) else assert (0); + file->by = NULL; + file->handle = NULL; + file->reader = NULL; + file->dict = NULL; + file->in[0] = '\0'; + file->first[0] = '\0'; + file->last[0] = '\0'; + case_nullify (&file->input); + /* FILEs go first, then TABLEs. */ if (file->type == MTF_TABLE || first_table == NULL) { @@ -624,13 +738,14 @@ cmd_match_files (void) if (lex_match ('*')) { - file->handle = NULL; - + file->handle = NULL; + file->reader = NULL; + if (seen & 2) { msg (SE, _("The active file may not be specified more " "than once.")); - goto lossage; + goto error; } seen |= 2; @@ -639,7 +754,7 @@ cmd_match_files (void) { msg (SE, _("Cannot specify the active file since no active " "file has been defined.")); - goto lossage; + goto error; } if (temporary != 0) @@ -650,25 +765,21 @@ cmd_match_files (void) "Temporary transformations will be made permanent.")); cancel_temporary (); } + + file->dict = default_dict; } else { - file->handle = fh_parse_file_handle (); - if (!file->handle) - goto lossage; - } + file->handle = fh_parse (); + if (file->handle == NULL) + goto error; + + file->reader = sfm_open_reader (file->handle, &file->dict, NULL); + if (file->reader == NULL) + goto error; - if (file->handle) - { - file->dict = sfm_read_dictionary (file->handle, NULL); - if (!file->dict) - goto lossage; case_create (&file->input, dict_get_next_value_idx (file->dict)); } - else - file->dict = default_dict; - if (!mtf_merge_dictionary (mtf.dict, file)) - goto lossage; } else if (lex_id_match ("IN", tokid) || lex_id_match ("FIRST", tokid) @@ -681,7 +792,7 @@ cmd_match_files (void) { msg (SE, _("IN, FIRST, and LAST subcommands may not occur " "before the first FILE or TABLE.")); - goto lossage; + goto error; } if (lex_match_id ("IN")) @@ -709,7 +820,7 @@ cmd_match_files (void) if (token != T_ID) { lex_error (NULL); - goto lossage; + goto error; } if (*name) @@ -717,7 +828,7 @@ cmd_match_files (void) msg (SE, _("Multiple %s subcommands for a single FILE or " "TABLE."), sbc); - goto lossage; + goto error; } strcpy (name, tokid); lex_get (); @@ -727,24 +838,22 @@ cmd_match_files (void) msg (SE, _("Duplicate variable name %s while creating %s " "variable."), name, sbc); - goto lossage; + goto error; } } else if (lex_id_match ("RENAME", tokid) || lex_id_match ("KEEP", tokid) || lex_id_match ("DROP", tokid)) { - int options = GTSV_OPT_MATCH_FILES; - if (mtf.tail == NULL) { msg (SE, _("RENAME, KEEP, and DROP subcommands may not occur " "before the first FILE or TABLE.")); - goto lossage; + goto error; } - if (!trim_dictionary (mtf.tail->dict, &options)) - goto lossage; + if (!trim_dictionary (mtf.tail->dict, OP_MATCH, NULL)) + goto error; } else if (lex_match_id ("MAP")) { @@ -753,26 +862,27 @@ cmd_match_files (void) else { lex_error (NULL); - goto lossage; + goto error; } } while (token != '.'); + for (iter = mtf.head; iter != NULL; iter = iter->next) + mtf_merge_dictionary (mtf.dict, iter); + if (seen & 4) { if (!(seen & 1)) { msg (SE, _("The BY subcommand is required when a TABLE subcommand " "is given.")); - goto lossage; + goto error; } } if (seen & 1) { - struct mtf_file *iter; - - for (iter = mtf.head; iter; iter = iter->next) + for (iter = mtf.head; iter != NULL; iter = iter->next) { int i; @@ -786,7 +896,7 @@ cmd_match_files (void) msg (SE, _("File %s lacks BY variable %s."), iter->handle ? handle_get_name (iter->handle) : "*", mtf.by[i]->name); - goto lossage; + goto error; } } } @@ -852,7 +962,7 @@ cmd_match_files (void) mtf_free (&mtf); return CMD_SUCCESS; -lossage: +error: mtf_free (&mtf); return CMD_FAILURE; } @@ -903,12 +1013,11 @@ var_type_description (struct variable *v) static void mtf_free_file (struct mtf_file *file) { - fh_close_handle (file->handle); - if (file->dict != NULL && file->dict != default_dict) - dict_destroy (file->dict); free (file->by); - if (file->handle) - case_destroy (&file->input); + sfm_close_reader (file->reader); + if (file->dict != default_dict) + dict_destroy (file->dict); + case_destroy (&file->input); free (file); } @@ -954,7 +1063,7 @@ mtf_delete_file_in_place (struct mtf_proc *mtf, struct mtf_file **file) for (i = 0; i < dict_get_var_cnt (f->dict); i++) { struct variable *v = dict_get_var (f->dict, i); - union value *out = case_data_rw (mtf->mtf_case, v->p.mtf.master->fv); + union value *out = case_data_rw (mtf->mtf_case, get_master (v)->fv); if (v->type == NUMERIC) out->f = SYSMIS; @@ -977,7 +1086,7 @@ mtf_read_nonactive_records (void *mtf_ UNUSED) { if (iter->handle) { - if (!sfm_read_case (iter->handle, &iter->input, iter->dict)) + if (!sfm_read_case (iter->reader, &iter->input)) mtf_delete_file_in_place (mtf, &iter); else iter = iter->next; @@ -1121,7 +1230,7 @@ mtf_processing (struct ccase *c, void *mtf_ UNUSED) case 1: if (iter->handle == NULL) return 1; - if (sfm_read_case (iter->handle, &iter->input, iter->dict)) + if (sfm_read_case (iter->reader, &iter->input)) goto again; mtf_delete_file_in_place (mtf, &iter); break; @@ -1149,14 +1258,14 @@ mtf_processing (struct ccase *c, void *mtf_ UNUSED) struct ccase *record; union value *out; - if (mtf->seq_nums[v->p.mtf.master->index] == mtf->seq_num) + if (mtf->seq_nums[get_master (v)->index] == mtf->seq_num) continue; - mtf->seq_nums[v->p.mtf.master->index] = mtf->seq_num; + mtf->seq_nums[get_master (v)->index] = mtf->seq_num; record = case_is_null (&iter->input) ? c : &iter->input; assert (v->type == NUMERIC || v->type == ALPHA); - out = case_data_rw (mtf->mtf_case, v->p.mtf.master->fv); + out = case_data_rw (mtf->mtf_case, get_master (v)->fv); if (v->type == NUMERIC) out->f = case_num (record, v->fv); else @@ -1176,11 +1285,11 @@ mtf_processing (struct ccase *c, void *mtf_ UNUSED) struct variable *v = dict_get_var (iter->dict, i); union value *out; - if (mtf->seq_nums[v->p.mtf.master->index] == mtf->seq_num) + if (mtf->seq_nums[get_master (v)->index] == mtf->seq_num) continue; - mtf->seq_nums[v->p.mtf.master->index] = mtf->seq_num; + mtf->seq_nums[get_master (v)->index] = mtf->seq_num; - out = case_data_rw (mtf->mtf_case, v->p.mtf.master->fv); + out = case_data_rw (mtf->mtf_case, get_master (v)->fv); if (v->type == NUMERIC) out->f = SYSMIS; else @@ -1202,9 +1311,9 @@ mtf_processing (struct ccase *c, void *mtf_ UNUSED) { struct mtf_file *next = iter->next_min; - if (iter->handle) + if (iter->reader != NULL) { - if (!sfm_read_case (iter->handle, &iter->input, iter->dict)) + if (!sfm_read_case (iter->reader, &iter->input)) mtf_delete_file_in_place (mtf, &iter); } @@ -1218,8 +1327,7 @@ mtf_processing (struct ccase *c, void *mtf_ UNUSED) return (mtf->head && mtf->head->type != MTF_TABLE); } -/* Merge the dictionary for file F into the master dictionary - mtf_dict. */ +/* Merge the dictionary for file F into master dictionary M. */ static int mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f) { @@ -1286,25 +1394,55 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f) var_type_description (dv), var_type_description (mv)); return 0; } - dv->p.mtf.master = mv; + set_master (dv, mv); } } return 1; } + +/* Marks V's master variable as MASTER. */ +static void +set_master (struct variable *v, struct variable *master) +{ + var_attach_aux (v, master, NULL); +} + +/* Returns the master variable corresponding to V, + as set with set_master(). */ +static struct variable * +get_master (struct variable *v) +{ + assert (v->aux != NULL); + return v->aux; +} /* 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 file_handle *handle = NULL; - struct dictionary *dict; - struct get_pgm *pgm; - int options = GTSV_OPT_NONE; + struct import_pgm *pgm = NULL; + struct file_handle *fh = NULL; + struct dictionary *dict = NULL; int type; + pgm = xmalloc (sizeof *pgm); + pgm->reader = NULL; + pgm->map = NULL; + case_nullify (&pgm->bounce); + for (;;) { lex_match ('/'); @@ -1313,8 +1451,8 @@ cmd_import (void) { lex_match ('='); - handle = fh_parse_file_handle (); - if (handle == NULL) + fh = fh_parse (); + if (fh == NULL) return CMD_FAILURE; } else if (lex_match_id ("TYPE")) @@ -1341,41 +1479,76 @@ cmd_import (void) discard_variables (); - dict = pfm_read_dictionary (handle, NULL); - if (dict == NULL) + pgm->reader = pfm_open_reader (fh, &dict, NULL); + if (pgm->reader == NULL) return CMD_FAILURE; - - if (0 == trim_dictionary (dict, &options)) - { - fh_close_handle (handle); - return CMD_FAILURE; - } - - dict_compact_values (dict); - + case_create (&pgm->bounce, dict_get_next_value_idx (dict)); + + start_case_map (dict); + if (!trim_dictionary (dict, OP_READ, NULL)) + goto error; + pgm->map = finish_case_map (dict); + dict_destroy (default_dict); default_dict = dict; - pgm = xmalloc (sizeof *pgm); - pgm->handle = handle; - pgm->case_size = dict_get_case_size (default_dict); vfm_source = create_case_source (&import_source_class, default_dict, pgm); return CMD_SUCCESS; + + error: + import_pgm_free (pgm); + if (dict != NULL) + dict_destroy (dict); + return CMD_FAILURE; } -/* Reads all the cases from the data file and passes them to - write_case(). */ +/* 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 ccase *c, + write_case_func *write_case, write_case_data wc_data) { - struct get_pgm *pgm = source->aux; - - while (pfm_read_case (pgm->handle, c, default_dict)) - if (!write_case (wc_data)) - break; + 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 = @@ -1383,85 +1556,128 @@ const struct case_source_class import_source_class = "IMPORT", NULL, import_source_read, - get_source_destroy, + import_source_destroy, }; + -static int export_write_case_func (struct ccase *c, void *); - -/* Parses the EXPORT command. */ -/* FIXME: same as cmd_save_internal(). */ -int -cmd_export (void) -{ - struct file_handle *handle; - struct dictionary *dict; - int options = GTSV_OPT_SAVE; +/* Case map. - struct save_trns *t; + A case map copies data from a case that corresponds for one + dictionary to a case that corresponds to a second dictionary + derived from the first by, optionally, deleting, reordering, + or renaming variables. (No new variables may be created.) + */ - int i; +/* A case map. */ +struct case_map + { + size_t value_cnt; /* Number of values in map. */ + int *map; /* For each destination index, the + corresponding source index. */ + }; - lex_match ('/'); - if (lex_match_id ("OUTFILE")) - lex_match ('='); +/* Prepares dictionary D for producing a case map. Afterward, + the caller may delete, reorder, or rename variables within D + at will before using finish_case_map() to produce the case + map. - handle = fh_parse_file_handle (); - if (handle == NULL) - return CMD_FAILURE; - - dict = dict_clone (default_dict); - for (i = 0; i < dict_get_var_cnt (dict); i++) - dict_get_var (dict, i)->aux = dict_get_var (default_dict, i); - if (0 == trim_dictionary (dict, &options)) + Uses D's aux members, which may not otherwise be in use. */ +static void +start_case_map (struct dictionary *d) +{ + size_t var_cnt = dict_get_var_cnt (d); + size_t i; + + for (i = 0; i < var_cnt; i++) { - fh_close_handle (handle); - return CMD_FAILURE; + struct variable *v = dict_get_var (d, i); + int *src_fv = xmalloc (sizeof *src_fv); + *src_fv = v->fv; + var_attach_aux (v, src_fv, var_dtor_free); } +} + +/* Produces a case map from dictionary D, which must have been + previously prepared with start_case_map(). - /* Write dictionary. */ - if (!pfm_write_dictionary (handle, dict)) + Does not retain any reference to D, and clears the aux members + set up by start_case_map(). + + Returns the new case map, or a null pointer if no mapping is + required (that is, no data has changed position). */ +static struct case_map * +finish_case_map (struct dictionary *d) +{ + struct case_map *map; + size_t var_cnt = dict_get_var_cnt (d); + size_t i; + int identity_map; + + map = xmalloc (sizeof *map); + map->value_cnt = dict_get_next_value_idx (d); + map->map = xmalloc (sizeof *map->map * map->value_cnt); + for (i = 0; i < map->value_cnt; i++) + map->map[i] = -1; + + identity_map = 1; + for (i = 0; i < var_cnt; i++) { - dict_destroy (dict); - fh_close_handle (handle); - return CMD_FAILURE; + struct variable *v = dict_get_var (d, i); + int src_fv = *(int *) var_detach_aux (v); + size_t idx; + + if (v->fv != src_fv) + identity_map = 0; + + for (idx = 0; idx < v->nv; idx++) + { + int src_idx = src_fv + idx; + int dst_idx = v->fv + idx; + + assert (map->map[dst_idx] == -1); + map->map[dst_idx] = src_idx; + } } - /* Fill in transformation structure. */ - t = xmalloc (sizeof *t); - t->h.proc = save_trns_proc; - t->h.free = save_trns_free; - t->f = handle; - t->nvar = dict_get_var_cnt (dict); - t->var = xmalloc (sizeof *t->var * t->nvar); - for (i = 0; i < t->nvar; i++) - t->var[i] = dict_get_var (dict, i)->aux; - t->case_buf = xmalloc (sizeof *t->case_buf * t->nvar); - dict_destroy (dict); + if (identity_map) + { + destroy_case_map (map); + return NULL; + } - procedure (export_write_case_func, t); - save_trns_free (&t->h); + while (map->value_cnt > 0 && map->map[map->value_cnt - 1] == -1) + map->value_cnt--; - return CMD_SUCCESS; + return map; } -/* Writes case C to the EXPORT file. */ -static int -export_write_case_func (struct ccase *c, void *aux) +/* Maps from SRC to DST, applying case map MAP. */ +static void +map_case (const struct case_map *map, + const struct ccase *src, struct ccase *dst) { - struct save_trns *t = aux; - union value *p = (union value *) t->case_buf; - int i; + size_t dst_idx; - for (i = 0; i < t->nvar; i++) - { - struct variable *v = t->var[i]; + assert (map != NULL); + assert (src != NULL); + assert (dst != NULL); + assert (src != dst); - if (v->type == NUMERIC) - (*p++).f = case_num (c, v->fv); - else - (*p++).c = (char *) case_str (c, v->fv); + for (dst_idx = 0; dst_idx < map->value_cnt; dst_idx++) + { + int src_idx = map->map[dst_idx]; + if (src_idx != -1) + *case_data_rw (dst, dst_idx) = *case_data (src, src_idx); } +} - pfm_write_case (t->f, (union value *) t->case_buf); - return 1; +/* Destroys case map MAP. */ +static void +destroy_case_map (struct case_map *map) +{ + if (map != NULL) + { + free (map->map); + free (map); + } } diff --git a/src/glob.c b/src/glob.c index 83dd2b66..9b4f93c4 100644 --- a/src/glob.c +++ b/src/glob.c @@ -70,6 +70,7 @@ extern void stifle_history (); #include "alloc.h" #include "command.h" +#include "dictionary.h" #include "do-ifP.h" #include "error.h" #include "expr.h" @@ -176,9 +177,6 @@ init_glob (int argc UNUSED, char **argv) logfn = xstrdup ("pspp.log"); logfile = NULL; - /* file-handle.h */ - fh_init_files (); - get_date (); } diff --git a/src/group.c b/src/group.c index e394745e..06e303e5 100644 --- a/src/group.c +++ b/src/group.c @@ -17,9 +17,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include +#include +#include "alloc.h" #include "hash.h" #include "group.h" -#include +#include "group_proc.h" +#include "str.h" +#include "var.h" /* Return -1 if the id of a is less than b; +1 if greater than and @@ -48,7 +53,17 @@ hash_group(const struct group_statistics *g, int width) void -free_group(struct group_statistics *v, void *aux) +free_group(struct group_statistics *v, void *aux UNUSED) { free(v); } + + +struct group_proc * +group_proc_get (struct variable *v) +{ + /* This is not ideal, obviously. */ + if (v->aux == NULL) + var_attach_aux (v, xmalloc (sizeof (struct group_proc)), var_dtor_free); + return v->aux; +} diff --git a/src/group_proc.h b/src/group_proc.h index af1b9758..36c15e65 100644 --- a/src/group_proc.h +++ b/src/group_proc.h @@ -45,4 +45,7 @@ struct group_proc }; +struct variable; +struct group_proc *group_proc_get (struct variable *); + #endif diff --git a/src/histogram.c b/src/histogram.c index 27e7b4b1..5429a903 100644 --- a/src/histogram.c +++ b/src/histogram.c @@ -78,6 +78,7 @@ write_legend(struct chart *ch, struct normal_curve *norm) void draw_histogram(struct chart *ch, const struct variable *var, + const struct freq_tab *frq_tab, const char *title, struct normal_curve *norm, int show_normal) @@ -96,8 +97,6 @@ draw_histogram(struct chart *ch, double ordinate_values[BINS]; - const struct freq_tab *frq_tab = &var->p.frq.tab ; - struct hsh_iterator hi; struct hsh_table *fh = frq_tab->data; struct freq *frq; diff --git a/src/inpt-pgm.c b/src/inpt-pgm.c index 0cbf66f3..e27b9dee 100644 --- a/src/inpt-pgm.c +++ b/src/inpt-pgm.c @@ -25,7 +25,8 @@ #include "case.h" #include "command.h" #include "data-list.h" -#include "dfm.h" +#include "dfm-read.h" +#include "dictionary.h" #include "error.h" #include "expr.h" #include "file-handle.h" @@ -312,7 +313,7 @@ struct reread_trns { struct trns_header h; - struct file_handle *handle; /* File to move file pointer back on. */ + struct dfm_reader *reader; /* File to move file pointer back on. */ struct expression *column; /* Column to reset file pointer to. */ }; @@ -320,16 +321,11 @@ struct reread_trns int cmd_reread (void) { - /* File to be re-read. */ - struct file_handle *h; - - /* Expression for column to set file pointer to. */ - struct expression *e; - - /* Created transformation. */ - struct reread_trns *t; + struct file_handle *fh; /* File to be re-read. */ + struct expression *e; /* Expression for column to set. */ + struct reread_trns *t; /* Created transformation. */ - h = default_handle; + fh = default_handle; e = NULL; while (token != '.') { @@ -351,8 +347,8 @@ cmd_reread (void) else if (lex_match_id ("FILE")) { lex_match ('='); - h = fh_parse_file_handle (); - if (h == NULL) + fh = fh_parse (); + if (fh == NULL) { expr_free (e); return CMD_FAILURE; @@ -369,7 +365,7 @@ cmd_reread (void) t = xmalloc (sizeof *t); t->h.proc = reread_trns_proc; t->h.free = reread_trns_free; - t->handle = h; + t->reader = dfm_open_reader (fh); t->column = e; add_transformation ((struct trns_header *) t); @@ -384,7 +380,7 @@ reread_trns_proc (struct trns_header * pt, struct ccase * c, struct reread_trns *t = (struct reread_trns *) pt; if (t->column == NULL) - dfm_reread_record (t->handle, 1); + dfm_reread_record (t->reader, 1); else { union value column; @@ -394,19 +390,21 @@ reread_trns_proc (struct trns_header * pt, struct ccase * c, { msg (SE, _("REREAD: Column numbers must be positive finite " "numbers. Column set to 1.")); - dfm_reread_record (t->handle, 1); + dfm_reread_record (t->reader, 1); } else - dfm_reread_record (t->handle, column.f); + dfm_reread_record (t->reader, column.f); } return -1; } /* Frees a REREAD transformation. */ static void -reread_trns_free (struct trns_header * t) +reread_trns_free (struct trns_header *t_) { - expr_free (((struct reread_trns *) t)->column); + struct reread_trns *t = (struct reread_trns *) t_; + expr_free (t->column); + dfm_close_reader (t->reader); } /* Parses END FILE command. */ diff --git a/src/levene.c b/src/levene.c index 0e36b87a..11e7480a 100644 --- a/src/levene.c +++ b/src/levene.c @@ -24,6 +24,8 @@ #include "error.h" #include "case.h" #include "casefile.h" +#include "dictionary.h" +#include "group_proc.h" #include "hash.h" #include "str.h" #include "var.h" @@ -162,17 +164,18 @@ levene_precalc (const struct levene_info *l) for(i = 0; i < l->n_dep ; ++i ) { struct variable *var = l->v_dep[i]; + struct group_proc *gp = group_proc_get (var); struct group_statistics *gs; struct hsh_iterator hi; lz[i].grand_total = 0; lz[i].total_n = 0; - lz[i].n_groups = var->p.grp_data.n_groups ; + lz[i].n_groups = gp->n_groups ; - for ( gs = hsh_first(var->p.grp_data.group_hash, &hi); + for ( gs = hsh_first(gp->group_hash, &hi); gs != 0; - gs = hsh_next(var->p.grp_data.group_hash, &hi)) + gs = hsh_next(gp->group_hash, &hi)) { gs->lz_total = 0; } @@ -212,11 +215,12 @@ levene_calc (const struct ccase *c, void *_l) for (i = 0; i < l->n_dep; ++i) { struct variable *var = l->v_dep[i]; + struct group_proc *gp = group_proc_get (var); double levene_z; const union value *v = case_data (c, var->fv); struct group_statistics *gs; - gs = hsh_find(var->p.grp_data.group_hash,(void *) &key ); + gs = hsh_find(gp->group_hash,(void *) &key ); if ( 0 == gs ) continue ; @@ -271,7 +275,7 @@ levene2_precalc (void *_l) struct group_statistics *g; struct variable *var = l->v_dep[v] ; - struct hsh_table *hash = var->p.grp_data.group_hash; + struct hsh_table *hash = group_proc_get (var)->group_hash; for(g = (struct group_statistics *) hsh_first(hash,&hi); @@ -321,7 +325,7 @@ levene2_calc (const struct ccase *c, void *_l) const union value *v = case_data (c, var->fv); struct group_statistics *gs; - gs = hsh_find(var->p.grp_data.group_hash,(void *) &key ); + gs = hsh_find(group_proc_get (var)->group_hash,(void *) &key ); if ( 0 == gs ) continue; @@ -351,7 +355,8 @@ levene2_postcalc (void *_l) struct group_statistics *g; struct variable *var = l->v_dep[v] ; - struct hsh_table *hash = var->p.grp_data.group_hash; + struct group_proc *gp = group_proc_get (var); + struct hsh_table *hash = gp->group_hash; for(g = (struct group_statistics *) hsh_first(hash,&hi); g != 0 ; @@ -359,12 +364,11 @@ levene2_postcalc (void *_l) { lz_numerator += g->n * pow2(g->lz_mean - lz[v].grand_mean ); } - lz_numerator *= ( l->v_dep[v]->p.grp_data.ugs.n - - l->v_dep[v]->p.grp_data.n_groups ); + lz_numerator *= ( gp->ugs.n - gp->n_groups ); - lz_denominator[v] *= (l->v_dep[v]->p.grp_data.n_groups - 1); + lz_denominator[v] *= (gp->n_groups - 1); - l->v_dep[v]->p.grp_data.levene = lz_numerator / lz_denominator[v] ; + gp->levene = lz_numerator / lz_denominator[v] ; } diff --git a/src/list.q b/src/list.q index 0ab91889..e3ac2ed5 100644 --- a/src/list.q +++ b/src/list.q @@ -25,6 +25,7 @@ #include "case.h" #include "command.h" #include "devind.h" +#include "dictionary.h" #include "lexer.h" #include "error.h" #include "magic.h" @@ -36,6 +37,7 @@ #include "var.h" #include "vfm.h" #include "format.h" +/* (headers) */ #include "debug-print.h" diff --git a/src/loop.c b/src/loop.c index 5e3f1699..ebe5ed22 100644 --- a/src/loop.c +++ b/src/loop.c @@ -22,6 +22,7 @@ #include "alloc.h" #include "case.h" #include "command.h" +#include "dictionary.h" #include "do-ifP.h" #include "error.h" #include "expr.h" diff --git a/src/main.c b/src/main.c index 4c216030..b4aa2435 100644 --- a/src/main.c +++ b/src/main.c @@ -23,12 +23,14 @@ #include "main.h" #include "cmdline.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "getline.h" #include "glob.h" #include "lexer.h" #include "output.h" #include "settings.h" +#include "var.h" #include #include @@ -100,6 +102,7 @@ static int execute_command (void) { int result; + /* Read the command's first token. We may hit end of file. If so, give the line reader a chance to proceed to the next file. @@ -123,6 +126,9 @@ execute_command (void) /* Unset the /ALGORITHM subcommand if it was used */ unset_cmd_algorithm (); + /* Clear any auxiliary data from the dictionary. */ + dict_clear_aux (default_dict); + return result; } diff --git a/src/matrix-data.c b/src/matrix-data.c index e90aef09..a699738d 100644 --- a/src/matrix-data.c +++ b/src/matrix-data.c @@ -27,7 +27,8 @@ #include "case.h" #include "command.h" #include "data-in.h" -#include "dfm.h" +#include "dfm-read.h" +#include "dictionary.h" #include "error.h" #include "file-handle.h" #include "lexer.h" @@ -42,6 +43,19 @@ /* FIXME: /N subcommand not implemented. It should be pretty simple, too. */ +/* Different types of variables for MATRIX DATA procedure. Order is + important: these are used for sort keys. */ +enum + { + MXD_SPLIT, /* SPLIT FILE variables. */ + MXD_ROWTYPE, /* ROWTYPE_. */ + MXD_FACTOR, /* Factor variables. */ + MXD_VARNAME, /* VARNAME_. */ + MXD_CONTINUOUS, /* Continuous variables. */ + + MXD_COUNT + }; + /* Format type enums. */ enum format_type { @@ -102,7 +116,7 @@ static const char *content_names[PROX + 1] = struct matrix_data_pgm { struct pool *container; /* Arena used for all allocations. */ - struct file_handle *data_file; /* The data file to be read. */ + struct dfm_reader *reader; /* Data file to read. */ /* Format. */ enum format_type fmt; /* LIST or FREE. */ @@ -133,21 +147,30 @@ struct matrix_data_pgm first continuous variable. */ }; +/* Auxiliary data attached to MATRIX DATA variables. */ +struct mxd_var + { + int var_type; /* Variable type. */ + int sub_type; /* Subtype. */ + }; + static const struct case_source_class matrix_data_with_rowtype_source_class; static const struct case_source_class matrix_data_without_rowtype_source_class; -static int compare_variables_by_mxd_vartype (const void *pa, +static int compare_variables_by_mxd_var_type (const void *pa, const void *pb); static void read_matrices_without_rowtype (struct matrix_data_pgm *); static void read_matrices_with_rowtype (struct matrix_data_pgm *); static int string_to_content_type (char *, int *); +static void attach_mxd_aux (struct variable *, int var_type, int sub_type); int cmd_matrix_data (void) { struct pool *pool; struct matrix_data_pgm *mx; - + struct file_handle *fh = NULL; + unsigned seen = 0; discard_variables (); @@ -155,7 +178,7 @@ cmd_matrix_data (void) pool = pool_create (); mx = pool_alloc (pool, sizeof *mx); mx->container = pool; - mx->data_file = inline_file; + mx->reader = NULL; mx->fmt = LIST; mx->section = LOWER; mx->diag = DIAGONAL; @@ -216,9 +239,8 @@ cmd_matrix_data (void) if (strcmp (v[i], "ROWTYPE_")) { new_var = dict_create_var_assert (default_dict, v[i], 0); - new_var->p.mxd.vartype = MXD_CONTINUOUS; - new_var->p.mxd.subtype = i; - } + attach_mxd_aux (new_var, MXD_CONTINUOUS, i); + } else mx->explicit_rowtype = 1; free (v[i]); @@ -226,18 +248,15 @@ cmd_matrix_data (void) free (v); } - { - mx->rowtype_ = dict_create_var_assert (default_dict, - "ROWTYPE_", 8); - mx->rowtype_->p.mxd.vartype = MXD_ROWTYPE; - mx->rowtype_->p.mxd.subtype = 0; - } + mx->rowtype_ = dict_create_var_assert (default_dict, + "ROWTYPE_", 8); + attach_mxd_aux (mx->rowtype_, MXD_ROWTYPE, 0); } else if (lex_match_id ("FILE")) { lex_match ('='); - mx->data_file = fh_parse_file_handle (); - if (mx->data_file == NULL) + fh = fh_parse (); + if (fh == NULL) goto lossage; } else if (lex_match_id ("FORMAT")) @@ -296,10 +315,9 @@ cmd_matrix_data (void) mx->single_split = dict_create_var_assert (default_dict, tokid, 0); + attach_mxd_aux (mx->single_split, MXD_CONTINUOUS, 0); lex_get (); - mx->single_split->p.mxd.vartype = MXD_CONTINUOUS; - dict_set_split_vars (default_dict, &mx->single_split, 1); } else @@ -320,14 +338,16 @@ cmd_matrix_data (void) for (i = 0; i < split_cnt; i++) { - if (split[i]->p.mxd.vartype != MXD_CONTINUOUS) + struct mxd_var *mv = split[i]->aux; + assert (mv != NULL); + if (mv->var_type != MXD_CONTINUOUS) { msg (SE, _("Split variable %s is already another type."), tokid); goto lossage; } - split[i]->p.mxd.vartype = MXD_SPLIT; - split[i]->p.mxd.subtype = i; + var_clear_aux (split[i]); + attach_mxd_aux (split[i], MXD_SPLIT, i); } } } @@ -350,14 +370,17 @@ cmd_matrix_data (void) for (i = 0; i < mx->n_factors; i++) { - if (mx->factors[i]->p.mxd.vartype != MXD_CONTINUOUS) + struct variable *v = mx->factors[i]; + struct mxd_var *mv = v->aux; + assert (mv != NULL); + if (mv->var_type != MXD_CONTINUOUS) { msg (SE, _("Factor variable %s is already another type."), tokid); goto lossage; } - mx->factors[i]->p.mxd.vartype = MXD_FACTOR; - mx->factors[i]->p.mxd.subtype = i; + var_clear_aux (v); + attach_mxd_aux (v, MXD_FACTOR, i); } } } @@ -537,11 +560,8 @@ cmd_matrix_data (void) } /* Create VARNAME_. */ - { - mx->varname_ = dict_create_var_assert (default_dict, "VARNAME_", 8); - mx->varname_->p.mxd.vartype = MXD_VARNAME; - mx->varname_->p.mxd.subtype = 0; - } + mx->varname_ = dict_create_var_assert (default_dict, "VARNAME_", 8); + attach_mxd_aux (mx->varname_, MXD_VARNAME, 0); /* Sort the dictionary variables into the desired order for the system file output. */ @@ -550,7 +570,7 @@ cmd_matrix_data (void) size_t nv; dict_get_vars (default_dict, &v, &nv, 0); - qsort (v, nv, sizeof *v, compare_variables_by_mxd_vartype); + qsort (v, nv, sizeof *v, compare_variables_by_mxd_var_type); dict_reorder_vars (default_dict, v, nv); free (v); } @@ -572,7 +592,8 @@ cmd_matrix_data (void) for (i = 0; i < dict_get_var_cnt (default_dict); i++) { struct variable *v = dict_get_var (default_dict, i); - int type = v->p.mxd.vartype; + struct mxd_var *mv = v->aux; + int type = mv->var_type; assert (type >= 0 && type < MXD_COUNT); v->print = v->write = fmt_tab[type]; @@ -590,7 +611,8 @@ cmd_matrix_data (void) goto lossage; } - if (!dfm_open_for_reading (mx->data_file)) + mx->reader = dfm_open_reader (fh); + if (mx->reader == NULL) goto lossage; if (mx->explicit_rowtype) @@ -598,6 +620,8 @@ cmd_matrix_data (void) else read_matrices_without_rowtype (mx); + dfm_close_reader (mx->reader); + pool_destroy (mx->container); return CMD_SUCCESS; @@ -654,20 +678,34 @@ string_to_content_type (char *s, int *collide) return -1; } -/* Compare two variables using p.mxd.vartype and p.mxd.subtype +/* Compare two variables using p.mxd.var_type and p.mxd.sub_type fields. */ static int -compare_variables_by_mxd_vartype (const void *a_, const void *b_) +compare_variables_by_mxd_var_type (const void *a_, const void *b_) { struct variable *const *pa = a_; struct variable *const *pb = b_; - const struct matrix_data_proc *a = &(*pa)->p.mxd; - const struct matrix_data_proc *b = &(*pb)->p.mxd; - - if (a->vartype != b->vartype) - return a->vartype > b->vartype ? 1 : -1; + const struct mxd_var *a = (*pa)->aux; + const struct mxd_var *b = (*pb)->aux; + + if (a->var_type != b->var_type) + return a->var_type > b->var_type ? 1 : -1; else - return a->subtype < b->subtype ? -1 : a->subtype > b->subtype; + return a->sub_type < b->sub_type ? -1 : a->sub_type > b->sub_type; +} + +/* Attaches a struct mxd_var with the specific member values to + V. */ +static void +attach_mxd_aux (struct variable *v, int var_type, int sub_type) +{ + struct mxd_var *mv; + + assert (v->aux == NULL); + mv = xmalloc (sizeof *mv); + mv->var_type = var_type; + mv->sub_type = sub_type; + var_attach_aux (v, mv, var_dtor_free); } /* Matrix tokenizer. */ @@ -688,10 +726,10 @@ struct matrix_token int length; /* MSTR: tokstr length. */ }; -static int mget_token (struct matrix_token *, struct file_handle *); +static int mget_token (struct matrix_token *, struct dfm_reader *); #if DEBUGGING -#define mget_token(TOKEN, HANDLE) mget_token_dump(TOKEN, HANDLE) +#define mget_token(TOKEN, READER) mget_token_dump(TOKEN, READER) static void mdump_token (const struct matrix_token *token) @@ -711,28 +749,28 @@ mdump_token (const struct matrix_token *token) } static int -mget_token_dump (struct matrix_token *token, struct file_handle *data_file) +mget_token_dump (struct matrix_token *token, struct dfm_reader *reader) { - int result = (mget_token) (token, data_file); + int result = (mget_token) (token, reader); mdump_token (token); return result; } #endif -/* Return the current position in DATA_FILE. */ +/* Return the current position in READER. */ static const char * -context (struct file_handle *data_file) +context (struct dfm_reader *reader) { static char buf[32]; - if (dfm_eof (data_file)) + if (dfm_eof (reader)) strcpy (buf, "at end of file"); else { struct len_string line; const char *sp; - dfm_get_record (data_file, &line); + dfm_get_record (reader, &line); sp = ls_c_str (&line); while (sp < ls_end (&line) && isspace ((unsigned char) *sp)) sp++; @@ -759,16 +797,16 @@ context (struct file_handle *data_file) /* Is there at least one token left in the data file? */ static int -another_token (struct file_handle *data_file) +another_token (struct dfm_reader *reader) { for (;;) { struct len_string line; const char *cp; - if (dfm_eof (data_file)) + if (dfm_eof (reader)) return 0; - dfm_get_record (data_file, &line); + dfm_get_record (reader, &line); cp = ls_c_str (&line); while (isspace ((unsigned char) *cp) && cp < ls_end (&line)) @@ -776,27 +814,27 @@ another_token (struct file_handle *data_file) if (cp < ls_end (&line)) { - dfm_forward_columns (data_file, cp - ls_c_str (&line)); + dfm_forward_columns (reader, cp - ls_c_str (&line)); return 1; } - dfm_forward_record (data_file); + dfm_forward_record (reader); } } -/* Parse a MATRIX DATA token from mx->data_file into TOKEN. */ +/* Parse a MATRIX DATA token from READER into TOKEN. */ static int -(mget_token) (struct matrix_token *token, struct file_handle *data_file) +(mget_token) (struct matrix_token *token, struct dfm_reader *reader) { struct len_string line; int first_column; char *cp; - if (!another_token (data_file)) + if (!another_token (reader)) return 0; - dfm_get_record (data_file, &line); - first_column = dfm_column_start (data_file); + dfm_get_record (reader, &line); + first_column = dfm_column_start (reader); /* Three types of fields: quoted with ', quoted with ", unquoted. */ cp = ls_c_str (&line); @@ -856,22 +894,22 @@ static int token->type = MSTR; } - dfm_forward_columns (data_file, cp - ls_c_str (&line)); + dfm_forward_columns (reader, cp - ls_c_str (&line)); return 1; } /* Forcibly skip the end of a line for content type CONTENT in - DATA_FILE. */ + READER. */ static int -force_eol (struct file_handle *data_file, const char *content) +force_eol (struct dfm_reader *reader, const char *content) { struct len_string line; const char *cp; - if (dfm_eof (data_file)) + if (dfm_eof (reader)) return 0; - dfm_get_record (data_file, &line); + dfm_get_record (reader, &line); cp = ls_c_str (&line); while (isspace ((unsigned char) *cp) && cp < ls_end (&line)) @@ -880,11 +918,11 @@ force_eol (struct file_handle *data_file, const char *content) if (cp < ls_end (&line)) { msg (SE, _("End of line expected %s while reading %s."), - context (data_file), content); + context (reader), content); return 0; } - dfm_forward_record (data_file); + dfm_forward_record (reader); return 1; } @@ -932,8 +970,6 @@ read_matrices_without_rowtype (struct matrix_data_pgm *mx) free (nr.split_values); free (nr.factor_values); - - fh_close_handle (mx->data_file); } /* Mirror data across the diagonal of matrix CP which contains @@ -1063,20 +1099,20 @@ nr_read_data_lines (struct nr_aux_data *nr, for (j = 0; j < n_cols; j++) { struct matrix_token token; - if (!mget_token (&token, mx->data_file)) + if (!mget_token (&token, mx->reader)) return 0; if (token.type != MNUM) { msg (SE, _("expecting value for %s %s"), dict_get_var (default_dict, j)->name, - context (mx->data_file)); + context (mx->reader)); return 0; } *cp++ = token.number; } if (mx->fmt != FREE - && !force_eol (mx->data_file, content_names[content])) + && !force_eol (mx->reader, content_names[content])) return 0; debug_printf (("\n")); } @@ -1185,7 +1221,7 @@ matrix_data_read_without_rowtype (struct case_source *source, nr_output_data (nr, c, write_case, wc_data); if (dict_get_split_cnt (default_dict) == 0 - || !another_token (mx->data_file)) + || !another_token (mx->reader)) return; } } @@ -1212,9 +1248,11 @@ nr_read_splits (struct nr_aux_data *nr, int compare) if (mx->single_split) { - if (!compare) - nr->split_values[0] - = ++dict_get_split_vars (default_dict)[0]->p.mxd.subtype; + if (!compare) + { + struct mxd_var *mv = dict_get_split_vars (default_dict)[0]->aux; + nr->split_values[0] = ++mv->sub_type; + } return 1; } @@ -1225,12 +1263,12 @@ nr_read_splits (struct nr_aux_data *nr, int compare) for (i = 0; i < split_cnt; i++) { struct matrix_token token; - if (!mget_token (&token, mx->data_file)) + if (!mget_token (&token, mx->reader)) return 0; if (token.type != MNUM) { msg (SE, _("Syntax error expecting SPLIT FILE value %s."), - context (mx->data_file)); + context (mx->reader)); return 0; } @@ -1275,12 +1313,12 @@ nr_read_factors (struct nr_aux_data *nr, int cell) for (i = 0; i < mx->n_factors; i++) { struct matrix_token token; - if (!mget_token (&token, mx->data_file)) + if (!mget_token (&token, mx->reader)) return 0; if (token.type != MNUM) { msg (SE, _("Syntax error expecting factor value %s."), - context (mx->data_file)); + context (mx->reader)); return 0; } @@ -1290,7 +1328,7 @@ nr_read_factors (struct nr_aux_data *nr, int cell) { msg (SE, _("Syntax error expecting value %g for %s %s."), nr->factor_values[i + mx->n_factors * cell], - mx->factors[i]->name, context (mx->data_file)); + mx->factors[i]->name, context (mx->reader)); return 0; } } @@ -1434,7 +1472,7 @@ static int wr_read_splits (struct wr_aux_data *, struct ccase *, static int wr_output_data (struct wr_aux_data *, struct ccase *, write_case_func *, write_case_data); static int wr_read_rowtype (struct wr_aux_data *, - const struct matrix_token *, struct file_handle *); + const struct matrix_token *, struct dfm_reader *); static int wr_read_factors (struct wr_aux_data *); static int wr_read_indeps (struct wr_aux_data *); static void matrix_data_read_with_rowtype (struct case_source *, @@ -1461,7 +1499,6 @@ read_matrices_with_rowtype (struct matrix_data_pgm *mx) procedure (NULL, NULL); free (wr.split_values); - fh_close_handle (mx->data_file); } /* Read from the data file and write it to the active file. */ @@ -1485,7 +1522,7 @@ matrix_data_read_with_rowtype (struct case_source *source, if (!wr_read_indeps (wr)) return; } - while (another_token (mx->data_file)); + while (another_token (mx->reader)); wr_output_data (wr, c, write_case, wc_data); } @@ -1520,12 +1557,12 @@ wr_read_splits (struct wr_aux_data *wr, for (i = 0; i < split_cnt; i++) { struct matrix_token token; - if (!mget_token (&token, mx->data_file)) + if (!mget_token (&token, mx->reader)) return 0; if (token.type != MNUM) { msg (SE, _("Syntax error %s expecting SPLIT FILE value."), - context (mx->data_file)); + context (mx->reader)); return 0; } @@ -1680,22 +1717,22 @@ wr_output_data (struct wr_aux_data *wr, return 1; } -/* Sets ROWTYPE_ based on the given TOKEN read from DATA_FILE. +/* Sets ROWTYPE_ based on the given TOKEN read from READER. Return success. */ static int wr_read_rowtype (struct wr_aux_data *wr, const struct matrix_token *token, - struct file_handle *data_file) + struct dfm_reader *reader) { if (wr->content != -1) { - msg (SE, _("Multiply specified ROWTYPE_ %s."), context (data_file)); + msg (SE, _("Multiply specified ROWTYPE_ %s."), context (reader)); return 0; } if (token->type != MSTR) { msg (SE, _("Syntax error %s expecting ROWTYPE_ string."), - context (data_file)); + context (reader)); return 0; } @@ -1714,7 +1751,7 @@ wr_read_rowtype (struct wr_aux_data *wr, if (wr->content == -1) { - msg (SE, _("Syntax error %s."), context (data_file)); + msg (SE, _("Syntax error %s."), context (reader)); return 0; } @@ -1736,19 +1773,19 @@ wr_read_factors (struct wr_aux_data *wr) for (i = 0; i < mx->n_factors; i++) { struct matrix_token token; - if (!mget_token (&token, mx->data_file)) + if (!mget_token (&token, mx->reader)) goto lossage; if (token.type == MSTR) { - if (!wr_read_rowtype (wr, &token, mx->data_file)) + if (!wr_read_rowtype (wr, &token, mx->reader)) goto lossage; - if (!mget_token (&token, mx->data_file)) + if (!mget_token (&token, mx->reader)) goto lossage; } if (token.type != MNUM) { msg (SE, _("Syntax error expecting factor value %s."), - context (mx->data_file)); + context (mx->reader)); goto lossage; } @@ -1758,9 +1795,9 @@ wr_read_factors (struct wr_aux_data *wr) if (wr->content == -1) { struct matrix_token token; - if (!mget_token (&token, mx->data_file)) + if (!mget_token (&token, mx->reader)) goto lossage; - if (!wr_read_rowtype (wr, &token, mx->data_file)) + if (!wr_read_rowtype (wr, &token, mx->reader)) goto lossage; } @@ -1920,20 +1957,20 @@ wr_read_indeps (struct wr_aux_data *wr) for (j = 0; j < n_cols; j++) { struct matrix_token token; - if (!mget_token (&token, mx->data_file)) + if (!mget_token (&token, mx->reader)) return 0; if (token.type != MNUM) { msg (SE, _("Syntax error expecting value for %s %s."), dict_get_var (default_dict, mx->first_continuous + j)->name, - context (mx->data_file)); + context (mx->reader)); return 0; } *cp++ = token.number; } if (mx->fmt != FREE - && !force_eol (mx->data_file, content_names[wr->content])) + && !force_eol (mx->reader, content_names[wr->content])) return 0; debug_printf (("\n")); } @@ -1959,3 +1996,4 @@ matrix_data_without_rowtype_source_class = matrix_data_read_without_rowtype, NULL, }; + diff --git a/src/means.q b/src/means.q index 483b6dc6..7dca14b2 100644 --- a/src/means.q +++ b/src/means.q @@ -20,6 +20,7 @@ #include #include #include +#include "dictionary.h" #include "error.h" #include "alloc.h" #include "command.h" @@ -35,8 +36,6 @@ /* (specification) means (mns_): *tables=custom; - +variables=custom; - +crossbreak=custom; +format=lab:!labels/nolabels/nocatlabs, name:!names/nonames, val:!values/novalues, @@ -130,17 +129,14 @@ mns_custom_tables (struct cmd_means *cmd) return 2; lex_match ('='); - if (cmd->sbc_tables || cmd->sbc_crossbreak) + if (cmd->sbc_tables) { - msg (SE, _("TABLES or CROSSBREAK subcommand may not appear more " + msg (SE, _("TABLES subcommand may not appear more " "than once.")); return 0; } - if (cmd->sbc_variables) - var_set = var_set_create_from_array (v_var, n_var); - else - var_set = var_set_create_from_dict (default_dict); + var_set = var_set_create_from_dict (default_dict); assert (var_set != NULL); do @@ -158,48 +154,6 @@ mns_custom_tables (struct cmd_means *cmd) nv_dim[n_dim - 1] = nvl; v_dim[n_dim - 1] = vl; - - if (cmd->sbc_variables) - { - int i; - - for (i = 0; i < nv_dim[0]; i++) - { - struct means_proc *v_inf = &v_dim[0][i]->p.mns; - - if (v_inf->min == SYSMIS) - { - msg (SE, _("Variable %s specified on TABLES or " - "CROSSBREAK, but not specified on " - "VARIABLES."), - v_dim[0][i]->name); - goto lossage; - } - - if (n_dim == 1) - { - v_inf->min = (int) v_inf->min; - v_inf->max = (int) v_inf->max; - } else { - if (v_inf->min == LOWEST || v_inf->max == HIGHEST) - { - msg (SE, _("LOWEST and HIGHEST may not be used " - "for independent variables (%s)."), - v_dim[0][i]->name); - goto lossage; - } - if (v_inf->min != (int) v_inf->min - || v_inf->max != (int) v_inf->max) - { - msg (SE, _("Independent variables (%s) may not " - "have noninteger endpoints in their " - "ranges."), - v_dim[0][i]->name); - goto lossage; - } - } - } - } } while (lex_match (T_BY)); @@ -211,98 +165,6 @@ mns_custom_tables (struct cmd_means *cmd) return 0; } -/* Parse CROSSBREAK subcommand. */ -static int -mns_custom_crossbreak (struct cmd_means *cmd) -{ - return mns_custom_tables (cmd); -} - -/* Parses the VARIABLES subcommand. */ -static int -mns_custom_variables (struct cmd_means *cmd) -{ - if (cmd->sbc_tables) - { - msg (SE, _("VARIABLES must precede TABLES.")); - return 0; - } - - if (cmd->sbc_variables == 1) - { - int i; - - for (i = 0; i < dict_get_var_cnt (default_dict); i++) - dict_get_var (default_dict, i)->p.mns.min = SYSMIS; - } - - do - { - int orig_n = n_var; - - double min, max; - - if (!parse_variables (default_dict, &v_var, &n_var, - PV_APPEND | PV_NO_DUPLICATE | PV_NO_SCRATCH)) - return 0; - - if (!lex_force_match ('(')) - return 0; - - /* Lower value. */ - if (token == T_ID - && (!strcmp (tokid, "LO") || lex_id_match ("LOWEST", tokid))) - min = LOWEST; - else - { - if (!lex_force_num ()) - return 0; - min = tokval; - } - lex_get (); - - lex_match (','); - - /* Higher value. */ - if (token == T_ID - && (!strcmp (tokid, "HI") || lex_id_match ("HIGHEST", tokid))) - max = HIGHEST; - else - { - if (!lex_force_num ()) - return 0; - max = tokval; - } - lex_get (); - - if (!lex_force_match (')')) - return 0; - - /* Range check. */ - if (max < min) - { - msg (SE, _("Upper value (%g) is less than lower value " - "(%g) on VARIABLES subcommand."), max, min); - return 0; - } - - { - int i; - - for (i = orig_n; i < n_var; i++) - { - struct means_proc *v_inf = &v_var[i]->p.mns; - - v_inf->min = min; - v_inf->max = max; - } - } - } - while (token != '/' && token != '.'); - - return 1; -} - /* Local Variables: mode: c diff --git a/src/modify-vars.c b/src/modify-vars.c index aab05c6e..5cddfe15 100644 --- a/src/modify-vars.c +++ b/src/modify-vars.c @@ -24,6 +24,7 @@ #include "alloc.h" #include "bitvector.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "hash.h" #include "lexer.h" diff --git a/src/numeric.c b/src/numeric.c index 26961289..ee8ec552 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -21,6 +21,7 @@ #include "error.h" #include #include "command.h" +#include "dictionary.h" #include "error.h" #include "lexer.h" #include "str.h" diff --git a/src/oneway.q b/src/oneway.q index bcc75c7e..390ce029 100644 --- a/src/oneway.q +++ b/src/oneway.q @@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "alloc.h" #include "str.h" #include "case.h" +#include "dictionary.h" #include "command.h" #include "lexer.h" #include "error.h" @@ -42,6 +43,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "group_proc.h" #include "group.h" #include "levene.h" +/* (headers) */ /* (specification) "ONEWAY" (oneway_): @@ -195,7 +197,7 @@ output_oneway(void) /* Clean up */ for (i = 0 ; i < n_vars ; ++i ) { - struct hsh_table *group_hash = vars[i]->p.grp_data.group_hash; + struct hsh_table *group_hash = group_proc_get (vars[i])->group_hash; hsh_destroy(group_hash); } @@ -281,8 +283,8 @@ show_anova_table(void) for ( i=0 ; i < n_vars ; ++i ) { - struct group_statistics *totals = &vars[i]->p.grp_data.ugs; - struct hsh_table *group_hash = vars[i]->p.grp_data.group_hash; + struct group_statistics *totals = &group_proc_get (vars[i])->ugs; + struct hsh_table *group_hash = group_proc_get (vars[i])->group_hash; struct hsh_iterator g; struct group_statistics *gs; double ssa=0; @@ -308,12 +310,13 @@ show_anova_table(void) tab_hline(t, TAL_1, 0, n_cols - 1 , i * 3 + 1); { + struct group_proc *gp = group_proc_get (vars[i]); const double sst = totals->ssq - ( totals->sum * totals->sum) / totals->n ; - const double df1 = vars[i]->p.grp_data.n_groups - 1; - const double df2 = totals->n - vars[i]->p.grp_data.n_groups ; + const double df1 = gp->n_groups - 1; + const double df2 = totals->n - gp->n_groups ; const double msa = ssa / df1; - vars[i]->p.grp_data.mse = (sst - ssa) / df2; + gp->mse = (sst - ssa) / df2; /* Sums of Squares */ @@ -329,11 +332,11 @@ show_anova_table(void) /* Mean Squares */ tab_float (t, 4, i * 3 + 1, TAB_RIGHT, msa, 8, 3); - tab_float (t, 4, i * 3 + 2, TAB_RIGHT, vars[i]->p.grp_data.mse, 8, 3); + tab_float (t, 4, i * 3 + 2, TAB_RIGHT, gp->mse, 8, 3); { - const double F = msa/vars[i]->p.grp_data.mse ; + const double F = msa/gp->mse ; /* The F value */ tab_float (t, 5, i * 3 + 1, 0, F, 8, 3); @@ -371,7 +374,7 @@ show_descriptives(void) for ( v = 0 ; v < n_vars ; ++v ) - n_rows += vars[v]->p.grp_data.n_groups + 1; + n_rows += group_proc_get (vars[v])->n_groups + 1; t = tab_create (n_cols,n_rows,0); tab_headers (t, 2, 0, 2, 0); @@ -414,16 +417,17 @@ show_descriptives(void) { double T; double std_error; - + + struct group_proc *gp = group_proc_get (vars[v]); struct hsh_iterator g; struct group_statistics *gs; - struct group_statistics *totals = &vars[v]->p.grp_data.ugs; + struct group_statistics *totals = &gp->ugs; int count = 0 ; const char *s = var_to_string(vars[v]); - struct hsh_table *group_hash = vars[v]->p.grp_data.group_hash; + struct hsh_table *group_hash = gp->group_hash; tab_text (t, 0, row, TAB_LEFT | TAT_TITLE, s); @@ -506,7 +510,7 @@ show_descriptives(void) tab_float(t, 8, row + count, 0, totals->minimum, 8, 2); tab_float(t, 9, row + count, 0, totals->maximum, 8, 2); - row += vars[v]->p.grp_data.n_groups + 1; + row += gp->n_groups + 1; } @@ -554,15 +558,16 @@ show_homogeneity(void) { double F; const struct variable *var = vars[v]; + const struct group_proc *gp = group_proc_get (vars[v]); const char *s = var_to_string(var); - const struct group_statistics *totals = &var->p.grp_data.ugs; + const struct group_statistics *totals = &gp->ugs; - const double df1 = var->p.grp_data.n_groups - 1; - const double df2 = totals->n - var->p.grp_data.n_groups ; + const double df1 = gp->n_groups - 1; + const double df2 = totals->n - gp->n_groups ; tab_text (t, 0, v + 1, TAB_LEFT | TAT_TITLE, s); - F = var->p.grp_data.levene; + F = gp->levene; tab_float (t, 1, v + 1, TAB_RIGHT, F, 8,3); tab_float (t, 2, v + 1, TAB_RIGHT, df1 ,8,0); tab_float (t, 3, v + 1, TAB_RIGHT, df2 ,8,0); @@ -716,7 +721,7 @@ show_contrast_tests(short *bad_contrast) int ci; double contrast_value = 0.0; double coef_msq = 0.0; - struct group_proc *grp_data = &vars[v]->p.grp_data ; + struct group_proc *grp_data = group_proc_get (vars[v]); struct hsh_table *group_hash = grp_data->group_hash; struct hsh_iterator g; struct group_statistics *gs; @@ -796,7 +801,7 @@ show_contrast_tests(short *bad_contrast) cmd.sbc_contrast, TAB_RIGHT, contrast_value, 8,2); - std_error_contrast = sqrt(vars[v]->p.grp_data.mse * coef_msq); + std_error_contrast = sqrt(grp_data->mse * coef_msq); /* Std. Error */ tab_float (t, 4, (v * lines_per_variable) + i + 1, @@ -882,13 +887,14 @@ precalc ( struct cmd_oneway *cmd UNUSED ) for(i=0; i< n_vars ; ++i) { - struct group_statistics *totals = &vars[i]->p.grp_data.ugs; + struct group_proc *gp = group_proc_get (vars[i]); + struct group_statistics *totals = &gp->ugs; /* Create a hash for each of the dependent variables. The hash contains a group_statistics structure, and is keyed by value of the independent variable */ - vars[i]->p.grp_data.group_hash = + gp->group_hash = hsh_create(4, (hsh_compare_func *) compare_group, (hsh_hash_func *) hash_group, @@ -961,7 +967,8 @@ run_oneway(const struct casefile *cf, void *cmd_) const union value *val = case_data (&c, v->fv); - struct hsh_table *group_hash = vars[i]->p.grp_data.group_hash; + struct group_proc *gp = group_proc_get (vars[i]); + struct hsh_table *group_hash = gp->group_hash; struct group_statistics *gs; @@ -985,7 +992,7 @@ run_oneway(const struct casefile *cf, void *cmd_) if (! value_is_missing(val,v) ) { - struct group_statistics *totals = &vars[i]->p.grp_data.ugs; + struct group_statistics *totals = &gp->ugs; totals->n+=weight; totals->sum+=weight * val->f; @@ -1008,7 +1015,7 @@ run_oneway(const struct casefile *cf, void *cmd_) gs->maximum = val->f * weight; } - vars[i]->p.grp_data.n_groups = hsh_count ( group_hash ); + gp->n_groups = hsh_count ( group_hash ); } } @@ -1040,8 +1047,9 @@ postcalc ( struct cmd_oneway *cmd UNUSED ) for(i = 0; i < n_vars ; ++i) { - struct hsh_table *group_hash = vars[i]->p.grp_data.group_hash; - struct group_statistics *totals = &vars[i]->p.grp_data.ugs; + struct group_proc *gp = group_proc_get (vars[i]); + struct hsh_table *group_hash = gp->group_hash; + struct group_statistics *totals = &gp->ugs; struct hsh_iterator g; struct group_statistics *gs; diff --git a/src/pfm-read.c b/src/pfm-read.c index 7be8ea05..e82fa00f 100644 --- a/src/pfm-read.c +++ b/src/pfm-read.c @@ -1,6 +1,8 @@ /* PSPP - computes sample statistics. Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. Written by Ben Pfaff . + Code for parsing floating-point numbers adapted from GNU C + library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -18,7 +20,7 @@ 02111-1307, USA. */ #include -#include "pfm.h" +#include "pfm-read.h" #include "error.h" #include #include @@ -28,6 +30,7 @@ #include #include "alloc.h" #include "case.h" +#include "dictionary.h" #include "file-handle.h" #include "format.h" #include "getline.h" @@ -40,36 +43,33 @@ #include "debug-print.h" -/* pfm's file_handle extension. */ -struct pfm_fhuser_ext +/* Portable file reader. */ +struct pfm_reader { - FILE *file; /* Actual file. */ + struct file_handle *fh; /* File handle. */ + FILE *file; /* File stream. */ - struct dictionary *dict; /* File's dictionary. */ int weight_index; /* 0-based index of weight variable, or -1. */ unsigned char *trans; /* 256-byte character set translation table. */ - int nvars; /* Number of variables. */ - int *vars; /* Variable widths, 0 for numeric. */ - int case_size; /* Number of `value's per case. */ + int var_cnt; /* Number of variables. */ + int *widths; /* Variable widths, 0 for numeric. */ + int value_cnt; /* Number of `value's per case. */ unsigned char buf[83]; /* Input buffer. */ unsigned char *bp; /* Buffer pointer. */ int cc; /* Current character. */ }; -static struct fh_ext_class pfm_r_class; - static int -corrupt_msg (struct file_handle *h, const char *format,...) +corrupt_msg (struct pfm_reader *r, const char *format,...) PRINTF_FORMAT (2, 3); /* Displays a corruption error. */ static int -corrupt_msg (struct file_handle *h, const char *format, ...) +corrupt_msg (struct pfm_reader *r, const char *format, ...) { - struct pfm_fhuser_ext *ext = h->ext; char buf[1024]; { @@ -87,10 +87,10 @@ corrupt_msg (struct file_handle *h, const char *format, ...) e.class = ME; getl_location (&e.where.filename, &e.where.line_number); - filename = handle_get_filename (h); + filename = handle_get_filename (r->fh); e.title = title = local_alloc (strlen (filename) + 80); sprintf (title, _("portable file %s corrupt at offset %ld: "), - filename, ftell (ext->file) - (82 - (long) (ext->bp - ext->buf))); + filename, ftell (r->file) - (82 - (long) (r->bp - r->buf))); e.text = buf; err_vmsg (&e); @@ -102,200 +102,173 @@ corrupt_msg (struct file_handle *h, const char *format, ...) } /* Closes a portable file after we're done with it. */ -static void -pfm_close (struct file_handle *h) +void +pfm_close_reader (struct pfm_reader *r) { - struct pfm_fhuser_ext *ext = h->ext; + if (r == NULL) + return; - if (EOF == fclose (ext->file)) + if (r->fh != NULL) + fh_close (r->fh, "portable file", "rs"); + if (fclose (r->file) == EOF) msg (ME, _("%s: Closing portable file: %s."), - handle_get_filename (h), strerror (errno)); - free (ext->vars); - free (ext->trans); - free (h->ext); + handle_get_filename (r->fh), strerror (errno)); + free (r->trans); + free (r); } -/* Displays the message X with corrupt_msg, then jumps to the lossage +/* Displays the message X with corrupt_msg, then jumps to the error label. */ -#define lose(X) \ - do \ - { \ - corrupt_msg X; \ - goto lossage; \ - } \ - while (0) +#define lose(X) \ + do { \ + corrupt_msg X; \ + goto error; \ + } while (0) /* Read an 80-character line into handle H's buffer. Return success. */ static int -fill_buf (struct file_handle *h) +fill_buf (struct pfm_reader *r) { - struct pfm_fhuser_ext *ext = h->ext; - - if (80 != fread (ext->buf, 1, 80, ext->file)) - lose ((h, _("Unexpected end of file."))); + if (80 != fread (r->buf, 1, 80, r->file)) + lose ((r, _("Unexpected end of file."))); /* PORTME: line ends. */ { int c; - c = getc (ext->file); + c = getc (r->file); if (c != '\n' && c != '\r') - lose ((h, _("Bad line end."))); + lose ((r, _("Bad line end."))); - c = getc (ext->file); + c = getc (r->file); if (c != '\n' && c != '\r') - ungetc (c, ext->file); + ungetc (c, r->file); } - if (ext->trans) + if (r->trans) { int i; for (i = 0; i < 80; i++) - ext->buf[i] = ext->trans[ext->buf[i]]; + r->buf[i] = r->trans[r->buf[i]]; } - ext->bp = ext->buf; + r->bp = r->buf; return 1; - lossage: + error: return 0; } /* Read a single character into cur_char. Return success; */ static int -read_char (struct file_handle *h) +read_char (struct pfm_reader *r) { - struct pfm_fhuser_ext *ext = h->ext; - - if (ext->bp >= &ext->buf[80] && !fill_buf (h)) + if (r->bp >= &r->buf[80] && !fill_buf (r)) return 0; - ext->cc = *ext->bp++; + r->cc = *r->bp++; return 1; } /* Advance a single character. */ -#define advance() if (!read_char (h)) goto lossage +#define advance() \ + do { \ + if (!read_char (r)) \ + goto error; \ + } while (0) /* Skip a single character if present, and return whether it was skipped. */ static inline int -skip_char (struct file_handle *h, int c) +skip_char (struct pfm_reader *r, int c) { - struct pfm_fhuser_ext *ext = h->ext; - - if (ext->cc == c) + if (r->cc == c) { advance (); return 1; } - lossage: + error: return 0; } /* Skip a single character if present, and return whether it was skipped. */ -#define match(C) skip_char (h, C) +#define match(C) skip_char (r, C) -static int read_header (struct file_handle *h); -static int read_version_data (struct file_handle *h, struct pfm_read_info *inf); -static int read_variables (struct file_handle *h); -static int read_value_label (struct file_handle *h); -void dump_dictionary (struct dictionary *dict); +static int read_header (struct pfm_reader *); +static int read_version_data (struct pfm_reader *, struct pfm_read_info *); +static int read_variables (struct pfm_reader *, struct dictionary *); +static int read_value_label (struct pfm_reader *, struct dictionary *); +void dump_dictionary (struct dictionary *); /* Reads the dictionary from file with handle H, and returns it in a dictionary structure. This dictionary may be modified in order to rename, reorder, and delete variables, etc. */ -struct dictionary * -pfm_read_dictionary (struct file_handle *h, struct pfm_read_info *inf) +struct pfm_reader * +pfm_open_reader (struct file_handle *fh, struct dictionary **dict, + struct pfm_read_info *info) { - /* The file handle extension record. */ - struct pfm_fhuser_ext *ext; - - /* Check whether the file is already open. */ - if (h->class == &pfm_r_class) - { - ext = h->ext; - return ext->dict; - } - else if (h->class != NULL) - { - msg (ME, _("Cannot read file %s as portable file: already opened " - "for %s."), - handle_get_name (h), h->class->name); - return NULL; - } - - msg (VM (1), _("%s: Opening portable-file handle %s for reading."), - handle_get_filename (h), handle_get_name (h)); - - /* Open the physical disk file. */ - ext = xmalloc (sizeof (struct pfm_fhuser_ext)); - ext->file = fopen (handle_get_filename (h), "rb"); - if (ext->file == NULL) + struct pfm_reader *r = NULL; + + *dict = dict_create (); + if (!fh_open (fh, "portable file", "rs")) + goto error; + + /* Create and initialize reader. */ + r = xmalloc (sizeof *r); + r->fh = fh; + r->file = fopen (handle_get_filename (r->fh), "rb"); + r->weight_index = -1; + r->trans = NULL; + r->var_cnt = 0; + r->widths = NULL; + r->value_cnt = 0; + r->bp = NULL; + + /* Check that file open succeeded, prime reading. */ + if (r->file == NULL) { msg (ME, _("An error occurred while opening \"%s\" for reading " "as a portable file: %s."), - handle_get_filename (h), strerror (errno)); + handle_get_filename (r->fh), strerror (errno)); err_cond_fail (); - free (ext); - return NULL; + goto error; } - - /* Initialize the sfm_fhuser_ext structure. */ - h->class = &pfm_r_class; - h->ext = ext; - ext->dict = NULL; - ext->trans = NULL; - if (!fill_buf (h)) - goto lossage; + if (!fill_buf (r)) + goto error; advance (); - /* Read the header. */ - if (!read_header (h)) - goto lossage; - - /* Read version, date info, product identification. */ - if (!read_version_data (h, inf)) - goto lossage; - - /* Read variables. */ - if (!read_variables (h)) - goto lossage; + /* Read header, version, date info, product id, variables. */ + if (!read_header (r) + || !read_version_data (r, info) + || !read_variables (r, *dict)) + goto error; - /* Value labels. */ + /* Read value labels. */ while (match (77 /* D */)) - if (!read_value_label (h)) - goto lossage; + if (!read_value_label (r, *dict)) + goto error; + /* Check that we've made it to the data. */ if (!match (79 /* F */)) - lose ((h, _("Data record expected."))); - - msg (VM (2), _("Read portable-file dictionary successfully.")); + lose ((r, _("Data record expected."))); - return ext->dict; + return r; - lossage: - /* Come here on unsuccessful completion. */ - msg (VM (1), _("Error reading portable-file dictionary.")); - - fclose (ext->file); - if (ext && ext->dict) - dict_destroy (ext->dict); - free (ext); - h->class = NULL; - h->ext = NULL; + error: + pfm_close_reader (r); + dict_destroy (*dict); + *dict = NULL; return NULL; } /* Read a floating point value and return its value, or second_lowest_value on error. */ static double -read_float (struct file_handle *h) +read_float (struct pfm_reader *r) { - struct pfm_fhuser_ext *ext = h->ext; double num = 0.; int got_dot = 0; int got_digit = 0; @@ -316,7 +289,7 @@ read_float (struct file_handle *h) for (;;) { - if (ext->cc >= 64 /* 0 */ && ext->cc <= 93 /* T */) + if (r->cc >= 64 /* 0 */ && r->cc <= 93 /* T */) { got_digit++; @@ -331,14 +304,14 @@ read_float (struct file_handle *h) digit so that we can multiply by 10 later. */ ++exponent; else - num = (num * 30.0) + (ext->cc - 64); + num = (num * 30.0) + (r->cc - 64); /* Keep track of the number of digits after the decimal point. If we just divided by 30 here, we would lose precision. */ if (got_dot) --exponent; } - else if (!got_dot && ext->cc == 127 /* . */) + else if (!got_dot && r->cc == 127 /* . */) /* Record that we have found the decimal point. */ got_dot = 1; else @@ -349,24 +322,24 @@ read_float (struct file_handle *h) } if (!got_digit) - lose ((h, "Number expected.")); + lose ((r, "Number expected.")); - if (ext->cc == 130 /* + */ || ext->cc == 141 /* - */) + if (r->cc == 130 /* + */ || r->cc == 141 /* - */) { /* Get the exponent. */ long int exp = 0; - int neg_exp = ext->cc == 141 /* - */; + int neg_exp = r->cc == 141 /* - */; for (;;) { advance (); - if (ext->cc < 64 /* 0 */ || ext->cc > 93 /* T */) + if (r->cc < 64 /* 0 */ || r->cc > 93 /* T */) break; if (exp > LONG_MAX / 30) goto overflow; - exp = exp * 30 + (ext->cc - 64); + exp = exp * 30 + (r->cc - 64); } /* We don't check whether there were actually any digits, but we @@ -377,7 +350,7 @@ read_float (struct file_handle *h) } if (!match (142 /* / */)) - lose ((h, _("Missing numeric terminator."))); + lose ((r, _("Missing numeric terminator."))); /* Multiply NUM by 30 to the EXPONENT power, checking for overflow. */ @@ -401,23 +374,23 @@ read_float (struct file_handle *h) else return DBL_MAX / 10; - lossage: + error: return second_lowest_value; } /* Read an integer and return its value, or NOT_INT on failure. */ static int -read_int (struct file_handle *h) +read_int (struct pfm_reader *r) { - double f = read_float (h); + double f = read_float (r); if (f == second_lowest_value) - goto lossage; + goto error; if (floor (f) != f || f >= INT_MAX || f <= INT_MIN) - lose ((h, _("Bad integer format."))); + lose ((r, _("Bad integer format."))); return f; - lossage: + error: return NOT_INT; } @@ -425,13 +398,12 @@ read_int (struct file_handle *h) failure. The buffer can be deallocated by calling with a NULL argument. */ static unsigned char * -read_string (struct file_handle *h) +read_string (struct pfm_reader *r) { - struct pfm_fhuser_ext *ext = h->ext; static char *buf; int n; - if (h == NULL) + if (r == NULL) { free (buf); buf = NULL; @@ -440,18 +412,18 @@ read_string (struct file_handle *h) else if (buf == NULL) buf = xmalloc (256); - n = read_int (h); + n = read_int (r); if (n == NOT_INT) return NULL; if (n < 0 || n > 255) - lose ((h, _("Bad string length %d."), n)); + lose ((r, _("Bad string length %d."), n)); { int i; for (i = 0; i < n; i++) { - buf[i] = ext->cc; + buf[i] = r->cc; advance (); } } @@ -459,16 +431,14 @@ read_string (struct file_handle *h) buf[n] = 0; return buf; - lossage: + error: return NULL; } /* Reads the 464-byte file header. */ int -read_header (struct file_handle *h) +read_header (struct pfm_reader *r) { - struct pfm_fhuser_ext *ext = h->ext; - /* For now at least, just ignore the vanity splash strings. */ { int i; @@ -484,7 +454,7 @@ read_header (struct file_handle *h) for (i = 0; i < 256; i++) { - src[i] = (unsigned char) ext->cc; + src[i] = (unsigned char) r->cc; advance (); } @@ -498,14 +468,14 @@ read_header (struct file_handle *h) if (trans_temp[src[i]] == -1) trans_temp[src[i]] = i; - ext->trans = xmalloc (256); + r->trans = xmalloc (256); for (i = 0; i < 256; i++) - ext->trans[i] = trans_temp[i] == -1 ? 0 : trans_temp[i]; + r->trans[i] = trans_temp[i] == -1 ? 0 : trans_temp[i]; /* Translate the input buffer. */ for (i = 0; i < 80; i++) - ext->buf[i] = ext->trans[ext->buf[i]]; - ext->cc = ext->trans[ext->cc]; + r->buf[i] = r->trans[r->buf[i]]; + r->cc = r->trans[r->cc]; } { @@ -514,71 +484,69 @@ read_header (struct file_handle *h) for (i = 0; i < 8; i++) if (!match (sig[i])) - lose ((h, "Missing SPSSPORT signature.")); + lose ((r, "Missing SPSSPORT signature.")); } return 1; - lossage: + error: return 0; } /* Reads the version and date info record, as well as product and subproduct identification records if present. */ int -read_version_data (struct file_handle *h, struct pfm_read_info *inf) +read_version_data (struct pfm_reader *r, struct pfm_read_info *info) { - struct pfm_fhuser_ext *ext = h->ext; - /* Version. */ if (!match (74 /* A */)) - lose ((h, "Unrecognized version code %d.", ext->cc)); + lose ((r, "Unrecognized version code %d.", r->cc)); /* Date. */ { static const int map[] = {6, 7, 8, 9, 3, 4, 0, 1}; - char *date = read_string (h); + char *date = read_string (r); int i; if (!date) return 0; if (strlen (date) != 8) - lose ((h, _("Bad date string length %d."), strlen (date))); + lose ((r, _("Bad date string length %d."), strlen (date))); for (i = 0; i < 8; i++) { if (date[i] < 64 /* 0 */ || date[i] > 73 /* 9 */) - lose ((h, _("Bad character in date."))); - if (inf) - inf->creation_date[map[i]] = date[i] - 64 /* 0 */ + '0'; + lose ((r, _("Bad character in date."))); + if (info) + info->creation_date[map[i]] = date[i] - 64 /* 0 */ + '0'; } - if (inf) + if (info) { - inf->creation_date[2] = inf->creation_date[5] = ' '; - inf->creation_date[10] = 0; + info->creation_date[2] = info->creation_date[5] = ' '; + info->creation_date[10] = 0; } } /* Time. */ { static const int map[] = {0, 1, 3, 4, 6, 7}; - char *time = read_string (h); + char *time = read_string (r); int i; if (!time) return 0; if (strlen (time) != 6) - lose ((h, _("Bad time string length %d."), strlen (time))); + lose ((r, _("Bad time string length %d."), strlen (time))); for (i = 0; i < 6; i++) { if (time[i] < 64 /* 0 */ || time[i] > 73 /* 9 */) - lose ((h, _("Bad character in time."))); - if (inf) - inf->creation_time[map[i]] = time[i] - 64 /* 0 */ + '0'; + lose ((r, _("Bad character in time."))); + if (info) + info->creation_time[map[i]] = time[i] - 64 /* 0 */ + '0'; } - if (inf) + if (info) { - inf->creation_time[2] = inf->creation_time[5] = ' '; - inf->creation_time[8] = 0; + info->creation_time[2] = info->creation_time[5] = ' '; + info->creation_time[8] = 0; } } @@ -587,57 +555,57 @@ read_version_data (struct file_handle *h, struct pfm_read_info *inf) { char *product; - product = read_string (h); + product = read_string (r); if (product == NULL) return 0; - if (inf) - strncpy (inf->product, product, 61); + if (info) + strncpy (info->product, product, 61); } - else if (inf) - inf->product[0] = 0; + else if (info) + info->product[0] = 0; /* Subproduct. */ if (match (67 /* 3 */)) { char *subproduct; - subproduct = read_string (h); + subproduct = read_string (r); if (subproduct == NULL) return 0; - if (inf) - strncpy (inf->subproduct, subproduct, 61); + if (info) + strncpy (info->subproduct, subproduct, 61); } - else if (inf) - inf->subproduct[0] = 0; + else if (info) + info->subproduct[0] = 0; return 1; - lossage: + error: return 0; } static int -convert_format (struct file_handle *h, int fmt[3], struct fmt_spec *v, +convert_format (struct pfm_reader *r, int fmt[3], struct fmt_spec *v, struct variable *vv) { v->type = translate_fmt (fmt[0]); if (v->type == -1) - lose ((h, _("%s: Bad format specifier byte (%d)."), vv->name, fmt[0])); + lose ((r, _("%s: Bad format specifier byte (%d)."), vv->name, fmt[0])); v->w = fmt[1]; v->d = fmt[2]; /* FIXME? Should verify the resulting specifier more thoroughly. */ if (v->type == -1) - lose ((h, _("%s: Bad format specifier byte (%d)."), vv->name, fmt[0])); + lose ((r, _("%s: Bad format specifier byte (%d)."), vv->name, fmt[0])); if ((vv->type == ALPHA) ^ ((formats[v->type].cat & FCAT_STRING) != 0)) - lose ((h, _("%s variable %s has %s format specifier %s."), + lose ((r, _("%s variable %s has %s format specifier %s."), vv->type == ALPHA ? _("String") : _("Numeric"), vv->name, formats[v->type].cat & FCAT_STRING ? _("string") : _("numeric"), formats[v->type].name)); return 1; - lossage: + error: return 0; } @@ -659,52 +627,49 @@ asciify (char *s) *s = spss2ascii[(unsigned char) *s]; } -static int parse_value (struct file_handle *, union value *, struct variable *); +static int parse_value (struct pfm_reader *, union value *, struct variable *); /* Read information on all the variables. */ static int -read_variables (struct file_handle *h) +read_variables (struct pfm_reader *r, struct dictionary *dict) { - struct pfm_fhuser_ext *ext = h->ext; char *weight_name = NULL; int i; if (!match (68 /* 4 */)) - lose ((h, _("Expected variable count record."))); + lose ((r, _("Expected variable count record."))); - ext->nvars = read_int (h); - if (ext->nvars <= 0 || ext->nvars == NOT_INT) - lose ((h, _("Invalid number of variables %d."), ext->nvars)); - ext->vars = xmalloc (sizeof *ext->vars * ext->nvars); + r->var_cnt = read_int (r); + if (r->var_cnt <= 0 || r->var_cnt == NOT_INT) + lose ((r, _("Invalid number of variables %d."), r->var_cnt)); + r->widths = xmalloc (sizeof *r->widths * r->var_cnt); /* Purpose of this value is unknown. It is typically 161. */ { - int x = read_int (h); + int x = read_int (r); if (x == NOT_INT) - goto lossage; + goto error; if (x != 161) - corrupt_msg (h, _("Unexpected flag value %d."), x); + corrupt_msg (r, _("Unexpected flag value %d."), x); } - ext->dict = dict_create (); - if (match (70 /* 6 */)) { - weight_name = read_string (h); + weight_name = read_string (r); if (!weight_name) - goto lossage; + goto error; asciify (weight_name); if (strlen (weight_name) > 8) { - corrupt_msg (h, _("Weight variable name (%s) truncated."), + corrupt_msg (r, _("Weight variable name (%s) truncated."), weight_name); weight_name[8] = '\0'; } } - for (i = 0; i < ext->nvars; i++) + for (i = 0; i < r->var_cnt; i++) { int width; unsigned char *name; @@ -713,23 +678,23 @@ read_variables (struct file_handle *h) int j; if (!match (71 /* 7 */)) - lose ((h, _("Expected variable record."))); + lose ((r, _("Expected variable record."))); - width = read_int (h); + width = read_int (r); if (width == NOT_INT) - goto lossage; + goto error; if (width < 0) - lose ((h, _("Invalid variable width %d."), width)); - ext->vars[i] = width; + lose ((r, _("Invalid variable width %d."), width)); + r->widths[i] = width; - name = read_string (h); + name = read_string (r); if (name == NULL) - goto lossage; + goto error; for (j = 0; j < 6; j++) { - fmt[j] = read_int (h); + fmt[j] = read_int (r); if (fmt[j] == NOT_INT) - goto lossage; + goto error; } /* Verify first character of variable name. @@ -737,15 +702,15 @@ read_variables (struct file_handle *h) Weirdly enough, there is no # character in the SPSS portable character set, so we can't check for it. */ if (strlen (name) > 8) - lose ((h, _("position %d: Variable name has %u characters."), + lose ((r, _("position %d: Variable name has %u characters."), i, strlen (name))); if ((name[0] < 74 /* A */ || name[0] > 125 /* Z */) && name[0] != 152 /* @ */) - lose ((h, _("position %d: Variable name begins with invalid " + lose ((r, _("position %d: Variable name begins with invalid " "character."), i)); if (name[0] >= 100 /* a */ && name[0] <= 125 /* z */) { - corrupt_msg (h, _("position %d: Variable name begins with " + corrupt_msg (r, _("position %d: Variable name begins with " "lowercase letter %c."), i, name[0] - 100 + 'a'); name[0] -= 26 /* a - A */; @@ -758,7 +723,7 @@ read_variables (struct file_handle *h) if (c >= 100 /* a */ && c <= 125 /* z */) { - corrupt_msg (h, _("position %d: Variable name character %d " + corrupt_msg (r, _("position %d: Variable name character %d " "is lowercase letter %c."), i, j + 1, c - 100 + 'a'); name[j] -= 26 /* z - Z */; @@ -768,42 +733,43 @@ read_variables (struct file_handle *h) || c == 136 /* $ */ || c == 146 /* _ */) name[j] = c; else - lose ((h, _("position %d: character `\\%03o' is not " + lose ((r, _("position %d: character `\\%03o' is not " "valid in a variable name."), i, c)); } asciify (name); if (width < 0 || width > 255) - lose ((h, "Bad width %d for variable %s.", width, name)); + lose ((r, "Bad width %d for variable %s.", width, name)); - v = dict_create_var (ext->dict, name, width); - v->get.fv = v->fv; + v = dict_create_var (dict, name, width); + v->aux = xmalloc (sizeof (int)); + *(int *) v->aux = v->fv; if (v == NULL) - lose ((h, _("Duplicate variable name %s."), name)); - if (!convert_format (h, &fmt[0], &v->print, v)) - goto lossage; - if (!convert_format (h, &fmt[3], &v->write, v)) - goto lossage; + lose ((r, _("Duplicate variable name %s."), name)); + if (!convert_format (r, &fmt[0], &v->print, v)) + goto error; + if (!convert_format (r, &fmt[3], &v->write, v)) + goto error; /* Range missing values. */ if (match (75 /* B */)) { v->miss_type = MISSING_RANGE; - if (!parse_value (h, &v->missing[0], v) - || !parse_value (h, &v->missing[1], v)) - goto lossage; + if (!parse_value (r, &v->missing[0], v) + || !parse_value (r, &v->missing[1], v)) + goto error; } else if (match (74 /* A */)) { v->miss_type = MISSING_HIGH; - if (!parse_value (h, &v->missing[0], v)) - goto lossage; + if (!parse_value (r, &v->missing[0], v)) + goto error; } else if (match (73 /* 9 */)) { v->miss_type = MISSING_LOW; - if (!parse_value (h, &v->missing[0], v)) - goto lossage; + if (!parse_value (r, &v->missing[0], v)) + goto error; } /* Single missing values. */ @@ -823,19 +789,19 @@ read_variables (struct file_handle *h) v->miss_type = map_next[v->miss_type]; if (v->miss_type == -1) - lose ((h, _("Bad missing values for %s."), v->name)); + lose ((r, _("Bad missing values for %s."), v->name)); assert (map_ofs[v->miss_type] != -1); - if (!parse_value (h, &v->missing[map_ofs[v->miss_type]], v)) - goto lossage; + if (!parse_value (r, &v->missing[map_ofs[v->miss_type]], v)) + goto error; } if (match (76 /* C */)) { - char *label = read_string (h); + char *label = read_string (r); if (label == NULL) - goto lossage; + goto error; v->label = xstrdup (label); asciify (v->label); @@ -844,29 +810,29 @@ read_variables (struct file_handle *h) if (weight_name != NULL) { - struct variable *weight_var = dict_lookup_var (ext->dict, weight_name); + struct variable *weight_var = dict_lookup_var (dict, weight_name); if (weight_var == NULL) - lose ((h, _("Weighting variable %s not present in dictionary."), + lose ((r, _("Weighting variable %s not present in dictionary."), weight_name)); free (weight_name); - dict_set_weight (ext->dict, weight_var); + dict_set_weight (dict, weight_var); } return 1; - lossage: + error: free (weight_name); return 0; } /* Parse a value for variable VV into value V. Returns success. */ static int -parse_value (struct file_handle *h, union value *v, struct variable *vv) +parse_value (struct pfm_reader *r, union value *v, struct variable *vv) { if (vv->type == ALPHA) { - char *mv = read_string (h); + char *mv = read_string (r); int j; if (mv == NULL) @@ -882,7 +848,7 @@ parse_value (struct file_handle *h, union value *v, struct variable *vv) } else { - v->f = read_float (h); + v->f = read_float (r); if (v->f == second_lowest_value) return 0; } @@ -892,10 +858,8 @@ parse_value (struct file_handle *h, union value *v, struct variable *vv) /* Parse a value label record and return success. */ static int -read_value_label (struct file_handle *h) +read_value_label (struct pfm_reader *r, struct dictionary *dict) { - struct pfm_fhuser_ext *ext = h->ext; - /* Variables. */ int nv; struct variable **v; @@ -905,31 +869,31 @@ read_value_label (struct file_handle *h) int i; - nv = read_int (h); + nv = read_int (r); if (nv == NOT_INT) return 0; v = xmalloc (sizeof *v * nv); for (i = 0; i < nv; i++) { - char *name = read_string (h); + char *name = read_string (r); if (name == NULL) - goto lossage; + goto error; asciify (name); - v[i] = dict_lookup_var (ext->dict, name); + v[i] = dict_lookup_var (dict, name); if (v[i] == NULL) - lose ((h, _("Unknown variable %s while parsing value labels."), name)); + lose ((r, _("Unknown variable %s while parsing value labels."), name)); if (v[0]->width != v[i]->width) - lose ((h, _("Cannot assign value labels to %s and %s, which " + lose ((r, _("Cannot assign value labels to %s and %s, which " "have different variable types or widths."), v[0]->name, v[i]->name)); } - n_labels = read_int (h); + n_labels = read_int (r); if (n_labels == NOT_INT) - goto lossage; + goto error; for (i = 0; i < n_labels; i++) { @@ -938,12 +902,12 @@ read_value_label (struct file_handle *h) int j; - if (!parse_value (h, &val, v[0])) - goto lossage; + if (!parse_value (r, &val, v[0])) + goto error; - label = read_string (h); + label = read_string (r); if (label == NULL) - goto lossage; + goto error; asciify (label); /* Assign the value_label's to each variable. */ @@ -955,90 +919,64 @@ read_value_label (struct file_handle *h) continue; if (var->type == NUMERIC) - lose ((h, _("Duplicate label for value %g for variable %s."), + lose ((r, _("Duplicate label for value %g for variable %s."), val.f, var->name)); else - lose ((h, _("Duplicate label for value `%.*s' for variable %s."), + lose ((r, _("Duplicate label for value `%.*s' for variable %s."), var->width, val.s, var->name)); } } free (v); return 1; - lossage: + error: free (v); return 0; } -/* Reads one case from portable file H into PERM - according to the instuctions given in associated dictionary DICT, - which must have the get.fv elements appropriately set. Returns - nonzero only if successful. */ +/* Reads one case from portable file R into C. Returns nonzero + only if successful. */ int -pfm_read_case (struct file_handle *h, struct ccase *perm, - struct dictionary *dict) +pfm_read_case (struct pfm_reader *r, struct ccase *c) { - struct pfm_fhuser_ext *ext = h->ext; - - union value *temp, *tp; - int i; + size_t i; + size_t idx; /* Check for end of file. */ - if (ext->cc == 99 /* Z */) + if (r->cc == 99 /* Z */) return 0; - /* The first concern is to obtain a full case relative to the data - file. (Cases in the data file have no particular relationship to - cases in the active file.) */ - tp = temp = local_alloc (sizeof *tp * ext->case_size); - for (tp = temp, i = 0; i < ext->nvars; i++) - if (ext->vars[i] == 0) - { - tp->f = read_float (h); - if (tp->f == second_lowest_value) - goto unexpected_eof; - tp++; - } - else - { - char *s = read_string (h); - if (s == NULL) - goto unexpected_eof; - asciify (s); - - st_bare_pad_copy (tp->s, s, ext->vars[i]); - tp += DIV_RND_UP (ext->vars[i], MAX_SHORT_STRING); - } - - /* Translate a case in data file format to a case in active file - format. */ - for (i = 0; i < dict_get_var_cnt (dict); i++) + idx = 0; + for (i = 0; i < r->var_cnt; i++) { - struct variable *v = dict_get_var (dict, i); - - if (v->get.fv == -1) - continue; + int width = r->widths[i]; - if (v->type == NUMERIC) - case_data_rw (perm, v->fv)->f = temp[v->get.fv].f; + if (width == 0) + { + double f = read_float (r); + if (f == second_lowest_value) + goto unexpected_eof; + + case_data_rw (c, idx)->f = f; + idx++; + } else - memcpy (case_data_rw (perm, v->fv)->s, &temp[v->get.fv], v->width); - } + { + char *s = read_string (r); + if (s == NULL) + goto unexpected_eof; + asciify (s); - local_free (temp); + st_bare_pad_copy (case_data_rw (c, idx)->s, s, width); + idx += DIV_RND_UP (width, MAX_SHORT_STRING); + } + } + return 1; unexpected_eof: - lose ((h, _("End of file midway through case."))); + lose ((r, _("End of file midway through case."))); - lossage: - local_free (temp); + error: return 0; } - -static struct fh_ext_class pfm_r_class = -{ - 5, - N_("reading as a portable file"), - pfm_close, -}; diff --git a/src/pfm-read.h b/src/pfm-read.h new file mode 100644 index 00000000..bb37f1db --- /dev/null +++ b/src/pfm-read.h @@ -0,0 +1,51 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef PFM_READ_H +#define PFM_READ_H + +/* Portable file reading. */ + +/* Portable file types. */ +enum pfm_type + { + PFM_COMM, /* Formatted for communication. */ + PFM_TAPE /* Formatted for tape. */ + }; + +/* Information produced by pfm_read_dictionary() that doesn't fit into + a dictionary struct. */ +struct pfm_read_info + { + char creation_date[11]; /* `dd mm yyyy' plus a null. */ + char creation_time[9]; /* `hh:mm:ss' plus a null. */ + char product[61]; /* Product name plus a null. */ + char subproduct[61]; /* Subproduct name plus a null. */ + }; + +struct dictionary; +struct file_handle; +struct ccase; +struct pfm_reader *pfm_open_reader (struct file_handle *, + struct dictionary **, + struct pfm_read_info *); +int pfm_read_case (struct pfm_reader *, struct ccase *); +void pfm_close_reader (struct pfm_reader *); + +#endif /* pfm-read.h */ diff --git a/src/pfm-write.c b/src/pfm-write.c index 1d553ed7..bdd93c99 100644 --- a/src/pfm-write.c +++ b/src/pfm-write.c @@ -18,7 +18,7 @@ 02111-1307, USA. */ #include -#include "pfm.h" +#include "pfm-write.h" #include "error.h" #include #include @@ -28,6 +28,8 @@ #include #include #include "alloc.h" +#include "case.h" +#include "dictionary.h" #include "error.h" #include "file-handle.h" #include "gmp.h" @@ -40,142 +42,124 @@ #include "debug-print.h" -/* pfm writer file_handle extension. */ -struct pfm_fhuser_ext +/* Portable file writer. */ +struct pfm_writer { - FILE *file; /* Actual file. */ + struct file_handle *fh; /* File handle. */ + FILE *file; /* File stream. */ int lc; /* Number of characters on this line so far. */ - int nvars; /* Number of variables. */ - int *vars; /* Variable widths. */ + size_t var_cnt; /* Number of variables. */ + struct pfm_var *vars; /* Variables. */ }; -static struct fh_ext_class pfm_w_class; +/* A variable to write to the portable file. */ +struct pfm_var + { + int width; /* 0=numeric, otherwise string var width. */ + int fv; /* Starting case index. */ + }; -static int bufwrite (struct file_handle *h, const void *buf, size_t nbytes); -static int write_header (struct file_handle *h); -static int write_version_data (struct file_handle *h); -static int write_variables (struct file_handle *h, struct dictionary *d); -static int write_value_labels (struct file_handle *h, struct dictionary *d); +static int buf_write (struct pfm_writer *, const void *, size_t); +static int write_header (struct pfm_writer *); +static int write_version_data (struct pfm_writer *); +static int write_variables (struct pfm_writer *, const struct dictionary *); +static int write_value_labels (struct pfm_writer *, const struct dictionary *); /* Writes the dictionary DICT to portable file HANDLE. Returns nonzero only if successful. */ -int -pfm_write_dictionary (struct file_handle *handle, struct dictionary *dict) +struct pfm_writer * +pfm_open_writer (struct file_handle *fh, const struct dictionary *dict) { - struct pfm_fhuser_ext *ext; - - if (handle->class != NULL) - { - msg (ME, _("Cannot write file %s as portable file: already opened " - "for %s."), - handle_get_name (handle), handle->class->name); - return 0; - } + struct pfm_writer *w = NULL; + size_t i; - msg (VM (1), _("%s: Opening portable-file handle %s for writing."), - handle_get_filename (handle), handle_get_name (handle)); + if (!fh_open (fh, "portable file", "we")) + goto error; /* Open the physical disk file. */ - handle->class = &pfm_w_class; - handle->ext = ext = xmalloc (sizeof (struct pfm_fhuser_ext)); - ext->file = fopen (handle_get_filename (handle), "wb"); - ext->lc = 0; - if (ext->file == NULL) + w = xmalloc (sizeof *w); + w->fh = fh; + w->file = fopen (handle_get_filename (fh), "wb"); + w->lc = 0; + w->var_cnt = 0; + w->vars = NULL; + + /* Check that file create succeeded. */ + if (w->file == NULL) { msg (ME, _("An error occurred while opening \"%s\" for writing " "as a portable file: %s."), - handle_get_filename (handle), strerror (errno)); + handle_get_filename (fh), strerror (errno)); err_cond_fail (); - free (ext); - return 0; + goto error; } - { - int i; - - ext->nvars = dict_get_var_cnt (dict); - ext->vars = xmalloc (sizeof *ext->vars * ext->nvars); - for (i = 0; i < ext->nvars; i++) - ext->vars[i] = dict_get_var (dict, i)->width; - } - - /* Write the file header. */ - if (!write_header (handle)) - goto lossage; - - /* Write version data. */ - if (!write_version_data (handle)) - goto lossage; - - /* Write variables. */ - if (!write_variables (handle, dict)) - goto lossage; - - /* Write value labels. */ - if (!write_value_labels (handle, dict)) - goto lossage; + w->var_cnt = dict_get_var_cnt (dict); + w->vars = xmalloc (sizeof *w->vars * w->var_cnt); + for (i = 0; i < w->var_cnt; i++) + { + const struct variable *dv = dict_get_var (dict, i); + struct pfm_var *pv = &w->vars[i]; + pv->width = dv->width; + pv->fv = dv->fv; + } - /* Write beginning of data marker. */ - if (!bufwrite (handle, "F", 1)) - goto lossage; + /* Write file header. */ + if (!write_header (w) + || !write_version_data (w) + || !write_variables (w, dict) + || !write_value_labels (w, dict) + || !buf_write (w, "F", 1)) + goto error; - msg (VM (2), _("Wrote portable-file header successfully.")); + return w; - return 1; - -lossage: - msg (VM (1), _("Error writing portable-file header.")); - fclose (ext->file); - free (ext->vars); - handle->class = NULL; - handle->ext = NULL; - return 0; +error: + pfm_close_writer (w); + return NULL; } /* Write NBYTES starting at BUF to the portable file represented by H. Break lines properly every 80 characters. */ static int -bufwrite (struct file_handle *h, const void *buf_, size_t nbytes) +buf_write (struct pfm_writer *w, const void *buf_, size_t nbytes) { const char *buf = buf_; - struct pfm_fhuser_ext *ext = h->ext; assert (buf != NULL); - while (nbytes + ext->lc >= 80) + while (nbytes + w->lc >= 80) { - size_t n = 80 - ext->lc; + size_t n = 80 - w->lc; - if (n && 1 != fwrite (buf, n, 1, ext->file)) - goto lossage; + if (n && fwrite (buf, n, 1, w->file) != 1) + goto error; - /* PORTME: line ends. */ - if (1 != fwrite ("\r\n", 2, 1, ext->file)) - goto lossage; + if (fwrite ("\r\n", 2, 1, w->file) != 1) + goto error; nbytes -= n; buf += n; - ext->lc = 0; + w->lc = 0; } - if (nbytes && 1 != fwrite (buf, nbytes, 1, ext->file)) - goto lossage; - ext->lc += nbytes; + if (nbytes && 1 != fwrite (buf, nbytes, 1, w->file)) + goto error; + w->lc += nbytes; return 1; - lossage: - abort (); + error: msg (ME, _("%s: Writing portable file: %s."), - handle_get_filename (h), strerror (errno)); + handle_get_filename (w->fh), strerror (errno)); return 0; } /* Write D to the portable file as a floating-point field, and return success. */ static int -write_float (struct file_handle *h, double d) +write_float (struct pfm_writer *w, double d) { int neg = 0; char *mantissa; @@ -191,7 +175,7 @@ write_float (struct file_handle *h, double d) } if (d == fabs (SYSMIS) || d == HUGE_VAL) - return bufwrite (h, "*.", 2); + return buf_write (w, "*.", 2); /* Use GNU libgmp2 to convert D into base-30. */ { @@ -238,7 +222,7 @@ write_float (struct file_handle *h, double d) } *cp++ = '/'; - success = bufwrite (h, buf, cp - buf); + success = buf_write (w, buf, cp - buf); local_free (buf); free (mantissa); return success; @@ -246,7 +230,7 @@ write_float (struct file_handle *h, double d) /* Write N to the portable file as an integer field, and return success. */ static int -write_int (struct file_handle *h, int n) +write_int (struct pfm_writer *w, int n) { char buf[64]; char *bp = &buf[64]; @@ -277,27 +261,27 @@ write_int (struct file_handle *h, int n) if (neg) *--bp = '-'; - return bufwrite (h, bp, &buf[64] - bp); + return buf_write (w, bp, &buf[64] - bp); } /* Write S to the portable file as a string field. */ static int -write_string (struct file_handle *h, const char *s) +write_string (struct pfm_writer *w, const char *s) { size_t n = strlen (s); - return write_int (h, (int) n) && bufwrite (h, s, n); + return write_int (w, (int) n) && buf_write (w, s, n); } /* Write file header. */ static int -write_header (struct file_handle *h) +write_header (struct pfm_writer *w) { /* PORTME. */ { int i; for (i = 0; i < 5; i++) - if (!bufwrite (h, "ASCII SPSS PORT FILE ", 40)) + if (!buf_write (w, "ASCII SPSS PORT FILE ", 40)) return 0; } @@ -312,11 +296,11 @@ write_header (struct file_handle *h) "0000000000000000000000000000000000000000000000000000000000000000" }; - if (!bufwrite (h, spss2ascii, 256)) + if (!buf_write (w, spss2ascii, 256)) return 0; } - if (!bufwrite (h, "SPSSPORT", 8)) + if (!buf_write (w, "SPSSPORT", 8)) return 0; return 1; @@ -324,9 +308,9 @@ write_header (struct file_handle *h) /* Writes version, date, and identification records. */ static int -write_version_data (struct file_handle *h) +write_version_data (struct pfm_writer *w) { - if (!bufwrite (h, "A", 1)) + if (!buf_write (w, "A", 1)) return 0; { @@ -348,16 +332,16 @@ write_version_data (struct file_handle *h) sprintf (date_str, "%04d%02d%02d", tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday); sprintf (time_str, "%02d%02d%02d", tmp->tm_hour, tmp->tm_min, tmp->tm_sec); - if (!write_string (h, date_str) || !write_string (h, time_str)) + if (!write_string (w, date_str) || !write_string (w, time_str)) return 0; } /* Product identification. */ - if (!bufwrite (h, "1", 1) || !write_string (h, version)) + if (!buf_write (w, "1", 1) || !write_string (w, version)) return 0; /* Subproduct identification. */ - if (!bufwrite (h, "3", 1) || !write_string (h, host_system)) + if (!buf_write (w, "3", 1) || !write_string (w, host_system)) return 0; return 1; @@ -365,31 +349,31 @@ write_version_data (struct file_handle *h) /* Write format F to file H, and return success. */ static int -write_format (struct file_handle *h, struct fmt_spec *f) +write_format (struct pfm_writer *w, struct fmt_spec *f) { - return (write_int (h, formats[f->type].spss) - && write_int (h, f->w) - && write_int (h, f->d)); + return (write_int (w, formats[f->type].spss) + && write_int (w, f->w) + && write_int (w, f->d)); } /* Write value V for variable VV to file H, and return success. */ static int -write_value (struct file_handle *h, union value *v, struct variable *vv) +write_value (struct pfm_writer *w, union value *v, struct variable *vv) { if (vv->type == NUMERIC) - return write_float (h, v->f); + return write_float (w, v->f); else - return write_int (h, vv->width) && bufwrite (h, v->s, vv->width); + return write_int (w, vv->width) && buf_write (w, v->s, vv->width); } /* Write variable records, and return success. */ static int -write_variables (struct file_handle *h, struct dictionary *dict) +write_variables (struct pfm_writer *w, const struct dictionary *dict) { int i; - if (!bufwrite (h, "4", 1) || !write_int (h, dict_get_var_cnt (dict)) - || !write_int (h, 161)) + if (!buf_write (w, "4", 1) || !write_int (w, dict_get_var_cnt (dict)) + || !write_int (w, 161)) return 0; for (i = 0; i < dict_get_var_cnt (dict); i++) @@ -404,17 +388,17 @@ write_variables (struct file_handle *h, struct dictionary *dict) struct variable *v = dict_get_var (dict, i); - if (!bufwrite (h, "7", 1) || !write_int (h, v->width) - || !write_string (h, v->name) - || !write_format (h, &v->print) || !write_format (h, &v->write)) + if (!buf_write (w, "7", 1) || !write_int (w, v->width) + || !write_string (w, v->name) + || !write_format (w, &v->print) || !write_format (w, &v->write)) return 0; for (m = miss_types[v->miss_type], j = 0; j < (int) strlen (m); j++) - if ((m[j] != ' ' && !bufwrite (h, &m[j], 1)) - || !write_value (h, &v->missing[j], v)) + if ((m[j] != ' ' && !buf_write (w, &m[j], 1)) + || !write_value (w, &v->missing[j], v)) return 0; - if (v->label && (!bufwrite (h, "C", 1) || !write_string (h, v->label))) + if (v->label && (!buf_write (w, "C", 1) || !write_string (w, v->label))) return 0; } @@ -423,7 +407,7 @@ write_variables (struct file_handle *h, struct dictionary *dict) /* Write value labels to disk. FIXME: Inefficient. */ static int -write_value_labels (struct file_handle *h, struct dictionary *dict) +write_value_labels (struct pfm_writer *w, const struct dictionary *dict) { int i; @@ -436,16 +420,16 @@ write_value_labels (struct file_handle *h, struct dictionary *dict) if (!val_labs_count (v->val_labs)) continue; - if (!bufwrite (h, "D", 1) - || !write_int (h, 1) - || !write_string (h, v->name) - || !write_int (h, val_labs_count (v->val_labs))) + if (!buf_write (w, "D", 1) + || !write_int (w, 1) + || !write_string (w, v->name) + || !write_int (w, val_labs_count (v->val_labs))) return 0; for (vl = val_labs_first_sorted (v->val_labs, &j); vl != NULL; vl = val_labs_next (v->val_labs, &j)) - if (!write_value (h, &vl->value, v) - || !write_string (h, vl->label)) + if (!write_value (w, &vl->value, v) + || !write_string (w, vl->label)) { val_labs_done (&j); return 0; @@ -458,24 +442,23 @@ write_value_labels (struct file_handle *h, struct dictionary *dict) /* Writes case ELEM to the portable file represented by H. Returns success. */ int -pfm_write_case (struct file_handle *h, const union value *elem) +pfm_write_case (struct pfm_writer *w, struct ccase *c) { - struct pfm_fhuser_ext *ext = h->ext; - int i; - for (i = 0; i < ext->nvars; i++) + for (i = 0; i < w->var_cnt; i++) { - const int width = ext->vars[i]; + struct pfm_var *v = &w->vars[i]; - if (width == 0) + if (v->width == 0) { - if (!write_float (h, elem[i].f)) + if (!write_float (w, case_num (c, v->fv))) return 0; } else { - if (!write_int (h, width) || !bufwrite (h, elem[i].c, width)) + if (!write_int (w, v->width) + || !buf_write (w, case_str (c, v->fv), v->width)) return 0; } } @@ -484,33 +467,30 @@ pfm_write_case (struct file_handle *h, const union value *elem) } /* Closes a portable file after we're done with it. */ -static void -pfm_close (struct file_handle *h) +void +pfm_close_writer (struct pfm_writer *w) { - struct pfm_fhuser_ext *ext = h->ext; + if (w == NULL) + return; + + fh_close (w->fh, "portable file", "we"); - { - char buf[80]; + if (w->file != NULL) + { + char buf[80]; - int n = 80 - ext->lc; - if (n == 0) - n = 80; + int n = 80 - w->lc; + if (n == 0) + n = 80; - memset (buf, 'Z', n); - bufwrite (h, buf, n); - } + memset (buf, 'Z', n); + buf_write (w, buf, n); - if (EOF == fclose (ext->file)) - msg (ME, _("%s: Closing portable file: %s."), - handle_get_filename (h), strerror (errno)); + if (fclose (w->file) == EOF) + msg (ME, _("%s: Closing portable file: %s."), + handle_get_filename (w->fh), strerror (errno)); + } - free (ext->vars); - free (ext); + free (w->vars); + free (w); } - -static struct fh_ext_class pfm_w_class = -{ - 6, - N_("writing as a portable file"), - pfm_close, -}; diff --git a/src/pfm-write.h b/src/pfm-write.h new file mode 100644 index 00000000..1f845d83 --- /dev/null +++ b/src/pfm-write.h @@ -0,0 +1,33 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef PFM_WRITE_H +#define PFM_WRITE_H + +/* Portable file writing. */ + +struct file_handle; +struct dictionary; +struct ccase; +struct pfm_writer *pfm_open_writer (struct file_handle *, + const struct dictionary *); +int pfm_write_case (struct pfm_writer *, struct ccase *); +void pfm_close_writer (struct pfm_writer *); + +#endif /* pfm-write.h */ diff --git a/src/pfm.h b/src/pfm.h deleted file mode 100644 index 172a8f53..00000000 --- a/src/pfm.h +++ /dev/null @@ -1,57 +0,0 @@ -/* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . - - 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -#if !pfm_h -#define pfm_h 1 - -/* Portable file manager (pfm). - - This module is in charge of reading and writing portable files. - pfm is an fhuser, so see file-handle.h for the fhuser interface. */ - -/* Portable file types. */ -enum - { - PFM_COMM, - PFM_TAPE - }; - -/* Information produced by pfm_read_dictionary() that doesn't fit into - a dictionary struct. */ -struct pfm_read_info - { - char creation_date[11]; /* `dd mm yyyy' plus a null. */ - char creation_time[9]; /* `hh:mm:ss' plus a null. */ - char product[61]; /* Product name plus a null. */ - char subproduct[61]; /* Subproduct name plus a null. */ - }; - -struct dictionary; -struct file_handle; -struct ccase; -union value; - -struct dictionary *pfm_read_dictionary (struct file_handle *, - struct pfm_read_info *); -int pfm_read_case (struct file_handle *, struct ccase *, struct dictionary *); - -int pfm_write_dictionary (struct file_handle *, struct dictionary *); -int pfm_write_case (struct file_handle *, const union value *elem); - -#endif /* !pfm_h */ diff --git a/src/piechart.c b/src/piechart.c index 29e0c791..4e0725e6 100644 --- a/src/piechart.c +++ b/src/piechart.c @@ -19,16 +19,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include "chart.h" #include #include #include #include +#include "str.h" #include "value-labels.h" /* Pie charts of course need to know Pi :) */ +#ifndef M_PI #define M_PI ( 22.0 / 7.0 ) +#endif #define min(A,B) ((A>B)?B:A) @@ -45,12 +49,11 @@ draw_segment(struct chart *ch, /* Draw a pie chart */ void -draw_piechart(struct chart *ch, const struct variable *var) +draw_piechart(struct chart *ch, const struct variable *var, + const struct freq_tab *frq_tab) { int i; - const struct freq_tab *frq_tab = &var->p.frq.tab ; - const int n_data = frq_tab->n_valid; const double left_label = ch->data_left + (ch->data_right - ch->data_left)/10.0; diff --git a/src/print.c b/src/print.c index 1bbc5ae6..b2ef755c 100644 --- a/src/print.c +++ b/src/print.c @@ -25,7 +25,7 @@ #include "alloc.h" #include "case.h" #include "command.h" -#include "dfm.h" +#include "dfm-write.h" #include "error.h" #include "expr.h" #include "file-handle.h" @@ -70,14 +70,15 @@ enum PRT_CMD_MASK = 1, /* Command type mask. */ PRT_PRINT = 0, /* PRINT transformation identifier. */ PRT_WRITE = 1, /* WRITE transformation identifier. */ - PRT_EJECT = 002 /* Can be combined with CMD_PRINT only. */ + PRT_EJECT = 002, /* Can be combined with CMD_PRINT only. */ + PRT_BINARY = 004 /* File is binary, omit newlines. */ }; /* PRINT, PRINT EJECT, WRITE private data structure. */ struct print_trns { struct trns_header h; - struct file_handle *handle; /* Output file, NULL=listing file. */ + struct dfm_writer *writer; /* Output file, NULL=listing file. */ int options; /* PRT_* bitmapped field. */ struct prt_out_spec *spec; /* Output specifications. */ int max_width; /* Maximum line width including null. */ @@ -100,8 +101,8 @@ static int internal_cmd_print (int flags); static trns_proc_func print_trns_proc; static trns_free_func print_trns_free; static int parse_specs (void); -static void dump_table (void); -static void append_var_spec (struct prt_out_spec *spec); +static void dump_table (const struct file_handle *); +static void append_var_spec (struct prt_out_spec *); static void alloc_line (void); /* Basic parsing. */ @@ -132,16 +133,14 @@ cmd_write (void) static int internal_cmd_print (int f) { - /* 0=print no table, 1=print table. (TABLE subcommand.) */ - int table = 0; - - /* malloc()'d transformation. */ - struct print_trns *trns; + int table = 0; /* Print table? */ + struct print_trns *trns; /* malloc()'d transformation. */ + struct file_handle *fh = NULL; /* Fill in prt to facilitate error-handling. */ prt.h.proc = print_trns_proc; prt.h.free = print_trns_free; - prt.handle = NULL; + prt.writer = NULL; prt.options = f; prt.spec = NULL; prt.line = NULL; @@ -157,16 +156,16 @@ internal_cmd_print (int f) { lex_match ('='); - prt.handle = fh_parse_file_handle (); - if (!prt.handle) - goto lossage; + fh = fh_parse (); + if (fh == NULL) + goto error; } else if (lex_match_id ("RECORDS")) { lex_match ('='); lex_match ('('); if (!lex_force_int ()) - goto lossage; + goto error; nrec = lex_integer (); lex_get (); lex_match (')'); @@ -178,20 +177,27 @@ internal_cmd_print (int f) else { lex_error (_("expecting a valid subcommand")); - goto lossage; + goto error; } } /* Parse variables and strings. */ if (!parse_specs ()) - goto lossage; - - if (prt.handle != NULL && !dfm_open_for_writing (prt.handle)) - goto lossage; + goto error; + + if (fh != NULL) + { + prt.writer = dfm_open_writer (fh); + if (prt.writer == NULL) + goto error; + + if (handle_get_mode (fh) == MODE_BINARY) + prt.options |= PRT_BINARY; + } /* Output the variable table if requested. */ if (table) - dump_table (); + dump_table (fh); /* Count the maximum line width. Allocate linebuffer if applicable. */ @@ -204,7 +210,7 @@ internal_cmd_print (int f) return CMD_SUCCESS; - lossage: + error: print_trns_free ((struct trns_header *) & prt); return CMD_FAILURE; } @@ -775,7 +781,7 @@ fail: /* Prints the table produced by the TABLE subcommand to the listing file. */ static void -dump_table (void) +dump_table (const struct file_handle *fh) { struct prt_out_spec *spec; struct tab_table *t; @@ -831,9 +837,9 @@ dump_table (void) assert (0); } - if (prt.handle != NULL) + if (fh != NULL) tab_title (t, 1, _("Writing %d record(s) to file %s."), - recno, handle_get_filename (prt.handle)); + recno, handle_get_filename (fh)); else tab_title (t, 1, _("Writing %d record(s) to the listing file."), recno); tab_submit (t); @@ -911,15 +917,14 @@ print_trns_proc (struct trns_header * trns, struct ccase * c, if (t->options & PRT_EJECT) som_eject_page (); - /* Note that a field written to a place where a field has already - been written truncates the record. `PRINT /A B (T10,F8,T1,F8).' - only outputs B. This is an example of bug-for-bug compatibility, - in the author's opinion. */ + /* Note that a field written to a place where a field has + already been written truncates the record. `PRINT /A B + (T10,F8,T1,F8).' only outputs B. */ for (i = t->spec; i; i = i->next) switch (i->type) { case PRT_NEWLINE: - if (t->handle == NULL) + if (t->writer == NULL) { buf[len] = 0; tab_output_text (TAT_FIX | TAT_NOWRAP, buf); @@ -927,7 +932,7 @@ print_trns_proc (struct trns_header * trns, struct ccase * c, else { if ((t->options & PRT_CMD_MASK) == PRT_PRINT - || handle_get_mode (t->handle) != MODE_BINARY) + || !(t->options & PRT_BINARY)) { /* PORTME: Line ends. */ #ifdef __MSDOS__ @@ -936,7 +941,7 @@ print_trns_proc (struct trns_header * trns, struct ccase * c, buf[len++] = '\n'; } - dfm_put_record (t->handle, buf, len); + dfm_put_record (t->writer, buf, len); } memset (buf, ' ', t->max_width); @@ -1003,7 +1008,7 @@ struct print_space_trns { struct trns_header h; - struct file_handle *handle; /* Output file, NULL=listing file. */ + struct dfm_writer *writer; /* Output data file. */ struct expression *e; /* Number of lines; NULL=1. */ } print_space_trns; @@ -1015,20 +1020,21 @@ int cmd_print_space (void) { struct print_space_trns *t; - struct file_handle *handle; + struct file_handle *fh; struct expression *e; + struct dfm_writer *writer; if (lex_match_id ("OUTFILE")) { lex_match ('='); - handle = fh_parse_file_handle (); - if (handle == NULL) + fh = fh_parse (); + if (fh == NULL) return CMD_FAILURE; lex_get (); } else - handle = NULL; + fh = NULL; if (token != '.') { @@ -1043,19 +1049,25 @@ cmd_print_space (void) else e = NULL; - if (handle != NULL && !dfm_open_for_writing (handle)) + if (fh != NULL) { - expr_free (e); - return CMD_FAILURE; + writer = dfm_open_writer (fh); + if (writer == NULL) + { + expr_free (e); + return CMD_FAILURE; + } } - + else + writer = NULL; + t = xmalloc (sizeof *t); t->h.proc = print_space_trns_proc; if (e) t->h.free = print_space_trns_free; else t->h.free = NULL; - t->handle = handle; + t->writer = writer; t->e = e; add_transformation ((struct trns_header *) t); @@ -1087,7 +1099,7 @@ print_space_trns_proc (struct trns_header * trns, struct ccase * c, else n = 1; - if (t->handle == NULL) + if (t->writer == NULL) while (n--) som_blank_line (); else @@ -1102,7 +1114,7 @@ print_space_trns_proc (struct trns_header * trns, struct ccase * c, buf[0] = '\n'; #endif while (n--) - dfm_put_record (t->handle, buf, LINE_END_WIDTH); + dfm_put_record (t->writer, buf, LINE_END_WIDTH); } return -1; diff --git a/src/q2c.c b/src/q2c.c index fec3e3ab..0ffc79f0 100644 --- a/src/q2c.c +++ b/src/q2c.c @@ -2022,11 +2022,6 @@ dump_header (void) dump (0, " Generated by q2c from %s on %s.", ifn, timep); dump (0, " Do not modify!"); dump (0, " */"); - - dump (0, nullstr); - dump (0, "#include \"settings.h\""); - dump (0, "#include \"subclist.h\""); - dump (0, nullstr); } /* Write out commands to free variable state. */ @@ -2165,7 +2160,9 @@ main (int argc, char *argv[]) dump (0, "#include \"alloc.h\""); dump (0, "#include \"error.h\""); dump (0, "#include \"lexer.h\""); + dump (0, "#include \"settings.h\""); dump (0, "#include \"str.h\""); + dump (0, "#include \"subclist.h\""); dump (0, "#include \"var.h\""); dump (0, nullstr); diff --git a/src/recode.c b/src/recode.c index 089caba1..034ae959 100644 --- a/src/recode.c +++ b/src/recode.c @@ -25,6 +25,7 @@ #include "alloc.h" #include "case.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "lexer.h" #include "magic.h" diff --git a/src/rename-vars.c b/src/rename-vars.c index 70243468..0219f283 100644 --- a/src/rename-vars.c +++ b/src/rename-vars.c @@ -22,6 +22,7 @@ #include "error.h" #include "alloc.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "hash.h" #include "lexer.h" diff --git a/src/repeat.c b/src/repeat.c index 2d788e27..3b57b66a 100644 --- a/src/repeat.c +++ b/src/repeat.c @@ -25,6 +25,7 @@ #include #include "alloc.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "getline.h" #include "lexer.h" diff --git a/src/sel-if.c b/src/sel-if.c index 6f6f2d02..8d224d02 100644 --- a/src/sel-if.c +++ b/src/sel-if.c @@ -20,6 +20,7 @@ #include #include "alloc.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "expr.h" #include "lexer.h" diff --git a/src/sfm-read.c b/src/sfm-read.c index 8ac6f8bd..9c0cc6d3 100644 --- a/src/sfm-read.c +++ b/src/sfm-read.c @@ -18,15 +18,17 @@ 02111-1307, USA. */ #include -#include "sfm.h" +#include "sfm-read.h" #include "sfmP.h" #include "error.h" #include #include #include #include +#include #include "alloc.h" #include "case.h" +#include "dictionary.h" #include "error.h" #include "file-handle.h" #include "filename.h" @@ -41,84 +43,75 @@ #include "debug-print.h" -/* PORTME: This file may require substantial revision for those - systems that don't meet the typical 32-bit integer/64-bit double - model. It's kinda hard to tell without having one of them on my - desk. */ - -/* sfm's file_handle extension. */ -struct sfm_fhuser_ext +/* System file reader. */ +struct sfm_reader { - FILE *file; /* Actual file. */ - int opened; /* Reference count. */ - - struct dictionary *dict; /* File's dictionary. */ + struct file_handle *fh; /* File handle. */ + FILE *file; /* File stream. */ int reverse_endian; /* 1=file has endianness opposite us. */ - int case_size; /* Number of `values's per case. */ - long ncases; /* Number of cases, -1 if unknown. */ + int fix_specials; /* 1=SYSMIS/HIGHEST/LOWEST differs from us. */ + int value_cnt; /* Number of `union values's per case. */ + long case_cnt; /* Number of cases, -1 if unknown. */ int compressed; /* 1=compressed, 0=not compressed. */ double bias; /* Compression bias, usually 100.0. */ - int weight_index; /* 0-based index of weighting variable, or -1. */ + int weight_idx; /* 0-based index of weighting variable, or -1. */ + + /* Variables. */ + struct sfm_var *vars; /* Variables. */ + size_t var_cnt; /* Number of variables. */ /* File's special constants. */ flt64 sysmis; flt64 highest; flt64 lowest; - /* Uncompression buffer. */ + /* Decompression buffer. */ flt64 *buf; /* Buffer data. */ flt64 *ptr; /* Current location in buffer. */ flt64 *end; /* End of buffer data. */ /* Compression instruction octet. */ - unsigned char x[sizeof (flt64)]; - /* Current instruction octet. */ + unsigned char x[8]; /* Current instruction octet. */ unsigned char *y; /* Location in current instruction octet. */ }; -static struct fh_ext_class sfm_r_class; +/* A variable in a system file. */ +struct sfm_var + { + int width; /* 0=numeric, otherwise string width. */ + int fv; /* Index into case. */ + }; /* Utilities. */ -/* bswap_int32(): Reverse the byte order of 32-bit integer *X. */ +/* Swap bytes *A and *B. */ static inline void -bswap_int32 (int32 *x) +bswap (unsigned char *a, unsigned char *b) { - unsigned char *y = (unsigned char *) x; - unsigned char t; - - t = y[0]; - y[0] = y[3]; - y[3] = t; + unsigned char t = *a; + *a = *b; + *b = t; +} - t = y[1]; - y[1] = y[2]; - y[2] = t; +/* bswap_int32(): Reverse the byte order of 32-bit integer *X. */ +static inline void +bswap_int32 (int32 *x_) +{ + unsigned char *x = (unsigned char *) x_; + bswap (x + 0, x + 3); + bswap (x + 1, x + 2); } /* Reverse the byte order of 64-bit floating point *X. */ static inline void -bswap_flt64 (flt64 *x) +bswap_flt64 (flt64 *x_) { - unsigned char *y = (unsigned char *) x; - unsigned char t; - - t = y[0]; - y[0] = y[7]; - y[7] = t; - - t = y[1]; - y[1] = y[6]; - y[6] = t; - - t = y[2]; - y[2] = y[5]; - y[5] = t; - - t = y[3]; - y[3] = y[4]; - y[4] = t; + unsigned char *x = (unsigned char *) x_; + bswap (x + 0, x + 7); + bswap (x + 1, x + 6); + bswap (x + 2, x + 5); + bswap (x + 3, x + 4); } static void @@ -152,172 +145,152 @@ corrupt_msg (int class, const char *format,...) } /* Closes a system file after we're done with it. */ -static void -sfm_close (struct file_handle *h) -{ - struct sfm_fhuser_ext *ext = h->ext; - - ext->opened--; - assert (ext->opened == 0); - if (EOF == fn_close (handle_get_filename (h), ext->file)) - msg (ME, _("%s: Closing system file: %s."), - handle_get_filename (h), strerror (errno)); - free (ext->buf); - free (h->ext); -} - -/* Closes a system file if we're done with it. */ void -sfm_maybe_close (struct file_handle *h) +sfm_close_reader (struct sfm_reader *r) { - struct sfm_fhuser_ext *ext = h->ext; + if (r == NULL) + return; - if (ext->opened == 1) - fh_close_handle (h); - else - ext->opened--; + if (r->fh != NULL) + fh_close (r->fh, "system file", "rs"); + if (fn_close (handle_get_filename (r->fh), r->file) == EOF) + msg (ME, _("%s: Closing system file: %s."), + handle_get_filename (r->fh), strerror (errno)); + free (r->vars); + free (r->buf); + free (r); } /* Dictionary reader. */ -static void *bufread (struct file_handle *handle, void *buf, size_t nbytes, - size_t minalloc); +static void *buf_read (struct sfm_reader *, void *buf, size_t byte_cnt, + size_t min_alloc); + +static int read_header (struct sfm_reader *, + struct dictionary *, struct sfm_read_info *); +static int parse_format_spec (struct sfm_reader *, int32, + struct fmt_spec *, struct variable *); +static int read_value_labels (struct sfm_reader *, struct dictionary *, + struct variable **var_by_idx); +static int read_variables (struct sfm_reader *, + struct dictionary *, struct variable ***var_by_idx); +static int read_machine_int32_info (struct sfm_reader *, int size, int count); +static int read_machine_flt64_info (struct sfm_reader *, int size, int count); +static int read_documents (struct sfm_reader *, struct dictionary *); -static int read_header (struct file_handle *h, struct sfm_read_info *inf); -static int parse_format_spec (struct file_handle *h, int32 s, - struct fmt_spec *v, struct variable *vv); -static int read_value_labels (struct file_handle *h, struct variable **var_by_index); -static int read_variables (struct file_handle *h, struct variable ***var_by_index); -static int read_machine_int32_info (struct file_handle *h, int size, int count); -static int read_machine_flt64_info (struct file_handle *h, int size, int count); -static int read_documents (struct file_handle *h); +static int fread_ok (struct sfm_reader *, void *, size_t); -/* Displays the message X with corrupt_msg, then jumps to the lossage +/* Displays the message X with corrupt_msg, then jumps to the error label. */ -#define lose(X) \ - do \ - { \ - corrupt_msg X; \ - goto lossage; \ - } \ - while (0) - -/* Calls bufread with the specified arguments, and jumps to lossage if - the read fails. */ -#define assertive_bufread(a,b,c,d) \ - do \ - { \ - if (!bufread (a,b,c,d)) \ - goto lossage; \ - } \ - while (0) - -/* Reads the dictionary from file with handle H, and returns it in a - dictionary structure. This dictionary may be modified in order to - rename, reorder, and delete variables, etc. */ -struct dictionary * -sfm_read_dictionary (struct file_handle *h, struct sfm_read_info *inf) +#define lose(X) \ + do { \ + corrupt_msg X; \ + goto error; \ + } while (0) + +/* Calls buf_read with the specified arguments, and jumps to + error if the read fails. */ +#define assertive_buf_read(a,b,c,d) \ + do { \ + if (!buf_read (a,b,c,d)) \ + goto error; \ + } while (0) + +/* Opens the system file designated by file handle FH for + reading. Reads the system file's dictionary into *DICT. + If INFO is non-null, then it receives additional info about the + system file. */ +struct sfm_reader * +sfm_open_reader (struct file_handle *fh, struct dictionary **dict, + struct sfm_read_info *info) { - /* The file handle extension record. */ - struct sfm_fhuser_ext *ext; - - /* Allows for quick reference to variables according to indexes - relative to position within a case. */ - struct variable **var_by_index = NULL; - - /* Check whether the file is already open. */ - if (h->class == &sfm_r_class) - { - ext = h->ext; - ext->opened++; - return ext->dict; - } - else if (h->class != NULL) - { - msg (ME, _("Cannot read file %s as system file: already opened for %s."), - handle_get_name (h), h->class->name); - return NULL; - } - - msg (VM (1), _("%s: Opening system-file handle %s for reading."), - handle_get_filename (h), handle_get_name (h)); - - /* Open the physical disk file. */ - ext = xmalloc (sizeof (struct sfm_fhuser_ext)); - ext->file = fn_open (handle_get_filename (h), "rb"); - if (ext->file == NULL) + struct sfm_reader *r = NULL; + struct variable **var_by_idx = NULL; + + *dict = dict_create (); + if (!fh_open (fh, "system file", "rs")) + goto error; + + /* Create and initialize reader. */ + r = xmalloc (sizeof *r); + r->fh = fh; + r->file = fn_open (handle_get_filename (fh), "rb"); + + r->reverse_endian = 0; + r->fix_specials = 0; + r->value_cnt = 0; + r->case_cnt = 0; + r->compressed = 0; + r->bias = 100.0; + r->weight_idx = -1; + + r->vars = NULL; + r->var_cnt = 0; + + r->sysmis = -FLT64_MAX; + r->highest = FLT64_MAX; + r->lowest = second_lowest_flt64; + + r->buf = r->ptr = r->end = NULL; + r->y = r->x + sizeof r->x; + + /* Check that file open succeeded. */ + if (r->file == NULL) { msg (ME, _("An error occurred while opening \"%s\" for reading " "as a system file: %s."), - handle_get_filename (h), strerror (errno)); + handle_get_filename (r->fh), strerror (errno)); err_cond_fail (); - free (ext); - return NULL; + goto error; } - /* Initialize the sfm_fhuser_ext structure. */ - h->class = &sfm_r_class; - h->ext = ext; - ext->dict = NULL; - ext->buf = ext->ptr = ext->end = NULL; - ext->y = ext->x + sizeof ext->x; - ext->opened = 1; - - /* Default special constants. */ - ext->sysmis = -FLT64_MAX; - ext->highest = FLT64_MAX; - ext->lowest = second_lowest_flt64; - - /* Read the header. */ - if (!read_header (h, inf)) - goto lossage; - - /* Read about the variables. */ - if (!read_variables (h, &var_by_index)) - goto lossage; + /* Read header and variables. */ + if (!read_header (r, *dict, info) || !read_variables (r, *dict, &var_by_idx)) + goto error; /* Handle weighting. */ - if (ext->weight_index != -1) + if (r->weight_idx != -1) { - struct variable *wv = var_by_index[ext->weight_index]; + struct variable *weight_var = var_by_idx[r->weight_idx]; - if (wv == NULL) - lose ((ME, _("%s: Weighting variable may not be a continuation of " - "a long string variable."), handle_get_filename (h))); - else if (wv->type == ALPHA) + if (weight_var == NULL) + lose ((ME, + _("%s: Weighting variable may not be a continuation of " + "a long string variable."), handle_get_filename (fh))); + else if (weight_var->type == ALPHA) lose ((ME, _("%s: Weighting variable may not be a string variable."), - handle_get_filename (h))); + handle_get_filename (fh))); - dict_set_weight (ext->dict, wv); + dict_set_weight (*dict, weight_var); } else - dict_set_weight (ext->dict, NULL); + dict_set_weight (*dict, NULL); /* Read records of types 3, 4, 6, and 7. */ for (;;) { int32 rec_type; - assertive_bufread (h, &rec_type, sizeof rec_type, 0); - if (ext->reverse_endian) + assertive_buf_read (r, &rec_type, sizeof rec_type, 0); + if (r->reverse_endian) bswap_int32 (&rec_type); switch (rec_type) { case 3: - if (!read_value_labels (h, var_by_index)) - goto lossage; + if (!read_value_labels (r, *dict, var_by_idx)) + goto error; break; case 4: lose ((ME, _("%s: Orphaned variable index record (type 4). Type 4 " "records must always immediately follow type 3 " "records."), - handle_get_filename (h))); + handle_get_filename (r->fh))); case 6: - if (!read_documents (h)) - goto lossage; + if (!read_documents (r, *dict)) + goto error; break; case 7: @@ -332,8 +305,8 @@ sfm_read_dictionary (struct file_handle *h, struct sfm_read_info *inf) int skip = 0; - assertive_bufread (h, &data, sizeof data, 0); - if (ext->reverse_endian) + assertive_buf_read (r, &data, sizeof data, 0); + if (r->reverse_endian) { bswap_int32 (&data.subtype); bswap_int32 (&data.size); @@ -343,13 +316,13 @@ sfm_read_dictionary (struct file_handle *h, struct sfm_read_info *inf) switch (data.subtype) { case 3: - if (!read_machine_int32_info (h, data.size, data.count)) - goto lossage; + if (!read_machine_int32_info (r, data.size, data.count)) + goto error; break; case 4: - if (!read_machine_flt64_info (h, data.size, data.count)) - goto lossage; + if (!read_machine_flt64_info (r, data.size, data.count)) + goto error; break; case 5: @@ -361,15 +334,15 @@ sfm_read_dictionary (struct file_handle *h, struct sfm_read_info *inf) default: msg (MW, _("%s: Unrecognized record type 7, subtype %d " "encountered in system file."), - handle_get_filename (h), data.subtype); + handle_get_filename (r->fh), data.subtype); skip = 1; } if (skip) { - void *x = bufread (h, NULL, data.size * data.count, 0); + void *x = buf_read (r, NULL, data.size * data.count, 0); if (x == NULL) - goto lossage; + goto error; free (x); } } @@ -379,43 +352,37 @@ sfm_read_dictionary (struct file_handle *h, struct sfm_read_info *inf) { int32 filler; - assertive_bufread (h, &filler, sizeof filler, 0); - goto break_out_of_loop; + assertive_buf_read (r, &filler, sizeof filler, 0); + goto success; } default: lose ((ME, _("%s: Unrecognized record type %d."), - handle_get_filename (h), rec_type)); + handle_get_filename (r->fh), rec_type)); } } -break_out_of_loop: +success: /* Come here on successful completion. */ - msg (VM (2), _("Read system-file dictionary successfully.")); - - free (var_by_index); - return ext->dict; + free (var_by_idx); + return r; -lossage: +error: /* Come here on unsuccessful completion. */ - msg (VM (1), _("Error reading system-file header.")); - - free (var_by_index); - fn_close (handle_get_filename (h), ext->file); - if (ext && ext->dict) - dict_destroy (ext->dict); - free (ext); - h->class = NULL; - h->ext = NULL; + sfm_close_reader (r); + free (var_by_idx); + if (*dict != NULL) + { + dict_destroy (*dict); + *dict = NULL; + } return NULL; } /* Read record type 7, subtype 3. */ static int -read_machine_int32_info (struct file_handle *h, int size, int count) +read_machine_int32_info (struct sfm_reader *r, int size, int count) { - struct sfm_fhuser_ext *ext = h->ext; - int32 data[8]; int file_bigendian; @@ -424,113 +391,105 @@ read_machine_int32_info (struct file_handle *h, int size, int count) if (size != sizeof (int32) || count != 8) lose ((ME, _("%s: Bad size (%d) or count (%d) field on record type 7, " "subtype 3. Expected size %d, count 8."), - handle_get_filename (h), size, count, sizeof (int32))); + handle_get_filename (r->fh), size, count, sizeof (int32))); - assertive_bufread (h, data, sizeof data, 0); - if (ext->reverse_endian) + assertive_buf_read (r, data, sizeof data, 0); + if (r->reverse_endian) for (i = 0; i < 8; i++) bswap_int32 (&data[i]); - /* PORTME: Check floating-point representation. */ #ifdef FPREP_IEEE754 if (data[4] != 1) lose ((ME, _("%s: Floating-point representation in system file is not " "IEEE-754. PSPP cannot convert between floating-point " "formats."), - handle_get_filename (h))); + handle_get_filename (r->fh))); +#else +#error Add support for your floating-point format. #endif - /* PORTME: Check recorded file endianness against intuited file - endianness. */ #ifdef WORDS_BIGENDIAN file_bigendian = 1; #else file_bigendian = 0; #endif - if (ext->reverse_endian) + if (r->reverse_endian) file_bigendian ^= 1; if (file_bigendian ^ (data[6] == 1)) - lose ((ME, _("%s: File-indicated endianness (%s) does not match endianness " - "intuited from file header (%s)."), - handle_get_filename (h), + lose ((ME, _("%s: File-indicated endianness (%s) does not match " + "endianness intuited from file header (%s)."), + handle_get_filename (r->fh), file_bigendian ? _("big-endian") : _("little-endian"), data[6] == 1 ? _("big-endian") : (data[6] == 2 ? _("little-endian") : _("unknown")))); /* PORTME: Character representation code. */ - if (data[7] != 2 && data[7] != 3) - lose ((ME, _("%s: File-indicated character representation code (%s) is not " - "ASCII."), - handle_get_filename (h), + if (data[7] != 2 && data[7] != 3) + lose ((ME, _("%s: File-indicated character representation code (%s) is " + "not ASCII."), + handle_get_filename (r->fh), (data[7] == 1 ? "EBCDIC" : (data[7] == 4 ? _("DEC Kanji") : _("Unknown"))))); return 1; -lossage: +error: return 0; } /* Read record type 7, subtype 4. */ static int -read_machine_flt64_info (struct file_handle *h, int size, int count) +read_machine_flt64_info (struct sfm_reader *r, int size, int count) { - struct sfm_fhuser_ext *ext = h->ext; - flt64 data[3]; - int i; if (size != sizeof (flt64) || count != 3) lose ((ME, _("%s: Bad size (%d) or count (%d) field on record type 7, " "subtype 4. Expected size %d, count 8."), - handle_get_filename (h), size, count, sizeof (flt64))); + handle_get_filename (r->fh), size, count, sizeof (flt64))); - assertive_bufread (h, data, sizeof data, 0); - if (ext->reverse_endian) + assertive_buf_read (r, data, sizeof data, 0); + if (r->reverse_endian) for (i = 0; i < 3; i++) bswap_flt64 (&data[i]); if (data[0] != SYSMIS || data[1] != FLT64_MAX || data[2] != second_lowest_flt64) { - ext->sysmis = data[0]; - ext->highest = data[1]; - ext->lowest = data[2]; + r->sysmis = data[0]; + r->highest = data[1]; + r->lowest = data[2]; msg (MW, _("%s: File-indicated value is different from internal value " "for at least one of the three system values. SYSMIS: " "indicated %g, expected %g; HIGHEST: %g, %g; LOWEST: " "%g, %g."), - handle_get_filename (h), (double) data[0], (double) SYSMIS, + handle_get_filename (r->fh), (double) data[0], (double) SYSMIS, (double) data[1], (double) FLT64_MAX, (double) data[2], (double) second_lowest_flt64); } return 1; -lossage: +error: return 0; } static int -read_header (struct file_handle *h, struct sfm_read_info *inf) +read_header (struct sfm_reader *r, + struct dictionary *dict, struct sfm_read_info *info) { - struct sfm_fhuser_ext *ext = h->ext; /* File extension strcut. */ struct sysfile_header hdr; /* Disk buffer. */ - struct dictionary *dict; /* File dictionary. */ char prod_name[sizeof hdr.prod_name + 1]; /* Buffer for product name. */ int skip_amt = 0; /* Amount of product name to omit. */ int i; - /* Create the dictionary. */ - dict = ext->dict = dict_create (); - /* Read header, check magic. */ - assertive_bufread (h, &hdr, sizeof hdr, 0); - if (0 != strncmp ("$FL2", hdr.rec_type, 4)) + assertive_buf_read (r, &hdr, sizeof hdr, 0); + if (strncmp ("$FL2", hdr.rec_type, 4) != 0) lose ((ME, _("%s: Bad magic. Proper system files begin with " "the four characters `$FL2'. This file will not be read."), - handle_get_filename (h))); + handle_get_filename (r->fh))); /* Check eye-catcher string. */ memcpy (prod_name, hdr.prod_name, sizeof hdr.prod_name); @@ -564,52 +523,52 @@ read_header (struct file_handle *h, struct sfm_read_info *inf) } /* Check endianness. */ - /* PORTME: endianness. */ if (hdr.layout_code == 2) - ext->reverse_endian = 0; + r->reverse_endian = 0; else { bswap_int32 (&hdr.layout_code); if (hdr.layout_code != 2) lose ((ME, _("%s: File layout code has unexpected value %d. Value " "should be 2, in big-endian or little-endian format."), - handle_get_filename (h), hdr.layout_code)); + handle_get_filename (r->fh), hdr.layout_code)); - ext->reverse_endian = 1; + r->reverse_endian = 1; bswap_int32 (&hdr.case_size); - bswap_int32 (&hdr.compressed); - bswap_int32 (&hdr.weight_index); - bswap_int32 (&hdr.ncases); + bswap_int32 (&hdr.compress); + bswap_int32 (&hdr.weight_idx); + bswap_int32 (&hdr.case_cnt); bswap_flt64 (&hdr.bias); } /* Copy basic info and verify correctness. */ - ext->case_size = hdr.case_size; - if (hdr.case_size <= 0 || ext->case_size > (INT_MAX - / (int) sizeof (union value) / 2)) + r->value_cnt = hdr.case_size; + if (r->value_cnt <= 0 + || r->value_cnt > (INT_MAX / (int) sizeof (union value) / 2)) lose ((ME, _("%s: Number of elements per case (%d) is not between 1 " "and %d."), - handle_get_filename (h), hdr.case_size, + handle_get_filename (r->fh), r->value_cnt, INT_MAX / sizeof (union value) / 2)); - ext->compressed = hdr.compressed; + r->compressed = hdr.compress; - ext->weight_index = hdr.weight_index - 1; - if (hdr.weight_index < 0 || hdr.weight_index > hdr.case_size) + r->weight_idx = hdr.weight_idx - 1; + if (hdr.weight_idx < 0 || hdr.weight_idx > r->value_cnt) lose ((ME, _("%s: Index of weighting variable (%d) is not between 0 " "and number of elements per case (%d)."), - handle_get_filename (h), hdr.weight_index, ext->case_size)); + handle_get_filename (r->fh), hdr.weight_idx, r->value_cnt)); - ext->ncases = hdr.ncases; - if (ext->ncases < -1 || ext->ncases > INT_MAX / 2) - lose ((ME, _("%s: Number of cases in file (%ld) is not between -1 and " - "%d."), handle_get_filename (h), (long) ext->ncases, INT_MAX / 2)); + r->case_cnt = hdr.case_cnt; + if (r->case_cnt < -1 || r->case_cnt > INT_MAX / 2) + lose ((ME, + _("%s: Number of cases in file (%ld) is not between -1 and %d."), + handle_get_filename (r->fh), (long) r->case_cnt, INT_MAX / 2)); - ext->bias = hdr.bias; - if (ext->bias != 100.0) + r->bias = hdr.bias; + if (r->bias != 100.0) corrupt_msg (MW, _("%s: Compression bias (%g) is not the usual " "value of 100."), - handle_get_filename (h), ext->bias); + handle_get_filename (r->fh), r->bias); /* Make a file label only on the condition that the given label is not all spaces or nulls. */ @@ -629,68 +588,67 @@ read_header (struct file_handle *h, struct sfm_read_info *inf) } } - if (inf) + if (info) { char *cp; - memcpy (inf->creation_date, hdr.creation_date, 9); - inf->creation_date[9] = 0; + memcpy (info->creation_date, hdr.creation_date, 9); + info->creation_date[9] = 0; - memcpy (inf->creation_time, hdr.creation_time, 8); - inf->creation_time[8] = 0; + memcpy (info->creation_time, hdr.creation_time, 8); + info->creation_time[8] = 0; #ifdef WORDS_BIGENDIAN - inf->bigendian = !ext->reverse_endian; + info->big_endian = !r->reverse_endian; #else - inf->bigendian = ext->reverse_endian; + info->big_endian = r->reverse_endian; #endif - inf->compressed = hdr.compressed; + info->compressed = hdr.compress; - inf->ncases = hdr.ncases; + info->case_cnt = hdr.case_cnt; for (cp = &prod_name[skip_amt]; cp < &prod_name[60]; cp++) if (isgraph ((unsigned char) *cp)) break; - strcpy (inf->product, cp); + strcpy (info->product, cp); } return 1; -lossage: +error: return 0; } /* Reads most of the dictionary from file H; also fills in the - associated VAR_BY_INDEX array. The get.* elements in the - created dictionary are set to appropriate values to allow the - file to be read. */ + associated VAR_BY_IDX array. */ static int -read_variables (struct file_handle *h, struct variable ***var_by_index) +read_variables (struct sfm_reader *r, + struct dictionary *dict, struct variable ***var_by_idx) { int i; - struct sfm_fhuser_ext *ext = h->ext; /* File extension record. */ - struct dictionary *dict = ext->dict; /* Dictionary being constructed. */ struct sysfile_variable sv; /* Disk buffer. */ int long_string_count = 0; /* # of long string continuation records still expected. */ int next_value = 0; /* Index to next `value' structure. */ + size_t var_cap = 0; /* Allocate variables. */ - *var_by_index = xmalloc (sizeof **var_by_index * ext->case_size); + *var_by_idx = xmalloc (sizeof **var_by_idx * r->value_cnt); /* Read in the entry for each variable and use the info to initialize the dictionary. */ - for (i = 0; i < ext->case_size; i++) + for (i = 0; i < r->value_cnt; i++) { struct variable *vv; char name[9]; + int nv; int j; - assertive_bufread (h, &sv, sizeof sv, 0); + assertive_buf_read (r, &sv, sizeof sv, 0); - if (ext->reverse_endian) + if (r->reverse_endian) { bswap_int32 (&sv.rec_type); bswap_int32 (&sv.type); @@ -703,7 +661,7 @@ read_variables (struct file_handle *h, struct variable ***var_by_index) if (sv.rec_type != 2) lose ((ME, _("%s: position %d: Bad record type (%d); " "the expected value was 2."), - handle_get_filename (h), i, sv.rec_type)); + handle_get_filename (r->fh), i, sv.rec_type)); /* If there was a long string previously, make sure that the continuations are present; otherwise make sure there aren't @@ -713,44 +671,44 @@ read_variables (struct file_handle *h, struct variable ***var_by_index) if (sv.type != -1) lose ((ME, _("%s: position %d: String variable does not have " "proper number of continuation records."), - handle_get_filename (h), i)); + handle_get_filename (r->fh), i)); - (*var_by_index)[i] = NULL; + (*var_by_idx)[i] = NULL; long_string_count--; continue; } else if (sv.type == -1) lose ((ME, _("%s: position %d: Superfluous long string continuation " "record."), - handle_get_filename (h), i)); + handle_get_filename (r->fh), i)); /* Check fields for validity. */ if (sv.type < 0 || sv.type > 255) lose ((ME, _("%s: position %d: Bad variable type code %d."), - handle_get_filename (h), i, sv.type)); + handle_get_filename (r->fh), i, sv.type)); if (sv.has_var_label != 0 && sv.has_var_label != 1) lose ((ME, _("%s: position %d: Variable label indicator field is not " - "0 or 1."), handle_get_filename (h), i)); + "0 or 1."), handle_get_filename (r->fh), i)); if (sv.n_missing_values < -3 || sv.n_missing_values > 3 || sv.n_missing_values == -1) lose ((ME, _("%s: position %d: Missing value indicator field is not " - "-3, -2, 0, 1, 2, or 3."), handle_get_filename (h), i)); + "-3, -2, 0, 1, 2, or 3."), handle_get_filename (r->fh), i)); /* Copy first character of variable name. */ if (!isalpha ((unsigned char) sv.name[0]) && sv.name[0] != '@' && sv.name[0] != '#') lose ((ME, _("%s: position %d: Variable name begins with invalid " "character."), - handle_get_filename (h), i)); + handle_get_filename (r->fh), i)); if (islower ((unsigned char) sv.name[0])) msg (MW, _("%s: position %d: Variable name begins with lowercase letter " "%c."), - handle_get_filename (h), i, sv.name[0]); + handle_get_filename (r->fh), i, sv.name[0]); if (sv.name[0] == '#') msg (MW, _("%s: position %d: Variable name begins with octothorpe " "(`#'). Scratch variables should not appear in system " "files."), - handle_get_filename (h), i); + handle_get_filename (r->fh), i); name[0] = toupper ((unsigned char) (sv.name[0])); /* Copy remaining characters of variable name. */ @@ -764,7 +722,7 @@ read_variables (struct file_handle *h, struct variable ***var_by_index) { msg (MW, _("%s: position %d: Variable name character %d is " "lowercase letter %c."), - handle_get_filename (h), i, j + 1, sv.name[j]); + handle_get_filename (r->fh), i, j + 1, sv.name[j]); name[j] = toupper ((unsigned char) (c)); } else if (isalnum (c) || c == '.' || c == '@' @@ -773,24 +731,20 @@ read_variables (struct file_handle *h, struct variable ***var_by_index) else lose ((ME, _("%s: position %d: character `\\%03o' (%c) is not valid in a " "variable name."), - handle_get_filename (h), i, c, c)); + handle_get_filename (r->fh), i, c, c)); } name[j] = 0; /* Create variable. */ - vv = (*var_by_index)[i] = dict_create_var (dict, name, sv.type); + vv = (*var_by_idx)[i] = dict_create_var (dict, name, sv.type); if (vv == NULL) lose ((ME, _("%s: Duplicate variable name `%s' within system file."), - handle_get_filename (h), name)); + handle_get_filename (r->fh), name)); /* Case reading data. */ - vv->get.fv = next_value; - if (sv.type == 0) - vv->get.nv = 1; - else - vv->get.nv = DIV_RND_UP (sv.type, sizeof (flt64)); - long_string_count = vv->get.nv - 1; - next_value += vv->get.nv; + nv = sv.type == 0 ? 1 : DIV_RND_UP (sv.type, sizeof (flt64)); + long_string_count = nv - 1; + next_value += nv; /* Get variable label, if any. */ if (sv.has_var_label == 1) @@ -799,20 +753,20 @@ read_variables (struct file_handle *h, struct variable ***var_by_index) int32 len; /* Read length of label. */ - assertive_bufread (h, &len, sizeof len, 0); - if (ext->reverse_endian) + assertive_buf_read (r, &len, sizeof len, 0); + if (r->reverse_endian) bswap_int32 (&len); /* Check len. */ if (len < 0 || len > 255) lose ((ME, _("%s: Variable %s indicates variable label of invalid " "length %d."), - handle_get_filename (h), vv->name, len)); + handle_get_filename (r->fh), vv->name, len)); /* Read label into variable structure. */ - vv->label = bufread (h, NULL, ROUND_UP (len, sizeof (int32)), len + 1); + vv->label = buf_read (r, NULL, ROUND_UP (len, sizeof (int32)), len + 1); if (vv->label == NULL) - goto lossage; + goto error; vv->label[len] = '\0'; } @@ -824,11 +778,11 @@ read_variables (struct file_handle *h, struct variable ***var_by_index) if (vv->width > MAX_SHORT_STRING) lose ((ME, _("%s: Long string variable %s may not have missing " "values."), - handle_get_filename (h), vv->name)); + handle_get_filename (r->fh), vv->name)); - assertive_bufread (h, mv, sizeof *mv * abs (sv.n_missing_values), 0); + assertive_buf_read (r, mv, sizeof *mv * abs (sv.n_missing_values), 0); - if (ext->reverse_endian && vv->type == NUMERIC) + if (r->reverse_endian && vv->type == NUMERIC) for (j = 0; j < abs (sv.n_missing_values); j++) bswap_flt64 (&mv[j]); @@ -849,14 +803,14 @@ read_variables (struct file_handle *h, struct variable ***var_by_index) if (vv->type == ALPHA) lose ((ME, _("%s: String variable %s may not have missing " "values specified as a range."), - handle_get_filename (h), vv->name)); + handle_get_filename (r->fh), vv->name)); - if (mv[0] == ext->lowest) + if (mv[0] == r->lowest) { vv->miss_type = MISSING_LOW; vv->missing[x++].f = mv[1]; } - else if (mv[1] == ext->highest) + else if (mv[1] == r->highest) { vv->miss_type = MISSING_HIGH; vv->missing[x++].f = mv[0]; @@ -878,39 +832,46 @@ read_variables (struct file_handle *h, struct variable ***var_by_index) else vv->miss_type = MISSING_NONE; - if (!parse_format_spec (h, sv.print, &vv->print, vv) - || !parse_format_spec (h, sv.write, &vv->write, vv)) - goto lossage; + if (!parse_format_spec (r, sv.print, &vv->print, vv) + || !parse_format_spec (r, sv.write, &vv->write, vv)) + goto error; + + /* Add variable to list. */ + if (var_cap >= r->var_cnt) + { + var_cap = 2 + r->var_cnt * 2; + r->vars = xrealloc (r->vars, var_cap * sizeof *r->vars); + } + r->vars[r->var_cnt].width = vv->width; + r->vars[r->var_cnt].fv = vv->fv; + r->var_cnt++; } /* Some consistency checks. */ if (long_string_count != 0) lose ((ME, _("%s: Long string continuation records omitted at end of " "dictionary."), - handle_get_filename (h))); - if (next_value != ext->case_size) + handle_get_filename (r->fh))); + if (next_value != r->value_cnt) lose ((ME, _("%s: System file header indicates %d variable positions but " "%d were read from file."), - handle_get_filename (h), ext->case_size, next_value)); + handle_get_filename (r->fh), r->value_cnt, next_value)); return 1; -lossage: - dict_destroy (dict); - ext->dict = NULL; - +error: return 0; } /* Translates the format spec from sysfile format to internal format. */ static int -parse_format_spec (struct file_handle *h, int32 s, struct fmt_spec *v, struct variable *vv) +parse_format_spec (struct sfm_reader *r, int32 s, struct fmt_spec *v, struct variable *vv) { v->type = translate_fmt ((s >> 16) & 0xff); if (v->type == -1) lose ((ME, _("%s: Bad format specifier byte (%d)."), - handle_get_filename (h), (s >> 16) & 0xff)); + handle_get_filename (r->fh), (s >> 16) & 0xff)); v->w = (s >> 8) & 0xff; v->d = s & 0xff; @@ -918,27 +879,26 @@ parse_format_spec (struct file_handle *h, int32 s, struct fmt_spec *v, struct va if (v->type == -1) lose ((ME, _("%s: Bad format specifier byte (%d)."), - handle_get_filename (h), (s >> 16) & 0xff)); + handle_get_filename (r->fh), (s >> 16) & 0xff)); if ((vv->type == ALPHA) ^ ((formats[v->type].cat & FCAT_STRING) != 0)) lose ((ME, _("%s: %s variable %s has %s format specifier %s."), - handle_get_filename (h), + handle_get_filename (r->fh), vv->type == ALPHA ? _("String") : _("Numeric"), vv->name, formats[v->type].cat & FCAT_STRING ? _("string") : _("numeric"), formats[v->type].name)); return 1; -lossage: +error: return 0; } /* Reads value labels from sysfile H and inserts them into the associated dictionary. */ int -read_value_labels (struct file_handle *h, struct variable **var_by_index) +read_value_labels (struct sfm_reader *r, + struct dictionary *dict, struct variable **var_by_idx) { - struct sfm_fhuser_ext *ext = h->ext; /* File extension record. */ - struct label { unsigned char raw_value[8]; /* Value as uninterpreted bytes. */ @@ -959,8 +919,8 @@ read_value_labels (struct file_handle *h, struct variable **var_by_index) don't know yet whether it is of numeric or string type. */ /* Read number of labels. */ - assertive_bufread (h, &n_labels, sizeof n_labels, 0); - if (ext->reverse_endian) + assertive_buf_read (r, &n_labels, sizeof n_labels, 0); + if (r->reverse_endian) bswap_int32 (&n_labels); /* Allocate memory. */ @@ -976,15 +936,15 @@ read_value_labels (struct file_handle *h, struct variable **var_by_index) size_t padded_len; /* Read value. */ - assertive_bufread (h, label->raw_value, sizeof label->raw_value, 0); + assertive_buf_read (r, label->raw_value, sizeof label->raw_value, 0); /* Read label length. */ - assertive_bufread (h, &label_len, sizeof label_len, 0); + assertive_buf_read (r, &label_len, sizeof label_len, 0); padded_len = ROUND_UP (label_len + 1, sizeof (flt64)); /* Read label, padding. */ label->label = xmalloc (padded_len + 1); - assertive_bufread (h, label->label, padded_len - 1, 0); + assertive_buf_read (r, label->label, padded_len - 1, 0); label->label[label_len] = 0; } @@ -995,53 +955,53 @@ read_value_labels (struct file_handle *h, struct variable **var_by_index) { int32 rec_type; - assertive_bufread (h, &rec_type, sizeof rec_type, 0); - if (ext->reverse_endian) + assertive_buf_read (r, &rec_type, sizeof rec_type, 0); + if (r->reverse_endian) bswap_int32 (&rec_type); if (rec_type != 4) lose ((ME, _("%s: Variable index record (type 4) does not immediately " "follow value label record (type 3) as it should."), - handle_get_filename (h))); + handle_get_filename (r->fh))); } /* Read number of variables associated with value label from type 4 record. */ - assertive_bufread (h, &n_vars, sizeof n_vars, 0); - if (ext->reverse_endian) + assertive_buf_read (r, &n_vars, sizeof n_vars, 0); + if (r->reverse_endian) bswap_int32 (&n_vars); - if (n_vars < 1 || n_vars > dict_get_var_cnt (ext->dict)) + if (n_vars < 1 || n_vars > dict_get_var_cnt (dict)) lose ((ME, _("%s: Number of variables associated with a value label (%d) " "is not between 1 and the number of variables (%d)."), - handle_get_filename (h), n_vars, dict_get_var_cnt (ext->dict))); + handle_get_filename (r->fh), n_vars, dict_get_var_cnt (dict))); /* Read the list of variables. */ var = xmalloc (n_vars * sizeof *var); for (i = 0; i < n_vars; i++) { - int32 var_index; + int32 var_idx; struct variable *v; /* Read variable index, check range. */ - assertive_bufread (h, &var_index, sizeof var_index, 0); - if (ext->reverse_endian) - bswap_int32 (&var_index); - if (var_index < 1 || var_index > ext->case_size) + assertive_buf_read (r, &var_idx, sizeof var_idx, 0); + if (r->reverse_endian) + bswap_int32 (&var_idx); + if (var_idx < 1 || var_idx > r->value_cnt) lose ((ME, _("%s: Variable index associated with value label (%d) is " "not between 1 and the number of values (%d)."), - handle_get_filename (h), var_index, ext->case_size)); + handle_get_filename (r->fh), var_idx, r->value_cnt)); /* Make sure it's a real variable. */ - v = var_by_index[var_index - 1]; + v = var_by_idx[var_idx - 1]; if (v == NULL) lose ((ME, _("%s: Variable index associated with value label (%d) " "refers to a continuation of a string variable, not to " "an actual variable."), - handle_get_filename (h), var_index)); + handle_get_filename (r->fh), var_idx)); if (v->type == ALPHA && v->width > MAX_SHORT_STRING) lose ((ME, _("%s: Value labels are not allowed on long string " "variables (%s)."), - handle_get_filename (h), v->name)); + handle_get_filename (r->fh), v->name)); /* Add it to the list of variables. */ var[i] = v; @@ -1053,7 +1013,7 @@ read_value_labels (struct file_handle *h, struct variable **var_by_index) lose ((ME, _("%s: Variables associated with value label are not all of " "identical type. Variable %s has %s type, but variable " "%s has %s type."), - handle_get_filename (h), + handle_get_filename (r->fh), var[0]->name, var[0]->type == ALPHA ? _("string") : _("numeric"), var[i]->name, var[i]->type == ALPHA ? _("string") : _("numeric"))); @@ -1071,7 +1031,7 @@ read_value_labels (struct file_handle *h, struct variable **var_by_index) flt64 f; assert (sizeof f == sizeof label->raw_value); memcpy (&f, label->raw_value, sizeof f); - if (ext->reverse_endian) + if (r->reverse_endian) bswap_flt64 (&f); label->value.f = f; } @@ -1093,11 +1053,11 @@ read_value_labels (struct file_handle *h, struct variable **var_by_index) if (var[0]->type == NUMERIC) msg (MW, _("%s: File contains duplicate label for value %g for " "variable %s."), - handle_get_filename (h), label->value.f, v->name); + handle_get_filename (r->fh), label->value.f, v->name); else msg (MW, _("%s: File contains duplicate label for value `%.*s' " "for variable %s."), - handle_get_filename (h), v->width, label->value.s, v->name); + handle_get_filename (r->fh), v->width, label->value.s, v->name); } } @@ -1107,7 +1067,7 @@ read_value_labels (struct file_handle *h, struct variable **var_by_index) free (var); return 1; -lossage: +error: if (labels) { for (i = 0; i < n_labels; i++) @@ -1118,62 +1078,58 @@ lossage: return 0; } -/* Reads NBYTES bytes from the file represented by H. If BUF is +/* Reads BYTE_CNT bytes from the file represented by H. If BUF is non-NULL, uses that as the buffer; otherwise allocates at least - MINALLOC bytes. Returns a pointer to the buffer on success, NULL + MIN_ALLOC bytes. Returns a pointer to the buffer on success, NULL on failure. */ static void * -bufread (struct file_handle *h, void *buf, size_t nbytes, size_t minalloc) +buf_read (struct sfm_reader *r, void *buf, size_t byte_cnt, size_t min_alloc) { - struct sfm_fhuser_ext *ext = h->ext; - if (buf == NULL) - buf = xmalloc (max (nbytes, minalloc)); - if (1 != fread (buf, nbytes, 1, ext->file)) + buf = xmalloc (max (byte_cnt, min_alloc)); + if (1 != fread (buf, byte_cnt, 1, r->file)) { - if (ferror (ext->file)) + if (ferror (r->file)) msg (ME, _("%s: Reading system file: %s."), - handle_get_filename (h), strerror (errno)); + handle_get_filename (r->fh), strerror (errno)); else corrupt_msg (ME, _("%s: Unexpected end of file."), - handle_get_filename (h)); + handle_get_filename (r->fh)); return NULL; } return buf; } -/* Reads a document record, type 6, from system file H, and sets up +/* Reads a document record, type 6, from system file R, and sets up the documents and n_documents fields in the associated dictionary. */ static int -read_documents (struct file_handle *h) +read_documents (struct sfm_reader *r, struct dictionary *dict) { - struct sfm_fhuser_ext *ext = h->ext; - struct dictionary *dict = ext->dict; - int32 n_lines; + int32 line_cnt; char *documents; if (dict_get_documents (dict) != NULL) lose ((ME, _("%s: System file contains multiple " "type 6 (document) records."), - handle_get_filename (h))); + handle_get_filename (r->fh))); - assertive_bufread (h, &n_lines, sizeof n_lines, 0); - if (n_lines <= 0) + assertive_buf_read (r, &line_cnt, sizeof line_cnt, 0); + if (line_cnt <= 0) lose ((ME, _("%s: Number of document lines (%ld) " "must be greater than 0."), - handle_get_filename (h), (long) n_lines)); + handle_get_filename (r->fh), (long) line_cnt)); - documents = bufread (h, NULL, 80 * n_lines, n_lines * 80 + 1); + documents = buf_read (r, NULL, 80 * line_cnt, line_cnt * 80 + 1); /* FIXME? Run through asciify. */ if (documents == NULL) return 0; - documents[80 * n_lines] = '\0'; + documents[80 * line_cnt] = '\0'; dict_set_documents (dict, documents); free (documents); return 1; -lossage: +error: return 0; } @@ -1183,43 +1139,40 @@ lossage: appropriately. Returns nonzero only if both no errors occur and data was read. */ static int -buffer_input (struct file_handle *h) +buffer_input (struct sfm_reader *r) { - struct sfm_fhuser_ext *ext = h->ext; size_t amt; - if (ext->buf == NULL) - ext->buf = xmalloc (sizeof *ext->buf * 128); - amt = fread (ext->buf, sizeof *ext->buf, 128, ext->file); - if (ferror (ext->file)) + if (r->buf == NULL) + r->buf = xmalloc (sizeof *r->buf * 128); + amt = fread (r->buf, sizeof *r->buf, 128, r->file); + if (ferror (r->file)) { msg (ME, _("%s: Error reading file: %s."), - handle_get_filename (h), strerror (errno)); + handle_get_filename (r->fh), strerror (errno)); return 0; } - ext->ptr = ext->buf; - ext->end = &ext->buf[amt]; + r->ptr = r->buf; + r->end = &r->buf[amt]; return amt; } -/* Reads a single case consisting of compressed data from system file - H into the array TEMP[] according to dictionary DICT, and returns - nonzero only if successful. */ -/* Data in system files is compressed in the following manner: - data values are grouped into sets of eight; each of the eight has - one instruction byte, which are output together in an octet; each - byte gives a value for that byte or indicates that the value can be - found following the instructions. */ +/* Reads a single case consisting of compressed data from system + file H into the array BUF[] according to reader R, and + returns nonzero only if successful. */ +/* Data in system files is compressed in this manner. Data + values are grouped into sets of eight ("octets"). Each value + in an octet has one instruction byte that are output together. + Each instruction byte gives a value for that byte or indicates + that the value can be found following the instructions. */ static int -read_compressed_data (struct file_handle *h, flt64 *temp) +read_compressed_data (struct sfm_reader *r, flt64 *buf) { - struct sfm_fhuser_ext *ext = h->ext; - - const unsigned char *p_end = ext->x + sizeof (flt64); - unsigned char *p = ext->y; + const unsigned char *p_end = r->x + sizeof (flt64); + unsigned char *p = r->y; - const flt64 *temp_beg = temp; - const flt64 *temp_end = &temp[ext->case_size]; + const flt64 *buf_beg = buf; + const flt64 *buf_end = &buf[r->value_cnt]; for (;;) { @@ -1231,152 +1184,181 @@ read_compressed_data (struct file_handle *h, flt64 *temp) continue; case 252: /* Code 252 is end of file. */ - if (temp_beg != temp) + if (buf_beg != buf) lose ((ME, _("%s: Compressed data is corrupted. Data ends " "in partial case."), - handle_get_filename (h))); - goto lossage; + handle_get_filename (r->fh))); + goto error; case 253: /* Code 253 indicates that the value is stored explicitly following the instruction bytes. */ - if (ext->ptr == NULL || ext->ptr >= ext->end) - if (!buffer_input (h)) + if (r->ptr == NULL || r->ptr >= r->end) + if (!buffer_input (r)) { lose ((ME, _("%s: Unexpected end of file."), - handle_get_filename (h))); - goto lossage; + handle_get_filename (r->fh))); + goto error; } - memcpy (temp++, ext->ptr++, sizeof *temp); - if (temp >= temp_end) - goto winnage; + memcpy (buf++, r->ptr++, sizeof *buf); + if (buf >= buf_end) + goto success; break; case 254: /* Code 254 indicates a string that is all blanks. */ - memset (temp++, ' ', sizeof *temp); - if (temp >= temp_end) - goto winnage; + memset (buf++, ' ', sizeof *buf); + if (buf >= buf_end) + goto success; break; case 255: /* Code 255 indicates the system-missing value. */ - *temp = ext->sysmis; - if (ext->reverse_endian) - bswap_flt64 (temp); - temp++; - if (temp >= temp_end) - goto winnage; + *buf = r->sysmis; + if (r->reverse_endian) + bswap_flt64 (buf); + buf++; + if (buf >= buf_end) + goto success; break; default: /* Codes 1 through 251 inclusive are taken to indicate a value of (BYTE - BIAS), where BYTE is the byte's value and BIAS is the compression bias (generally 100.0). */ - *temp = *p - ext->bias; - if (ext->reverse_endian) - bswap_flt64 (temp); - temp++; - if (temp >= temp_end) - goto winnage; + *buf = *p - r->bias; + if (r->reverse_endian) + bswap_flt64 (buf); + buf++; + if (buf >= buf_end) + goto success; break; } /* We have reached the end of this instruction octet. Read another. */ - if (ext->ptr == NULL || ext->ptr >= ext->end) - if (!buffer_input (h)) + if (r->ptr == NULL || r->ptr >= r->end) + if (!buffer_input (r)) { - if (temp_beg != temp) + if (buf_beg != buf) lose ((ME, _("%s: Unexpected end of file."), - handle_get_filename (h))); - goto lossage; + handle_get_filename (r->fh))); + goto error; } - memcpy (ext->x, ext->ptr++, sizeof *temp); - p = ext->x; + memcpy (r->x, r->ptr++, sizeof *buf); + p = r->x; } /* Not reached. */ assert (0); -winnage: +success: /* We have filled up an entire record. Update state and return successfully. */ - ext->y = ++p; + r->y = ++p; return 1; -lossage: +error: /* We have been unsuccessful at filling a record, either through i/o error or through an end-of-file indication. Update state and return unsuccessfully. */ return 0; } -/* Reads one case from system file H into PERM - according to the instructions given in associated dictionary DICT, - which must have the get.* elements appropriately set. Returns - nonzero only if successful. */ +/* Reads one case from READER's file into C. Returns nonzero + only if successful. */ int -sfm_read_case (struct file_handle *h, struct ccase *perm, struct dictionary *dict) +sfm_read_case (struct sfm_reader *r, struct ccase *c) { - struct sfm_fhuser_ext *ext = h->ext; - - size_t nbytes; - flt64 *temp; - - int i; - - /* The first concern is to obtain a full case relative to the data - file. (Cases in the data file have no particular relationship to - cases in the active file.) */ - nbytes = sizeof *temp * ext->case_size; - temp = local_alloc (nbytes); - - if (ext->compressed == 0) + if (!r->compressed && sizeof (flt64) == sizeof (double)) { - size_t amt = fread (temp, 1, nbytes, ext->file); + /* Fast path: external and internal representations are the + same, except possibly for endianness or SYSMIS. Read + directly into the case's buffer, then fix up any minor + details as needed. */ + if (!fread_ok (r, case_data_all_rw (c), + sizeof (union value) * r->value_cnt)) + return 0; + + /* Fix up endianness if needed. */ + if (r->reverse_endian) + { + int i; + + for (i = 0; i < r->var_cnt; i++) + if (r->vars[i].width == 0) + bswap_flt64 (&case_data_rw (c, r->vars[i].fv)->f); + } - if (amt != nbytes) - { - if (ferror (ext->file)) - msg (ME, _("%s: Reading system file: %s."), - handle_get_filename (h), strerror (errno)); - else if (amt != 0) - msg (ME, _("%s: Partial record at end of system file."), - handle_get_filename (h)); - goto lossage; - } + /* Fix up SYSMIS values if needed. + I don't think this will ever actually kick in, but it + can't hurt. */ + if (r->sysmis != SYSMIS) + { + int i; + + for (i = 0; i < r->var_cnt; i++) + if (r->vars[i].width == 0 && case_num (c, i) == r->sysmis) + case_data_rw (c, r->vars[i].fv)->f = SYSMIS; + } } - else if (!read_compressed_data (h, temp)) - goto lossage; - - /* Translate a case in data file format to a case in active file - format. */ - for (i = 0; i < dict_get_var_cnt (dict); i++) + else { - struct variable *v = dict_get_var (dict, i); - - if (v->get.fv == -1) - continue; - - if (v->type == NUMERIC) - { - flt64 src = temp[v->get.fv]; - if (ext->reverse_endian) - bswap_flt64 (&src); - case_data_rw (perm, v->fv)->f = src == ext->sysmis ? SYSMIS : src; - } + /* Slow path: internal and external representations differ. + Read into a bounce buffer, then copy to C. */ + flt64 *bounce; + flt64 *bounce_cur; + size_t bounce_size; + int read_ok; + int i; + + bounce_size = sizeof *bounce * r->value_cnt; + bounce = bounce_cur = local_alloc (bounce_size); + + if (!r->compressed) + read_ok = fread_ok (r, bounce, bounce_size); else - memcpy (case_data_rw (perm, v->fv)->s, &temp[v->get.fv], v->width); - } + read_ok = read_compressed_data (r, bounce); + if (!read_ok) + { + local_free (bounce); + return 0; + } - local_free (temp); - return 1; + for (i = 0; i < r->var_cnt; i++) + { + struct sfm_var *v = &r->vars[i]; + + if (v->width == 0) + { + flt64 f = *bounce_cur++; + if (r->reverse_endian) + bswap_flt64 (&f); + case_data_rw (c, i)->f = f == r->sysmis ? SYSMIS : f; + } + else + { + memcpy (case_data_rw (c, v->fv)->s, bounce_cur, v->width); + bounce_cur += DIV_RND_UP (v->width, sizeof (flt64)); + } + } -lossage: - local_free (temp); - return 0; + local_free (bounce); + } + return 1; } -static struct fh_ext_class sfm_r_class = +static int +fread_ok (struct sfm_reader *r, void *buffer, size_t byte_cnt) { - 3, - N_("reading as a system file"), - sfm_close, -}; + size_t read_bytes = fread (buffer, 1, byte_cnt, r->file); + + if (read_bytes == byte_cnt) + return 1; + else + { + if (ferror (r->file)) + msg (ME, _("%s: Reading system file: %s."), + handle_get_filename (r->fh), strerror (errno)); + else if (read_bytes != 0) + msg (ME, _("%s: Partial record at end of system file."), + handle_get_filename (r->fh)); + return 0; + } +} diff --git a/src/sfm-read.h b/src/sfm-read.h new file mode 100644 index 00000000..4c2e9f9b --- /dev/null +++ b/src/sfm-read.h @@ -0,0 +1,45 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef SFM_READ_H +#define SFM_READ_H 1 + +/* Reading system files. */ + +/* System file info that doesn't fit in struct dictionary. */ +struct sfm_read_info + { + char creation_date[10]; /* `dd mmm yy' plus a null. */ + char creation_time[9]; /* `hh:mm:ss' plus a null. */ + int big_endian; /* 1=big-endian, 0=little-endian. */ + int compressed; /* 0=no, 1=yes. */ + int case_cnt; /* -1 if unknown. */ + char product[61]; /* Product name plus a null. */ + }; + +struct dictionary; +struct file_handle; +struct ccase; +struct sfm_reader *sfm_open_reader (struct file_handle *, + struct dictionary **, + struct sfm_read_info *); +int sfm_read_case (struct sfm_reader *, struct ccase *); +void sfm_close_reader (struct sfm_reader *); + +#endif /* sfm-read.h */ diff --git a/src/sfm-write.c b/src/sfm-write.c index 8769e235..aedb5a8a 100644 --- a/src/sfm-write.c +++ b/src/sfm-write.c @@ -18,7 +18,7 @@ 02111-1307, USA. */ #include -#include "sfm.h" +#include "sfm-write.h" #include "sfmP.h" #include "error.h" #include @@ -29,6 +29,8 @@ #include /* Required by SunOS4. */ #endif #include "alloc.h" +#include "case.h" +#include "dictionary.h" #include "error.h" #include "file-handle.h" #include "getline.h" @@ -42,109 +44,131 @@ #include "debug-print.h" -/* PORTME: This file may require substantial revision for those - systems that don't meet the typical 32-bit integer/64-bit double - model. It's kinda hard to tell without having one of them on my - desk. */ - /* Compression bias used by PSPP. Values between (1 - COMPRESSION_BIAS) and (251 - COMPRESSION_BIAS) inclusive can be compressed. */ #define COMPRESSION_BIAS 100 -/* sfm writer file_handle extension. */ -struct sfm_fhuser_ext +/* System file writer. */ +struct sfm_writer { - FILE *file; /* Actual file. */ + struct file_handle *fh; /* File handle. */ + FILE *file; /* File stream. */ + + int needs_translation; /* 0=use fast path, 1=translation needed. */ + int compress; /* 1=compressed, 0=not compressed. */ + int case_cnt; /* Number of cases written so far. */ + size_t flt64_cnt; /* Number of flt64 elements in case. */ - int compressed; /* 1=compressed, 0=not compressed. */ + /* Compression buffering. */ flt64 *buf; /* Buffered data. */ flt64 *end; /* Buffer end. */ flt64 *ptr; /* Current location in buffer. */ unsigned char *x; /* Location in current instruction octet. */ unsigned char *y; /* End of instruction octet. */ - int n_cases; /* Number of cases written so far. */ - char *elem_type; /* ALPHA or NUMERIC for each flt64 element. */ + /* Variables. */ + struct sfm_var *vars; /* Variables. */ + size_t var_cnt; /* Number of variables. */ }; -static struct fh_ext_class sfm_w_class; +/* A variable in a system file. */ +struct sfm_var + { + int width; /* 0=numeric, otherwise string width. */ + int fv; /* Index into case. */ + size_t flt64_cnt; /* Number of flt64 elements. */ + }; static char *append_string_max (char *, const char *, const char *); -static int write_header (struct sfm_write_info *inf); -static int bufwrite (struct file_handle *h, const void *buf, size_t nbytes); -static int write_variable (struct sfm_write_info *inf, struct variable *v); -static int write_value_labels (struct sfm_write_info *inf, struct variable * s, int index); -static int write_rec_7_34 (struct sfm_write_info *inf); -static int write_documents (struct sfm_write_info *inf); - -/* Writes the dictionary INF->dict to system file INF->h. The system - file is compressed if INF->compress is nonzero. INF->case_size is - set to the number of flt64 elements in a single case. Returns - nonzero only if successful. */ -int -sfm_write_dictionary (struct sfm_write_info *inf) +static int write_header (struct sfm_writer *, const struct dictionary *); +static int buf_write (struct sfm_writer *, const void *, size_t); +static int write_variable (struct sfm_writer *, struct variable *); +static int write_value_labels (struct sfm_writer *, + struct variable *, int idx); +static int write_rec_7_34 (struct sfm_writer *); +static int write_documents (struct sfm_writer *, const struct dictionary *); +static int does_dict_need_translation (const struct dictionary *); + +static inline int +var_flt64_cnt (const struct variable *v) +{ + return v->type == NUMERIC ? 1 : DIV_RND_UP (v->width, sizeof (flt64)); +} + +/* Opens the system file designated by file handle FH for writing + cases from dictionary D. If COMPRESS is nonzero, the + system file will be compressed. + + No reference to D is retained, so it may be modified or + destroyed at will after this function returns. */ +struct sfm_writer * +sfm_open_writer (struct file_handle *fh, + const struct dictionary *d, int compress) { - struct dictionary *d = inf->dict; - struct sfm_fhuser_ext *ext; + struct sfm_writer *w = NULL; + int idx; int i; - int index; - if (inf->h->class != NULL) + if (!fh_open (fh, "system file", "we")) + goto error; + + /* Create and initialize writer. */ + w = xmalloc (sizeof *w); + w->fh = fh; + w->file = fopen (handle_get_filename (fh), "wb"); + + w->needs_translation = does_dict_need_translation (d); + w->compress = compress; + w->case_cnt = 0; + w->flt64_cnt = 0; + + w->buf = w->end = w->ptr = NULL; + w->x = w->y = NULL; + + w->var_cnt = dict_get_var_cnt (d); + w->vars = xmalloc (sizeof *w->vars * w->var_cnt); + for (i = 0; i < w->var_cnt; i++) { - msg (ME, _("Cannot write file %s as system file: " - "already opened for %s."), - handle_get_name (inf->h), inf->h->class->name); - return 0; + const struct variable *dv = dict_get_var (d, i); + struct sfm_var *sv = &w->vars[i]; + sv->width = dv->width; + sv->fv = dv->fv; + sv->flt64_cnt = var_flt64_cnt (dv); } - msg (VM (1), _("%s: Opening system-file handle %s for writing."), - handle_get_filename (inf->h), handle_get_name (inf->h)); - - /* Open the physical disk file. */ - inf->h->class = &sfm_w_class; - inf->h->ext = ext = xmalloc (sizeof (struct sfm_fhuser_ext)); - ext->file = fopen (handle_get_filename (inf->h), "wb"); - ext->elem_type = NULL; - if (ext->file == NULL) + /* Check that file create succeeded. */ + if (w->file == NULL) { - msg (ME, _("An error occurred while opening \"%s\" for writing " + msg (ME, _("Error opening \"%s\" for writing " "as a system file: %s."), - handle_get_filename (inf->h), strerror (errno)); + handle_get_filename (w->fh), strerror (errno)); err_cond_fail (); - free (ext); - return 0; + goto error; } - /* Initialize the sfm_fhuser_ext structure. */ - ext->compressed = inf->compress; - ext->buf = ext->ptr = NULL; - ext->x = ext->y = NULL; - ext->n_cases = 0; - /* Write the file header. */ - if (!write_header (inf)) - goto lossage; + if (!write_header (w, d)) + goto error; /* Write basic variable info. */ for (i = 0; i < dict_get_var_cnt (d); i++) - write_variable (inf, dict_get_var (d, i)); + write_variable (w, dict_get_var (d, i)); /* Write out value labels. */ - for (index = i = 0; i < dict_get_var_cnt (d); i++) + for (idx = i = 0; i < dict_get_var_cnt (d); i++) { struct variable *v = dict_get_var (d, i); - if (!write_value_labels (inf, v, index)) - goto lossage; - index += (v->type == NUMERIC ? 1 - : DIV_RND_UP (v->width, sizeof (flt64))); + if (!write_value_labels (w, v, idx)) + goto error; + idx += var_flt64_cnt (v); } - if (dict_get_documents (d) != NULL && !write_documents (inf)) - goto lossage; - if (!write_rec_7_34 (inf)) - goto lossage; + if (dict_get_documents (d) != NULL && !write_documents (w, d)) + goto error; + if (!write_rec_7_34 (w)) + goto error; /* Write record 999. */ { @@ -158,22 +182,41 @@ sfm_write_dictionary (struct sfm_write_info *inf) rec_999.rec_type = 999; rec_999.filler = 0; - if (!bufwrite (inf->h, &rec_999, sizeof rec_999)) - goto lossage; + if (!buf_write (w, &rec_999, sizeof rec_999)) + goto error; } - msg (VM (2), _("Wrote system-file header successfully.")); + if (w->compress) + { + w->buf = xmalloc (sizeof *w->buf * 128); + w->ptr = w->buf; + w->end = &w->buf[128]; + w->x = (unsigned char *) w->ptr++; + w->y = (unsigned char *) w->ptr; + } - return 1; + return w; -lossage: - msg (VM (1), _("Error writing system-file header.")); - fclose (ext->file); - inf->h->class = NULL; - inf->h->ext = NULL; - free (ext->elem_type); - ext->elem_type = NULL; - return 0; + error: + sfm_close_writer (w); + return NULL; +} + +static int +does_dict_need_translation (const struct dictionary *d) +{ + size_t case_idx; + size_t i; + + case_idx = 0; + for (i = 0; i < dict_get_var_cnt (d); i++) + { + struct variable *v = dict_get_var (d, i); + if (v->fv != case_idx) + return 0; + case_idx += v->nv; + } + return 1; } /* Returns value of X truncated to two least-significant digits. */ @@ -187,13 +230,10 @@ rerange (int x) return x; } -/* Write the sysfile_header header to the system file represented by - INF. */ +/* Write the sysfile_header header to system file W. */ static int -write_header (struct sfm_write_info *inf) +write_header (struct sfm_writer *w, const struct dictionary *d) { - struct dictionary *d = inf->dict; - struct sfm_fhuser_ext *ext = inf->h->ext; struct sysfile_header hdr; char *p; int i; @@ -210,31 +250,17 @@ write_header (struct sfm_write_info *inf) hdr.layout_code = 2; - hdr.case_size = 0; + w->flt64_cnt = 0; for (i = 0; i < dict_get_var_cnt (d); i++) - { - struct variable *v = dict_get_var (d, i); - hdr.case_size += (v->type == NUMERIC ? 1 - : DIV_RND_UP (v->width, sizeof (flt64))); - } - inf->case_size = hdr.case_size; + w->flt64_cnt += var_flt64_cnt (dict_get_var (d, i)); + hdr.case_size = w->flt64_cnt; - p = ext->elem_type = xmalloc (inf->case_size); - for (i = 0; i < dict_get_var_cnt (d); i++) - { - struct variable *v = dict_get_var (d, i); - int count = (v->type == NUMERIC ? 1 - : DIV_RND_UP (v->width, sizeof (flt64))); - while (count--) - *p++ = v->type; - } - - hdr.compressed = inf->compress; + hdr.compress = w->compress; if (dict_get_weight (d) != NULL) { struct variable *weight_var; - int recalc_weight_index = 1; + int recalc_weight_idx = 1; int i; weight_var = dict_get_weight (d); @@ -243,18 +269,17 @@ write_header (struct sfm_write_info *inf) struct variable *v = dict_get_var (d, i); if (v == weight_var) break; - recalc_weight_index += (v->type == NUMERIC ? 1 - : DIV_RND_UP (v->width, sizeof (flt64))); + recalc_weight_idx += var_flt64_cnt (v); } - hdr.weight_index = recalc_weight_index; + hdr.weight_idx = recalc_weight_idx; } else - hdr.weight_index = 0; + hdr.weight_idx = 0; - hdr.ncases = -1; + hdr.case_cnt = -1; hdr.bias = COMPRESSION_BIAS; - if ((time_t) - 1 == time (&t)) + if (time (&t) == (time_t) -1) { memcpy (hdr.creation_date, "01 Jan 70", 9); memcpy (hdr.creation_time, "00:00:00", 8); @@ -262,10 +287,10 @@ write_header (struct sfm_write_info *inf) else { static const char *month_name[12] = - { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", - }; + { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + }; struct tm *tmp = localtime (&t); int day = rerange (tmp->tm_mday); int mon = rerange (tmp->tm_mon + 1); @@ -291,7 +316,7 @@ write_header (struct sfm_write_info *inf) memset (hdr.padding, 0, sizeof hdr.padding); - if (!bufwrite (inf->h, &hdr, sizeof hdr)) + if (!buf_write (w, &hdr, sizeof hdr)) return 0; return 1; } @@ -305,18 +330,18 @@ write_format_spec (struct fmt_spec *src, int32 *dest) } /* Write the variable record(s) for primary variable P and secondary - variable S to the system file represented by INF. */ + variable S to system file W. */ static int -write_variable (struct sfm_write_info *inf, struct variable *v) +write_variable (struct sfm_writer *w, struct variable *v) { struct sysfile_variable sv; /* Missing values. */ - flt64 m[3]; /* Missing value values. */ - int nm; /* Number of missing values, possibly negative. */ + flt64 m[3]; /* Missing value values. */ + int nm; /* Number of missing values, possibly negative. */ sv.rec_type = 2; - sv.type = (v->type == NUMERIC ? 0 : v->width); + sv.type = v->width; sv.has_var_label = (v->label != NULL); switch (v->miss_type) @@ -373,7 +398,7 @@ write_variable (struct sfm_write_info *inf, struct variable *v) write_format_spec (&v->write, &sv.write); memcpy (sv.name, v->name, strlen (v->name)); memset (&sv.name[strlen (v->name)], ' ', 8 - strlen (v->name)); - if (!bufwrite (inf->h, &sv, sizeof sv)) + if (!buf_write (w, &sv, sizeof sv)) return 0; if (v->label) @@ -392,11 +417,11 @@ write_variable (struct sfm_write_info *inf, struct variable *v) memcpy (l.label, v->label, l.label_len); memset (&l.label[l.label_len], ' ', ext_len - l.label_len); - if (!bufwrite (inf->h, &l, offsetof (struct label, label) + ext_len)) - return 0; + if (!buf_write (w, &l, offsetof (struct label, label) + ext_len)) + return 0; } - if (nm && !bufwrite (inf->h, m, sizeof *m * nm)) + if (nm && !buf_write (w, m, sizeof *m * nm)) return 0; if (v->type == ALPHA && v->width > (int) sizeof (flt64)) @@ -413,7 +438,7 @@ write_variable (struct sfm_write_info *inf, struct variable *v) pad_count = DIV_RND_UP (v->width, (int) sizeof (flt64)) - 1; for (i = 0; i < pad_count; i++) - if (!bufwrite (inf->h, &sv, sizeof sv)) + if (!buf_write (w, &sv, sizeof sv)) return 0; } @@ -421,10 +446,10 @@ write_variable (struct sfm_write_info *inf, struct variable *v) } /* Writes the value labels for variable V having system file variable - index INDEX to the system file associated with INF. Returns + index IDX to system file W. Returns nonzero only if successful. */ static int -write_value_labels (struct sfm_write_info * inf, struct variable *v, int index) +write_value_labels (struct sfm_writer *w, struct variable *v, int idx) { struct value_label_rec { @@ -433,7 +458,7 @@ write_value_labels (struct sfm_write_info * inf, struct variable *v, int index) flt64 labels[1] P; }; - struct variable_index_rec + struct var_idx_rec { int32 rec_type P; int32 n_vars P; @@ -442,7 +467,7 @@ write_value_labels (struct sfm_write_info * inf, struct variable *v, int index) struct val_labs_iterator *i; struct value_label_rec *vlr; - struct variable_index_rec vir; + struct var_idx_rec vir; struct val_lab *vl; size_t vlr_size; flt64 *loc; @@ -475,7 +500,7 @@ write_value_labels (struct sfm_write_info * inf, struct variable *v, int index) loc += DIV_RND_UP (len + 1, sizeof (flt64)); } - if (!bufwrite (inf->h, vlr, vlr_size)) + if (!buf_write (w, vlr, vlr_size)) { free (vlr); return 0; @@ -484,8 +509,8 @@ write_value_labels (struct sfm_write_info * inf, struct variable *v, int index) vir.rec_type = 4; vir.n_vars = 1; - vir.vars[0] = index + 1; - if (!bufwrite (inf->h, &vir, sizeof vir)) + vir.vars[0] = idx + 1; + if (!buf_write (w, &vir, sizeof vir)) return 0; return 1; @@ -493,14 +518,13 @@ write_value_labels (struct sfm_write_info * inf, struct variable *v, int index) /* Writes record type 6, document record. */ static int -write_documents (struct sfm_write_info * inf) +write_documents (struct sfm_writer *w, const struct dictionary *d) { - struct dictionary *d = inf->dict; struct - { - int32 rec_type P; /* Always 6. */ - int32 n_lines P; /* Number of lines of documents. */ - } + { + int32 rec_type P; /* Always 6. */ + int32 n_lines P; /* Number of lines of documents. */ + } rec_6; const char *documents; @@ -511,9 +535,9 @@ write_documents (struct sfm_write_info * inf) rec_6.rec_type = 6; rec_6.n_lines = n_lines; - if (!bufwrite (inf->h, &rec_6, sizeof rec_6)) + if (!buf_write (w, &rec_6, sizeof rec_6)) return 0; - if (!bufwrite (inf->h, documents, 80 * n_lines)) + if (!buf_write (w, documents, 80 * n_lines)) return 0; return 1; @@ -521,7 +545,7 @@ write_documents (struct sfm_write_info * inf) /* Writes record type 7, subtypes 3 and 4. */ static int -write_rec_7_34 (struct sfm_write_info * inf) +write_rec_7_34 (struct sfm_writer *w) { struct { @@ -588,7 +612,7 @@ write_rec_7_34 (struct sfm_write_info * inf) rec_7.elem_4[1] = FLT64_MAX; rec_7.elem_4[2] = second_lowest_flt64; - if (!bufwrite (inf->h, &rec_7, sizeof rec_7)) + if (!buf_write (w, &rec_7, sizeof rec_7)) return 0; return 1; } @@ -596,15 +620,13 @@ write_rec_7_34 (struct sfm_write_info * inf) /* Write NBYTES starting at BUF to the system file represented by H. */ static int -bufwrite (struct file_handle * h, const void *buf, size_t nbytes) +buf_write (struct sfm_writer *w, const void *buf, size_t nbytes) { - struct sfm_fhuser_ext *ext = h->ext; - - assert (buf); - if (1 != fwrite (buf, nbytes, 1, ext->file)) + assert (buf != NULL); + if (fwrite (buf, nbytes, 1, w->file) != 1) { msg (ME, _("%s: Writing system file: %s."), - handle_get_filename (h), strerror (errno)); + handle_get_filename (w->fh), strerror (errno)); return 0; } return 1; @@ -625,132 +647,169 @@ append_string_max (char *dest, const char *src, const char *end) element. If there's not room, pads out the current instruction octet with zero and dumps out the buffer. */ static inline int -ensure_buf_space (struct file_handle *h) +ensure_buf_space (struct sfm_writer *w) { - struct sfm_fhuser_ext *ext = h->ext; - - if (ext->ptr >= ext->end) + if (w->ptr >= w->end) { - memset (ext->x, 0, ext->y - ext->x); - ext->x = ext->y; - ext->ptr = ext->buf; - if (!bufwrite (h, ext->buf, sizeof *ext->buf * 128)) + memset (w->x, 0, w->y - w->x); + w->x = w->y; + w->ptr = w->buf; + if (!buf_write (w, w->buf, sizeof *w->buf * 128)) return 0; } return 1; } -/* Writes case ELEM consisting of N_ELEM flt64 elements to the system - file represented by H. Return success. */ +static void write_compressed_data (struct sfm_writer *w, const flt64 *elem); + +/* Writes case C to system file W. + Returns nonzero if successful. */ int -sfm_write_case (struct file_handle * h, const flt64 *elem, int n_elem) +sfm_write_case (struct sfm_writer *w, struct ccase *c) { - struct sfm_fhuser_ext *ext = h->ext; - const flt64 *end_elem = &elem[n_elem]; - char *elem_type = ext->elem_type; + w->case_cnt++; - ext->n_cases++; + if (!w->needs_translation && !w->compress + && sizeof (flt64) == sizeof (union value)) + { + /* Fast path: external and internal representations are the + same and the dictionary is properly ordered. Write + directly to file. */ + buf_write (w, case_data_all (c), sizeof (union value) * w->flt64_cnt); + } + else + { + /* Slow path: internal and external representations differ. + Write into a bounce buffer, then write to W. */ + flt64 *bounce; + flt64 *bounce_cur; + size_t bounce_size; + size_t i; + + bounce_size = sizeof *bounce * w->flt64_cnt; + bounce = bounce_cur = local_alloc (bounce_size); + + for (i = 0; i < w->var_cnt; i++) + { + struct sfm_var *v = &w->vars[i]; + + if (v->width == 0) + *bounce_cur = case_num (c, v->fv); + else + memcpy (bounce_cur, case_data (c, v->fv)->s, v->width); + bounce_cur += v->flt64_cnt; + } - if (ext->compressed == 0) - return bufwrite (h, elem, sizeof *elem * n_elem); + if (!w->compress) + buf_write (w, bounce, bounce_size); + else + write_compressed_data (w, bounce); + + local_free (bounce); + } + + return 1; +} - if (ext->buf == NULL) +static void +put_instruction (struct sfm_writer *w, unsigned char instruction) +{ + if (w->x >= w->y) { - ext->buf = xmalloc (sizeof *ext->buf * 128); - ext->ptr = ext->buf; - ext->end = &ext->buf[128]; - ext->x = (unsigned char *) (ext->ptr++); - ext->y = (unsigned char *) (ext->ptr); + if (!ensure_buf_space (w)) + return; + w->x = (unsigned char *) w->ptr++; + w->y = (unsigned char *) w->ptr; } - for (; elem < end_elem; elem++, elem_type++) + *w->x++ = instruction; +} + +static void +put_element (struct sfm_writer *w, const flt64 *elem) +{ + if (!ensure_buf_space (w)) + return; + memcpy (w->ptr++, elem, sizeof *elem); +} + +static void +write_compressed_data (struct sfm_writer *w, const flt64 *elem) +{ + size_t i; + + for (i = 0; i < w->var_cnt; i++) { - if (ext->x >= ext->y) - { - if (!ensure_buf_space (h)) - return 0; - ext->x = (unsigned char *) (ext->ptr++); - ext->y = (unsigned char *) (ext->ptr); - } + struct sfm_var *v = &w->vars[i]; - if (*elem_type == NUMERIC) + if (v->width == 0) { - if (*elem == -FLT64_MAX) + if (*elem == -FLT64_MAX) + put_instruction (w, 255); + else if (*elem >= 1 - COMPRESSION_BIAS + && *elem <= 251 - COMPRESSION_BIAS + && *elem == (int) *elem) + put_instruction (w, (int) *elem + COMPRESSION_BIAS); + else { - *ext->x++ = 255; - continue; - } - else if (*elem > INT_MIN && *elem < INT_MAX) - { - int value = *elem; - - if (value >= 1 - COMPRESSION_BIAS - && value <= 251 - COMPRESSION_BIAS - && value == *elem) - { - *ext->x++ = value + COMPRESSION_BIAS; - continue; - } + put_instruction (w, 253); + put_element (w, elem); } + elem++; } - else - { - if (0 == memcmp ((char *) elem, - " ", - sizeof (flt64))) + else + { + size_t j; + + for (j = 0; j < v->flt64_cnt; j++, elem++) { - *ext->x++ = 254; - continue; + if (!memcmp (elem, " ", sizeof (flt64))) + put_instruction (w, 254); + else + { + put_instruction (w, 253); + put_element (w, elem); + } } } - - *ext->x++ = 253; - if (!ensure_buf_space (h)) - return 0; - *ext->ptr++ = *elem; } - - return 1; } /* Closes a system file after we're done with it. */ -static void -sfm_close (struct file_handle * h) +void +sfm_close_writer (struct sfm_writer *w) { - struct sfm_fhuser_ext *ext = h->ext; + if (w == NULL) + return; - if (ext->buf != NULL && ext->ptr > ext->buf) + fh_close (w->fh, "system file", "we"); + + if (w->file != NULL) { - memset (ext->x, 0, ext->y - ext->x); - bufwrite (h, ext->buf, (ext->ptr - ext->buf) * sizeof *ext->buf); - } + /* Flush buffer. */ + if (w->buf != NULL && w->ptr > w->buf) + { + memset (w->x, 0, w->y - w->x); + buf_write (w, w->buf, (w->ptr - w->buf) * sizeof *w->buf); + } - /* Attempt to seek back to the beginning in order to write the - number of cases. If that's not possible (i.e., we're writing to - a tty or a pipe), then it's not a big deal because we wrote the - code that indicates an unknown number of cases. */ - if (0 == fseek (ext->file, offsetof (struct sysfile_header, ncases), - SEEK_SET)) - { - int32 n_cases = ext->n_cases; + /* Seek back to the beginning and update the number of cases. + This is just a courtesy to later readers, so there's no need + to check return values or report errors. */ + if (!fseek (w->file, offsetof (struct sysfile_header, case_cnt), SEEK_SET)) + { + int32 case_cnt = w->case_cnt; - /* I don't really care about the return value: it doesn't matter - whether this data is written. This is the only situation in - which you will see me fail to check a return value. */ - fwrite (&n_cases, sizeof n_cases, 1, ext->file); - } + /* I don't really care about the return value: it doesn't + matter whether this data is written. */ + fwrite (&case_cnt, sizeof case_cnt, 1, w->file); + } - if (EOF == fclose (ext->file)) - msg (ME, _("%s: Closing system file: %s."), - handle_get_filename (h), strerror (errno)); - free (ext->buf); + if (fclose (w->file) == EOF) + msg (ME, _("%s: Closing system file: %s."), + handle_get_filename (w->fh), strerror (errno)); + } - free (ext->elem_type); - free (ext); + free (w->buf); + free (w->vars); + free (w); } - -static struct fh_ext_class sfm_w_class = -{ - 4, - N_("writing as a system file"), - sfm_close, -}; diff --git a/src/sfm-write.h b/src/sfm-write.h new file mode 100644 index 00000000..82cf2c95 --- /dev/null +++ b/src/sfm-write.h @@ -0,0 +1,33 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef SFM_WRITE_H +#define SFM_WRITE_H 1 + +/* Writing system files. */ + +struct file_handle; +struct dictionary; +struct ccase; +struct sfm_writer *sfm_open_writer (struct file_handle *, + const struct dictionary *, int compress); +int sfm_write_case (struct sfm_writer *, struct ccase *); +void sfm_close_writer (struct sfm_writer *); + +#endif /* sfm-write.h */ diff --git a/src/sfm.h b/src/sfm.h deleted file mode 100644 index e5691649..00000000 --- a/src/sfm.h +++ /dev/null @@ -1,66 +0,0 @@ -/* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . - - 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -#if !sfm_h -#define sfm_h 1 - -/* System file manager (sfm). - - This module is in charge of reading and writing system files. For - now, only ordinary system files are supported; in the future, PC+ - compatible system files should be supported, too. sfm is an - fhuser, so see file-handle.h for the fhuser interface. */ - -/* Information produced by sfm_read_dictionary() that doesn't fit into - a dictionary struct. */ -struct sfm_read_info - { - char creation_date[10]; /* `dd mmm yy' plus a null. */ - char creation_time[9]; /* `hh:mm:ss' plus a null. */ - int bigendian; /* 1=big-endian, 0=little-endian. */ - int compressed; /* 0=no, 1=yes. */ - int ncases; /* -1 if unknown. */ - char product[61]; /* Product name plus a null. */ - }; - -struct dictionary; -struct file_handle; -struct ccase; - -struct dictionary *sfm_read_dictionary (struct file_handle *, - struct sfm_read_info *); -int sfm_read_case (struct file_handle *, struct ccase *, struct dictionary *); -void sfm_maybe_close (struct file_handle *); - -/* Information needed by sfm_write_dictionary(). */ -struct sfm_write_info - { - /* Read by sfm_write_dictionary(). */ - struct file_handle *h; /* File handle. */ - struct dictionary *dict; /* Primary dictionary. */ - int compress; /* 1=compress, 0=do not compress. */ - - /* Written by sfm_write_dictionary(). */ - int case_size; /* Number of flt64 elements per case. */ - }; - -int sfm_write_dictionary (struct sfm_write_info *); -int sfm_write_case (struct file_handle *, const flt64* elem, int n_elem); - -#endif /* !sfm_h */ diff --git a/src/sfmP.h b/src/sfmP.h index fd47a070..6734087e 100644 --- a/src/sfmP.h +++ b/src/sfmP.h @@ -30,18 +30,18 @@ /* Record Type 1: General Information. */ struct sysfile_header { - char rec_type[4] P; /* Record-type code, "$FL2". */ - char prod_name[60] P; /* Product identification. */ - int32 layout_code P; /* 2. */ - int32 case_size P; /* Number of `value's per case. */ - int32 compressed P; /* 1=compressed, 0=not compressed. */ - int32 weight_index P; /* 1-based index of weighting var, or zero. */ - int32 ncases P; /* Number of cases, -1 if unknown. */ - flt64 bias P; /* Compression bias (100.0). */ - char creation_date[9] P; /* `dd mmm yy' creation date of file. */ - char creation_time[8] P; /* `hh:mm:ss' 24-hour creation time. */ - char file_label[64] P; /* File label. */ - char padding[3] P; /* Ignored padding. */ + char rec_type[4] P; /* 00: Record-type code, "$FL2". */ + char prod_name[60] P; /* 04: Product identification. */ + int32 layout_code P; /* 40: 2. */ + int32 case_size P; /* 44: Number of `value's per case. */ + int32 compress P; /* 48: 1=compressed, 0=not compressed. */ + int32 weight_idx P; /* 4c: 1-based index of weighting var, or 0. */ + int32 case_cnt P; /* 50: Number of cases, -1 if unknown. */ + flt64 bias P; /* 54: Compression bias (100.0). */ + char creation_date[9] P; /* 5c: `dd mmm yy' creation date of file. */ + char creation_time[8] P; /* 65: `hh:mm:ss' 24-hour creation time. */ + char file_label[64] P; /* 6d: File label. */ + char padding[3] P; /* ad: Ignored padding. */ }; /* Record Type 2: Variable. */ diff --git a/src/split-file.c b/src/split-file.c index 6eba150b..733aa9fb 100644 --- a/src/split-file.c +++ b/src/split-file.c @@ -21,6 +21,7 @@ #include #include "alloc.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "lexer.h" #include "str.h" diff --git a/src/str.c b/src/str.c index 9d2d0b3c..265c2a23 100644 --- a/src/str.c +++ b/src/str.c @@ -326,6 +326,13 @@ ds_c_str (const struct string *st) return st->string; } +/* Returns the string data inside ST. */ +char * +ds_data (const struct string *st) +{ + return st->string; +} + /* Returns a pointer to the null terminator ST. This might not be an actual null character unless ds_c_str() has been called since the last modification to ST. */ diff --git a/src/str.h b/src/str.h index b1a44e22..9b90cf60 100644 --- a/src/str.h +++ b/src/str.h @@ -40,7 +40,7 @@ char *strtok_r (char *, const char *, char **); #endif -#if !HAVE_STPCPY && !__linux__ +#if !HAVE_STPCPY char *stpcpy (char *dest, const char *src); #endif diff --git a/src/sysfile-info.c b/src/sysfile-info.c index 5a91fc39..5c8f6a65 100644 --- a/src/sysfile-info.c +++ b/src/sysfile-info.c @@ -24,13 +24,14 @@ #include "algorithm.h" #include "alloc.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "file-handle.h" #include "hash.h" #include "lexer.h" #include "misc.h" #include "output.h" -#include "sfm.h" +#include "sfm-read.h" #include "som.h" #include "tab.h" #include "value-labels.h" @@ -73,21 +74,22 @@ cmd_sysfile_info (void) struct file_handle *h; struct dictionary *d; struct tab_table *t; - struct sfm_read_info inf; + struct sfm_reader *reader; + struct sfm_read_info info; int r, nr; int i; lex_match_id ("FILE"); lex_match ('='); - h = fh_parse_file_handle (); + h = fh_parse (); if (!h) return CMD_FAILURE; - d = sfm_read_dictionary (h, &inf); - fh_close_handle (h); - if (!d) + reader = sfm_open_reader (h, &d, &info); + if (!reader) return CMD_FAILURE; + sfm_close_reader (reader); t = tab_create (2, 9, 0); tab_vline (t, TAL_1 | TAL_SPACING, 1, 0, 8); @@ -102,15 +104,15 @@ cmd_sysfile_info (void) } tab_text (t, 0, 2, TAB_LEFT, _("Created:")); tab_text (t, 1, 2, TAB_LEFT | TAT_PRINTF, "%s %s by %s", - inf.creation_date, inf.creation_time, inf.product); + info.creation_date, info.creation_time, info.product); tab_text (t, 0, 3, TAB_LEFT, _("Endian:")); - tab_text (t, 1, 3, TAB_LEFT, inf.bigendian ? _("Big.") : _("Little.")); + tab_text (t, 1, 3, TAB_LEFT, info.big_endian ? _("Big.") : _("Little.")); tab_text (t, 0, 4, TAB_LEFT, _("Variables:")); tab_text (t, 1, 4, TAB_LEFT | TAT_PRINTF, "%d", dict_get_var_cnt (d)); tab_text (t, 0, 5, TAB_LEFT, _("Cases:")); tab_text (t, 1, 5, TAB_LEFT | TAT_PRINTF, - inf.ncases == -1 ? _("Unknown") : "%d", inf.ncases); + info.case_cnt == -1 ? _("Unknown") : "%d", info.case_cnt); tab_text (t, 0, 6, TAB_LEFT, _("Type:")); tab_text (t, 1, 6, TAB_LEFT, _("System File.")); tab_text (t, 0, 7, TAB_LEFT, _("Weight:")); @@ -121,7 +123,7 @@ cmd_sysfile_info (void) } tab_text (t, 0, 8, TAB_LEFT, _("Mode:")); tab_text (t, 1, 8, TAB_LEFT | TAT_PRINTF, - _("Compression %s."), inf.compressed ? _("on") : _("off")); + _("Compression %s."), info.compressed ? _("on") : _("off")); tab_dim (t, tab_natural_dimensions); tab_submit (t); diff --git a/src/t-test.q b/src/t-test.q index ab25065f..d5349ddd 100644 --- a/src/t-test.q +++ b/src/t-test.q @@ -29,6 +29,7 @@ #include "str.h" #include "case.h" #include "command.h" +#include "dictionary.h" #include "lexer.h" #include "error.h" #include "magic.h" @@ -42,6 +43,7 @@ #include "group_proc.h" #include "casefile.h" #include "levene.h" +/* (headers) */ /* (specification) "T-TEST" (tts_): @@ -342,7 +344,7 @@ cmd_t_test(void) /* Destroy any group statistics we created */ for (v = 0 ; v < cmd.n_variables ; ++v ) { - struct group_proc *grpp = &cmd.v_variables[v]->p.grp_data; + struct group_proc *grpp = group_proc_get (cmd.v_variables[v]); free(grpp->group_hash); } } @@ -749,7 +751,7 @@ ssbox_independent_samples_populate(struct ssbox *ssb, for (i=0; i < cmd->n_variables; ++i) { struct variable *var = cmd->v_variables[i]; - struct hsh_table *grp_hash = var->p.grp_data.group_hash; + struct hsh_table *grp_hash = group_proc_get (var)->group_hash; int count=0; tab_text (ssb->t, 0, i*2+1, TAB_LEFT, cmd->v_variables[i]->name); @@ -849,7 +851,7 @@ ssbox_paired_populate(struct ssbox *ssb,struct cmd_t_test *cmd UNUSED) { struct group_statistics *gs; - gs=&pairs[i].v[j]->p.grp_data.ugs; + gs = &group_proc_get (pairs[i].v[j])->ugs; /* Titles */ @@ -875,8 +877,7 @@ ssbox_one_sample_populate(struct ssbox *ssb, struct cmd_t_test *cmd) for (i=0; i < cmd->n_variables; ++i) { - struct group_statistics *gs; - gs= &cmd->v_variables[i]->p.grp_data.ugs; + struct group_statistics *gs = &group_proc_get (cmd->v_variables[i])->ugs; tab_text (ssb->t, 0, i+1, TAB_LEFT, cmd->v_variables[i]->name); tab_float (ssb->t,1, i+1, TAB_RIGHT, gs->n, 2, 0); @@ -1011,8 +1012,9 @@ trbox_independent_samples_populate(struct trbox *self, double mean_diff; struct variable *var = cmd->v_variables[i]; + struct group_proc *grp_data = group_proc_get (var); - struct hsh_table *grp_hash = var->p.grp_data.group_hash; + struct hsh_table *grp_hash = grp_data->group_hash; struct group_statistics *gs0 ; struct group_statistics *gs1 ; @@ -1041,12 +1043,11 @@ trbox_independent_samples_populate(struct trbox *self, tab_text (self->t, 1, i*2+3, TAB_LEFT, _("Equal variances assumed")); - tab_float(self->t, 2, i*2+3, TAB_CENTER, - cmd->v_variables[i]->p.grp_data.levene, 8,3); + tab_float(self->t, 2, i*2+3, TAB_CENTER, grp_data->levene, 8,3); /* Now work out the significance of the Levene test */ - df1 = 1; df2 = cmd->v_variables[i]->p.grp_data.ugs.n - 2; - q = gsl_cdf_fdist_Q(cmd->v_variables[i]->p.grp_data.levene, df1, df2); + df1 = 1; df2 = grp_data->ugs.n - 2; + q = gsl_cdf_fdist_Q(grp_data->levene, df1, df2); tab_float(self->t, 3, i*2+3, TAB_CENTER, q, 8,3 ); @@ -1282,8 +1283,7 @@ trbox_one_sample_populate(struct trbox *trb, struct cmd_t_test *cmd) double t; double p,q; double df; - struct group_statistics *gs; - gs= &cmd->v_variables[i]->p.grp_data.ugs; + struct group_statistics *gs = &group_proc_get (cmd->v_variables[i])->ugs; tab_text (trb->t, 0, i+3, TAB_LEFT, cmd->v_variables[i]->name); @@ -1445,7 +1445,7 @@ common_calc (const struct ccase *c, void *_cmd) struct variable *v = cmd->v_variables[i]; const union value *val = case_data (c, v->fv); - gs= &cmd->v_variables[i]->p.grp_data.ugs; + gs= &group_proc_get (cmd->v_variables[i])->ugs; if (! value_is_missing(val,v) ) { @@ -1466,7 +1466,7 @@ common_precalc ( struct cmd_t_test *cmd ) for(i=0; i< cmd->n_variables ; ++i) { struct group_statistics *gs; - gs= &cmd->v_variables[i]->p.grp_data.ugs; + gs= &group_proc_get (cmd->v_variables[i])->ugs; gs->sum=0; gs->n=0; @@ -1485,7 +1485,7 @@ common_postcalc ( struct cmd_t_test *cmd ) for(i=0; i< cmd->n_variables ; ++i) { struct group_statistics *gs; - gs= &cmd->v_variables[i]->p.grp_data.ugs; + gs= &group_proc_get (cmd->v_variables[i])->ugs; gs->mean=gs->sum / gs->n; gs->s_std_dev= sqrt( @@ -1533,7 +1533,7 @@ one_sample_calc (const struct ccase *c, void *cmd_) struct variable *v = cmd->v_variables[i]; const union value *val = case_data (c, v->fv); - gs= &cmd->v_variables[i]->p.grp_data.ugs; + gs= &group_proc_get (cmd->v_variables[i])->ugs; if ( ! value_is_missing(val,v)) gs->sum_diff += weight * (val->f - cmd->n_testval[0]); @@ -1551,7 +1551,7 @@ one_sample_precalc ( struct cmd_t_test *cmd ) for(i=0; i< cmd->n_variables ; ++i) { struct group_statistics *gs; - gs= &cmd->v_variables[i]->p.grp_data.ugs; + gs= &group_proc_get (cmd->v_variables[i])->ugs; gs->sum_diff=0; } @@ -1566,7 +1566,7 @@ one_sample_postcalc (struct cmd_t_test *cmd) for(i=0; i< cmd->n_variables ; ++i) { struct group_statistics *gs; - gs= &cmd->v_variables[i]->p.grp_data.ugs; + gs= &group_proc_get (cmd->v_variables[i])->ugs; gs->mean_diff = gs->sum_diff / gs->n ; } @@ -1715,7 +1715,7 @@ group_precalc (struct cmd_t_test *cmd ) for(i=0; i< cmd->n_variables ; ++i) { - struct group_proc *ttpr = &cmd->v_variables[i]->p.grp_data; + struct group_proc *ttpr = group_proc_get (cmd->v_variables[i]); /* There's always 2 groups for a T - TEST */ ttpr->n_groups = 2; @@ -1791,7 +1791,7 @@ group_calc (const struct ccase *c, struct cmd_t_test *cmd) { struct variable *var = cmd->v_variables[i]; const union value *val = case_data (c, var->fv); - struct hsh_table *grp_hash = var->p.grp_data.group_hash; + struct hsh_table *grp_hash = group_proc_get (var)->group_hash; struct group_statistics *gs; gs = hsh_find(grp_hash, (void *) gv); @@ -1821,7 +1821,7 @@ group_postcalc ( struct cmd_t_test *cmd ) for(i=0; i< cmd->n_variables ; ++i) { struct variable *var = cmd->v_variables[i]; - struct hsh_table *grp_hash = var->p.grp_data.group_hash; + struct hsh_table *grp_hash = group_proc_get (var)->group_hash; struct hsh_iterator g; struct group_statistics *gs; int count=0; diff --git a/src/temporary.c b/src/temporary.c index c04ce764..0edb37f5 100644 --- a/src/temporary.c +++ b/src/temporary.c @@ -23,6 +23,7 @@ #include #include "alloc.h" #include "command.h" +#include "dictionary.h" #include "do-ifP.h" #include "error.h" #include "hash.h" diff --git a/src/title.c b/src/title.c index e0191acc..68a38e47 100644 --- a/src/title.c +++ b/src/title.c @@ -22,6 +22,7 @@ #include #include "alloc.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "lexer.h" #include "main.h" diff --git a/src/value-labels.c b/src/value-labels.c index 91dd1702..8b1d3286 100644 --- a/src/value-labels.c +++ b/src/value-labels.c @@ -21,9 +21,9 @@ #include "value-labels.h" #include "error.h" #include -#include #include "alloc.h" #include "hash.h" +#include "str.h" static hsh_compare_func compare_int_val_lab; static hsh_hash_func hash_int_val_lab; diff --git a/src/var.h b/src/var.h index d7756fce..46a0efc5 100644 --- a/src/var.h +++ b/src/var.h @@ -22,7 +22,6 @@ #include #include "format.h" -#include "group_proc.h" #include "val.h" /* Frequency tables. */ @@ -67,93 +66,6 @@ struct freq_tab double valid_cases; /* Sum of weights of valid cases. */ }; -/* Procedures' private per-variable data. */ - -/* Structure name suffixes for private data: - _proc: for a procedure (i.e., LIST -> list_proc). - _trns: for a transformation (i.e., COMPUTE -> compute_trns. - _pgm: for an input program (i.e., DATA LIST -> data_list_pgm). */ - -/* CROSSTABS private data. */ -struct crosstab_proc - { - /* Integer mode only. */ - int min; /* Minimum value. */ - int max; /* Maximum value + 1. */ - int count; /* max - min. */ - }; - - -/* FREQUENCIES private data. */ -enum - { - frq_mean = 0, frq_semean, frq_median, frq_mode, frq_stddev, frq_variance, - frq_kurt, frq_sekurt, frq_skew, frq_seskew, frq_range, frq_min, frq_max, - frq_sum, frq_n_stats - }; - -struct frequencies_proc - { - int used; /* 1=This variable already used. */ - - /* Freqency table. */ - struct freq_tab tab; /* Frequencies table to use. */ - - /* Percentiles. */ - int n_groups; /* Number of groups. */ - double *groups; /* Groups. */ - - /* Statistics. */ - double stat[frq_n_stats]; - }; - -/* LIST private data. */ -struct list_proc - { - int newline; /* Whether a new line begins here. */ - int width; /* Field width. */ - int vert; /* Whether to print the varname vertically. */ - }; - -/* GET private data. */ -struct get_proc - { - int fv, nv; /* First, # of values. */ - }; - -/* MEANS private data. */ -struct means_proc - { - double min, max; /* Range for integer mode. */ - }; - -/* Different types of variables for MATRIX DATA procedure. Order is - important: these are used for sort keys. */ -enum - { - MXD_SPLIT, /* SPLIT FILE variables. */ - MXD_ROWTYPE, /* ROWTYPE_. */ - MXD_FACTOR, /* Factor variables. */ - MXD_VARNAME, /* VARNAME_. */ - MXD_CONTINUOUS, /* Continuous variables. */ - - MXD_COUNT - }; - -/* MATRIX DATA private data. */ -struct matrix_data_proc - { - int vartype; /* Variable type. */ - int subtype; /* Subtype. */ - }; - -/* MATCH FILES private data. */ -struct match_files_proc - { - struct variable *master; /* Corresponding master file variable. */ - }; - - /* Script variables. */ /* Variable type. */ @@ -164,8 +76,7 @@ enum }; /* Types of missing values. Order is significant, see - mis-val.c:parse_numeric(), sfm-read.c:sfm_read_dictionary() - sfm-write.c:sfm_write_dictionary(), + mis-val.c:parse_numeric(), sfm-read.c, sfm-write.c, sysfile-info.c:cmd_sysfile_info(), mis-val.c:copy_missing_values(), pfm-read.c:read_variables(), pfm-write.c:write_variables(), apply-dict.c:cmd_apply_dictionary(), and more (?). */ @@ -208,25 +119,20 @@ struct variable struct val_labs *val_labs; /* Value labels. */ char *label; /* Variable label. */ - /* Per-procedure info. */ + /* Per-command info. */ void *aux; - struct get_proc get; - union - { - struct crosstab_proc crs; - struct frequencies_proc frq; - struct list_proc lst; - struct means_proc mns; - struct matrix_data_proc mxd; - struct match_files_proc mtf; - struct group_proc grp_data; - } - p; + void (*aux_dtor) (struct variable *); }; int compare_variables (const void *, const void *, void *); unsigned hash_variable (const void *, void *); +void *var_attach_aux (struct variable *, + void *aux, void (*aux_dtor) (struct variable *)); +void var_clear_aux (struct variable *); +void *var_detach_aux (struct variable *); +void var_dtor_free (struct variable *); + /* Classes of variables. */ enum dict_class { @@ -247,82 +153,6 @@ struct vector int cnt; /* Number of variables. */ }; -/* Dictionary. */ - -/* Complete dictionary state. */ -struct dictionary; - -struct dictionary *dict_create (void); -struct dictionary *dict_clone (const struct dictionary *); -void dict_clear (struct dictionary *); -void dict_destroy (struct dictionary *); - -size_t dict_get_var_cnt (const struct dictionary *); -struct variable *dict_get_var (const struct dictionary *, size_t idx); -void dict_get_vars (const struct dictionary *, - struct variable ***vars, size_t *cnt, - unsigned exclude_classes); - -struct variable *dict_create_var (struct dictionary *, const char *, - int width); -struct variable *dict_create_var_assert (struct dictionary *, const char *, - int width); -struct variable *dict_clone_var (struct dictionary *, const struct variable *, - const char *); -void dict_rename_var (struct dictionary *, struct variable *, const char *); - -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 *); -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); -int 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 *); -double dict_get_case_weight (const struct dictionary *, - const struct ccase *, int *); -void dict_set_weight (struct dictionary *, struct variable *); - -struct variable *dict_get_filter (const struct dictionary *); -void dict_set_filter (struct dictionary *, struct variable *); - -int dict_get_case_limit (const struct dictionary *); -void dict_set_case_limit (struct dictionary *, int); - -int dict_get_next_value_idx (const struct dictionary *); -size_t dict_get_case_size (const struct dictionary *); - -void dict_compact_values (struct dictionary *); -size_t dict_get_compacted_value_cnt (const struct dictionary *); -int *dict_get_compacted_idx_to_fv (const struct dictionary *); - -struct variable *const *dict_get_split_vars (const struct dictionary *); -size_t dict_get_split_cnt (const struct dictionary *); -void dict_set_split_vars (struct dictionary *, - struct variable *const *, size_t cnt); - -const char *dict_get_label (const struct dictionary *); -void dict_set_label (struct dictionary *, const char *); - -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); -const struct vector *dict_get_vector (const struct dictionary *, - size_t idx); -size_t dict_get_vector_cnt (const struct dictionary *); -const struct vector *dict_lookup_vector (const struct dictionary *, - const char *name); -void dict_clear_vectors (struct dictionary *); void discard_variables (void); @@ -360,6 +190,7 @@ void cancel_temporary (void); /* Functions. */ +struct ccase; void dump_split_vars (const struct ccase *); typedef int (* is_missing_func )(const union value *, const struct variable *); diff --git a/src/vars-atr.c b/src/vars-atr.c index 0b6877db..3ce08b05 100644 --- a/src/vars-atr.c +++ b/src/vars-atr.c @@ -23,6 +23,7 @@ #include #include "alloc.h" #include "command.h" +#include "dictionary.h" #include "do-ifP.h" #include "expr.h" #include "file-handle.h" @@ -34,6 +35,44 @@ #include "debug-print.h" +void * +var_attach_aux (struct variable *v, + void *aux, void (*aux_dtor) (struct variable *)) +{ + assert (v->aux == NULL); + assert (aux != NULL); + v->aux = aux; + v->aux_dtor = aux_dtor; + return aux; +} + +void * +var_detach_aux (struct variable *v) +{ + void *aux = v->aux; + assert (aux != NULL); + v->aux = NULL; + return aux; +} + +void +var_clear_aux (struct variable *v) +{ + assert (v != NULL); + if (v->aux != NULL) + { + if (v->aux_dtor != NULL) + v->aux_dtor (v); + v->aux = NULL; + } +} + +void +var_dtor_free (struct variable *v) +{ + free (v->aux); +} + /* Compares A and B, which both have the given WIDTH, and returns a strcmp()-type result. */ int @@ -67,7 +106,7 @@ void discard_variables (void) { dict_clear (default_dict); - default_handle = inline_file; + default_handle = NULL; n_lag = 0; diff --git a/src/vars-prs.c b/src/vars-prs.c index 91376a5a..3a83964f 100644 --- a/src/vars-prs.c +++ b/src/vars-prs.c @@ -23,6 +23,7 @@ #include #include "alloc.h" #include "bitvector.h" +#include "dictionary.h" #include "error.h" #include "hash.h" #include "lexer.h" diff --git a/src/vector.c b/src/vector.c index 80582f76..2a712a62 100644 --- a/src/vector.c +++ b/src/vector.c @@ -22,6 +22,7 @@ #include #include "alloc.h" #include "command.h" +#include "dictionary.h" #include "error.h" #include "lexer.h" #include "misc.h" diff --git a/src/vfm.c b/src/vfm.c index 1d3d2a5c..89624165 100644 --- a/src/vfm.c +++ b/src/vfm.c @@ -30,6 +30,7 @@ #include "alloc.h" #include "case.h" #include "casefile.h" +#include "dictionary.h" #include "do-ifP.h" #include "error.h" #include "expr.h" diff --git a/src/weight.c b/src/weight.c index 7fac10cc..c95b7910 100644 --- a/src/weight.c +++ b/src/weight.c @@ -21,6 +21,7 @@ #include "error.h" #include #include "command.h" +#include "dictionary.h" #include "error.h" #include "lexer.h" #include "str.h"