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