X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Foutput.c;h=a556ad81e8e7b1f49584261829459988b83b732b;hb=27cc40906c7b388fc0bec644b324ef6a4dec6dc3;hp=4dc9902c35452c880252ffe4bc42a80f4e107724;hpb=a65d2daa73de4351795dd8c1d3da6e5cb12a1dac;p=pspp-builds.git diff --git a/src/output/output.c b/src/output/output.c index 4dc9902c..a556ad81 100644 --- a/src/output/output.c +++ b/src/output/output.c @@ -39,12 +39,6 @@ #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 { @@ -79,7 +73,7 @@ struct outp_driver_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; @@ -228,12 +222,6 @@ find_defn_value (const char *key) 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); @@ -242,6 +230,7 @@ outp_init (void) #ifdef HAVE_CAIRO add_class (&cairo_class); #endif + add_class (&odt_class); add_name (def, &def[strlen (def)], OUTP_S_INIT_FILE); } @@ -351,13 +340,13 @@ exit: 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 (); } @@ -427,29 +416,18 @@ outp_configure_macro (char *bp) 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) { @@ -617,10 +595,9 @@ get_option_token (struct substring *s, const char *driver_name, } bool -outp_parse_options (struct substring options, - bool (*callback) (struct outp_driver *, const char *key, - const struct string *value), - struct outp_driver *driver) +outp_parse_options (const char *driver_name, struct substring options, + bool (*callback) (void *aux, const char *key, + const struct string *value), void *aux) { struct string key = DS_EMPTY_INITIALIZER; struct string value = DS_EMPTY_INITIALIZER; @@ -633,7 +610,7 @@ outp_parse_options (struct substring options, if (ss_is_empty (left)) break; - if (!get_option_token (&left, driver->name, &key)) + if (!get_option_token (&left, driver_name, &key)) break; ss_ltrim (&left, ss_cstr (CC_SPACES)); @@ -641,15 +618,15 @@ outp_parse_options (struct substring options, { error (0, 0, _("syntax error expecting `=' " "parsing options for driver \"%s\""), - driver->name); + driver_name); break; } ss_ltrim (&left, ss_cstr (CC_SPACES)); - if (!get_option_token (&left, driver->name, &value)) + if (!get_option_token (&left, driver_name, &value)) break; - ok = callback (driver, ds_cstr (&key), &value); + ok = callback (aux, ds_cstr (&key), &value); } while (ok); @@ -664,8 +641,7 @@ static struct outp_driver * 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; @@ -677,11 +653,10 @@ static void 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. */ @@ -708,38 +683,67 @@ configure_driver (struct substring driver_name, struct substring class_name, 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: @@ -778,26 +782,10 @@ static void 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 @@ -1093,17 +1081,17 @@ outp_get_paper_size (const char *size, int *h, int *v) 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; }