From b8b67a1e1f709640ccdb3422a591b938edb0ceea Mon Sep 17 00:00:00 2001 From: John Darrington Date: Wed, 29 Nov 2006 12:19:07 +0000 Subject: [PATCH] Oops. committing new files --- src/language/line-buffer.c | 587 ------------------------------------- src/language/line-buffer.h | 69 ----- src/language/prompt.c | 101 +++++++ src/language/prompt.h | 44 +++ src/language/syntax-file.c | 155 ++++++++++ src/language/syntax-file.h | 34 +++ src/libpspp/getl.c | 233 +++++++++++++++ src/libpspp/getl.h | 74 +++++ src/libpspp/msg-locator.c | 85 ++++++ src/libpspp/msg-locator.h | 36 +++ 10 files changed, 762 insertions(+), 656 deletions(-) delete mode 100644 src/language/line-buffer.c delete mode 100644 src/language/line-buffer.h create mode 100644 src/language/prompt.c create mode 100644 src/language/prompt.h create mode 100644 src/language/syntax-file.c create mode 100644 src/language/syntax-file.h create mode 100644 src/libpspp/getl.c create mode 100644 src/libpspp/getl.h create mode 100644 src/libpspp/msg-locator.c create mode 100644 src/libpspp/msg-locator.h diff --git a/src/language/line-buffer.c b/src/language/line-buffer.c deleted file mode 100644 index 0dcb70f9..00000000 --- a/src/language/line-buffer.c +++ /dev/null @@ -1,587 +0,0 @@ -/* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ - -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "gettext.h" -#define _(msgid) gettext (msgid) - -/* Source file. */ -struct getl_source - { - struct getl_source *included_from; /* File that this is nested inside. */ - struct getl_source *includes; /* File nested inside this file. */ - struct getl_source *next; /* Next file in list. */ - - /* Current location. */ - char *fn; /* File name. */ - int ln; /* Line number. */ - - enum getl_source_type - { - SYNTAX_FILE, - FILTER, - FUNCTION, - INTERACTIVE - } - type; - - union - { - /* SYNTAX_FILE. */ - FILE *syntax_file; - - /* FILTER. */ - struct - { - void (*filter) (struct string *line, void *aux); - void (*close) (void *aux); - void *aux; - } - filter; - - /* FUNCTION. */ - struct - { - bool (*read) (struct string *line, char **fn, int *ln, void *aux); - void (*close) (void *aux); - void *aux; - } - function; - - /* INTERACTIVE. */ - bool (*interactive) (struct string *line, enum getl_prompt_style); - } - u; - - }; - -/* List of source files. */ -static struct getl_source *cur_source; -static struct getl_source *last_source; - -static struct string getl_include_path; - - -static void close_source (void); - -static void init_prompts (void); -static void uninit_prompts (void); -static enum getl_prompt_style get_prompt_style (void); - - -/* Initialize getl. */ -void -getl_initialize (void) -{ - ds_init_cstr (&getl_include_path, - fn_getenv_default ("STAT_INCLUDE_PATH", include_path)); - init_prompts (); -} - - -/* Delete everything from the include path. */ -void -getl_clear_include_path (void) -{ - ds_clear (&getl_include_path); -} - -/* Add to the include path. */ -void -getl_add_include_dir (const char *path) -{ - if (ds_length (&getl_include_path)) - ds_put_char (&getl_include_path, ':'); - - ds_put_cstr (&getl_include_path, path); -} - -/* Appends source S to the list of source files. */ -static void -append_source (struct getl_source *s) -{ - s->included_from = s->includes = s->next = NULL; - if (last_source == NULL) - cur_source = s; - else - last_source->next = s; - last_source = s; -} - -/* Nests source S within the current source file. */ -static void -include_source (struct getl_source *s) -{ - if (last_source == NULL) - append_source (s); - else - { - s->included_from = cur_source; - s->includes = s->next = NULL; - s->next = NULL; - cur_source->includes = s; - cur_source = s; - } -} - -/* Creates a source of the given TYPE. - Type-specific data must be initialized by the caller. */ -static struct getl_source * -create_source (enum getl_source_type type) -{ - struct getl_source *s = xmalloc (sizeof *s); - s->fn = NULL; - s->ln = 0; - s->type = type; - return s; -} - -/* Creates a syntax file source with file name FN. */ -static struct getl_source * -create_syntax_file_source (const char *fn) -{ - struct getl_source *s = create_source (SYNTAX_FILE); - s->fn = xstrdup (fn); - s->u.syntax_file = NULL; - return s; -} - -/* Creates a filter source with the given FILTER and CLOSE - functions that receive auxiliary data AUX. */ -static struct getl_source * -create_filter_source (void (*filter) (struct string *, void *aux), - void (*close) (void *aux), - void *aux) -{ - struct getl_source *s = create_source (FILTER); - s->u.filter.filter = filter; - s->u.filter.close = close; - s->u.filter.aux = aux; - return s; -} - -/* Creates a function source with the given READ and CLOSE - functions that receive auxiliary data AUX. */ -static struct getl_source * -create_function_source (bool (*read) (struct string *line, - char **fn, int *ln, void *aux), - void (*close) (void *aux), - void *aux) -{ - struct getl_source *s = create_source (FUNCTION); - s->u.function.read = read; - s->u.function.close = close; - s->u.function.aux = aux; - return s; -} - -/* Creates an interactive source with the given FUNCTION. */ -static struct getl_source * -create_interactive_source (bool (*function) (struct string *line, - enum getl_prompt_style)) -{ - struct getl_source *s = xmalloc (sizeof *s); - s->fn = NULL; - s->ln = 0; - s->type = INTERACTIVE; - s->u.interactive = function; - return s; -} - -/* Adds FN to the tail end of the list of source files to - execute. */ -void -getl_append_syntax_file (const char *fn) -{ - append_source (create_syntax_file_source (fn)); -} - -/* Inserts the given file with name FN into the current file - after the current line. */ -void -getl_include_syntax_file (const char *fn) -{ - if (cur_source != NULL) - { - char *found_fn = fn_search_path (fn, ds_cstr (&getl_include_path), - fn_dir_name (cur_source->fn)); - if (found_fn != NULL) - { - include_source (create_syntax_file_source (found_fn)); - free (found_fn); - } - else - msg (SE, _("Can't find `%s' in include file search path."), fn); - } - else - getl_append_syntax_file (fn); -} - -/* Inserts the given filter into the current file after the - current line. Each line read while the filter is in place - will be passed through FILTER, which may modify it as - necessary. When the filter is closed, CLOSE will be called. - AUX will be passed to both functions. - - The filter cannot itself output any new lines, and it will be - closed as soon as any line would be read from it. This means - that, for a filter to be useful, another source must be nested - inside it with, e.g., getl_include_syntax_file(). */ -void -getl_include_filter (void (*filter) (struct string *, void *aux), - void (*close) (void *aux), - void *aux) -{ - include_source (create_filter_source (filter, close, aux)); -} - -/* Inserts the given functional source into the current file - after the current line. Lines are read by calling READ, which - should write the next line in LINE, store the file name and - line number of the line in *FN and *LN, and return true. The - string stored in *FN will not be freed by getl. When no lines - are left, READ should return false. - - When the source is closed, CLOSE will be called. - - AUX will be passed to both READ and CLOSE. */ -void -getl_include_function (bool (*read) (struct string *line, - char **fn, int *ln, void *aux), - void (*close) (void *aux), - void *aux) -{ - include_source (create_function_source (read, close, aux)); -} - -/* Adds an interactive source to the end of the list of sources. - FUNCTION will be called to obtain a line. It should store the - line in LINE. PROMPT is the prompt to be displayed to the - user. FUNCTION should return true when a line has been - obtained or false at end of file. */ -void -getl_append_interactive (bool (*function) (struct string *line, - enum getl_prompt_style)) -{ - append_source (create_interactive_source (function)); -} - -/* Closes all sources until an interactive source is - encountered. */ -void -getl_abort_noninteractive (void) -{ - while (cur_source != NULL && cur_source->type != INTERACTIVE) - close_source (); -} - -/* Returns true if the current source is interactive, - false otherwise. */ -bool -getl_is_interactive (void) -{ - return cur_source != NULL && cur_source->type == INTERACTIVE; -} - -/* Closes the current file, whether it be a main file or included - file, then moves cur_source to the next file in the chain. */ -static void -close_source (void) -{ - struct getl_source *s; - - s = cur_source; - switch (s->type) - { - case SYNTAX_FILE: - if (s->u.syntax_file && EOF == fn_close (s->fn, s->u.syntax_file)) - msg (MW, _("Closing `%s': %s."), s->fn, strerror (errno)); - free (s->fn); - break; - - case FILTER: - if (s->u.filter.close != NULL) - s->u.filter.close (s->u.filter.aux); - break; - - case FUNCTION: - if (s->u.function.close != NULL) - s->u.function.close (s->u.function.aux); - break; - - case INTERACTIVE: - break; - } - - if (s->included_from != NULL) - { - cur_source = s->included_from; - cur_source->includes = NULL; - } - else - { - cur_source = s->next; - if (cur_source == NULL) - last_source = NULL; - } - - free (s); -} - -/* Puts the current file and line number in *FN and *LN, respectively, - or NULL and -1 if none. */ -void -getl_location (const char **fn, int *ln) -{ - if (fn != NULL) - *fn = cur_source ? cur_source->fn : ""; - if (ln != NULL) - *ln = cur_source ? cur_source->ln : -1; -} - -/* File locator stack. */ -static const struct msg_locator **file_loc; - -static int nfile_loc, mfile_loc; - -/* Close getl. */ -void -getl_uninitialize (void) -{ - while (cur_source != NULL) - close_source (); - ds_destroy (&getl_include_path); - free(file_loc); - file_loc = NULL; - nfile_loc = mfile_loc = 0; - uninit_prompts (); -} - - -/* File locator stack functions. */ - -/* Pushes F onto the stack of file locations. */ -void -msg_push_msg_locator (const struct msg_locator *loc) -{ - if (nfile_loc >= mfile_loc) - { - if (mfile_loc == 0) - mfile_loc = 8; - else - mfile_loc *= 2; - - file_loc = xnrealloc (file_loc, mfile_loc, sizeof *file_loc); - } - - file_loc[nfile_loc++] = loc; -} - -/* Pops F off the stack of file locations. - Argument F is only used for verification that that is actually the - item on top of the stack. */ -void -msg_pop_msg_locator (const struct msg_locator *loc) -{ - assert (nfile_loc >= 0 && file_loc[nfile_loc - 1] == loc); - nfile_loc--; -} - -/* Puts the current file and line number into LOC, or NULL and -1 if - none. */ -void -get_msg_location (struct msg_locator *loc) -{ - if (nfile_loc) - *loc = *file_loc[nfile_loc - 1]; - else - getl_location (&loc->file_name, &loc->line_number); -} - -/* Reads a line from syntax file source S into LINE. - Returns true if successful, false at end of file. */ -static bool -read_syntax_file (struct string *line, struct getl_source *s) -{ - /* Open file, if not yet opened. */ - if (s->u.syntax_file == NULL) - { - verbose_msg (1, _("opening \"%s\" as syntax file"), s->fn); - s->u.syntax_file = fn_open (s->fn, "r"); - - if (s->u.syntax_file == NULL) - { - msg (ME, _("Opening `%s': %s."), s->fn, strerror (errno)); - return false; - } - } - - /* Read line from file and remove new-line. - Skip initial "#! /usr/bin/pspp" line. */ - do - { - s->ln++; - if (!ds_read_line (line, s->u.syntax_file)) - { - if (ferror (s->u.syntax_file)) - msg (ME, _("Reading `%s': %s."), s->fn, strerror (errno)); - return false; - } - ds_chomp (line, '\n'); - } - while (s->ln == 1 && !memcmp (ds_cstr (line), "#!", 2)); - - /* Echo to listing file, if configured to do so. */ - if (get_echo ()) - tab_output_text (TAB_LEFT | TAB_FIX, ds_cstr (line)); - - return true; -} - -/* Reads a line from source S into LINE. - Returns true if successful, false at end of file. */ -static bool -read_line_from_source (struct string *line, struct getl_source *s) -{ - ds_clear (line); - switch (s->type) - { - case SYNTAX_FILE: - return read_syntax_file (line, s); - case FILTER: - return false; - case FUNCTION: - return s->u.function.read (line, &s->fn, &s->ln, s->u.function.aux); - case INTERACTIVE: - return s->u.interactive (line, get_prompt_style ()); - } - - NOT_REACHED (); -} - -/* Reads a single line into LINE. - Returns true when a line has been read, false at end of input. - If INTERACTIVE is non-null, then when true is returned - *INTERACTIVE will be set to true if the line was obtained - interactively, false otherwise. */ -bool -do_read_line (struct string *line, bool *interactive) -{ - while (cur_source != NULL) - { - struct getl_source *s = cur_source; - if (read_line_from_source (line, s)) - { - if (interactive != NULL) - *interactive = s->type == INTERACTIVE; - - while ((s = s->included_from) != NULL) - if (s->type == FILTER) - s->u.filter.filter (line, s->u.filter.aux); - - return true; - } - close_source (); - } - - return false; -} - - -/* Current prompts in each style. */ -static char *prompts[GETL_PROMPT_CNT]; - -/* Current prompting style. */ -static enum getl_prompt_style current_style; - -/* Initializes prompts. */ -static void -init_prompts (void) -{ - prompts[GETL_PROMPT_FIRST] = xstrdup ("PSPP> "); - prompts[GETL_PROMPT_LATER] = xstrdup (" > "); - prompts[GETL_PROMPT_DATA] = xstrdup ("data> "); - current_style = GETL_PROMPT_FIRST; -} - -/* Frees prompts. */ -static void -uninit_prompts (void) -{ - int i; - - for (i = 0; i < GETL_PROMPT_CNT; i++) - { - free (prompts[i]); - prompts[i] = NULL; - } -} - -/* Gets the command prompt for the given STYLE. */ -const char * -getl_get_prompt (enum getl_prompt_style style) -{ - assert (style < GETL_PROMPT_CNT); - return prompts[style]; -} - -/* Sets the given STYLE's prompt to STRING. */ -void -getl_set_prompt (enum getl_prompt_style style, const char *string) -{ - assert (style < GETL_PROMPT_CNT); - free (prompts[style]); - prompts[style] = xstrdup (string); -} - -/* Sets STYLE as the current prompt style. */ -void -getl_set_prompt_style (enum getl_prompt_style style) -{ - assert (style < GETL_PROMPT_CNT); - current_style = style; -} - -/* Returns the current prompt. */ -static enum getl_prompt_style -get_prompt_style (void) -{ - return current_style; -} diff --git a/src/language/line-buffer.h b/src/language/line-buffer.h deleted file mode 100644 index ee3db559..00000000 --- a/src/language/line-buffer.h +++ /dev/null @@ -1,69 +0,0 @@ -/* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ - -#ifndef GETL_H -#define GETL_H 1 - -#include -#include - -enum getl_prompt_style - { - GETL_PROMPT_FIRST, /* First line of command. */ - GETL_PROMPT_LATER, /* Second or later line of command. */ - GETL_PROMPT_DATA, /* Between BEGIN DATA and END DATA. */ - GETL_PROMPT_CNT - }; - - -void getl_initialize (void); -void getl_uninitialize (void); - -void getl_clear_include_path (void); -void getl_add_include_dir (const char *); - -void getl_append_syntax_file (const char *); -void getl_include_syntax_file (const char *); -void getl_include_filter (void (*filter) (struct string *, void *aux), - void (*close) (void *aux), - void *aux); -void getl_include_function (bool (*read) (struct string *line, - char **fn, int *ln, void *aux), - void (*close) (void *aux), - void *aux); -void getl_append_interactive (bool (*function) (struct string *line, - enum getl_prompt_style)); -void getl_abort_noninteractive (void); -bool getl_is_interactive (void); - -bool getl_read_line (bool *interactive); - -const char *getl_get_prompt (enum getl_prompt_style); -void getl_set_prompt (enum getl_prompt_style, const char *); -void getl_set_prompt_style (enum getl_prompt_style); - -struct msg_locator; -void get_msg_location (struct msg_locator *loc); - -void getl_location (const char **fn, int *ln); - -bool do_read_line (struct string *line, bool *interactive); - - -#endif /* line-buffer.h */ diff --git a/src/language/prompt.c b/src/language/prompt.c new file mode 100644 index 00000000..5640c508 --- /dev/null +++ b/src/language/prompt.c @@ -0,0 +1,101 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include + +#include +#include +#include + +#include "prompt.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Current prompts in each style. */ +static char *prompts[PROMPT_CNT]; + +/* Current prompting style. */ +static enum prompt_style current_style; + +/* Initializes prompts. */ +void +prompt_init (void) +{ + prompts[PROMPT_FIRST] = xstrdup ("PSPP> "); + prompts[PROMPT_LATER] = xstrdup (" > "); + prompts[PROMPT_DATA] = xstrdup ("data> "); + current_style = PROMPT_FIRST; +} + +/* Frees prompts. */ +void +prompt_done (void) +{ + int i; + + for (i = 0; i < PROMPT_CNT; i++) + { + free (prompts[i]); + prompts[i] = NULL; + } +} + +/* Gets the command prompt for the given STYLE. */ +const char * +prompt_get (enum prompt_style style) +{ + assert (style < PROMPT_CNT); + return prompts[style]; +} + +/* Sets the given STYLE's prompt to STRING. */ +void +prompt_set (enum prompt_style style, const char *string) +{ + assert (style < PROMPT_CNT); + free (prompts[style]); + prompts[style] = xstrdup (string); +} + +/* Sets STYLE as the current prompt style. */ +void +prompt_set_style (enum prompt_style style) +{ + assert (style < PROMPT_CNT); + current_style = style; +} + +/* Returns the current prompt. */ +enum prompt_style +prompt_get_style (void) +{ + return current_style; +} diff --git a/src/language/prompt.h b/src/language/prompt.h new file mode 100644 index 00000000..e10c3241 --- /dev/null +++ b/src/language/prompt.h @@ -0,0 +1,44 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef PROMPT_H +#define PROMPT_H 1 + +#include + +enum prompt_style + { + PROMPT_FIRST, /* First line of command. */ + PROMPT_LATER, /* Second or later line of command. */ + PROMPT_DATA, /* Between BEGIN DATA and END DATA. */ + PROMPT_CNT + }; + + +void prompt_init (void); +void prompt_done (void); + +enum prompt_style prompt_get_style (void); + +const char *prompt_get (enum prompt_style); +void prompt_set (enum prompt_style, const char *); +void prompt_set_style (enum prompt_style); + + +#endif /* PROMPT_H */ diff --git a/src/language/syntax-file.c b/src/language/syntax-file.c new file mode 100644 index 00000000..e41466ce --- /dev/null +++ b/src/language/syntax-file.c @@ -0,0 +1,155 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include + +#include "syntax-file.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "prompt.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +#include + + +struct syntax_file_source + { + struct getl_interface parent ; + + FILE *syntax_file; + + /* Current location. */ + char *fn; /* File name. */ + int ln; /* Line number. */ + }; + +static const char * +name (const struct getl_interface *s) +{ + const struct syntax_file_source *sfs = (const struct syntax_file_source *) s; + return sfs->fn; +} + +static int +line_number (const struct getl_interface *s) +{ + const struct syntax_file_source *sfs = (const struct syntax_file_source *) s; + return sfs->ln; +} + + +/* Reads a line from syntax file source S into LINE. + Returns true if successful, false at end of file. */ +bool +read_syntax_file (struct getl_interface *s, struct string *line) +{ + struct syntax_file_source *sfs = (struct syntax_file_source *) s; + + /* Open file, if not yet opened. */ + if (sfs->syntax_file == NULL) + { + verbose_msg (1, _("opening \"%s\" as syntax file"), sfs->fn); + sfs->syntax_file = fn_open (sfs->fn, "r"); + + if (sfs->syntax_file == NULL) + { + msg (ME, _("Opening `%s': %s."), sfs->fn, strerror (errno)); + return false; + } + } + + /* Read line from file and remove new-line. + Skip initial "#! /usr/bin/pspp" line. */ + do + { + sfs->ln++; + if (!ds_read_line (line, sfs->syntax_file)) + { + if (ferror (sfs->syntax_file)) + msg (ME, _("Reading `%s': %s."), sfs->fn, strerror (errno)); + return false; + } + ds_chomp (line, '\n'); + } + while (sfs->ln == 1 && !memcmp (ds_cstr (line), "#!", 2)); + + /* Echo to listing file, if configured to do so. */ + if (get_echo ()) + tab_output_text (TAB_LEFT | TAB_FIX, ds_cstr (line)); + + return true; +} + +static void +syntax_close (struct getl_interface *s) +{ + struct syntax_file_source *sfs = (struct syntax_file_source *) s; + + if (sfs->syntax_file && EOF == fn_close (sfs->fn, sfs->syntax_file)) + msg (MW, _("Closing `%s': %s."), sfs->fn, strerror (errno)); + free (sfs->fn); + free (sfs); +} + +static bool +always_false (const struct getl_interface *s UNUSED) +{ + return false; +} + + +/* Creates a syntax file source with file name FN. */ +struct getl_interface * +create_syntax_file_source (const char *fn) +{ + struct syntax_file_source *ss = xzalloc (sizeof (*ss)); + + ss->fn = xstrdup (fn); + + ss->parent.interactive = always_false; + ss->parent.read = read_syntax_file ; + ss->parent.filter = NULL; + ss->parent.close = syntax_close ; + ss->parent.name = name ; + ss->parent.location = line_number; + + return (struct getl_interface *) ss; +} + diff --git a/src/language/syntax-file.h b/src/language/syntax-file.h new file mode 100644 index 00000000..c09af216 --- /dev/null +++ b/src/language/syntax-file.h @@ -0,0 +1,34 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#if !SYNTAX_FILE +#define SYNTAX_FILE 1 + +#include + +struct string; +struct getl_interface; +struct getl_source; + +bool read_syntax_file (struct getl_interface *s, struct string *line); + +/* Creates a syntax file source with file name FN. */ +struct getl_interface * create_syntax_file_source (const char *fn) ; + +#endif diff --git a/src/libpspp/getl.c b/src/libpspp/getl.c new file mode 100644 index 00000000..f3d71981 --- /dev/null +++ b/src/libpspp/getl.c @@ -0,0 +1,233 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include + +#include + +#include "getl.h" + +#include +#include +#include +#include + +#include + +struct getl_source + { + struct getl_source *included_from; /* File that this is nested inside. */ + struct getl_source *includes; /* File nested inside this file. */ + + struct ll ll; /* Element in the sources list */ + + struct getl_interface *interface; + }; + +/* List of source files. */ +static struct ll_list sources ; + +static struct string the_include_path; + +const char * +getl_include_path (void) +{ + return ds_cstr (&the_include_path); +} + +static struct getl_source * +current_source (struct ll_list *list) +{ + const struct ll *ll = ll_head (list); + return ll_data (ll, struct getl_source, ll ); +} + +/* Initialize getl. */ +void +getl_initialize (void) +{ + ll_init (&sources); + ds_init_cstr (&the_include_path, + fn_getenv_default ("STAT_INCLUDE_PATH", include_path)); +} + +/* Delete everything from the include path. */ +void +getl_clear_include_path (void) +{ + ds_clear (&the_include_path); +} + +/* Add to the include path. */ +void +getl_add_include_dir (const char *path) +{ + if (ds_length (&the_include_path)) + ds_put_char (&the_include_path, ':'); + + ds_put_cstr (&the_include_path, path); +} + +/* Appends source S to the list of source files. */ +void +getl_append_source (struct getl_interface *i) +{ + struct getl_source *s = xzalloc (sizeof ( struct getl_source )); + + s->interface = i ; + + ll_push_head (&sources, &s->ll); +} + +/* Nests source S within the current source file. */ +void +getl_include_source (struct getl_interface *i) +{ + struct getl_source *current = current_source (&sources); + struct getl_source *s = xzalloc (sizeof ( struct getl_source )); + + s->interface = i; + + s->included_from = current ; + s->includes = NULL; + current->includes = s; + + ll_push_head (&sources, &s->ll); +} + +/* Closes the current source, and move the current source to the + next file in the chain. */ +static void +close_source (void) +{ + struct getl_source *s = current_source (&sources); + + if ( s->interface->close ) + s->interface->close (s->interface); + + ll_pop_head (&sources); + + if (s->included_from != NULL) + current_source (&sources)->includes = NULL; + + free (s); +} + +/* Closes all sources until an interactive source is + encountered. */ +void +getl_abort_noninteractive (void) +{ + while ( ! ll_is_empty (&sources)) + { + const struct getl_source *s = current_source (&sources); + + if ( !s->interface->interactive (s->interface) ) + close_source (); + } +} + +/* Returns true if the current source is interactive, + false otherwise. */ +bool +getl_is_interactive (void) +{ + const struct getl_source *s = current_source (&sources); + + if (ll_is_empty (&sources) ) + return false; + + return s->interface->interactive (s->interface); +} + +/* Returns the name of the current source, or NULL if there is no + current source */ +const char * +getl_source_name (void) +{ + const struct getl_source *s = current_source (&sources); + + if ( ll_is_empty (&sources) ) + return NULL; + + if ( ! s->interface->name ) + return NULL; + + return s->interface->name (s->interface); +} + +/* Returns the location within the current source, or -1 if there is + no current source */ +int +getl_source_location (void) +{ + const struct getl_source *s = current_source (&sources); + + if ( ll_is_empty (&sources) ) + return -1; + + if ( !s->interface->location ) + return -1; + + return s->interface->location (s->interface); +} + + +/* Close getl. */ +void +getl_uninitialize (void) +{ + while ( !ll_is_empty (&sources)) + close_source (); + ds_destroy (&the_include_path); +} + + +/* Reads a single line into LINE. + Returns true when a line has been read, false at end of input. + If INTERACTIVE is non-null, then when true is returned + *INTERACTIVE will be set to true if the line was obtained + interactively, false otherwise. */ +bool +do_read_line (struct string *line, bool *interactive) +{ + while (!ll_is_empty (&sources)) + { + struct getl_source *s = current_source (&sources); + + ds_clear (line); + if (s->interface->read (s->interface, line)) + { + if (interactive != NULL) + *interactive = s->interface->interactive (s->interface); + + while ((s)) + { + if (s->interface->filter) + s->interface->filter (s->interface, line); + s = s->included_from; + } + + return true; + } + close_source (); + } + + return false; +} diff --git a/src/libpspp/getl.h b/src/libpspp/getl.h new file mode 100644 index 00000000..34c9b912 --- /dev/null +++ b/src/libpspp/getl.h @@ -0,0 +1,74 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef GETL_H +#define GETL_H 1 + +#include +#include + +struct string; + +struct getl_source; + + +/* An abstract base class for objects which act as line buffers for the + PSPP. Ie anything which might contain content for the lexer */ +struct getl_interface + { + /* Returns true, if the interface is interactive */ + bool (*interactive) (const struct getl_interface *); + + /* Read a line from the interface */ + bool (*read) (struct getl_interface *, struct string *); + + /* Close and destroy the interface */ + void (*close) (struct getl_interface *); + + /* Filter for current and all included sources. May be NULL */ + void (*filter) (struct getl_interface *, struct string *line); + + /* Returns the name of the source */ + const char * (*name) (const struct getl_interface *); + + /* Returns the current location within the source */ + int (*location) (const struct getl_interface *); + }; + +void getl_initialize (void); +void getl_uninitialize (void); + +void getl_clear_include_path (void); +void getl_add_include_dir (const char *); +const char * getl_include_path (void); + +void getl_abort_noninteractive (void); +bool getl_is_interactive (void); + +bool getl_read_line (bool *interactive); + +bool do_read_line (struct string *line, bool *interactive); + +void getl_append_source (struct getl_interface *s) ; +void getl_include_source (struct getl_interface *s) ; + +const char * getl_source_name (void); +int getl_source_location (void); + +#endif /* line-buffer.h */ diff --git a/src/libpspp/msg-locator.c b/src/libpspp/msg-locator.c new file mode 100644 index 00000000..5f7e5dd0 --- /dev/null +++ b/src/libpspp/msg-locator.c @@ -0,0 +1,85 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include +#include +#include +#include "msg-locator.h" +#include +#include +#include "getl.h" + +/* File locator stack. */ +static const struct msg_locator **file_loc; + +static int nfile_loc, mfile_loc; + +void +msg_locator_done (void) +{ + free(file_loc); + file_loc = NULL; + nfile_loc = mfile_loc = 0; +} + + +/* File locator stack functions. */ + +/* Pushes F onto the stack of file locations. */ +void +msg_push_msg_locator (const struct msg_locator *loc) +{ + if (nfile_loc >= mfile_loc) + { + if (mfile_loc == 0) + mfile_loc = 8; + else + mfile_loc *= 2; + + file_loc = xnrealloc (file_loc, mfile_loc, sizeof *file_loc); + } + + file_loc[nfile_loc++] = loc; +} + +/* Pops F off the stack of file locations. + Argument F is only used for verification that that is actually the + item on top of the stack. */ +void +msg_pop_msg_locator (const struct msg_locator *loc) +{ + assert (nfile_loc >= 0 && file_loc[nfile_loc - 1] == loc); + nfile_loc--; +} + +/* Puts the current file and line number into LOC, or NULL and -1 if + none. */ +void +get_msg_location (struct msg_locator *loc) +{ + if (nfile_loc) + { + *loc = *file_loc[nfile_loc - 1]; + } + else + { + loc->file_name = getl_source_name (); + loc->line_number = getl_source_location (); + } +} diff --git a/src/libpspp/msg-locator.h b/src/libpspp/msg-locator.h new file mode 100644 index 00000000..b39ea6d2 --- /dev/null +++ b/src/libpspp/msg-locator.h @@ -0,0 +1,36 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +struct msg_locator ; + +void msg_locator_done (void); + +/* File locator stack functions. */ + +/* Pushes F onto the stack of file locations. */ +void msg_push_msg_locator (const struct msg_locator *loc); + +/* Pops F off the stack of file locations. + Argument F is only used for verification that that is actually the + item on top of the stack. */ +void msg_pop_msg_locator (const struct msg_locator *loc); + +/* Puts the current file and line number into LOC, or NULL and -1 if + none. */ +void get_msg_location (struct msg_locator *loc); -- 2.30.2