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., 51 Franklin Street, Fifth Floor, Boston, MA
21 #include <libpspp/message.h>
22 #include <language/command.h>
27 #include <libpspp/alloc.h>
28 #include <libpspp/compiler.h>
29 #include <data/dictionary.h>
30 #include <libpspp/message.h>
31 #include <language/lexer/lexer.h>
32 #include <data/settings.h>
33 #include <output/manager.h>
34 #include <libpspp/str.h>
35 #include <output/table.h>
36 #include <data/variable.h>
37 #include <procedure.h>
48 #define _(msgid) gettext (msgid)
49 #define N_(msgid) msgid
51 /* Global variables. */
53 /* A STATE_* constant giving the current program state. */
56 /* Static variables. */
58 /* A single command. */
61 const char *name; /* Command name. */
62 int transition[4]; /* Transitions to make from each state. */
63 int (*func) (void); /* Function to call. */
64 int skip_entire_name; /* If zero, we don't skip the
65 final token in the command name. */
66 short debug; /* Set if this cmd available only in test mode*/
69 /* Define the command array. */
70 #define DEFCMD(NAME, T1, T2, T3, T4, FUNC) \
71 {NAME, {T1, T2, T3, T4}, FUNC, 1, 0},
72 #define DBGCMD(NAME, T1, T2, T3, T4, FUNC) \
73 {NAME, {T1, T2, T3, T4}, FUNC, 1, 1},
74 #define SPCCMD(NAME, T1, T2, T3, T4, FUNC) \
75 {NAME, {T1, T2, T3, T4}, FUNC, 0, 0},
76 #define UNIMPL(NAME, T1, T2, T3, T4, DESC) \
77 {NAME, {T1, T2, T3, T4}, NULL, 1, 0},
78 static const struct command commands[] =
80 #include "command.def"
87 /* Complete the line using the name of a command,
88 * based upon the current prg_state
91 pspp_completion_function (const char *text, int state)
94 const struct command *cmd = 0;
98 if ( state + skip >= sizeof(commands)/ sizeof(struct command))
104 cmd = &commands[state + skip];
106 if ( cmd->transition[pgm_state] == STATE_ERROR || ( cmd->debug && ! get_testing_mode () ) )
112 if ( text == 0 || 0 == strncasecmp (cmd->name, text, strlen(text)))
121 return xstrdup(cmd->name);
126 #define COMMAND_CNT (sizeof commands / sizeof *commands)
128 /* Command parser. */
130 static const struct command *parse_command_name (void);
132 /* Determines whether command C is appropriate to call in this
133 part of a FILE TYPE structure. */
135 FILE_TYPE_okay (const struct command *c UNUSED)
140 if (c->func != cmd_record_type
141 && c->func != cmd_data_list
142 && c->func != cmd_repeating_data
143 && c->func != cmd_end_file_type)
144 msg (SE, _("%s not allowed inside FILE TYPE/END FILE TYPE."), c->name);
146 else if (c->func == cmd_repeating_data && fty.type == FTY_GROUPED)
147 msg (SE, _("%s not allowed inside FILE TYPE GROUPED/END FILE TYPE."),
149 else if (!fty.had_rec_type && c->func != cmd_record_type)
150 msg (SE, _("RECORD TYPE must be the first command inside a "
151 "FILE TYPE structure."));
155 if (c->func == cmd_record_type)
156 fty.had_rec_type = 1;
166 /* Parses an entire PSPP command. This includes everything from the
167 command name to the terminating dot. Does most of its work by
168 passing it off to the respective command dispatchers. Only called
169 by parse() in main.c. */
173 const struct command *cp; /* Iterator used to find the proper command. */
176 /* The generic alloca package performs garbage collection when it is
177 called with an argument of zero. */
179 #endif /* C_ALLOCA */
181 /* Null commands can result from extra empty lines. */
185 /* Parse comments. */
186 if ((token == T_ID && !strcasecmp (tokid, "COMMENT"))
187 || token == T_EXP || token == '*' || token == '[')
193 /* Otherwise the line must begin with a command name, which is
194 always an ID token. */
197 lex_error (_("expecting command name"));
201 /* Parse the command name. */
202 cp = parse_command_name ();
205 if (cp->func == NULL)
207 msg (SE, _("%s is not yet implemented."), cp->name);
208 while (token && token != '.')
213 /* If we're in a FILE TYPE structure, only certain commands can be
215 if (pgm_state == STATE_INPUT
216 && case_source_is_class (vfm_source, &file_type_source_class)
217 && !FILE_TYPE_okay (cp))
220 /* Certain state transitions are not allowed. Check for these. */
221 assert (pgm_state >= 0 && pgm_state < STATE_ERROR);
222 if (cp->transition[pgm_state] == STATE_ERROR)
224 static const char *state_name[4] =
226 N_("%s is not allowed (1) before a command to specify the "
227 "input program, such as DATA LIST, (2) between FILE TYPE "
228 "and END FILE TYPE, (3) between INPUT PROGRAM and END "
230 N_("%s is not allowed within an input program."),
231 N_("%s is only allowed within an input program."),
232 N_("%s is only allowed within an input program."),
235 msg (SE, gettext (state_name[pgm_state]), cp->name);
239 /* The structured output manager numbers all its tables. Increment
240 the major table number for each separate procedure. */
246 /* Call the command dispatcher. */
247 err_set_command_name (cp->name);
248 tab_set_command_name (cp->name);
249 result = cp->func ();
250 err_set_command_name (NULL);
251 tab_set_command_name (NULL);
253 /* Perform the state transition if the command completed
254 successfully (at least in part). */
255 if (result != CMD_FAILURE && result != CMD_CASCADING_FAILURE)
257 pgm_state = cp->transition[pgm_state];
259 if (pgm_state == STATE_ERROR)
261 discard_variables ();
262 pgm_state = STATE_INIT;
266 /* Pass the command's success value up to the caller. */
272 match_strings (const char *a, size_t a_len,
273 const char *b, size_t b_len)
275 size_t match_len = 0;
277 while (a_len > 0 && b_len > 0)
279 /* Mismatch always returns zero. */
280 if (toupper ((unsigned char) *a++) != toupper ((unsigned char) *b++))
292 /* Returns the first character in the first word in STRING,
293 storing the word's length in *WORD_LEN. If no words remain,
294 returns a null pointer and stores 0 in *WORD_LEN. Words are
295 sequences of alphanumeric characters or single
296 non-alphanumeric characters. Words are delimited by
299 find_word (const char *string, size_t *word_len)
301 /* Skip whitespace and asterisks. */
302 while (isspace ((unsigned char) *string))
312 /* Special one-character word? */
313 if (!isalnum ((unsigned char) *string))
319 /* Alphanumeric word. */
321 while (isalnum ((unsigned char) string[*word_len]))
327 /* Returns nonzero if strings A and B can be confused based on
328 their first three letters. */
330 conflicting_3char_prefixes (const char *a, const char *b)
332 size_t aw_len, bw_len;
335 aw = find_word (a, &aw_len);
336 bw = find_word (b, &bw_len);
337 assert (aw != NULL && bw != NULL);
339 /* Words that are the same don't conflict. */
340 if (aw_len == bw_len && !buf_compare_case (aw, bw, aw_len))
343 /* Words that are otherwise the same in the first three letters
345 return ((aw_len > 3 && bw_len > 3)
346 || (aw_len == 3 && bw_len > 3)
347 || (bw_len == 3 && aw_len > 3)) && !buf_compare_case (aw, bw, 3);
350 /* Returns nonzero if CMD can be confused with another command
351 based on the first three letters of its first word. */
353 conflicting_3char_prefix_command (const struct command *cmd)
355 assert (cmd >= commands && cmd < commands + COMMAND_CNT);
357 return ((cmd > commands
358 && conflicting_3char_prefixes (cmd[-1].name, cmd[0].name))
359 || (cmd < commands + COMMAND_CNT
360 && conflicting_3char_prefixes (cmd[0].name, cmd[1].name)));
363 /* Ways that a set of words can match a command name. */
366 MISMATCH, /* Not a match. */
367 PARTIAL_MATCH, /* The words begin the command name. */
368 COMPLETE_MATCH /* The words are the command name. */
371 /* Figures out how well the WORD_CNT words in WORDS match CMD,
372 and returns the appropriate enum value. If WORDS are a
373 partial match for CMD and the next word in CMD is a dash, then
374 *DASH_POSSIBLE is set to 1 if DASH_POSSIBLE is non-null;
375 otherwise, *DASH_POSSIBLE is unchanged. */
376 static enum command_match
377 cmd_match_words (const struct command *cmd,
378 char *const words[], size_t word_cnt,
385 for (word = find_word (cmd->name, &word_len), word_idx = 0;
386 word != NULL && word_idx < word_cnt;
387 word = find_word (word + word_len, &word_len), word_idx++)
388 if (word_len != strlen (words[word_idx])
389 || buf_compare_case (word, words[word_idx], word_len))
391 size_t match_chars = match_strings (word, word_len,
393 strlen (words[word_idx]));
394 if (match_chars == 0)
399 else if (match_chars == 1 || match_chars == 2)
401 /* One- and two-character abbreviations are not
405 else if (match_chars == 3)
407 /* Three-character abbreviations are acceptable
408 in the first word of a command if there are
409 no name conflicts. They are always
410 acceptable after the first word. */
411 if (word_idx == 0 && conflicting_3char_prefix_command (cmd))
414 else /* match_chars > 3 */
416 /* Four-character and longer abbreviations are
417 always acceptable. */
421 if (word == NULL && word_idx == word_cnt)
423 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR"}. */
424 return COMPLETE_MATCH;
426 else if (word == NULL)
428 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR", "BAZ"}. */
433 /* cmd->name = "FOO BAR BAZ", words[] = {"FOO", "BAR"}. */
434 if (word[0] == '-' && dash_possible != NULL)
436 return PARTIAL_MATCH;
440 /* Returns the number of commands for which the WORD_CNT words in
441 WORDS are a partial or complete match. If some partial match
442 has a dash as the next word, then *DASH_POSSIBLE is set to 1,
443 otherwise it is set to 0. */
445 count_matching_commands (char *const words[], size_t word_cnt,
448 const struct command *cmd;
453 for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++)
454 if (cmd_match_words (cmd, words, word_cnt, dash_possible) != MISMATCH)
457 return cmd_match_count;
460 /* Returns the command for which the WORD_CNT words in WORDS are
461 a complete match. Returns a null pointer if no such command
463 static const struct command *
464 get_complete_match (char *const words[], size_t word_cnt)
466 const struct command *cmd;
468 for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++)
469 if (cmd_match_words (cmd, words, word_cnt, NULL) == COMPLETE_MATCH)
475 /* Frees the WORD_CNT words in WORDS. */
477 free_words (char *words[], size_t word_cnt)
481 for (idx = 0; idx < word_cnt; idx++)
485 /* Flags an error that the command whose name is given by the
486 WORD_CNT words in WORDS is unknown. */
488 unknown_command_error (char *const words[], size_t word_cnt)
495 for (idx = 0; idx < word_cnt; idx++)
496 words_len += strlen (words[idx]);
498 cp = name = xmalloc (words_len + word_cnt + 16);
499 for (idx = 0; idx < word_cnt; idx++)
503 cp = stpcpy (cp, words[idx]);
507 msg (SE, _("Unknown command %s."), name);
513 /* Parse the command name and return a pointer to the corresponding
514 struct command if successful.
515 If not successful, return a null pointer. */
516 static const struct command *
517 parse_command_name (void)
521 int complete_word_cnt;
525 word_cnt = complete_word_cnt = 0;
526 while (token == T_ID || (dash_possible && token == '-'))
530 assert (word_cnt < sizeof words / sizeof *words);
532 words[word_cnt] = xstrdup (ds_c_str (&tokstr));
534 words[word_cnt] = xstrdup ("-");
535 str_uppercase (words[word_cnt]);
538 cmd_match_cnt = count_matching_commands (words, word_cnt,
540 if (cmd_match_cnt == 0)
542 else if (cmd_match_cnt == 1)
544 const struct command *command = get_complete_match (words, word_cnt);
547 if (command->skip_entire_name)
549 if ( command->debug & !get_testing_mode () )
551 free_words (words, word_cnt);
555 else /* cmd_match_cnt > 1 */
557 /* Do we have a complete command name so far? */
558 if (get_complete_match (words, word_cnt) != NULL)
559 complete_word_cnt = word_cnt;
564 /* If we saw a complete command name earlier, drop back to
566 if (complete_word_cnt)
568 int pushback_word_cnt;
569 const struct command *command;
571 /* Get the command. */
572 command = get_complete_match (words, complete_word_cnt);
573 assert (command != NULL);
575 /* Figure out how many words we want to keep.
576 We normally want to swallow the entire command. */
577 pushback_word_cnt = complete_word_cnt + 1;
578 if (!command->skip_entire_name)
581 /* FIXME: We only support one-token pushback. */
582 assert (pushback_word_cnt + 1 >= word_cnt);
584 while (word_cnt > pushback_word_cnt)
587 if (strcmp (words[word_cnt], "-"))
588 lex_put_back_id (words[word_cnt]);
591 free (words[word_cnt]);
594 if ( command->debug && !get_testing_mode () )
597 free_words (words, word_cnt);
602 unknown_command_error (words, word_cnt);
603 free_words (words, word_cnt);
607 /* Simple commands. */
609 /* Parse and execute FINISH command. */
616 /* Parses the N command. */
618 cmd_n_of_cases (void)
623 if (!lex_force_int ())
627 if (!lex_match_id ("ESTIMATED"))
628 dict_set_case_limit (default_dict, x);
630 return lex_end_of_command ();
633 /* Parses, performs the EXECUTE procedure. */
637 if (!procedure (NULL, NULL))
638 return CMD_CASCADING_FAILURE;
639 return lex_end_of_command ();
642 /* Parses, performs the ERASE command. */
646 if (get_safer_mode ())
648 msg (SE, _("This command not allowed when the SAFER option is set."));
652 if (!lex_force_match_id ("FILE"))
655 if (!lex_force_string ())
658 if (remove (ds_c_str (&tokstr)) == -1)
660 msg (SW, _("Error removing `%s': %s."),
661 ds_c_str (&tokstr), strerror (errno));
669 /* Spawn a shell process. */
680 const char *shell_fn;
686 for (i = 3; i < 20; i++)
690 shell_fn = getenv ("SHELL");
691 if (shell_fn == NULL)
692 shell_fn = "/bin/sh";
695 const char *cp = strrchr (shell_fn, '/');
696 cp = cp ? &cp[1] : shell_fn;
697 shell_process = local_alloc (strlen (cp) + 8);
698 strcpy (shell_process, "-");
699 strcat (shell_process, cp);
700 if (strcmp (cp, "sh"))
701 shell_process[0] = '+';
704 execl (shell_fn, shell_process, NULL);
710 msg (SE, _("Couldn't fork: %s."), strerror (errno));
715 while (wait (NULL) != pid)
722 /* Parses the HOST command argument and executes the specified
723 command. Returns a suitable command return code. */
730 /* Handle either a string argument or a full-line argument. */
732 int c = lex_look_ahead ();
734 if (c == '\'' || c == '"')
737 if (!lex_force_string ())
739 cmd = ds_c_str (&tokstr);
744 cmd = lex_rest_of_line (NULL);
750 /* Execute the command. */
751 if (system (cmd) == -1)
752 msg (SE, _("Error executing command: %s."), strerror (errno));
754 /* Finish parsing. */
761 lex_error (_("expecting end of command"));
762 return CMD_TRAILING_GARBAGE;
771 /* Parses, performs the HOST command. */
777 if (get_safer_mode ())
779 msg (SE, _("This command not allowed when the SAFER option is set."));
784 /* Figure out whether to invoke an interactive shell or to execute a
785 single shell command. */
786 if (lex_look_ahead () == '.')
789 code = shell () ? CMD_PART_SUCCESS_MAYBE : CMD_SUCCESS;
792 code = run_command ();
794 /* Make sure that the system has a command interpreter, then run a
796 if (system (NULL) != 0)
797 code = run_command ();
800 msg (SE, _("No operating system support for this command."));
808 /* Parses, performs the NEW FILE command. */
812 discard_variables ();
814 return lex_end_of_command ();
817 /* Parses, performs the CLEAR TRANSFORMATIONS command. */
819 cmd_clear_transformations (void)
821 cancel_transformations ();
822 /* FIXME: what about variables created by transformations?
823 They need to be properly initialized. */