X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fjournal.c;h=a07fd4a094fdc1f213e82c67f965f14eb570973a;hb=2031b99a3f1970a0b9a840652f0aff80ec34b433;hp=1a700898ac5e1d6707de700d4b59de1723b32c74;hpb=f550aee00a62fe1d8baf62d83cd7efef6cc2ee92;p=pspp diff --git a/src/output/journal.c b/src/output/journal.c index 1a700898ac..a07fd4a094 100644 --- a/src/output/journal.c +++ b/src/output/journal.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2010 Free Software Foundation, Inc. + Copyright (C) 2007, 2010, 2012, 2013 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 @@ -21,15 +21,15 @@ #include #include #include +#include #include "data/file-name.h" #include "libpspp/cast.h" +#include "libpspp/message.h" #include "libpspp/str.h" #include "output/driver-provider.h" -#include "output/message-item.h" -#include "output/text-item.h" +#include "output/output-item.h" -#include "gl/error.h" #include "gl/fwriteerror.h" #include "gl/xalloc.h" @@ -40,16 +40,17 @@ struct journal_driver { struct output_driver driver; FILE *file; - char *command_name; + + /* Name of journal file. */ + char *file_name; + bool destroyed; }; static const struct output_driver_class journal_class; /* Journal driver, if journaling is enabled. */ -static struct journal_driver *journal; +static struct journal_driver journal; -/* Name of journal file. */ -static char *journal_file_name; static struct journal_driver * journal_driver_cast (struct output_driver *driver) @@ -61,13 +62,14 @@ journal_driver_cast (struct output_driver *driver) static void journal_close (void) { - if (journal != NULL && journal->file != NULL) + if (journal.file != NULL) { - if (fwriteerror (journal->file)) - error (0, errno, _("error writing output file \"%s\""), - journal_file_name); - journal->file = NULL; - } + if (fwriteerror (journal.file)) + msg_error (errno, _("error writing output file `%s'"), + journal.file_name); + + } + journal.file = NULL; } static void @@ -75,29 +77,26 @@ journal_destroy (struct output_driver *driver) { struct journal_driver *j = journal_driver_cast (driver); - journal_close (); - free (j->command_name); - free (j); + if (!j->destroyed) + journal_close (); - journal = NULL; + j->destroyed = true; } static void -journal_output (struct journal_driver *j, const char *s) +journal_output (struct journal_driver *j, char *s) { - if (j->file == NULL) + if (j->file) { - j->file = fopen (journal_file_name, "a"); - if (j->file == NULL) - { - error (0, errno, _("error opening output file \"%s\""), - journal_file_name); - output_driver_destroy (&j->driver); - return; - } + fprintf (j->file, "%s\n", s); + + /* Flush the journal in case the syntax we're about to write + causes a crash. Having the syntax already written to disk + makes postmortem analysis of the problem possible. */ + fflush (j->file); } - fprintf (j->file, "%s\n", s); + free (s); } static void @@ -105,65 +104,84 @@ journal_submit (struct output_driver *driver, const struct output_item *item) { struct journal_driver *j = journal_driver_cast (driver); - output_driver_track_current_command (item, &j->command_name); - - if (is_text_item (item)) + switch (item->type) { - const struct text_item *text_item = to_text_item (item); - enum text_item_type type = text_item_get_type (text_item); - - if (type == TEXT_ITEM_SYNTAX) - journal_output (j, text_item_get_text (text_item)); - } - else if (is_message_item (item)) - { - const struct message_item *message_item = to_message_item (item); - const struct msg *msg = message_item_get_msg (message_item); - char *s = msg_to_string (msg, j->command_name); - journal_output (j, s); - free (s); + case OUTPUT_ITEM_MESSAGE: + journal_output (j, msg_to_string (item->message)); + break; + + case OUTPUT_ITEM_TEXT: + if (item->text.subtype == TEXT_ITEM_SYNTAX) + journal_output (j, text_item_get_plain_text (item)); + break; + + case OUTPUT_ITEM_GROUP: + for (size_t i = 0; i < item->group.n_children; i++) + journal_submit (driver, item->group.children[i]); + break; + + case OUTPUT_ITEM_CHART: + case OUTPUT_ITEM_IMAGE: + case OUTPUT_ITEM_PAGE_BREAK: + case OUTPUT_ITEM_TABLE: + break; } } static const struct output_driver_class journal_class = { - "journal", - journal_destroy, - journal_submit, - NULL /* flush */ + .name = "journal", + .destroy = journal_destroy, + .submit = journal_submit, }; + /* Enables journaling. */ void -journal_enable (void) +journal_init (void) { - if (journal == NULL) - { - /* If no journal file name is configured, use the default. */ - if (journal_file_name == NULL) - { - const char *output_path = default_output_path (); - journal_file_name = xasprintf ("%s%s", output_path, "pspp.jnl"); - } - - /* Create journal driver. */ - journal = xzalloc (sizeof *journal); - output_driver_init (&journal->driver, &journal_class, "journal", - SETTINGS_DEVICE_UNFILTERED); - journal->file = NULL; - journal->command_name = NULL; - - /* Register journal driver. */ - output_driver_register (&journal->driver); - } + /* Create journal driver. */ + output_driver_init (&journal.driver, &journal_class, "journal", + SETTINGS_DEVICE_UNFILTERED); + journal.file = NULL; + + /* Register journal driver. */ + output_driver_register (&journal.driver); + + journal_enable (); + journal.destroyed = false; } /* Disables journaling. */ void journal_disable (void) { - if (journal != NULL) - output_driver_destroy (&journal->driver); + journal_close (); +} + + +/* Enable journaling. */ +void +journal_enable (void) +{ + if (journal.file == NULL) + { + journal.file = fopen (journal_get_file_name (), "a"); + if (journal.file == NULL) + { + msg_error (errno, _("error opening output file `%s'"), + journal_get_file_name ()); + journal_close (); + } + } +} + + +/* Returns true if journaling is enabled, false otherwise. */ +bool +journal_is_enabled (void) +{ + return journal.file != NULL ; } /* Sets the name of the journal file to FILE_NAME. */ @@ -171,6 +189,19 @@ void journal_set_file_name (const char *file_name) { journal_close (); - free (journal_file_name); - journal_file_name = xstrdup (file_name); + free (journal.file_name); + journal.file_name = xstrdup (file_name); +} + +/* Returns the name of the journal file. The caller must not modify or free + the returned string. */ +const char * +journal_get_file_name (void) +{ + if (journal.file_name == NULL) + { + const char *output_path = default_output_path (); + journal.file_name = xasprintf ("%s%s", output_path, "pspp.jnl"); + } + return journal.file_name; }