From 0e4ef2c7099e82d8e43cf87a53c36430d1ce879f Mon Sep 17 00:00:00 2001 From: John Darrington Date: Mon, 19 Dec 2005 06:42:32 +0000 Subject: [PATCH] Separated getl.c into getl.c and readln.c --- src/ChangeLog | 6 ++ src/Makefile.am | 2 + src/error.c | 6 +- src/format.c | 32 ++++-- src/getl.c | 261 +++++--------------------------------------- src/getl.h | 10 +- src/main.c | 13 ++- src/readln.c | 279 ++++++++++++++++++++++++++++++++++++++++++++++++ src/readln.h | 32 ++++++ src/settings.c | 1 - src/settings.h | 3 + 11 files changed, 402 insertions(+), 243 deletions(-) create mode 100644 src/readln.c create mode 100644 src/readln.h diff --git a/src/ChangeLog b/src/ChangeLog index d95bf559..a3d2c4b3 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +Mon Dec 19 14:01:56 WST 2005 John Darrington + + * format.c: Additional error checking. + * getl.[ch]: Separated into getl.c and readln.c + * settings.[ch]: Made CC_CNT public + Fri Dec 16 09:11:48 WST 2005 John Darrington * examine.q: Fixed buglet when cleaning up at end of procedure. diff --git a/src/Makefile.am b/src/Makefile.am index e3b3952e..b9b09d57 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -190,6 +190,8 @@ pspp_SOURCES = \ random.h \ range-prs.c \ range-prs.h \ + readln.c \ + readln.h \ recode.c \ rename-vars.c \ repeat.c \ diff --git a/src/error.c b/src/error.c index 7ca387ab..5547261a 100644 --- a/src/error.c +++ b/src/error.c @@ -201,7 +201,11 @@ static void dump_message (char *errbuf, unsigned indent, void err_done (void) { - free (file_loc); + lex_done(); + getl_uninitialize (); + readln_uninitialize(); + + free(file_loc); file_loc = NULL; nfile_loc = mfile_loc = 0; } diff --git a/src/format.c b/src/format.c index 1c09e26c..cce8c46e 100644 --- a/src/format.c +++ b/src/format.c @@ -64,8 +64,19 @@ fmt_to_string (const struct fmt_spec *f) static bool check_common_specifier (const struct fmt_spec *spec, bool emit_error) { - struct fmt_desc *f = &formats[spec->type]; - char *str = fmt_to_string (spec); + struct fmt_desc *f ; + char *str; + + if ( spec->type > FMT_NUMBER_OF_FORMATS ) + { + if (emit_error) + msg (SE, _("Format specifies a bad type (%d)"), spec->type); + + return false; + } + + f = &formats[spec->type]; + str = fmt_to_string (spec); if ((f->cat & FCAT_EVEN_WIDTH) && spec->w % 2) { @@ -92,11 +103,16 @@ check_common_specifier (const struct fmt_spec *spec, bool emit_error) int check_input_specifier (const struct fmt_spec *spec, int emit_error) { - struct fmt_desc *f = &formats[spec->type]; - char *str = fmt_to_string (spec); + struct fmt_desc *f ; + char *str ; if (!check_common_specifier (spec, emit_error)) return false; + + f = &formats[spec->type]; + str = fmt_to_string (spec); + + if (spec->type == FMT_X) return 1; if (f->cat & FCAT_OUTPUT_ONLY) @@ -131,11 +147,15 @@ check_input_specifier (const struct fmt_spec *spec, int emit_error) int check_output_specifier (const struct fmt_spec *spec, int emit_error) { - struct fmt_desc *f = &formats[spec->type]; - char *str = fmt_to_string (spec); + struct fmt_desc *f; + char *str ; if (!check_common_specifier (spec, emit_error)) return false; + + f = &formats[spec->type]; + str = fmt_to_string (spec); + if (spec->type == FMT_X) return 1; if (spec->w < f->Omin_w || spec->w > f->Omax_w) diff --git a/src/getl.c b/src/getl.c index a02244d7..bd380abf 100644 --- a/src/getl.c +++ b/src/getl.c @@ -38,36 +38,6 @@ #include "gettext.h" #define _(msgid) gettext (msgid) -/* Global variables. */ -struct string getl_buf; -struct getl_script *getl_head; -struct getl_script *getl_tail; -int getl_interactive; -int getl_welcomed; -int getl_mode; -int getl_prompt; - -#if HAVE_LIBREADLINE -#include -#endif - -#if HAVE_LIBHISTORY -static char *history_file; - -#if HAVE_READLINE_HISTORY_H -#include -#else /* no readline/history.h */ -extern void add_history (char *); -extern void using_history (void); -extern int read_history (char *); -extern void stifle_history (int); -extern int write_history (char *); -#endif /* no readline/history.h */ -#endif /* -lhistory */ - - -extern struct cmd_set cmd; - static struct string getl_include_path; /* Number of levels of DO REPEAT structures we're nested inside. If @@ -75,7 +45,8 @@ static struct string getl_include_path; performed. */ static int DO_REPEAT_level; -static int read_console (void); +struct string getl_buf; + /* Initialize getl. */ void @@ -84,9 +55,6 @@ getl_initialize (void) ds_create (&getl_include_path, fn_getenv_default ("STAT_INCLUDE_PATH", include_path)); ds_init (&getl_buf, 256); -#if HAVE_LIBREADLINE - rl_completion_entry_function = pspp_completion_function; -#endif } /* Close getl. */ @@ -94,14 +62,15 @@ void getl_uninitialize (void) { getl_close_all(); -#if HAVE_LIBHISTORY && defined (unix) - if (history_file) - write_history (history_file); -#endif ds_destroy (&getl_buf); ds_destroy (&getl_include_path); } + +struct getl_script *getl_head; +struct getl_script *getl_tail; + + /* Returns a string that represents the directory that the syntax file currently being read resides in. If there is no syntax file then returns the OS current working directory. Return value must be @@ -227,7 +196,6 @@ getl_add_virtual_file (struct getl_script *file) void getl_add_DO_REPEAT_file (struct getl_script *file) { - /* getl_head == NULL can't happen. */ assert (getl_head); DO_REPEAT_level++; @@ -242,28 +210,11 @@ getl_add_DO_REPEAT_file (struct getl_script *file) file->f = NULL; } -/* Display a welcoming message. */ -static void -welcome (void) -{ - getl_welcomed = 1; - fputs ("PSPP is free software and you are welcome to distribute copies of " - "it\nunder certain conditions; type \"show copying.\" to see the " - "conditions.\nThere is ABSOLUTELY NO WARRANTY for PSPP; type \"show " - "warranty.\" for details.\n", stdout); - puts (stat_version); -} - -/* Reads a single line from the user's terminal. */ - -/* From repeat.c. */ -extern void perform_DO_REPEAT_substitutions (void); - /* Reads a single line from the line buffer associated with getl_head. Returns 1 if a line was successfully read or 0 if no more lines are available. */ -static int -handle_line_buffer (void) +int +getl_handle_line_buffer (void) { struct getl_script *s = getl_head; @@ -297,84 +248,6 @@ handle_line_buffer (void) return 1; } -/* Reads a single line into getl_buf from the list of files. Will not - read from the eof of one file to the beginning of another unless - the options field on the new file's getl_script is nonzero. Return - zero on eof. */ -int -getl_read_line (void) -{ - getl_mode = GETL_MODE_BATCH; - - while (getl_head) - { - struct getl_script *s = getl_head; - - ds_clear (&getl_buf); - if (s->separate) - return 0; - - if (s->first_line) - { - if (!handle_line_buffer ()) - { - getl_close_file (); - continue; - } - perform_DO_REPEAT_substitutions (); - if (getl_head->print) - tab_output_text (TAB_LEFT | TAT_FIX | TAT_PRINTF, "+%s", - ds_c_str (&getl_buf)); - return 1; - } - - if (s->f == NULL) - { - msg (VM (1), _("%s: Opening as syntax file."), s->fn); - s->f = fn_open (s->fn, "r"); - - if (s->f == NULL) - { - msg (ME, _("Opening `%s': %s."), s->fn, strerror (errno)); - getl_close_file (); - continue; - } - } - - if (!ds_gets (&getl_buf, s->f)) - { - if (ferror (s->f)) - msg (ME, _("Reading `%s': %s."), s->fn, strerror (errno)); - getl_close_file (); - continue; - } - if (ds_length (&getl_buf) > 0 && ds_end (&getl_buf)[-1] == '\n') - ds_truncate (&getl_buf, ds_length (&getl_buf) - 1); - - if (get_echo()) - tab_output_text (TAB_LEFT | TAT_FIX, ds_c_str (&getl_buf)); - - getl_head->ln++; - - /* Allows shebang invocation: `#! /usr/local/bin/pspp'. */ - if (ds_c_str (&getl_buf)[0] == '#' - && ds_c_str (&getl_buf)[1] == '!') - continue; - - return 1; - } - - if (getl_interactive == 0) - return 0; - - getl_mode = GETL_MODE_INTERACTIVE; - - if (getl_welcomed == 0) - welcome (); - - return read_console (); -} - /* Closes the current file, whether it be a main file or included file, then moves getl_head to the next file in the chain. */ void @@ -420,90 +293,6 @@ getl_close_file (void) free (s); } -/* PORTME: Adapt to your local system's idea of the terminal. */ -#if HAVE_LIBREADLINE - -#if HAVE_READLINE_READLINE_H -#include -#else /* no readline/readline.h */ -extern char *readline (char *); -#endif /* no readline/readline.h */ - -static int -read_console (void) -{ - char *line; - const char *prompt; - - err_error_count = err_warning_count = 0; - err_already_flagged = 0; - -#if HAVE_LIBHISTORY - if (!history_file) - { -#ifdef unix - history_file = tilde_expand (HISTORY_FILE); -#endif - using_history (); - read_history (history_file); - stifle_history (MAX_HISTORY); - } -#endif /* -lhistory */ - - switch (getl_prompt) - { - case GETL_PRPT_STANDARD: - prompt = get_prompt (); - break; - - case GETL_PRPT_CONTINUATION: - prompt = get_cprompt (); - break; - - case GETL_PRPT_DATA: - prompt = get_dprompt (); - break; - - default: - assert (0); - abort (); - } - - line = readline (prompt); - if (!line) - return 0; - -#if HAVE_LIBHISTORY - if (*line) - add_history (line); -#endif - - ds_clear (&getl_buf); - ds_puts (&getl_buf, line); - - free (line); - - return 1; -} -#else /* no -lreadline */ -static int -read_console (void) -{ - err_error_count = err_warning_count = 0; - err_already_flagged = 0; - - fputs (getl_prompt ? get_cprompt() : get_prompt(), stdout); - ds_clear (&getl_buf); - if (ds_gets (&getl_buf, stdin)) - return 1; - - if (ferror (stdin)) - msg (FE, "stdin: fgets(): %s.", strerror (errno)); - - return 0; -} -#endif /* no -lreadline */ - /* Closes all files. */ void getl_close_all (void) @@ -512,22 +301,21 @@ getl_close_all (void) getl_close_file (); } -/* Sets the options flag of the current script to 0, thus allowing it - to be read in. Returns nonzero if this action was taken, zero - otherwise. */ -int -getl_perform_delayed_reset (void) +bool +getl_is_separate(void) { - if (getl_head && getl_head->separate) - { - getl_head->separate = 0; - discard_variables (); - lex_reset_eof (); - return 1; - } - return 0; + return (getl_head && getl_head->separate); } +void +getl_set_separate(bool sep) +{ + assert (getl_head); + + getl_head->separate = sep ; +} + + /* Puts the current file and line number in *FN and *LN, respectively, or NULL and -1 if none. */ void @@ -538,3 +326,10 @@ getl_location (const char **fn, int *ln) if (ln != NULL) *ln = getl_head ? getl_head->ln : -1; } + +bool +getl_reading_script (void) +{ + return (getl_head != NULL); +} + diff --git a/src/getl.h b/src/getl.h index 483d9a27..71fca576 100644 --- a/src/getl.h +++ b/src/getl.h @@ -20,6 +20,7 @@ #if !getl_h #define getl_h 1 +#include #include /* Defines a list of lines used by DO REPEAT. */ @@ -88,7 +89,8 @@ extern int getl_prompt; /* Are we reading a script? Are we interactive? */ #define getl_am_interactive (getl_head == NULL) -#define getl_reading_script (getl_head != NULL) + +bool getl_reading_script (void); /* Current line. This line may be modified by modules other than getl.c, and by lexer.c in particular. */ @@ -113,5 +115,11 @@ int getl_perform_delayed_reset (void); void getl_add_DO_REPEAT_file (struct getl_script *); void getl_add_virtual_file (struct getl_script *); void getl_location (const char **, int *); +int getl_handle_line_buffer (void); + +bool getl_is_separate(void); + +void getl_set_separate(bool sep); + #endif /* getl_h */ diff --git a/src/main.c b/src/main.c index 4918eefc..0441d74a 100644 --- a/src/main.c +++ b/src/main.c @@ -34,6 +34,7 @@ #include "output.h" #include "progname.h" #include "random.h" +#include "readln.h" #include "settings.h" #include "var.h" #include "version.h" @@ -92,6 +93,7 @@ main (int argc, char **argv) fn_init (); fh_init (); getl_initialize (); + readln_initialize (); settings_init (); random_init (); @@ -155,7 +157,16 @@ execute_command (void) if (token != T_STOP) break; - if (!getl_perform_delayed_reset ()) + /* Sets the options flag of the current script to 0, thus allowing it + to be read in. Returns nonzero if this action was taken, zero + otherwise. */ + if (getl_head && getl_head->separate) + { + getl_head->separate = 0; + discard_variables (); + lex_reset_eof (); + } + else terminate (err_error_count == 0); } diff --git a/src/readln.c b/src/readln.c new file mode 100644 index 00000000..2327cec7 --- /dev/null +++ b/src/readln.c @@ -0,0 +1,279 @@ +/* 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 "readln.h" +#include "command.h" +#include "version.h" +#include "getl.h" +#include "str.h" +#include "tab.h" +#include "error.h" +#include "filename.h" +#include "settings.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + + +#if HAVE_LIBREADLINE +#include +#endif + +#if HAVE_LIBHISTORY +static char *history_file; + +#if HAVE_READLINE_HISTORY_H +#include +#else /* no readline/history.h */ +extern void add_history (char *); +extern void using_history (void); +extern int read_history (char *); +extern void stifle_history (int); +extern int write_history (char *); +#endif /* no readline/history.h */ +#endif /* -lhistory */ + + +static int read_console (void); + +static bool initialised = false; + +/* Initialize getl. */ +void +readln_initialize (void) +{ + initialised = true; +#if HAVE_LIBREADLINE + rl_completion_entry_function = pspp_completion_function; +#endif +} + +/* Close getl. */ +void +readln_uninitialize (void) +{ + initialised = false; +#if HAVE_LIBHISTORY && defined (unix) + if (history_file) + write_history (history_file); +#endif +} + +static bool welcomed = false; + +/* Display a welcoming message. */ +static void +welcome (void) +{ + welcomed = true; + fputs ("PSPP is free software and you are welcome to distribute copies of " + "it\nunder certain conditions; type \"show copying.\" to see the " + "conditions.\nThere is ABSOLUTELY NO WARRANTY for PSPP; type \"show " + "warranty.\" for details.\n", stdout); + puts (stat_version); +} + +/* From repeat.c. */ +extern void perform_DO_REPEAT_substitutions (void); + + /* Global variables. */ +int getl_mode; +int getl_interactive; +int getl_prompt; + +/* +extern struct cmd_set cmd; +*/ + + +/* Reads a single line into getl_buf from the list of files. Will not + read from the eof of one file to the beginning of another unless + the options field on the new file's getl_script is nonzero. Return + zero on eof. */ +int +getl_read_line (void) +{ + assert (initialised); + getl_mode = GETL_MODE_BATCH; + + while (getl_head) + { + struct getl_script *s = getl_head; + + ds_clear (&getl_buf); + if (s->separate) + return 0; + + if (s->first_line) + { + if (!getl_handle_line_buffer ()) + { + getl_close_file (); + continue; + } + perform_DO_REPEAT_substitutions (); + if (getl_head->print) + tab_output_text (TAB_LEFT | TAT_FIX | TAT_PRINTF, "+%s", + ds_c_str (&getl_buf)); + return 1; + } + + if (s->f == NULL) + { + msg (VM (1), _("%s: Opening as syntax file."), s->fn); + s->f = fn_open (s->fn, "r"); + + if (s->f == NULL) + { + msg (ME, _("Opening `%s': %s."), s->fn, strerror (errno)); + getl_close_file (); + continue; + } + } + + if (!ds_gets (&getl_buf, s->f)) + { + if (ferror (s->f)) + msg (ME, _("Reading `%s': %s."), s->fn, strerror (errno)); + getl_close_file (); + continue; + } + if (ds_length (&getl_buf) > 0 && ds_end (&getl_buf)[-1] == '\n') + ds_truncate (&getl_buf, ds_length (&getl_buf) - 1); + + if (get_echo()) + tab_output_text (TAB_LEFT | TAT_FIX, ds_c_str (&getl_buf)); + + getl_head->ln++; + + /* Allows shebang invocation: `#! /usr/local/bin/pspp'. */ + if (ds_c_str (&getl_buf)[0] == '#' + && ds_c_str (&getl_buf)[1] == '!') + continue; + + return 1; + } + + if (getl_interactive == 0) + return 0; + + getl_mode = GETL_MODE_INTERACTIVE; + + if (!welcomed) + welcome (); + + return read_console (); +} + + +/* PORTME: Adapt to your local system's idea of the terminal. */ +#if HAVE_LIBREADLINE + +#if HAVE_READLINE_READLINE_H +#include +#else /* no readline/readline.h */ +extern char *readline (char *); +#endif /* no readline/readline.h */ + +static int +read_console (void) +{ + char *line; + const char *prompt; + + assert(initialised); + + err_error_count = err_warning_count = 0; + err_already_flagged = 0; + +#if HAVE_LIBHISTORY + if (!history_file) + { +#ifdef unix + history_file = tilde_expand (HISTORY_FILE); +#endif + using_history (); + read_history (history_file); + stifle_history (MAX_HISTORY); + } +#endif /* -lhistory */ + + switch (getl_prompt) + { + case GETL_PRPT_STANDARD: + prompt = get_prompt (); + break; + + case GETL_PRPT_CONTINUATION: + prompt = get_cprompt (); + break; + + case GETL_PRPT_DATA: + prompt = get_dprompt (); + break; + + default: + assert (0); + abort (); + } + + line = readline (prompt); + if (!line) + return 0; + +#if HAVE_LIBHISTORY + if (*line) + add_history (line); +#endif + + ds_clear (&getl_buf); + ds_puts (&getl_buf, line); + + free (line); + + return 1; +} +#else /* no -lreadline */ +static int +read_console (void) +{ + assert(initialised); + + err_error_count = err_warning_count = 0; + err_already_flagged = 0; + + fputs (getl_prompt ? get_cprompt() : get_prompt(), stdout); + ds_clear (&getl_buf); + if (ds_gets (&getl_buf, stdin)) + return 1; + + if (ferror (stdin)) + msg (FE, "stdin: fgets(): %s.", strerror (errno)); + + return 0; +} +#endif /* no -lreadline */ + diff --git a/src/readln.h b/src/readln.h new file mode 100644 index 00000000..540776a1 --- /dev/null +++ b/src/readln.h @@ -0,0 +1,32 @@ +/* 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 READLN_H +#define READLN_H + +#include + +/* Initialize getl. */ +void readln_initialize (void); + +/* Close getl. */ +void readln_uninitialize (void); + +#endif /* READLN_H */ + diff --git a/src/settings.c b/src/settings.c index 94af922a..3bd98c18 100644 --- a/src/settings.c +++ b/src/settings.c @@ -67,7 +67,6 @@ static size_t workspace = 4L * 1024 * 1024; static struct fmt_spec default_format = {FMT_F, 8, 2}; -#define CC_CNT 5 #define CC_INITIALIZER {"-", "", "", "", '.', ','} static struct custom_currency cc[CC_CNT] = { diff --git a/src/settings.h b/src/settings.h index abb1743b..2eedbddb 100644 --- a/src/settings.h +++ b/src/settings.h @@ -101,6 +101,9 @@ void set_workspace (size_t); const struct fmt_spec *get_format (void); void set_format (const struct fmt_spec *); +/* Maximum number of custom currency specifications */ +#define CC_CNT 5 + /* One custom currency specification. */ #define CC_WIDTH 16 struct custom_currency -- 2.30.2