Added the parser for the rank command.
authorJohn Darrington <john@darrington.wattle.id.au>
Fri, 27 May 2005 04:39:51 +0000 (04:39 +0000)
committerJohn Darrington <john@darrington.wattle.id.au>
Fri, 27 May 2005 04:39:51 +0000 (04:39 +0000)
Separated the sort algorithm from the SORT command parser.

po/en_GB.po
po/pspp.pot
src/ChangeLog
src/Makefile.am
src/aggregate.c
src/rank.q [new file with mode: 0644]
src/sort-prs.c [new file with mode: 0644]
src/sort-prs.h [new file with mode: 0644]
src/sort.c
src/sort.h

index b37eff2e51ddd0e59b16dfcb48834a610e70013a..65f38593f79899bde85f9f1605b399fe7604a1a7 100644 (file)
@@ -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 <john@darrington.wattle.id.au>\n"
 "Language-Team: John Darrington <john@darrington.wattle.id.au>\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 "
index 61387a3aa5d5e7756a7ce2ad6e48d1678032b355..db12dad62ffd93594854c18e76da164a6a299f3b 100644 (file)
@@ -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 <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\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 "
index 18c7c1fe4061eda294b17da2897a0a130b4a9a01..49e2b47a15da33e84bd60555d60698ac9a3ee027 100644 (file)
@@ -1,3 +1,10 @@
+Fri May 27 12:34:43 WST 2005 John Darrington <john@darrington.wattle.id.au>
+       
+       * 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  <blp@gnu.org>
 
        Fix PR 13192.
index 8a81c4f7042069ccd76fdd8796ad71dae1969eaa..6623c2540060401cd9ba17e3cf98fc2d99d4c2c4 100644 (file)
@@ -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 \
index 47c60f344c53fbbd660d28903695c2f2170dfad2..8fe168ecf78175581c92de4d50f4c3ba6bb0b144 100644 (file)
@@ -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 (file)
index 0000000..ad6a7ee
--- /dev/null
@@ -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 <config.h>
+#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 (file)
index 0000000..2682588
--- /dev/null
@@ -0,0 +1,159 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Written by Ben Pfaff <blp@gnu.org>.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
+
+#include <config.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#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 (file)
index 0000000..e7ee485
--- /dev/null
@@ -0,0 +1,38 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Written by Ben Pfaff <blp@gnu.org>.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
+
+#ifndef SORT_PRS_H
+#define SORT_PRS_H
+
+#include <config.h>
+#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 */
index a16055f971725953ade58241b1f8f8ea67e30bb9..bb4220b75943a231d6bdd5395d6615bf3acef70a 100644 (file)
@@ -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"
 
 #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
index 347574c4d20ba5bd90f68625eb0159cd537e0d8a..37d9db577f30e02b2b6ade3857f4d0981d9e8de1 100644 (file)
@@ -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 */