Until now, the output subsystem has taken responsibility for
allocating, freeing, registering, and unregistering output drivers.
This is usually what we want it to do, but PSPPIRE will soon want to
register an output driver of its own, independent of the main driver
configuration mechanism. This commit refactors the output driver
subsystem slightly to make this possible.
/* PSPP - a program for statistical analysis.
/* 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
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
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;
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;
this->width = 79;
this->font_height = 1;
this->prop_em_width = 1;
x->box[i] = pool_strdup (x->pool, s);
}
x->box[i] = pool_strdup (x->pool, s);
}
+ outp_register_driver (this);
+
return true;
error:
pool_destroy (x->pool);
return true;
error:
pool_destroy (x->pool);
+ outp_free_driver (this);
/* Driver initialization. */
static bool
/* 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;
{
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;
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;
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);
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);
return true;
error:
this->class->close_driver (this);
+ outp_free_driver (this);
/* PSPP - a program for statistical analysis.
/* 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
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
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;
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");
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);
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);
return true;
error:
this->class->close_driver (this);
+ outp_free_driver (this);
#include "gettext.h"
#define _(msgid) gettext (msgid)
#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
{
/* Where the output driver name came from. */
enum
{
};
static struct outp_driver_class_list *outp_class_list;
};
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;
char *outp_title;
char *outp_subtitle;
- 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);
char def[] = "default";
add_class (&html_class);
- 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"));
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 ();
}
init_default_drivers ();
}
-/* 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 ();
/* 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);
+ }
find_driver (char *name)
{
struct outp_driver *d;
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;
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)
{
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 outp_driver_class_list *c;
struct substring token;
size_t save_idx = 0;
struct substring token;
size_t save_idx = 0;
int device;
/* Find class. */
int device;
/* Find class. */
error (0, 0, _("unknown device type `%.*s'"),
(int) ss_length (token), ss_data (token));
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->cp_x = d->cp_y = 0;
d->ext = NULL;
d->prc = NULL;
d->cp_x = d->cp_y = 0;
d->ext = NULL;
d->prc = NULL;
- /* 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. */
/* 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:
}
/* String LINE is in format:
destroy_driver (struct outp_driver *d)
{
outp_close_page (d);
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
}
/* Tries to match S as one of the keywords in TAB, with
struct outp_driver *
outp_drivers (struct outp_driver *d)
{
struct outp_driver *
outp_drivers (struct outp_driver *d)
{
- 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);
/* PSPP - a program for statistical analysis.
/* 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
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
#ifndef OUTPUT_OUTPUT_H
#define OUTPUT_OUTPUT_H 1
/* Line styles. */
enum outp_line_style
{
/* Line styles. */
enum outp_line_style
{
const char *name; /* Name of this driver class. */
int special; /* Boolean value. */
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 *);
bool (*close_driver) (struct outp_driver *);
void (*open_page) (struct outp_driver *);
/* Defines the configuration of an output driver. */
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. */
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);
extern char *outp_subtitle;
void outp_init (void);
void outp_read_devices (void);
void outp_configure_driver_line (struct substring);
void outp_read_devices (void);
void outp_configure_driver_line (struct substring);
+
+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 *);
void outp_configure_clear (void);
void outp_configure_add (char *);
/* Imported from som-frnt.c. */
void som_destroy_driver (struct outp_driver *);
/* 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 */
#endif /* output/output.h */
/* PSPP - a program for statistical analysis.
/* 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
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
/* 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;
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;
this->width = this->length = 0;
this->font_height = PSUS * 10 / 72;
write_ps_prologue (this);
write_ps_prologue (this);
+ outp_register_driver (this);
return true;
error:
this->class->close_driver (this);
return true;
error:
this->class->close_driver (this);
+ outp_free_driver (this);