sys-file-reader: Avoid assert-fail for duplicate attribute names.
[pspp] / tests / data / sys-file-reader.at
index 2564e7d11ab41a7d1c3b37c89dea5247a27bba49..d071f37c09f97529d20934181e9635ee2f271010 100644 (file)
@@ -1,3 +1,19 @@
+dnl PSPP - a program for statistical analysis.
+dnl Copyright (C) 2017 Free Software Foundation, Inc.
+dnl 
+dnl This program is free software: you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation, either version 3 of the License, or
+dnl (at your option) any later version.
+dnl 
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU General Public License for more details.
+dnl 
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program.  If not, see <http://www.gnu.org/licenses/>.
+dnl
 AT_BANNER([system file reader - positive])
 
 AT_SETUP([variable labels and missing values])
@@ -6,12 +22,13 @@ AT_DATA([sys-file.sack], [dnl
 dnl File header.
 "$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
 2; dnl Layout code
-22; dnl Nominal case size
+28; dnl Nominal case size
 0; dnl Not compressed
-0; dnl Not weighted 
+0; dnl Not weighted
 1; dnl 1 case.
 100.0; dnl Bias.
-"01 Jan 11"; "20:53:52"; s64 "PSPP synthetic test file";
+"01 Jan 11"; "20:53:52";
+"PSPP synthetic test file: "; i8 244; i8 245; i8 246; i8 248; s34 "";
 i8 0 *3;
 
 dnl Numeric variable, no label or missing values.
@@ -19,7 +36,7 @@ dnl Numeric variable, no label or missing values.
 
 dnl Numeric variable, variable label.
 2; 0; 1; 0; 0x050800 *2; s8 "NUM2";
-26; "Numeric variable 2's label"; i8 0 *2;
+32; "Numeric variable 2's label ("; i8 249; i8 250; i8 251; ")";
 
 dnl Numeric variable, one missing value.
 2; 0; 0; 1; 0x050800 *2; s8 "NUM3";
@@ -42,7 +59,8 @@ dnl Numeric variable, range of missing values.
 dnl Numeric variables, range of missing values plus discrete value.
 2; 0; 0; -3; 0x050800 *2; s8 "NUM8"; 1.0; 3.0; 5.0;
 2; 0; 0; -3; 0x050800 *2; s8 "NUM9"; 1.0; HIGHEST; -5.0;
-2; 0; 0; -3; 0x050800 *2; s8 "NUM10"; LOWEST; 1.0; 5.0;
+2; 0; 0; -3; 0x050800 *2; "NUM"; i8 192; i8 200; i8 204; i8 209; i8 210;
+LOWEST; 1.0; 5.0;
 
 dnl String variable, no label or missing values.
 2; 4; 0; 0; 0x010400 *2; s8 "STR1";
@@ -66,11 +84,24 @@ dnl String variable, three missing values.
 2; 4; 0; 3; 0x010400 *2; s8 "STR6"; s8 "MISS"; s8 "OTHR"; s8 "MORE";
 
 dnl Long string variable, one missing value.
+dnl (This is not how SPSS represents missing values for long strings--it
+dnl uses a separate record as shown later below--but old versions of PSPP
+dnl did use this representation so we continue supporting it for backward
+dnl compatibility.
 2; 11; 0; 1; 0x010b00 *2; s8 "STR7"; "first8by";
 2; -1; 0; 0; 0; 0; s8 "";
 
+dnl Long string variables that will have missing values added with a
+dnl later record.
+2; 9; 0; 0; 0x010900 *2; s8 "STR8";
+2; -1; 0; 0; 0; 0; s8 "";
+2; 10; 0; 0; 0x010a00 *2; s8 "STR9";
+2; -1; 0; 0; 0; 0; s8 "";
+2; 11; 0; 0; 0x010b00 *2; s8 "STR10";
+2; -1; 0; 0; 0; 0; s8 "";
+
 dnl Long string variable, value label.
-2; 25; 1; 0; 0x011900 *2; s8 "STR8"; 14; "25-byte string"; i8 0 * 2;
+2; 25; 1; 0; 0x011900 *2; s8 "STR11"; 14; "25-byte string"; i8 0 * 2;
 ( 2; -1; 0; 0; 0; 0; s8 ""; ) * 2;
 dnl Variable label fields on continuation records have been spotted in system
 dnl files created by "SPSS Power Macintosh Release 6.1".
@@ -82,6 +113,18 @@ dnl Machine integer info record.
 dnl Machine floating-point info record.
 7; 4; 8; 3; SYSMIS; HIGHEST; LOWEST;
 
+dnl Long string variable missing values record.
+7; 22; 1; COUNT (
+dnl One missing value for STR8.
+COUNT("STR8"); i8 1; 8; "abcdefgh";
+
+dnl Two missing values for STR9.
+COUNT("STR9"); i8 2; 8; "abcdefgh"; 8; "01234567";
+
+dnl Three missing values for STR9.
+COUNT("STR10"); i8 3; 8; "abcdefgh"; 8; "01234567"; 8; "0       ";
+);
+
 dnl Character encoding record.
 7; 20; 1; 12; "windows-1252";
 
@@ -91,63 +134,68 @@ dnl Dictionary termination record.
 dnl Data.
 1.0; 2.0; 3.0; 4.0; 5.0; 6.0; 7.0; 8.0; 9.0; 10.0;
 s8 "abcd"; s8 "efgh"; s8 "ijkl"; s8 "mnop"; s8 "qrst"; s8 "uvwx";
-s16 "yzABCDEFGHI"; s32 "JKLMNOPQRSTUVWXYZ01234567";
-])
-for variant in \
-       "be e07ee28eaf7bceca017e83e9fd46be3c" \
-       "le c357aa20227c856b8a80d1b840722da1"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
+s16 "yzABCDEFGHI"; s16 "JKLMNOPQR"; s16 "STUVWXYZ01";
+s16 "23456789abc"; s32 "defghijklmnopqstuvwxyzABC";
 ])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
+DISPLAY FILE LABEL.
 DISPLAY DICTIONARY.
 LIST.
 ])
   AT_CHECK([pspp -o pspp.csv sys-file.sps])
-  AT_CHECK([grep -v Measure pspp.csv | grep -v Display], [0], [dnl
-Variable,Description,,Position
-num1,Format: F8.0,,1
-num2,Numeric variable 2's label,,2
-,Format: F8.0,,
-num3,Format: F8.0,,3
-,Missing Values: 1,,
-num4,Another numeric variable label,,4
-,Format: F8.0,,
-,Missing Values: 1,,
-num5,Format: F8.0,,5
-,Missing Values: 1; 2,,
-num6,Format: F8.0,,6
-,Missing Values: 1; 2; 3,,
-num7,Format: F8.0,,7
-,Missing Values: 1 THRU 3,,
-num8,Format: F8.0,,8
-,Missing Values: 1 THRU 3; 5,,
-num9,Format: F8.0,,9
-,Missing Values: 1 THRU HIGHEST; -5,,
-num10,Format: F8.0,,10
-,Missing Values: LOWEST THRU 1; 5,,
-str1,Format: A4,,11
-str2,String variable 2's label,,12
-,Format: A4,,
-str3,Format: A4,,13
-,"Missing Values: ""MISS""",,
-str4,Another string variable label,,14
-,Format: A4,,
-,"Missing Values: ""OTHR""",,
-str5,Format: A4,,15
-,"Missing Values: ""MISS""; ""OTHR""",,
-str6,Format: A4,,16
-,"Missing Values: ""MISS""; ""OTHR""; ""MORE""",,
-str7,Format: A11,,17
-,"Missing Values: ""first8by""",,
-str8,25-byte string,,18
-,Format: A25,,
+  AT_CHECK([cat pspp.csv], [0], [dnl
+File label: PSPP synthetic test file: ôõöø
+
+Variable,Description,Position
+num1,Format: F8.0,1
+num2,"Label: Numeric variable 2's label (ùúû)
+Format: F8.0",2
+num3,"Format: F8.0
+Missing Values: 1",3
+num4,"Label: Another numeric variable label
+Format: F8.0
+Missing Values: 1",4
+num5,"Format: F8.0
+Missing Values: 1; 2",5
+num6,"Format: F8.0
+Missing Values: 1; 2; 3",6
+num7,"Format: F8.0
+Missing Values: 1 THRU 3",7
+num8,"Format: F8.0
+Missing Values: 1 THRU 3; 5",8
+num9,"Format: F8.0
+Missing Values: 1 THRU HIGHEST; -5",9
+numàèìñò,"Format: F8.0
+Missing Values: LOWEST THRU 1; 5",10
+str1,Format: A4,11
+str2,"Label: String variable 2's label
+Format: A4",12
+str3,"Format: A4
+Missing Values: ""MISS""",13
+str4,"Label: Another string variable label
+Format: A4
+Missing Values: ""OTHR""",14
+str5,"Format: A4
+Missing Values: ""MISS""; ""OTHR""",15
+str6,"Format: A4
+Missing Values: ""MISS""; ""OTHR""; ""MORE""",16
+str7,"Format: A11
+Missing Values: ""first8by""",17
+str8,"Format: A9
+Missing Values: ""abcdefgh""",18
+str9,"Format: A10
+Missing Values: ""abcdefgh""; ""01234567""",19
+str10,"Format: A11
+Missing Values: ""abcdefgh""; ""01234567""; ""0       """,20
+str11,"Label: 25-byte string
+Format: A25",21
 
 Table: Data List
-num1,num2,num3,num4,num5,num6,num7,num8,num9,num10,str1,str2,str3,str4,str5,str6,str7,str8
-1,2,3,4,5,6,7,8,9,10,abcd,efgh,ijkl,mnop,qrst,uvwx,yzABCDEFGHI,JKLMNOPQRSTUVWXYZ01234567
+num1,num2,num3,num4,num5,num6,num7,num8,num9,numàèìñò,str1,str2,str3,str4,str5,str6,str7,str8,str9,str10,str11
+1,2,3,4,5,6,7,8,9,10,abcd,efgh,ijkl,mnop,qrst,uvwx,yzABCDEFGHI,JKLMNOPQR,STUVWXYZ01,23456789abc,defghijklmnopqstuvwxyzABC
 ])
 done
 AT_CLEANUP
@@ -173,30 +221,28 @@ dnl Numeric variable, variable label.
 2; 0; 1; 0; 0x050800 *2; s8 "NUM2";
 26; "Numeric variable 2's label"; i8 0 *2;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 
 dnl Data.
 1.0; 2.0; 
 ])
-for variant in \
-       "be 413e7bc80a47fcd7e4c8020e8e120060" \
-       "le d7db9120b1ff28c83aa6fe9fc405d903"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DICTIONARY.
 LIST.
 ])
   AT_CHECK([pspp -o pspp.csv sys-file.sps])
-  AT_CHECK([grep -v Measure pspp.csv | grep -v Display], [0], [dnl
-Variable,Description,,Position
-num1,Format: F8.0,,1
-num2,Numeric variable 2's label,,2
-,Format: F8.0,,
+  AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,Position
+num1,Format: F8.0,1
+num2,"Label: Numeric variable 2's label
+Format: F8.0",2
 
 Table: Data List
 num1,num2
@@ -229,30 +275,28 @@ dnl Numeric variable, variable label.
 dnl Machine integer info record (SPSS 13).
 7; 3; 4; 8; 13; 2; 3; -1; 1; 1; ENDIAN; 1252;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 
 dnl Data.
 1.0; 2.0; 
 ])
-for variant in \
-       "be 3d17aae7d99538dc73c5cb42692b1038" \
-       "le 8ad1000df598617d5258f323c882d749"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DICTIONARY.
 LIST.
 ])
   AT_CHECK([pspp -o pspp.csv sys-file.sps])
-  AT_CHECK([grep -v Measure pspp.csv | grep -v Display], [0], [dnl
-Variable,Description,,Position
-num1,Format: F8.0,,1
-num2,Numeric variable 2's label,,2
-,Format: F8.0,,
+  AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,Position
+num1,Format: F8.0,1
+num2,"Label: Numeric variable 2's label
+Format: F8.0",2
 
 Table: Data List
 num1,num2
@@ -291,7 +335,7 @@ dnl String variables.
 2; 6; 0; 0; 0x010600 *2; s8 "STR6"; dnl index 11
 2; 7; 0; 0; 0x010700 *2; s8 "STR7"; dnl index 12
 2; 8; 0; 0; 0x010800 *2; s8 "STR8"; dnl index 13
-2; 9; 0; 0; 0x010900 *2; s8 "STR9"; dnl index 14
+2; 9; 0; 0; 0x010900 *2; "STR9"; i8 230; s3 ""; dnl index 14
 2; -1; 0; 0; 0; 0; s8 "";
 2; 12; 0; 0; 0x010c00 *2; s8 "STR12"; dnl index 16
 2; -1; 0; 0; 0; 0; s8 "";
@@ -301,7 +345,7 @@ dnl String variables.
 ( 2; -1; 0; 0; 0; 0; s8 ""; ) * 2;
 
 dnl One value label for NUM1.
-3; 1; 1.0; i8 3; s7 "one"; 4; 1; 1;
+3; 1; 1.0; i8 17; i8 238; i8 228; i8 232; i8 237; s19 " (in Russian)"; 4; 1; 1;
 
 dnl Two value labels for NUM2, as a single pair of type 3 and type 4 records.
 3; 2; 1.0; i8 3; s7 "one"; 2.0; i8 3; s7 "two"; 4; 1; 2;
@@ -345,9 +389,15 @@ dnl One value label for STR6, STR7, STR8.
 3; 1; s8 "JKLMNOP"; i8 25; s31 "value label for `JKLMNOP'"; 4; 1; 12;
 3; 1; s8 "JKLMNOPQ"; i8 26; s31 "value label for `JKLMNOPQ'"; 4; 1; 13;
 
+dnl Machine integer info record.
+7; 3; 4; 8; 1; 2; 3; -1; 1; 1; ENDIAN; 1251;
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1251";
+
 7; 21; 1; COUNT (
-dnl One value label for STR9,
-COUNT("STR9"); 9; 1; COUNT("RSTUVWXYZ"); COUNT("value label for `RSTUVWXYZ'");
+dnl One value label for STR9ж,
+COUNT("STR9"; i8 230); 9; 1; COUNT("RSTUVWXYZ"); COUNT("value label for `RSTUVWXYZ'");
 
 dnl Two value labels for STR12.
 COUNT("STR12"); 12; 2;
@@ -358,7 +408,7 @@ dnl Three value labels for STR16.
 COUNT("STR16"); 16; 3;
 COUNT("opqrstuvwxyzABCD"); COUNT("value label for `opqrstuvwxyzABCD'");
 COUNT("EFGHIJKLMNOPQRST"); COUNT("value label for `EFGHIJKLMNOPQRST'");
-COUNT("UVWXYZ0123456789"); COUNT("value label for `UVWXYZ0123456789'");
+COUNT("UVWXYZ0123456789"); COUNT("value label for `UVWXYZ0123456789' with Cyrillic letters: `"; i8 244; i8 245; i8 246; "'");
 
 dnl One value label for STR17.
 COUNT("STR17"); 17; 1;
@@ -368,73 +418,102 @@ COUNT("abcdefghijklmnopq"); COUNT("value label for `abcdefghijklmnopq'");
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be 1de55cc9fb523c8f9b014cdc5387c12b" \
-       "le 76a6974012df7351b591c5964c41e582"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DICTIONARY.
 ])
   AT_CHECK([pspp -o pspp.csv sys-file.sps])
-  AT_CHECK([grep -v Measure pspp.csv | grep -v Display], [0], [dnl
-Variable,Description,,Position
-num1,Format: F8.0,,1
-,1,one,
-num2,Format: F8.0,,2
-,1,one,
-,2,two,
-num3,Format: F8.0,,3
-,3,three,
-,4,four,
-num4,Format: F8.0,,4
-,5,five,
-,7,seven,
-,8,eight,
-,9,nine,
-num5,Format: F8.0,,5
-,6,six,
-,7,seven,
-,8,eight,
-,10,ten,
-str1,Format: A1,,6
-,a,value label for `a',
-str2,Format: A2,,7
-,bc,value label for `bc',
-,de,value label for `de',
-str3,Format: A3,,8
-,fgh,value label for `fgh',
-,ijk,value label for `ijk',
-str4,Format: A4,,9
-,BCDE,value label for `BCDE',
-,lmno,value label for `lmno',
-,tuvw,value label for `tuvw',
-,xyzA,value label for `xyzA',
-str5,Format: A4,,10
-,FGHI,value label for `FGHI',
-,pqrs,value label for `pqrs',
-,tuvw,value label for `tuvw',
-,xyzA,value label for `xyzA',
-str6,Format: A6,,11
-,JKLMNO,value label for `JKLMNO',
-str7,Format: A7,,12
-,JKLMNOP,value label for `JKLMNOP',
-str8,Format: A8,,13
-,JKLMNOPQ,value label for `JKLMNOPQ',
-str9,Format: A9,,14
-,RSTUVWXYZ,value label for `RSTUVWXYZ',
-str12,Format: A12,,15
-,0123456789ab,value label for `0123456789ab',
-,cdefghijklmn,value label for `cdefghijklmn',
-str16,Format: A16,,16
-,EFGHIJKLMNOPQRST,value label for `EFGHIJKLMNOPQRST',
-,UVWXYZ0123456789,value label for `UVWXYZ0123456789',
-,opqrstuvwxyzABCD,value label for `opqrstuvwxyzABCD',
-str17,Format: A17,,17
-,abcdefghijklmnopq,value label for `abcdefghijklmnopq',
+  AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,Position
+num1,"Format: F8.0
+
+Value,Label
+1,один (in Russian)",1
+num2,"Format: F8.0
+
+Value,Label
+1,one
+2,two",2
+num3,"Format: F8.0
+
+Value,Label
+3,three
+4,four",3
+num4,"Format: F8.0
+
+Value,Label
+5,five
+7,seven
+8,eight
+9,nine",4
+num5,"Format: F8.0
+
+Value,Label
+6,six
+7,seven
+8,eight
+10,ten",5
+str1,"Format: A1
+
+Value,Label
+a,value label for `a'",6
+str2,"Format: A2
+
+Value,Label
+bc,value label for `bc'
+de,value label for `de'",7
+str3,"Format: A3
+
+Value,Label
+fgh,value label for `fgh'
+ijk,value label for `ijk'",8
+str4,"Format: A4
+
+Value,Label
+BCDE,value label for `BCDE'
+lmno,value label for `lmno'
+tuvw,value label for `tuvw'
+xyzA,value label for `xyzA'",9
+str5,"Format: A4
+
+Value,Label
+FGHI,value label for `FGHI'
+pqrs,value label for `pqrs'
+tuvw,value label for `tuvw'
+xyzA,value label for `xyzA'",10
+str6,"Format: A6
+
+Value,Label
+JKLMNO,value label for `JKLMNO'",11
+str7,"Format: A7
+
+Value,Label
+JKLMNOP,value label for `JKLMNOP'",12
+str8,"Format: A8
+
+Value,Label
+JKLMNOPQ,value label for `JKLMNOPQ'",13
+str9ж,"Format: A9
+
+Value,Label
+RSTUVWXYZ,value label for `RSTUVWXYZ'",14
+str12,"Format: A12
+
+Value,Label
+0123456789ab,value label for `0123456789ab'
+cdefghijklmn,value label for `cdefghijklmn'",15
+str16,"Format: A16
+
+Value,Label
+EFGHIJKLMNOPQRST,value label for `EFGHIJKLMNOPQRST'
+UVWXYZ0123456789,value label for `UVWXYZ0123456789' with Cyrillic letters: `фхц'
+opqrstuvwxyzABCD,value label for `opqrstuvwxyzABCD'",16
+str17,"Format: A17
+
+Value,Label
+abcdefghijklmnopq,value label for `abcdefghijklmnopq'",17
 ])
 done
 AT_CLEANUP
@@ -456,26 +535,29 @@ i8 0 *3;
 dnl Numeric variable, no label or missing values.
 2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
 
+dnl Machine integer info record.
+7; 3; 4; 8; 1; 2; 3; -1; 1; 1; ENDIAN; 1252;
+
 dnl Document record.
-6; 4;
+6; 5;
 s80 "First line of documents";
 s80 "Second line of documents";
+"abb"; i8 233; " appliqu"; i8 233; " attach"; i8 233; " blas"; i8 233; " caf"; i8 233; " canap"; i8 233; " clich"; i8 233; " consomm"; i8 233;
+s25 "";
 s80 "";
 s80 "Last line of documents";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 
 dnl Data.
 1.0;
 ])
-for variant in \
-       "be 8738124d7932cc8ff803142fbf38710b" \
-       "le f3ca2123ec9e8bda91c6b865ba39f506"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DOCUMENTS.
@@ -489,6 +571,8 @@ First line of documents
 
 Second line of documents
 
+abbé appliqué attaché blasé café canapé cliché consommé
+
 
 
 Last line of documents
@@ -500,6 +584,53 @@ num1
 done
 AT_CLEANUP
 
+AT_SETUP([empty document record])
+AT_KEYWORDS([sack synthetic system file positive])
+AT_DATA([sys-file.sack], [dnl
+dnl File header.
+"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
+2; dnl Layout code
+1; dnl Nominal case size
+0; dnl Not compressed
+0; dnl Not weighted 
+1; dnl 1 case.
+100.0; dnl Bias.
+"01 Jan 11"; "20:53:52"; s64 "PSPP synthetic test file";
+i8 0 *3;
+
+dnl Numeric variable, no label or missing values.
+2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
+
+dnl Machine integer info record.
+7; 3; 4; 8; 1; 2; 3; -1; 1; 1; ENDIAN; 1252;
+
+dnl Document record.
+6; 0;
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
+dnl Dictionary termination record.
+999; 0;
+
+dnl Data.
+1.0;
+])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET FILE='sys-file.sav'.
+LIST.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps])
+  AT_CHECK([cat pspp.csv], [0], [dnl
+Table: Data List
+num1
+1
+])
+done
+AT_CLEANUP
+
 AT_SETUP([multiple response sets])
 AT_KEYWORDS([sack synthetic system file positive])
 AT_DATA([sys-file.sack], [dnl
@@ -515,7 +646,7 @@ dnl File header.
 i8 0 *3;
 
 dnl $a
-2; 0; 0; 0; 0x050800 *2; s8 "A";
+2; 0; 0; 0; 0x050800 *2; i8 0x82; i8 0xa0; s6 "";
 2; 0; 0; 0; 0x050800 *2; s8 "B";
 2; 0; 0; 0; 0x050800 *2; s8 "C";
 
@@ -526,9 +657,9 @@ dnl $b
 2; 0; 0; 0; 0x050800 *2; s8 "G";
 
 dnl $c
-2; 3; 0; 0; 0x010300 *2; s8 "H";
-2; 3; 0; 0; 0x010300 *2; s8 "I";
-2; 3; 0; 0; 0x010300 *2; s8 "J";
+2; 4; 0; 0; 0x010400 *2; s8 "H";
+2; 4; 0; 0; 0x010400 *2; s8 "I";
+2; 4; 0; 0; 0x010400 *2; s8 "J";
 
 dnl $d
 2; 0; 0; 0; 0x050800 *2; s8 "K";
@@ -540,27 +671,29 @@ dnl $e
 2; 6; 0; 0; 0x010600 *2; s8 "O";
 2; 6; 0; 0; 0x010600 *2; s8 "P";
 
+dnl Machine integer info record.
+7; 3; 4; 8; 1; 2; 3; -1; 1; 1; ENDIAN; 932;
+
 7; 7; 1;
 COUNT(
-  "$a=C 10 my mcgroup a b c"; i8 10;
-  "$b=D2 55 0  g e f d"; i8 10;
-  "$c=D3 Yes 10 mdgroup #2 h i j"; i8 10);
+  "$a=C 10 my mcgroup "; i8 0x82; i8 0xa0; " b c"; i8 10;
+  "$b=D2 55 0  g e f d"; i8 10; i8 10;
+  "$c=D4 "; i8 0x82; i8 0xcd; i8 0x82; i8 0xa2; " 10 mdgroup #2 h i j"; i8 10);
 
 7; 19; 1;
 COUNT(
+  i8 10;
   "$d=E 1 2 34 13 third mdgroup k l m"; i8 10;
-  "$e=E 11 6 choice 0  n o p"; i8 10);
+  "$e=E 11 6 choice 0  n o p"; i8 10; i8 10; i8 10; i8 10);
+
+dnl Character encoding record.
+7; 20; 1; 9; "shift_jis";
 
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be 0caa3446d7a3f6985e79fd1fcc999b10" \
-       "le 9dbeba699e4149ed836f55bad7346d67"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 MRSETS /DISPLAY NAME=ALL.
@@ -569,7 +702,7 @@ MRSETS /DISPLAY NAME=ALL.
   AT_CHECK([cat pspp.csv], [0], [dnl
 Table: Multiple Response Sets
 Name,Variables,Details
-$a,"a
+$a,"
 b
 c
 ","Multiple category set
@@ -589,7 +722,7 @@ j
 ","Multiple dichotomy set
 Label: mdgroup #2
 Label source: Provided by user
-Counted value: `Yes'
+Counted value: `はい'
 Category label source: Variable labels
 "
 $d,"k
@@ -613,6 +746,55 @@ Category label source: Value labels of counted value
 done
 AT_CLEANUP
 
+dnl Also checks for handling of CR-only line ends in file label and
+dnl extra product info.
+AT_SETUP([extra product info])
+AT_KEYWORDS([sack synthetic system file positive])
+AT_DATA([sys-file.sack], [dnl
+dnl File header.
+"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
+2; dnl Layout code
+4; dnl Nominal case size
+0; dnl Not compressed
+0; dnl Not weighted
+0; dnl No cases.
+100.0; dnl Bias.
+"01 Jan 11"; "20:53:52"; "PSPP synthetic"; i8 13; s49 "test file";
+i8 0 *3;
+
+dnl Numeric variables.
+2; 0; 0; 0; 0x050800 *2; s8 "A";
+2; 0; 0; 0; 0x050800 *2; s8 "B";
+2; 0; 0; 0; 0x050800 *2; s8 "C";
+2; 0; 0; 0; 0x050800 *2; s8 "D";
+
+dnl Extra product info.
+7; 10; 1; COUNT ("Extra product info"; i8 13; "another line"; i8 13; "blah");
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
+dnl Dictionary termination record.
+999; 0;
+])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+SYSFILE INFO FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps])
+  AT_CHECK([sed 7q pspp.csv], [0], [dnl
+File:,sys-file.sav
+Label:,"PSPP synthetic
+test file"
+Created:,01 Jan 11 20:53:52 by $(@%:@) SPSS DATA FILE PSPP synthetic test file
+Product:,"Extra product info
+another line
+blah"
+])
+done
+AT_CLEANUP
+
 AT_SETUP([variable display parameters, without width])
 AT_KEYWORDS([sack synthetic system file positive])
 AT_DATA([sys-file.sack], [dnl
@@ -664,71 +846,57 @@ dnl Variable display parameters
 0; 1;
 0; 2;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be c130d9345080579b8862b360924edbfa" \
-       "le 6fde96f5a7c7386bff6cca049cd84d6a"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DICTIONARY.
 ])
   AT_CHECK([pspp -o pspp.csv sys-file.sps])
   AT_CHECK([cat pspp.csv], [0], [dnl
-Variable,Description,,Position
-a,Format: F8.0,,1
-,Measure: Nominal,,
-,Display Alignment: Left,,
-,Display Width: 8,,
-b,Format: F8.0,,2
-,Measure: Ordinal,,
-,Display Alignment: Left,,
-,Display Width: 8,,
-c,Format: F8.0,,3
-,Measure: Scale,,
-,Display Alignment: Left,,
-,Display Width: 8,,
-d,Format: F8.0,,4
-,Measure: Nominal,,
-,Display Alignment: Right,,
-,Display Width: 8,,
-h,Format: A3,,5
-,Measure: Ordinal,,
-,Display Alignment: Right,,
-,Display Width: 3,,
-i,Format: A3,,6
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 3,,
-j,Format: A3,,7
-,Measure: Nominal,,
-,Display Alignment: Center,,
-,Display Width: 3,,
-k,Format: A3,,8
-,Measure: Ordinal,,
-,Display Alignment: Center,,
-,Display Width: 3,,
-l,Format: A9,,9
-,Measure: Scale,,
-,Display Alignment: Center,,
-,Display Width: 9,,
-m,Format: A10,,10
-,Measure: Nominal,,
-,Display Alignment: Left,,
-,Display Width: 10,,
-n,Format: A17,,11
-,Measure: Nominal,,
-,Display Alignment: Right,,
-,Display Width: 17,,
-o,Format: A25,,12
-,Measure: Nominal,,
-,Display Alignment: Center,,
-,Display Width: 25,,
+Variable,Description,Position
+a,"Format: F8.0
+Measure: Nominal
+Display Alignment: Left",1
+b,"Format: F8.0
+Measure: Ordinal
+Display Alignment: Left",2
+c,"Format: F8.0
+Measure: Scale
+Display Alignment: Left",3
+d,"Format: F8.0
+Measure: Nominal
+Display Alignment: Right",4
+h,"Format: A3
+Measure: Ordinal
+Display Alignment: Right",5
+i,"Format: A3
+Measure: Scale
+Display Alignment: Right",6
+j,"Format: A3
+Measure: Nominal
+Display Alignment: Center",7
+k,"Format: A3
+Measure: Ordinal
+Display Alignment: Center",8
+l,"Format: A9
+Measure: Scale
+Display Alignment: Center",9
+m,"Format: A10
+Measure: Nominal
+Display Alignment: Left",10
+n,"Format: A17
+Measure: Nominal
+Display Alignment: Right",11
+o,"Format: A25
+Measure: Nominal
+Display Alignment: Center",12
 ])
 done
 AT_CLEANUP
@@ -784,71 +952,69 @@ dnl Variable display parameters
 0; 11; 1;
 0; 12; 2;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be 3ace75689a0b7faa9360936bbfe26055" \
-       "le 6e93f35d19a9882eb53ffb1b067ef7cd"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DICTIONARY.
 ])
   AT_CHECK([pspp -o pspp.csv sys-file.sps])
   AT_CHECK([cat pspp.csv], [0], [dnl
-Variable,Description,,Position
-a,Format: F8.0,,1
-,Measure: Nominal,,
-,Display Alignment: Left,,
-,Display Width: 1,,
-b,Format: F8.0,,2
-,Measure: Ordinal,,
-,Display Alignment: Left,,
-,Display Width: 2,,
-c,Format: F8.0,,3
-,Measure: Scale,,
-,Display Alignment: Left,,
-,Display Width: 3,,
-d,Format: F8.0,,4
-,Measure: Nominal,,
-,Display Alignment: Right,,
-,Display Width: 4,,
-h,Format: A3,,5
-,Measure: Ordinal,,
-,Display Alignment: Right,,
-,Display Width: 5,,
-i,Format: A3,,6
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 6,,
-j,Format: A3,,7
-,Measure: Nominal,,
-,Display Alignment: Center,,
-,Display Width: 7,,
-k,Format: A3,,8
-,Measure: Ordinal,,
-,Display Alignment: Center,,
-,Display Width: 8,,
-l,Format: A9,,9
-,Measure: Scale,,
-,Display Alignment: Center,,
-,Display Width: 9,,
-m,Format: A10,,10
-,Measure: Nominal,,
-,Display Alignment: Left,,
-,Display Width: 10,,
-n,Format: A17,,11
-,Measure: Nominal,,
-,Display Alignment: Right,,
-,Display Width: 11,,
-o,Format: A25,,12
-,Measure: Nominal,,
-,Display Alignment: Center,,
-,Display Width: 12,,
+Variable,Description,Position
+a,"Format: F8.0
+Measure: Nominal
+Display Alignment: Left
+Display Width: 1",1
+b,"Format: F8.0
+Measure: Ordinal
+Display Alignment: Left
+Display Width: 2",2
+c,"Format: F8.0
+Measure: Scale
+Display Alignment: Left
+Display Width: 3",3
+d,"Format: F8.0
+Measure: Nominal
+Display Alignment: Right
+Display Width: 4",4
+h,"Format: A3
+Measure: Ordinal
+Display Alignment: Right
+Display Width: 5",5
+i,"Format: A3
+Measure: Scale
+Display Alignment: Right
+Display Width: 6",6
+j,"Format: A3
+Measure: Nominal
+Display Alignment: Center
+Display Width: 7",7
+k,"Format: A3
+Measure: Ordinal
+Display Alignment: Center
+Display Width: 8",8
+l,"Format: A9
+Measure: Scale
+Display Alignment: Center
+Display Width: 9",9
+m,"Format: A10
+Measure: Nominal
+Display Alignment: Left
+Display Width: 10",10
+n,"Format: A17
+Measure: Nominal
+Display Alignment: Right
+Display Width: 11",11
+o,"Format: A25
+Measure: Nominal
+Display Alignment: Center
+Display Width: 12",12
 ])
 done
 AT_CLEANUP
@@ -859,7 +1025,7 @@ AT_DATA([sys-file.sack], [dnl
 dnl File header.
 "$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
 2; dnl Layout code
-4; dnl Nominal case size
+7; dnl Nominal case size
 0; dnl Not compressed
 0; dnl Not weighted 
 0; dnl No cases.
@@ -872,36 +1038,49 @@ dnl Numeric variables.
 2; 0; 0; 0; 0x050800 *2; s8 "LONGVA_A";
 2; 0; 0; 0; 0x050800 *2; s8 "LONGVA_B";
 2; 0; 0; 0; 0x050800 *2; s8 "LONGVA_C";
+2; 0; 0; 0; 0x050800 *2; "CO"; i8 214; "RDINA";
+2; 0; 0; 0; 0x050800 *2; "CO"; i8 214; "RDI_A";
+2; 0; 0; 0; 0x050800 *2; "CO"; i8 214; "RDI_B";
+
+dnl Machine integer info record.
+7; 3; 4; 8; 1; 2; 3; -1; 1; 1; ENDIAN; 1252;
+
+dnl Machine floating-point info record.
+7; 4; 8; 3; SYSMIS; HIGHEST; LOWEST;
 
 dnl Long variable names.
 7; 13; 1; COUNT (
 "LONGVARI=LongVariableName1"; i8 9;
 "LONGVA_A=LongVariableName2"; i8 9;
 "LONGVA_B=LongVariableName3"; i8 9;
-"LONGVA_C=LongVariableName4";
+"LONGVA_C=LongVariableName4"; i8 9;
+"CO"; i8 214; "RDINA=Co"; i8 246; "rdinate_X"; i8 9;
+"CO"; i8 214; "RDI_A=Co"; i8 246; "rdinate_Y"; i8 9;
+"CO"; i8 214; "RDI_B=Co"; i8 246; "rdinate_Z";
 );
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be eb7a8b4055a5d880a185a566048876b3" \
-       "le dd4ecd7541320b9b51746717ef20973f"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DICTIONARY.
 ])
   AT_CHECK([pspp -o pspp.csv sys-file.sps])
-  AT_CHECK([grep -v Measure pspp.csv | grep -v Display], [0], [dnl
-Variable,Description,,Position
-LongVariableName1,Format: F8.0,,1
-LongVariableName2,Format: F8.0,,2
-LongVariableName3,Format: F8.0,,3
-LongVariableName4,Format: F8.0,,4
+  AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,Position
+LongVariableName1,Format: F8.0,1
+LongVariableName2,Format: F8.0,2
+LongVariableName3,Format: F8.0,3
+LongVariableName4,Format: F8.0,4
+Coördinate_X,Format: F8.0,5
+Coördinate_Y,Format: F8.0,6
+Coördinate_Z,Format: F8.0,7
 ])
 done
 AT_CLEANUP
@@ -921,9 +1100,9 @@ dnl File header.
 i8 0 *3;
 
 dnl 256-byte string.
-2; 255; 0; 0; 0x01FF00 *2; s8 "STR256";
+2; 255; 0; 0; 0x01FF00 *2; "S"; i8 201; s6 "Q256";
 (2; -1; 0; 0; 0; 0; s8 "") * 31;
-2; 4; 0; 0; 0x010400 *2; s8 "STR256_1";
+2; 4; 0; 0; 0x010400 *2; "S"; i8 201; "Q256_1";
 
 dnl 600-byte string.
 2; 255; 0; 0; 0x01FF00 *2; s8 "STR600";
@@ -933,12 +1112,18 @@ dnl 600-byte string.
 2; 96; 0; 0; 0x016000 *2; s8 "STR600_2";
 (2; -1; 0; 0; 0; 0; s8 "") * 11;
 
+dnl Machine integer info record.
+7; 3; 4; 8; 1; 2; 3; -1; 1; 1; ENDIAN; 1252;
+
 dnl Very long string record.
 7; 14; 1; COUNT (
-"STR256=00256"; i8 0; i8 9;
+"S"; i8 201; "Q256=00256"; i8 0; i8 9;
 "STR600=00600"; i8 0; i8 9;
 );
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 
@@ -948,26 +1133,21 @@ dnl Data.
 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#" * 9;
 "abcdefghijklmnopqrstuvwxyzABCDEF";
 ])
-for variant in \
-       "be 40a4327805d8b59891084317248f5d4a" \
-       "le ced2584a43037b893b7feb068e2cb9d6"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DICTIONARY.
 LIST.
 ])
   AT_CHECK([pspp -o pspp.csv sys-file.sps])
-  AT_CHECK([grep -v Measure pspp.csv | grep -v Display], [0], [dnl
-Variable,Description,,Position
-str256,Format: A256,,1
-str600,Format: A600,,2
+  AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,Position
+séq256,Format: A256,1
+str600,Format: A600,2
 
 Table: Data List
-str256,str600
+séq256,str600
 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@a,abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#abcdefghijklmnopqrstuvwxyz
 ])
 done
@@ -979,7 +1159,7 @@ AT_DATA([sys-file.sack], [dnl
 dnl File header.
 "$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
 2; dnl Layout code
-2; dnl Nominal case size
+3; dnl Nominal case size
 0; dnl Not compressed
 0; dnl Not weighted 
 0; dnl 1 case.
@@ -990,62 +1170,180 @@ i8 0 *3;
 dnl Variables.
 2; 0; 0; 0; 0x050800 *2; s8 "FIRSTVAR";
 2; 0; 0; 0; 0x050800 *2; s8 "SECONDVA";
+2; 0; 0; 0; 0x050800 *2; s8 "THIRDVAR";
+
+dnl Machine integer info record.
+7; 3; 4; 8; 1; 2; 3; -1; 1; 1; ENDIAN; 1252;
 
 dnl Long variable names.
 7; 13; 1; COUNT (
 "FIRSTVAR=FirstVariable"; i8 9;
-"SECONDVA=SecondVariable"; i8 9;
+"SECONDVA=S"; i8 233; "condVariable"; i8 9;
+"THIRDVAR=ThirdVariable"; i8 9
 );
 
 dnl Data file attributes record.
 7; 17; 1; COUNT (
-"Attr1('Value1'"; i8 10; "''QuotedValue''"; i8 10; ")";
-"SecondAttr('123'"; i8 10; "'456'"; i8 10; ")";
+"Attr1('Value1'"; i8 10; "''d"; i8 233; "claration''"; i8 10; ")";
+"S"; i8 233; "condAttr('123'"; i8 10; "'456'"; i8 10; ")";
 );
 
 dnl Variable attributes record.
 7; 18; 1; COUNT (
 "FirstVariable:";
-  "fred('23'"; i8 10; "'34'"; i8 10; ")";
+  "ad"; i8 232; "le('23'"; i8 10; "'34'"; i8 10; ")";
   "bert('123'"; i8 10; ")";
-"/SecondVariable:";
+  "$@Role('1'"; i8 10; ")";
+"/S"; i8 233; "condVariable:";
   "xyzzy('quux'"; i8 10; ")";
 );
 
+dnl Another variable attributes record.
+dnl Only system files written by "Stata 14.1/-savespss- 1.77 by S.Radyakin"
+dnl include multiple variable attributes records.
+7; 18; 1; COUNT ("ThirdVariable:fizz('buzz'"; i8 10; ")";);
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be 955802de462daf810c0ecc81ee2320a1" \
-       "le 7fc6439aedfa00615bb1fe94d6701305"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET FILE='sys-file.sav'.
+DISPLAY @ATTRIBUTES.
 ])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps])
+  AT_CHECK([cat pspp.csv], [0],
+[[Variable,Description
+FirstVariable,"Attribute,Value
+$@Role,1
+adèle[1],23
+adèle[2],34
+bert,123"
+SécondVariable,"Attribute,Value
+xyzzy,quux"
+ThirdVariable,"Attribute,Value
+fizz,buzz"
+
+Table: Custom data file attributes.
+Attribute,Value
+Attr1[1],Value1
+Attr1[2],'déclaration'
+SécondAttr[1],123
+SécondAttr[2],456
+]])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
-DISPLAY ATTRIBUTES.
+DISPLAY DICTIONARY.
 ])
   AT_CHECK([pspp -o pspp.csv sys-file.sps])
   AT_CHECK([cat pspp.csv], [0],
-[[Variable,Description,
-FirstVariable,Custom attributes:,
-,bert,123
-,fred[1],23
-,fred[2],34
-SecondVariable,Custom attributes:,
-,xyzzy,quux
+[[Variable,Description,Position
+FirstVariable,"Format: F8.0
+Role: Output
+
+Attribute,Value
+adèle[1],23
+adèle[2],34
+bert,123",1
+SécondVariable,"Format: F8.0
+Role: Input
+
+Attribute,Value
+xyzzy,quux",2
+ThirdVariable,"Format: F8.0
+Role: Input
+
+Attribute,Value
+fizz,buzz",3
 
 Table: Custom data file attributes.
 Attribute,Value
-SecondAttr[1],123
-SecondAttr[2],456
 Attr1[1],Value1
-Attr1[2],'QuotedValue'
+Attr1[2],'déclaration'
+SécondAttr[1],123
+SécondAttr[2],456
 ]])
 done
 AT_CLEANUP
 
+AT_SETUP([variable roles])
+AT_KEYWORDS([sack synthetic system file positive])
+AT_DATA([sys-file.sack], [dnl
+dnl File header.
+"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
+2; dnl Layout code
+7; dnl Nominal case size
+0; dnl Not compressed
+0; dnl Not weighted
+0; dnl 1 case.
+100.0; dnl Bias.
+"01 Jan 11"; "20:53:52"; s64 "PSPP synthetic test file";
+i8 0 *3;
+
+dnl Variables.
+2; 0; 0; 0; 0x050800 *2; s8 "I";
+2; 0; 0; 0; 0x050800 *2; s8 "O";
+2; 0; 0; 0; 0x050800 *2; s8 "B";
+2; 0; 0; 0; 0x050800 *2; s8 "N";
+2; 0; 0; 0; 0x050800 *2; s8 "P";
+2; 0; 0; 0; 0x050800 *2; s8 "S";
+2; 0; 0; 0; 0x050800 *2; s8 "X";
+
+dnl Machine integer info record.
+7; 3; 4; 8; 1; 2; 3; -1; 1; 1; ENDIAN; 1252;
+
+dnl Variable attributes record.
+7; 18; 1; COUNT (
+"I:$@Role('0'"; i8 10; ")";
+"/O:$@Role('1'"; i8 10; ")";
+"/B:$@Role('2'"; i8 10; ")";
+"/N:$@Role('3'"; i8 10; ")";
+"/P:$@Role('4'"; i8 10; ")";
+"/S:$@Role('5'"; i8 10; ")";
+"/X:$@Role('6'"; i8 10; ")";
+);
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
+dnl Dictionary termination record.
+999; 0;
+])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET FILE='sys-file.sav'.
+DISPLAY DICTIONARY.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [0], [dnl
+warning: `sys-file.sav': Invalid role for variable x.
+])
+  AT_CHECK([cat pspp.csv], [0], [dnl
+warning: `sys-file.sav': Invalid role for variable x.
+
+Variable,Description,Position
+i,"Format: F8.0
+Role: Input",1
+o,"Format: F8.0
+Role: Output",2
+b,"Format: F8.0
+Role: Both",3
+n,"Format: F8.0
+Role: None",4
+p,"Format: F8.0
+Role: Partition",5
+s,"Format: F8.0
+Role: Split",6
+x,"Format: F8.0
+Role: Input",7
+])
+done
+AT_CLEANUP
+
 AT_SETUP([compressed data])
 AT_KEYWORDS([sack synthetic system file positive])
 AT_DATA([sys-file.sack], [dnl
@@ -1053,7 +1351,7 @@ dnl File header.
 "$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
 2; dnl Layout code
 6; dnl Nominal case size
-1; dnl Not compressed
+1; dnl Simple compression
 0; dnl Not weighted 
 -1; dnl Unspecified number of cases.
 100.0; dnl Bias.
@@ -1070,6 +1368,9 @@ dnl String variable.
 2; 15; 0; 0; 0x010f00 *2; s8 "STR15";
 2; -1; 0; 0; 0; 0; s8 "";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 
@@ -1080,26 +1381,21 @@ s8 "vwxyzABC"; s8 "DEFG"; s8 "HIJKLMNO";
 i8 254 253 252 0 0 0 0 0; s8 "PQRSTUVW";
 
 ])
-for variant in \
-       "be c0670e436b068f45710b98f6f7d01dc5" \
-       "le 2e43a7f8861df4e714a192dfb3c8b2f4"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DICTIONARY.
 LIST.
 ])
   AT_CHECK([pspp -o pspp.csv sys-file.sps])
-  AT_CHECK([grep -v Measure pspp.csv | grep -v Display], [0], [dnl
-Variable,Description,,Position
-num1,Format: F8.0,,1
-num2,Format: F8.0,,2
-str4,Format: A4,,3
-str8,Format: A8,,4
-str15,Format: A15,,5
+  AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,Position
+num1,Format: F8.0,1
+num2,Format: F8.0,2
+str4,Format: A4,3
+str8,Format: A8,4
+str15,Format: A15,5
 
 Table: Data List
 num1,num2,str4,str8,str15
@@ -1117,7 +1413,7 @@ dnl File header.
 "$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
 2; dnl Layout code
 6; dnl Nominal case size
-1; dnl Not compressed
+1; dnl Simple compression.
 0; dnl Not weighted 
 -1; dnl Unspecified number of cases.
 0.0; dnl Bias.
@@ -1134,6 +1430,9 @@ dnl String variable.
 2; 15; 0; 0; 0x010f00 *2; s8 "STR15";
 2; -1; 0; 0; 0; 0; s8 "";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 
@@ -1144,26 +1443,21 @@ s8 "vwxyzABC"; s8 "DEFG"; s8 "HIJKLMNO";
 i8 254 253 252 0 0 0 0 0; s8 "PQRSTUVW";
 
 ])
-for variant in \
-       "be 2f0d25704ee497ae833213a3e4ff5e8b" \
-       "le 49f68a9e1ba02a2f7e9166686a0db9d9"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DICTIONARY.
 LIST.
 ])
   AT_CHECK([pspp -o pspp.csv sys-file.sps], [0])
-  AT_CHECK([grep -v Measure pspp.csv | grep -v Display], [0], [dnl
-Variable,Description,,Position
-num1,Format: F8.0,,1
-num2,Format: F8.0,,2
-str4,Format: A4,,3
-str8,Format: A8,,4
-str15,Format: A15,,5
+  AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,Position
+num1,Format: F8.0,1
+num2,Format: F8.0,2
+str4,Format: A4,3
+str8,Format: A8,4
+str15,Format: A15,5
 
 Table: Data List
 num1,num2,str4,str8,str15
@@ -1181,7 +1475,7 @@ dnl File header.
 "$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
 2; dnl Layout code
 6; dnl Nominal case size
-1; dnl Not compressed
+1; dnl Simple compression.
 0; dnl Not weighted 
 -1; dnl Unspecified number of cases.
 50.0; dnl Bias.
@@ -1198,6 +1492,9 @@ dnl String variable.
 2; 15; 0; 0; 0x010f00 *2; s8 "STR15";
 2; -1; 0; 0; 0; 0; s8 "";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 
@@ -1208,13 +1505,8 @@ s8 "vwxyzABC"; s8 "DEFG"; s8 "HIJKLMNO";
 i8 254 253 252 0 0 0 0 0; s8 "PQRSTUVW";
 
 ])
-for variant in \
-       "be 668b85e3dee0797883e9933a096b8c18" \
-       "le 5e7a9c4e88cd2dbc2322943da663868e"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DICTIONARY.
@@ -1223,15 +1515,15 @@ LIST.
   AT_CHECK([pspp -o pspp.csv sys-file.sps], [0], 
     [warning: `sys-file.sav' near offset 0x54: Compression bias is not the usual value of 100, or system file uses unrecognized floating-point format.
 ])
-  AT_CHECK([grep -v Measure pspp.csv | grep -v Display], [0], [dnl
+  AT_CHECK([cat pspp.csv], [0], [dnl
 "warning: `sys-file.sav' near offset 0x54: Compression bias is not the usual value of 100, or system file uses unrecognized floating-point format."
 
-Variable,Description,,Position
-num1,Format: F8.0,,1
-num2,Format: F8.0,,2
-str4,Format: A4,,3
-str8,Format: A8,,4
-str15,Format: A15,,5
+Variable,Description,Position
+num1,Format: F8.0,1
+num2,Format: F8.0,2
+str4,Format: A4,3
+str8,Format: A8,4
+str15,Format: A15,5
 
 Table: Data List
 num1,num2,str4,str8,str15
@@ -1241,29 +1533,194 @@ num1,num2,str4,str8,str15
 ])
 done
 AT_CLEANUP
-\f
-AT_BANNER([system file reader - negative])
 
-AT_SETUP([misplaced type 4 record])
-AT_KEYWORDS([sack synthetic system file negative])
-AT_DATA([sys-file.sack], [dnl
+m4_divert_push([PREPARE_TESTS])
+zcompressed_sack () {
+    cat <<'EOF'
 dnl File header.
-"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
-2; 1; 1; 0; -1; 100.0; "01 Jan 11"; "20:53:52"; s64 ""; i8 0 *3;
+"$FL3"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
+2; dnl Layout code
+6; dnl Nominal case size
+2; dnl zlib compressed
+0; dnl Not weighted
+-1; dnl Unspecified number of cases.
+100.0; dnl Bias.
+"01 Jan 11"; "20:53:52"; s64 "PSPP synthetic test file";
+i8 0 *3;
 
-dnl Numeric variable.
+dnl Numeric variables.
+2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
+2; 0; 0; 0; 0x050800 *2; s8 "NUM2";
+
+dnl String variable.
+2; 4; 0; 0; 0x010400 *2; s8 "STR4";
+2; 8; 0; 0; 0x010800 *2; s8 "STR8";
+2; 15; 0; 0; 0x010f00 *2; s8 "STR15";
+2; -1; 0; 0; 0; 0; s8 "";
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
+dnl Dictionary termination record.
+999; 0;
+
+dnl ZLIB data header.
+i64 0x194;    # zheader_ofs
+i64 0x205;    # ztrailer_ofs
+i64 48;       # ztrailer_len
+
+dnl ZLIB data block.
+dnl
+dnl This is the compressed form of:
+dnl
+dnl 01 64 fe fd fe fd ff fb  61 62 63 64 65 66 67 68  |.d......abcdefgh|
+dnl 30 31 32 33 20 20 20 20  fd fd fd fe 65 66 fd fd  |0123    ....ef..|
+dnl 6a 6b 6c 6d 20 20 20 20  6e 6f 70 71 72 73 74 75  |jklm    nopqrstu|
+dnl 76 77 78 79 7a 41 42 43  44 45 46 47 20 20 20 20  |vwxyzABCDEFG    |
+dnl 48 49 4a 4b 4c 4d 4e 4f  fe fd fc 00 00 00 00 00  |HIJKLMNO........|
+dnl 50 51 52 53 54 55 56 57                           |PQRSTUVW|
+dnl
+dnl which is the data from the "compressed data" test.
+hex "78 01 63 4c f9 f7 f7 df  df ff bf 13 93 92 53 52";
+hex "d3 d2 33 0c 0c 8d 8c 15  80 e0 ef df bf ff 52 d3";
+hex "fe fe cd ca ce c9 05 f1  f3 f2 0b 0a 8b 8a 4b 4a";
+hex "cb ca 2b 2a ab 1c 9d 9c  5d 5c dd dc 41 e2 1e 9e";
+hex "5e de 3e be 7e fe ff fe  fe 61 00 81 80 c0 a0 e0";
+hex "90 d0 b0 70 00 0f 3f 23  d7";
+
+dnl ZLIB data trailer fixed header:
+i64 -100;     # ztrailer_bias
+i64 0;        # ztrailer_zero
+0x3ff000;     # block_size
+1;            # n_blocks
+
+dnl ZLIB block descriptor:
+i64 0x194;    # uncompressed_ofs
+i64 0x1ac;    # compressed_ofs
+88;           # uncompressed_size
+89;           # compressed_size
+EOF
+}
+m4_divert_pop([PREPARE_TESTS])
+
+AT_SETUP([zcompressed data])
+AT_KEYWORDS([sack synthetic system file positive zlib])
+zcompressed_sack > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET FILE='sys-file.sav'.
+DISPLAY DICTIONARY.
+LIST.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps])
+  AT_CHECK([cat pspp.csv], [0], [dnl
+Variable,Description,Position
+num1,Format: F8.0,1
+num2,Format: F8.0,2
+str4,Format: A4,3
+str8,Format: A8,4
+str15,Format: A15,5
+
+Table: Data List
+num1,num2,str4,str8,str15
+-99,0,,abcdefgh,0123   @&t@
+.,151,jklm,nopqrstu,vwxyzABC       @&t@
+1,2,DEFG,HIJKLMNO,PQRSTUV
+])
+done
+AT_CLEANUP
+\f
+AT_BANNER([system file reader - negative])
+
+AT_SETUP([no variables])
+AT_KEYWORDS([sack synthetic system file negative])
+AT_DATA([sys-file.sack], [dnl
+dnl File header.
+"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
+2; dnl Layout code
+0; dnl Nominal case size (empty)
+0; dnl Not compressed
+0; dnl Not weighted
+0; dnl 0 cases.
+100.0; dnl Bias.
+"01 Jan 11"; "20:53:52"; s64 "PSPP synthetic test file";
+i8 0 *3;
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
+dnl Dictionary termination record.
+999; 0;
+])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -O format=csv sys-file.sps], [1], [dnl
+sys-file.sps:1: error: GET: `sys-file.sav': Data file dictionary has no variables.
+])
+
+  dnl At one point pspp-convert would hang forever if there were no variables,
+  dnl so check against regression.
+  AT_CHECK([pspp-convert sys-file.sav sys-file.txt])
+  AT_CHECK([cat sys-file.txt], [0], [
+])
+done
+AT_CLEANUP
+
+AT_SETUP([unspecified character encoding])
+AT_KEYWORDS([sack synthetic system file positive])
+AT_DATA([sys-file.sack], [dnl
+dnl File header.
+"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
+2; dnl Layout code
+4; dnl Nominal case size
+0; dnl Not compressed
+0; dnl Not weighted
+0; dnl No cases.
+100.0; dnl Bias.
+"01 Jan 11"; "20:53:52";
+"PSPP synthetic test file: "; i8 244; i8 245; i8 246; i8 248; s34 "";
+i8 0 *3;
+
+dnl Numeric variables.
+2; 0; 0; 0; 0x050800 *2; s8 "A";
+2; 0; 0; 0; 0x050800 *2; s8 "B";
+2; 0; 0; 0; 0x050800 *2; s8 "C";
+2; 0; 0; 0; 0x050800 *2; s8 "D";
+
+dnl Dictionary termination record.
+999; 0;
+])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET 'sys-file.sav'.
+])
+  AT_CHECK([pspp -O format=csv sys-file.sps], [0], [stdout])
+  AT_CHECK([sed 's/default encoding.*For/default encoding.  For/' stdout], [0], [dnl
+"warning: `sys-file.sav': This system file does not indicate its own character encoding.  Using default encoding.  For best results, specify an encoding explicitly.  Use SYSFILE INFO with ENCODING=""DETECT"" to analyze the possible encodings."
+])
+done
+AT_CLEANUP
+
+AT_SETUP([misplaced type 4 record])
+AT_KEYWORDS([sack synthetic system file negative])
+AT_DATA([sys-file.sack], [dnl
+dnl File header.
+"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
+2; 1; 1; 0; -1; 100.0; "01 Jan 11"; "20:53:52"; s64 ""; i8 0 *3;
+
+dnl Numeric variable.
 2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
 
 dnl Type 4 record.
 >>4<<;
 ])
-for variant in \
-       "be 6e0bb549fff1fd1af333d51b8a6e0f43" \
-       "le 7b62734edcee2a1689c463f2866d11b8"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
@@ -1285,13 +1742,8 @@ dnl Numeric variable.
 dnl Type 8 record (not a valid type).
 >>8<<;
 ])
-for variant in \
-       "be dc8f078c23046ee7db74ec1003178a11" \
-       "le dc7f111642f0629f4370630fd092eee3"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
@@ -1310,16 +1762,14 @@ dnl File header.
 dnl Numeric variable.
 2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be c57e91aa426f61813c3ad91ea3a56dda" \
-       "le 5d1a6c114b135b219473c8ad5bb44bda"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], 
@@ -1338,16 +1788,14 @@ dnl File header.
 dnl Numeric variable.
 2; 0; 0; 0; 0x050800 *2; s8 >>"$UM1"<<;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be decb7ac6defa1ab3cc7a386d1843c1ae" \
-       "le 5279b6275633bac55d167faebccfdb14"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
@@ -1366,16 +1814,14 @@ dnl File header.
 dnl Numeric variable.
 2; 0; 0; 0; 0x050800 *2; s8 >>"TO"<<;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 57e6ad709668bbf538e2efee4af49916" \
-       "le 523f14b611efa380bbadf7a16ea43fed"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
@@ -1394,16 +1840,14 @@ dnl File header.
 dnl String variable with invalid width 256.
 2; 256; 0; 0; 0x050800 *2; s8 "VAR1";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 170bb18589ba264a0ed2d57b41fe77e1" \
-       "le 9528b4b5936ef5630bbd3bdd60a123c3"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
@@ -1412,6 +1856,8 @@ do
 done
 AT_CLEANUP
 
+dnl SPSS-generated system file can contain duplicate variable names
+dnl (see bug #41475).
 AT_SETUP([duplicate variable name])
 AT_KEYWORDS([sack synthetic system file negative])
 AT_DATA([sys-file.sack], [dnl
@@ -1423,20 +1869,23 @@ dnl Numeric variables.
 2; 0; 0; 0; 0x050800 *2; s8 "VAR1";
 2; 0; 0; 0; 0x050800 *2; s8 "VAR1";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be d8f5fd768ab1d641f9330a4840c71343" \
-       "le f01e123d384cdaa7c2f7fc4791325ebf"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+DISPLAY DICTIONARY.
 ])
-  AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
-   [error: `sys-file.sav' near offset 0xd4: Duplicate variable name `VAR1'.
+  AT_CHECK([pspp -O format=csv sys-file.sps], [0],
+   [warning: `sys-file.sav' near offset 0xd4: Renaming variable with duplicate name `VAR1' to `VAR001'.
+
+Variable,Description,Position
+var1,Format: F8.0,1
+var001,Format: F8.0,2
 ])
 done
 AT_CLEANUP
@@ -1451,16 +1900,14 @@ dnl File header.
 dnl Numeric variable.
 2; 0; >>2<<; 0; 0x050800 *2; s8 "VAR1";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 3c5ff8d8f146457a385ca92d3d23ca8a" \
-       "le 37e9f956d321ae57b0bf7fe2384e892b"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
@@ -1479,16 +1926,14 @@ dnl File header.
 dnl Numeric variable.
 2; 0; 0; >>-1<<; 0x050800 *2; s8 "VAR1";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be d1d0d4aedf9f053452c4b1e658ade5e2" \
-       "le df697575499fe12921185a3d23a5d61d"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
@@ -1507,16 +1952,14 @@ dnl File header.
 dnl String variable.
 2; 8; 0; >>4<<; 0x010800 *2; s8 "VAR1";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be f833033be7b102fae19159989f62faa6" \
-       "le 9704ba828bb7a36ef0262838f6b7936b"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
@@ -1536,16 +1979,14 @@ dnl String variable.
 2; 10; 0; 0; 0x010a00 *2; s8 "VAR1";
 >>2; 0; 0; 0; 0x050800 *2; s8 "VAR2";<<
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be c8f9ad2b2acd2918055e2b78c1e0b4b8" \
-       "le 1afab4d6aee90a6fe8d2dbf229e06409"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
 done
 AT_CLEANUP
 
-AT_SETUP([unknown variable format])
+AT_SETUP([invalid variable format])
 AT_KEYWORDS([sack synthetic system file negative])
 AT_DATA([sys-file.sack], [dnl
 dnl File header.
 "$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
-2; 1; 1; 0; -1; 100.0; "01 Jan 11"; "20:53:52"; s64 ""; i8 0 *3;
+2; 4; 1; 0; -1; 100.0; "01 Jan 11"; "20:53:52"; s64 ""; i8 0 *3;
 
-dnl Numeric variable.
-2; 0; 0; 0; >>0xff0800<< *2; s8 "VAR1";
+dnl Numeric variable, invalid format types.
+dnl No warning is issued for type 0 because it has been observed in real
+dnl system files.
+2; 0; 0; 0; >>0xff0800; 0<<; s8 "NUM1";
+
+dnl Numeric variable, string formats.
+2; 0; 0; 0; >>0x010800<<; >>0x021000<<; s8 "VAR1";
+
+dnl String variable, numeric formats.
+2; 4; 0; 0; >>0x050800<<; >>0x110a01<<; s8 "STR1";
+
+dnl String variable, wrong width formats.
+2; 4; 0; 0; >>0x010800<<; >>0x020400<<; s8 "STR2";
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
 
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be fcf94b3ff11b7e2ff50c226b609cff1e" \
-       "le 88fc97cc80d5a170e53a7cc89e204b0d"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
-  AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
-   [error: `sys-file.sav' near offset 0xc0: Unknown variable format 255.
+  AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
+warning: `sys-file.sav' near offset 0xc0: Variable NUM1 with width 0 has invalid print format 0xff0800.
+
+warning: `sys-file.sav' near offset 0xe0: Variable VAR1 with width 0 has invalid print format 0x10800.
+
+warning: `sys-file.sav' near offset 0xe4: Variable VAR1 with width 0 has invalid write format 0x21000.
+
+warning: `sys-file.sav' near offset 0x100: Variable STR1 with width 4 has invalid print format 0x50800.
+
+warning: `sys-file.sav' near offset 0x104: Variable STR1 with width 4 has invalid write format 0x110a01.
+
+warning: `sys-file.sav' near offset 0x120: Variable STR2 with width 4 has invalid print format 0x10800.
+
+warning: `sys-file.sav' near offset 0x124: Variable STR2 with width 4 has invalid write format 0x20400.
 ])
 done
 AT_CLEANUP
 
-AT_SETUP([invalid numeric variable format])
+AT_SETUP([invalid long string missing values])
 AT_KEYWORDS([sack synthetic system file negative])
 AT_DATA([sys-file.sack], [dnl
 dnl File header.
 "$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
-2; 3; 1; 0; -1; 100.0; "01 Jan 11"; "20:53:52"; s64 ""; i8 0 *3;
+2; dnl Layout code
+7; dnl Nominal case size
+0; dnl Not compressed
+0; dnl Not weighted
+1; dnl 1 case.
+100.0; dnl Bias.
+"01 Jan 11"; "20:53:52";
+"PSPP synthetic test file: "; i8 244; i8 245; i8 246; i8 248; s34 "";
+i8 0 *3;
 
-dnl Numeric variable, string formats.
-2; 0; 0; 0; >>0x010800<<; >>0x021000<<; s8 "VAR1";
+dnl One numeric variable.
+2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
 
-dnl String variable, numeric formats.
-2; 4; 0; 0; >>0x050800<<; >>0x110a01<<; s8 "STR1";
+dnl Long string variables that will have missing values added with a
+dnl later record.
+2; 9; 0; 0; 0x010900 *2; s8 "STR1";
+2; -1; 0; 0; 0; 0; s8 "";
+2; 10; 0; 0; 0x010a00 *2; s8 "STR2";
+2; -1; 0; 0; 0; 0; s8 "";
+2; 11; 0; 0; 0x010b00 *2; s8 "STR3";
+2; -1; 0; 0; 0; 0; s8 "";
 
-dnl String variable, wrong width formats.
-2; 4; 0; 0; >>0x010800<<; >>0x020400<<; s8 "STR2";
+dnl Machine integer info record.
+7; 3; 4; 8; 1; 2; 3; -1; 1; 1; ENDIAN; 1252;
 
-dnl End of dictionary.
+dnl Machine floating-point info record.
+7; 4; 8; 3; SYSMIS; HIGHEST; LOWEST;
+
+dnl Long string variable missing values record.
+7; 22; 1; COUNT (
+dnl Zero missing values (not allowed) for STR1 .
+COUNT("STR1"); i8 >>0<<;
+
+dnl Four missing values (not allowed) for STR2.
+COUNT("STR2"); i8 4;
+8; "abcdefgh"; 8; "ijklmnop"; 8; "qrstuvwx"; 8; "yz012345";
+
+dnl Missing values for unknown variable
+COUNT(>>"Nonexistent"<<); i8 1; 8; "abcdefgh";
+
+dnl Missing values for numeric variable
+COUNT(>>"NUM1"<<); i8 1; 8; "abcdefgh";
+
+dnl Too long missing value
+COUNT("STR3"); i8 1; >>COUNT("abcdefghijkl")<<;
+);
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
+dnl Dictionary termination record.
 999; 0;
+s8 "abcd"; s8 "efgh"; s8 "ijkl"; s8 "mnop"; s8 "qrst"; s8 "uvwx";
+s16 "yzABCDEFGHI"; s16 "JKLMNOPQR"; s16 "STUVWXYZ01";
+s16 "23456789abc"; s32 "defghijklmnopqstuvwxyzABC";
 ])
-for variant in \
-       "be 0c36a39ec9118eb4a83f10a9483b5a37" \
-       "le 1d498d60eeb2c88e0479f113fb3ffe4b"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
-  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET FILE='sys-file.sav'.
+DISPLAY DICTIONARY.
 ])
-  AT_CHECK([pspp -O format=csv sys-file.sps], [0], 
-   [warning: `sys-file.sav' near offset 0xc0: Numeric variable VAR1 has invalid print format A8.
+  AT_CHECK([pspp -O format=csv sys-file.sps], [0],
+   ["warning: `sys-file.sav' near offset 0x1f8: Long string missing values record says variable STR1 has 0 missing values, but only 1 to 3 missing values are allowed."
 
-warning: `sys-file.sav' near offset 0xc4: Numeric variable VAR1 has invalid write format AHEX16.
+"warning: `sys-file.sav' near offset 0x201: Long string missing values record says variable STR2 has 4 missing values, but only 1 to 3 missing values are allowed."
 
-warning: `sys-file.sav' near offset 0xe0: String variable STR1 has invalid print format F8.0.
+warning: `sys-file.sav' near offset 0x242: Ignoring long string missing value record for unknown variable Nonexistent.
 
-warning: `sys-file.sav' near offset 0xe4: String variable STR1 has invalid write format E10.1.
+warning: `sys-file.sav' near offset 0x257: Ignoring long string missing value record for numeric variable NUM1.
 
-warning: `sys-file.sav' near offset 0x100: String variable STR2 has invalid print format A8.
+"warning: `sys-file.sav' near offset 0x270: Ignoring long string missing value 0 for variable str3, with width 11, that has bad value width 12."
 
-warning: `sys-file.sav' near offset 0x104: String variable STR2 has invalid write format AHEX4.
+Variable,Description,Position
+num1,Format: F8.0,1
+str1,Format: A9,2
+str2,"Format: A10
+Missing Values: ""abcdefgh""; ""ijklmnop""; ""qrstuvwx""",3
+str3,Format: A11,4
 ])
 done
 AT_CLEANUP
@@ -1639,20 +2146,23 @@ dnl Numeric variable.
 dnl String variable.
 2; 4; 0; 0; 0x010400 *2; s8 "STR1";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 82d30105e46c4896c24f9dcec26c4749" \
-       "le 32e235119be70050eb78bf4186a5a046"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+DISPLAY DICTIONARY.
 ])
-  AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
-   [error: `sys-file.sav': Weighting variable must be numeric (not string variable `STR1').
+  AT_CHECK([pspp -O format=csv sys-file.sps], [0],
+   [warning: `sys-file.sav': Ignoring string variable `STR1' set as weighting variable.
+
+Variable,Description,Position
+num1,Format: F8.0,1
+str1,Format: A4,2
 ])
 done
 AT_CLEANUP
@@ -1670,16 +2180,14 @@ dnl Numeric variable.
 dnl String variable.
 2; 4; 0; 0; 0x010400 *2; s8 "STR1";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be cd9af924ff20bc75834aa2c696254c97" \
-       "le cbe0f2f514f5e95f27644d0b4314bc78"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
@@ -1693,7 +2201,7 @@ AT_KEYWORDS([sack synthetic system file negative])
 AT_DATA([sys-file.sack], [dnl
 dnl File header.
 "$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
-2; 2; 1; >>3<<; -1; 100.0; "01 Jan 11"; "20:53:52"; s64 ""; i8 0 *3;
+2; 3; 1; >>3<<; -1; 100.0; "01 Jan 11"; "20:53:52"; s64 ""; i8 0 *3;
 
 dnl Numeric variable.
 2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
@@ -1702,16 +2210,14 @@ dnl Long string variable.
 2; 9; 0; 0; 0x010900 *2; s8 "STR1";
 (2; -1; 0; 0; 0; 0; s8 "");
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 0c395354df56ea5ff374aafcc535d633" \
-       "le d977f684ea9d4648ed40f8c6dddde9f7"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
@@ -1736,16 +2242,14 @@ dnl Two document records.
 dnl Dictionary termination record.
 999; 0;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Data.
 1.0;
 ])
-for variant in \
-       "be 18aa3348a216ed494efe28285b348fa8" \
-       "le 19b21522bcef1dcc60af328f923f307e"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -1756,41 +2260,6 @@ done
 AT_CLEANUP
 
 
-AT_SETUP([empty document record])
-AT_KEYWORDS([sack synthetic system file negative])
-AT_DATA([sys-file.sack], [dnl
-dnl File header.
-"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
-2; 2; 1; 0; -1; 100.0; "01 Jan 11"; "20:53:52"; s64 ""; i8 0 *3;
-
-dnl Numeric variable, no label or missing values.
-2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
-
-dnl Empty document record.
-6; >>0<<;
-
-dnl Dictionary termination record.
-999; 0;
-
-dnl Data.
-1.0;
-])
-for variant in \
-       "be d8ef29c1b97f9ed226cbd938c9c49b6e" \
-       "le f6a560c5b62e2c472429d85294f36e61"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
-  AT_DATA([sys-file.sps], [dnl
-GET FILE='sys-file.sav'.
-])
-  AT_CHECK([pspp -O format=csv sys-file.sps], [1], [dnl
-error: `sys-file.sav' near offset 0xd4: Number of document lines (0) must be greater than 0 and less than 26843545.
-])
-done
-AT_CLEANUP
-
 AT_SETUP([extension record too large])
 AT_KEYWORDS([sack synthetic system file negative])
 AT_DATA([sys-file.sack], [dnl
@@ -1804,13 +2273,8 @@ dnl Numeric variable, no label or missing values.
 dnl Too-large extension record.
 7; 3; >>0xfffff000 * 2<<;
 ])
-for variant in \
-       "be 5a6679dc41ac349b0b73fc430937c05c" \
-       "le d4769c7f650cfbf160e0386d0d33be04"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -1833,21 +2297,19 @@ dnl Numeric variable, no label or missing values.
 dnl Unknown extension record type.
 7; 30; 1; 1; i8 0;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be ac8395e27677408189bcb8655e56cc0e" \
-       "le e308bfcd51f1e3c28d7379c29271f9d6"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
-  AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
-"warning: `sys-file.sav' near offset 0xd8: Unrecognized record type 7, subtype 30.  Please send a copy of this file, and the syntax which created it to bug-gnu-pspp@gnu.org."
+  AT_CHECK_UNQUOTED([pspp -O format=csv sys-file.sps], [0], [dnl
+"warning: \`sys-file.sav' near offset 0xd8: Unrecognized record type 7, subtype 30.  For help, please send this file to ${PACKAGE_BUGREPORT} and mention that you were using ${PACKAGE_STRING}."
 ])
 done
 AT_CLEANUP
@@ -1865,16 +2327,16 @@ dnl Numeric variable, no label or missing values.
 dnl Machine integer info record.
 7; 3; 4; >>9<<; 1; 2; 3; -1; 1; 1; ENDIAN; 1252; >>1234<<;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 21ec84826886b0a266d1360f8279d769" \
-       "le 15dcba7b2b89b7d8a21ebcc872f515af"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [ignore])
-  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
 "warning: `sys-file.sav' near offset 0xd8: Record type 7, subtype 3 has bad count 9 (expected 8)."
@@ -1895,16 +2357,16 @@ dnl Numeric variable, no label or missing values.
 dnl Machine integer info record.
 7; 3; 4; 8; 1; 2; 3; -1; >>2<<; 1; ENDIAN; 1252;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be d510ed28278649eee997fb6881a4c04f" \
-       "le fbf1eca561a4e243b7ae844ed1677035"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [ignore])
-  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], [dnl
 error: `sys-file.sav' near offset 0xd8: Floating-point representation indicated by system file (2) differs from expected (1).
@@ -1925,28 +2387,24 @@ dnl Numeric variable, no label or missing values.
 dnl Machine integer info record.
 7; 3; 4; 8; 1; 2; 3; -1; 1; 1; >>3<<; 1252;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 855123d16d5e1560b91d60753dad79ad 1" \
-       "le d6626b4fa2e46a91f26c2fc609b2f1e0 2"
-do
+for variant in "be 1" "le 2"; do
   set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+  AT_CHECK([sack --$[1] sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 DISPLAY DICTIONARY.
 ])
   AT_CHECK_UNQUOTED([pspp -O format=csv sys-file.sps], [0], [dnl
-warning: \`sys-file.sav' near offset 0xd8: Integer format indicated by system file (3) differs from expected ($[3]).
+warning: \`sys-file.sav' near offset 0xd8: Integer format indicated by system file (3) differs from expected ($[2]).
 
-Variable,Description,,Position
-num1,Format: F8.0,,1
-,Measure: Scale,,
-,Display Alignment: Right,,
-,Display Width: 8,,
+Variable,Description,Position
+num1,Format: F8.0,1
 ])
 done
 AT_CLEANUP
@@ -1965,16 +2423,16 @@ dnl Numeric variable, no label or missing values.
 dnl Machine floating-point info record.
 7; 4; 8; >>4<<; SYSMIS; HIGHEST; LOWEST; 0.0;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 29c9a173638fbb8bb1efe1176c4d670f" \
-       "le 5cb49eb1084e5b9cd573a54705ff86a7"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [ignore])
-  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
 "warning: `sys-file.sav' near offset 0xd8: Record type 7, subtype 4 has bad count 4 (expected 3)."
@@ -1995,24 +2453,22 @@ dnl Numeric variable, no label or missing values.
 dnl Machine floating-point info record.
 7; 4; 8; 3; >>0.0<<; >>1.0<<; >>2.0<<;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 1e7452d9bb0a2397bf6084a25437514e" \
-       "le f59f9a83f723cde1611869ff6d91d325"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
-  AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
-warning: `sys-file.sav' near offset 0xd8: File specifies unexpected value 0 as SYSMIS.
+  AT_CHECK([pspp -O format=csv sys-file.sps | sed 's/ [(].*/.../'], [0], [dnl
+"warning: `sys-file.sav' near offset 0xd8: File specifies unexpected value 0...
 
-warning: `sys-file.sav' near offset 0xd8: File specifies unexpected value 1 as HIGHEST.
+"warning: `sys-file.sav' near offset 0xd8: File specifies unexpected value 1...
 
-warning: `sys-file.sav' near offset 0xd8: File specifies unexpected value 2 as LOWEST.
+"warning: `sys-file.sav' near offset 0xd8: File specifies unexpected value 2...
 ])
 done
 AT_CLEANUP
@@ -2022,30 +2478,97 @@ AT_KEYWORDS([sack synthetic system file negative multiple response])
 AT_DATA([sys-file.sack], [dnl
 dnl File header.
 "$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
-2; 1; 1; 0; -1; 100.0; "01 Jan 11"; "20:53:52"; s64 ""; i8 0 *3;
+2; dnl Layout code
+16; dnl Nominal case size
+0; dnl Not compressed
+0; dnl Not weighted
+0; dnl No cases.
+100.0; dnl Bias.
+"01 Jan 11"; "20:53:52"; s64 "PSPP synthetic test file";
+i8 0 *3;
 
-dnl Numeric variable, no label or missing values.
-2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
+dnl $a
+2; 0; 0; 0; 0x050800 *2; i8 0x82; i8 0xa0; s6 "";
+2; 0; 0; 0; 0x050800 *2; s8 "B";
+2; 0; 0; 0; 0x050800 *2; s8 "C";
 
-dnl Multiple response sets.
-7; 7; 1; COUNT("a=C");
-7; 19; 1; COUNT("xyz=D");
+dnl $b
+2; 0; 0; 0; 0x050800 *2; s8 "D";
+2; 0; 0; 0; 0x050800 *2; s8 "E";
+2; 0; 0; 0; 0x050800 *2; s8 "F";
+2; 0; 0; 0; 0x050800 *2; s8 "G";
+
+dnl $c
+2; 4; 0; 0; 0x010400 *2; s8 "H";
+2; 4; 0; 0; 0x010400 *2; s8 "I";
+2; 4; 0; 0; 0x010400 *2; s8 "J";
+
+dnl $d
+2; 0; 0; 0; 0x050800 *2; s8 "K";
+2; 0; 0; 0; 0x050800 *2; s8 "L";
+2; 0; 0; 0; 0x050800 *2; s8 "M";
+
+dnl $e
+2; 6; 0; 0; 0x010600 *2; s8 "N";
+2; 6; 0; 0; 0x010600 *2; s8 "O";
+2; 6; 0; 0; 0x010600 *2; s8 "P";
+
+dnl Machine integer info record.
+7; 3; 4; 8; 1; 2; 3; -1; 1; 1; ENDIAN; 932;
+
+7; 7; 1;
+COUNT(
+  "$a=C 10 my mcgroup "; i8 0x82; i8 0xa0; " b c"; i8 10;
+  "b=D2 55 0  g e f d"; i8 10;
+  "$c=D4 "; i8 0x82; i8 0xcd; i8 0x82; i8 0xa2; " 10 mdgroup #2 h i j"; i8 10);
+
+7; 19; 1;
+COUNT(
+  "$d=E 1 2 34 13 third mdgroup k l m"; i8 10;
+  "e=E 11 6 choice 0  n o p"; i8 10);
+
+dnl Character encoding record.
+7; 20; 1; 9; "shift_jis";
 
+dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be 15a9bf44d0cd6186a60629b77079c5a5" \
-       "le 161c99aca5e7a3684df096137e72ce5b"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+MRSETS /DISPLAY NAME=ALL.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
-warning: `sys-file.sav' near offset 0xd8: `a' does not begin with `$' at offset 2 in MRSETS record.
+warning: `sys-file.sav': Invalid multiple response set name `b'.
+
+warning: `sys-file.sav': Invalid multiple response set name `e'.
 
-warning: `sys-file.sav' near offset 0xeb: `xyz' does not begin with `$' at offset 4 in MRSETS record.
+Table: Multiple Response Sets
+Name,Variables,Details
+$a,"あ
+b
+c
+","Multiple category set
+Label: my mcgroup
+"
+$c,"h
+i
+j
+","Multiple dichotomy set
+Label: mdgroup #2
+Label source: Provided by user
+Counted value: `はい'
+Category label source: Variable labels
+"
+$d,"k
+l
+m
+","Multiple dichotomy set
+Label: third mdgroup
+Label source: Provided by user
+Counted value: 34
+Category label source: Value labels of counted value
+"
 ])
 done
 AT_CLEANUP
@@ -2063,15 +2586,13 @@ dnl Numeric variable, no label or missing values.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=Cx");
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be c5e5656ba3d74c3a967850f29ad89970" \
-       "le 29f110509c3d6893a7d21ae2d66aad9d"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
@@ -2093,15 +2614,13 @@ dnl Numeric variable, no label or missing values.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=Ex");
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be a9e1dc63e2524882a5e3d2949a2da9d4" \
-       "le ac709ca1928f65f47a8c8efdd9454b50"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
@@ -2123,19 +2642,17 @@ dnl Numeric variable, no label or missing values.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=E 2");
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be 8c710e85a0a1609d0d03dec80aaf5f94" \
-       "le 4682440b82f22d4bd2ac56afb7fa3152"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
-warning: `sys-file.sav' near offset 0xd8: Unexpected label source value `2' following `E' at offset 7 in MRSETS record.
+warning: `sys-file.sav' near offset 0xd8: Unexpected label source value following `E' at offset 7 in MRSETS record.
 
 warning: `sys-file.sav' near offset 0xd8: Expecting digit at offset 7 in MRSETS record.
 ])
@@ -2155,15 +2672,13 @@ dnl Numeric variable, no label or missing values.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=");
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be fc5e5200d8f56b9a5a713e4a95313a3b" \
-       "le 578a61e8a06b20216612f566c2050879"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
@@ -2185,15 +2700,13 @@ dnl Numeric variable, no label or missing values.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=Dx");
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be 23d0e2f65c7c5f93bbedcc0f2b260c69" \
-       "le c3860c1d80e08842264948056e72c0db"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
@@ -2215,15 +2728,13 @@ dnl Numeric variable, no label or missing values.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=D1x");
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be c9ce001723763e0698878b7e43a887e8" \
-       "le e258a1e4491d5a1d1e7d2272ef631a22"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
@@ -2245,15 +2756,13 @@ dnl Numeric variable, no label or missing values.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=D4 abc");
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be 196d1266fa0e8e315769dcbe3130e3df" \
-       "le 23df1ba7b77a26da8ce1c2cfbcaadce0"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
@@ -2275,15 +2784,13 @@ dnl Numeric variable, no label or missing values.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=D3 abcx");
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be 86314bb0bbdfad48c10af8b8d8106d6e" \
-       "le 2b8d05ff501ca78e51f7110ce88a2364"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
@@ -2305,21 +2812,19 @@ dnl Numeric variable, no label or missing values.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=C 0  NUM1");
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be cea939cf3e6a5f88cb45e8fa871c5e13" \
-       "le 52135afec082f50f37eafacadbb2cd65"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
-warning: `sys-file.sav' near offset 0xd8: Missing new-line parsing variable names at offset 14 in MRSETS record.
+warning: `sys-file.sav' near offset 0xd8: Missing new-line parsing variable names at offset 13 in MRSETS record.
 
-warning: `sys-file.sav' near offset 0xd8: MRSET $a has only 1 variables.
+warning: `sys-file.sav': MRSET $a has only one variable.
 ])
 done
 AT_CLEANUP
@@ -2337,21 +2842,19 @@ dnl Numeric variable, no label or missing values.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=C 0  NUM1 NUM1"; i8 10);
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be 4b1b5fa2dc22cf0afdd35422290b0a29" \
-       "le e4304b57976440a036f25f8dd8ac1404"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
-warning: `sys-file.sav' near offset 0xd8: Duplicate variable name NUM1 at offset 18 in MRSETS record.
+warning: `sys-file.sav': MRSET $a contains duplicate variable name NUM1.
 
-warning: `sys-file.sav' near offset 0xd8: MRSET $a has only 1 variables.
+warning: `sys-file.sav': MRSET $a has only one variable.
 ])
 done
 AT_CLEANUP
@@ -2370,21 +2873,19 @@ dnl Variables.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=C 0  NUM1 STR1"; i8 10);
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be 0f130e967e4097823f85b8711eb20727" \
-       "le 4dc987b4303fd115f1cae9be3963acc9"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
-warning: `sys-file.sav' near offset 0xf8: MRSET $a contains both string and numeric variables.
+warning: `sys-file.sav': MRSET $a contains both string and numeric variables.
 
-warning: `sys-file.sav' near offset 0xf8: MRSET $a has only 1 variables.
+warning: `sys-file.sav': MRSET $a has only one variable.
 ])
 done
 AT_CLEANUP
@@ -2402,24 +2903,22 @@ dnl Numeric variable, no label or missing values.
 dnl Multiple response sets.
 7; 7; 1; COUNT("$a=C 0  NUM1"; i8 10);
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 999; 0;
 ])
-for variant in \
-       "be 3a891e0a467afb3d622629c70f329ada" \
-       "le 432998ec08370510411af4f5207c015e"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
-warning: `sys-file.sav' near offset 0xd8: MRSET $a has only 1 variables.
+warning: `sys-file.sav': MRSET $a has only one variable.
 ])
 done
 AT_CLEANUP
 
-AT_SETUP([only one variable in mrset])
+AT_SETUP([zero or one variable in mrset])
 AT_KEYWORDS([sack synthetic system file negative multiple response])
 AT_DATA([sys-file.sack], [dnl
 dnl File header.
@@ -2430,21 +2929,21 @@ dnl Numeric variable, no label or missing values.
 2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
 
 dnl Multiple response sets.
-7; 7; 1; COUNT("$a=C 0  NUM1"; i8 10);
+7; 7; 1; COUNT("$a=C 0  NUM1"; i8 10; "$b=C 0  "; i8 10);
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
 
 999; 0;
 ])
-for variant in \
-       "be 3a891e0a467afb3d622629c70f329ada" \
-       "le 432998ec08370510411af4f5207c015e"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
-warning: `sys-file.sav' near offset 0xd8: MRSET $a has only 1 variables.
+warning: `sys-file.sav': MRSET $a has only one variable.
+
+warning: `sys-file.sav': MRSET $b has no variables.
 ])
 done
 AT_CLEANUP
@@ -2462,16 +2961,14 @@ dnl Numeric variable, no label or missing values.
 dnl Display parameters record.
 7; 11; >>8<<; 2; 1.0; 1.0;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 7c0f1ae47ae11e37d435c4abaceca226" \
-       "le c29d05a1f8f15ed2201f31f8b787aaa0"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
@@ -2493,16 +2990,14 @@ dnl Numeric variable, no label or missing values.
 dnl Display parameters record.
 7; 11; 4; >>4<<; 1; 1; 2; 2;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 372b57e73c69b05047b60bf6c596e2a1" \
-       "le 2a550d8c5ceae4de7ced77df66e49d0f"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
@@ -2524,16 +3019,14 @@ dnl Numeric variable, no label or missing values.
 dnl Display parameters record.
 7; 11; 4; 2; >>4<<; 0;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be d43e7616b03743339f37292dec6c2204" \
-       "le 821533c29a070cefdd8f07f4e1741d2a"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
@@ -2555,16 +3048,14 @@ dnl Numeric variable, no label or missing values.
 dnl Display parameters record.
 7; 11; 4; 2; 1; >>-1<<;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be c54bc48b5767e2ec3a9ef31df790cb7c" \
-       "le a4d8b14af64221abe83adb417d110e10"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
@@ -2586,16 +3077,14 @@ dnl Numeric variables.
 dnl Long variable names.
 7; 13; 1; COUNT (>>"xyzzy"<<);
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be b67b6e3c1900e5a9cc691055008f0447" \
-       "le 26cc52e601f830f9087a0ea2bd9527df"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -2621,26 +3110,30 @@ dnl Numeric variables.
 dnl Long variable names.
 7; 13; 1; COUNT (
 "LONGVARI=_Invalid"; i8 9;
+"LONGVARI=$Invalid"; i8 9;
+"LONGVARI=#Invalid"; i8 9;
 "LONGVA_A=LongVariableName"; i8 9;
 "LONGVA_B=LONGVARIABLENAME"; i8 9;
 );
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be 9b4b4daa00084d984efb8f889bcb727c" \
-       "le c1b1470d5cd615106e9ae507c9948d8e"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
 warning: `sys-file.sav' near offset 0x138: Long variable mapping from LONGVARI to invalid variable name `_Invalid'.
 
+warning: `sys-file.sav' near offset 0x138: Long variable mapping from LONGVARI to invalid variable name `$Invalid'.
+
+warning: `sys-file.sav' near offset 0x138: Long variable mapping from LONGVARI to invalid variable name `#Invalid'.
+
 warning: `sys-file.sav' near offset 0x138: Duplicate long variable name `LONGVARIABLENAME'.
 ])
 done
@@ -2663,16 +3156,14 @@ dnl Very long string map.
 "NUM1=00256"; i8 0; i8 9;
 );
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be 1309d8d9fb24bcf08952dce9b0f39a94" \
-       "le 94a39de88f8034001b3e467c4cc04d0f"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -2704,16 +3195,14 @@ dnl Very long string map.
 "STR1=00256"; i8 0; i8 9;
 );
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be 1d09a44a46859e6eda28e053dd4b7a8b" \
-       "le 63b9ac0b3953f3e0d5ee248ebe257794"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -2724,9 +3213,6 @@ done
 AT_CLEANUP
 
 AT_SETUP([too many value labels])
-dnl Skip the test if multiplying a small number by INT32_MAX would not
-dnl cause an overflow in size_t.
-AT_SKIP_IF([test $SIZEOF_SIZE_T -gt 4])
 AT_KEYWORDS([sack synthetic system file negative])
 AT_DATA([sys-file.sack], [dnl
 dnl File header.
@@ -2737,13 +3223,8 @@ dnl Numeric variable.
 2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
 3; >>0x7fffffff<<;
 ])
-for variant in \
-       "be 975b2668dde395ddf619977958b37412" \
-       "le 0c14aa278cfc2a4b801f91c14321f03b"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -2766,16 +3247,14 @@ dnl Numeric variable.
 dnl Value label with missing type 4 record.
 3; 1; 1.0; i8 3; s7 "one";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 >>999; 0<<;
 ])
-for variant in \
-       "be 5e1286ac92e3f25ff98492bc5019d608" \
-       "le b33c12f776bbcaa43aa3bfdd4799e0c0"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -2798,13 +3277,8 @@ dnl Numeric variable.
 dnl Value label with no variables.
 3; 1; 1.0; i8 3; s7 "one"; 4; >>0<<;
 ])
-for variant in \
-       "be b0dcec30a936cbcad21c4f3d6fe10fcf" \
-       "le 3b9fdfce5c8c248048232fd6eac018e3"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -2828,15 +3302,14 @@ dnl Long string variable.
 dnl Value label that names long string variable.
 3; 1; s8 "xyzzy"; i8 3; s7 "one"; 4; 1; >>1<<;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 14053a4f09de4c7c4c55281534dd66f4" \
-       "le 8a61cc994c659fd66307d2f0fd64ce20"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [ignore])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -2860,15 +3333,14 @@ dnl Variables.
 dnl Value label that names numeric and string variables.
 3; 1; s8 "xyzzy"; i8 3; s7 "one"; 4; 2; >>1; 2<<;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be 7577c456726a88f52bbef63a8b47bf1a" \
-       "le 3ba5c6af9ad0ae5cc88f9f63e726e414"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [ignore])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -2893,16 +3365,14 @@ dnl Duplicate value labels.
 3; 1; s8 "xyzzy"; i8 3; s7 "one"; 4; 2; >>1; 1<<;
 3; 1; 1.0; i8 3; s7 "one"; 4; 2; >>2; 2<<;
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl End of dictionary.
 999; 0;
 ])
-for variant in \
-       "be ef0f5b2ebddb5a3bfcda16c93a2508f4" \
-       "le c00e27abd9a6c06bf29a108d7220435a"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -2935,23 +3405,21 @@ dnl Variable attributes record.
   "fred('23'"; i8 10
 );
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be 0fc71f5e3cdb6b7f2dd73d011d4885c2" \
-       "le e519b44715400156a2bfe648eb5cff34"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
-warning: `sys-file.sav' near offset 0xdf: Error parsing attribute value Attr1[[1]].
+warning: `sys-file.sav' near offset 0xde: Error parsing attribute value Attr1[[1]].
 
-warning: `sys-file.sav' near offset 0x102: Error parsing attribute value fred[[2]].
+warning: `sys-file.sav' near offset 0x101: Error parsing attribute value fred[[2]].
 ])
 done
 AT_CLEANUP
@@ -2978,16 +3446,14 @@ dnl Variable attributes record.
   "fred(23"; i8 10; ")"
 );
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be 33dba37c2247e63c04bb74a7b472293d" \
-       "le 041025a9d9d9e21a7fabd90ba7341934"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [dnl
 GET FILE='sys-file.sav'.
 ])
@@ -2999,6 +3465,48 @@ warning: `sys-file.sav' near offset 0x106: Attribute value fred[[1]] is not quot
 done
 AT_CLEANUP
 
+AT_SETUP([duplicate attribute name])
+AT_KEYWORDS([sack synthetic system file negative])
+AT_DATA([sys-file.sack], [dnl
+dnl File header.
+"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
+2; 1; 1; 0; -1; 100.0; "01 Jan 11"; "20:53:52"; s64 ""; i8 0 *3;
+
+dnl Variables.
+2; 0; 0; 0; 0x050800 *2; s8 "FIRSTVAR";
+
+dnl Data file attributes record.
+7; 17; 1; COUNT (
+"Attr1('value'"; i8 10; ")";
+"Attr1('value'"; i8 10; ")";
+);
+
+dnl Variable attributes record.
+7; 18; 1; COUNT (
+"FIRSTVAR:";
+  "fred('23'"; i8 10; ")";
+  "fred('23'"; i8 10; ")";
+);
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
+dnl Dictionary termination record.
+999; 0;
+])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [dnl
+GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
+warning: `sys-file.sav' near offset 0xf6: Duplicate attribute Attr1.
+
+warning: `sys-file.sav' near offset 0x125: Duplicate attribute fred.
+])
+done
+AT_CLEANUP
+
 AT_SETUP([bad variable name in long string value label])
 AT_KEYWORDS([sack synthetic system file negative])
 AT_DATA([sys-file.sack], [dnl
@@ -3034,26 +3542,24 @@ COUNT("abcdefghijklmn"); COUNT("value label for `abcdefghijklmn'");
 >>COUNT("abcdefghijklmn"); COUNT("another value label for `abcdefghijklmn'")<<;
 );
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 ])
-for variant in \
-       "be cf2e883dadb00e2c6404c09ea0a4e388" \
-       "le 89c340faf0a7e4a8c834f9687684c091"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
-warning: `sys-file.sav' near offset 0x128: Ignoring long string value record for unknown variable STR9.
+warning: `sys-file.sav' near offset 0x128: Ignoring long string value label record for unknown variable STR9.
 
-warning: `sys-file.sav' near offset 0x164: Ignoring long string value record for numeric variable NUM1.
+warning: `sys-file.sav' near offset 0x164: Ignoring long string value label record for numeric variable NUM1.
 
-warning: `sys-file.sav' near offset 0x193: Ignoring long string value record for variable STR14 because the record's width (9) does not match the variable's width (14).
+warning: `sys-file.sav' near offset 0x193: Ignoring long string value label record for variable STR14 because the record's width (9) does not match the variable's width (14).
 
-"warning: `sys-file.sav' near offset 0x1d4: Ignoring long string value 0 for variable str14, with width 14, that has bad value width 9."
+"warning: `sys-file.sav' near offset 0x1d4: Ignoring long string value label 0 for variable str14, with width 14, that has bad value width 9."
 
 warning: `sys-file.sav' near offset 0x259: Duplicate value label for `abcdefghijklmn' on str14.
 ])
@@ -3071,6 +3577,9 @@ dnl Numeric variables.
 2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
 2; 0; 0; 0; 0x050800 *2; s8 "NUM2";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Data.
 999; 0;
 1.0; 2.0;
@@ -3079,13 +3588,8 @@ dnl Data.
 7.0; 8.0;
 dnl Missing record here.
 ])
-for variant in \
-       "be 6ee097c3934055d0c4564641636f4b5a" \
-       "le ae03fe1b888091d6938b5a436d44ac60"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 LIST.
 ])
@@ -3113,23 +3617,21 @@ dnl Numeric variables.
 2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
 2; 0; 0; 0; 0x050800 *2; s8 "NUM2";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Data.
 999; 0;
 1.0; 2.0;
 3.0;
 ])
-for variant in \
-       "be 4bcc085d7d8f0f09c6a4ba8064ffe61c" \
-       "le 7387fc5edd2740aff92c30ca688d6d9b"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 LIST.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
-   [error: `sys-file.sav' near offset 0x110: File ends in partial case.
+   [error: `sys-file.sav' near offset 0x12c: File ends in partial case.
 
 Table: Data List
 num1,num2
@@ -3149,23 +3651,21 @@ dnl Numeric variables.
 2; 14; 0; 0; 0x010e00 *2; s8 "STR14";
 2; -1; 0; 0; 0; 0; s8 "";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Data.
 999; 0;
 s14 "one data item";
 s8 "partial";
 ])
-for variant in \
-       "be 4a9e84f9e679afb7bb71acd0bb7eab89" \
-       "le 30752606f14ee2deec2854e8e6de4b3b"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 LIST.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
-   [error: `sys-file.sav' near offset 0x10e: Unexpected end of file.
+   [error: `sys-file.sav' near offset 0x12a: Unexpected end of file.
 
 Table: Data List
 str14
@@ -3198,24 +3698,22 @@ dnl String variable.
 2; 15; 0; 0; 0x010f00 *2; s8 "STR15";
 2; -1; 0; 0; 0; 0; s8 "";
 
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
 dnl Dictionary termination record.
 999; 0;
 
 dnl Compressed data.
 i8 1 100 254 253 254 253; i8 255 251; "abcdefgh"; s8 "0123";
 ])
-for variant in \
-       "be ef01b16e2e397d979a3a7d20725ebe6d" \
-       "le 51f7a61e9bc68992469d16c55d6ecd88"
-do
-  set $variant
-  AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
-])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
   AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
 LIST.
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [1], 
-   [error: `sys-file.sav' near offset 0x190: File ends in partial case.
+   [error: `sys-file.sav' near offset 0x1ac: File ends in partial case.
 
 Table: Data List
 num1,num2,str4,str8,str15
@@ -3224,3 +3722,255 @@ num1,num2,str4,str8,str15
 done
 AT_CLEANUP
 
+AT_SETUP([zcompressed data - bad zheader_ofs])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*zheader_ofs.*/>>i64 0<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [1], [error: `sys-file.sav' near offset 0x194: Wrong ZLIB data header offset 0 (expected 0x194).
+])
+done
+AT_CLEANUP
+
+AT_SETUP([zcompressed data - bad ztrailer_ofs])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*ztrailer_ofs.*/>>i64 0<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [1], [error: `sys-file.sav' near offset 0x194: Impossible ZLIB trailer offset 0x0.
+])
+done
+AT_CLEANUP
+
+# ztrailer_len must be a multiple of 24 and at least 48,
+# so a value of 12 is impossible.
+AT_SETUP([zcompressed data - invalid ztrailer_len])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*ztrailer_len.*/>>i64 12<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [1], [error: `sys-file.sav' near offset 0x194: Invalid ZLIB trailer length 12.
+])
+done
+AT_CLEANUP
+
+# ztrailer_ofs + ztrailer_len must be the file size.
+AT_SETUP([zcompressed data - wrong ztrailer_len])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*ztrailer_len.*/>>i64 72<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [1], [warning: `sys-file.sav' near offset 0x1ac: End of ZLIB trailer (0x24d) is not file size (0x235).
+error: `sys-file.sav' near offset 0x21d: 72-byte ZLIB trailer specifies 1 data blocks (expected 2).
+])
+done
+AT_CLEANUP
+
+AT_SETUP([zcompressed data - wrong ztrailer_bias])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*ztrailer_bias.*/>>i64 0<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [1], [error: `sys-file.sav' near offset 0x20d: ZLIB trailer bias (0) differs from file header bias (100.00).
+])
+done
+AT_CLEANUP
+
+AT_SETUP([zcompressed data - wrong ztrailer_zero])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*ztrailer_zero.*/>>i64 100<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [0], [warning: `sys-file.sav' near offset 0x215: ZLIB trailer "zero" field has nonzero value 100.
+])
+done
+AT_CLEANUP
+
+AT_SETUP([zcompressed data - wrong block_size])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*block_size.*/>>0x1000<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [0], [warning: `sys-file.sav' near offset 0x219: ZLIB trailer specifies unexpected 4096-byte block size.
+])
+done
+AT_CLEANUP
+
+AT_SETUP([zcompressed data - wrong n_blocks])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*n_blocks.*/>>2<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [1], [error: `sys-file.sav' near offset 0x21d: 48-byte ZLIB trailer specifies 2 data blocks (expected 1).
+])
+done
+AT_CLEANUP
+
+AT_SETUP([zcompressed data - wrong uncompressed_ofs])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*uncompressed_ofs.*/i64 >>0x177<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [1], [error: `sys-file.sav' near offset 0x21d: ZLIB block descriptor 0 reported uncompressed data offset 0x177, when 0x194 was expected.
+])
+done
+AT_CLEANUP
+
+AT_SETUP([zcompressed data - wrong compressed_ofs])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*@%:@ compressed_ofs.*/i64 >>0x191<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [1], [error: `sys-file.sav' near offset 0x21d: ZLIB block descriptor 0 reported compressed data offset 0x191, when 0x1ac was expected.
+])
+done
+AT_CLEANUP
+
+AT_SETUP([zcompressed data - compressed sizes don't add up])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+AT_DATA([sys-file.sack], [dnl
+dnl File header.
+"$FL3"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file";
+2; dnl Layout code
+6; dnl Nominal case size
+2; dnl zlib compressed
+0; dnl Not weighted
+-1; dnl Unspecified number of cases.
+100.0; dnl Bias.
+"01 Jan 11"; "20:53:52"; s64 "PSPP synthetic test file";
+i8 0 *3;
+
+dnl Numeric variables.
+2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
+2; 0; 0; 0; 0x050800 *2; s8 "NUM2";
+
+dnl String variable.
+2; 4; 0; 0; 0x010400 *2; s8 "STR4";
+2; 8; 0; 0; 0x010800 *2; s8 "STR8";
+2; 15; 0; 0; 0x010f00 *2; s8 "STR15";
+2; -1; 0; 0; 0; 0; s8 "";
+
+dnl Character encoding record.
+7; 20; 1; 12; "windows-1252";
+
+dnl Dictionary termination record.
+999; 0;
+
+dnl ZLIB data header.
+i64 0x194;    # zheader_ofs
+i64 0x1ac;    # ztrailer_ofs
+i64 72;       # ztrailer_len
+
+dnl This is where the ZLIB data blocks would go, but we don't need any to
+dnl provoke this message so we omit them.
+
+dnl ZLIB data trailer fixed header:
+i64 -100;     # ztrailer_bias
+i64 0;        # ztrailer_zero
+0x3ff000;     # block_size
+2;            # n_blocks
+
+dnl ZLIB block descriptor 1:
+i64 0x194;    # uncompressed_ofs
+i64 0x1ac;    # compressed_ofs
+0x100000;     # uncompressed_size
+0x12345;      # compressed_size
+
+dnl ZLIB block descriptor 2:
+i64 0x100194; # uncompressed_ofs
+i64 0x12421;  # compressed_ofs
+0x100000;     # uncompressed_size
+0x12345;      # compressed_size
+])
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [1], [warning: `sys-file.sav' near offset 0x1c4: ZLIB block descriptor 0 reported block size 0x100000, when 0x3ff000 was expected.
+error: `sys-file.sav' near offset 0x1dc: ZLIB block descriptor 1 reported compressed data offset 0x12421, when 0x124f1 was expected.
+])
+done
+AT_CLEANUP
+
+AT_SETUP([zcompressed data - uncompressed_size > block_size])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*uncompressed_size.*/>>0x400000<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [0], [warning: `sys-file.sav' near offset 0x21d: ZLIB block descriptor 0 reported block size 0x400000, when at most 0x3ff000 was expected.
+])
+done
+AT_CLEANUP
+
+AT_SETUP([zcompressed data - compression expands data too much])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*uncompressed_size.*/>>50<<;/
+s/.*@%:@ compressed_size.*/>>100<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [1], [error: `sys-file.sav' near offset 0x21d: ZLIB block descriptor 0 reports compressed size 100 and uncompressed size 50.
+])
+done
+AT_CLEANUP
+
+AT_SETUP([zcompressed data - compressed sizes don't add up])
+AT_KEYWORDS([sack synthetic system file negative zlib])
+zcompressed_sack | sed 's/.*@%:@ compressed_size.*/>>88<<;/' > sys-file.sack
+for variant in be le; do
+  AT_CHECK([sack --$variant sys-file.sack > sys-file.sav])
+  AT_DATA([sys-file.sps], [GET FILE='sys-file.sav'.
+])
+  AT_CHECK([pspp -o pspp.csv sys-file.sps], [1], [error: `sys-file.sav' near offset 0x235: ZLIB trailer is at offset 0x205 but 0x204 would be expected from block descriptors.
+])
+done
+AT_CLEANUP
+
+# CVE-2017-10791.
+# See also https://bugzilla.redhat.com/show_bug.cgi?id=1467004.
+# See also https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=866890.
+# See also https://security-tracker.debian.org/tracker/CVE-2017-10791.
+# Found by team OWL337, using the collAFL fuzzer.
+AT_SETUP([integer overflows in long string missing values])
+AT_KEYWORDS([system file negative])
+cp $top_srcdir/tests/data/CVE-2017-10791.sav .
+AT_CHECK([pspp-convert -O csv -e ASCII CVE-2017-10791.sav -], [0], [], [dnl
+`CVE-2017-10791.sav' near offset 0x217: Extension record subtype 21 ends unexpectedly.
+])
+AT_CLEANUP
+
+# CVE-2017-10792.
+# See also https://bugzilla.redhat.com/show_bug.cgi?id=1467005.
+# See also https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=866890.
+# See also https://security-tracker.debian.org/tracker/CVE-2017-10792.
+# Reported by team OWL337, with fuzzer collAFL.
+AT_SETUP([null dereference skipping bad extension record 18])
+AT_KEYWORDS([system file negative])
+cp $top_srcdir/tests/data/CVE-2017-10792.sav .
+AT_CHECK([pspp-convert -O csv -e ASCII CVE-2017-10792.sav -], [0], [], [dnl
+`CVE-2017-10792.sav' near offset 0x1c0: Record type 7, subtype 18 has bad size 4 (expected 1).
+])
+AT_CLEANUP