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
38 /* Global variables. */
39 struct string getl_buf;
40 struct getl_script *getl_head;
41 struct getl_script *getl_tail;
48 #include <readline/readline.h>
52 static char *history_file;
54 #if HAVE_READLINE_HISTORY_H
55 #include <readline/history.h>
56 #else /* no readline/history.h */
57 extern void add_history (char *);
58 extern void using_history (void);
59 extern int read_history (char *);
60 extern void stifle_history (int);
61 extern int write_history (char *);
62 #endif /* no readline/history.h */
63 #endif /* -lhistory */
66 extern struct cmd_set cmd;
68 static struct string getl_include_path;
70 /* Number of levels of DO REPEAT structures we're nested inside. If
71 this is greater than zero then DO REPEAT macro substitutions are
73 static int DO_REPEAT_level;
75 static int read_console (void);
77 /* Initialize getline. */
79 getl_initialize (void)
81 ds_create (&getl_include_path,
82 fn_getenv_default ("STAT_INCLUDE_PATH", include_path));
83 ds_init (&getl_buf, 256);
85 rl_completion_entry_function = pspp_completion_function;
91 getl_uninitialize (void)
94 #if HAVE_LIBHISTORY && defined (unix)
96 write_history (history_file);
98 ds_destroy (&getl_buf);
99 ds_destroy (&getl_include_path);
102 /* Returns a string that represents the directory that the syntax file
103 currently being read resides in. If there is no syntax file then
104 returns the OS current working directory. Return value must be
107 getl_get_current_directory (void)
109 return getl_head ? fn_dirname (getl_head->fn) : fn_get_cwd ();
112 /* Delete everything from the include path. */
114 getl_clear_include_path (void)
116 ds_clear (&getl_include_path);
119 /* Add to the include path. */
121 getl_add_include_dir (const char *path)
123 if (ds_length (&getl_include_path))
124 ds_putc (&getl_include_path, PATH_DELIMITER);
126 ds_puts (&getl_include_path, path);
129 /* Adds FN to the tail end of the list of script files to execute.
130 OPTIONS is the value to stick in the options field of the
131 getl_script struct. If WHERE is zero then the file is added after
132 all other files; otherwise it is added before all other files (this
133 can be done only if parsing has not yet begun). */
135 getl_add_file (const char *fn, int separate, int where)
137 struct getl_script *n = xmalloc (sizeof *n);
141 if (getl_tail == NULL)
142 getl_head = getl_tail = n;
144 getl_tail = getl_tail->next = n;
147 assert (getl_head->f == NULL);
151 n->included_from = n->includes = NULL;
152 n->fn = xstrdup (fn);
155 n->separate = separate;
156 n->first_line = NULL;
159 /* Inserts the given file with filename FN into the current file after
162 getl_include (const char *fn)
164 struct getl_script *n;
168 char *cur_dir = getl_get_current_directory ();
169 real_fn = fn_search_path (fn, ds_c_str (&getl_include_path), cur_dir);
175 msg (SE, _("Can't find `%s' in include file search path."), fn);
181 getl_add_file (real_fn, 0, 0);
186 n = xmalloc (sizeof *n);
187 n->included_from = getl_head;
188 getl_head = getl_head->includes = n;
195 n->first_line = NULL;
199 /* Add the virtual file FILE to the list of files to be processed.
200 The first_line field in FILE must already have been initialized. */
202 getl_add_virtual_file (struct getl_script *file)
204 if (getl_tail == NULL)
205 getl_head = getl_tail = file;
207 getl_tail = getl_tail->next = file;
208 file->included_from = file->includes = NULL;
210 file->fn = file->first_line->line;
211 file->ln = -file->first_line->len - 1;
214 file->cur_line = NULL;
215 file->remaining_loops = 1;
216 file->loop_index = -1;
220 /* Causes the DO REPEAT virtual file passed in FILE to be included in
221 the current file. The first_line, cur_line, remaining_loops,
222 loop_index, and macros fields in FILE must already have been
225 getl_add_DO_REPEAT_file (struct getl_script *file)
227 /* getl_head == NULL can't happen. */
231 file->included_from = getl_head;
232 getl_head = getl_head->includes = file;
233 file->includes = NULL;
235 assert (file->first_line->len < 0);
236 file->fn = file->first_line->line;
237 file->ln = -file->first_line->len - 1;
242 /* Display a welcoming message. */
247 fputs ("PSPP is free software and you are welcome to distribute copies of "
248 "it\nunder certain conditions; type \"show copying.\" to see the "
249 "conditions.\nThere is ABSOLUTELY NO WARRANTY for PSPP; type \"show "
250 "warranty.\" for details.\n", stdout);
254 /* Reads a single line from the user's terminal. */
257 extern void perform_DO_REPEAT_substitutions (void);
259 /* Reads a single line from the line buffer associated with getl_head.
260 Returns 1 if a line was successfully read or 0 if no more lines are
263 handle_line_buffer (void)
265 struct getl_script *s = getl_head;
267 /* Check that we're not all done. */
270 if (s->cur_line == NULL)
273 if (s->remaining_loops-- == 0)
275 s->cur_line = s->first_line;
278 if (s->cur_line->len < 0)
280 s->ln = -s->cur_line->len - 1;
281 s->fn = s->cur_line->line;
282 s->cur_line = s->cur_line->next;
286 while (s->cur_line == NULL);
288 ds_concat (&getl_buf, s->cur_line->line, s->cur_line->len);
290 /* Advance pointers. */
291 s->cur_line = s->cur_line->next;
297 /* Reads a single line into getl_buf from the list of files. Will not
298 read from the eof of one file to the beginning of another unless
299 the options field on the new file's getl_script is nonzero. Return
302 getl_read_line (void)
304 getl_mode = GETL_MODE_BATCH;
308 struct getl_script *s = getl_head;
310 ds_clear (&getl_buf);
316 if (!handle_line_buffer ())
321 perform_DO_REPEAT_substitutions ();
322 if (getl_head->print)
323 tab_output_text (TAB_LEFT | TAT_FIX | TAT_PRINTF, "+%s",
324 ds_c_str (&getl_buf));
330 msg (VM (1), _("%s: Opening as syntax file."), s->fn);
331 s->f = fn_open (s->fn, "r");
335 msg (ME, _("Opening `%s': %s."), s->fn, strerror (errno));
341 if (!ds_gets (&getl_buf, s->f))
344 msg (ME, _("Reading `%s': %s."), s->fn, strerror (errno));
348 if (ds_length (&getl_buf) > 0 && ds_end (&getl_buf)[-1] == '\n')
349 ds_truncate (&getl_buf, ds_length (&getl_buf) - 1);
352 tab_output_text (TAB_LEFT | TAT_FIX, ds_c_str (&getl_buf));
356 /* Allows shebang invocation: `#! /usr/local/bin/pspp'. */
357 if (ds_c_str (&getl_buf)[0] == '#'
358 && ds_c_str (&getl_buf)[1] == '!')
364 if (getl_interactive == 0)
367 getl_mode = GETL_MODE_INTERACTIVE;
369 if (getl_welcomed == 0)
372 return read_console ();
375 /* Closes the current file, whether it be a main file or included
376 file, then moves getl_head to the next file in the chain. */
378 getl_close_file (void)
380 struct getl_script *s = getl_head;
384 assert (getl_tail != NULL);
388 struct getl_line_list *cur, *next;
390 s->fn = NULL; /* It will be freed below. */
391 for (cur = s->first_line; cur; cur = next)
401 if (s->f && EOF == fn_close (s->fn, s->f))
402 msg (MW, _("Closing `%s': %s."), s->fn, strerror (errno));
405 if (s->included_from)
407 getl_head = s->included_from;
408 getl_head->includes = NULL;
413 if (NULL == getl_head)
420 /* PORTME: Adapt to your local system's idea of the terminal. */
423 #if HAVE_READLINE_READLINE_H
424 #include <readline/readline.h>
425 #else /* no readline/readline.h */
426 extern char *readline (char *);
427 #endif /* no readline/readline.h */
435 err_error_count = err_warning_count = 0;
436 err_already_flagged = 0;
442 history_file = tilde_expand (HISTORY_FILE);
445 read_history (history_file);
446 stifle_history (MAX_HISTORY);
448 #endif /* -lhistory */
452 case GETL_PRPT_STANDARD:
453 prompt = get_prompt();
456 case GETL_PRPT_CONTINUATION:
457 prompt = get_cprompt();
461 prompt = get_dprompt();
469 line = readline (prompt);
478 ds_clear (&getl_buf);
479 ds_puts (&getl_buf, line);
483 #else /* no -lreadline */
487 err_error_count = err_warning_count = 0;
488 err_already_flagged = 0;
490 fputs (getl_prompt ? get_cprompt() : get_prompt(), stdout);
491 ds_clear (&getl_buf);
492 if (ds_gets (&getl_buf, stdin))
496 msg (FE, "stdin: fgets(): %s.", strerror (errno));
500 #endif /* no -lreadline */
502 /* Closes all files. */
504 getl_close_all (void)
510 /* Sets the options flag of the current script to 0, thus allowing it
511 to be read in. Returns nonzero if this action was taken, zero
514 getl_perform_delayed_reset (void)
516 if (getl_head && getl_head->separate)
518 getl_head->separate = 0;
519 discard_variables ();
526 /* Puts the current file and line number in *FN and *LN, respectively,
527 or NULL and -1 if none. */
529 getl_location (const char **fn, int *ln)
532 *fn = getl_head ? getl_head->fn : NULL;
534 *ln = getl_head ? getl_head->ln : -1;