From: Ben Pfaff Date: Fri, 24 Aug 2007 05:00:50 +0000 (+0000) Subject: Implement journaling. Bug #17240. X-Git-Tag: v0.6.0~297 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp-builds.git;a=commitdiff_plain;h=fdcc4b6875ccdbf7bd01bc401e87afbeb71c2bfd Implement journaling. Bug #17240. * msg-ui.c (handle_msg): Send message to write_journal function as well as msg_file. (dump_message): Change interface so that it takes a function pointer instead of a FILE. (write_stream): New function. (write_journal): New function. * read-line.c (welcome): Call journal_enable, so that the journal is enabled by default. * automake.mk (output_sources): Add journal.c, journal.h. * journal.c: New file. * journal.h: New file. --- diff --git a/doc/utilities.texi b/doc/utilities.texi index 03ef7c34..ba5a5e8b 100644 --- a/doc/utilities.texi +++ b/doc/utilities.texi @@ -592,8 +592,16 @@ files. These subcommands are @table @asis @item JOURNAL -@item LOG -Not currently used. +@itemx LOG +These subcommands, which are synonyms, control the journal. The +default is ON, which causes commands entered interactively to be +written to the journal file. Commands included from syntax files that +are included interactively and error messages printed by PSPP are also +written to the journal file, prefixed by @samp{>}. OFF disables use +of the journal. + +The journal is named @file{pspp.jnl} by default. A different name may +be specified. @end table System file subcommands affect the default format of system files diff --git a/src/language/lexer/ChangeLog b/src/language/lexer/ChangeLog index fdc29375..7c74373f 100644 --- a/src/language/lexer/ChangeLog +++ b/src/language/lexer/ChangeLog @@ -1,3 +1,9 @@ +2007-08-16 Ben Pfaff + + Implement journaling. Bug #17240. + + * lexer.c (lex_get_line_raw): Pass the line read to journal_write. + 2007-06-03 Ben Pfaff Implement missing functions for subcommand integer lists. diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index a20cc175..4e10ec22 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "size_max.h" @@ -856,8 +857,13 @@ bool lex_get_line_raw (struct lexer *lexer, enum getl_syntax *syntax) { enum getl_syntax dummy; - bool ok = getl_read_line (lexer->ss, &lexer->line_buffer, - syntax != NULL ? syntax : &dummy); + bool ok; + + if (syntax == NULL) + syntax = &dummy; + ok = getl_read_line (lexer->ss, &lexer->line_buffer, syntax); + journal_write (*syntax == GETL_BATCH, ds_cstr (&lexer->line_buffer)); + return ok; } diff --git a/src/language/utilities/ChangeLog b/src/language/utilities/ChangeLog index 8af47c08..1f5e3869 100644 --- a/src/language/utilities/ChangeLog +++ b/src/language/utilities/ChangeLog @@ -1,3 +1,11 @@ +2007-08-16 Ben Pfaff + + Implement journaling. Bug #17240. + + * set.q: Add LOG subcommand as synonym for JOURNAL. + (stc_custom_journal): Implement. + (stc_custom_log): New function. + 2007-05-06 Ben Pfaff Abstract the documents within a dictionary a little better. diff --git a/src/language/utilities/set.q b/src/language/utilities/set.q index e2d993e7..5552984b 100644 --- a/src/language/utilities/set.q +++ b/src/language/utilities/set.q @@ -41,6 +41,7 @@ #include #include #include +#include #include #if HAVE_LIBTERMCAP @@ -83,6 +84,7 @@ int tgetnum (const char *); histogram=string "x==1" "one character long"; include=inc:on/off; journal=custom; + log=custom; length=custom; listing=custom; lowres=lores:auto/on/off; @@ -507,19 +509,29 @@ static int stc_custom_journal (struct lexer *lexer, struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED) { lex_match (lexer, '='); - if (!lex_match_id (lexer, "ON") && !lex_match_id (lexer, "OFF")) + if (lex_match_id (lexer, "ON") || lex_match_id (lexer, "YES")) + journal_enable (); + else if (lex_match_id (lexer, "OFF") || lex_match_id (lexer, "NO")) + journal_disable (); + else if (lex_token (lexer) == T_STRING || lex_token (lexer) == T_ID) { - if (lex_token (lexer) == T_STRING) - lex_get (lexer); - else - { - lex_error (lexer, NULL); - return 0; - } + journal_set_file_name (ds_cstr (lex_tokstr (lexer))); + lex_get (lexer); + } + else + { + lex_error (lexer, NULL); + return 0; } return 1; } +static int +stc_custom_log (struct lexer *lexer, struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED) +{ + return stc_custom_journal (lexer, ds, cmd, aux); +} + static int stc_custom_listing (struct lexer *lexer, struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED) { diff --git a/src/output/ChangeLog b/src/output/ChangeLog index 7f78e2b5..24a019f1 100644 --- a/src/output/ChangeLog +++ b/src/output/ChangeLog @@ -1,3 +1,13 @@ +2007-08-23 Ben Pfaff + + Implement journaling. Bug #17240. + + * automake.mk (output_sources): Add journal.c, journal.h. + + * journal.c: New file. + + * journal.h: New file. + 2007-08-16 Ben Pfaff * output.c output.h: export function outp_configure_driver_line. diff --git a/src/output/automake.mk b/src/output/automake.mk index 4bb4780c..78898f46 100644 --- a/src/output/automake.mk +++ b/src/output/automake.mk @@ -11,6 +11,8 @@ output_sources = \ src/output/ascii.c \ src/output/html.c \ src/output/htmlP.h \ + src/output/journal.c \ + src/output/journal.h \ src/output/output.c \ src/output/output.h \ src/output/postscript.c \ diff --git a/src/output/journal.c b/src/output/journal.c new file mode 100644 index 00000000..33fbaf2b --- /dev/null +++ b/src/output/journal.c @@ -0,0 +1,101 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2007 Free Software Foundation, Inc. + + 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 3 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, see . */ + +#include + +#include + +#include +#include +#include + +#include + +#include "fwriteerror.h" +#include "error.h" +#include "xalloc.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +/* Journaling enabled? */ +static bool journal_enabled = false; + +/* Name of the journal file. */ +static char *journal_file_name = NULL; + +/* Journal file. */ +static FILE *journal_file = NULL; + +/* Enables journaling. */ +void +journal_enable (void) +{ + journal_enabled = true; +} + +/* Disables journaling. */ +void +journal_disable (void) +{ + journal_enabled = false; + if (journal_file != NULL) + fflush (journal_file); +} + +/* Sets the name of the journal file to FILE_NAME. */ +void +journal_set_file_name (const char *file_name) +{ + assert (file_name != NULL); + + if (journal_file != NULL) + { + if (fwriteerror (journal_file)) + error (0, errno, _("error writing \"%s\""), journal_file_name); + } + + free (journal_file_name); + journal_file_name = xstrdup (file_name); +} + +/* Writes LINE to the journal file (if journaling is enabled). + If PREFIX is non-null, the line will be prefixed by "> ". */ +void +journal_write (bool prefix, const char *line) +{ + if (!journal_enabled) + return; + + if (journal_file == NULL) + { + if (journal_file_name == NULL) + journal_file_name = xstrdup ("pspp.jnl"); + journal_file = fopen (journal_file_name, "w"); + if (journal_file == NULL) + { + error (0, errno, _("error creating \"%s\""), journal_file_name); + journal_enabled = false; + return; + } + } + + if (prefix) + fputs ("> ", journal_file); + fputs (line, journal_file); + if (strchr (line, '\n') == NULL) + putc ('\n', journal_file); +} diff --git a/src/output/journal.h b/src/output/journal.h new file mode 100644 index 00000000..3509ff09 --- /dev/null +++ b/src/output/journal.h @@ -0,0 +1,34 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2007 Free Software Foundation, Inc. + + 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 3 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, see . */ + +/* Journal for commands and errors. + + The journal file records the commands entered interactively + during a PSPP session. It also records, prefixed by "> ", + commands from files included with interactive commands and + errors. */ + +#ifndef OUTPUT_JOURNAL_H +#define OUTPUT_JOURNAL_H 1 + +#include + +void journal_enable (void); +void journal_disable (void); +void journal_set_file_name (const char *); +void journal_write (bool prefix, const char *); + +#endif /* output/journal.h */ diff --git a/src/ui/terminal/ChangeLog b/src/ui/terminal/ChangeLog index a98b9244..079aee78 100644 --- a/src/ui/terminal/ChangeLog +++ b/src/ui/terminal/ChangeLog @@ -1,3 +1,17 @@ +2007-08-23 Ben Pfaff + + Implement journaling. Bug #17240. + + * msg-ui.c (handle_msg): Send message to write_journal function + as well as msg_file. + (dump_message): Change interface so that it takes a function + pointer instead of a FILE. + (write_stream): New function. + (write_journal): New function. + + * read-line.c (welcome): Call journal_enable, so that the journal + is enabled by default. + 2007-07-25 Ben Pfaff Make interactive output go to the terminal (bug #17213), by diff --git a/src/ui/terminal/msg-ui.c b/src/ui/terminal/msg-ui.c index 6c40a8c7..b51a3e55 100644 --- a/src/ui/terminal/msg-ui.c +++ b/src/ui/terminal/msg-ui.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -112,9 +113,11 @@ any_errors (void) return error_count > 0; } -static void dump_message (char *msg, unsigned width, unsigned indent, FILE *); -static void dump_line (int line_indent, const char *line, size_t length, - FILE *); +typedef void write_line_func (int indent, struct substring line, void *aux); +static void dump_message (char *msg, unsigned width, unsigned indent, + write_line_func *, void *aux); +static write_line_func write_stream; +static write_line_func write_journal; static void handle_msg (const struct msg *m) @@ -169,16 +172,21 @@ handle_msg (const struct msg *m) ds_put_cstr (&string, m->text); if (msg_file != stdout || get_error_routing_to_terminal ()) - dump_message (ds_cstr (&string), get_viewwidth (), 8, msg_file); + dump_message (ds_cstr (&string), get_viewwidth (), 8, + write_stream, msg_file); + + dump_message (ds_cstr (&string), 78, 0, write_journal, NULL); ds_destroy (&string); } /* Divides MSG into lines of WIDTH width for the first line and WIDTH - INDENT width for each succeeding line, and writes the - lines to STREAM. */ + lines by calling DUMP_LINE for each line, passing AUX as + auxiliary data. */ static void -dump_message (char *msg, unsigned width, unsigned indent, FILE *stream) +dump_message (char *msg, unsigned width, unsigned indent, + write_line_func *dump_line, void *aux) { size_t length = strlen (msg); char *string, *breaks; @@ -194,8 +202,7 @@ dump_message (char *msg, unsigned width, unsigned indent, FILE *stream) { free (string); free (breaks); - fputs (msg, stream); - putc ('\n', stream); + dump_line (0, ss_cstr (msg), aux); return; } @@ -210,42 +217,44 @@ dump_message (char *msg, unsigned width, unsigned indent, FILE *stream) line_start = 0; line_indent = 0; for (i = 0; i < length; i++) - switch (breaks[i]) + if (breaks[i] == UC_BREAK_POSSIBLE || breaks[i] == UC_BREAK_MANDATORY) { - case UC_BREAK_POSSIBLE: - /* Break before this character, - and include this character in the next line. */ - dump_line (line_indent, &string[line_start], i - line_start, stream); - line_start = i; - line_indent = indent; - break; - case UC_BREAK_MANDATORY: - /* Break before this character, - but don't include this character in the next line - (because it'string a new-line). */ - dump_line (line_indent, &string[line_start], i - line_start, stream); - line_start = i + 1; + dump_line (line_indent, + ss_buffer (string + line_start, i - line_start), aux); line_indent = indent; - break; - default: - break; + + /* UC_BREAK_POSSIBLE means that a line break can be + inserted, and that the character should be included + in the next line. + UC_BREAK_MANDATORY means that this character is a line + break, so it should not be included in the next line. */ + line_start = i + (breaks[i] == UC_BREAK_MANDATORY); } if (line_start < length) - dump_line (line_indent, &string[line_start], length - line_start, stream); + dump_line (line_indent, + ss_buffer (string + line_start, length - line_start), aux); free (string); free (breaks); } -/* Write LINE_INDENT spaces, the LENGTH characters in LINE, then - a new-line to STREAM. */ +/* Write LINE_INDENT spaces, LINE, then a new-line to STREAM. */ static void -dump_line (int line_indent, const char *line, size_t length, FILE *stream) +write_stream (int line_indent, struct substring line, void *stream_) { + FILE *stream = stream_; int i; for (i = 0; i < line_indent; i++) putc (' ', stream); - fwrite (line, 1, length, stream); + fwrite (ss_data (line), 1, ss_length (line), stream); putc ('\n', stream); } +/* Writes LINE to the journal. */ +static void +write_journal (int line_indent, struct substring line, void *unused UNUSED) +{ + char *s = xstrndup (ss_data (line), ss_length (line)); + journal_write (true, s); + free (s); +} diff --git a/src/ui/terminal/read-line.c b/src/ui/terminal/read-line.c index c6279ce9..2529dee4 100644 --- a/src/ui/terminal/read-line.c +++ b/src/ui/terminal/read-line.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "xalloc.h" @@ -129,6 +130,7 @@ welcome (void) "warranty.\" for details.\n", stdout); puts (stat_version); readln_initialize (); + journal_enable (); } /* Gets a line from the user and stores it into LINE.