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
39 #define _(msgid) gettext (msgid)
41 /* Global variables. */
42 struct string getl_buf;
43 struct getl_script *getl_head;
44 struct getl_script *getl_tail;
51 #include <readline/readline.h>
55 static char *history_file;
57 #if HAVE_READLINE_HISTORY_H
58 #include <readline/history.h>
59 #else /* no readline/history.h */
60 extern void add_history (char *);
61 extern void using_history (void);
62 extern int read_history (char *);
63 extern void stifle_history (int);
64 extern int write_history (char *);
65 #endif /* no readline/history.h */
66 #endif /* -lhistory */
69 extern struct cmd_set cmd;
71 static struct string getl_include_path;
73 /* Number of levels of DO REPEAT structures we're nested inside. If
74 this is greater than zero then DO REPEAT macro substitutions are
76 static int DO_REPEAT_level;
78 static int read_console (void);
80 /* Initialize getl. */
82 getl_initialize (void)
84 ds_create (&getl_include_path,
85 fn_getenv_default ("STAT_INCLUDE_PATH", include_path));
86 ds_init (&getl_buf, 256);
88 rl_completion_entry_function = pspp_completion_function;
94 getl_uninitialize (void)
97 #if HAVE_LIBHISTORY && defined (unix)
99 write_history (history_file);
101 ds_destroy (&getl_buf);
102 ds_destroy (&getl_include_path);
105 /* Returns a string that represents the directory that the syntax file
106 currently being read resides in. If there is no syntax file then
107 returns the OS current working directory. Return value must be
110 getl_get_current_directory (void)
112 return getl_head ? fn_dirname (getl_head->fn) : fn_get_cwd ();
115 /* Delete everything from the include path. */
117 getl_clear_include_path (void)
119 ds_clear (&getl_include_path);
122 /* Add to the include path. */
124 getl_add_include_dir (const char *path)
126 if (ds_length (&getl_include_path))
127 ds_putc (&getl_include_path, PATH_DELIMITER);
129 ds_puts (&getl_include_path, path);
132 /* Adds FN to the tail end of the list of script files to execute.
133 OPTIONS is the value to stick in the options field of the
134 getl_script struct. If WHERE is zero then the file is added after
135 all other files; otherwise it is added before all other files (this
136 can be done only if parsing has not yet begun). */
138 getl_add_file (const char *fn, int separate, int where)
140 struct getl_script *n = xmalloc (sizeof *n);
144 if (getl_tail == NULL)
145 getl_head = getl_tail = n;
147 getl_tail = getl_tail->next = n;
150 assert (getl_head->f == NULL);
154 n->included_from = n->includes = NULL;
155 n->fn = xstrdup (fn);
158 n->separate = separate;
159 n->first_line = NULL;
162 /* Inserts the given file with filename FN into the current file after
165 getl_include (const char *fn)
167 struct getl_script *n;
171 char *cur_dir = getl_get_current_directory ();
172 real_fn = fn_search_path (fn, ds_c_str (&getl_include_path), cur_dir);
178 msg (SE, _("Can't find `%s' in include file search path."), fn);
184 getl_add_file (real_fn, 0, 0);
189 n = xmalloc (sizeof *n);
190 n->included_from = getl_head;
191 getl_head = getl_head->includes = n;
198 n->first_line = NULL;
202 /* Add the virtual file FILE to the list of files to be processed.
203 The first_line field in FILE must already have been initialized. */
205 getl_add_virtual_file (struct getl_script *file)
207 if (getl_tail == NULL)
208 getl_head = getl_tail = file;
210 getl_tail = getl_tail->next = file;
211 file->included_from = file->includes = NULL;
213 file->fn = file->first_line->line;
214 file->ln = -file->first_line->len - 1;
217 file->cur_line = NULL;
218 file->remaining_loops = 1;
219 file->loop_index = -1;
223 /* Causes the DO REPEAT virtual file passed in FILE to be included in
224 the current file. The first_line, cur_line, remaining_loops,
225 loop_index, and macros fields in FILE must already have been
228 getl_add_DO_REPEAT_file (struct getl_script *file)
230 /* getl_head == NULL can't happen. */
234 file->included_from = getl_head;
235 getl_head = getl_head->includes = file;
236 file->includes = NULL;
238 assert (file->first_line->len < 0);
239 file->fn = file->first_line->line;
240 file->ln = -file->first_line->len - 1;
245 /* Display a welcoming message. */
250 fputs ("PSPP is free software and you are welcome to distribute copies of "
251 "it\nunder certain conditions; type \"show copying.\" to see the "
252 "conditions.\nThere is ABSOLUTELY NO WARRANTY for PSPP; type \"show "
253 "warranty.\" for details.\n", stdout);
257 /* Reads a single line from the user's terminal. */
260 extern void perform_DO_REPEAT_substitutions (void);
262 /* Reads a single line from the line buffer associated with getl_head.
263 Returns 1 if a line was successfully read or 0 if no more lines are
266 handle_line_buffer (void)
268 struct getl_script *s = getl_head;
270 /* Check that we're not all done. */
273 if (s->cur_line == NULL)
276 if (s->remaining_loops-- == 0)
278 s->cur_line = s->first_line;
281 if (s->cur_line->len < 0)
283 s->ln = -s->cur_line->len - 1;
284 s->fn = s->cur_line->line;
285 s->cur_line = s->cur_line->next;
289 while (s->cur_line == NULL);
291 ds_concat (&getl_buf, s->cur_line->line, s->cur_line->len);
293 /* Advance pointers. */
294 s->cur_line = s->cur_line->next;
300 /* Reads a single line into getl_buf from the list of files. Will not
301 read from the eof of one file to the beginning of another unless
302 the options field on the new file's getl_script is nonzero. Return
305 getl_read_line (void)
307 getl_mode = GETL_MODE_BATCH;
311 struct getl_script *s = getl_head;
313 ds_clear (&getl_buf);
319 if (!handle_line_buffer ())
324 perform_DO_REPEAT_substitutions ();
325 if (getl_head->print)
326 tab_output_text (TAB_LEFT | TAT_FIX | TAT_PRINTF, "+%s",
327 ds_c_str (&getl_buf));
333 msg (VM (1), _("%s: Opening as syntax file."), s->fn);
334 s->f = fn_open (s->fn, "r");
338 msg (ME, _("Opening `%s': %s."), s->fn, strerror (errno));
344 if (!ds_gets (&getl_buf, s->f))
347 msg (ME, _("Reading `%s': %s."), s->fn, strerror (errno));
351 if (ds_length (&getl_buf) > 0 && ds_end (&getl_buf)[-1] == '\n')
352 ds_truncate (&getl_buf, ds_length (&getl_buf) - 1);
355 tab_output_text (TAB_LEFT | TAT_FIX, ds_c_str (&getl_buf));
359 /* Allows shebang invocation: `#! /usr/local/bin/pspp'. */
360 if (ds_c_str (&getl_buf)[0] == '#'
361 && ds_c_str (&getl_buf)[1] == '!')
367 if (getl_interactive == 0)
370 getl_mode = GETL_MODE_INTERACTIVE;
372 if (getl_welcomed == 0)
375 return read_console ();
378 /* Closes the current file, whether it be a main file or included
379 file, then moves getl_head to the next file in the chain. */
381 getl_close_file (void)
383 struct getl_script *s = getl_head;
387 assert (getl_tail != NULL);
391 struct getl_line_list *cur, *next;
393 s->fn = NULL; /* It will be freed below. */
394 for (cur = s->first_line; cur; cur = next)
404 if (s->f && EOF == fn_close (s->fn, s->f))
405 msg (MW, _("Closing `%s': %s."), s->fn, strerror (errno));
408 if (s->included_from)
410 getl_head = s->included_from;
411 getl_head->includes = NULL;
416 if (NULL == getl_head)
423 /* PORTME: Adapt to your local system's idea of the terminal. */
426 #if HAVE_READLINE_READLINE_H
427 #include <readline/readline.h>
428 #else /* no readline/readline.h */
429 extern char *readline (char *);
430 #endif /* no readline/readline.h */
438 err_error_count = err_warning_count = 0;
439 err_already_flagged = 0;
445 history_file = tilde_expand (HISTORY_FILE);
448 read_history (history_file);
449 stifle_history (MAX_HISTORY);
451 #endif /* -lhistory */
455 case GETL_PRPT_STANDARD:
456 prompt = get_prompt();
459 case GETL_PRPT_CONTINUATION:
460 prompt = get_cprompt();
464 prompt = get_dprompt();
472 line = readline (prompt);
481 ds_clear (&getl_buf);
482 ds_puts (&getl_buf, line);
488 #else /* no -lreadline */
492 err_error_count = err_warning_count = 0;
493 err_already_flagged = 0;
495 fputs (getl_prompt ? get_cprompt() : get_prompt(), stdout);
496 ds_clear (&getl_buf);
497 if (ds_gets (&getl_buf, stdin))
501 msg (FE, "stdin: fgets(): %s.", strerror (errno));
505 #endif /* no -lreadline */
507 /* Closes all files. */
509 getl_close_all (void)
515 /* Sets the options flag of the current script to 0, thus allowing it
516 to be read in. Returns nonzero if this action was taken, zero
519 getl_perform_delayed_reset (void)
521 if (getl_head && getl_head->separate)
523 getl_head->separate = 0;
524 discard_variables ();
531 /* Puts the current file and line number in *FN and *LN, respectively,
532 or NULL and -1 if none. */
534 getl_location (const char **fn, int *ln)
537 *fn = getl_head ? getl_head->fn : NULL;
539 *ln = getl_head ? getl_head->ln : -1;