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
79 struct set_cust_currency set_cc[5];
88 int set_errors, set_messages, set_results;
89 struct fmt_spec set_format;
107 #if !USE_INTERNAL_PAGER
109 #endif /* !USE_INTERNAL_PAGER */
112 char *set_results_file;
114 int set_scompression;
117 int set_testing_mode;
122 static void set_routing (int q, int *setting);
123 static int set_ccx (const char *cc_string, struct set_cust_currency * cc,
128 automenu=automenu:on/off;
131 block=string "x==1" "one character long";
132 boxstring=string "x==3 || x==11" "3 or 11 characters long";
133 case=size:upper/uplow;
140 compression=compress:on/off;
143 decimal=dec:dot/_comma;
148 endcmd=string "x==1" "one character long";
149 errorbreak=errbrk:on/off;
150 errors=errors:on/off/terminal/listing/both/none;
152 headers=headers:no/yes/blank;
153 helpwindows=helpwin:on/off;
154 highres=hires:on/off;
155 histogram=string "x==1" "one character long";
161 lowres=lores:auto/on/off;
163 menus=menus:standard/extended;
164 messages=messages:on/off/terminal/listing/both/none;
169 mprint=mprint:on/off;
176 printback=prtbck:on/off;
179 ptranslate=ptrans:on/off;
182 runreview=runrev:auto/manual;
184 scompression=scompress:on/off;
186 scripttab=string "x==1" "one character long";
188 tb1=string "x==3 || x==11" "3 or 11 characters long";
190 undefined=undef:warn/nowarn;
202 int internal_cmd_set (void);
209 lex_match_id ("SET");
211 if (!parse_set (&cmd))
215 msg (SW, _("%s is obsolete."),"BLOCK");
217 if (cmd.sbc_boxstring)
218 msg (SW, _("%s is obsolete."),"BOXSTRING");
220 if (cmd.compress != -1)
222 msg (MW, _("Active file compression is not yet implemented "
223 "(and probably won't be)."));
224 set_compression = cmd.compress == STC_OFF ? 0 : 1;
226 if (cmd.scompress != -1)
227 set_scompression = cmd.scompress == STC_OFF ? 0 : 1;
228 if (cmd.n_cpi != NOT_LONG)
231 msg (SE, _("CPI must be greater than 0."));
235 if (cmd.sbc_histogram)
236 msg (MW, _("%s is obsolete."),"HISTOGRAM");
237 if (cmd.n_lpi != NOT_LONG)
240 msg (SE, _("LPI must be greater than 0."));
245 /* Windows compatible syntax. */
247 msg (SW, _("CASE is not implemented and probably won't be. If you care, "
248 "complain about it."));
250 set_ccx (cmd.s_cca, &set_cc[0], 'A');
252 set_ccx (cmd.s_ccb, &set_cc[1], 'B');
254 set_ccx (cmd.s_ccc, &set_cc[2], 'C');
256 set_ccx (cmd.s_ccd, &set_cc[3], 'D');
258 set_ccx (cmd.s_cce, &set_cc[4], 'E');
261 set_decimal = cmd.dec == STC_DOT ? '.' : ',';
262 set_grouping = cmd.dec == STC_DOT ? ',' : '.';
264 if (cmd.errors != -1)
265 set_routing (cmd.errors, &set_errors);
266 if (cmd.headers != -1)
267 set_headers = cmd.headers == STC_NO ? 0 : (cmd.headers == STC_YES ? 1 : 2);
268 if (cmd.messages != -1)
269 set_routing (cmd.messages, &set_messages);
271 set_mexpand = cmd.mexp == STC_OFF ? 0 : 1;
272 if (cmd.n_miterate != NOT_LONG)
274 if (cmd.n_miterate > 0)
275 set_miterate = cmd.n_miterate;
277 msg (SE, _("Value for MITERATE (%ld) must be greater than 0."),
280 if (cmd.n_mnest != NOT_LONG)
283 set_mnest = cmd.n_mnest;
285 msg (SE, _("Value for MNEST (%ld) must be greater than 0."),
288 if (cmd.mprint != -1)
289 set_mprint = cmd.mprint == STC_OFF ? 0 : 1;
290 if (cmd.n_mxerrs != NOT_LONG)
293 msg (SE, _("MXERRS must be at least 1."));
295 set_mxerrs = cmd.n_mxerrs;
297 if (cmd.n_mxloops != NOT_LONG)
300 msg (SE, _("MXLOOPS must be at least 1."));
302 set_mxloops = cmd.n_mxloops;
304 if (cmd.n_mxmemory != NOT_LONG)
305 msg (SE, _("%s is obsolete."),"MXMEMORY");
306 if (cmd.n_mxwarns != NOT_LONG)
307 set_mxwarns = cmd.n_mxwarns;
308 if (cmd.prtbck != -1)
309 set_printback = cmd.prtbck == STC_OFF ? 0 : 1;
311 msg (SE, _("%s is obsolete."),"SCRIPTTAB");
313 msg (SW, _("TBFONTS not implemented."));
315 msg (SW, _("TB1 not implemented."));
317 set_undefined = cmd.undef == STC_NOWARN ? 0 : 1;
318 if (cmd.n_workspace != NOT_LONG)
319 msg (SE, _("%s is obsolete."),"WORKSPACE");
321 /* PC+ compatible syntax. */
323 outp_enable_device (cmd.scrn == STC_OFF ? 0 : 1, OUTP_DEV_SCREEN);
325 if (cmd.automenu != -1)
326 msg (SW, _("%s is obsolete."),"AUTOMENU");
328 msg (SW, _("%s is obsolete."),"BEEP");
333 set_cprompt = cmd.s_cprompt;
334 cmd.s_cprompt = NULL;
339 set_dprompt = cmd.s_dprompt;
340 cmd.s_dprompt = NULL;
343 set_echo = cmd.echo == STC_OFF ? 0 : 1;
345 set_endcmd = cmd.s_endcmd[0];
347 msg (SW, _("%s is obsolete."),"EJECT");
348 if (cmd.errbrk != -1)
349 set_errorbreak = cmd.errbrk == STC_OFF ? 0 : 1;
350 if (cmd.helpwin != -1)
351 msg (SW, _("%s is obsolete."),"HELPWINDOWS");
353 set_include = cmd.inc == STC_OFF ? 0 : 1;
355 msg (MW, _("%s is obsolete."),"MENUS");
357 set_nullline = cmd.null == STC_OFF ? 0 : 1;
359 set_more = cmd.more == STC_OFF ? 0 : 1;
361 outp_enable_device (cmd.prtr == STC_OFF ? 0 : 1, OUTP_DEV_PRINTER);
365 set_prompt = cmd.s_prompt;
368 if (cmd.ptrans != -1)
369 msg (SW, _("%s is obsolete."),"PTRANSLATE");
370 if (cmd.runrev != -1)
371 msg (SW, _("%s is obsolete."),"RUNREVIEW");
372 if (cmd.safe == STC_ON)
375 msg (SW, _("%s is obsolete."),"XSORT");
382 /* Sets custom currency specifier CC having name CC_NAME ('A' through
383 'E') to correspond to the settings in CC_STRING. */
385 set_ccx (const char *cc_string, struct set_cust_currency * cc, int cc_name)
387 if (strlen (cc_string) > 16)
389 msg (SE, _("CC%c: Length of custom currency string `%s' (%d) "
390 "exceeds maximum length of 16."),
391 cc_name, cc_string, strlen (cc_string));
395 /* Determine separators. */
398 int n_commas, n_periods;
400 /* Count the number of commas and periods. There must be exactly
401 three of one or the other. */
402 n_commas = n_periods = 0;
403 for (sp = cc_string; *sp; sp++)
409 if (!((n_commas == 3) ^ (n_periods == 3)))
411 msg (SE, _("CC%c: Custom currency string `%s' does not contain "
412 "exactly three periods or commas (not both)."),
416 else if (n_commas == 3)
428 /* Copy cc_string to cc, changing separators to nulls. */
432 strcpy (cc->buf, cc_string);
433 cp = cc->neg_prefix = cc->buf;
435 while (*cp++ != cc->grouping)
440 while (*cp++ != cc->grouping)
445 while (*cp++ != cc->grouping)
454 /* Sets *SETTING, which is a combination of SET_ROUTE_* bits that
455 indicates what to do with some sort of output, to the value
456 indicated by Q, which is a value provided by the input parser. */
458 set_routing (int q, int *setting)
463 *setting |= SET_ROUTE_DISABLE;
466 *setting &= ~SET_ROUTE_DISABLE;
469 *setting &= ~(SET_ROUTE_LISTING | SET_ROUTE_OTHER);
470 *setting |= SET_ROUTE_SCREEN;
473 *setting &= ~SET_ROUTE_SCREEN;
474 *setting |= SET_ROUTE_LISTING | SET_ROUTE_OTHER;
477 *setting |= SET_ROUTE_SCREEN | SET_ROUTE_LISTING | SET_ROUTE_OTHER;
480 *setting &= ~(SET_ROUTE_SCREEN | SET_ROUTE_LISTING | SET_ROUTE_OTHER);
488 stc_custom_pager (struct cmd_set *cmd unused)
491 #if !USE_INTERNAL_PAGER
492 if (lex_match_id ("OFF"))
500 if (!lex_force_string ())
504 set_pager = xstrdup (ds_value (&tokstr));
508 #else /* USE_INTERNAL_PAGER */
511 msg (SW, "External pagers not supported.");
513 #endif /* USE_INTERNAL_PAGER */
516 /* Parses the BLANKS subcommand, which controls the value that
517 completely blank fields in numeric data imply. X, Wnd: Syntax is
518 SYSMIS or a numeric value; PC+: Syntax is '.', which is equivalent
519 to SYSMIS, or a numeric value. */
521 stc_custom_blanks (struct cmd_set *cmd unused)
524 if ((token == T_ID && lex_id_match ("SYSMIS", tokid))
525 || (token == T_STRING && !strcmp (tokid, ".")))
532 if (!lex_force_num ())
541 stc_custom_length (struct cmd_set *cmd unused)
546 if (lex_match_id ("NONE"))
550 if (!lex_force_int ())
552 if (lex_integer () < 1)
554 msg (SE, _("LENGTH must be at least 1."));
557 page_length = lex_integer ();
561 /* FIXME: Set page length. */
566 stc_custom_results (struct cmd_set *cmd unused)
574 static struct tuple tab[] =
578 {"TERMINAL", STC_TERMINAL},
579 {"LISTING", STC_LISTING},
591 msg (SE, _("Missing identifier in RESULTS subcommand."));
595 for (t = tab; t->s; t++)
596 if (lex_id_match (t->s, tokid))
599 set_routing (t->v, &set_results);
602 msg (SE, _("Unrecognized identifier in RESULTS subcommand."));
607 stc_custom_seed (struct cmd_set *cmd unused)
610 if (lex_match_id ("RANDOM"))
614 if (!lex_force_num ())
623 stc_custom_width (struct cmd_set *cmd unused)
628 if (lex_match_id ("NARROW"))
630 else if (lex_match_id ("WIDE"))
634 if (!lex_force_int ())
636 if (lex_integer () < 1)
638 msg (SE, _("WIDTH must be at least 1."));
641 page_width = lex_integer ();
645 /* FIXME: Set page width. */
649 /* Parses FORMAT subcommand, which consists of a numeric format
652 stc_custom_format (struct cmd_set *cmd unused)
657 if (!parse_format_specifier (&fmt, 0))
659 if ((formats[fmt.type].cat & FCAT_STRING) != 0)
661 msg (SE, _("FORMAT requires numeric output format as an argument. "
662 "Specified format %s is of type string."),
663 fmt_to_string (&fmt));
672 stc_custom_journal (struct cmd_set *cmd unused)
675 if (lex_match_id ("ON"))
677 else if (lex_match_id ("OFF"))
679 if (token == T_STRING)
681 set_journal = xstrdup (ds_value (&tokstr));
687 /* Parses COLOR subcommand. PC+: either ON or OFF or two or three
688 comma-delimited numbers inside parentheses. */
690 stc_custom_color (struct cmd_set *cmd unused)
692 msg (MW, _("%s is obsolete."),"COLOR");
695 if (!lex_match_id ("ON") && !lex_match_id ("YES") && !lex_match_id ("OFF") && !lex_match_id ("NO"))
697 if (!lex_force_match ('('))
699 if (!lex_match ('*'))
701 if (!lex_force_int ())
703 if (lex_integer () < 0 || lex_integer () > 15)
705 msg (SE, _("Text color must be in range 0-15."));
710 if (!lex_force_match (','))
712 if (!lex_match ('*'))
714 if (!lex_force_int ())
716 if (lex_integer () < 0 || lex_integer () > 7)
718 msg (SE, _("Background color must be in range 0-7."));
723 if (lex_match (',') && !lex_match ('*'))
725 if (!lex_force_int ())
727 if (lex_integer () < 0 || lex_integer () > 7)
729 msg (SE, _("Border color must be in range 0-7."));
734 if (!lex_force_match (')'))
741 stc_custom_listing (struct cmd_set *cmd unused)
744 if (lex_match_id ("ON") || lex_match_id ("YES"))
745 outp_enable_device (1, OUTP_DEV_LISTING);
746 else if (lex_match_id ("OFF") || lex_match_id ("NO"))
747 outp_enable_device (0, OUTP_DEV_LISTING);
757 stc_custom_disk (struct cmd_set *cmd unused)
759 stc_custom_listing (cmd);
764 stc_custom_log (struct cmd_set *cmd unused)
766 stc_custom_journal (cmd);
771 stc_custom_rcolor (struct cmd_set *cmd unused)
773 msg (SW, _("%s is obsolete."),"RCOLOR");
776 if (!lex_force_match ('('))
779 if (!lex_match ('*'))
781 if (!lex_force_int ())
783 if (lex_integer () < 0 || lex_integer () > 6)
785 msg (SE, _("Lower window color must be between 0 and 6."));
790 if (!lex_force_match (','))
793 if (!lex_match ('*'))
795 if (!lex_force_int ())
797 if (lex_integer () < 0 || lex_integer () > 6)
799 msg (SE, _("Upper window color must be between 0 and 6."));
805 if (lex_match (',') && !lex_match ('*'))
807 if (!lex_force_int ())
809 if (lex_integer () < 0 || lex_integer () > 6)
811 msg (SE, _("Frame color must be between 0 and 6."));
820 stc_custom_viewlength (struct cmd_set *cmd unused)
822 if (lex_match_id ("MINIMUM"))
824 else if (lex_match_id ("MEDIAN"))
825 set_viewlength = 43; /* This is not correct for VGA displays. */
826 else if (lex_match_id ("MAXIMUM"))
830 if (!lex_force_int ())
833 if (lex_integer () >= (43 + 25) / 2)
838 set_viewlength = lex_integer ();
844 msg (SW, _("VIEWLENGTH not implemented."));
850 stc_custom_workdev (struct cmd_set *cmd unused)
854 msg (SW, _("%s is obsolete."),"WORKDEV");
857 for (*c = 'A'; *c <= 'Z'; (*c)++)
858 if (token == T_ID && lex_id_match (c, tokid))
863 msg (SE, _("Drive letter expected in WORKDEV subcommand."));