From 55b1c76a0846cb91ac5af9f3d638b7ecf03ea76a Mon Sep 17 00:00:00 2001 From: John Darrington Date: Fri, 27 May 2005 04:39:51 +0000 Subject: [PATCH] Added the parser for the rank command. Separated the sort algorithm from the SORT command parser. --- po/en_GB.po | 169 ++++++++++++----------- po/pspp.pot | 169 ++++++++++++----------- src/ChangeLog | 7 + src/Makefile.am | 7 +- src/aggregate.c | 3 +- src/rank.q | 354 ++++++++++++++++++++++++++++++++++++++++++++++++ src/sort-prs.c | 159 ++++++++++++++++++++++ src/sort-prs.h | 38 ++++++ src/sort.c | 120 +--------------- src/sort.h | 29 +++- 10 files changed, 768 insertions(+), 287 deletions(-) create mode 100644 src/rank.q create mode 100644 src/sort-prs.c create mode 100644 src/sort-prs.h diff --git a/po/en_GB.po b/po/en_GB.po index b37eff2e..65f38593 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: 2005-05-23 12:08+0800\n" +"POT-Creation-Date: 2005-05-27 12:24+0800\n" "PO-Revision-Date: 2004-01-23 13:04+0800\n" "Last-Translator: John Darrington \n" "Language-Team: John Darrington \n" @@ -16,62 +16,62 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -#: src/aggregate.c:195 +#: src/aggregate.c:196 msgid "while expecting COLUMNWISE" msgstr "" -#: src/aggregate.c:224 +#: src/aggregate.c:225 msgid "expecting BREAK" msgstr "" -#: src/aggregate.c:229 +#: src/aggregate.c:230 msgid "" "When PRESORTED is specified, specifying sorting directions with (A) or (D) " "has no effect. Output data will be sorted the same way as the input data." msgstr "" -#: src/aggregate.c:385 +#: src/aggregate.c:386 msgid "expecting aggregation function" msgstr "" -#: src/aggregate.c:401 +#: src/aggregate.c:402 #, c-format msgid "Unknown aggregation function %s." msgstr "" -#: src/aggregate.c:416 +#: src/aggregate.c:417 msgid "expecting `('" msgstr "" -#: src/aggregate.c:453 +#: src/aggregate.c:454 #, c-format msgid "Missing argument %d to %s." msgstr "" -#: src/aggregate.c:462 +#: src/aggregate.c:463 #, c-format msgid "Arguments to %s must be of same type as source variables." msgstr "" -#: src/aggregate.c:472 +#: src/aggregate.c:473 msgid "expecting `)'" msgstr "" -#: src/aggregate.c:484 +#: src/aggregate.c:485 #, c-format msgid "" "Number of source variables (%d) does not match number of target variables (%" "d)." msgstr "" -#: src/aggregate.c:500 +#: src/aggregate.c:501 #, c-format msgid "" "The value arguments passed to the %s function are out-of-order. They will " "be treated as if they had been specified in the correct order." msgstr "" -#: src/aggregate.c:567 +#: src/aggregate.c:568 #, c-format msgid "" "Variable name %s is not unique within the aggregate file dictionary, which " @@ -84,12 +84,12 @@ msgid "Variable %s is %s in target file, but %s in source file." msgstr "" #: src/apply-dict.c:71 src/apply-dict.c:72 src/format.c:236 -#: src/sfm-read.c:1013 src/sfm-read.c:1151 src/sfm-read.c:1152 +#: src/sfm-read.c:1029 src/sfm-read.c:1174 src/sfm-read.c:1175 msgid "string" msgstr "" #: src/apply-dict.c:71 src/apply-dict.c:72 src/format.c:236 -#: src/sfm-read.c:1013 src/sfm-read.c:1151 src/sfm-read.c:1152 +#: src/sfm-read.c:1029 src/sfm-read.c:1174 src/sfm-read.c:1175 msgid "numeric" msgstr "" @@ -1495,11 +1495,11 @@ msgstr "" msgid "%s variables are not compatible with %s format %s." msgstr "" -#: src/format.c:235 src/pfm-read.c:473 src/sfm-read.c:1011 src/sfm-read.c:1020 +#: src/format.c:235 src/pfm-read.c:473 src/sfm-read.c:1027 src/sfm-read.c:1036 msgid "String" msgstr "" -#: src/format.c:235 src/pfm-read.c:473 src/sfm-read.c:1011 src/sfm-read.c:1020 +#: src/format.c:235 src/pfm-read.c:473 src/sfm-read.c:1027 src/sfm-read.c:1036 msgid "Numeric" msgstr "" @@ -1620,14 +1620,14 @@ msgstr "" msgid "IN variable name %s duplicates an existing variable name." msgstr "" -#: src/get.c:1415 +#: src/get.c:1417 #, 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:1506 +#: src/get.c:1508 msgid "expecting COMM or TAPE" msgstr "" @@ -2603,12 +2603,12 @@ msgstr "" msgid "Bad time string length %d." msgstr "" -#: src/pfm-read.c:465 src/sfm-read.c:1003 +#: src/pfm-read.c:465 src/sfm-read.c:1019 #, c-format msgid "%s: Bad format specifier byte (%d)." msgstr "" -#: src/pfm-read.c:472 src/sfm-read.c:1019 +#: src/pfm-read.c:472 src/sfm-read.c:1035 #, c-format msgid "%s variable %s has invalid format specifier %s." msgstr "" @@ -3084,70 +3084,75 @@ msgstr "" msgid "%s: Long variable mapping for nonexistent variable %s." msgstr "" -#: src/sfm-read.c:446 +#: src/sfm-read.c:428 +#, c-format +msgid "%s: Duplicate long variable name `%s' within system file." +msgstr "" + +#: src/sfm-read.c:456 #, c-format msgid "%s: Unrecognized record type 7, subtype %d encountered in system file." msgstr "" -#: src/sfm-read.c:471 +#: src/sfm-read.c:481 #, c-format msgid "%s: Unrecognized record type %d." msgstr "" -#: src/sfm-read.c:503 +#: src/sfm-read.c:513 #, 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:514 +#: src/sfm-read.c:524 #, 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:530 +#: src/sfm-read.c:540 #, c-format msgid "" "%s: File-indicated endianness (%s) does not match endianness intuited from " "file header (%s)." msgstr "" -#: src/sfm-read.c:533 src/sfm-read.c:534 +#: src/sfm-read.c:543 src/sfm-read.c:544 msgid "big-endian" msgstr "" -#: src/sfm-read.c:533 src/sfm-read.c:534 +#: src/sfm-read.c:543 src/sfm-read.c:544 msgid "little-endian" msgstr "" -#: src/sfm-read.c:535 +#: src/sfm-read.c:545 msgid "unknown" msgstr "" -#: src/sfm-read.c:539 +#: src/sfm-read.c:549 #, c-format msgid "%s: File-indicated character representation code (%s) is not ASCII." msgstr "" -#: src/sfm-read.c:543 +#: src/sfm-read.c:553 msgid "DEC Kanji" msgstr "" -#: src/sfm-read.c:543 src/sysfile-info.c:115 +#: src/sfm-read.c:553 src/sysfile-info.c:115 msgid "Unknown" msgstr "" -#: src/sfm-read.c:559 +#: src/sfm-read.c:569 #, 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:574 +#: src/sfm-read.c:584 #, c-format msgid "" "%s: File-indicated value is different from internal value for at least one " @@ -3155,210 +3160,220 @@ msgid "" "%g; LOWEST: %g, %g." msgstr "" -#: src/sfm-read.c:601 +#: src/sfm-read.c:611 #, 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:643 +#: src/sfm-read.c:653 #, 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:671 +#: src/sfm-read.c:681 #, c-format msgid "%s: Number of cases in file (%ld) is not between -1 and %d." msgstr "" -#: src/sfm-read.c:676 +#: src/sfm-read.c:686 #, c-format msgid "%s: Compression bias (%g) is not the usual value of 100." msgstr "" -#: src/sfm-read.c:799 +#: src/sfm-read.c:809 #, c-format msgid "" "%s: position %d: String variable does not have proper number of continuation " "records." msgstr "" -#: src/sfm-read.c:810 +#: src/sfm-read.c:820 #, c-format msgid "%s: position %d: Superfluous long string continuation record." msgstr "" -#: src/sfm-read.c:816 +#: src/sfm-read.c:826 #, c-format msgid "%s: position %d: Bad variable type code %d." msgstr "" -#: src/sfm-read.c:819 +#: src/sfm-read.c:829 #, c-format msgid "%s: position %d: Variable label indicator field is not 0 or 1." msgstr "" -#: src/sfm-read.c:823 +#: src/sfm-read.c:833 #, c-format msgid "" "%s: position %d: Missing value indicator field is not -3, -2, 0, 1, 2, or 3." msgstr "" -#: src/sfm-read.c:829 +#: src/sfm-read.c:839 #, c-format msgid "%s: position %d: Variable name begins with invalid character." msgstr "" -#: src/sfm-read.c:833 +#: src/sfm-read.c:843 #, c-format msgid "%s: position %d: Variable name begins with lowercase letter %c." msgstr "" -#: src/sfm-read.c:837 +#: src/sfm-read.c:847 #, c-format msgid "" "%s: position %d: Variable name begins with octothorpe (`#'). Scratch " "variables should not appear in system files." msgstr "" -#: src/sfm-read.c:852 +#: src/sfm-read.c:862 #, c-format msgid "%s: position %d: Variable name character %d is lowercase letter %c." msgstr "" -#: src/sfm-read.c:861 +#: src/sfm-read.c:871 #, c-format msgid "" "%s: position %d: character `\\%03o' (%c) is not valid in a variable name." msgstr "" -#: src/sfm-read.c:870 +#: src/sfm-read.c:878 +#, c-format +msgid "%s: Invalid variable name `%s' within system file." +msgstr "" + +#: src/sfm-read.c:885 #, c-format msgid "%s: Duplicate variable name `%s' within system file." msgstr "" -#: src/sfm-read.c:892 +#: src/sfm-read.c:908 #, c-format msgid "%s: Variable %s indicates variable label of invalid length %d." msgstr "" -#: src/sfm-read.c:912 +#: src/sfm-read.c:928 #, c-format msgid "%s: Long string variable %s may not have missing values." msgstr "" -#: src/sfm-read.c:937 +#: src/sfm-read.c:953 #, c-format msgid "" "%s: String variable %s may not have missing values specified as a range." msgstr "" -#: src/sfm-read.c:979 +#: src/sfm-read.c:995 #, c-format msgid "%s: Long string continuation records omitted at end of dictionary." msgstr "" -#: src/sfm-read.c:984 +#: src/sfm-read.c:1000 #, c-format msgid "" "%s: System file header indicates %d variable positions but %d were read from " "file." msgstr "" -#: src/sfm-read.c:1009 +#: src/sfm-read.c:1025 #, c-format msgid "%s: %s variable %s has %s format specifier %s." msgstr "" -#: src/sfm-read.c:1097 +#: src/sfm-read.c:1078 +#, c-format +msgid "%s: Invalid number of labels: %d. Ignoring labels." +msgstr "" + +#: src/sfm-read.c:1120 #, 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:1108 +#: src/sfm-read.c:1131 #, 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:1124 +#: src/sfm-read.c:1147 #, 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:1131 +#: src/sfm-read.c:1154 #, 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:1136 +#: src/sfm-read.c:1159 #, c-format msgid "%s: Value labels are not allowed on long string variables (%s)." msgstr "" -#: src/sfm-read.c:1147 +#: src/sfm-read.c:1170 #, 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:1188 +#: src/sfm-read.c:1211 #, c-format msgid "%s: File contains duplicate label for value %g for variable %s." msgstr "" -#: src/sfm-read.c:1192 +#: src/sfm-read.c:1215 #, c-format msgid "%s: File contains duplicate label for value `%.*s' for variable %s." msgstr "" -#: src/sfm-read.c:1234 src/sfm-read.c:1511 +#: src/sfm-read.c:1257 src/sfm-read.c:1534 #, c-format msgid "%s: Reading system file: %s." msgstr "" -#: src/sfm-read.c:1237 src/sfm-read.c:1352 src/sfm-read.c:1394 +#: src/sfm-read.c:1260 src/sfm-read.c:1375 src/sfm-read.c:1417 #, c-format msgid "%s: Unexpected end of file." msgstr "" -#: src/sfm-read.c:1252 +#: src/sfm-read.c:1275 #, c-format msgid "%s: Seeking system file: %s." msgstr "" -#: src/sfm-read.c:1267 +#: src/sfm-read.c:1290 #, c-format msgid "%s: System file contains multiple type 6 (document) records." msgstr "" -#: src/sfm-read.c:1273 +#: src/sfm-read.c:1296 #, c-format msgid "%s: Number of document lines (%ld) must be greater than 0." msgstr "" -#: src/sfm-read.c:1305 +#: src/sfm-read.c:1328 #, c-format msgid "%s: Error reading file: %s." msgstr "" -#: src/sfm-read.c:1342 +#: src/sfm-read.c:1365 #, c-format msgid "%s: Compressed data is corrupted. Data ends in partial case." msgstr "" -#: src/sfm-read.c:1514 +#: src/sfm-read.c:1537 #, c-format msgid "%s: Partial record at end of system file." msgstr "" @@ -3373,19 +3388,11 @@ msgstr "" msgid "%s: Writing system file: %s." msgstr "" -#: src/sort.c:103 +#: src/sort.c:82 msgid "Buffer limit must be at least 2." msgstr "" -#: src/sort.c:221 -msgid "`A' or `D' expected inside parentheses." -msgstr "" - -#: src/sort.c:226 -msgid "`)' expected." -msgstr "" - -#: src/sort.c:573 +#: src/sort.c:458 #, c-format msgid "" "Out of memory. Could not allocate room for minimum of %d cases of %d bytes " diff --git a/po/pspp.pot b/po/pspp.pot index 61387a3a..db12dad6 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: 2005-05-23 12:08+0800\n" +"POT-Creation-Date: 2005-05-27 12:24+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,62 +17,62 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: src/aggregate.c:195 +#: src/aggregate.c:196 msgid "while expecting COLUMNWISE" msgstr "" -#: src/aggregate.c:224 +#: src/aggregate.c:225 msgid "expecting BREAK" msgstr "" -#: src/aggregate.c:229 +#: src/aggregate.c:230 msgid "" "When PRESORTED is specified, specifying sorting directions with (A) or (D) " "has no effect. Output data will be sorted the same way as the input data." msgstr "" -#: src/aggregate.c:385 +#: src/aggregate.c:386 msgid "expecting aggregation function" msgstr "" -#: src/aggregate.c:401 +#: src/aggregate.c:402 #, c-format msgid "Unknown aggregation function %s." msgstr "" -#: src/aggregate.c:416 +#: src/aggregate.c:417 msgid "expecting `('" msgstr "" -#: src/aggregate.c:453 +#: src/aggregate.c:454 #, c-format msgid "Missing argument %d to %s." msgstr "" -#: src/aggregate.c:462 +#: src/aggregate.c:463 #, c-format msgid "Arguments to %s must be of same type as source variables." msgstr "" -#: src/aggregate.c:472 +#: src/aggregate.c:473 msgid "expecting `)'" msgstr "" -#: src/aggregate.c:484 +#: src/aggregate.c:485 #, c-format msgid "" "Number of source variables (%d) does not match number of target variables (%" "d)." msgstr "" -#: src/aggregate.c:500 +#: src/aggregate.c:501 #, c-format msgid "" "The value arguments passed to the %s function are out-of-order. They will " "be treated as if they had been specified in the correct order." msgstr "" -#: src/aggregate.c:567 +#: src/aggregate.c:568 #, c-format msgid "" "Variable name %s is not unique within the aggregate file dictionary, which " @@ -85,12 +85,12 @@ msgid "Variable %s is %s in target file, but %s in source file." msgstr "" #: src/apply-dict.c:71 src/apply-dict.c:72 src/format.c:236 -#: src/sfm-read.c:1013 src/sfm-read.c:1151 src/sfm-read.c:1152 +#: src/sfm-read.c:1029 src/sfm-read.c:1174 src/sfm-read.c:1175 msgid "string" msgstr "" #: src/apply-dict.c:71 src/apply-dict.c:72 src/format.c:236 -#: src/sfm-read.c:1013 src/sfm-read.c:1151 src/sfm-read.c:1152 +#: src/sfm-read.c:1029 src/sfm-read.c:1174 src/sfm-read.c:1175 msgid "numeric" msgstr "" @@ -1496,11 +1496,11 @@ msgstr "" msgid "%s variables are not compatible with %s format %s." msgstr "" -#: src/format.c:235 src/pfm-read.c:473 src/sfm-read.c:1011 src/sfm-read.c:1020 +#: src/format.c:235 src/pfm-read.c:473 src/sfm-read.c:1027 src/sfm-read.c:1036 msgid "String" msgstr "" -#: src/format.c:235 src/pfm-read.c:473 src/sfm-read.c:1011 src/sfm-read.c:1020 +#: src/format.c:235 src/pfm-read.c:473 src/sfm-read.c:1027 src/sfm-read.c:1036 msgid "Numeric" msgstr "" @@ -1621,14 +1621,14 @@ msgstr "" msgid "IN variable name %s duplicates an existing variable name." msgstr "" -#: src/get.c:1415 +#: src/get.c:1417 #, 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:1506 +#: src/get.c:1508 msgid "expecting COMM or TAPE" msgstr "" @@ -2604,12 +2604,12 @@ msgstr "" msgid "Bad time string length %d." msgstr "" -#: src/pfm-read.c:465 src/sfm-read.c:1003 +#: src/pfm-read.c:465 src/sfm-read.c:1019 #, c-format msgid "%s: Bad format specifier byte (%d)." msgstr "" -#: src/pfm-read.c:472 src/sfm-read.c:1019 +#: src/pfm-read.c:472 src/sfm-read.c:1035 #, c-format msgid "%s variable %s has invalid format specifier %s." msgstr "" @@ -3085,70 +3085,75 @@ msgstr "" msgid "%s: Long variable mapping for nonexistent variable %s." msgstr "" -#: src/sfm-read.c:446 +#: src/sfm-read.c:428 +#, c-format +msgid "%s: Duplicate long variable name `%s' within system file." +msgstr "" + +#: src/sfm-read.c:456 #, c-format msgid "%s: Unrecognized record type 7, subtype %d encountered in system file." msgstr "" -#: src/sfm-read.c:471 +#: src/sfm-read.c:481 #, c-format msgid "%s: Unrecognized record type %d." msgstr "" -#: src/sfm-read.c:503 +#: src/sfm-read.c:513 #, 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:514 +#: src/sfm-read.c:524 #, 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:530 +#: src/sfm-read.c:540 #, c-format msgid "" "%s: File-indicated endianness (%s) does not match endianness intuited from " "file header (%s)." msgstr "" -#: src/sfm-read.c:533 src/sfm-read.c:534 +#: src/sfm-read.c:543 src/sfm-read.c:544 msgid "big-endian" msgstr "" -#: src/sfm-read.c:533 src/sfm-read.c:534 +#: src/sfm-read.c:543 src/sfm-read.c:544 msgid "little-endian" msgstr "" -#: src/sfm-read.c:535 +#: src/sfm-read.c:545 msgid "unknown" msgstr "" -#: src/sfm-read.c:539 +#: src/sfm-read.c:549 #, c-format msgid "%s: File-indicated character representation code (%s) is not ASCII." msgstr "" -#: src/sfm-read.c:543 +#: src/sfm-read.c:553 msgid "DEC Kanji" msgstr "" -#: src/sfm-read.c:543 src/sysfile-info.c:115 +#: src/sfm-read.c:553 src/sysfile-info.c:115 msgid "Unknown" msgstr "" -#: src/sfm-read.c:559 +#: src/sfm-read.c:569 #, 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:574 +#: src/sfm-read.c:584 #, c-format msgid "" "%s: File-indicated value is different from internal value for at least one " @@ -3156,210 +3161,220 @@ msgid "" "%g; LOWEST: %g, %g." msgstr "" -#: src/sfm-read.c:601 +#: src/sfm-read.c:611 #, 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:643 +#: src/sfm-read.c:653 #, 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:671 +#: src/sfm-read.c:681 #, c-format msgid "%s: Number of cases in file (%ld) is not between -1 and %d." msgstr "" -#: src/sfm-read.c:676 +#: src/sfm-read.c:686 #, c-format msgid "%s: Compression bias (%g) is not the usual value of 100." msgstr "" -#: src/sfm-read.c:799 +#: src/sfm-read.c:809 #, c-format msgid "" "%s: position %d: String variable does not have proper number of continuation " "records." msgstr "" -#: src/sfm-read.c:810 +#: src/sfm-read.c:820 #, c-format msgid "%s: position %d: Superfluous long string continuation record." msgstr "" -#: src/sfm-read.c:816 +#: src/sfm-read.c:826 #, c-format msgid "%s: position %d: Bad variable type code %d." msgstr "" -#: src/sfm-read.c:819 +#: src/sfm-read.c:829 #, c-format msgid "%s: position %d: Variable label indicator field is not 0 or 1." msgstr "" -#: src/sfm-read.c:823 +#: src/sfm-read.c:833 #, c-format msgid "" "%s: position %d: Missing value indicator field is not -3, -2, 0, 1, 2, or 3." msgstr "" -#: src/sfm-read.c:829 +#: src/sfm-read.c:839 #, c-format msgid "%s: position %d: Variable name begins with invalid character." msgstr "" -#: src/sfm-read.c:833 +#: src/sfm-read.c:843 #, c-format msgid "%s: position %d: Variable name begins with lowercase letter %c." msgstr "" -#: src/sfm-read.c:837 +#: src/sfm-read.c:847 #, c-format msgid "" "%s: position %d: Variable name begins with octothorpe (`#'). Scratch " "variables should not appear in system files." msgstr "" -#: src/sfm-read.c:852 +#: src/sfm-read.c:862 #, c-format msgid "%s: position %d: Variable name character %d is lowercase letter %c." msgstr "" -#: src/sfm-read.c:861 +#: src/sfm-read.c:871 #, c-format msgid "" "%s: position %d: character `\\%03o' (%c) is not valid in a variable name." msgstr "" -#: src/sfm-read.c:870 +#: src/sfm-read.c:878 +#, c-format +msgid "%s: Invalid variable name `%s' within system file." +msgstr "" + +#: src/sfm-read.c:885 #, c-format msgid "%s: Duplicate variable name `%s' within system file." msgstr "" -#: src/sfm-read.c:892 +#: src/sfm-read.c:908 #, c-format msgid "%s: Variable %s indicates variable label of invalid length %d." msgstr "" -#: src/sfm-read.c:912 +#: src/sfm-read.c:928 #, c-format msgid "%s: Long string variable %s may not have missing values." msgstr "" -#: src/sfm-read.c:937 +#: src/sfm-read.c:953 #, c-format msgid "" "%s: String variable %s may not have missing values specified as a range." msgstr "" -#: src/sfm-read.c:979 +#: src/sfm-read.c:995 #, c-format msgid "%s: Long string continuation records omitted at end of dictionary." msgstr "" -#: src/sfm-read.c:984 +#: src/sfm-read.c:1000 #, c-format msgid "" "%s: System file header indicates %d variable positions but %d were read from " "file." msgstr "" -#: src/sfm-read.c:1009 +#: src/sfm-read.c:1025 #, c-format msgid "%s: %s variable %s has %s format specifier %s." msgstr "" -#: src/sfm-read.c:1097 +#: src/sfm-read.c:1078 +#, c-format +msgid "%s: Invalid number of labels: %d. Ignoring labels." +msgstr "" + +#: src/sfm-read.c:1120 #, 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:1108 +#: src/sfm-read.c:1131 #, 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:1124 +#: src/sfm-read.c:1147 #, 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:1131 +#: src/sfm-read.c:1154 #, 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:1136 +#: src/sfm-read.c:1159 #, c-format msgid "%s: Value labels are not allowed on long string variables (%s)." msgstr "" -#: src/sfm-read.c:1147 +#: src/sfm-read.c:1170 #, 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:1188 +#: src/sfm-read.c:1211 #, c-format msgid "%s: File contains duplicate label for value %g for variable %s." msgstr "" -#: src/sfm-read.c:1192 +#: src/sfm-read.c:1215 #, c-format msgid "%s: File contains duplicate label for value `%.*s' for variable %s." msgstr "" -#: src/sfm-read.c:1234 src/sfm-read.c:1511 +#: src/sfm-read.c:1257 src/sfm-read.c:1534 #, c-format msgid "%s: Reading system file: %s." msgstr "" -#: src/sfm-read.c:1237 src/sfm-read.c:1352 src/sfm-read.c:1394 +#: src/sfm-read.c:1260 src/sfm-read.c:1375 src/sfm-read.c:1417 #, c-format msgid "%s: Unexpected end of file." msgstr "" -#: src/sfm-read.c:1252 +#: src/sfm-read.c:1275 #, c-format msgid "%s: Seeking system file: %s." msgstr "" -#: src/sfm-read.c:1267 +#: src/sfm-read.c:1290 #, c-format msgid "%s: System file contains multiple type 6 (document) records." msgstr "" -#: src/sfm-read.c:1273 +#: src/sfm-read.c:1296 #, c-format msgid "%s: Number of document lines (%ld) must be greater than 0." msgstr "" -#: src/sfm-read.c:1305 +#: src/sfm-read.c:1328 #, c-format msgid "%s: Error reading file: %s." msgstr "" -#: src/sfm-read.c:1342 +#: src/sfm-read.c:1365 #, c-format msgid "%s: Compressed data is corrupted. Data ends in partial case." msgstr "" -#: src/sfm-read.c:1514 +#: src/sfm-read.c:1537 #, c-format msgid "%s: Partial record at end of system file." msgstr "" @@ -3374,19 +3389,11 @@ msgstr "" msgid "%s: Writing system file: %s." msgstr "" -#: src/sort.c:103 +#: src/sort.c:82 msgid "Buffer limit must be at least 2." msgstr "" -#: src/sort.c:221 -msgid "`A' or `D' expected inside parentheses." -msgstr "" - -#: src/sort.c:226 -msgid "`)' expected." -msgstr "" - -#: src/sort.c:573 +#: src/sort.c:458 #, c-format msgid "" "Out of memory. Could not allocate room for minimum of %d cases of %d bytes " diff --git a/src/ChangeLog b/src/ChangeLog index 18c7c1fe..49e2b47a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +Fri May 27 12:34:43 WST 2005 John Darrington + + * sort-prs.[ch] (newfiles), aggregate.c, sort.[ch]: Separated the guts + of the sort algorithm from the parser for the SORT command. + + * rank.q: Added the parser for the RANK command. + Thu May 26 12:29:21 2005 Ben Pfaff Fix PR 13192. diff --git a/src/Makefile.am b/src/Makefile.am index 8a81c4f7..6623c254 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,13 +22,13 @@ $(q_sources_c): q2c$(EXEEXT) ./q2c $< $@ q_sources_c = correlations.c crosstabs.c examine.c file-handle.c \ -frequencies.c list.c means.c oneway.c set.c t-test.c +frequencies.c list.c means.c oneway.c rank.c set.c t-test.c CLEANFILES=$(q_sources_c) DISTCLEANFILES=version.c q_sources_q = correlations.q crosstabs.q examine.q file-handle.q \ -frequencies.q list.q means.q oneway.q set.q t-test.q +frequencies.q list.q means.q oneway.q rank.q set.q t-test.q if WITHCHARTS chart_sources = barchart.c \ @@ -66,7 +66,8 @@ pfm-write.c pfm-write.h \ pool.c pool.h postscript.c print.c recode.c \ rename-vars.c repeat.c repeat.h sample.c sel-if.c settings.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 \ +sort.c sort.h sort-prs.c sort-prs.h \ +split-file.c str.c str.h subclist.c subclist.h \ sysfile-info.c tab.c tab.h temporary.c stat.h mkfile.c mkfile.h \ title.c val.h val-labs.c value-labels.c value-labels.h \ var-display.c \ diff --git a/src/aggregate.c b/src/aggregate.c index 47c60f34..8fe168ec 100644 --- a/src/aggregate.c +++ b/src/aggregate.c @@ -33,6 +33,7 @@ #include "pool.h" #include "settings.h" #include "sfm-write.h" +#include "sort-prs.h" #include "sort.h" #include "str.h" #include "var.h" @@ -208,7 +209,7 @@ cmd_aggregate (void) lex_match ('='); agr.sort = sort_parse_criteria (default_dict, &agr.break_vars, &agr.break_var_cnt, - &saw_direction); + &saw_direction, NULL); if (agr.sort == NULL) goto error; diff --git a/src/rank.q b/src/rank.q new file mode 100644 index 00000000..ad6a7ee0 --- /dev/null +++ b/src/rank.q @@ -0,0 +1,354 @@ +/* PSPP - RANK. -*-c-*- + +Copyright (C) 2005 Free Software Foundation, Inc. +Author: John Darrington 2005 + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ + +#include +#include "command.h" +#include "dictionary.h" +#include "sort.h" +#include "sort-prs.h" +#include "var.h" + +/* (headers) */ + +/* (specification) + "RANK" (rank_): + *^variables=custom; + +rank=custom; + +normal=custom; + +percent=custom; + +ntiles=custom; + +rfraction=custom; + +proportion=custom; + +n=custom; + +savage=custom; + +print=print:!yes/no; + +missing=miss:!exclude/include. +*/ +/* (declarations) */ +/* (functions) */ + + + +enum RANK_FUNC + { + RANK, + NORMAL, + PERCENT, + RFRACTION, + PROPORTION, + N, + NTILES, + SAVAGE, + }; + + +struct rank_spec +{ + enum RANK_FUNC rfunc; + struct variable **destvars; + struct variable *srcvar; +}; + + +static struct rank_spec *rank_specs; +static int n_rank_specs; + +static struct sort_criteria *sc; + +static struct variable **group_vars; +static int n_group_vars; + +static struct cmd_rank cmd; + + + +int cmd_rank(void); + +int +cmd_rank(void) +{ + int i; + n_rank_specs = 0; + + if ( !parse_rank(&cmd) ) + return CMD_FAILURE; + +#if 1 + for (i = 0 ; i < sc->crit_cnt ; ++i ) + { + struct sort_criterion *crit = &sc->crits[i]; + + printf("Dir: %d; Index: %d\n", crit->dir, crit->fv); + } + + for (i = 0 ; i < n_group_vars ; ++i ) + printf("Group var: %s\n",group_vars[0]->name); + + for (i = 0 ; i < n_rank_specs ; ++i ) + { + int j; + printf("Ranks spec %d; Func: %d\n",i, rank_specs[i].rfunc); + + for (j=0; j < sc->crit_cnt ; ++j ) + printf("Dest var is \"%s\"\n", rank_specs[i].destvars[j]->name); + } +#endif + + + free(group_vars); + + for (i = 0 ; i < n_rank_specs ; ++i ) + { + free(rank_specs[i].destvars); + } + + free(rank_specs); + + sort_destroy_criteria(sc); + + return CMD_SUCCESS; +} + + + +/* Parser for the variables sub command + Returns 1 on success */ +static int +rank_custom_variables(struct cmd_rank *cmd UNUSED) +{ + static const int terminators[2] = {T_BY, 0}; + + lex_match('='); + + if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL) + && token != T_ALL) + return 2; + + sc = sort_parse_criteria (default_dict, 0, 0, 0, terminators); + + if ( lex_match(T_BY) ) + { + if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)) + { + return 2; + } + + if (!parse_variables (default_dict, &group_vars, &n_group_vars, + PV_NO_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH) ) + { + free (group_vars); + return 0; + } + } + + return 1; +} + + +/* Return a name for a new variable which ranks the variable VAR_NAME, + according to the ranking function F. + If IDX is non zero, then IDX is used as a disambiguating number. + FIXME: This is not very robust. +*/ +static char * +new_variable_name(const char *ranked_var_name, enum RANK_FUNC f, int idx) +{ + static char new_name[SHORT_NAME_LEN + 1]; + char temp[SHORT_NAME_LEN + 1]; + + if ( idx == 0 ) + { + switch (f) + { + case RANK: + case RFRACTION: + strcpy(new_name,"R"); + break; + + case NORMAL: + case N: + case NTILES: + strcpy(new_name,"N"); + break; + + case PERCENT: + case PROPORTION: + strcpy(new_name,"P"); + break; + + case SAVAGE: + strcpy(new_name,"S"); + break; + + default: + assert(false); + break; + } + + strncat(new_name, ranked_var_name, 7); + } + else + { + strncpy(temp, ranked_var_name, 3); + snprintf(new_name, SHORT_NAME_LEN, "%s%03d", temp, idx); + } + + return new_name; +} + +/* Parse the [/rank INTO var1 var2 ... varN ] clause */ +static int +parse_rank_function(struct cmd_rank *cmd UNUSED, enum RANK_FUNC f) +{ + static const struct fmt_spec f8_2 = {FMT_F, 8, 2}; + int var_count = 0; + + n_rank_specs++; + rank_specs = xrealloc(rank_specs, n_rank_specs * sizeof *rank_specs); + rank_specs[n_rank_specs - 1].rfunc = f; + + rank_specs[n_rank_specs - 1].destvars = + xcalloc(sc->crit_cnt ,sizeof (struct variable *)); + + if (lex_match_id("INTO")) + { + struct variable *destvar; + + while( token == T_ID ) + { + ++var_count; + if ( dict_lookup_var (default_dict, tokid) != NULL ) + { + msg(ME, _("Variable %s already exists."), tokid); + return 0; + } + if ( var_count > sc->crit_cnt ) + { + msg(ME, _("Too many variables in INTO clause."), tokid); + return 0; + } + + destvar = dict_create_var (default_dict, tokid, 0); + if ( destvar ) + { + destvar->print = destvar->write = f8_2; + } + + rank_specs[n_rank_specs - 1].destvars[var_count - 1] = destvar ; + + lex_get(); + + } + } + + /* Allocate rank variable names to all those which haven't had INTO + variables assigned */ + while (var_count < sc->crit_cnt) + { + static int idx=0; + struct variable *destvar ; + const struct variable *v = dict_get_var(default_dict, + sc->crits[var_count].fv); + + char *new_name; + + do { + new_name = new_variable_name(v->name, f, idx); + + destvar = dict_create_var (default_dict, new_name, 0); + if (!destvar ) + ++idx; + + } while( !destvar ) ; + + destvar->print = destvar->write = f8_2; + + rank_specs[n_rank_specs - 1].destvars[var_count] = destvar ; + + ++var_count; + } + + return 1; +} + + +static int +rank_custom_rank(struct cmd_rank *cmd ) +{ + return parse_rank_function(cmd, RANK); +} + +static int +rank_custom_normal(struct cmd_rank *cmd ) +{ + return parse_rank_function(cmd, NORMAL); +} + +static int +rank_custom_percent(struct cmd_rank *cmd ) +{ + return parse_rank_function(cmd, NORMAL); +} + +static int +rank_custom_rfraction(struct cmd_rank *cmd ) +{ + return parse_rank_function(cmd, RFRACTION); +} + +static int +rank_custom_proportion(struct cmd_rank *cmd ) +{ + return parse_rank_function(cmd, PROPORTION); +} + +static int +rank_custom_n(struct cmd_rank *cmd ) +{ + return parse_rank_function(cmd, N); +} + +static int +rank_custom_savage(struct cmd_rank *cmd ) +{ + return parse_rank_function(cmd, SAVAGE); +} + + +static int +rank_custom_ntiles(struct cmd_rank *cmd ) +{ + if ( lex_force_match('(') ) + { + if ( lex_force_int() ) + { + lex_get(); + lex_force_match(')'); + } + else + return 0; + } + else + return 0; + + return parse_rank_function(cmd, NTILES); +} + + diff --git a/src/sort-prs.c b/src/sort-prs.c new file mode 100644 index 00000000..2682588e --- /dev/null +++ b/src/sort-prs.c @@ -0,0 +1,159 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include +#include +#include +#include + +#include "alloc.h" +#include "error.h" +#include "lexer.h" +#include "sort-prs.h" +#include "sort.h" +#include "var.h" + + + +static bool is_terminator(int tok, const int *terminators); + + +/* Parses a list of sort keys and returns a struct sort_criteria + based on it. Returns a null pointer on error. + If SAW_DIRECTION is nonnull, sets *SAW_DIRECTION to true if at + least one parenthesized sort direction was specified, false + otherwise. + If TERMINATORS is non-null, then it must be a pointer to a + null terminated list of tokens, in addition to the defaults, + which are to be considered terminators of the clause being parsed. + The default terminators are '/' and '.' + +*/ +struct sort_criteria * +sort_parse_criteria (const struct dictionary *dict, + struct variable ***vars, int *var_cnt, + bool *saw_direction, + const int *terminators + ) +{ + struct sort_criteria *criteria; + struct variable **local_vars = NULL; + size_t local_var_cnt; + + assert ((vars == NULL) == (var_cnt == NULL)); + if (vars == NULL) + { + vars = &local_vars; + var_cnt = &local_var_cnt; + } + + criteria = xmalloc (sizeof *criteria); + criteria->crits = NULL; + criteria->crit_cnt = 0; + + *vars = NULL; + *var_cnt = 0; + if (saw_direction != NULL) + *saw_direction = false; + + do + { + int prev_var_cnt = *var_cnt; + enum sort_direction direction; + + /* Variables. */ + if (!parse_variables (dict, vars, var_cnt, + PV_NO_DUPLICATE | PV_APPEND | PV_NO_SCRATCH)) + goto error; + + /* Sort direction. */ + if (lex_match ('(')) + { + if (lex_match_id ("D") || lex_match_id ("DOWN")) + direction = SRT_DESCEND; + else if (lex_match_id ("A") || lex_match_id ("UP")) + direction = SRT_ASCEND; + else + { + msg (SE, _("`A' or `D' expected inside parentheses.")); + goto error; + } + if (!lex_match (')')) + { + msg (SE, _("`)' expected.")); + goto error; + } + if (saw_direction != NULL) + *saw_direction = true; + } + else + direction = SRT_ASCEND; + + criteria->crits = xrealloc (criteria->crits, + sizeof *criteria->crits * *var_cnt); + criteria->crit_cnt = *var_cnt; + for (; prev_var_cnt < criteria->crit_cnt; prev_var_cnt++) + { + struct sort_criterion *c = &criteria->crits[prev_var_cnt]; + c->fv = (*vars)[prev_var_cnt]->fv; + c->width = (*vars)[prev_var_cnt]->width; + c->dir = direction; + } + } + while (token != '.' && token != '/' && !is_terminator(token, terminators)); + + free (local_vars); + return criteria; + + error: + free (local_vars); + sort_destroy_criteria (criteria); + return NULL; +} + +/* Return TRUE if TOK is a member of the list of TERMINATORS. + FALSE otherwise */ +static bool +is_terminator(int tok, const int *terminators) +{ + if (terminators == NULL ) + return false; + + while ( *terminators) + { + if (tok == *terminators++) + return true; + } + + return false; +} + + + +/* Destroys a SORT CASES program. */ +void +sort_destroy_criteria (struct sort_criteria *criteria) +{ + if (criteria != NULL) + { + free (criteria->crits); + free (criteria); + } +} + diff --git a/src/sort-prs.h b/src/sort-prs.h new file mode 100644 index 00000000..e7ee4850 --- /dev/null +++ b/src/sort-prs.h @@ -0,0 +1,38 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef SORT_PRS_H +#define SORT_PRS_H + +#include +#include "bool.h" + +struct variable; +struct dictionary; + +struct sort_criteria *sort_parse_criteria (const struct dictionary *, + struct variable ***, int *, + bool *saw_direction, + const int *terminators + ); + +void sort_destroy_criteria (struct sort_criteria *criteria) ; + + +#endif /* SORT_PRS_H */ diff --git a/src/sort.c b/src/sort.c index a16055f9..bb4220b7 100644 --- a/src/sort.c +++ b/src/sort.c @@ -36,6 +36,7 @@ #include "lexer.h" #include "misc.h" #include "settings.h" +#include "sort-prs.h" #include "str.h" #include "var.h" #include "vfm.h" @@ -43,28 +44,6 @@ #include "debug-print.h" -/* Sort direction. */ -enum sort_direction - { - SRT_ASCEND, /* A, B, C, ..., X, Y, Z. */ - SRT_DESCEND /* Z, Y, X, ..., C, B, A. */ - }; - -/* A sort criterion. */ -struct sort_criterion - { - int fv; /* Variable data index. */ - int width; /* 0=numeric, otherwise string widthe. */ - enum sort_direction dir; /* Sort direction. */ - }; - -/* A set of sort criteria. */ -struct sort_criteria - { - struct sort_criterion *crits; - size_t crit_cnt; - }; - /* These should only be changed for testing purposes. */ static int min_buffers = 64; static int max_buffers = INT_MAX; @@ -86,7 +65,7 @@ cmd_sort_cases (void) lex_match (T_BY); - criteria = sort_parse_criteria (default_dict, NULL, NULL, NULL); + criteria = sort_parse_criteria (default_dict, NULL, NULL, NULL, NULL); if (criteria == NULL) return CMD_FAILURE; @@ -169,101 +148,6 @@ sort_active_file_to_casefile (const struct sort_criteria *criteria) return sort_execute (casefile_get_reader (src), criteria); } -/* Parses a list of sort keys and returns a struct sort_criteria - based on it. Returns a null pointer on error. - If SAW_DIRECTION is nonnull, sets *SAW_DIRECTION to true if at - least one parenthesized sort direction was specified, false - otherwise. */ -struct sort_criteria * -sort_parse_criteria (const struct dictionary *dict, - struct variable ***vars, int *var_cnt, - bool *saw_direction) -{ - struct sort_criteria *criteria; - struct variable **local_vars = NULL; - size_t local_var_cnt; - - assert ((vars == NULL) == (var_cnt == NULL)); - if (vars == NULL) - { - vars = &local_vars; - var_cnt = &local_var_cnt; - } - - criteria = xmalloc (sizeof *criteria); - criteria->crits = NULL; - criteria->crit_cnt = 0; - - *vars = NULL; - *var_cnt = 0; - if (saw_direction != NULL) - *saw_direction = false; - - do - { - int prev_var_cnt = *var_cnt; - enum sort_direction direction; - - /* Variables. */ - if (!parse_variables (dict, vars, var_cnt, - PV_NO_DUPLICATE | PV_APPEND | PV_NO_SCRATCH)) - goto error; - - /* Sort direction. */ - if (lex_match ('(')) - { - if (lex_match_id ("D") || lex_match_id ("DOWN")) - direction = SRT_DESCEND; - else if (lex_match_id ("A") || lex_match_id ("UP")) - direction = SRT_ASCEND; - else - { - msg (SE, _("`A' or `D' expected inside parentheses.")); - goto error; - } - if (!lex_match (')')) - { - msg (SE, _("`)' expected.")); - goto error; - } - if (saw_direction != NULL) - *saw_direction = true; - } - else - direction = SRT_ASCEND; - - criteria->crits = xrealloc (criteria->crits, - sizeof *criteria->crits * *var_cnt); - criteria->crit_cnt = *var_cnt; - for (; prev_var_cnt < criteria->crit_cnt; prev_var_cnt++) - { - struct sort_criterion *c = &criteria->crits[prev_var_cnt]; - c->fv = (*vars)[prev_var_cnt]->fv; - c->width = (*vars)[prev_var_cnt]->width; - c->dir = direction; - } - } - while (token != '.' && token != '/'); - - free (local_vars); - return criteria; - - error: - free (local_vars); - sort_destroy_criteria (criteria); - return NULL; -} - -/* Destroys a SORT CASES program. */ -void -sort_destroy_criteria (struct sort_criteria *criteria) -{ - if (criteria != NULL) - { - free (criteria->crits); - free (criteria); - } -} /* Reads all the cases from READER, which is destroyed. Sorts the cases according to CRITERIA. Returns the sorted cases in diff --git a/src/sort.h b/src/sort.h index 347574c4..37d9db57 100644 --- a/src/sort.h +++ b/src/sort.h @@ -27,14 +27,37 @@ struct casereader; struct dictionary; struct variable; -struct sort_criteria *sort_parse_criteria (const struct dictionary *, - struct variable ***, int *, - bool *saw_direction); + +/* Sort direction. */ +enum sort_direction + { + SRT_ASCEND, /* A, B, C, ..., X, Y, Z. */ + SRT_DESCEND /* Z, Y, X, ..., C, B, A. */ + }; + +/* A sort criterion. */ +struct sort_criterion + { + int fv; /* Variable data index. */ + int width; /* 0=numeric, otherwise string width. */ + enum sort_direction dir; /* Sort direction. */ + }; + +/* A set of sort criteria. */ +struct sort_criteria + { + struct sort_criterion *crits; + size_t crit_cnt; + }; + + void sort_destroy_criteria (struct sort_criteria *); struct casefile *sort_execute (struct casereader *, const struct sort_criteria *); + int sort_active_file_in_place (const struct sort_criteria *); + struct casefile *sort_active_file_to_casefile (const struct sort_criteria *); #endif /* !sort_h */ -- 2.30.2