more tests
[pspp] / tests / language / stats / ctables.at
index b1a497db3c69ce58de7c78a3d945125371ef3c73..ff60efa8df2ea8ec1bdc068a2719bc586506d617 100644 (file)
@@ -2,13 +2,9 @@ AT_BANNER([CTABLES])
 
 dnl Features not yet tested:
 dnl - Preprocessing to distinguish categorical from scale.
-dnl - Parsing (positive and negative)
-dnl - String variables and values
 dnl - Testing details of missing value handling in summaries.
-dnl - test CLABELS ROWLABELS=LAYER.
 dnl - Test VLABELS.
 dnl - Test WEIGHT and adjustment weights.
-dnl - EMPTY=INCLUDE For string ranges.
 dnl - Summary functions:
 dnl   * Separate summary functions for totals and subtotals.
 dnl   * )CILEVEL in summary label specification
@@ -17,10 +13,8 @@ dnl   * VALUE
 dnl   * LABEL
 dnl   * ascending/descending
 dnl - CATEGORIES:
-dnl   * String values
 dnl   * Date values
 dnl   * THRU (numeric ranges)
-dnl   * THRU (string ranges)
 dnl   * OTHERNM
 dnl - FORMAT:
 dnl   * MINCOLWIDTH, MAXCOLWIDTH, UNITS.
@@ -33,7 +27,6 @@ dnl - TITLES: )DATE, )TIME, )TABLE.
 dnl - Test PCOMPUTE:
 dnl   * PCOMPUTE for more than one kind of summary (e.g. [COUNT, ROWPCT]).
 dnl   * MISSING, OTHERNM
-dnl   * strings and string ranges
 dnl   * multi-dimensional (multiple CCT_POSTCOMPUTE in one cell)
 dnl   * dates
 dnl - PPROPERTIES:
@@ -55,36 +48,634 @@ dnl   * .LCL and .UCL suffixes.
 dnl   * .SE suffixes.
 dnl - CATEGORIES:
 dnl   * Data-dependent sorting.
-dnl
-dnl
-dnl Bug:
-dnl     CTABLES /TABLE=qnd1 [MEAN, MEDIAN] BY qns3a.
-dnl produces a bad median:
-dnl                     Custom Tables
-dnl +--------------------------+-----------------------+
-dnl |                          |      S3a. GENDER:     |
-dnl |                          +-----------+-----------+
-dnl |                          |    Male   |   Female  |
-dnl |                          +----+------+----+------+
-dnl |                          |Mean|Median|Mean|Median|
-dnl +--------------------------+----+------+----+------+
-dnl |D1. AGE: What is your age?|  46|   999|  50|   999|
-dnl +--------------------------+----+------+----+------+
-
-
-
-# AT_SETUP([CTABLES parsing])
-# AT_DATA([ctables.sps],
-# [[DATA LIST LIST NOTABLE /x y z.
-# CTABLES /TABLE=(x + y) > z.
-# CTABLES /TABLE=(x[c] + y[c]) > z.
-# CTABLES /TABLE=(x + y) > z[c].
-# CTABLES /TABLE=x BY y BY z.
-# CTABLES /TABLE=x[c] [ROWPCT.COUNT] > y[c].
-# CTABLES /TABLE=x[c] > y[c] [ROWPCT.COUNT].
-# ]])
-# AT_CHECK([pspp ctables.sps])
-# AT_CLEANUP
+
+AT_SETUP([CTABLES parsing])
+AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .])
+AT_DATA([ctables.sps],
+[[GET 'nhtsa.sav'.
+CTABLES
+    /FORMAT MINCOLWIDTH=10 MAXCOLWIDTH=20 UNITS=POINTS EMPTY=ZERO MISSING="x"
+    /FORMAT MINCOLWIDTH=DEFAULT MAXCOLWIDTH=DEFAULT UNITS=INCHES EMPTY=BLANK MISSING="."
+    /FORMAT UNITS=CM EMPTY="(-)"
+    /VLABELS VARIABLES=qn1 DISPLAY=DEFAULT
+    /VLABELS VARIABLES=qn17 DISPLAY=NAME
+    /VLABELS VARIABLES=qns3a DISPLAY=LABEL
+    /VLABELS VARIABLES=qnd1 DISPLAY=BOTH
+    /VLABELS VARIABLES=qn20 DISPLAY=NONE
+    /MRSETS COUNTDUPLICATES=NO
+    /MRSETS COUNTDUPLICATES=YES
+    /SMISSING VARIABLE
+    /SMISSING LISTWISE
+    /WEIGHT VARIABLE=qns3a
+    /HIDESMALLCOUNTS
+    /HIDESMALLCOUNTS COUNT=10
+    /TABLE qnsa1
+    /SLABELS POSITION=COLUMN VISIBLE=YES
+    /SLABELS VISIBLE=NO POSITION=ROW
+    /SLABELS POSITION=LAYER
+    /CLABELS AUTO
+    /CLABELS ROWLABELS=OPPOSITE
+    /CRITERIA CILEVEL=50
+    /CATEGORIES VARIABLES=qn1 qn17
+                ORDER=A KEY=VALUE MISSING=INCLUDE TOTAL=YES LABEL="xyzzy"
+               POSITION=BEFORE EMPTY=INCLUDE.
+CTABLES /TABLE qnsa1 /CLABELS ROWLABELS=LAYER.
+CTABLES /TABLE qnsa1 /CLABELS COLLABELS=OPPOSITE.
+CTABLES /TABLE qnsa1 /CLABELS COLLABELS=LAYER.
+]])
+AT_CHECK([pspp ctables.sps -O box=unicode -O width=80], [0], [dnl
+         Custom Tables
+Count
+╭───────────────────┬────┬────╮
+│                   │ RDD│CELL│
+├───────────────────┼────┼────┤
+│Sa1. SAMPLE SOURCE:│5392│1607│
+╰───────────────────┴────┴────╯
+
+       Custom Tables
+RDD
+╭───────────────────┬─────╮
+│                   │Count│
+├───────────────────┼─────┤
+│Sa1. SAMPLE SOURCE:│ 5392│
+╰───────────────────┴─────╯
+
+          Custom Tables
+╭────────────────────────┬─────╮
+│                        │Count│
+├────────────────────────┼─────┤
+│Sa1. SAMPLE SOURCE: RDD │ 5392│
+│                    CELL│ 1607│
+╰────────────────────────┴─────╯
+
+          Custom Tables
+╭────────────────────────┬─────╮
+│                        │Count│
+├────────────────────────┼─────┤
+│Sa1. SAMPLE SOURCE: RDD │ 5392│
+│                    CELL│ 1607│
+╰────────────────────────┴─────╯
+])
+AT_CLEANUP
+
+AT_SETUP([CTABLES parsing - negative])
+AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .])
+AT_DATA([ctables.sps],
+[[GET 'nhtsa.sav'.
+CTABLES.
+CTABLES /FORMAT MINCOLWIDTH='foo'.
+CTABLES /TABLE qn1 [**].
+CTABLES /TABLE qn1 [NOTAFUNCTION].
+CTABLES /TABLE (qn1.
+CTABLES /TABLE **.
+CTABLES /TABLE NOTAVAR.
+STRING string(A8).
+CTABLES /TABLE string[S].
+CTABLES /TABLE qn1 [PTILE 101].
+CTABLES /TABLE qn1 [MEAN F0.1].
+CTABLES /TABLE qn1 [MEAN NEGPAREN1.2].
+CTABLES /TABLE qn1 [MEAN NEGPAREN3.4].
+CTABLES /TABLE qn1 [MEAN TOTALS].
+CTABLES /TABLE qn1 [MEAN TOTALS[STDDEV]%].
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [SUBTOTAL=x].
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [LO **].
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [LO THRU x].
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [1 THRU **].
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 ['x' THRU **].
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&**].
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&x].
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 KEY=PTILE(qn1, 101).
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 KEY=MEAN(qn1.
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 KEY=MEAN.
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 MISSING=**.
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 TOTAL=**.
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 LABEL=**.
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 POSITION=**.
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 EMPTY=**.
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 **.
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [1,2,3] **.
+CTABLES /PCOMPUTE &k=EXPR(SUBTOTAL[0]).
+CTABLES /PCOMPUTE &k=EXPR(SUBTOTAL[1**]).
+CTABLES /PCOMPUTE &k=EXPR([LO **]).
+CTABLES /PCOMPUTE &k=EXPR([LO THRU **]).
+CTABLES /PCOMPUTE &k=EXPR([1 THRU **]).
+CTABLES /PCOMPUTE &k=EXPR([1**]).
+CTABLES /PCOMPUTE &k=EXPR((1x)).
+CTABLES /PCOMPUTE **k.
+CTABLES /PCOMPUTE &1.
+CTABLES /PCOMPUTE &k**.
+CTABLES /PCOMPUTE &k=**.
+CTABLES /PCOMPUTE &k=EXPR**.
+CTABLES /PCOMPUTE &k=EXPR(1x).
+CTABLES /PCOMPUTE &k=EXPR(1) /PCOMPUTE &k=EXPR(2).
+CTABLES /PCOMPUTE &k=EXPR(1) /PPROPERTIES &k FORMAT=NOTAFUNCTION.
+CTABLES /PCOMPUTE &k=EXPR(1) /PPROPERTIES &k FORMAT=PTILE **.
+CTABLES /PCOMPUTE &k=EXPR(1) /PPROPERTIES &k LABEL=**.
+CTABLES /PCOMPUTE &k=EXPR(1) /PPROPERTIES &k HIDESOURCECATS=**.
+CTABLES /PCOMPUTE &k=EXPR(1) /PPROPERTIES &k **.
+CTABLES /FORMAT EMPTY=**.
+CTABLES /FORMAT MISSING=**.
+CTABLES /FORMAT **.
+CTABLES /FORMAT MINCOLWIDTH=20 MAXCOLWIDTH=10/.
+CTABLES /VLABELS **.
+CTABLES /VLABELS VARIABLES=NOTAVAR.
+CTABLES /VLABELS VARIABLES=qn1 **.
+CTABLES /VLABELS VARIABLES=qn1 DISPLAY=**.
+CTABLES /MRSETS **.
+CTABLES /MRSETS COUNTDUPLICATES=**.
+CTABLES /SMISSING **.
+CTABLES /WEIGHT **.
+CTABLES /WEIGHT VARIABLE=NOTAVAR.
+CTABLES /HIDESMALLCOUNTS COUNT=1.
+CTABLES /QUUX.
+CTABLES /HIDESMALLCOUNTS COUNT=2.
+CTABLES /TABLE qn1**.
+CTABLES /TABLE qn1 /SLABELS POSITION=**.
+CTABLES /TABLE qn1 /SLABELS VISIBLE=**.
+CTABLES /TABLE qn1 /SLABELS **.
+CTABLES /TABLE qn1 /CLABELS ROWLABELS=**.
+CTABLES /TABLE qn1 /CLABELS COLLABELS=**.
+CTABLES /TABLE qn1 /CLABELS **.
+CTABLES /TABLE qn1 /CRITERIA **.
+CTABLES /TABLE qn1 /CRITERIA CILEVEL=101.
+CTABLES /TABLE qn1 /TITLES **.
+CTABLES /TABLE qn1 /SIGTEST TYPE=**.
+CTABLES /TABLE qn1 /SIGTEST ALPHA=**.
+CTABLES /TABLE qn1 /SIGTEST INCLUDEMRSETS=**.
+CTABLES /TABLE qn1 /SIGTEST CATEGORIES=**.
+CTABLES /TABLE qn1 /SIGTEST **.
+CTABLES /TABLE qn1 /COMPARETEST TYPE=**.
+CTABLES /TABLE qn1 /COMPARETEST ALPHA=**.
+CTABLES /TABLE qn1 /COMPARETEST ALPHA=0,5.
+CTABLES /TABLE qn1 /COMPARETEST ADJUST=**.
+CTABLES /TABLE qn1 /COMPARETEST INCLUDEMRSETS=**.
+CTABLES /TABLE qn1 /COMPARETEST MEANSVARIANCE=**.
+CTABLES /TABLE qn1 /COMPARETEST CATEGORIES=**.
+CTABLES /TABLE qn1 /COMPARETEST MERGE=**.
+CTABLES /TABLE qn1 /COMPARETEST STYLE=**.
+CTABLES /TABLE qn1 /COMPARETEST SHOWSIG=**.
+CTABLES /TABLE qn1 /COMPARETEST **.
+CTABLES /TABLE qn1 / **.
+CTABLES /TABLE qn1 /CLABELS ROWLABELS=OPPOSITE /CLABELS COLLABELS=OPPOSITE.
+CTABLES /TABLE qn20 > qnd1.
+CTABLES /TABLE qn1 [ROWPCT] > qnsa1.
+NUMERIC datetime (DATETIME17.0).
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=datetime ['123'].
+]])
+AT_CHECK([pspp ctables.sps -O box=unicode -O width=80], [1],
+[[ctables.sps:2.8: error: CTABLES: Syntax error at end of command: expecting `/'.
+
+ctables.sps:3.29-3.33: error: CTABLES: Syntax error at `'foo'': Expected non-
+negative number for MINCOLWIDTH.
+
+ctables.sps:4.21-4.22: error: CTABLES: Syntax error at `**': expecting
+identifier.
+
+ctables.sps:5.21-5.32: error: CTABLES: Syntax error at `NOTAFUNCTION': Expecting
+summary function name.
+
+ctables.sps:6.20: error: CTABLES: Syntax error at end of command: expecting `@:}@'.
+
+ctables.sps:7.16-7.17: error: CTABLES: Syntax error at `**': expecting
+identifier.
+
+ctables.sps:8: error: CTABLES: NOTAVAR is not a variable name.
+
+ctables.sps:10.16-10.24: error: CTABLES: Cannot use string variable string as a
+scale variable.
+   10 | CTABLES /TABLE string[S].
+      |                ^~~~~~~~~
+
+ctables.sps:11.27-11.29: error: CTABLES: Syntax error at `101': Expected number
+between 0 and 100 for PTILE.
+
+ctables.sps:12: error: CTABLES: Output format F0.1 specifies width 0, but F
+requires a width between 1 and 40.
+
+ctables.sps:13.26-13.36: error: CTABLES: Syntax error at `NEGPAREN1.2': Output
+format NEGPAREN requires width 2 or greater.
+
+ctables.sps:14.26-14.36: error: CTABLES: Syntax error at `NEGPAREN3.4': Output
+format NEGPAREN requires width greater than decimals.
+
+ctables.sps:15.21-15.24: error: CTABLES: Summary function MEAN applies only to
+scale variables.
+   15 | CTABLES /TABLE qn1 [MEAN TOTALS].
+      |                     ^~~~
+
+ctables.sps:15.16-15.18: note: CTABLES: 'QN1' is not a scale variable.
+   15 | CTABLES /TABLE qn1 [MEAN TOTALS].
+      |                ^~~
+
+ctables.sps:15.32: error: CTABLES: Syntax error at `@:>@': expecting `@<:@'.
+
+ctables.sps:16.21-16.24: error: CTABLES: Summary function MEAN applies only to
+scale variables.
+   16 | CTABLES /TABLE qn1 [MEAN TOTALS[STDDEV]%].
+      |                     ^~~~
+
+ctables.sps:16.16-16.18: note: CTABLES: 'QN1' is not a scale variable.
+   16 | CTABLES /TABLE qn1 [MEAN TOTALS[STDDEV]%].
+      |                ^~~
+
+ctables.sps:16.40: error: CTABLES: Syntax error at `%': expecting `@:>@'.
+
+ctables.sps:17.56: error: CTABLES: Syntax error at `x': expecting string.
+
+ctables.sps:18.50-18.51: error: CTABLES: Syntax error at `**': expecting THRU.
+
+ctables.sps:19.55: error: CTABLES: Syntax error at `x': expecting number.
+
+ctables.sps:20.54-20.55: error: CTABLES: Syntax error at `**': expecting number.
+
+ctables.sps:21.56-21.57: error: CTABLES: Syntax error at `**': expecting string.
+
+ctables.sps:22.48-22.49: error: CTABLES: Syntax error at `**': expecting
+identifier.
+
+ctables.sps:23.47-23.48: error: CTABLES: Unknown postcompute &x.
+   23 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&x].
+      |                                               ^~
+
+ctables.sps:24.61-24.63: error: CTABLES: Syntax error at `101': Expected number
+between 0 and 100 for PTILE.
+
+ctables.sps:25.58: error: CTABLES: Syntax error at end of command: expecting
+`@:}@'.
+
+ctables.sps:26.54: error: CTABLES: Syntax error at end of command: expecting
+`@{:@'.
+
+ctables.sps:27.54-27.55: error: CTABLES: Syntax error at `**': expecting INCLUDE
+or EXCLUDE.
+
+ctables.sps:28.52-28.53: error: CTABLES: Syntax error at `**': expecting YES or
+NO.
+
+ctables.sps:29.52-29.53: error: CTABLES: Syntax error at `**': expecting string.
+
+ctables.sps:30.55-30.56: error: CTABLES: Syntax error at `**': expecting BEFORE
+or AFTER.
+
+ctables.sps:31.52-31.53: error: CTABLES: Syntax error at `**': expecting INCLUDE
+or EXCLUDE.
+
+ctables.sps:32.46-32.47: error: CTABLES: Syntax error at `**': expecting ORDER,
+KEY, MISSING, TOTAL, LABEL, POSITION, or EMPTY.
+
+ctables.sps:33.54-33.55: error: CTABLES: Syntax error at `**': expecting TOTAL,
+LABEL, POSITION, or EMPTY.
+
+ctables.sps:34.36: error: CTABLES: Syntax error at `0': Expected positive
+integer for SUBTOTAL.
+
+ctables.sps:35.37-35.38: error: CTABLES: Syntax error at `**': expecting `@:>@'.
+
+ctables.sps:36.31-36.32: error: CTABLES: Syntax error at `**': expecting THRU.
+
+ctables.sps:37.36-37.37: error: CTABLES: Syntax error at `**': expecting number.
+
+ctables.sps:38.35-38.36: error: CTABLES: Syntax error at `**': expecting number.
+
+ctables.sps:39.29-39.30: error: CTABLES: Syntax error at `**': expecting `@:>@'.
+
+ctables.sps:40.29: error: CTABLES: Syntax error at `x': expecting `@:}@'.
+
+ctables.sps:41.19-41.20: error: CTABLES: Syntax error at `**': expecting &.
+
+ctables.sps:42.20: error: CTABLES: Syntax error at `1': expecting identifier.
+
+ctables.sps:43.21-43.22: error: CTABLES: Syntax error at `**': expecting `='.
+
+ctables.sps:44.22-44.23: error: CTABLES: Syntax error at `**': expecting EXPR.
+
+ctables.sps:45.26-45.27: error: CTABLES: Syntax error at `**': expecting `('.
+
+ctables.sps:46.28: error: CTABLES: Syntax error at `x': expecting `)'.
+
+ctables.sps:47.31-47.49: warning: CTABLES: New definition of &k will override
+the previous definition.
+   47 | CTABLES /PCOMPUTE &k=EXPR(1) /PCOMPUTE &k=EXPR(2).
+      |                               ^~~~~~~~~~~~~~~~~~~
+
+ctables.sps:47.10-47.28: note: CTABLES: This is the previous definition.
+   47 | CTABLES /PCOMPUTE &k=EXPR(1) /PCOMPUTE &k=EXPR(2).
+      |          ^~~~~~~~~~~~~~~~~~~
+
+ctables.sps:47.50: error: CTABLES: Syntax error at end of command: expecting
+`/'.
+
+ctables.sps:48.53-48.64: error: CTABLES: Syntax error at `NOTAFUNCTION':
+Expecting summary function name.
+
+ctables.sps:49.59-49.60: error: CTABLES: Syntax error at `**': Expected number
+between 0 and 100 for PTILE.
+
+ctables.sps:50.52-50.53: error: CTABLES: Syntax error at `**': expecting string.
+
+ctables.sps:51.61-51.62: error: CTABLES: Syntax error at `**': expecting YES or
+NO.
+
+ctables.sps:52.46-52.47: error: CTABLES: Syntax error at `**': expecting LABEL,
+FORMAT, or HIDESOURCECATS.
+
+ctables.sps:53.23-53.24: error: CTABLES: Syntax error at `**': expecting string.
+
+ctables.sps:54.25-54.26: error: CTABLES: Syntax error at `**': expecting string.
+
+ctables.sps:55.17-55.18: error: CTABLES: Syntax error at `**': expecting
+MINCOLWIDTH, MAXCOLWIDTH, UNITS, EMPTY, or MISSING.
+
+ctables.sps:56: error: CTABLES: MINCOLWIDTH must not be greater than
+MAXCOLWIDTH.
+
+ctables.sps:57.18-57.19: error: CTABLES: Syntax error at `**': expecting
+VARIABLES.
+
+ctables.sps:58: error: CTABLES: NOTAVAR is not a variable name.
+
+ctables.sps:59.32-59.33: error: CTABLES: Syntax error at `**': expecting
+DISPLAY.
+
+ctables.sps:60.40-60.41: error: CTABLES: Syntax error at `**': expecting
+DEFAULT, NAME, LABEL, BOTH, or NONE.
+
+ctables.sps:61.17-61.18: error: CTABLES: Syntax error at `**': expecting
+COUNTDUPLICATES.
+
+ctables.sps:62.33-62.34: error: CTABLES: Syntax error at `**': expecting YES or
+NO.
+
+ctables.sps:63.19-63.20: error: CTABLES: Syntax error at `**': expecting
+VARIABLE or LISTWISE.
+
+ctables.sps:64.17-64.18: error: CTABLES: Syntax error at `**': expecting
+VARIABLE.
+
+ctables.sps:65: error: CTABLES: NOTAVAR is not a variable name.
+
+ctables.sps:66.32: error: CTABLES: Syntax error at `1': Expected integer 2 or
+greater for HIDESMALLCOUNTS COUNT.
+
+ctables.sps:67.10-67.13: error: CTABLES: Syntax error at `QUUX': expecting
+FORMAT, VLABELS, MRSETS, SMISSING, PCOMPUTE, PPROPERTIES, WEIGHT,
+HIDESMALLCOUNTS, or TABLE.
+
+ctables.sps:68.33: error: CTABLES: Syntax error at end of command: expecting
+`/'.
+
+ctables.sps:69.19-69.20: error: CTABLES: Syntax error at `**': expecting `/'.
+
+ctables.sps:70.38-70.39: error: CTABLES: Syntax error at `**': expecting COLUMN,
+ROW, or LAYER.
+
+ctables.sps:71.37-71.38: error: CTABLES: Syntax error at `**': expecting YES or
+NO.
+
+ctables.sps:72.29-72.30: error: CTABLES: Syntax error at `**': expecting
+POSITION or VISIBLE.
+
+ctables.sps:73.39-73.40: error: CTABLES: Syntax error at `**': expecting
+OPPOSITE or LAYER.
+
+ctables.sps:74.39-74.40: error: CTABLES: Syntax error at `**': expecting
+OPPOSITE or LAYER.
+
+ctables.sps:75.29-75.30: error: CTABLES: Syntax error at `**': expecting AUTO,
+ROWLABELS, or COLLABELS.
+
+ctables.sps:76.30-76.31: error: CTABLES: Syntax error at `**': expecting
+CILEVEL.
+
+ctables.sps:77.38-77.40: error: CTABLES: Syntax error at `101': Expected number
+in @<:@0,100@:}@ for CILEVEL.
+
+ctables.sps:78.28-78.29: error: CTABLES: Syntax error at `**': expecting
+CAPTION, CORNER, or TITLE.
+
+ctables.sps:79.34-79.35: error: CTABLES: Syntax error at `**': expecting
+CHISQUARE.
+
+ctables.sps:80.35-80.36: error: CTABLES: Syntax error at `**': Expected number
+in @<:@0,1@:}@ for ALPHA.
+
+ctables.sps:81.43-81.44: error: CTABLES: Syntax error at `**': expecting YES or
+NO.
+
+ctables.sps:82.40-82.41: error: CTABLES: Syntax error at `**': expecting
+ALLVISIBLE or SUBTOTALS.
+
+ctables.sps:83.29-83.30: error: CTABLES: Syntax error at `**': expecting TYPE,
+ALPHA, INCLUDEMRSETS, or CATEGORIES.
+
+ctables.sps:84.38-84.39: error: CTABLES: Syntax error at `**': expecting PROP or
+MEAN.
+
+ctables.sps:85.39-85.40: error: CTABLES: Syntax error at `**': Expected number
+in (0,1) for ALPHA.
+
+ctables.sps:86.39: error: CTABLES: Syntax error at `0': Expected number in (0,1)
+for ALPHA.
+
+ctables.sps:87.40-87.41: error: CTABLES: Syntax error at `**': expecting
+BONFERRONI, BH, or NONE.
+
+ctables.sps:88.47-88.48: error: CTABLES: Syntax error at `**': expecting YES or
+NO.
+
+ctables.sps:89.47-89.48: error: CTABLES: Syntax error at `**': expecting ALLCATS
+or TESTEDCATS.
+
+ctables.sps:90.44-90.45: error: CTABLES: Syntax error at `**': expecting
+ALLVISIBLE or SUBTOTALS.
+
+ctables.sps:91.39-91.40: error: CTABLES: Syntax error at `**': expecting YES or
+NO.
+
+ctables.sps:92.39-92.40: error: CTABLES: Syntax error at `**': expecting APA or
+SIMPLE.
+
+ctables.sps:93.41-93.42: error: CTABLES: Syntax error at `**': expecting YES or
+NO.
+
+ctables.sps:94.33-94.34: error: CTABLES: Syntax error at `**': expecting TYPE,
+ALPHA, ADJUST, INCLUDEMRSETS, MEANSVARIANCE, CATEGORIES, MERGE, STYLE, or
+SHOWSIG.
+
+ctables.sps:95.22-95.23: error: CTABLES: Syntax error at `**': expecting TABLE,
+SLABELS, CLABELS, CRITERIA, CATEGORIES, TITLES, SIGTEST, or COMPARETEST.
+
+ctables.sps:96: error: CTABLES: ROWLABELS and COLLABELS may not both be
+specified.
+
+ctables.sps:97.16-97.26: error: CTABLES: Cannot nest scale variables.
+   97 | CTABLES /TABLE qn20 > qnd1.
+      |                ^~~~~~~~~~~
+
+ctables.sps:97.16-97.19: note: CTABLES: This is an outer scale variable.
+   97 | CTABLES /TABLE qn20 > qnd1.
+      |                ^~~~
+
+ctables.sps:97.23-97.26: note: CTABLES: This is an inner scale variable.
+   97 | CTABLES /TABLE qn20 > qnd1.
+      |                       ^~~~
+
+ctables.sps:98.16-98.35: error: CTABLES: Summaries may only be requested for
+categorical variables at the innermost nesting level.
+   98 | CTABLES /TABLE qn1 [ROWPCT] > qnsa1.
+      |                ^~~~~~~~~~~~~~~~~~~~
+
+ctables.sps:98.16-98.18: note: CTABLES: This outer categorical variable has a
+summary.
+   98 | CTABLES /TABLE qn1 [ROWPCT] > qnsa1.
+      |                ^~~
+
+ctables.sps:100.52-100.56: error: CTABLES: Failed to parse category
+specification as format DATETIME: Day (123) must be between 1 and 31..
+  100 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=datetime ['123'].
+      |                                                    ^~~~~
+]])
+AT_CLEANUP
+
+AT_SETUP([CTABLES parsing - more negative])
+AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .])
+AT_DATA([ctables.sps],
+[[GET 'nhtsa.sav'.
+CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&pc].
+CTABLES /PCOMPUTE &pc=EXPR(TOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&pc].
+CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1 [&pc, SUBTOTAL, SUBTOTAL].
+
+STRING string(A8).
+CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 ['string'].
+CTABLES /TABLE string /CATEGORIES VARIABLES=string [1].
+
+CTABLES /TABLE qn1 /CLABELS ROWLABELS=OPPOSITE /CATEGORIES VARIABLES=qn1 KEY=MEAN(qn1).
+
+CTABLES /TABLE qnd1 /CLABELS ROWLABELS=OPPOSITE.
+CTABLES /TABLE qn1 + string /CLABELS ROWLABELS=OPPOSITE.
+CTABLES /TABLE qn1 + qnsa1 /CLABELS ROWLABELS=OPPOSITE.
+CTABLES /TABLE qn105ba + qn105bb /CLABELS ROWLABELS=OPPOSITE /CATEGORIES VARIABLES=qn105ba [1,2,3].
+
+CTABLES /PCOMPUTE &x=EXPR(1**2**3).
+CTABLES /PCOMPUTE &x=EXPR([**]).
+CTABLES /PCOMPUTE &x=EXPR(**).
+
+CTABLES /TABLE.
+
+CTABLES /TABLE qn113 [COUNT] BY qn114 [COUNT] BY qn116 [COUNT]. 
+]])
+AT_CHECK([pspp ctables.sps -O box=unicode -O width=80], [1],
+[[ctables.sps:2.76-2.78: error: CTABLES: Computed category &pc references a
+category not included in the category list.
+    2 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES
+VARIABLES=qn1 [&pc].
+      |
+^~~
+
+ctables.sps:2.28-2.35: note: CTABLES: This is the missing category.
+    2 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES
+VARIABLES=qn1 [&pc].
+      |                            ^~~~~~~~
+
+ctables.sps:2.76-2.79: note: CTABLES: To fix the problem, add subtotals to the
+list of categories here.
+    2 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES
+VARIABLES=qn1 [&pc].
+      |
+^~~~
+
+ctables.sps:3.73-3.75: error: CTABLES: Computed category &pc references a
+category not included in the category list.
+    3 | CTABLES /PCOMPUTE &pc=EXPR(TOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1
+[&pc].
+      |
+^~~
+
+ctables.sps:3.28-3.32: note: CTABLES: This is the missing category.
+    3 | CTABLES /PCOMPUTE &pc=EXPR(TOTAL) /TABLE qn1 /CATEGORIES VARIABLES=qn1
+[&pc].
+      |                            ^~~~~
+
+ctables.sps:3: note: CTABLES: To fix the problem, add TOTAL=YES to the
+variable's CATEGORIES specification.
+
+ctables.sps:4.76-4.99: error: CTABLES: These categories include 2 instances of
+SUBTOTAL or HSUBTOTAL, so references from computed categories must refer to
+subtotals by position, e.g. SUBTOTAL[1].
+    4 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES
+VARIABLES=qn1 [&pc, SUBTOTAL, SUBTOTAL].
+      |
+^~~~~~~~~~~~~~~~~~~~~~~~
+
+ctables.sps:4.28-4.35: note: CTABLES: This is the reference that lacks a
+position.
+    4 | CTABLES /PCOMPUTE &pc=EXPR(SUBTOTAL) /TABLE qn1 /CATEGORIES
+VARIABLES=qn1 [&pc, SUBTOTAL, SUBTOTAL].
+      |                            ^~~~~~~~
+
+ctables.sps:7.47-7.54: error: CTABLES: This category specification may be
+applied only to string variables, but this subcommand tries to apply it to
+numeric variable QN1.
+    7 | CTABLES /TABLE qn1 /CATEGORIES VARIABLES=qn1 ['string'].
+      |                                               ^~~~~~~~
+
+ctables.sps:8.53: error: CTABLES: This category specification may be applied
+only to numeric variables, but this subcommand tries to apply it to string
+variable string.
+    8 | CTABLES /TABLE string /CATEGORIES VARIABLES=string [1].
+      |                                                     ^
+
+ctables.sps:10: error: CTABLES: ROWLABELS=OPPOSITE is not allowed with sorting
+based on a summary function.
+
+ctables.sps:12: error: CTABLES: ROWLABELS=OPPOSITE requires the variables to be
+moved to be categorical, but qnd1 is a scale variable.
+
+ctables.sps:13: error: CTABLES: ROWLABELS=OPPOSITE requires the variables to be
+moved to have the same width, but QN1 has width 0 and string has width 8.
+
+ctables.sps:14: error: CTABLES: ROWLABELS=OPPOSITE requires the variables to be
+moved to have the same value labels, but QN1 and QNSA1 have different value
+labels.
+
+ctables.sps:15: error: CTABLES: ROWLABELS=OPPOSITE requires the variables to be
+moved to have the same category specifications, but QN105BA and QN105BB have
+different category specifications.
+
+ctables.sps:17.27-17.33: warning: CTABLES: The exponentiation operator (`**') is
+left-associative: `a**b**c' equals `(a**b)**c', not `a**(b**c)'.  To disable
+this warning, insert parentheses.
+   17 | CTABLES /PCOMPUTE &x=EXPR(1**2**3).
+      |                           ^~~~~~~
+
+ctables.sps:17.35: error: CTABLES: Syntax error at end of command: expecting
+`/'.
+
+ctables.sps:18.28-18.29: error: CTABLES: Syntax error at `**'.
+
+ctables.sps:19.27-19.28: error: CTABLES: Syntax error at `**'.
+
+ctables.sps:21.15: error: CTABLES: Syntax error at end of command: At least one
+variable must be specified.
+
+ctables.sps:23: error: CTABLES: Summaries may appear only on one axis.
+
+ctables.sps:23.16-23.20: note: CTABLES: This variable on the rows axis has a
+summary.
+   23 | CTABLES /TABLE qn113 [COUNT] BY qn114 [COUNT] BY qn116 [COUNT].
+      |                ^~~~~
+
+ctables.sps:23.33-23.37: note: CTABLES: This variable on the columns axis has a
+summary.
+   23 | CTABLES /TABLE qn113 [COUNT] BY qn114 [COUNT] BY qn116 [COUNT].
+      |                                 ^~~~~
+
+ctables.sps:23.50-23.54: note: CTABLES: This variable on the layers axis has a
+summary.
+   23 | CTABLES /TABLE qn113 [COUNT] BY qn114 [COUNT] BY qn116 [COUNT].
+      |                                                  ^~~~~
+]])
+AT_CLEANUP
 
 AT_SETUP([CTABLES one categorical variable])
 AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .])
@@ -129,6 +720,96 @@ Every day
 ])
 AT_CLEANUP
 
+AT_SETUP([CTABLES one string variable])
+AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .])
+AT_DATA([ctables.sps],
+[[GET 'nhtsa.sav'.
+STRING licensed(A8).
+MISSING VALUES licensed('DontKnow', 'Refused').
+RECODE qnd7a(1='Yes')(2='No')(3='DontKnow')(4='Refused') INTO licensed.
+CTABLES /TABLE licensed.
+CTABLES /TABLE licensed [COUNT, TOTALS[COUNT, VALIDN]] /CATEGORIES VARIABLES=ALL TOTAL=YES MISSING=INCLUDE.
+CTABLES /TABLE licensed /CATEGORIES VARIABLES=licensed ['Yes', 'No'] TOTAL=YES.
+* Notice that the string matching is case-sensitive.
+CTABLES /TABLE licensed /CATEGORIES VARIABLES=licensed ['Yes', 'no'] TOTAL=YES.
+CTABLES /TABLE licensed /CATEGORIES VARIABLES=licensed ['No' THRU 'yes'] TOTAL=YES.
+CTABLES
+    /PCOMPUTE &notyes=EXPR(['No']+['DontKnow']+['Refused'])
+    /PPROPERTIES &notyes LABEL='Not Yes' HIDESOURCECATS=YES
+    /TABLE licensed
+    /CATEGORIES VARIABLES=licensed ['Yes', &notyes, 'No', 'DontKnow', 'Refused'].
+CTABLES
+    /PCOMPUTE &notyes=EXPR(['DontKnow' THRU 'No'] + ['Refused'])
+    /PPROPERTIES &notyes LABEL='Not Yes' HIDESOURCECATS=YES
+    /TABLE licensed
+    /CATEGORIES VARIABLES=licensed ['Yes', &notyes, 'DontKnow' THRU 'No', 'Refused'].
+]])
+AT_CHECK([pspp ctables.sps -O box=unicode -O width=80], [0], [dnl
+    Custom Tables
+╭────────────┬─────╮
+│            │Count│
+├────────────┼─────┤
+│licensed No │  572│
+│         Yes│ 6379│
+╰────────────┴─────╯
+
+          Custom Tables
+╭─────────────────┬─────┬───────╮
+│                 │Count│Valid N│
+├─────────────────┼─────┼───────┤
+│licensed DontKnow│    4│       │
+│         No      │  572│       │
+│         Refused │   44│       │
+│         Yes     │ 6379│       │
+│         Total   │ 6999│   6951│
+╰─────────────────┴─────┴───────╯
+
+     Custom Tables
+╭──────────────┬─────╮
+│              │Count│
+├──────────────┼─────┤
+│licensed Yes  │ 6379│
+│         No   │  572│
+│         Total│ 6951│
+╰──────────────┴─────╯
+
+     Custom Tables
+╭──────────────┬─────╮
+│              │Count│
+├──────────────┼─────┤
+│licensed Yes  │ 6379│
+│         no   │    0│
+│         Total│ 6379│
+╰──────────────┴─────╯
+
+      Custom Tables
+╭────────────────┬─────╮
+│                │Count│
+├────────────────┼─────┤
+│licensed No     │  572│
+│         Refused│   44│
+│         Yes    │ 6379│
+│         Total  │ 6995│
+╰────────────────┴─────╯
+
+      Custom Tables
+╭────────────────┬─────╮
+│                │Count│
+├────────────────┼─────┤
+│licensed Yes    │ 6379│
+│         Not Yes│  620│
+╰────────────────┴─────╯
+
+      Custom Tables
+╭────────────────┬─────╮
+│                │Count│
+├────────────────┼─────┤
+│licensed Yes    │ 6379│
+│         Not Yes│  620│
+╰────────────────┴─────╯
+])
+AT_CLEANUP
+
 AT_SETUP([CTABLES one scale variable])
 AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .])
 AT_DATA([ctables.sps],
@@ -891,10 +1572,31 @@ AT_SETUP([CTABLES CLABELS])
 AT_CHECK([ln $top_srcdir/examples/nhtsa.sav . || cp $top_srcdir/examples/nhtsa.sav .])
 AT_DATA([ctables.sps],
 [[GET 'nhtsa.sav'.
+CTABLES /TABLE AgeGroup BY qns3a.
 CTABLES /TABLE AgeGroup BY qns3a /CLABELS ROWLABELS=OPPOSITE.
 CTABLES /TABLE AgeGroup BY qns3a /CLABELS COLLABELS=OPPOSITE.
+CTABLES /TABLE AgeGroup BY qns3a /CLABELS ROWLABELS=LAYER.
+CTABLES /TABLE AgeGroup BY qns3a /CLABELS COLLABELS=LAYER.
 ]])
-AT_CHECK([pspp ctables.sps -O box=unicode -O width=120], [0], [dnl
+pwd
+AT_CHECK([pspp ctables.sps --table-look="$builddir"/all-layers.stt -O box=unicode -O width=120], [0], [dnl
+             Custom Tables
+╭───────────────────────┬────────────╮
+│                       │S3a. GENDER:│
+│                       ├─────┬──────┤
+│                       │ Male│Female│
+│                       ├─────┼──────┤
+│                       │Count│ Count│
+├───────────────────────┼─────┼──────┤
+│Age group 15 or younger│    0│     0│
+│          16 to 25     │  594│   505│
+│          26 to 35     │  476│   491│
+│          36 to 45     │  489│   548│
+│          46 to 55     │  526│   649│
+│          56 to 65     │  516│   731│
+│          66 or older  │  531│   943│
+╰───────────────────────┴─────┴──────╯
+
                                                       Custom Tables
 ╭───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
 │       │                                                 S3a. GENDER:                                                 │
@@ -937,6 +1639,122 @@ AT_CHECK([pspp ctables.sps -O box=unicode -O width=120], [0], [dnl
 │          66 or older   Male  │         531│
 │                        Female│         943│
 ╰──────────────────────────────┴────────────╯
+
+      Custom Tables
+15 or younger
+╭─────────┬────────────╮
+│         │S3a. GENDER:│
+│         ├─────┬──────┤
+│         │ Male│Female│
+│         ├─────┼──────┤
+│         │Count│ Count│
+├─────────┼─────┼──────┤
+│Age group│    0│     0│
+╰─────────┴─────┴──────╯
+
+      Custom Tables
+16 to 25
+╭─────────┬────────────╮
+│         │S3a. GENDER:│
+│         ├─────┬──────┤
+│         │ Male│Female│
+│         ├─────┼──────┤
+│         │Count│ Count│
+├─────────┼─────┼──────┤
+│Age group│  594│   505│
+╰─────────┴─────┴──────╯
+
+      Custom Tables
+26 to 35
+╭─────────┬────────────╮
+│         │S3a. GENDER:│
+│         ├─────┬──────┤
+│         │ Male│Female│
+│         ├─────┼──────┤
+│         │Count│ Count│
+├─────────┼─────┼──────┤
+│Age group│  476│   491│
+╰─────────┴─────┴──────╯
+
+      Custom Tables
+36 to 45
+╭─────────┬────────────╮
+│         │S3a. GENDER:│
+│         ├─────┬──────┤
+│         │ Male│Female│
+│         ├─────┼──────┤
+│         │Count│ Count│
+├─────────┼─────┼──────┤
+│Age group│  489│   548│
+╰─────────┴─────┴──────╯
+
+      Custom Tables
+46 to 55
+╭─────────┬────────────╮
+│         │S3a. GENDER:│
+│         ├─────┬──────┤
+│         │ Male│Female│
+│         ├─────┼──────┤
+│         │Count│ Count│
+├─────────┼─────┼──────┤
+│Age group│  526│   649│
+╰─────────┴─────┴──────╯
+
+      Custom Tables
+56 to 65
+╭─────────┬────────────╮
+│         │S3a. GENDER:│
+│         ├─────┬──────┤
+│         │ Male│Female│
+│         ├─────┼──────┤
+│         │Count│ Count│
+├─────────┼─────┼──────┤
+│Age group│  516│   731│
+╰─────────┴─────┴──────╯
+
+      Custom Tables
+66 or older
+╭─────────┬────────────╮
+│         │S3a. GENDER:│
+│         ├─────┬──────┤
+│         │ Male│Female│
+│         ├─────┼──────┤
+│         │Count│ Count│
+├─────────┼─────┼──────┤
+│Age group│  531│   943│
+╰─────────┴─────┴──────╯
+
+             Custom Tables
+Male
+╭───────────────────────┬────────────╮
+│                       │S3a. GENDER:│
+│                       ├────────────┤
+│                       │    Count   │
+├───────────────────────┼────────────┤
+│Age group 15 or younger│           0│
+│          16 to 25     │         594│
+│          26 to 35     │         476│
+│          36 to 45     │         489│
+│          46 to 55     │         526│
+│          56 to 65     │         516│
+│          66 or older  │         531│
+╰───────────────────────┴────────────╯
+
+             Custom Tables
+Female
+╭───────────────────────┬────────────╮
+│                       │S3a. GENDER:│
+│                       ├────────────┤
+│                       │    Count   │
+├───────────────────────┼────────────┤
+│Age group 15 or younger│           0│
+│          16 to 25     │         505│
+│          26 to 35     │         491│
+│          36 to 45     │         548│
+│          46 to 55     │         649│
+│          56 to 65     │         731│
+│          66 or older  │         943│
+╰───────────────────────┴────────────╯
 ])
 AT_CLEANUP
 
@@ -984,17 +1802,22 @@ END DATA.
 MISSING VALUES x (1, 2) y (2, 3).
 VARIABLE LEVEL ALL (NOMINAL).
 
-CTABLES /TABLE x[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, TOTALS[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, VALIDN, TOTALN]]
+CTABLES /TABLE x[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN,
+                 TOTALS[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, VALIDN, TOTALN]]
     /CATEGORIES VARIABLES=ALL TOTAL=YES.
-CTABLES /TABLE x[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, TOTALS[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, VALIDN, TOTALN]]
+CTABLES /TABLE x[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN,
+                 TOTALS[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, VALIDN, TOTALN]]
     /CATEGORIES VARIABLES=ALL TOTAL=YES MISSING=INCLUDE.
-CTABLES /TABLE x BY y[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN, TOTALS[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN, VALIDN, TOTALN]]
+CTABLES /TABLE x BY y[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN,
+                      TOTALS[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN, VALIDN, TOTALN]]
     /CATEGORIES VARIABLES=ALL TOTAL=YES
     /SLABELS POSITION=ROW.
-CTABLES /TABLE x BY y[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN, TOTALS[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN, VALIDN, TOTALN]]
+CTABLES /TABLE x BY y[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN,
+                      TOTALS[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN, VALIDN, TOTALN]]
     /CATEGORIES VARIABLES=ALL TOTAL=YES MISSING=INCLUDE
     /SLABELS POSITION=ROW.
-CTABLES /TABLE x BY y[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN, TOTALS[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN, VALIDN, TOTALN]]
+CTABLES /TABLE x BY y[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN,
+                      TOTALS[COUNT, COLPCT, COLPCT.VALIDN, COLPCT.TOTALN, ROWPCT, ROWPCT.VALIDN, ROWPCT.TOTALN, VALIDN, TOTALN]]
     /CATEGORIES VARIABLES=x [1, 2, 3, 4] TOTAL=YES 
     /CATEGORIES VARIABLES=y [1, 3, 4, 5] TOTAL=YES 
     /SLABELS POSITION=ROW.