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, _("%s is not yet implemented."),"TBFONTS");
316 msg (SW, _("%s is not yet implemented."),"TB1");
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 ())
625 stc_custom_width (struct cmd_set *cmd UNUSED)
630 if (lex_match_id ("NARROW"))
632 else if (lex_match_id ("WIDE"))
636 if (!lex_force_int ())
638 if (lex_integer () < 1)
640 msg (SE, _("WIDTH must be at least 1."));
643 page_width = lex_integer ();
647 /* FIXME: Set page width. */
651 /* Parses FORMAT subcommand, which consists of a numeric format
654 stc_custom_format (struct cmd_set *cmd UNUSED)
659 if (!parse_format_specifier (&fmt, 0))
661 if ((formats[fmt.type].cat & FCAT_STRING) != 0)
663 msg (SE, _("FORMAT requires numeric output format as an argument. "
664 "Specified format %s is of type string."),
665 fmt_to_string (&fmt));
674 stc_custom_journal (struct cmd_set *cmd UNUSED)
677 if (lex_match_id ("ON"))
679 else if (lex_match_id ("OFF"))
681 if (token == T_STRING)
683 set_journal = xstrdup (ds_value (&tokstr));
689 /* Parses COLOR subcommand. PC+: either ON or OFF or two or three
690 comma-delimited numbers inside parentheses. */
692 stc_custom_color (struct cmd_set *cmd UNUSED)
694 msg (MW, _("%s is obsolete."),"COLOR");
697 if (!lex_match_id ("ON") && !lex_match_id ("YES") && !lex_match_id ("OFF") && !lex_match_id ("NO"))
699 if (!lex_force_match ('('))
701 if (!lex_match ('*'))
703 if (!lex_force_int ())
705 if (lex_integer () < 0 || lex_integer () > 15)
707 msg (SE, _("Text color must be in range 0-15."));
712 if (!lex_force_match (','))
714 if (!lex_match ('*'))
716 if (!lex_force_int ())
718 if (lex_integer () < 0 || lex_integer () > 7)
720 msg (SE, _("Background color must be in range 0-7."));
725 if (lex_match (',') && !lex_match ('*'))
727 if (!lex_force_int ())
729 if (lex_integer () < 0 || lex_integer () > 7)
731 msg (SE, _("Border color must be in range 0-7."));
736 if (!lex_force_match (')'))
743 stc_custom_listing (struct cmd_set *cmd UNUSED)
746 if (lex_match_id ("ON") || lex_match_id ("YES"))
747 outp_enable_device (1, OUTP_DEV_LISTING);
748 else if (lex_match_id ("OFF") || lex_match_id ("NO"))
749 outp_enable_device (0, OUTP_DEV_LISTING);
759 stc_custom_disk (struct cmd_set *cmd UNUSED)
761 stc_custom_listing (cmd);
766 stc_custom_log (struct cmd_set *cmd UNUSED)
768 stc_custom_journal (cmd);
773 stc_custom_rcolor (struct cmd_set *cmd UNUSED)
775 msg (SW, _("%s is obsolete."),"RCOLOR");
778 if (!lex_force_match ('('))
781 if (!lex_match ('*'))
783 if (!lex_force_int ())
785 if (lex_integer () < 0 || lex_integer () > 6)
787 msg (SE, _("Lower window color must be between 0 and 6."));
792 if (!lex_force_match (','))
795 if (!lex_match ('*'))
797 if (!lex_force_int ())
799 if (lex_integer () < 0 || lex_integer () > 6)
801 msg (SE, _("Upper window color must be between 0 and 6."));
807 if (lex_match (',') && !lex_match ('*'))
809 if (!lex_force_int ())
811 if (lex_integer () < 0 || lex_integer () > 6)
813 msg (SE, _("Frame color must be between 0 and 6."));
822 stc_custom_viewlength (struct cmd_set *cmd UNUSED)
824 if (lex_match_id ("MINIMUM"))
826 else if (lex_match_id ("MEDIAN"))
827 set_viewlength = 43; /* This is not correct for VGA displays. */
828 else if (lex_match_id ("MAXIMUM"))
832 if (!lex_force_int ())
835 if (lex_integer () >= (43 + 25) / 2)
840 set_viewlength = lex_integer ();
846 msg (SW, _("%s is not yet implemented."),"VIEWLENGTH");
852 stc_custom_workdev (struct cmd_set *cmd UNUSED)
856 msg (SW, _("%s is obsolete."),"WORKDEV");
859 for (*c = 'A'; *c <= 'Z'; (*c)++)
860 if (token == T_ID && lex_id_match (c, tokid))
865 msg (SE, _("Drive letter expected in WORKDEV subcommand."));