1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
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.
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.
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
21 Categories of SET subcommands:
23 data input: BLANKS, DECIMAL, FORMAT.
25 program input: ENDCMD, NULLINE.
27 interaction: CPROMPT, DPROMPT, ERRORBREAK, MXERRS, MXWARNS, PROMPT.
29 program execution: MEXPAND, MITERATE, MNEST, MPRINT,
30 MXLOOPS, SEED, UNDEFINED.
32 data output: CCA...CCE, DECIMAL, FORMAT, RESULTS-p.
34 output routing: ECHO, ERRORS, INCLUDE, MESSAGES, PRINTBACK, ERRORS,
37 output activation: LISTING (on/off), SCREEN, PRINTER.
39 output driver options: HEADERS, MORE, PAGER, VIEWLENGTH, VIEWWIDTH,
42 logging: LOG, JOURNAL.
44 system files: COMP/COMPRESSION, SCOMP/SCOMPRESSION.
52 These subcommands remain to be implemented:
53 ECHO, PRINTBACK, INCLUDE
54 MORE, PAGER, VIEWLENGTH, VIEWWIDTH, HEADERS
56 These subcommands are not complete:
57 MESSAGES, ERRORS, RESULTS
58 LISTING/DISK, LOG/JOURNAL
84 #else /* !HAVE_TERMCAP_H */
85 int tgetent (char *, const char *);
86 int tgetnum (const char *);
87 #endif /* !HAVE_TERMCAP_H */
88 #endif /* !HAVE_LIBTERMCAP */
90 static int set_errors;
91 static int set_messages;
92 static int set_results;
94 static double set_blanks=SYSMIS;
96 static struct fmt_spec set_format={FMT_F,8,2};
98 static struct set_cust_currency set_cc[5];
100 static char *set_journal;
101 static int set_journaling;
103 static int set_listing=1;
105 #if !USE_INTERNAL_PAGER
106 static char *set_pager=0;
107 #endif /* !USE_INTERNAL_PAGER */
109 static unsigned long set_seed;
110 static int seed_flag=0;
112 static int long_view=0;
113 int set_testing_mode=0;
114 static int set_viewlength;
115 static int set_viewwidth;
117 void aux_show_warranty(void);
118 void aux_show_copying(void);
120 static const char *route_to_string(int routing);
121 static void set_routing (int q, int *setting);
123 static int set_ccx (const char *cc_string, struct set_cust_currency * cc,
127 automenu=automenu:on/off;
130 block=string "x==1" "one character long";
131 boxstring=string "x==3 || x==11" "3 or 11 characters long";
132 case=size:upper/uplow;
139 compression=compress:on/off;
140 cpi=integer "x>0" "%s must be greater than 0";
142 decimal=dec:dot/comma;
147 endcmd=string "x==1" "one character long";
148 errorbreak=errbrk:on/off;
149 errors=errors:on/off/terminal/listing/both/none;
151 headers=headers:no/yes/blank;
152 helpwindows=helpwin:on/off;
153 highres=hires:on/off;
154 histogram=string "x==1" "one character long";
160 lowres=lores:auto/on/off;
161 lpi=integer "x>0" "% must be greater than 0";
162 menus=menus:standard/extended;
163 messages=messages:on/off/terminal/listing/both/none;
165 miterate=integer "x>0" "%s must be greater than 0";
166 mnest=integer "x>0" "%s must be greater than 0";
168 mprint=mprint:on/off;
169 mxerrs=integer "x >= 1" "%s must be at least 1";
170 mxloops=integer "x >=1" "%s must be at least 1";
175 printback=prtbck:on/off;
178 ptranslate=ptrans:on/off;
181 runreview=runrev:auto/manual;
183 scompression=scompress:on/off;
185 scripttab=string "x==1" "one character long";
187 tb1=string "x==3 || x==11" "3 or 11 characters long";
189 undefined=undef:warn/nowarn;
194 workspace=integer "x>=1024" "%s must be at least 1 MB";
203 aux_stc_custom_blanks(struct cmd_set *cmd UNUSED)
205 if ( set_blanks == SYSMIS )
208 msg(MM, "%g", set_blanks);
214 aux_stc_custom_color(struct cmd_set *cmd UNUSED)
216 msg (MW, _("%s is obsolete."),"COLOR");
221 aux_stc_custom_listing(struct cmd_set *cmd UNUSED)
224 msg(MM, _("LISTING is ON"));
226 msg(MM, _("LISTING is OFF"));
232 aux_stc_custom_disk(struct cmd_set *cmd UNUSED)
234 return aux_stc_custom_listing(cmd);
238 aux_stc_custom_format(struct cmd_set *cmd UNUSED)
240 msg(MM, fmt_to_string(&set_format));
247 aux_stc_custom_journal(struct cmd_set *cmd UNUSED)
250 msg(MM, set_journal);
252 msg(MM, _("Journalling is off") );
258 aux_stc_custom_length(struct cmd_set *cmd UNUSED)
260 msg(MM, "%d", set_viewlength);
265 aux_stc_custom_log(struct cmd_set *cmd )
267 return aux_stc_custom_journal (cmd);
271 aux_stc_custom_pager(struct cmd_set *cmd UNUSED)
273 #if !USE_INTERNAL_PAGER
278 #else /* USE_INTERNAL_PAGER */
279 msg (MM, "Internal pager.");
280 #endif /* USE_INTERNAL_PAGER */
286 aux_stc_custom_rcolor(struct cmd_set *cmd UNUSED)
288 msg (SW, _("%s is obsolete."),"RCOLOR");
293 aux_stc_custom_results(struct cmd_set *cmd UNUSED)
296 msg(MM, route_to_string(set_results) );
302 aux_stc_custom_seed(struct cmd_set *cmd UNUSED)
304 msg(MM, "%ld",set_seed);
309 aux_stc_custom_viewlength(struct cmd_set *cmd UNUSED)
311 msg(MM, "%d", set_viewlength);
316 aux_stc_custom_viewwidth(struct cmd_set *cmd UNUSED)
318 msg(MM, "%d", set_viewwidth);
323 aux_stc_custom_width(struct cmd_set *cmd UNUSED)
325 msg(MM, "%d", set_viewwidth);
330 aux_stc_custom_workdev(struct cmd_set *cmd UNUSED)
332 msg (SW, _("%s is obsolete."),"WORKDEV");
339 warranty=show_warranty;
340 copying=show_copying.
344 static struct cmd_set cmd;
349 lex_match_id ("SHOW");
351 if (!aux_parse_set (&cmd))
361 if (!parse_set (&cmd))
365 set_ccx (cmd.s_cca, &set_cc[0], 'A');
367 set_ccx (cmd.s_ccb, &set_cc[1], 'B');
369 set_ccx (cmd.s_ccc, &set_cc[2], 'C');
371 set_ccx (cmd.s_ccd, &set_cc[3], 'D');
373 set_ccx (cmd.s_cce, &set_cc[4], 'E');
376 set_routing (cmd.errors, &set_errors);
377 if (cmd.sbc_messages)
378 set_routing (cmd.messages, &set_messages);
380 /* PC+ compatible syntax. */
382 outp_enable_device (cmd.scrn == STC_OFF ? 0 : 1, OUTP_DEV_SCREEN);
384 outp_enable_device (cmd.prtr == STC_OFF ? 0 : 1, OUTP_DEV_PRINTER);
386 if (cmd.sbc_automenu )
387 msg (SW, _("%s is obsolete."),"AUTOMENU");
389 msg (SW, _("%s is obsolete."),"BEEP");
391 msg (SW, _("%s is obsolete."),"BLOCK");
392 if (cmd.sbc_boxstring)
393 msg (SW, _("%s is obsolete."),"BOXSTRING");
395 msg (SW, _("%s is obsolete."),"EJECT");
396 if (cmd.sbc_helpwindows )
397 msg (SW, _("%s is obsolete."),"HELPWINDOWS");
398 if (cmd.sbc_histogram)
399 msg (MW, _("%s is obsolete."),"HISTOGRAM");
401 msg (MW, _("%s is obsolete."),"MENUS");
402 if (cmd.sbc_ptranslate )
403 msg (SW, _("%s is obsolete."),"PTRANSLATE");
404 if (cmd.sbc_runreview )
405 msg (SW, _("%s is obsolete."),"RUNREVIEW");
407 msg (SW, _("%s is obsolete."),"XSORT");
408 if (cmd.sbc_mxmemory )
409 msg (SE, _("%s is obsolete."),"MXMEMORY");
410 if (cmd.sbc_scripttab)
411 msg (SE, _("%s is obsolete."),"SCRIPTTAB");
414 msg (SW, _("%s is not yet implemented."),"TBFONTS");
415 if (cmd.sbc_tb1 && cmd.s_tb1)
416 msg (SW, _("%s is not yet implemented."),"TB1");
418 /* Windows compatible syntax. */
420 msg (SW, _("CASE is not implemented and probably won't be. "
421 "If you care, complain about it."));
423 if (cmd.sbc_compression)
425 msg (MW, _("Active file compression is not yet implemented "
426 "(and probably won't be)."));
432 /* Sets custom currency specifier CC having name CC_NAME ('A' through
433 'E') to correspond to the settings in CC_STRING. */
435 set_ccx (const char *cc_string, struct set_cust_currency * cc, int cc_name)
437 if (strlen (cc_string) > 16)
439 msg (SE, _("CC%c: Length of custom currency string `%s' (%d) "
440 "exceeds maximum length of 16."),
441 cc_name, cc_string, strlen (cc_string));
445 /* Determine separators. */
448 int n_commas, n_periods;
450 /* Count the number of commas and periods. There must be exactly
451 three of one or the other. */
452 n_commas = n_periods = 0;
453 for (sp = cc_string; *sp; sp++)
459 if (!((n_commas == 3) ^ (n_periods == 3)))
461 msg (SE, _("CC%c: Custom currency string `%s' does not contain "
462 "exactly three periods or commas (not both)."),
466 else if (n_commas == 3)
478 /* Copy cc_string to cc, changing separators to nulls. */
482 strcpy (cc->buf, cc_string);
483 cp = cc->neg_prefix = cc->buf;
485 while (*cp++ != cc->grouping)
490 while (*cp++ != cc->grouping)
495 while (*cp++ != cc->grouping)
506 route_to_string(int routing)
514 strcpy(s, _("None"));
518 if (routing & SET_ROUTE_DISABLE )
520 strcpy(s, _("Disabled") );
524 if (routing & SET_ROUTE_SCREEN)
525 strcat(s, _("Screen") );
527 if (routing & SET_ROUTE_LISTING)
532 strcat(s, _("Listing") );
535 if (routing & SET_ROUTE_OTHER)
539 strcat(s, _("Other") );
548 /* Sets *SETTING, which is a combination of SET_ROUTE_* bits that
549 indicates what to do with some sort of output, to the value
550 indicated by Q, which is a value provided by the input parser. */
552 set_routing (int q, int *setting)
557 *setting |= SET_ROUTE_DISABLE;
560 *setting &= ~SET_ROUTE_DISABLE;
563 *setting &= ~(SET_ROUTE_LISTING | SET_ROUTE_OTHER);
564 *setting |= SET_ROUTE_SCREEN;
567 *setting &= ~SET_ROUTE_SCREEN;
568 *setting |= SET_ROUTE_LISTING | SET_ROUTE_OTHER;
571 *setting |= SET_ROUTE_SCREEN | SET_ROUTE_LISTING | SET_ROUTE_OTHER;
574 *setting &= ~(SET_ROUTE_SCREEN | SET_ROUTE_LISTING | SET_ROUTE_OTHER);
582 stc_custom_pager (struct cmd_set *cmd UNUSED)
585 #if !USE_INTERNAL_PAGER
586 if (lex_match_id ("OFF"))
594 if (!lex_force_string ())
598 set_pager = xstrdup (ds_value (&tokstr));
602 #else /* USE_INTERNAL_PAGER */
605 msg (SW, "External pagers not supported.");
607 #endif /* USE_INTERNAL_PAGER */
610 /* Parses the BLANKS subcommand, which controls the value that
611 completely blank fields in numeric data imply. X, Wnd: Syntax is
612 SYSMIS or a numeric value; PC+: Syntax is '.', which is equivalent
613 to SYSMIS, or a numeric value. */
615 stc_custom_blanks (struct cmd_set *cmd UNUSED)
618 if ((token == T_ID && lex_id_match ("SYSMIS", tokid))
619 || (token == T_STRING && !strcmp (tokid, ".")))
626 if (!lex_force_num ())
635 stc_custom_length (struct cmd_set *cmd UNUSED)
640 if (lex_match_id ("NONE"))
644 if (!lex_force_int ())
646 if (lex_integer () < 1)
648 msg (SE, _("LENGTH must be at least 1."));
651 page_length = lex_integer ();
655 if ( page_length != -1 )
656 set_viewlength = page_length;
662 stc_custom_results (struct cmd_set *cmd UNUSED)
670 static struct tuple tab[] =
674 {"TERMINAL", STC_TERMINAL},
675 {"LISTING", STC_LISTING},
687 msg (SE, _("Missing identifier in RESULTS subcommand."));
691 for (t = tab; t->s; t++)
692 if (lex_id_match (t->s, tokid))
695 set_routing (t->v, &set_results);
698 msg (SE, _("Unrecognized identifier in RESULTS subcommand."));
703 stc_custom_seed (struct cmd_set *cmd UNUSED)
706 if (lex_match_id ("RANDOM"))
707 set_seed = random_seed();
710 if (!lex_force_num ())
721 stc_custom_width (struct cmd_set *cmd UNUSED)
726 if (lex_match_id ("NARROW"))
728 else if (lex_match_id ("WIDE"))
732 if (!lex_force_int ())
734 if (lex_integer () < 1)
736 msg (SE, _("WIDTH must be at least 1."));
739 page_width = lex_integer ();
743 set_viewwidth = page_width;
747 /* Parses FORMAT subcommand, which consists of a numeric format
750 stc_custom_format (struct cmd_set *cmd UNUSED)
755 if (!parse_format_specifier (&fmt, 0))
757 if ((formats[fmt.type].cat & FCAT_STRING) != 0)
759 msg (SE, _("FORMAT requires numeric output format as an argument. "
760 "Specified format %s is of type string."),
761 fmt_to_string (&fmt));
770 stc_custom_journal (struct cmd_set *cmd UNUSED)
773 if (lex_match_id ("ON"))
775 else if (lex_match_id ("OFF"))
777 if (token == T_STRING)
779 set_journal = xstrdup (ds_value (&tokstr));
785 /* Parses COLOR subcommand. PC+: either ON or OFF or two or three
786 comma-delimited numbers inside parentheses. */
788 stc_custom_color (struct cmd_set *cmd UNUSED)
790 msg (MW, _("%s is obsolete."),"COLOR");
793 if (!lex_match_id ("ON") && !lex_match_id ("YES") && !lex_match_id ("OFF") && !lex_match_id ("NO"))
795 if (!lex_force_match ('('))
797 if (!lex_match ('*'))
799 if (!lex_force_int ())
801 if (lex_integer () < 0 || lex_integer () > 15)
803 msg (SE, _("Text color must be in range 0-15."));
808 if (!lex_force_match (','))
810 if (!lex_match ('*'))
812 if (!lex_force_int ())
814 if (lex_integer () < 0 || lex_integer () > 7)
816 msg (SE, _("Background color must be in range 0-7."));
821 if (lex_match (',') && !lex_match ('*'))
823 if (!lex_force_int ())
825 if (lex_integer () < 0 || lex_integer () > 7)
827 msg (SE, _("Border color must be in range 0-7."));
832 if (!lex_force_match (')'))
839 stc_custom_listing (struct cmd_set *cmd UNUSED)
842 if (lex_match_id ("ON") || lex_match_id ("YES"))
844 else if (lex_match_id ("OFF") || lex_match_id ("NO"))
851 outp_enable_device (set_listing, OUTP_DEV_LISTING);
857 stc_custom_disk (struct cmd_set *cmd UNUSED)
859 return stc_custom_listing (cmd);
863 stc_custom_log (struct cmd_set *cmd UNUSED)
865 return stc_custom_journal (cmd);
869 stc_custom_rcolor (struct cmd_set *cmd UNUSED)
871 msg (SW, _("%s is obsolete."),"RCOLOR");
874 if (!lex_force_match ('('))
877 if (!lex_match ('*'))
879 if (!lex_force_int ())
881 if (lex_integer () < 0 || lex_integer () > 6)
883 msg (SE, _("Lower window color must be between 0 and 6."));
888 if (!lex_force_match (','))
891 if (!lex_match ('*'))
893 if (!lex_force_int ())
895 if (lex_integer () < 0 || lex_integer () > 6)
897 msg (SE, _("Upper window color must be between 0 and 6."));
903 if (lex_match (',') && !lex_match ('*'))
905 if (!lex_force_int ())
907 if (lex_integer () < 0 || lex_integer () > 6)
909 msg (SE, _("Frame color must be between 0 and 6."));
918 stc_custom_viewwidth (struct cmd_set *cmd UNUSED)
922 if ( !lex_force_int() )
925 set_viewwidth = lex_integer();
932 stc_custom_viewlength (struct cmd_set *cmd UNUSED)
934 if (lex_match_id ("MINIMUM"))
936 else if (lex_match_id ("MEDIAN"))
937 set_viewlength = 43; /* This is not correct for VGA displays. */
938 else if (lex_match_id ("MAXIMUM"))
942 if (!lex_force_int ())
945 if (lex_integer () >= (43 + 25) / 2)
950 set_viewlength = lex_integer ();
956 msg (SW, _("%s is not yet implemented."),"VIEWLENGTH");
962 stc_custom_workdev (struct cmd_set *cmd UNUSED)
966 msg (SW, _("%s is obsolete."),"WORKDEV");
969 for (*c = 'A'; *c <= 'Z'; (*c)++)
970 if (token == T_ID && lex_id_match (c, tokid))
975 msg (SE, _("Drive letter expected in WORKDEV subcommand."));
982 set_viewport(int sig_num UNUSED)
985 static char term_buffer[16384];
988 /* Workable defaults before we determine the real terminal size. */
994 #if __DJGPP__ || __BORLANDC__
999 set_viewlength = max (ti.screenheight, 25);
1000 set_viewwidth = max (ti.screenwidth, 79);
1002 #elif HAVE_LIBTERMCAP
1007 /* This code stolen from termcap.info, though modified. */
1008 termtype = getenv ("TERM");
1010 msg (FE, _("Specify a terminal type with `setenv TERM <yourtype>'."));
1012 success = tgetent (term_buffer, termtype);
1016 msg (IE, _("Could not access the termcap data base."));
1018 msg (IE, _("Terminal type `%s' is not defined."), termtype);
1022 set_viewlength = tgetnum ("li");
1023 set_viewwidth = tgetnum ("co") - 1;
1030 /* Try the environment variables */
1031 s = getenv("COLUMNS");
1032 if ( s ) set_viewwidth = atoi(s);
1034 s = getenv("LINES");
1035 if ( s ) set_viewlength = atoi(s);
1037 #endif /* !HAVE_LIBTERMCAP */
1041 /* Public functions */
1046 cmd.s_dprompt = xstrdup (_("data> "));
1047 cmd.s_cprompt = xstrdup (" > ");
1048 cmd.s_prompt = xstrdup ("PSPP> ");
1049 cmd.s_endcmd = xstrdup (".");
1051 assert(cmd.safe == 0 );
1059 cmd.headers = STC_YES;
1060 cmd.errbrk = STC_OFF;
1062 cmd.scompress = STC_OFF;
1063 cmd.undef = STC_WARN;
1064 cmd.mprint = STC_ON ;
1065 cmd.prtbck = STC_ON ;
1069 set_journal = xstrdup ("pspp.jnl");
1072 cmd.n_mxwarns = 100;
1075 cmd.n_workspace = 4L * 1024 * 1024;
1078 #if !USE_INTERNAL_PAGER
1082 pager = getenv ("STAT_PAGER");
1083 if (!pager) set_pager = getenv ("PAGER");
1086 set_pager = xstrdup (pager);
1089 set_pager = xstrdup (DEFAULT_PAGER);
1090 #endif /* DEFAULT_PAGER */
1092 #endif /* !USE_INTERNAL_PAGER */
1098 for (i = 0; i < 5; i++)
1100 struct set_cust_currency *cc = &set_cc[i];
1101 strcpy (cc->buf, "-");
1102 cc->neg_prefix = cc->buf;
1103 cc->prefix = &cc->buf[1];
1104 cc->suffix = &cc->buf[1];
1105 cc->neg_suffix = &cc->buf[1];
1114 signal (SIGWINCH, set_viewport);
1120 force_long_view(void)
1129 return !(cmd.safe != STC_ON) ;
1133 /* Set safer mode */
1144 return (cmd.dec == STC_DOT ? '.' : ',');
1151 return (cmd.dec == STC_DOT ? ',' : '.');
1158 return cmd.s_prompt;
1164 return cmd.s_dprompt;
1170 return cmd.s_cprompt;
1177 return (cmd.echo != STC_OFF );
1182 get_errorbreak(void)
1184 return (cmd.errbrk != STC_OFF);
1189 get_scompression(void)
1191 return (cmd.scompress != STC_OFF );
1197 return (cmd.undef != STC_NOWARN);
1203 return cmd.n_mxwarns;
1209 return cmd.n_mxerrs;
1215 return ( cmd.mprint != STC_OFF );
1221 return (cmd.prtbck != STC_OFF );
1227 return cmd.n_mxloops;
1233 return (cmd.null != STC_OFF );
1239 return (cmd.inc != STC_OFF );
1245 return cmd.s_endcmd[0];
1250 get_max_workspace(void)
1252 return cmd.n_workspace;
1267 /* CCA through CCE. */
1268 const struct set_cust_currency *
1275 aux_show_warranty(void)
1277 msg(MM,lack_of_warranty);
1281 aux_show_copying(void)
1288 get_viewlength(void)
1290 return set_viewlength;
1296 return set_viewwidth;
1305 /* Return 1 if the seed has been set since the last time this function
1307 Fill the value pointed to by seed with the seed .
1310 seed_is_set(unsigned long *seed)