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