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