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