/* PSPP - computes sample statistics.
Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
- Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
#include <errno.h>
#include <ctype.h>
#include <libpspp/alloc.h>
-#include <data/filename.h>
+#include <data/file-name.h>
#include "htmlP.h"
#include "intprops.h"
#include <libpspp/misc.h>
/* A list of driver classes. */
struct outp_driver_class_list
{
- struct outp_class *class;
+ const struct outp_class *class;
struct outp_driver_class_list *next;
};
-struct outp_driver_class_list *outp_class_list;
-struct outp_driver *outp_driver_list;
+static struct outp_driver_class_list *outp_class_list;
+static struct outp_driver *outp_driver_list;
char *outp_title;
char *outp_subtitle;
static int disabled_devices;
static void destroy_driver (struct outp_driver *);
-static void configure_driver_line (struct string *);
-static void configure_driver (const struct string *, const struct string *,
- const struct string *, const struct string *);
+static void configure_driver_line (struct substring);
+static void configure_driver (const struct substring, const struct substring,
+ const struct substring, const struct substring);
/* Add a class to the class list. */
static void
-add_class (struct outp_class *class)
+add_class (const struct outp_class *class)
{
struct outp_driver_class_list *new_list = xmalloc (sizeof *new_list);
for (d = outp_macros; d; d = d->next)
if (!strcmp (key, d->key))
- return ds_c_str(&d->value);
+ return ds_cstr (&d->value);
if (!strcmp (key, "viewwidth"))
{
sprintf (buf, "%d", get_viewwidth ());
{
extern struct outp_class ascii_class;
extern struct outp_class postscript_class;
- extern struct outp_class html_class;
char def[] = "default";
}
static void
-init_default_drivers (void)
+init_default_drivers (void)
{
- struct string s;
-
error (0, 0, _("using default output driver configuration"));
-
- ds_create (&s,
- "list:ascii:listing:"
- "length=66 width=79 output-file=\"pspp.list\"");
- configure_driver_line (&s);
- ds_destroy (&s);
+ configure_driver (ss_cstr ("list"),
+ ss_cstr ("ascii"),
+ ss_cstr ("listing"),
+ ss_cstr ("length=66 width=79 output-file=\"pspp.list\""));
}
/* Reads the initialization file; initializes
init_fn = fn_search_path (fn_getenv_default ("STAT_OUTPUT_INIT_FILE",
"devices"),
fn_getenv_default ("STAT_OUTPUT_INIT_PATH",
- config_path),
- NULL);
+ config_path));
- ds_init (&line, 128);
+ ds_init_empty (&line);
if (init_fn == NULL)
{
error (0, 0, _("cannot find output initialization file "
- "(use `-vvvvv' to view search path)"));
+ "(use `-vv' to view search path)"));
goto exit;
}
{
char *cp;
- if (!ds_get_config_line (f, &line, &line_number))
+ if (!ds_read_config_line (&line, &line_number, f))
{
if (ferror (f))
error (0, errno, _("reading \"%s\""), init_fn);
break;
}
- for (cp = ds_c_str (&line); isspace ((unsigned char) *cp); cp++);
+ for (cp = ds_cstr (&line); isspace ((unsigned char) *cp); cp++);
if (!strncmp ("define", cp, 6) && isspace ((unsigned char) cp[6]))
outp_configure_macro (&cp[7]);
else if (*cp)
struct outp_names *n = search_names (cp, ep);
if (n)
{
- configure_driver_line (&line);
+ configure_driver_line (ds_ss (&line));
delete_name (n);
}
}
ds_destroy (&line);
delete_macros ();
- if (result)
+ if (result)
{
- if (outp_driver_list == NULL)
- error (0, 0, _("no active output drivers"));
+ if (outp_driver_list == NULL)
+ error (0, 0, _("no active output drivers"));
}
else
error (0, 0, _("error reading device definition file"));
free (d);
return;
}
-
+
if (*ep == '=')
ep++;
while (isspace ((unsigned char) *ep))
ep++;
- ds_create(&d->value, ep);
- fn_interp_vars(&d->value, find_defn_value);
+ ds_init_cstr (&d->value, ep);
+ fn_interp_vars (ds_ss (&d->value), find_defn_value, &d->value);
d->next = outp_macros;
d->prev = NULL;
if (outp_macros)
void
outp_done (void)
{
- struct outp_driver_class_list *n = outp_class_list ;
+ struct outp_driver_class_list *n = outp_class_list ;
destroy_list (&outp_driver_list);
- while (n)
+ while (n)
{
struct outp_driver_class_list *next = n->next;
free(n);
free (outp_title);
outp_title = NULL;
-
+
free (outp_subtitle);
outp_subtitle = NULL;
}
putc('\n', stdout);
}
-/* Obtains a token from S starting at position *POS, which is
- updated. Errors are reported against the given DRIVER_NAME.
+/* Obtains a token from S and advances its position. Errors are
+ reported against the given DRIVER_NAME.
The token is stored in TOKEN. Returns true if successful,
false on syntax error.
Caller is responsible for skipping leading spaces. */
static bool
-get_option_token (const struct string *s, const char *driver_name,
- size_t *pos, struct string *token)
+get_option_token (struct substring *s, const char *driver_name,
+ struct string *token)
{
int c;
-
+
ds_clear (token);
- c = ds_at (s, *pos);
+ c = ss_get_char (s);
if (c == EOF)
{
error (0, 0, _("syntax error parsing options for \"%s\" driver"),
{
int quote = c;
- ++*pos;
for (;;)
{
- c = ds_at (s, (*pos)++);
+ c = ss_get_char (s);
if (c == quote)
break;
- else if (c == EOF)
+ else if (c == EOF)
{
error (0, 0,
_("reached end of options inside quoted string "
return false;
}
else if (c != '\\')
- ds_putc (token, c);
+ ds_put_char (token, c);
else
{
int out;
-
- switch (ds_at (s, *pos))
+
+ c = ss_get_char (s);
+ switch (c)
{
case '\'':
out = '\'';
case '6':
case '7':
out = c - '0';
- while (ds_at (s, *pos) >= '0' && ds_at (s, *pos) <= '7')
- out = c * 8 + ds_at (s, (*pos)++) - '0';
+ while (ss_first (*s) >= '0' && ss_first (*s) <= '7')
+ out = c * 8 + (ss_get_char (s) - '0');
break;
case 'x':
case 'X':
out = 0;
- while (isxdigit (ds_at (s, *pos)))
+ while (isxdigit (ss_first (*s)))
{
- c = ds_at (s, *pos);
- if (!isxdigit (c))
- break;
- (*pos)++;
-
+ c = ss_get_char (s);
out *= 16;
if (isdigit (c))
out += c - '0';
driver_name);
return false;
}
- ds_putc (token, out);
+ ds_put_char (token, out);
}
}
}
- else
+ else
{
- do
+ for (;;)
{
- ds_putc (token, c);
- c = ds_at (s, ++*pos);
+ ds_put_char (token, c);
+
+ c = ss_first (*s);
+ if (c == EOF || c == '=' || isspace (c))
+ break;
+ ss_advance (s, 1);
}
- while (c != EOF && c != '=' && !isspace (c));
}
-
+
return 1;
}
bool
-outp_parse_options (const struct string *options,
+outp_parse_options (struct substring options,
bool (*callback) (struct outp_driver *, const char *key,
const struct string *value),
struct outp_driver *driver)
{
- struct string key = DS_INITIALIZER;
- struct string value = DS_INITIALIZER;
- size_t pos = 0;
+ struct string key = DS_EMPTY_INITIALIZER;
+ struct string value = DS_EMPTY_INITIALIZER;
+ struct substring left = options;
bool ok = true;
do
{
- pos += ds_span (options, pos, " \t");
- if (ds_at (options, pos) == EOF)
+ ss_ltrim (&left, ss_cstr (CC_SPACES));
+ if (ss_is_empty (left))
break;
-
- if (!get_option_token (options, driver->name, &pos, &key))
+
+ if (!get_option_token (&left, driver->name, &key))
break;
- pos += ds_span (options, pos, " \t");
- if (ds_at (options, pos) != '=')
+ ss_ltrim (&left, ss_cstr (CC_SPACES));
+ if (!ss_match_char (&left, '='))
{
error (0, 0, _("syntax error expecting `=' "
"parsing options for driver \"%s\""),
driver->name);
break;
}
- pos++;
-
- pos += ds_span (options, pos, " \t");
- if (!get_option_token (options, driver->name, &pos, &value))
+
+ ss_ltrim (&left, ss_cstr (CC_SPACES));
+ if (!get_option_token (&left, driver->name, &value))
break;
- ok = callback (driver, ds_c_str (&key), &value);
+ ok = callback (driver, ds_cstr (&key), &value);
}
while (ok);
-
+
ds_destroy (&key);
ds_destroy (&value);
return NULL;
}
-/* String S is in format:
- DRIVERNAME:CLASSNAME:DEVICETYPE:OPTIONS
- Adds a driver to outp_driver_list pursuant to the specification
- provided. */
+/* Adds a driver to outp_driver_list pursuant to the
+ specification provided. */
static void
-configure_driver (const struct string *driver_name,
- const struct string *class_name,
- const struct string *device_type,
- const struct string *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 substring token;
+ size_t save_idx = 0;
int device;
/* Find class. */
for (c = outp_class_list; c; c = c->next)
- if (!strcmp (c->class->name, ds_c_str (class_name)))
+ if (!ss_compare (ss_cstr (c->class->name), class_name))
break;
if (c == NULL)
{
- error (0, 0, _("unknown output driver class `%s'"),
- ds_c_str (class_name));
+ error (0, 0, _("unknown output driver class `%.*s'"),
+ (int) ss_length (class_name), ss_data (class_name));
return;
}
-
+
/* Parse device type. */
device = 0;
- if (device_type != NULL)
- {
- struct string token = DS_INITIALIZER;
- size_t save_idx = 0;
-
- while (ds_tokenize (device_type, &token, " \t\r\v", &save_idx))
- {
- const char *type = ds_c_str (&token);
- if (!strcmp (type, "listing"))
- device |= OUTP_DEV_LISTING;
- else if (!strcmp (type, "screen"))
- device |= OUTP_DEV_SCREEN;
- else if (!strcmp (type, "printer"))
- device |= OUTP_DEV_PRINTER;
- else
- error (0, 0, _("unknown device type `%s'"), type);
- }
- ds_destroy (&token);
- }
+ while (ss_tokenize (device_type, ss_cstr (CC_SPACES), &save_idx, &token))
+ if (!ss_compare (token, ss_cstr ("listing")))
+ device |= OUTP_DEV_LISTING;
+ else if (!ss_compare (token, ss_cstr ("screen")))
+ device |= OUTP_DEV_SCREEN;
+ else if (!ss_compare (token, ss_cstr ("printer")))
+ device |= OUTP_DEV_PRINTER;
+ else
+ 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 = xstrdup (ds_c_str (driver_name));
+ d->name = ss_xstrdup (driver_name);
d->page_open = false;
d->device = OUTP_DEV_NONE;
d->cp_x = d->cp_y = 0;
Adds a driver to outp_driver_list pursuant to the specification
provided. */
static void
-configure_driver_line (struct string *line)
+configure_driver_line (struct substring line_)
{
- struct string tokens[4];
+ struct string line = DS_EMPTY_INITIALIZER;
+ struct substring tokens[4];
size_t save_idx;
size_t i;
- fn_interp_vars (line, find_defn_value);
+ fn_interp_vars (line_, find_defn_value, &line);
save_idx = 0;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++)
{
- struct string *token = &tokens[i];
- ds_init (token, 0);
- ds_separate (line, token, i < 3 ? ":" : "", &save_idx);
- ds_trim_spaces (token);
+ struct substring *token = &tokens[i];
+ ds_separate (&line, ss_cstr (i < 3 ? ":" : ""), &save_idx, token);
+ ss_trim (token, ss_cstr (CC_SPACES));
}
- if (!ds_is_empty (&tokens[0]) && !ds_is_empty (&tokens[1]))
- configure_driver (&tokens[0], &tokens[1], &tokens[2], &tokens[3]);
+ if (!ss_is_empty (tokens[0]) && !ss_is_empty (tokens[1]))
+ configure_driver (tokens[0], tokens[1], tokens[2], tokens[3]);
else
error (0, 0,
_("driver definition line missing driver name or class name"));
- for (i = 0; i < 4; i++)
- ds_destroy (&tokens[i]);
+ ds_destroy (&line);
}
/* Destroys output driver D. */
code and stores subcategory in *SUBCAT on success. Returns -1
on failure. */
int
-outp_match_keyword (const char *s, struct outp_option *tab, int *subcat)
+outp_match_keyword (const char *s, const struct outp_option *tab, int *subcat)
{
for (; tab->keyword != NULL; tab++)
if (!strcmp (s, tab->keyword))
/* Stores the dimensions in 1/72000" units of paper identified by
SIZE, which is of form `HORZ x VERT' or `HORZ by VERT' where each
- of HORZ and VERT are dimensions, into *H and *V. Return nonzero on
+ of HORZ and VERT are dimensions, into *H and *V. Return true on
success. */
-static int
+static bool
internal_get_paper_size (char *size, int *h, int *v)
{
char *tail;
size++;
*h = outp_evaluate_dimension (size, &tail);
if (tail == NULL)
- return 0;
+ return false;
while (isspace ((unsigned char) *tail))
tail++;
if (*tail == 'x')
else
{
error (0, 0, _("`x' expected in paper size `%s'"), size);
- return 0;
+ return false;
}
*v = outp_evaluate_dimension (tail, &tail);
if (tail == NULL)
if (*tail)
{
error (0, 0, _("trailing garbage `%s' on paper size `%s'"), tail, size);
- return 0;
+ return false;
}
-
- return 1;
+
+ return true;
}
/* Stores the dimensions, in 1/72000" units, of paper identified by
SIZE into *H and *V. SIZE may be a pair of dimensions of form `H x
V', or it may be a case-insensitive paper identifier, which is
- looked up in the `papersize' configuration file. Returns nonzero
+ looked up in the `papersize' configuration file. Returns true
on success. May modify SIZE. */
/* Don't read further unless you've got a strong stomach. */
-int
+bool
outp_get_paper_size (char *size, int *h, int *v)
{
struct paper_size
struct string line;
int line_number = 0;
- int free_it = 0;
- int result = 0;
+ bool free_it = false;
+ bool result = false;
char *ep;
while (isspace ((unsigned char) *size))
error (0, 0, _("paper size name cannot be empty"));
return 0;
}
-
+
ep++;
if (*ep)
*ep = 0;
pprsz_fn = fn_search_path (fn_getenv_default ("STAT_OUTPUT_PAPERSIZE_FILE",
"papersize"),
fn_getenv_default ("STAT_OUTPUT_INIT_PATH",
- config_path),
- NULL);
+ config_path));
- ds_init (&line, 128);
+ ds_init_empty (&line);
if (pprsz_fn == NULL)
{
for (;;)
{
- char *cp, *bp, *ep;
+ struct substring p, name;
- if (!ds_get_config_line (f, &line, &line_number))
+ if (!ds_read_config_line (&line, &line_number, f))
{
if (ferror (f))
error (0, errno, _("error reading \"%s\""), pprsz_fn);
break;
}
- for (cp = ds_c_str (&line); isspace ((unsigned char) *cp); cp++);
- if (*cp == 0)
- continue;
- if (*cp != '"')
- goto lex_error;
- for (bp = ep = cp + 1; *ep && *ep != '"'; ep++);
- if (!*ep)
+
+ p = ds_ss (&line);
+ ss_ltrim (&p, ss_cstr (CC_SPACES));
+ if (!ss_match_char (&p, '"') || !ss_get_until (&p, '"', &name))
goto lex_error;
- *ep = 0;
- if (0 != strcasecmp (bp, size))
+ if (ss_compare (name, ss_cstr (size)))
continue;
- for (cp = ep + 1; isspace ((unsigned char) *cp); cp++);
- if (*cp == '=')
+ ss_ltrim (&p, ss_cstr (CC_SPACES));
+ if (ss_match_char (&p, '='))
{
- size = xmalloc (ep - bp + 1);
- strcpy (size, bp);
- free_it = 1;
+ if (free_it)
+ free (size);
+ ss_trim (&p, ss_cstr (CC_SPACES));
+ size = ss_xstrdup (p);
+ free_it = true;
continue;
}
- size = &ep[1];
+ size = ss_data (p);
break;
lex_error:
if (!result)
error (0, 0, _("error reading paper size definition file"));
-
+
return result;
}
struct outp_driver *
outp_drivers (struct outp_driver *d)
{
-#if DEBUGGING
- struct outp_driver *orig_d = d;
-#endif
-
for (;;)
{
if (d == NULL)
/* Opens a page on driver D (if one is not open). */
void
-outp_open_page (struct outp_driver *d)
+outp_open_page (struct outp_driver *d)
{
- if (!d->page_open)
+ if (!d->page_open)
{
d->cp_x = d->cp_y = 0;
/* Closes the page on driver D (if one is open). */
void
-outp_close_page (struct outp_driver *d)
+outp_close_page (struct outp_driver *d)
{
- if (d->page_open)
+ if (d->page_open)
{
if (d->class->close_page != NULL)
d->class->close_page (d);
}
}
-/* Ejects the paper on device D, if a page is open and is not
- blank. */
+/* Ejects the page on device D, if a page is open and non-blank,
+ and opens a new page. */
void
outp_eject_page (struct outp_driver *d)
{
if (d->page_open && d->cp_y != 0)
- {
- outp_close_page (d);
- outp_open_page (d);
- }
+ outp_close_page (d);
+ outp_open_page (d);
}
/* Returns the width of string S, in device units, when output on
{
struct outp_text text;
int width;
-
+
text.font = font;
text.justification = OUTP_LEFT;
- ls_init (&text.string, (char *) s, strlen (s));
+ text.string = ss_cstr (s);
text.h = text.v = INT_MAX;
d->class->text_metrics (d, &text, &width, NULL);