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;
118 int set_testing_mode;
123 static void set_routing (int q, int *setting);
124 static int set_ccx (const char *cc_string, struct set_cust_currency * cc,
129 automenu=automenu:on/off;
132 block=string "x==1" "one character long";
133 boxstring=string "x==3 || x==11" "3 or 11 characters long";
134 case=size:upper/uplow;
141 compression=compress:on/off;
144 decimal=dec:dot/_comma;
149 endcmd=string "x==1" "one character long";
150 errorbreak=errbrk:on/off;
151 errors=errors:on/off/terminal/listing/both/none;
153 headers=headers:no/yes/blank;
154 helpwindows=helpwin:on/off;
155 highres=hires:on/off;
156 histogram=string "x==1" "one character long";
162 lowres=lores:auto/on/off;
164 menus=menus:standard/extended;
165 messages=messages:on/off/terminal/listing/both/none;
170 mprint=mprint:on/off;
177 printback=prtbck:on/off;
180 ptranslate=ptrans:on/off;
183 runreview=runrev:auto/manual;
185 scompression=scompress:on/off;
187 scripttab=string "x==1" "one character long";
189 tb1=string "x==3 || x==11" "3 or 11 characters long";
191 undefined=undef:warn/nowarn;
203 int internal_cmd_set (void);
210 lex_match_id ("SET");
212 if (!parse_set (&cmd))
216 msg (SW, _("%s is obsolete."),"BLOCK");
218 if (cmd.sbc_boxstring)
219 msg (SW, _("%s is obsolete."),"BOXSTRING");
221 if (cmd.compress != -1)
223 msg (MW, _("Active file compression is not yet implemented "
224 "(and probably won't be)."));
225 set_compression = cmd.compress == STC_OFF ? 0 : 1;
227 if (cmd.scompress != -1)
228 set_scompression = cmd.scompress == STC_OFF ? 0 : 1;
229 if (cmd.n_cpi != NOT_LONG)
232 msg (SE, _("CPI must be greater than 0."));
236 if (cmd.sbc_histogram)
237 msg (MW, _("%s is obsolete."),"HISTOGRAM");
238 if (cmd.n_lpi != NOT_LONG)
241 msg (SE, _("LPI must be greater than 0."));
246 /* Windows compatible syntax. */
248 msg (SW, _("CASE is not implemented and probably won't be. If you care, "
249 "complain about it."));
251 set_ccx (cmd.s_cca, &set_cc[0], 'A');
253 set_ccx (cmd.s_ccb, &set_cc[1], 'B');
255 set_ccx (cmd.s_ccc, &set_cc[2], 'C');
257 set_ccx (cmd.s_ccd, &set_cc[3], 'D');
259 set_ccx (cmd.s_cce, &set_cc[4], 'E');
262 set_decimal = cmd.dec == STC_DOT ? '.' : ',';
263 set_grouping = cmd.dec == STC_DOT ? ',' : '.';
265 if (cmd.errors != -1)
266 set_routing (cmd.errors, &set_errors);
267 if (cmd.headers != -1)
268 set_headers = cmd.headers == STC_NO ? 0 : (cmd.headers == STC_YES ? 1 : 2);
269 if (cmd.messages != -1)
270 set_routing (cmd.messages, &set_messages);
272 set_mexpand = cmd.mexp == STC_OFF ? 0 : 1;
273 if (cmd.n_miterate != NOT_LONG)
275 if (cmd.n_miterate > 0)
276 set_miterate = cmd.n_miterate;
278 msg (SE, _("Value for MITERATE (%ld) must be greater than 0."),
281 if (cmd.n_mnest != NOT_LONG)
284 set_mnest = cmd.n_mnest;
286 msg (SE, _("Value for MNEST (%ld) must be greater than 0."),
289 if (cmd.mprint != -1)
290 set_mprint = cmd.mprint == STC_OFF ? 0 : 1;
291 if (cmd.n_mxerrs != NOT_LONG)
294 msg (SE, _("MXERRS must be at least 1."));
296 set_mxerrs = cmd.n_mxerrs;
298 if (cmd.n_mxloops != NOT_LONG)
301 msg (SE, _("MXLOOPS must be at least 1."));
303 set_mxloops = cmd.n_mxloops;
305 if (cmd.n_mxmemory != NOT_LONG)
306 msg (SE, _("%s is obsolete."),"MXMEMORY");
307 if (cmd.n_mxwarns != NOT_LONG)
308 set_mxwarns = cmd.n_mxwarns;
309 if (cmd.prtbck != -1)
310 set_printback = cmd.prtbck == STC_OFF ? 0 : 1;
312 msg (SE, _("%s is obsolete."),"SCRIPTTAB");
314 msg (SW, _("TBFONTS not implemented."));
316 msg (SW, _("TB1 not implemented."));
318 set_undefined = cmd.undef == STC_NOWARN ? 0 : 1;
319 if (cmd.n_workspace != NOT_LONG)
320 msg (SE, _("%s is obsolete."),"WORKSPACE");
322 /* PC+ compatible syntax. */
324 outp_enable_device (cmd.scrn == STC_OFF ? 0 : 1, OUTP_DEV_SCREEN);
326 if (cmd.automenu != -1)
327 msg (SW, _("%s is obsolete."),"AUTOMENU");
329 msg (SW, _("%s is obsolete."),"BEEP");
334 set_cprompt = cmd.s_cprompt;
335 cmd.s_cprompt = NULL;
340 set_dprompt = cmd.s_dprompt;
341 cmd.s_dprompt = NULL;
344 set_echo = cmd.echo == STC_OFF ? 0 : 1;
346 set_endcmd = cmd.s_endcmd[0];
348 msg (SW, _("%s is obsolete."),"EJECT");
349 if (cmd.errbrk != -1)
350 set_errorbreak = cmd.errbrk == STC_OFF ? 0 : 1;
351 if (cmd.helpwin != -1)
352 msg (SW, _("%s is obsolete."),"HELPWINDOWS");
354 set_include = cmd.inc == STC_OFF ? 0 : 1;
356 msg (MW, _("%s is obsolete."),"MENUS");
358 set_nullline = cmd.null == STC_OFF ? 0 : 1;
360 set_more = cmd.more == STC_OFF ? 0 : 1;
362 outp_enable_device (cmd.prtr == STC_OFF ? 0 : 1, OUTP_DEV_PRINTER);
366 set_prompt = cmd.s_prompt;
369 if (cmd.ptrans != -1)
370 msg (SW, _("%s is obsolete."),"PTRANSLATE");
371 if (cmd.runrev != -1)
372 msg (SW, _("%s is obsolete."),"RUNREVIEW");
373 if (cmd.safe == STC_ON)
376 msg (SW, _("%s is obsolete."),"XSORT");
383 /* Sets custom currency specifier CC having name CC_NAME ('A' through
384 'E') to correspond to the settings in CC_STRING. */
386 set_ccx (const char *cc_string, struct set_cust_currency * cc, int cc_name)
388 if (strlen (cc_string) > 16)
390 msg (SE, _("CC%c: Length of custom currency string `%s' (%d) "
391 "exceeds maximum length of 16."),
392 cc_name, cc_string, strlen (cc_string));
396 /* Determine separators. */
399 int n_commas, n_periods;
401 /* Count the number of commas and periods. There must be exactly
402 three of one or the other. */
403 n_commas = n_periods = 0;
404 for (sp = cc_string; *sp; sp++)
410 if (!((n_commas == 3) ^ (n_periods == 3)))
412 msg (SE, _("CC%c: Custom currency string `%s' does not contain "
413 "exactly three periods or commas (not both)."),
417 else if (n_commas == 3)
429 /* Copy cc_string to cc, changing separators to nulls. */
433 strcpy (cc->buf, cc_string);
434 cp = cc->neg_prefix = cc->buf;
436 while (*cp++ != cc->grouping)
441 while (*cp++ != cc->grouping)
446 while (*cp++ != cc->grouping)
455 /* Sets *SETTING, which is a combination of SET_ROUTE_* bits that
456 indicates what to do with some sort of output, to the value
457 indicated by Q, which is a value provided by the input parser. */
459 set_routing (int q, int *setting)
464 *setting |= SET_ROUTE_DISABLE;
467 *setting &= ~SET_ROUTE_DISABLE;
470 *setting &= ~(SET_ROUTE_LISTING | SET_ROUTE_OTHER);
471 *setting |= SET_ROUTE_SCREEN;
474 *setting &= ~SET_ROUTE_SCREEN;
475 *setting |= SET_ROUTE_LISTING | SET_ROUTE_OTHER;
478 *setting |= SET_ROUTE_SCREEN | SET_ROUTE_LISTING | SET_ROUTE_OTHER;
481 *setting &= ~(SET_ROUTE_SCREEN | SET_ROUTE_LISTING | SET_ROUTE_OTHER);
489 stc_custom_pager (struct cmd_set *cmd unused)
492 #if !USE_INTERNAL_PAGER
493 if (lex_match_id ("OFF"))
501 if (!lex_force_string ())
505 set_pager = xstrdup (ds_value (&tokstr));
509 #else /* USE_INTERNAL_PAGER */
512 msg (SW, "External pagers not supported.");
514 #endif /* USE_INTERNAL_PAGER */
517 /* Parses the BLANKS subcommand, which controls the value that
518 completely blank fields in numeric data imply. X, Wnd: Syntax is
519 SYSMIS or a numeric value; PC+: Syntax is '.', which is equivalent
520 to SYSMIS, or a numeric value. */
522 stc_custom_blanks (struct cmd_set *cmd unused)
525 if ((token == T_ID && lex_id_match ("SYSMIS", tokid))
526 || (token == T_STRING && !strcmp (tokid, ".")))
533 if (!lex_force_num ())
542 stc_custom_length (struct cmd_set *cmd unused)
547 if (lex_match_id ("NONE"))
551 if (!lex_force_int ())
553 if (lex_integer () < 1)
555 msg (SE, _("LENGTH must be at least 1."));
558 page_length = lex_integer ();
562 /* FIXME: Set page length. */
567 stc_custom_results (struct cmd_set *cmd unused)
575 static struct tuple tab[] =
579 {"TERMINAL", STC_TERMINAL},
580 {"LISTING", STC_LISTING},
592 msg (SE, _("Missing identifier in RESULTS subcommand."));
596 for (t = tab; t->s; t++)
597 if (lex_id_match (t->s, tokid))
600 set_routing (t->v, &set_results);
603 msg (SE, _("Unrecognized identifier in RESULTS subcommand."));
608 stc_custom_seed (struct cmd_set *cmd unused)
611 if (lex_match_id ("RANDOM"))
615 if (!lex_force_num ())
624 stc_custom_width (struct cmd_set *cmd unused)
629 if (lex_match_id ("NARROW"))
631 else if (lex_match_id ("WIDE"))
635 if (!lex_force_int ())
637 if (lex_integer () < 1)
639 msg (SE, _("WIDTH must be at least 1."));
642 page_width = lex_integer ();
646 /* FIXME: Set page width. */
650 /* Parses FORMAT subcommand, which consists of a numeric format
653 stc_custom_format (struct cmd_set *cmd unused)
658 if (!parse_format_specifier (&fmt, 0))
660 if ((formats[fmt.type].cat & FCAT_STRING) != 0)
662 msg (SE, _("FORMAT requires numeric output format as an argument. "
663 "Specified format %s is of type string."),
664 fmt_to_string (&fmt));
673 stc_custom_journal (struct cmd_set *cmd unused)
676 if (lex_match_id ("ON"))
678 else if (lex_match_id ("OFF"))
680 if (token == T_STRING)
682 set_journal = xstrdup (ds_value (&tokstr));
688 /* Parses COLOR subcommand. PC+: either ON or OFF or two or three
689 comma-delimited numbers inside parentheses. */
691 stc_custom_color (struct cmd_set *cmd unused)
693 msg (MW, _("%s is obsolete."),"COLOR");
696 if (!lex_match_id ("ON") && !lex_match_id ("YES") && !lex_match_id ("OFF") && !lex_match_id ("NO"))
698 if (!lex_force_match ('('))
700 if (!lex_match ('*'))
702 if (!lex_force_int ())
704 if (lex_integer () < 0 || lex_integer () > 15)
706 msg (SE, _("Text color must be in range 0-15."));
711 if (!lex_force_match (','))
713 if (!lex_match ('*'))
715 if (!lex_force_int ())
717 if (lex_integer () < 0 || lex_integer () > 7)
719 msg (SE, _("Background color must be in range 0-7."));
724 if (lex_match (',') && !lex_match ('*'))
726 if (!lex_force_int ())
728 if (lex_integer () < 0 || lex_integer () > 7)
730 msg (SE, _("Border color must be in range 0-7."));
735 if (!lex_force_match (')'))
742 stc_custom_listing (struct cmd_set *cmd unused)
745 if (lex_match_id ("ON") || lex_match_id ("YES"))
746 outp_enable_device (1, OUTP_DEV_LISTING);
747 else if (lex_match_id ("OFF") || lex_match_id ("NO"))
748 outp_enable_device (0, OUTP_DEV_LISTING);
758 stc_custom_disk (struct cmd_set *cmd unused)
760 stc_custom_listing (cmd);
765 stc_custom_log (struct cmd_set *cmd unused)
767 stc_custom_journal (cmd);
772 stc_custom_rcolor (struct cmd_set *cmd unused)
774 msg (SW, _("%s is obsolete."),"RCOLOR");
777 if (!lex_force_match ('('))
780 if (!lex_match ('*'))
782 if (!lex_force_int ())
784 if (lex_integer () < 0 || lex_integer () > 6)
786 msg (SE, _("Lower window color must be between 0 and 6."));
791 if (!lex_force_match (','))
794 if (!lex_match ('*'))
796 if (!lex_force_int ())
798 if (lex_integer () < 0 || lex_integer () > 6)
800 msg (SE, _("Upper window color must be between 0 and 6."));
806 if (lex_match (',') && !lex_match ('*'))
808 if (!lex_force_int ())
810 if (lex_integer () < 0 || lex_integer () > 6)
812 msg (SE, _("Frame color must be between 0 and 6."));
821 stc_custom_viewlength (struct cmd_set *cmd unused)
823 if (lex_match_id ("MINIMUM"))
825 else if (lex_match_id ("MEDIAN"))
826 set_viewlength = 43; /* This is not correct for VGA displays. */
827 else if (lex_match_id ("MAXIMUM"))
831 if (!lex_force_int ())
834 if (lex_integer () >= (43 + 25) / 2)
839 set_viewlength = lex_integer ();
845 msg (SW, _("VIEWLENGTH not implemented."));
851 stc_custom_workdev (struct cmd_set *cmd unused)
855 msg (SW, _("%s is obsolete."),"WORKDEV");
858 for (*c = 'A'; *c <= 'Z'; (*c)++)
859 if (token == T_ID && lex_id_match (c, tokid))
864 msg (SE, _("Drive letter expected in WORKDEV subcommand."));