Remove "Written by Ben Pfaff <blp@gnu.org>" lines everywhere.
[pspp-builds.git] / src / language / data-io / matrix-data.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17    02110-1301, USA. */
18
19 #include <config.h>
20
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <float.h>
24
25 #include <data/case-source.h>
26 #include <data/case.h>
27 #include <data/data-in.h>
28 #include <data/dictionary.h>
29 #include <data/procedure.h>
30 #include <data/variable.h>
31 #include <language/command.h>
32 #include <language/data-io/data-reader.h>
33 #include <language/data-io/file-handle.h>
34 #include <language/lexer/lexer.h>
35 #include <language/lexer/variable-parser.h>
36 #include <libpspp/alloc.h>
37 #include <libpspp/array.h>
38 #include <libpspp/assertion.h>
39 #include <libpspp/compiler.h>
40 #include <libpspp/message.h>
41 #include <libpspp/message.h>
42 #include <libpspp/misc.h>
43 #include <libpspp/pool.h>
44 #include <libpspp/str.h>
45
46 #include "minmax.h"
47 #include "size_max.h"
48
49 #include "gettext.h"
50 #define _(msgid) gettext (msgid)
51
52 /* FIXME: /N subcommand not implemented.  It should be pretty simple,
53    too. */
54
55 /* Different types of variables for MATRIX DATA procedure.  Order is
56    important: these are used for sort keys. */
57 enum
58   {
59     MXD_SPLIT,                  /* SPLIT FILE variables. */
60     MXD_ROWTYPE,                /* ROWTYPE_. */
61     MXD_FACTOR,                 /* Factor variables. */
62     MXD_VARNAME,                /* VARNAME_. */
63     MXD_CONTINUOUS,             /* Continuous variables. */
64
65     MXD_COUNT
66   };
67
68 /* Format type enums. */
69 enum format_type
70   {
71     LIST,
72     FREE
73   };
74
75 /* Matrix section enums. */
76 enum matrix_section
77   {
78     LOWER,
79     UPPER,
80     FULL
81   };
82
83 /* Diagonal inclusion enums. */
84 enum include_diagonal
85   {
86     DIAGONAL,
87     NODIAGONAL
88   };
89
90 /* CONTENTS types. */
91 enum content_type
92   {
93     N_VECTOR,
94     N_SCALAR,
95     N_MATRIX,
96     MEAN,
97     STDDEV,
98     COUNT,
99     MSE,
100     DFE,
101     MAT,
102     COV,
103     CORR,
104     PROX,
105     
106     LPAREN,
107     RPAREN,
108     EOC
109   };
110
111 /* 0=vector, 1=matrix, 2=scalar. */
112 static const int content_type[PROX + 1] = 
113   {
114     0, 2, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1,
115   };
116
117 /* Name of each content type. */
118 static const char *const content_names[PROX + 1] =
119   {
120     "N", "N", "N_MATRIX", "MEAN", "STDDEV", "COUNT", "MSE",
121     "DFE", "MAT", "COV", "CORR", "PROX",
122   };
123
124 /* A MATRIX DATA input program. */
125 struct matrix_data_pgm 
126   {
127     struct pool *container;     /* Arena used for all allocations. */
128     struct dfm_reader *reader;  /* Data file to read. */
129
130     /* Format. */
131     enum format_type fmt;       /* LIST or FREE. */
132     enum matrix_section section;/* LOWER or UPPER or FULL. */
133     enum include_diagonal diag; /* DIAGONAL or NODIAGONAL. */
134
135     int explicit_rowtype;       /* ROWTYPE_ specified explicitly in data? */
136     struct variable *rowtype_, *varname_; /* ROWTYPE_, VARNAME_ variables. */
137     
138     struct variable *single_split; /* Single SPLIT FILE variable. */
139
140     /* Factor variables.  */
141     size_t n_factors;           /* Number of factor variables. */
142     struct variable **factors;  /* Factor variables. */
143     int is_per_factor[PROX + 1]; /* Is there per-factor data? */
144
145     int cells;                  /* Number of cells, or -1 if none. */
146
147     int pop_n;                  /* Population N specified by user. */
148
149     /* CONTENTS subcommand. */
150     int contents[EOC * 3 + 1];  /* Contents. */
151     int n_contents;             /* Number of entries. */
152
153     /* Continuous variables. */
154     int n_continuous;           /* Number of continuous variables. */
155     int first_continuous;       /* Index into dictionary of
156                                    first continuous variable. */
157   };
158
159 /* Auxiliary data attached to MATRIX DATA variables. */
160 struct mxd_var 
161   {
162     int var_type;               /* Variable type. */
163     int sub_type;               /* Subtype. */
164   };
165
166 static const struct case_source_class matrix_data_with_rowtype_source_class;
167 static const struct case_source_class matrix_data_without_rowtype_source_class;
168
169 static int compare_variables_by_mxd_var_type (const void *pa,
170                                              const void *pb);
171 static bool read_matrices_without_rowtype (struct dataset *ds, struct matrix_data_pgm *);
172 static bool read_matrices_with_rowtype (struct dataset *ds, struct matrix_data_pgm *);
173 static int string_to_content_type (const char *, int *);
174 static void attach_mxd_aux (struct variable *, int var_type, int sub_type);
175
176 int
177 cmd_matrix_data (struct lexer *lexer, struct dataset *ds)
178 {
179   struct pool *pool;
180   struct matrix_data_pgm *mx;
181   struct file_handle *fh = fh_inline_file ();
182   bool ok;
183     
184   unsigned seen = 0;
185   
186   discard_variables (ds);
187
188   pool = pool_create ();
189   mx = pool_alloc (pool, sizeof *mx);
190   mx->container = pool;
191   mx->reader = NULL;
192   mx->fmt = LIST;
193   mx->section = LOWER;
194   mx->diag = DIAGONAL;
195   mx->explicit_rowtype = 0;
196   mx->rowtype_ = NULL;
197   mx->varname_ = NULL;
198   mx->single_split = NULL;
199   mx->n_factors = 0;
200   mx->factors = NULL;
201   memset (mx->is_per_factor, 0, sizeof mx->is_per_factor);
202   mx->cells = -1;
203   mx->pop_n = -1;
204   mx->n_contents = 0;
205   mx->n_continuous = 0;
206   mx->first_continuous = 0;
207   while (lex_token (lexer) != '.')
208     {
209       lex_match (lexer, '/');
210
211       if (lex_match_id (lexer, "VARIABLES"))
212         {
213           char **v;
214           size_t nv;
215
216           if (seen & 1)
217             {
218               msg (SE, _("VARIABLES subcommand multiply specified."));
219               goto lossage;
220             }
221           seen |= 1;
222           
223           lex_match (lexer, '=');
224           if (!parse_DATA_LIST_vars (lexer, &v, &nv, PV_NO_DUPLICATE))
225             goto lossage;
226           
227           {
228             size_t i;
229
230             for (i = 0; i < nv; i++)
231               if (!strcasecmp (v[i], "VARNAME_"))
232                 {
233                   msg (SE, _("VARNAME_ cannot be explicitly specified on "
234                              "VARIABLES."));
235                   for (i = 0; i < nv; i++)
236                     free (v[i]);
237                   free (v);
238                   goto lossage;
239                 }
240           }
241           
242           {
243             size_t i;
244
245             for (i = 0; i < nv; i++)
246               {
247                 struct variable *new_var;
248                 
249                 if (strcasecmp (v[i], "ROWTYPE_"))
250                   {
251                     new_var = dict_create_var_assert (dataset_dict (ds), v[i], 0);
252                     attach_mxd_aux (new_var, MXD_CONTINUOUS, i);
253                   }
254                 else
255                   mx->explicit_rowtype = 1;
256                 free (v[i]);
257               }
258             free (v);
259           }
260           
261           mx->rowtype_ = dict_create_var_assert (dataset_dict (ds),
262                                                  "ROWTYPE_", 8);
263           attach_mxd_aux (mx->rowtype_, MXD_ROWTYPE, 0);
264         }
265       else if (lex_match_id (lexer, "FILE"))
266         {
267           lex_match (lexer, '=');
268           fh = fh_parse (lexer, FH_REF_FILE | FH_REF_INLINE);
269           if (fh == NULL)
270             goto lossage;
271         }
272       else if (lex_match_id (lexer, "FORMAT"))
273         {
274           lex_match (lexer, '=');
275
276           while (lex_token (lexer) == T_ID)
277             {
278               if (lex_match_id (lexer, "LIST"))
279                 mx->fmt = LIST;
280               else if (lex_match_id (lexer, "FREE"))
281                 mx->fmt = FREE;
282               else if (lex_match_id (lexer, "LOWER"))
283                 mx->section = LOWER;
284               else if (lex_match_id (lexer, "UPPER"))
285                 mx->section = UPPER;
286               else if (lex_match_id (lexer, "FULL"))
287                 mx->section = FULL;
288               else if (lex_match_id (lexer, "DIAGONAL"))
289                 mx->diag = DIAGONAL;
290               else if (lex_match_id (lexer, "NODIAGONAL"))
291                 mx->diag = NODIAGONAL;
292               else 
293                 {
294                   lex_error (lexer, _("in FORMAT subcommand"));
295                   goto lossage;
296                 }
297             }
298         }
299       else if (lex_match_id (lexer, "SPLIT"))
300         {
301           lex_match (lexer, '=');
302
303           if (seen & 2)
304             {
305               msg (SE, _("SPLIT subcommand multiply specified."));
306               goto lossage;
307             }
308           seen |= 2;
309           
310           if (lex_token (lexer) != T_ID)
311             {
312               lex_error (lexer, _("in SPLIT subcommand"));
313               goto lossage;
314             }
315           
316           if (dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) == NULL
317               && (lex_look_ahead (lexer) == '.' || lex_look_ahead (lexer) == '/'))
318             {
319               if (!strcasecmp (lex_tokid (lexer), "ROWTYPE_")
320                   || !strcasecmp (lex_tokid (lexer), "VARNAME_"))
321                 {
322                   msg (SE, _("Split variable may not be named ROWTYPE_ "
323                              "or VARNAME_."));
324                   goto lossage;
325                 }
326
327               mx->single_split = dict_create_var_assert (dataset_dict (ds),
328                                                          lex_tokid (lexer), 0);
329               attach_mxd_aux (mx->single_split, MXD_CONTINUOUS, 0);
330               lex_get (lexer);
331
332               dict_set_split_vars (dataset_dict (ds), &mx->single_split, 1);
333             }
334           else
335             {
336               struct variable **split;
337               size_t n;
338
339               if (!parse_variables (lexer, dataset_dict (ds), 
340                                     &split, &n, PV_NO_DUPLICATE))
341                 goto lossage;
342
343               dict_set_split_vars (dataset_dict (ds), split, n);
344             }
345           
346           {
347             struct variable *const *split = dict_get_split_vars (dataset_dict (ds));
348             size_t split_cnt = dict_get_split_cnt (dataset_dict (ds));
349             int i;
350
351             for (i = 0; i < split_cnt; i++)
352               {
353                 struct mxd_var *mv = var_get_aux (split[i]);
354                 if (mv->var_type != MXD_CONTINUOUS)
355                   {
356                     msg (SE, _("Split variable %s is already another type."),
357                          lex_tokid (lexer));
358                     goto lossage;
359                   }
360                 var_clear_aux (split[i]);
361                 attach_mxd_aux (split[i], MXD_SPLIT, i);
362               }
363           }
364         }
365       else if (lex_match_id (lexer, "FACTORS"))
366         {
367           lex_match (lexer, '=');
368           
369           if (seen & 4)
370             {
371               msg (SE, _("FACTORS subcommand multiply specified."));
372               goto lossage;
373             }
374           seen |= 4;
375
376           if (!parse_variables (lexer, dataset_dict (ds), &mx->factors, &mx->n_factors,
377                                 PV_NONE))
378             goto lossage;
379           
380           {
381             size_t i;
382             
383             for (i = 0; i < mx->n_factors; i++)
384               {
385                 struct variable *v = mx->factors[i];
386                 struct mxd_var *mv = var_get_aux (v);
387                 if (mv->var_type != MXD_CONTINUOUS)
388                   {
389                     msg (SE, _("Factor variable %s is already another type."),
390                          lex_tokid (lexer));
391                     goto lossage;
392                   }
393                 var_clear_aux (v);
394                 attach_mxd_aux (v, MXD_FACTOR, i);
395               }
396           }
397         }
398       else if (lex_match_id (lexer, "CELLS"))
399         {
400           lex_match (lexer, '=');
401           
402           if (mx->cells != -1)
403             {
404               msg (SE, _("CELLS subcommand multiply specified."));
405               goto lossage;
406             }
407
408           if (!lex_is_integer (lexer) || lex_integer (lexer) < 1)
409             {
410               lex_error (lexer, _("expecting positive integer"));
411               goto lossage;
412             }
413
414           mx->cells = lex_integer (lexer);
415           lex_get (lexer);
416         }
417       else if (lex_match_id (lexer, "N"))
418         {
419           lex_match (lexer, '=');
420
421           if (mx->pop_n != -1)
422             {
423               msg (SE, _("N subcommand multiply specified."));
424               goto lossage;
425             }
426
427           if (!lex_is_integer (lexer) || lex_integer (lexer) < 1)
428             {
429               lex_error (lexer, _("expecting positive integer"));
430               goto lossage;
431             }
432
433           mx->pop_n = lex_integer (lexer);
434           lex_get (lexer);
435         }
436       else if (lex_match_id (lexer, "CONTENTS"))
437         {
438           int inside_parens = 0;
439           unsigned collide = 0;
440           int item;
441           
442           if (seen & 8)
443             {
444               msg (SE, _("CONTENTS subcommand multiply specified."));
445               goto lossage;
446             }
447           seen |= 8;
448
449           lex_match (lexer, '=');
450           
451           {
452             int i;
453             
454             for (i = 0; i <= PROX; i++)
455               mx->is_per_factor[i] = 0;
456           }
457
458           for (;;)
459             {
460               if (lex_match (lexer, '('))
461                 {
462                   if (inside_parens)
463                     {
464                       msg (SE, _("Nested parentheses not allowed."));
465                       goto lossage;
466                     }
467                   inside_parens = 1;
468                   item = LPAREN;
469                 }
470               else if (lex_match (lexer, ')'))
471                 {
472                   if (!inside_parens)
473                     {
474                       msg (SE, _("Mismatched right parenthesis (`(')."));
475                       goto lossage;
476                     }
477                   if (mx->contents[mx->n_contents - 1] == LPAREN)
478                     {
479                       msg (SE, _("Empty parentheses not allowed."));
480                       goto lossage;
481                     }
482                   inside_parens = 0;
483                   item = RPAREN;
484                 }
485               else 
486                 {
487                   int content_type;
488                   int collide_index;
489                   
490                   if (lex_token (lexer) != T_ID)
491                     {
492                       lex_error (lexer, _("in CONTENTS subcommand"));
493                       goto lossage;
494                     }
495
496                   content_type = string_to_content_type (lex_tokid (lexer),
497                                                          &collide_index);
498                   if (content_type == -1)
499                     {
500                       lex_error (lexer, _("in CONTENTS subcommand"));
501                       goto lossage;
502                     }
503                   lex_get (lexer);
504
505                   if (collide & (1 << collide_index))
506                     {
507                       msg (SE, _("Content multiply specified for %s."),
508                            content_names[content_type]);
509                       goto lossage;
510                     }
511                   collide |= (1 << collide_index);
512                   
513                   item = content_type;
514                   mx->is_per_factor[item] = inside_parens;
515                 }
516               mx->contents[mx->n_contents++] = item;
517
518               if (lex_token (lexer) == '/' || lex_token (lexer) == '.')
519                 break;
520             }
521
522           if (inside_parens)
523             {
524               msg (SE, _("Missing right parenthesis."));
525               goto lossage;
526             }
527           mx->contents[mx->n_contents] = EOC;
528         }
529       else 
530         {
531           lex_error (lexer, NULL);
532           goto lossage;
533         }
534     }
535   
536   if (lex_token (lexer) != '.')
537     {
538       lex_error (lexer, _("expecting end of command"));
539       goto lossage;
540     }
541   
542   if (!(seen & 1))
543     {
544       msg (SE, _("Missing VARIABLES subcommand."));
545       goto lossage;
546     }
547   
548   if (!mx->n_contents && !mx->explicit_rowtype)
549     {
550       msg (SW, _("CONTENTS subcommand not specified: assuming file "
551                  "contains only CORR matrix."));
552
553       mx->contents[0] = CORR;
554       mx->contents[1] = EOC;
555       mx->n_contents = 0;
556     }
557
558   if (mx->n_factors && !mx->explicit_rowtype && mx->cells == -1)
559     {
560       msg (SE, _("Missing CELLS subcommand.  CELLS is required "
561                  "when ROWTYPE_ is not given in the data and "
562                  "factors are present."));
563       goto lossage;
564     }
565
566   if (mx->explicit_rowtype && mx->single_split)
567     {
568       msg (SE, _("Split file values must be present in the data when "
569                  "ROWTYPE_ is present."));
570       goto lossage;
571     }
572       
573   /* Create VARNAME_. */
574   mx->varname_ = dict_create_var_assert (dataset_dict (ds), "VARNAME_", 8);
575   attach_mxd_aux (mx->varname_, MXD_VARNAME, 0);
576   
577   /* Sort the dictionary variables into the desired order for the
578      system file output. */
579   {
580     struct variable **v;
581     size_t nv;
582
583     dict_get_vars (dataset_dict (ds), &v, &nv, 0);
584     qsort (v, nv, sizeof *v, compare_variables_by_mxd_var_type);
585     dict_reorder_vars (dataset_dict (ds), v, nv);
586     free (v);
587   }
588
589   /* Set formats. */
590   {
591     static const struct fmt_spec fmt_tab[MXD_COUNT] =
592       {
593         {FMT_F, 4, 0},
594         {FMT_A, 8, 0},
595         {FMT_F, 4, 0},
596         {FMT_A, 8, 0},
597         {FMT_F, 10, 4},
598       };
599     
600     int i;
601
602     mx->first_continuous = -1;
603     for (i = 0; i < dict_get_var_cnt (dataset_dict (ds)); i++)
604       {
605         struct variable *v = dict_get_var (dataset_dict (ds), i);
606         struct mxd_var *mv = var_get_aux (v);
607         int type = mv->var_type;
608         
609         assert (type >= 0 && type < MXD_COUNT);
610         var_set_both_formats (v, &fmt_tab[type]);
611
612         if (type == MXD_CONTINUOUS)
613           mx->n_continuous++;
614         if (mx->first_continuous == -1 && type == MXD_CONTINUOUS)
615           mx->first_continuous = i;
616       }
617   }
618
619   if (mx->n_continuous == 0)
620     {
621       msg (SE, _("No continuous variables specified."));
622       goto lossage;
623     }
624
625   mx->reader = dfm_open_reader (fh, lexer);
626   if (mx->reader == NULL)
627     goto lossage;
628
629   if (mx->explicit_rowtype)
630     ok = read_matrices_with_rowtype (ds, mx);
631   else
632     ok = read_matrices_without_rowtype (ds, mx);
633
634   dfm_close_reader (mx->reader);
635
636   pool_destroy (mx->container);
637
638   return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
639
640 lossage:
641   discard_variables (ds);
642   free (mx->factors);
643   pool_destroy (mx->container);
644   return CMD_CASCADING_FAILURE;
645 }
646
647 /* Look up string S as a content-type name and return the
648    corresponding enumerated value, or -1 if there is no match.  If
649    COLLIDE is non-NULL then *COLLIDE returns a value (suitable for use
650    as a bit-index) which can be used for determining whether a related
651    statistic has already been used. */
652 static int
653 string_to_content_type (const char *s, int *collide)
654 {
655   static const struct
656     {
657       int value;
658       int collide;
659       const char *string;
660     }
661   *tp,
662   tab[] = 
663     {
664       {N_VECTOR, 0, "N_VECTOR"},
665       {N_VECTOR, 0, "N"},
666       {N_SCALAR, 0, "N_SCALAR"},
667       {N_MATRIX, 1, "N_MATRIX"},
668       {MEAN, 2, "MEAN"},
669       {STDDEV, 3, "STDDEV"},
670       {STDDEV, 3, "SD"},
671       {COUNT, 4, "COUNT"},
672       {MSE, 5, "MSE"},
673       {DFE, 6, "DFE"},
674       {MAT, 7, "MAT"},
675       {COV, 8, "COV"},
676       {CORR, 9, "CORR"},
677       {PROX, 10, "PROX"},
678       {-1, -1, NULL},
679     };
680
681   for (tp = tab; tp->value != -1; tp++)
682     if (!strcasecmp (s, tp->string))
683       {
684         if (collide)
685           *collide = tp->collide;
686         
687         return tp->value;
688       }
689   return -1;
690 }
691
692 /* Compare two variables using p.mxd.var_type and p.mxd.sub_type
693    fields. */
694 static int
695 compare_variables_by_mxd_var_type (const void *a_, const void *b_)
696 {
697   struct variable *const *pa = a_;
698   struct variable *const *pb = b_;
699   const struct mxd_var *a = var_get_aux (*pa);
700   const struct mxd_var *b = var_get_aux (*pb);
701   
702   if (a->var_type != b->var_type)
703     return a->var_type > b->var_type ? 1 : -1;
704   else
705     return a->sub_type < b->sub_type ? -1 : a->sub_type > b->sub_type;
706 }
707
708 /* Attaches a struct mxd_var with the specific member values to
709    V. */
710 static void
711 attach_mxd_aux (struct variable *v, int var_type, int sub_type) 
712 {
713   struct mxd_var *mv;
714   
715   assert (var_get_aux (v) == NULL);
716   mv = xmalloc (sizeof *mv);
717   mv->var_type = var_type;
718   mv->sub_type = sub_type;
719   var_attach_aux (v, mv, var_dtor_free);
720 }
721 \f
722 /* Matrix tokenizer. */
723
724 /* Matrix token types. */
725 enum matrix_token_type
726   {
727     MNUM,               /* Number. */
728     MSTR                /* String. */
729   };
730
731 /* A MATRIX DATA parsing token. */
732 struct matrix_token
733   {
734     enum matrix_token_type type; 
735     double number;       /* MNUM: token value. */
736     char *string;        /* MSTR: token string; not null-terminated. */
737     int length;          /* MSTR: tokstr length. */
738   };
739
740 static int mget_token (struct matrix_token *, struct dfm_reader *);
741
742 #if DEBUGGING
743 #define mget_token(TOKEN, READER) mget_token_dump(TOKEN, READER)
744
745 static void
746 mdump_token (const struct matrix_token *token)
747 {
748   switch (token->type)
749     {
750     case MNUM:
751       printf (" #%g", token->number);
752       break;
753     case MSTR:
754       printf (" '%.*s'", token->length, token->string);
755       break;
756     default:
757       NOT_REACHED ();
758     }
759   fflush (stdout);
760 }
761
762 static int
763 mget_token_dump (struct matrix_token *token, struct dfm_reader *reader)
764 {
765   int result = (mget_token) (token, reader);
766   mdump_token (token);
767   return result;
768 }
769 #endif
770
771 /* Return the current position in READER. */
772 static const char *
773 context (struct dfm_reader *reader)
774 {
775   static struct string buf = DS_EMPTY_INITIALIZER;
776
777   ds_clear (&buf);
778   if (dfm_eof (reader))
779     ds_assign_cstr (&buf, "at end of file");
780   else 
781     {
782       struct substring p;
783       
784       p = dfm_get_record (reader);
785       ss_ltrim (&p, ss_cstr (CC_SPACES));
786       if (ss_is_empty (p))
787         ds_assign_cstr (&buf, "at end of line");
788       else
789         ds_put_format (&buf, "before `%.*s'",
790                        (int) ss_cspan (p, ss_cstr (CC_SPACES)), ss_data (p));
791     }
792   
793   return ds_cstr (&buf);
794 }
795
796 /* Is there at least one token left in the data file? */
797 static bool
798 another_token (struct dfm_reader *reader)
799 {
800   for (;;)
801     {
802       struct substring p;
803       size_t space_cnt;
804       
805       if (dfm_eof (reader))
806         return false;
807
808       p = dfm_get_record (reader);
809       space_cnt = ss_span (p, ss_cstr (CC_SPACES));
810       if (space_cnt < ss_length (p)) 
811         {
812           dfm_forward_columns (reader, space_cnt);
813           return true;
814         }
815
816       dfm_forward_record (reader);
817     }
818   NOT_REACHED();
819 }
820
821 /* Parse a MATRIX DATA token from READER into TOKEN. */
822 static int
823 (mget_token) (struct matrix_token *token, struct dfm_reader *reader)
824 {
825   struct substring line, p;
826   struct substring s;
827   int c;
828
829   if (!another_token (reader))
830     return 0;
831
832   line = p = dfm_get_record (reader);
833
834   /* Three types of fields: quoted with ', quoted with ", unquoted. */
835   c = ss_first (p);
836   if (c == '\'' || c == '"')
837     {
838       ss_get_char (&p);
839       if (!ss_get_until (&p, c, &s))
840         msg (SW, _("Scope of string exceeds line."));
841     }
842   else
843     {
844       bool is_num = isdigit (c) || c == '.';
845       const char *start = ss_data (p);
846       
847       for (;;) 
848         {
849           c = ss_first (p);
850           if (strchr (CC_SPACES ",-+", c) != NULL)
851             break;
852
853           if (isdigit (c))
854             is_num = true;
855           if (strchr ("deDE", c) && strchr ("+-", ss_at (p, 1)))
856             {
857               is_num = true;
858               ss_advance (&p, 2);
859             }
860           else
861             ss_advance (&p, 1);
862         }
863       s = ss_buffer (start, ss_data (p) - start);
864
865       if (is_num)
866         data_in (s, FMT_F, 0,
867                  dfm_get_column (reader, ss_data (s)),
868                  (union value *) &token->number, 0);
869       else
870         token->type = MSTR;
871     }
872   token->string = ss_data (s);
873   token->length = ss_length (s);
874   
875   dfm_reread_record (reader, dfm_get_column (reader, ss_end (s)));
876     
877   return 1;
878 }
879
880 /* Forcibly skip the end of a line for content type CONTENT in
881    READER. */
882 static int
883 force_eol (struct dfm_reader *reader, const char *content)
884 {
885   struct substring p;
886
887   if (dfm_eof (reader))
888     return 0;
889
890   p = dfm_get_record (reader);
891   if (ss_span (p, ss_cstr (CC_SPACES)) != ss_length (p))
892     {
893       msg (SE, _("End of line expected %s while reading %s."),
894            context (reader), content);
895       return 0;
896     }
897   
898   dfm_forward_record (reader);
899   return 1;
900 }
901 \f
902 /* Back end, omitting ROWTYPE_. */
903
904 struct nr_aux_data 
905   {
906     const struct dictionary *dict; /* The dictionary */
907     struct matrix_data_pgm *mx; /* MATRIX DATA program. */
908     double ***data;             /* MATRIX DATA data. */
909     double *factor_values;      /* Factor values. */
910     int max_cell_idx;           /* Max-numbered cell that we have
911                                    read so far, plus one. */
912     double *split_values;       /* SPLIT FILE variable values. */
913   };
914
915 static bool nr_read_splits (struct nr_aux_data *, int compare);
916 static bool nr_read_factors (struct nr_aux_data *, int cell);
917 static bool nr_output_data (struct nr_aux_data *, struct ccase *,
918                             write_case_func *, write_case_data);
919 static bool matrix_data_read_without_rowtype (struct case_source *source,
920                                               struct ccase *,
921                                               write_case_func *,
922                                               write_case_data);
923
924 /* Read from the data file and write it to the active file.
925    Returns true if successful, false if an I/O error occurred. */
926 static bool
927 read_matrices_without_rowtype (struct dataset *ds, struct matrix_data_pgm *mx)
928 {
929   struct nr_aux_data nr;
930   bool ok;
931   
932   if (mx->cells == -1)
933     mx->cells = 1;
934
935   nr.mx = mx;
936   nr.dict = dataset_dict (ds);
937   nr.data = NULL;
938   nr.factor_values = xnmalloc (mx->n_factors * mx->cells,
939                                sizeof *nr.factor_values);
940   nr.max_cell_idx = 0;
941   nr.split_values = xnmalloc (dict_get_split_cnt (dataset_dict (ds)),
942                               sizeof *nr.split_values);
943
944   proc_set_source (ds, create_case_source (
945                      &matrix_data_without_rowtype_source_class, &nr));
946   
947   ok = procedure (ds, NULL, NULL);
948
949   free (nr.split_values);
950   free (nr.factor_values);
951
952   return ok;
953 }
954
955 /* Mirror data across the diagonal of matrix CP which contains
956    CONTENT type data. */
957 static void
958 fill_matrix (struct matrix_data_pgm *mx, int content, double *cp)
959 {
960   int type = content_type[content];
961
962   if (type == 1 && mx->section != FULL)
963     {
964       if (mx->diag == NODIAGONAL)
965         {
966           const double fill = content == CORR ? 1.0 : SYSMIS;
967           int i;
968
969           for (i = 0; i < mx->n_continuous; i++)
970             cp[i * (1 + mx->n_continuous)] = fill;
971         }
972       
973       {
974         int c, r;
975         
976         if (mx->section == LOWER)
977           {
978             int n_lines = mx->n_continuous;
979             if (mx->section != FULL && mx->diag == NODIAGONAL)
980               n_lines--;
981             
982             for (r = 1; r < n_lines; r++)
983               for (c = 0; c < r; c++)
984                 cp[r + c * mx->n_continuous] = cp[c + r * mx->n_continuous];
985           }
986         else 
987           {
988             assert (mx->section == UPPER);
989             for (r = 1; r < mx->n_continuous; r++)
990               for (c = 0; c < r; c++)
991                 cp[c + r * mx->n_continuous] = cp[r + c * mx->n_continuous];
992           }
993       }
994     }
995   else if (type == 2)
996     {
997       int c;
998
999       for (c = 1; c < mx->n_continuous; c++)
1000         cp[c] = cp[0];
1001     }
1002 }
1003
1004 /* Read data lines for content type CONTENT from the data file.
1005    If PER_FACTOR is nonzero, then factor information is read from
1006    the data file.  Data is for cell number CELL. */
1007 static int
1008 nr_read_data_lines (struct nr_aux_data *nr,
1009                     int per_factor, int cell, int content, int compare)
1010 {
1011   struct matrix_data_pgm *mx = nr->mx;
1012   const int type = content_type[content];               /* Content type. */
1013   int n_lines; /* Number of lines to parse from data file for this type. */
1014   double *cp;                   /* Current position in vector or matrix. */
1015   int i;
1016
1017   if (type != 1)
1018     n_lines = 1;
1019   else
1020     {
1021       n_lines = mx->n_continuous;
1022       if (mx->section != FULL && mx->diag == NODIAGONAL)
1023         n_lines--;
1024     }
1025
1026   cp = nr->data[content][cell];
1027   if (type == 1 && mx->section == LOWER && mx->diag == NODIAGONAL)
1028     cp += mx->n_continuous;
1029
1030   for (i = 0; i < n_lines; i++)
1031     {
1032       int n_cols;
1033       
1034       if (!nr_read_splits (nr, 1))
1035         return 0;
1036       if (per_factor && !nr_read_factors (nr, cell))
1037         return 0;
1038       compare = 1;
1039
1040       switch (type)
1041         {
1042         case 0:
1043           n_cols = mx->n_continuous;
1044           break;
1045         case 1:
1046           switch (mx->section)
1047             {
1048             case LOWER:
1049               n_cols = i + 1;
1050               break;
1051             case UPPER:
1052               cp += i;
1053               n_cols = mx->n_continuous - i;
1054               if (mx->diag == NODIAGONAL)
1055                 {
1056                   n_cols--;
1057                   cp++;
1058                 }
1059               break;
1060             case FULL:
1061               n_cols = mx->n_continuous;
1062               break;
1063             default:
1064               NOT_REACHED ();
1065             }
1066           break;
1067         case 2:
1068           n_cols = 1;
1069           break;
1070         default:
1071           NOT_REACHED ();
1072         }
1073
1074       {
1075         int j;
1076         
1077         for (j = 0; j < n_cols; j++)
1078           {
1079             struct matrix_token token;
1080             if (!mget_token (&token, mx->reader))
1081               return 0;
1082             if (token.type != MNUM)
1083               {
1084                 msg (SE, _("expecting value for %s %s"),
1085                      var_get_name (dict_get_var (nr->dict, j)),
1086                      context (mx->reader));
1087                 return 0;
1088               }
1089
1090             *cp++ = token.number;
1091           }
1092         if (mx->fmt != FREE
1093             && !force_eol (mx->reader, content_names[content]))
1094           return 0;
1095       }
1096
1097       if (mx->section == LOWER)
1098         cp += mx->n_continuous - n_cols;
1099     }
1100
1101   fill_matrix (mx, content, nr->data[content][cell]);
1102
1103   return 1;
1104 }
1105
1106 /* When ROWTYPE_ does not appear in the data, reads the matrices and
1107    writes them to the output file.
1108    Returns true if successful, false if an I/O error occurred. */
1109 static bool
1110 matrix_data_read_without_rowtype (struct case_source *source,
1111                                   struct ccase *c,
1112                                   write_case_func *write_case,
1113                                   write_case_data wc_data)
1114 {
1115   struct nr_aux_data *nr = source->aux;
1116   struct matrix_data_pgm *mx = nr->mx;
1117
1118   {
1119     int *cp;
1120
1121     nr->data = pool_nalloc (mx->container, PROX + 1, sizeof *nr->data);
1122     
1123     {
1124       int i;
1125
1126       for (i = 0; i <= PROX; i++)
1127         nr->data[i] = NULL;
1128     }
1129     
1130     for (cp = mx->contents; *cp != EOC; cp++)
1131       if (*cp != LPAREN && *cp != RPAREN)
1132         {
1133           int per_factor = mx->is_per_factor[*cp];
1134           int n_entries;
1135           
1136           n_entries = mx->n_continuous;
1137           if (content_type[*cp] == 1)
1138             n_entries *= mx->n_continuous;
1139           
1140           {
1141             int n_vectors = per_factor ? mx->cells : 1;
1142             int i;
1143             
1144             nr->data[*cp] = pool_nalloc (mx->container,
1145                                          n_vectors, sizeof **nr->data);
1146             
1147             for (i = 0; i < n_vectors; i++)
1148               nr->data[*cp][i] = pool_nalloc (mx->container,
1149                                               n_entries, sizeof ***nr->data);
1150           }
1151         }
1152   }
1153   
1154   for (;;)
1155     {
1156       int *bp, *ep, *np;
1157       
1158       if (!nr_read_splits (nr, 0))
1159         return true;
1160       
1161       for (bp = mx->contents; *bp != EOC; bp = np)
1162         {
1163           int per_factor;
1164
1165           /* Trap the CONTENTS that we should parse in this pass
1166              between bp and ep.  Set np to the starting bp for next
1167              iteration. */
1168           if (*bp == LPAREN)
1169             {
1170               ep = ++bp;
1171               while (*ep != RPAREN)
1172                 ep++;
1173               np = &ep[1];
1174               per_factor = 1;
1175             }
1176           else
1177             {
1178               ep = &bp[1];
1179               while (*ep != EOC && *ep != LPAREN)
1180                 ep++;
1181               np = ep;
1182               per_factor = 0;
1183             }
1184           
1185           {
1186             int i;
1187               
1188             for (i = 0; i < (per_factor ? mx->cells : 1); i++)
1189               {
1190                 int *cp;
1191
1192                 for (cp = bp; cp < ep; cp++) 
1193                   if (!nr_read_data_lines (nr, per_factor, i, *cp, cp != bp))
1194                     return true;
1195               }
1196           }
1197         }
1198
1199       if (!nr_output_data (nr, c, write_case, wc_data))
1200         return false;
1201
1202       if (dict_get_split_cnt (nr->dict) == 0
1203           || !another_token (mx->reader))
1204         return true;
1205     }
1206 }
1207
1208 /* Read the split file variables.  If COMPARE is 1, compares the
1209    values read to the last values read and returns true if they're equal,
1210    false otherwise. */
1211 static bool
1212 nr_read_splits (struct nr_aux_data *nr, int compare)
1213 {
1214   struct matrix_data_pgm *mx = nr->mx;
1215   static int just_read = 0; /* FIXME: WTF? */
1216   size_t split_cnt;
1217   size_t i;
1218
1219   if (compare && just_read)
1220     {
1221       just_read = 0;
1222       return true;
1223     }
1224   
1225   if (dict_get_split_vars (nr->dict) == NULL)
1226     return true;
1227
1228   if (mx->single_split)
1229     {
1230       if (!compare) 
1231         {
1232           struct mxd_var *mv = var_get_aux (dict_get_split_vars (nr->dict)[0]);
1233           nr->split_values[0] = ++mv->sub_type; 
1234         }
1235       return true;
1236     }
1237
1238   if (!compare)
1239     just_read = 1;
1240
1241   split_cnt = dict_get_split_cnt (nr->dict);
1242   for (i = 0; i < split_cnt; i++) 
1243     {
1244       struct matrix_token token;
1245       if (!mget_token (&token, mx->reader))
1246         return false;
1247       if (token.type != MNUM)
1248         {
1249           msg (SE, _("Syntax error expecting SPLIT FILE value %s."),
1250                context (mx->reader));
1251           return false;
1252         }
1253
1254       if (!compare)
1255         nr->split_values[i] = token.number;
1256       else if (nr->split_values[i] != token.number)
1257         {
1258           msg (SE, _("Expecting value %g for %s."),
1259                nr->split_values[i],
1260                var_get_name (dict_get_split_vars (nr->dict)[i]));
1261           return false;
1262         }
1263     }
1264
1265   return true;
1266 }
1267
1268 /* Read the factors for cell CELL.  If COMPARE is 1, compares the
1269    values read to the last values read and returns true if they're equal,
1270    false otherwise. */
1271 static bool
1272 nr_read_factors (struct nr_aux_data *nr, int cell)
1273 {
1274   struct matrix_data_pgm *mx = nr->mx;
1275   bool compare;
1276   
1277   if (mx->n_factors == 0)
1278     return true;
1279
1280   assert (nr->max_cell_idx >= cell);
1281   if (cell != nr->max_cell_idx)
1282     compare = true;
1283   else
1284     {
1285       compare = false;
1286       nr->max_cell_idx++;
1287     }
1288       
1289   {
1290     size_t i;
1291     
1292     for (i = 0; i < mx->n_factors; i++)
1293       {
1294         struct matrix_token token;
1295         if (!mget_token (&token, mx->reader))
1296           return false;
1297         if (token.type != MNUM)
1298           {
1299             msg (SE, _("Syntax error expecting factor value %s."),
1300                  context (mx->reader));
1301             return false;
1302           }
1303         
1304         if (!compare)
1305           nr->factor_values[i + mx->n_factors * cell] = token.number;
1306         else if (nr->factor_values[i + mx->n_factors * cell] != token.number)
1307           {
1308             msg (SE, _("Syntax error expecting value %g for %s %s."),
1309                  nr->factor_values[i + mx->n_factors * cell],
1310                  var_get_name (mx->factors[i]), context (mx->reader));
1311             return false;
1312           }
1313       }
1314   }
1315
1316   return true;
1317 }
1318
1319 /* Write the contents of a cell having content type CONTENT and data
1320    CP to the active file.
1321    Returns true if successful, false if an I/O error occurred. */
1322 static bool
1323 dump_cell_content (const struct dictionary *dict, 
1324                    struct matrix_data_pgm *mx, int content, double *cp,
1325                    struct ccase *c,
1326                    write_case_func *write_case, write_case_data wc_data)
1327 {
1328   int type = content_type[content];
1329
1330   {
1331     buf_copy_str_rpad (case_data_rw (c, mx->rowtype_)->s, 8,
1332                        content_names[content]);
1333     
1334     if (type != 1)
1335       memset (case_data_rw (c, mx->varname_)->s, ' ', 8);
1336   }
1337
1338   {
1339     int n_lines = (type == 1) ? mx->n_continuous : 1;
1340     int i;
1341                 
1342     for (i = 0; i < n_lines; i++)
1343       {
1344         int j;
1345
1346         for (j = 0; j < mx->n_continuous; j++)
1347           {
1348             struct variable *v = dict_get_var (dict, mx->first_continuous + j);
1349             case_data_rw (c, v)->f = *cp;
1350             cp++;
1351           }
1352         if (type == 1)
1353           buf_copy_str_rpad (case_data_rw (c, mx->varname_)->s, 8,
1354                              var_get_name (
1355                                dict_get_var (dict, mx->first_continuous + i)));
1356         if (!write_case (wc_data))
1357           return false;
1358       }
1359   }
1360   return true;
1361 }
1362
1363 /* Finally dump out everything from nr_data[] to the output file. */
1364 static bool
1365 nr_output_data (struct nr_aux_data *nr, struct ccase *c,
1366                 write_case_func *write_case, write_case_data wc_data)
1367 {
1368   struct matrix_data_pgm *mx = nr->mx;
1369   
1370   {
1371     struct variable *const *split;
1372     size_t split_cnt;
1373     size_t i;
1374
1375     split_cnt = dict_get_split_cnt (nr->dict);
1376     split = dict_get_split_vars (nr->dict);
1377     for (i = 0; i < split_cnt; i++)
1378       case_data_rw (c, split[i])->f = nr->split_values[i];
1379   }
1380
1381   if (mx->n_factors)
1382     {
1383       int cell;
1384
1385       for (cell = 0; cell < mx->cells; cell++)
1386         {
1387           {
1388             size_t factor;
1389
1390             for (factor = 0; factor < mx->n_factors; factor++)
1391               case_data_rw (c, mx->factors[factor])->f
1392                 = nr->factor_values[factor + cell * mx->n_factors];
1393           }
1394           
1395           {
1396             int content;
1397             
1398             for (content = 0; content <= PROX; content++)
1399               if (mx->is_per_factor[content])
1400                 {
1401                   assert (nr->data[content] != NULL
1402                           && nr->data[content][cell] != NULL);
1403
1404                   if (!dump_cell_content (nr->dict, mx, 
1405                                           content, nr->data[content][cell],
1406                                           c, write_case, wc_data))
1407                     return false;
1408                 }
1409           }
1410         }
1411     }
1412
1413   {
1414     int content;
1415     
1416     {
1417       size_t factor;
1418
1419       for (factor = 0; factor < mx->n_factors; factor++)
1420         case_data_rw (c, mx->factors[factor])->f = SYSMIS;
1421     }
1422     
1423     for (content = 0; content <= PROX; content++)
1424       if (!mx->is_per_factor[content] && nr->data[content] != NULL) 
1425         {
1426           if (!dump_cell_content (nr->dict, mx, content, nr->data[content][0],
1427                                   c, write_case, wc_data))
1428             return false; 
1429         }
1430   }
1431
1432   return true;
1433 }
1434 \f
1435 /* Back end, with ROWTYPE_. */
1436
1437 /* All the data for one set of factor values. */
1438 struct factor_data
1439   {
1440     double *factors;
1441     int n_rows[PROX + 1];
1442     double *data[PROX + 1];
1443     struct factor_data *next;
1444   };
1445
1446 /* With ROWTYPE_ auxiliary data. */
1447 struct wr_aux_data 
1448   {
1449     const struct dictionary *dict;            /* The dictionary */
1450     struct matrix_data_pgm *mx;         /* MATRIX DATA program. */
1451     int content;                        /* Type of current row. */
1452     double *split_values;               /* SPLIT FILE variable values. */
1453     struct factor_data *data;           /* All the data. */
1454     struct factor_data *current;        /* Current factor. */
1455   };
1456
1457 static bool wr_read_splits (struct wr_aux_data *, struct ccase *,
1458                            write_case_func *, write_case_data);
1459 static bool wr_output_data (struct wr_aux_data *, struct ccase *,
1460                            write_case_func *, write_case_data);
1461 static bool wr_read_rowtype (struct wr_aux_data *, 
1462                             const struct matrix_token *, struct dfm_reader *);
1463 static bool wr_read_factors (struct wr_aux_data *);
1464 static bool wr_read_indeps (struct wr_aux_data *);
1465 static bool matrix_data_read_with_rowtype (struct case_source *,
1466                                            struct ccase *,
1467                                            write_case_func *,
1468                                            write_case_data);
1469
1470 /* When ROWTYPE_ appears in the data, reads the matrices and writes
1471    them to the output file.
1472    Returns true if successful, false if an I/O error occurred. */
1473 static bool
1474 read_matrices_with_rowtype (struct dataset *ds, struct matrix_data_pgm *mx)
1475 {
1476   struct wr_aux_data wr;
1477   bool ok;
1478
1479   wr.mx = mx;
1480   wr.content = -1;
1481   wr.split_values = NULL;
1482   wr.data = NULL;
1483   wr.current = NULL;
1484   wr.dict = dataset_dict (ds);
1485   mx->cells = 0;
1486
1487   proc_set_source (ds, 
1488                    create_case_source (&matrix_data_with_rowtype_source_class,
1489                                        &wr));
1490   ok = procedure (ds, NULL, NULL);
1491
1492   free (wr.split_values);
1493   return ok;
1494 }
1495
1496 /* Read from the data file and write it to the active file.
1497    Returns true if successful, false if an I/O error occurred. */
1498 static bool
1499 matrix_data_read_with_rowtype (struct case_source *source,
1500                                struct ccase *c,
1501                                write_case_func *write_case,
1502                                write_case_data wc_data)
1503 {
1504   struct wr_aux_data *wr = source->aux;
1505   struct matrix_data_pgm *mx = wr->mx;
1506
1507   do
1508     {
1509       if (!wr_read_splits (wr, c, write_case, wc_data))
1510         return true;
1511
1512       if (!wr_read_factors (wr))
1513         return true;
1514
1515       if (!wr_read_indeps (wr))
1516         return true;
1517     }
1518   while (another_token (mx->reader));
1519
1520   return wr_output_data (wr, c, write_case, wc_data);
1521 }
1522
1523 /* Read the split file variables.  If they differ from the previous
1524    set of split variables then output the data.  Returns success. */
1525 static bool 
1526 wr_read_splits (struct wr_aux_data *wr,
1527                 struct ccase *c,
1528                 write_case_func *write_case, write_case_data wc_data)
1529 {
1530   struct matrix_data_pgm *mx = wr->mx;
1531   bool compare;
1532   size_t split_cnt;
1533
1534   split_cnt = dict_get_split_cnt (wr->dict);
1535   if (split_cnt == 0)
1536     return true;
1537
1538   if (wr->split_values)
1539     compare = true;
1540   else
1541     {
1542       compare = false;
1543       wr->split_values = xnmalloc (split_cnt, sizeof *wr->split_values);
1544     }
1545   
1546   {
1547     bool different = false;
1548     int i;
1549
1550     for (i = 0; i < split_cnt; i++)
1551       {
1552         struct matrix_token token;
1553         if (!mget_token (&token, mx->reader))
1554           return false;
1555         if (token.type != MNUM)
1556           {
1557             msg (SE, _("Syntax error %s expecting SPLIT FILE value."),
1558                  context (mx->reader));
1559             return false;
1560           }
1561
1562         if (compare && wr->split_values[i] != token.number && !different)
1563           {
1564             if (!wr_output_data (wr, c, write_case, wc_data))
1565               return 0;
1566             different = true;
1567             mx->cells = 0;
1568           }
1569         wr->split_values[i] = token.number;
1570       }
1571   }
1572
1573   return true;
1574 }
1575
1576 /* Compares doubles A and B, treating SYSMIS as greatest. */
1577 static int
1578 compare_doubles (const void *a_, const void *b_, const void *aux UNUSED)
1579 {
1580   const double *a = a_;
1581   const double *b = b_;
1582
1583   if (*a == *b)
1584     return 0;
1585   else if (*a == SYSMIS)
1586     return 1;
1587   else if (*b == SYSMIS)
1588     return -1;
1589   else if (*a > *b)
1590     return 1;
1591   else
1592     return -1;
1593 }
1594
1595 /* Return strcmp()-type comparison of the MX->n_factors factors at _A and
1596    _B.  Sort missing values toward the end. */
1597 static int
1598 compare_factors (const void *a_, const void *b_, const void *mx_)
1599 {
1600   const struct matrix_data_pgm *mx = mx_;
1601   struct factor_data *const *pa = a_;
1602   struct factor_data *const *pb = b_;
1603   const double *a = (*pa)->factors;
1604   const double *b = (*pb)->factors;
1605
1606   return lexicographical_compare_3way (a, mx->n_factors,
1607                                        b, mx->n_factors,
1608                                        sizeof *a,
1609                                        compare_doubles, NULL);
1610 }
1611
1612 /* Write out the data for the current split file to the active
1613    file.
1614    Returns true if successful, false if an I/O error occurred. */
1615 static bool
1616 wr_output_data (struct wr_aux_data *wr,
1617                 struct ccase *c,
1618                 write_case_func *write_case, write_case_data wc_data)
1619 {
1620   struct matrix_data_pgm *mx = wr->mx;
1621   bool ok = true;
1622
1623   {
1624     struct variable *const *split;
1625     size_t split_cnt;
1626     size_t i;
1627
1628     split_cnt = dict_get_split_cnt (wr->dict);
1629     split = dict_get_split_vars (wr->dict);
1630     for (i = 0; i < split_cnt; i++)
1631       case_data_rw (c, split[i])->f = wr->split_values[i];
1632   }
1633
1634   /* Sort the wr->data list. */
1635   {
1636     struct factor_data **factors;
1637     struct factor_data *iter;
1638     int i;
1639
1640     factors = xnmalloc (mx->cells, sizeof *factors);
1641
1642     for (i = 0, iter = wr->data; iter; iter = iter->next, i++)
1643       factors[i] = iter;
1644
1645     sort (factors, mx->cells, sizeof *factors, compare_factors, mx);
1646
1647     wr->data = factors[0];
1648     for (i = 0; i < mx->cells - 1; i++)
1649       factors[i]->next = factors[i + 1];
1650     factors[mx->cells - 1]->next = NULL;
1651
1652     free (factors);
1653   }
1654
1655   /* Write out records for every set of factor values. */
1656   {
1657     struct factor_data *iter;
1658     
1659     for (iter = wr->data; iter; iter = iter->next)
1660       {
1661         {
1662           size_t factor;
1663
1664           for (factor = 0; factor < mx->n_factors; factor++)
1665             case_data_rw (c, mx->factors[factor])->f = iter->factors[factor];
1666         }
1667         
1668         {
1669           int content;
1670
1671           for (content = 0; content <= PROX; content++)
1672             {
1673               if (!iter->n_rows[content])
1674                 continue;
1675               
1676               {
1677                 int type = content_type[content];
1678                 int n_lines = (type == 1
1679                                ? (mx->n_continuous
1680                                   - (mx->section != FULL && mx->diag == NODIAGONAL))
1681                                : 1);
1682                 
1683                 if (n_lines != iter->n_rows[content])
1684                   {
1685                     msg (SE, _("Expected %d lines of data for %s content; "
1686                                "actually saw %d lines.  No data will be "
1687                                "output for this content."),
1688                          n_lines, content_names[content],
1689                          iter->n_rows[content]);
1690                     continue;
1691                   }
1692               }
1693
1694               fill_matrix (mx, content, iter->data[content]);
1695
1696               ok = dump_cell_content (wr->dict, mx, content, 
1697                                       iter->data[content],
1698                                       c, write_case, wc_data);
1699               if (!ok)
1700                 break;
1701             }
1702         }
1703       }
1704   }
1705   
1706   pool_destroy (mx->container);
1707   mx->container = pool_create ();
1708   
1709   wr->data = wr->current = NULL;
1710   
1711   return ok;
1712 }
1713
1714 /* Sets ROWTYPE_ based on the given TOKEN read from READER.
1715    Return success. */
1716 static bool 
1717 wr_read_rowtype (struct wr_aux_data *wr,
1718                  const struct matrix_token *token,
1719                  struct dfm_reader *reader)
1720 {
1721   if (wr->content != -1)
1722     {
1723       msg (SE, _("Multiply specified ROWTYPE_ %s."), context (reader));
1724       return false;
1725     }
1726   if (token->type != MSTR)
1727     {
1728       msg (SE, _("Syntax error %s expecting ROWTYPE_ string."),
1729            context (reader));
1730       return false;
1731     }
1732   
1733   {
1734     char s[16];
1735     char *cp;
1736     
1737     memcpy (s, token->string, MIN (15, token->length));
1738     s[MIN (15, token->length)] = 0;
1739
1740     for (cp = s; *cp; cp++)
1741       *cp = toupper ((unsigned char) *cp);
1742
1743     wr->content = string_to_content_type (s, NULL);
1744   }
1745
1746   if (wr->content == -1)
1747     {
1748       msg (SE, _("Syntax error %s."), context (reader));
1749       return 0;
1750     }
1751
1752   return true;
1753 }
1754
1755 /* Read the factors for the current row.  Select a set of factors and
1756    point wr_current to it. */
1757 static bool 
1758 wr_read_factors (struct wr_aux_data *wr)
1759 {
1760   struct matrix_data_pgm *mx = wr->mx;
1761   double *factor_values = local_alloc (sizeof *factor_values * mx->n_factors);
1762
1763   wr->content = -1;
1764   {
1765     size_t i;
1766   
1767     for (i = 0; i < mx->n_factors; i++)
1768       {
1769         struct matrix_token token;
1770         if (!mget_token (&token, mx->reader))
1771           goto lossage;
1772         if (token.type == MSTR)
1773           {
1774             if (!wr_read_rowtype (wr, &token, mx->reader))
1775               goto lossage;
1776             if (!mget_token (&token, mx->reader))
1777               goto lossage;
1778           }
1779         if (token.type != MNUM)
1780           {
1781             msg (SE, _("Syntax error expecting factor value %s."),
1782                  context (mx->reader));
1783             goto lossage;
1784           }
1785         
1786         factor_values[i] = token.number;
1787       }
1788   }
1789   if (wr->content == -1)
1790     {
1791       struct matrix_token token;
1792       if (!mget_token (&token, mx->reader))
1793         goto lossage;
1794       if (!wr_read_rowtype (wr, &token, mx->reader))
1795         goto lossage;
1796     }
1797   
1798   /* Try the most recent factor first as a simple caching
1799      mechanism. */
1800   if (wr->current)
1801     {
1802       size_t i;
1803       
1804       for (i = 0; i < mx->n_factors; i++)
1805         if (factor_values[i] != wr->current->factors[i])
1806           goto cache_miss;
1807       goto winnage;
1808     }
1809
1810   /* Linear search through the list. */
1811 cache_miss:
1812   {
1813     struct factor_data *iter;
1814
1815     for (iter = wr->data; iter; iter = iter->next)
1816       {
1817         size_t i;
1818
1819         for (i = 0; i < mx->n_factors; i++)
1820           if (factor_values[i] != iter->factors[i])
1821             goto next_item;
1822         
1823         wr->current = iter;
1824         goto winnage;
1825         
1826       next_item: ;
1827       }
1828   }
1829
1830   /* Not found.  Make a new item. */
1831   {
1832     struct factor_data *new = pool_alloc (mx->container, sizeof *new);
1833
1834     new->factors = pool_nalloc (mx->container,
1835                                 mx->n_factors, sizeof *new->factors);
1836     
1837     {
1838       size_t i;
1839
1840       for (i = 0; i < mx->n_factors; i++)
1841         new->factors[i] = factor_values[i];
1842     }
1843     
1844     {
1845       int i;
1846
1847       for (i = 0; i <= PROX; i++)
1848         {
1849           new->n_rows[i] = 0;
1850           new->data[i] = NULL;
1851         }
1852     }
1853
1854     new->next = wr->data;
1855     wr->data = wr->current = new;
1856     mx->cells++;
1857   }
1858
1859 winnage:
1860   local_free (factor_values);
1861   return true;
1862
1863 lossage:
1864   local_free (factor_values);
1865   return false;
1866 }
1867
1868 /* Read the independent variables into wr->current. */
1869 static bool 
1870 wr_read_indeps (struct wr_aux_data *wr)
1871 {
1872   struct matrix_data_pgm *mx = wr->mx;
1873   struct factor_data *c = wr->current;
1874   const int type = content_type[wr->content];
1875   const int n_rows = c->n_rows[wr->content];
1876   double *cp;
1877   int n_cols;
1878
1879   /* Allocate room for data if necessary. */
1880   if (c->data[wr->content] == NULL)
1881     {
1882       int n_items = mx->n_continuous;
1883       if (type == 1)
1884         n_items *= mx->n_continuous;
1885       
1886       c->data[wr->content] = pool_nalloc (mx->container,
1887                                           n_items, sizeof **c->data);
1888     }
1889
1890   cp = &c->data[wr->content][n_rows * mx->n_continuous];
1891
1892   /* Figure out how much to read from this line. */
1893   switch (type)
1894     {
1895     case 0:
1896     case 2:
1897       if (n_rows > 0)
1898         {
1899           msg (SE, _("Duplicate specification for %s."),
1900                content_names[wr->content]);
1901           return false;
1902         }
1903       if (type == 0)
1904         n_cols = mx->n_continuous;
1905       else
1906         n_cols = 1;
1907       break;
1908     case 1:
1909       if (n_rows >= mx->n_continuous - (mx->section != FULL && mx->diag == NODIAGONAL))
1910         {
1911           msg (SE, _("Too many rows of matrix data for %s."),
1912                content_names[wr->content]);
1913           return false;
1914         }
1915       
1916       switch (mx->section)
1917         {
1918         case LOWER:
1919           n_cols = n_rows + 1;
1920           if (mx->diag == NODIAGONAL)
1921             cp += mx->n_continuous;
1922           break;
1923         case UPPER:
1924           cp += n_rows;
1925           n_cols = mx->n_continuous - n_rows;
1926           if (mx->diag == NODIAGONAL)
1927             {
1928               n_cols--;
1929               cp++;
1930             }
1931           break;
1932         case FULL:
1933           n_cols = mx->n_continuous;
1934           break;
1935         default:
1936           NOT_REACHED ();
1937         }
1938       break;
1939     default:
1940       NOT_REACHED ();
1941     }
1942   c->n_rows[wr->content]++;
1943
1944   /* Read N_COLS items at CP. */
1945   {
1946     int j;
1947         
1948     for (j = 0; j < n_cols; j++)
1949       {
1950         struct matrix_token token;
1951         if (!mget_token (&token, mx->reader))
1952           return false;
1953         if (token.type != MNUM)
1954           {
1955             msg (SE, _("Syntax error expecting value for %s %s."),
1956                  var_get_name (dict_get_var (wr->dict,
1957                                              mx->first_continuous + j)),
1958                  context (mx->reader));
1959             return false;
1960           }
1961
1962         *cp++ = token.number;
1963       }
1964     if (mx->fmt != FREE
1965         && !force_eol (mx->reader, content_names[wr->content]))
1966       return false;
1967   }
1968
1969   return true;
1970 }
1971 \f
1972 /* Matrix source. */
1973
1974 static const struct case_source_class matrix_data_with_rowtype_source_class = 
1975   {
1976     "MATRIX DATA",
1977     NULL,
1978     matrix_data_read_with_rowtype,
1979     NULL,
1980   };
1981
1982 static const struct case_source_class 
1983 matrix_data_without_rowtype_source_class =
1984   {
1985     "MATRIX DATA",
1986     NULL,
1987     matrix_data_read_without_rowtype,
1988     NULL,
1989   };
1990