/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2007, 2009 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
const struct string *val);
static bool
-ascii_open_driver (struct outp_driver *this, struct substring options)
+ascii_open_driver (const char *name, int types, struct substring options)
{
+ struct outp_driver *this;
struct ascii_driver_ext *x;
int i;
+ this = outp_allocate_driver (&ascii_class, name, types);
this->width = 79;
this->font_height = 1;
this->prop_em_width = 1;
x->box[i] = pool_strdup (x->pool, s);
}
+ outp_register_driver (this);
+
return true;
error:
pool_destroy (x->pool);
+ outp_free_driver (this);
return false;
}
/* Driver initialization. */
static bool
-xr_open_driver (struct outp_driver *this, struct substring options)
+xr_open_driver (const char *name, int types, struct substring options)
{
cairo_surface_t *surface;
cairo_status_t status;
+ struct outp_driver *this;
struct xr_driver_ext *x;
double width_pt, length_pt;
size_t i;
+ this = outp_allocate_driver (&cairo_class, name, types);
this->width = this->length = 0;
this->font_height = XR_POINT * 10;
memcpy (this->vert_line_width, this->horiz_line_width,
sizeof this->vert_line_width);
+ outp_register_driver (this);
return true;
error:
this->class->close_driver (this);
+ outp_free_driver (this);
return false;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
const char *content);
static bool
-html_open_driver (struct outp_driver *this, struct substring options)
+html_open_driver (const char *name, int types, struct substring options)
{
+ struct outp_driver *this;
struct html_driver_ext *x;
+ this = outp_allocate_driver (&html_class, name, types);
this->ext = x = xmalloc (sizeof *x);
x->file_name = xstrdup ("pspp.html");
x->chart_file_name = xstrdup ("pspp-#.png");
print_title_tag (x->file, "H1", outp_title);
print_title_tag (x->file, "H2", outp_subtitle);
+ outp_register_driver (this);
return true;
error:
this->class->close_driver (this);
+ outp_free_driver (this);
return false;
}
#include "gettext.h"
#define _(msgid) gettext (msgid)
-/* FIXME? Should the output configuration format be changed to
- drivername:classname:devicetype:options, where devicetype is zero
- or more of screen, printer, listing? */
-
-/* FIXME: Have the reentrancy problems been solved? */
-
/* Where the output driver name came from. */
enum
{
};
static struct outp_driver_class_list *outp_class_list;
-static struct outp_driver *outp_driver_list;
+static struct ll_list outp_driver_list = LL_INITIALIZER (outp_driver_list);
char *outp_title;
char *outp_subtitle;
void
outp_init (void)
{
- extern struct outp_class ascii_class;
- extern struct outp_class postscript_class;
-#ifdef HAVE_CAIRO
- extern struct outp_class cairo_class;
-#endif
-
char def[] = "default";
add_class (&html_class);
if (result)
{
- if (outp_driver_list == NULL)
+ if (ll_is_empty (&outp_driver_list))
error (0, 0, _("no active output drivers"));
}
else
error (0, 0, _("error reading device definition file"));
- if (!result || outp_driver_list == NULL)
+ if (!result || ll_is_empty (&outp_driver_list))
init_default_drivers ();
}
outp_macros = d;
}
-/* Destroys all the drivers in driver list *DL and sets *DL to
- NULL. */
-static void
-destroy_list (struct outp_driver ** dl)
-{
- struct outp_driver *d, *next;
-
- for (d = *dl; d; d = next)
- {
- destroy_driver (d);
- next = d->next;
- free (d);
- }
- *dl = NULL;
-}
-
/* Closes all the output drivers. */
void
outp_done (void)
{
struct outp_driver_class_list *n = outp_class_list ;
outp_configure_clear ();
- destroy_list (&outp_driver_list);
+ while (!ll_is_empty (&outp_driver_list))
+ {
+ struct outp_driver *d = ll_data (ll_head (&outp_driver_list),
+ struct outp_driver, node);
+ destroy_driver (d);
+ }
while (n)
{
find_driver (char *name)
{
struct outp_driver *d;
-
- for (d = outp_driver_list; d; d = d->next)
+ ll_for_each (d, struct outp_driver, node, &outp_driver_list)
if (!strcmp (d->name, name))
return d;
return NULL;
configure_driver (struct substring driver_name, struct substring class_name,
struct substring device_type, struct substring options)
{
- struct outp_driver *d, *iter;
struct outp_driver_class_list *c;
-
struct substring token;
size_t save_idx = 0;
+ char *name;
int device;
/* Find class. */
error (0, 0, _("unknown device type `%.*s'"),
(int) ss_length (token), ss_data (token));
- /* Open the device. */
- d = xmalloc (sizeof *d);
- d->next = d->prev = NULL;
- d->class = c->class;
- d->name = ss_xstrdup (driver_name);
+ /* Open driver. */
+ name = ss_xstrdup (driver_name);
+ if (!c->class->open_driver (name, device, options))
+ error (0, 0, _("cannot initialize output driver `%s' of class `%s'"),
+ name, c->class->name);
+ free (name);
+}
+
+/* Allocates and returns a new outp_driver for a device with the
+ given NAME and CLASS and the OUTP_DEV_* type(s) in TYPES
+
+ This function is intended to be used by output drivers, not
+ by their clients. */
+struct outp_driver *
+outp_allocate_driver (const struct outp_class *class,
+ const char *name, int types)
+{
+ struct outp_driver *d = xmalloc (sizeof *d);
+ d->class = class;
+ d->name = xstrdup (name);
d->page_open = false;
- d->device = device;
+ d->device = types;
d->cp_x = d->cp_y = 0;
d->ext = NULL;
d->prc = NULL;
+ return d;
+}
- /* Open driver. */
- if (!d->class->open_driver (d, options))
- {
- error (0, 0, _("cannot initialize output driver `%s' of class `%s'"),
- d->name, d->class->name);
- free (d->name);
- free (d);
- return;
- }
+/* Frees driver D and the data that it owns directly. The
+ driver's class must already have unregistered D (if it was
+ registered) and freed data private to its class.
+
+ This function is intended to be used by output drivers, not
+ by their clients. */
+void
+outp_free_driver (struct outp_driver *d)
+{
+ free (d->name);
+ free (d);
+}
+
+/* Adds D to the list of drivers that will be used for output. */
+void
+outp_register_driver (struct outp_driver *d)
+{
+ struct outp_driver *victim;
/* Find like-named driver and delete. */
- iter = find_driver (d->name);
- if (iter != NULL)
- destroy_driver (iter);
+ victim = find_driver (d->name);
+ if (victim != NULL)
+ destroy_driver (victim);
- /* Add to list. */
- d->next = outp_driver_list;
- d->prev = NULL;
- if (outp_driver_list != NULL)
- outp_driver_list->prev = d;
- outp_driver_list = d;
+ /* Add D to list. */
+ ll_push_tail (&outp_driver_list, &d->node);
+}
+
+/* Remove driver D from the list of drivers that will be used for
+ output. */
+void
+outp_unregister_driver (struct outp_driver *d)
+{
+ ll_remove (&d->node);
}
/* String LINE is in format:
destroy_driver (struct outp_driver *d)
{
outp_close_page (d);
- if (d->class)
- {
- struct outp_driver_class_list *c;
-
- d->class->close_driver (d);
-
- for (c = outp_class_list; c; c = c->next)
- if (c->class == d->class)
- break;
- assert (c != NULL);
- }
- free (d->name);
-
- /* Remove this driver from the global driver list. */
- if (d->prev)
- d->prev->next = d->next;
- if (d->next)
- d->next->prev = d->prev;
- if (d == outp_driver_list)
- outp_driver_list = d->next;
+ if (d->class && d->class->close_driver)
+ d->class->close_driver (d);
+ outp_unregister_driver (d);
+ outp_free_driver (d);
}
/* Tries to match S as one of the keywords in TAB, with
struct outp_driver *
outp_drivers (struct outp_driver *d)
{
- for (;;)
+ do
{
- if (d == NULL)
- d = outp_driver_list;
- else
- d = d->next;
+ struct ll *next;
+
+ next = d == NULL ? ll_head (&outp_driver_list) : ll_next (&d->node);
+ if (next == ll_null (&outp_driver_list))
+ return NULL;
- if (d == NULL
- || (d->device == 0 || (d->device & disabled_devices) != d->device))
- break;
+ d = ll_data (next, struct outp_driver, node);
}
+ while (d->device != 0 && (d->device & disabled_devices) == d->device);
return d;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2007, 2009 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
#ifndef OUTPUT_OUTPUT_H
#define OUTPUT_OUTPUT_H 1
+#include <libpspp/ll.h>
#include <libpspp/str.h>
-
/* Line styles. */
enum outp_line_style
{
const char *name; /* Name of this driver class. */
int special; /* Boolean value. */
- bool (*open_driver) (struct outp_driver *, struct substring options);
+ bool (*open_driver) (const char *name, int types,
+ struct substring options);
bool (*close_driver) (struct outp_driver *);
void (*open_page) (struct outp_driver *);
/* Defines the configuration of an output driver. */
struct outp_driver
{
- struct outp_driver *next, *prev; /* List of drivers. */
+ struct ll node; /* Node in list of drivers. */
const struct outp_class *class; /* Driver class. */
char *name; /* Name of this driver. */
bool page_open; /* 1=page is open, 0=page is closed. */
extern char *outp_subtitle;
void outp_init (void);
+void outp_done (void);
void outp_read_devices (void);
void outp_configure_driver_line (struct substring);
-void outp_done (void);
+
+struct outp_driver *outp_allocate_driver (const struct outp_class *class,
+ const char *name, int types);
+void outp_free_driver (struct outp_driver *);
+void outp_register_driver (struct outp_driver *);
+void outp_unregister_driver (struct outp_driver *);
void outp_configure_clear (void);
void outp_configure_add (char *);
/* Imported from som-frnt.c. */
void som_destroy_driver (struct outp_driver *);
+/* Common drivers. */
+extern const struct outp_class ascii_class;
+extern const struct outp_class postscript_class;
+#ifdef HAVE_CAIRO
+extern const struct outp_class cairo_class;
+#endif
+
#endif /* output/output.h */
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 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
/* Driver initialization. */
static bool
-ps_open_driver (struct outp_driver *this, struct substring options)
+ps_open_driver (const char *name, int types, struct substring options)
{
+ struct outp_driver *this;
struct ps_driver_ext *x;
size_t i;
+ this = outp_allocate_driver (&postscript_class, name, types);
this->width = this->length = 0;
this->font_height = PSUS * 10 / 72;
write_ps_prologue (this);
+ outp_register_driver (this);
return true;
error:
this->class->close_driver (this);
+ outp_free_driver (this);
return false;
}