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
47 #include "debug-print.h"
49 /* Global variables. */
51 /* A STATE_* constant giving the current program state. */
54 /* The name of the procedure currently executing, if any. */
57 /* Static variables. */
59 /* A single command. */
62 /* Initialized statically. */
63 char cmd[22]; /* Command name. */
64 int transition[4]; /* Transitions to make from each state. */
65 int (*func) (void); /* Function to call. */
67 /* Calculated at startup time. */
68 char *word[3]; /* cmd[], divided into individual words. */
69 struct command *next; /* Next command with same word[0]. */
72 /* Define the command array. */
73 #define DEFCMD(NAME, T1, T2, T3, T4, FUNC) \
74 {NAME, {T1, T2, T3, T4}, FUNC, {NULL, NULL, NULL}, NULL},
75 #define UNIMPL(NAME, T1, T2, T3, T4) \
76 {NAME, {T1, T2, T3, T4}, NULL, {NULL, NULL, NULL}, NULL},
77 static struct command cmd_table[] =
79 #include "command.def"
80 {"", {ERRO, ERRO, ERRO, ERRO}, NULL, {NULL, NULL, NULL}, NULL},
87 static struct command *figure_out_command (void);
89 /* Breaks the `cmd' member of C into individual words and sets C's
90 word[] member appropriately. */
92 split_words (struct command *c)
97 cmd = xstrdup (c->cmd);
98 for (i = 0; i < 3; i++)
99 cmd = c->word[i] = strtok_r (i == 0 ? cmd : NULL, " -", &save);
102 /* Initializes the command parser. */
108 /* Break up command names into words. */
109 for (c = cmd_table; c->cmd[0]; c++)
112 /* Make chains of commands having the same first word. */
113 for (c = cmd_table; c->cmd[0]; c++)
115 struct command *first;
116 for (first = c; c[1].word[0] && !strcmp (c[0].word[0], c[1].word[0]); c++)
123 /* Determines whether command C is appropriate to call in this
124 part of a FILE TYPE structure. */
126 FILE_TYPE_okay (struct command *c)
130 if (c->func != cmd_record_type
131 && c->func != cmd_data_list
132 && c->func != cmd_repeating_data
133 && c->func != cmd_end_file_type)
134 msg (SE, _("%s not allowed inside FILE TYPE/END FILE TYPE."), c->cmd);
137 else if (c->func == cmd_repeating_data && fty.type == FTY_GROUPED)
138 msg (SE, _("%s not allowed inside FILE TYPE GROUPED/END FILE TYPE."),
140 else if (!fty.had_rec_type && c->func != cmd_record_type)
141 msg (SE, _("RECORD TYPE must be the first command inside a "
142 "FILE TYPE structure."));
148 if (c->func == cmd_record_type)
149 fty.had_rec_type = 1;
155 /* Parses an entire PSPP command. This includes everything from the
156 command name to the terminating dot. Does most of its work by
157 passing it off to the respective command dispatchers. Only called
158 by parse() in main.c. */
162 struct command *cp; /* Iterator used to find the proper command. */
165 /* The generic alloca package performs garbage collection when it is
166 called with an argument of zero. */
168 #endif /* C_ALLOCA */
170 /* Null commands can result from extra empty lines. */
174 /* Parse comments. */
175 if ((token == T_ID && !strcmp (tokid, "COMMENT"))
176 || token == T_EXP || token == '*' || token == '[')
182 /* Otherwise the line must begin with a command name, which is
183 always an ID token. */
186 msg (SE, _("This line does not begin with a valid command name."));
190 /* Parse the command name. */
191 cp = figure_out_command ();
194 if (cp->func == NULL)
196 msg (SE, _("%s is not yet implemented."), cp->cmd);
197 while (token && token != '.')
202 /* If we're in a FILE TYPE structure, only certain commands can be
204 if (pgm_state == STATE_INPUT && vfm_source == &file_type_source
205 && !FILE_TYPE_okay (cp))
208 /* Certain state transitions are not allowed. Check for these. */
209 assert (pgm_state >= 0 && pgm_state < STATE_ERROR);
210 if (cp->transition[pgm_state] == STATE_ERROR)
212 static const char *state_name[4] =
214 N_("%s is not allowed (1) before a command to specify the "
215 "input program, such as DATA LIST, (2) between FILE TYPE "
216 "and END FILE TYPE, (3) between INPUT PROGRAM and END "
218 N_("%s is not allowed within an input program."),
219 N_("%s is only allowed within an input program."),
220 N_("%s is only allowed within an input program."),
223 msg (SE, gettext (state_name[pgm_state]), cp->cmd);
228 if (cp->func != cmd_remark)
229 printf (_("%s command beginning\n"), cp->cmd);
232 /* The structured output manager numbers all its tables. Increment
233 the major table number for each separate procedure. */
239 /* Call the command dispatcher. Save and restore the name of
240 the current command around this call. */
242 const char *prev_proc;
244 prev_proc = cur_proc;
246 result = cp->func ();
247 cur_proc = prev_proc;
250 /* Perform the state transition if the command completed
251 successfully (at least in part). */
254 pgm_state = cp->transition[pgm_state];
256 if (pgm_state == STATE_ERROR)
258 discard_variables ();
259 pgm_state = STATE_INIT;
264 if (cp->func != cmd_remark)
265 printf (_("%s command completed\n\n"), cp->cmd);
268 /* Pass the command's success value up to the caller. */
273 /* Parse the command name and return a pointer to the corresponding
274 struct command if successful.
275 If not successful, return a null pointer. */
276 static struct command *
277 figure_out_command (void)
279 static const char *unk =
280 N_("The identifier(s) specified do not form a valid command name:");
282 static const char *inc =
283 N_("The identifier(s) specified do not form a complete command name:");
287 /* Parse the INCLUDE short form.
288 Note that `@' is a valid character in identifiers. */
290 return &cmd_table[0];
292 /* Find a command whose first word matches this identifier.
293 If it is the only command that begins with this word, return
295 for (cp = cmd_table; cp->cmd[0]; cp++)
296 if (lex_id_match (cp->word[0], tokid))
299 if (cp->cmd[0] == '\0')
301 msg (SE, "%s %s.", gettext (unk), ds_value (&tokstr));
305 if (cp->next == NULL)
308 /* We know that there is more than one command starting with this
309 word. Read the next word in the command name. */
311 struct command *ocp = cp;
313 /* Verify that the next token is an identifier, because we
314 must disambiguate this command name. */
318 /* If there's a command whose name is the first word only,
319 return it. This happens with, i.e., PRINT vs. PRINT
321 if (ocp->word[1] == NULL)
324 msg (SE, "%s %s.", gettext (inc), ds_value (&tokstr));
328 for (; cp; cp = cp->next)
329 if (cp->word[1] && lex_id_match (cp->word[1], tokid))
334 /* No match. If there's a command whose name is the first
335 word only, return it. This happens with, i.e., PRINT
337 if (ocp->word[1] == NULL)
340 msg (SE, "%s %s %s.", gettext (unk), ocp->word[0], tokid);
344 /* Check whether the next token is an identifier.
346 if (!isalpha ((unsigned char) (lex_look_ahead ())))
348 /* Check whether there is an unambiguous interpretation.
349 If not, give an error. */
352 && !strcmp (cp->word[1], cp->next->word[1]))
354 msg (SE, "%s %s %s.", gettext (inc), ocp->word[0], ocp->word[1]);
362 /* If this command can have a third word, disambiguate based on it. */
366 && !strcmp (cp->word[1], cp->next->word[1])))
368 struct command *ocp = cp;
371 assert (token == T_ID);
373 /* Try to find a command with this third word.
375 for (; cp; cp = cp->next)
377 && !strcmp (cp->word[1], ocp->word[1])
378 && lex_id_match (cp->word[2], tokid))
384 /* If no command with this third word found, make sure that
385 there's a command with those first two words but without a
390 msg (SE, "%s %s %s %s.",
391 gettext (unk), ocp->word[0], ocp->word[1], ds_value (&tokstr));
399 /* Simple commands. */
401 /* Parse and execute EXIT command. */
405 if (getl_reading_script)
407 msg (SE, _("This command is not accepted in a syntax file. "
408 "Instead, use FINISH to terminate a syntax file."));
417 /* Parse and execute FINISH command. */
421 /* Do not check for `.'
422 Do not fetch any extra tokens. */
423 if (getl_interactive)
425 msg (SM, _("This command is not executed "
426 "in interactive mode. Instead, PSPP drops "
427 "down to the command prompt. Use EXIT if you really want "
437 /* Extracts a null-terminated 8-or-fewer-character PREFIX from STRING.
438 PREFIX is converted to lowercase. Removes trailing spaces from
439 STRING as a side effect. */
441 extract_prefix (char *string, char *prefix)
443 /* Length of STRING. */
446 /* Points to the null terminator in STRING (`end pointer'). */
449 /* Strip spaces from end of STRING. */
450 len = strlen (string);
451 while (len && isspace ((unsigned char) string[len - 1]))
454 /* Find null terminator. */
455 ep = memchr (string, '\0', 8);
459 /* Copy prefix, converting to lowercase. */
461 *prefix++ = tolower ((unsigned char) (*string++));
465 /* Prints STRING on the console and to the listing file, replacing \n
468 output_line (char *string)
470 /* Location of \n in line read in. */
473 cp = strstr (string, "\\n");
477 tab_output_text (TAB_LEFT | TAT_NOWRAP, string);
479 cp = strstr (string, "\\n");
481 tab_output_text (TAB_LEFT | TAT_NOWRAP, string);
484 /* Parse and execute REMARK command. */
488 /* Points to the line read in. */
494 /* 8-character sentinel used to terminate remark. */
497 /* Beginning of line used to compare with SENTINEL. */
502 s = lex_rest_of_line (NULL);
509 /* Read in SENTINEL from end of current line. */
511 while (isspace ((unsigned char) *cp))
513 extract_prefix (cp, sentinel);
514 if (sentinel[0] == 0)
516 msg (SE, _("The sentinel may not be the empty string."));
520 /* Read in other lines until we encounter the sentinel. */
521 while (getl_read_line ())
523 extract_prefix (ds_value (&getl_buf), prefix);
524 if (!strcmp (sentinel, prefix))
527 /* Output the line. */
528 output_line (ds_value (&getl_buf));
531 /* Calling lex_entire_line() forces the sentinel line to be
533 getl_prompt = GETL_PRPT_STANDARD;
539 /* Parses the N command. */
541 cmd_n_of_cases (void)
548 lex_match_id ("CASES");
549 if (!lex_force_int ())
553 if (!lex_match_id ("ESTIMATED"))
554 dict_set_case_limit (default_dict, x);
556 return lex_end_of_command ();
559 /* Parses, performs the EXECUTE procedure. */
563 lex_match_id ("EXECUTE");
564 procedure (NULL, NULL, NULL);
565 return lex_end_of_command ();
568 /* Parses, performs the ERASE command. */
574 msg (SE, _("This command not allowed when the SAFER option is set."));
578 lex_match_id ("ERASE");
579 if (!lex_force_match_id ("FILE"))
582 if (!lex_force_string ())
585 if (remove (ds_value (&tokstr)) == -1)
587 msg (SW, _("Error removing `%s': %s."),
588 ds_value (&tokstr), strerror (errno));
592 return lex_end_of_command ();
596 /* Spawn a shell process. */
607 const char *shell_fn;
613 for (i = 3; i < 20; i++)
617 shell_fn = getenv ("SHELL");
618 if (shell_fn == NULL)
619 shell_fn = "/bin/sh";
622 const char *cp = strrchr (shell_fn, '/');
623 cp = cp ? &cp[1] : shell_fn;
624 shell_process = local_alloc (strlen (cp) + 8);
625 strcpy (shell_process, "-");
626 strcat (shell_process, cp);
627 if (strcmp (cp, "sh"))
628 shell_process[0] = '+';
631 execl (shell_fn, shell_process, NULL);
637 msg (SE, _("Couldn't fork: %s."), strerror (errno));
642 while (wait (NULL) != pid)
649 /* Parses the HOST command argument and executes the specified
650 command. Returns a suitable command return code. */
657 /* Handle either a string argument or a full-line argument. */
659 int c = lex_look_ahead ();
661 if (c == '\'' || c == '"')
664 if (!lex_force_string ())
666 cmd = ds_value (&tokstr);
671 cmd = lex_rest_of_line (NULL);
676 /* Execute the command. */
677 if (system (cmd) == -1)
678 msg (SE, _("Error executing command: %s."), strerror (errno));
680 /* Finish parsing. */
687 lex_error (_("expecting end of command"));
688 return CMD_TRAILING_GARBAGE;
697 /* Parses, performs the HOST command. */
705 msg (SE, _("This command not allowed when the SAFER option is set."));
709 lex_match_id ("HOST");
712 /* Figure out whether to invoke an interactive shell or to execute a
713 single shell command. */
714 if (lex_look_ahead () == '.')
717 code = shell () ? CMD_PART_SUCCESS_MAYBE : CMD_SUCCESS;
720 code = run_command ();
722 /* Make sure that the system has a command interpreter, then run a
724 if (system (NULL) != 0)
725 success = run_command ();
728 msg (SE, _("No operating system support for this command."));
729 success = CMD_FAILURE;
733 return code ? CMD_FAILURE : CMD_SUCCESS;
736 /* Parses, performs the NEW FILE command. */
740 lex_match_id ("NEW");
741 lex_match_id ("FILE");
743 discard_variables ();
745 return lex_end_of_command ();
748 /* Parses, performs the CLEAR TRANSFORMATIONS command. */
750 cmd_clear_transformations (void)
752 lex_match_id ("CLEAR");
753 lex_match_id ("TRANSFORMATIONS");
755 if (getl_reading_script)
757 msg (SW, _("This command is not valid in a syntax file."));
761 cancel_transformations ();