From ebf3b993687a25782fe72f45bf3e72aa4bee7c95 Mon Sep 17 00:00:00 2001 From: John Darrington Date: Tue, 28 Mar 2006 06:05:05 +0000 Subject: [PATCH] Fixed memory leaks resulting from fn_interp_vars et. al. --- po/en_GB.po | 90 +++++++++++++-------------- po/pspp.pot | 90 +++++++++++++-------------- src/data/ChangeLog | 6 ++ src/data/filename.c | 135 +++++++++++++++++++++++----------------- src/data/filename.h | 4 +- src/libpspp/ChangeLog | 5 ++ src/libpspp/str.c | 90 +++++++++++++++++++++++++++ src/libpspp/str.h | 12 ++++ src/output/ChangeLog | 5 ++ src/output/html.c | 14 +++-- src/output/output.c | 113 +++++++++++++++++++++------------ src/output/postscript.c | 22 +++---- 12 files changed, 381 insertions(+), 205 deletions(-) diff --git a/po/en_GB.po b/po/en_GB.po index 9bc4b370..82b0f4d4 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PSPP 0.3.1\n" "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n" -"POT-Creation-Date: 2006-03-21 09:48+0800\n" +"POT-Creation-Date: 2006-03-28 13:51+0800\n" "PO-Revision-Date: 2004-01-23 13:04+0800\n" "Last-Translator: John Darrington \n" "Language-Team: John Darrington \n" @@ -311,21 +311,21 @@ msgstr "" msgid "Can't re-open %s as a %s for %s." msgstr "" -#: src/data/filename.c:226 +#: src/data/filename.c:249 #, c-format msgid "Searching for `%s'..." msgstr "" -#: src/data/filename.c:234 src/data/filename.c:266 +#: src/data/filename.c:257 src/data/filename.c:289 msgid "Search unsuccessful!" msgstr "" -#: src/data/filename.c:259 +#: src/data/filename.c:282 #, c-format msgid "Found `%s'." msgstr "" -#: src/data/filename.c:676 +#: src/data/filename.c:699 #, c-format msgid "Not opening pipe file `%s' because SAFER option set." msgstr "" @@ -1761,7 +1761,7 @@ msgstr "" msgid "`/FORMAT WEIGHT' specified, but weighting is not on." msgstr "" -#: src/language/data-io/list.q:258 src/output/html.c:411 +#: src/language/data-io/list.q:258 src/output/html.c:413 #, c-format msgid "Cannot open first page on HTML device %s." msgstr "" @@ -2784,8 +2784,8 @@ msgstr "" msgid "Opening `%s': %s." msgstr "" -#: src/language/line-buffer.c:459 src/output/html.c:339 -#: src/output/postscript.c:1454 +#: src/language/line-buffer.c:459 src/output/html.c:341 +#: src/output/postscript.c:1452 #, c-format msgid "Reading `%s': %s." msgstr "" @@ -2999,7 +2999,7 @@ msgstr "" #: src/language/stats/crosstabs.q:1156 #, c-format -msgid " 95%% Confidence Interval" +msgid "95%% Confidence Interval" msgstr "" #: src/language/stats/crosstabs.q:1159 src/language/stats/t-test.q:984 @@ -4242,7 +4242,7 @@ msgstr "" msgid "Writing `%s': %s" msgstr "" -#: src/output/ascii.c:1584 src/output/postscript.c:2101 +#: src/output/ascii.c:1584 src/output/postscript.c:2099 #, c-format msgid "%s - Page %d" msgstr "" @@ -4430,17 +4430,17 @@ msgstr "" msgid "nowhere" msgstr "" -#: src/output/html.c:348 +#: src/output/html.c:350 #, c-format msgid "%s: HTML prologue read successfully." msgstr "" -#: src/output/html.c:352 +#: src/output/html.c:354 #, c-format msgid "%s: Error reading HTML prologue." msgstr "" -#: src/output/html.c:380 +#: src/output/html.c:382 #, c-format msgid "HTML output driver: %s: %s" msgstr "" @@ -4469,19 +4469,19 @@ msgstr "" msgid "%s: Opening device description file..." msgstr "" -#: src/output/output.c:297 src/output/output.c:1172 +#: src/output/output.c:297 src/output/output.c:1205 #: src/output/postscript.c:1095 #, c-format msgid "Opening %s: %s." msgstr "" -#: src/output/output.c:308 src/output/output.c:1183 +#: src/output/output.c:308 src/output/output.c:1216 #: src/output/postscript.c:1110 #, c-format msgid "Reading %s: %s." msgstr "" -#: src/output/output.c:330 src/output/output.c:495 +#: src/output/output.c:330 src/output/output.c:497 msgid "Syntax error." msgstr "" @@ -4502,119 +4502,119 @@ msgstr "" msgid "Error reading device definition file." msgstr "" -#: src/output/output.c:467 +#: src/output/output.c:469 #, c-format msgid "" "Driver classes:\n" "\t" msgstr "" -#: src/output/output.c:596 +#: src/output/output.c:598 msgid "Syntax error in string constant." msgstr "" -#: src/output/output.c:628 +#: src/output/output.c:630 msgid "Syntax error in options." msgstr "" -#: src/output/output.c:638 +#: src/output/output.c:640 msgid "Syntax error in options (`=' expected)." msgstr "" -#: src/output/output.c:645 +#: src/output/output.c:647 msgid "Syntax error in options (value expected after `=')." msgstr "" -#: src/output/output.c:721 +#: src/output/output.c:744 #, c-format msgid "Unknown output driver class `%s'." msgstr "" -#: src/output/output.c:728 +#: src/output/output.c:751 #, c-format msgid "Can't initialize output driver class `%s'." msgstr "" -#: src/output/output.c:735 +#: src/output/output.c:758 #, c-format msgid "Can't initialize output driver `%s' of class `%s'." msgstr "" -#: src/output/output.c:757 +#: src/output/output.c:780 #, c-format msgid "Unknown device type `%s'." msgstr "" -#: src/output/output.c:770 +#: src/output/output.c:793 #, c-format msgid "Can't complete initialization of output driver `%s' of class `%s'." msgstr "" -#: src/output/output.c:813 +#: src/output/output.c:839 msgid "Driver definition line contains fewer fields than expected" msgstr "" -#: src/output/output.c:843 +#: src/output/output.c:876 #, c-format msgid "Can't deinitialize output driver class `%s'." msgstr "" -#: src/output/output.c:916 +#: src/output/output.c:949 #, c-format msgid "Trying to find keyword `%s'...\n" msgstr "" -#: src/output/output.c:1033 +#: src/output/output.c:1066 #, c-format msgid "Unit \"%s\" is unknown in dimension \"%s\"." msgstr "" -#: src/output/output.c:1048 +#: src/output/output.c:1081 #, c-format msgid "Bad dimension \"%s\"." msgstr "" -#: src/output/output.c:1074 +#: src/output/output.c:1107 #, c-format msgid "`x' expected in paper size `%s'." msgstr "" -#: src/output/output.c:1084 +#: src/output/output.c:1117 #, c-format msgid "Trailing garbage `%s' on paper size `%s'." msgstr "" -#: src/output/output.c:1133 +#: src/output/output.c:1166 msgid "Paper size name must not be empty." msgstr "" -#: src/output/output.c:1164 +#: src/output/output.c:1197 msgid "Cannot find `papersize' configuration file." msgstr "" -#: src/output/output.c:1168 +#: src/output/output.c:1201 #, c-format msgid "%s: Opening paper size definition file..." msgstr "" -#: src/output/output.c:1210 +#: src/output/output.c:1243 msgid "Syntax error in paper size definition." msgstr "" -#: src/output/output.c:1239 +#: src/output/output.c:1272 msgid "Paper size definition file read successfully." msgstr "" -#: src/output/output.c:1241 +#: src/output/output.c:1274 msgid "Error reading paper size definition file." msgstr "" -#: src/output/output.c:1297 +#: src/output/output.c:1330 #, c-format msgid "Error closing page on %s device of %s class." msgstr "" -#: src/output/output.c:1301 +#: src/output/output.c:1334 #, c-format msgid "Error opening page on %s device of %s class." msgstr "" @@ -4730,22 +4730,22 @@ msgstr "" msgid "%s: %s: Opening PostScript prologue..." msgstr "" -#: src/output/postscript.c:1467 +#: src/output/postscript.c:1465 #, c-format msgid "%s: PostScript prologue read successfully." msgstr "" -#: src/output/postscript.c:1471 +#: src/output/postscript.c:1469 #, c-format msgid "%s: Error reading PostScript prologue." msgstr "" -#: src/output/postscript.c:1641 +#: src/output/postscript.c:1639 #, c-format msgid "PostScript output driver: %s: %s" msgstr "" -#: src/output/postscript.c:2340 +#: src/output/postscript.c:2338 #, c-format msgid "PostScript driver: Cannot find encoding `%s' for PostScript font `%s'." msgstr "" diff --git a/po/pspp.pot b/po/pspp.pot index 63379e4c..450ace18 100644 --- a/po/pspp.pot +++ b/po/pspp.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n" -"POT-Creation-Date: 2006-03-21 09:48+0800\n" +"POT-Creation-Date: 2006-03-28 13:51+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -312,21 +312,21 @@ msgstr "" msgid "Can't re-open %s as a %s for %s." msgstr "" -#: src/data/filename.c:226 +#: src/data/filename.c:249 #, c-format msgid "Searching for `%s'..." msgstr "" -#: src/data/filename.c:234 src/data/filename.c:266 +#: src/data/filename.c:257 src/data/filename.c:289 msgid "Search unsuccessful!" msgstr "" -#: src/data/filename.c:259 +#: src/data/filename.c:282 #, c-format msgid "Found `%s'." msgstr "" -#: src/data/filename.c:676 +#: src/data/filename.c:699 #, c-format msgid "Not opening pipe file `%s' because SAFER option set." msgstr "" @@ -1762,7 +1762,7 @@ msgstr "" msgid "`/FORMAT WEIGHT' specified, but weighting is not on." msgstr "" -#: src/language/data-io/list.q:258 src/output/html.c:411 +#: src/language/data-io/list.q:258 src/output/html.c:413 #, c-format msgid "Cannot open first page on HTML device %s." msgstr "" @@ -2785,8 +2785,8 @@ msgstr "" msgid "Opening `%s': %s." msgstr "" -#: src/language/line-buffer.c:459 src/output/html.c:339 -#: src/output/postscript.c:1454 +#: src/language/line-buffer.c:459 src/output/html.c:341 +#: src/output/postscript.c:1452 #, c-format msgid "Reading `%s': %s." msgstr "" @@ -3000,7 +3000,7 @@ msgstr "" #: src/language/stats/crosstabs.q:1156 #, c-format -msgid " 95%% Confidence Interval" +msgid "95%% Confidence Interval" msgstr "" #: src/language/stats/crosstabs.q:1159 src/language/stats/t-test.q:984 @@ -4243,7 +4243,7 @@ msgstr "" msgid "Writing `%s': %s" msgstr "" -#: src/output/ascii.c:1584 src/output/postscript.c:2101 +#: src/output/ascii.c:1584 src/output/postscript.c:2099 #, c-format msgid "%s - Page %d" msgstr "" @@ -4431,17 +4431,17 @@ msgstr "" msgid "nowhere" msgstr "" -#: src/output/html.c:348 +#: src/output/html.c:350 #, c-format msgid "%s: HTML prologue read successfully." msgstr "" -#: src/output/html.c:352 +#: src/output/html.c:354 #, c-format msgid "%s: Error reading HTML prologue." msgstr "" -#: src/output/html.c:380 +#: src/output/html.c:382 #, c-format msgid "HTML output driver: %s: %s" msgstr "" @@ -4470,19 +4470,19 @@ msgstr "" msgid "%s: Opening device description file..." msgstr "" -#: src/output/output.c:297 src/output/output.c:1172 +#: src/output/output.c:297 src/output/output.c:1205 #: src/output/postscript.c:1095 #, c-format msgid "Opening %s: %s." msgstr "" -#: src/output/output.c:308 src/output/output.c:1183 +#: src/output/output.c:308 src/output/output.c:1216 #: src/output/postscript.c:1110 #, c-format msgid "Reading %s: %s." msgstr "" -#: src/output/output.c:330 src/output/output.c:495 +#: src/output/output.c:330 src/output/output.c:497 msgid "Syntax error." msgstr "" @@ -4503,119 +4503,119 @@ msgstr "" msgid "Error reading device definition file." msgstr "" -#: src/output/output.c:467 +#: src/output/output.c:469 #, c-format msgid "" "Driver classes:\n" "\t" msgstr "" -#: src/output/output.c:596 +#: src/output/output.c:598 msgid "Syntax error in string constant." msgstr "" -#: src/output/output.c:628 +#: src/output/output.c:630 msgid "Syntax error in options." msgstr "" -#: src/output/output.c:638 +#: src/output/output.c:640 msgid "Syntax error in options (`=' expected)." msgstr "" -#: src/output/output.c:645 +#: src/output/output.c:647 msgid "Syntax error in options (value expected after `=')." msgstr "" -#: src/output/output.c:721 +#: src/output/output.c:744 #, c-format msgid "Unknown output driver class `%s'." msgstr "" -#: src/output/output.c:728 +#: src/output/output.c:751 #, c-format msgid "Can't initialize output driver class `%s'." msgstr "" -#: src/output/output.c:735 +#: src/output/output.c:758 #, c-format msgid "Can't initialize output driver `%s' of class `%s'." msgstr "" -#: src/output/output.c:757 +#: src/output/output.c:780 #, c-format msgid "Unknown device type `%s'." msgstr "" -#: src/output/output.c:770 +#: src/output/output.c:793 #, c-format msgid "Can't complete initialization of output driver `%s' of class `%s'." msgstr "" -#: src/output/output.c:813 +#: src/output/output.c:839 msgid "Driver definition line contains fewer fields than expected" msgstr "" -#: src/output/output.c:843 +#: src/output/output.c:876 #, c-format msgid "Can't deinitialize output driver class `%s'." msgstr "" -#: src/output/output.c:916 +#: src/output/output.c:949 #, c-format msgid "Trying to find keyword `%s'...\n" msgstr "" -#: src/output/output.c:1033 +#: src/output/output.c:1066 #, c-format msgid "Unit \"%s\" is unknown in dimension \"%s\"." msgstr "" -#: src/output/output.c:1048 +#: src/output/output.c:1081 #, c-format msgid "Bad dimension \"%s\"." msgstr "" -#: src/output/output.c:1074 +#: src/output/output.c:1107 #, c-format msgid "`x' expected in paper size `%s'." msgstr "" -#: src/output/output.c:1084 +#: src/output/output.c:1117 #, c-format msgid "Trailing garbage `%s' on paper size `%s'." msgstr "" -#: src/output/output.c:1133 +#: src/output/output.c:1166 msgid "Paper size name must not be empty." msgstr "" -#: src/output/output.c:1164 +#: src/output/output.c:1197 msgid "Cannot find `papersize' configuration file." msgstr "" -#: src/output/output.c:1168 +#: src/output/output.c:1201 #, c-format msgid "%s: Opening paper size definition file..." msgstr "" -#: src/output/output.c:1210 +#: src/output/output.c:1243 msgid "Syntax error in paper size definition." msgstr "" -#: src/output/output.c:1239 +#: src/output/output.c:1272 msgid "Paper size definition file read successfully." msgstr "" -#: src/output/output.c:1241 +#: src/output/output.c:1274 msgid "Error reading paper size definition file." msgstr "" -#: src/output/output.c:1297 +#: src/output/output.c:1330 #, c-format msgid "Error closing page on %s device of %s class." msgstr "" -#: src/output/output.c:1301 +#: src/output/output.c:1334 #, c-format msgid "Error opening page on %s device of %s class." msgstr "" @@ -4731,22 +4731,22 @@ msgstr "" msgid "%s: %s: Opening PostScript prologue..." msgstr "" -#: src/output/postscript.c:1467 +#: src/output/postscript.c:1465 #, c-format msgid "%s: PostScript prologue read successfully." msgstr "" -#: src/output/postscript.c:1471 +#: src/output/postscript.c:1469 #, c-format msgid "%s: Error reading PostScript prologue." msgstr "" -#: src/output/postscript.c:1641 +#: src/output/postscript.c:1639 #, c-format msgid "PostScript output driver: %s: %s" msgstr "" -#: src/output/postscript.c:2340 +#: src/output/postscript.c:2338 #, c-format msgid "PostScript driver: Cannot find encoding `%s' for PostScript font `%s'." msgstr "" diff --git a/src/data/ChangeLog b/src/data/ChangeLog index ce225537..669836c6 100644 --- a/src/data/ChangeLog +++ b/src/data/ChangeLog @@ -1,3 +1,9 @@ +Tue Mar 28 13:47:16 WST 2006 John Darrington + + * filename.[ch] (fn_interp_vars): Changed the signature and semantics + so as to modify the string inline. Thus makeing it easier to + destroy the results when no longer needed. + 2006-03-25 Jason Stover * category.c (cat_stored_values_destroy): Fixed memory leak. diff --git a/src/data/filename.c b/src/data/filename.c index 569d185d..728585df 100644 --- a/src/data/filename.c +++ b/src/data/filename.c @@ -69,69 +69,87 @@ fn_init (void) /* Functions for performing operations on filenames. */ -/* Substitutes $variables as defined by GETENV into INPUT and returns - a copy of the resultant string. Supports $var and ${var} syntaxes; - $$ substitutes as $. */ -char * -fn_interp_vars (const char *input, const char *(*getenv) (const char *)) + +/* Substitutes $variables as defined by GETENV into TARGET. + TARGET must be a string containing the text for which substitution + is required. + Supports $var and ${var} syntaxes; + $$ substitutes as $. +*/ +void +fn_interp_vars (struct string *target, + const char *(*getenv) (const char *)) { - struct string output; + assert (target); - if (NULL == strchr (input, '$')) - return xstrdup (input); + char *input = xmalloc(ds_length(target) + 1); + char *s = input; - ds_init (&output, strlen (input)); + strcpy(input, ds_c_str(target)); + + if (NULL == strchr (ds_c_str(target), '$')) + goto done; + + ds_clear(target); for (;;) - switch (*input) - { - case '\0': - return ds_c_str (&output); + { + switch (*s) + { + case '\0': + goto done ; - case '$': - input++; - - if (*input == '$') - { - ds_putc (&output, '$'); - input++; - } - else - { - int stop; - int start; - const char *value; - - start = ds_length (&output); - - if (*input == '(') - { - stop = ')'; - input++; - } - else if (*input == '{') - { - stop = '}'; - input++; - } - else - stop = 0; + case '$': + s++; - while (*input && *input != stop - && (stop || isalpha ((unsigned char) *input))) - ds_putc (&output, *input++); + if (*s == '$') + { + ds_putc (target, '$'); + s++; + } + else + { + int stop; + int start; + const char *value; + + start = ds_length (target); + + if (*s == '(') + { + stop = ')'; + s++; + } + else if (*s == '{') + { + stop = '}'; + s++; + } + else + stop = 0; + + while (*s && *s != stop + && (stop || isalpha ((unsigned char) *s))) + { + ds_putc (target, *s++); + } - value = getenv (ds_c_str (&output) + start); - ds_truncate (&output, start); - ds_puts (&output, value); + value = getenv (ds_c_str (target) + start); + ds_truncate (target, start); + ds_puts (target, value); - if (stop && *input == stop) - input++; - } + if (stop && *s == stop) + s++; + } - default: - ds_putc (&output, *input++); - } + default: + ds_putc (target, *s++); + } + } + + done: + free(input); + return; } #ifdef unix @@ -218,9 +236,14 @@ fn_search_path (const char *basename, const char *path, const char *prepend) return fn_tilde_expand (basename); { - char *temp = fn_interp_vars (path, fn_getenv); - bp = subst_path = fn_tilde_expand (temp); - free (temp); + struct string temp; + ds_create(&temp, path); + + fn_interp_vars(&temp, fn_getenv); + + bp = subst_path = fn_tilde_expand (ds_c_str(&temp)); + + ds_destroy(&temp); } msg (VM (4), _("Searching for `%s'..."), basename); diff --git a/src/data/filename.h b/src/data/filename.h index 3ad4d642..93fa6e2a 100644 --- a/src/data/filename.h +++ b/src/data/filename.h @@ -36,7 +36,9 @@ extern const char *config_path; void fn_init (void); -char *fn_interp_vars (const char *input, const char *(*getenv) (const char *)); +struct string; +void fn_interp_vars (struct string *target, + const char *(*getenv) (const char *)); char *fn_tilde_expand (const char *fn); char *fn_search_path (const char *basename, const char *path, const char *prepend); diff --git a/src/libpspp/ChangeLog b/src/libpspp/ChangeLog index dea90675..1902d196 100644 --- a/src/libpspp/ChangeLog +++ b/src/libpspp/ChangeLog @@ -1,3 +1,8 @@ +Tue Mar 28 13:49:11 WST 2006 John Darrington + + * str.[ch]: New functions ds_create_substr, ds_find, ds_n_find, + ds_ltrim_spaces + Sat Mar 4 12:59:01 2006 Ben Pfaff * compiler.h: New file. diff --git a/src/libpspp/str.c b/src/libpspp/str.c index 6b207ee2..b8e55344 100644 --- a/src/libpspp/str.c +++ b/src/libpspp/str.c @@ -242,6 +242,21 @@ ds_create (struct string *st, const char *s) strcpy (st->string, s); } +/* Initializes DST with the contents of SRC between characters FIRST and LAST + inclusive */ +void +ds_create_substr(struct string *dst, const struct string *src, + int first, int last) +{ + assert(last >= first); + dst->length = last - first + 1; + dst->capacity = 8 + dst->length * 2; + dst->string = xmalloc (dst->capacity + 1); + + memcpy (dst->string, &src->string[first], dst->length); +} + + /* Initializes ST, making room for at least CAPACITY characters. */ void ds_init (struct string *st, size_t capacity) @@ -330,6 +345,28 @@ ds_rtrim_spaces (struct string *st) return cnt; } +/* Removes leading spaces from ST. + Returns number of spaces removed. */ +int +ds_ltrim_spaces (struct string *st) +{ + int idx = ds_n_find(st, "\t "); + if (0 == idx) + return 0; + + if (idx < 0 ) + { + int len = ds_length(st); + ds_clear(st); + return len; + } + + ds_replace(st, &ds_c_str(st)[idx]); + + return idx; +} + + /* If the last character in ST is C, removes it and returns true. Otherwise, returns false without modifying ST. */ bool @@ -401,6 +438,59 @@ ds_capacity (const struct string *st) return st->capacity; } + +/* Returns the index of the first character in ST which + is an element of the set CS. + Returns -1 if no characters are found. +*/ +int +ds_find(const struct string *st, const char cs[]) +{ + int i; + int j; + for(i = 0; i < st->length ; ++i) + { + if ('\0' == st->string[i]) + break; + for (j = 0 ; j < strlen(cs) ; ++j) + { + if ( st->string[i] == cs[j]) + return i; + } + } + return -1; +} + +/* Returns the index of the first character in ST which + is NOT an element of the set CS. + Returns -1 if no such character is found. +*/ +int +ds_n_find(const struct string *st, const char cs[]) +{ + int i; + int j; + for(i = 0; i < st->length ; ++i) + { + bool found = false; + if ('\0' == st->string[i]) + break; + for (j = 0 ; j < strlen(cs) ; ++j) + { + if ( st->string[i] == cs[j]) + { + found = true; + break; + } + } + if ( !found ) + return i; + } + return -1; +} + + + /* Returns the first character in ST as a value in the range of unsigned char. Returns EOF if ST is the empty string. */ int diff --git a/src/libpspp/str.h b/src/libpspp/str.h index 7773db02..c0643263 100644 --- a/src/libpspp/str.h +++ b/src/libpspp/str.h @@ -20,6 +20,7 @@ #if !str_h #define str_h 1 +#include #include #include #include @@ -128,6 +129,8 @@ void ds_shrink (struct string *); void ds_truncate (struct string *, size_t); void ds_rpad (struct string *, size_t length, char pad); int ds_rtrim_spaces (struct string *); +int ds_ltrim_spaces (struct string *st); + bool ds_chomp (struct string *, char); /* Inspectors. */ @@ -171,6 +174,7 @@ ds_length (const struct string *st) extern inline char * ds_c_str (const struct string *st) { + assert(st); ((char *) st->string)[st->length] = '\0'; return st->string; } @@ -206,4 +210,12 @@ spprintf (char *dst, const char *format, ...) return dst + count; } +int ds_find(const struct string *st, const char cs[]); + +int ds_n_find(const struct string *st, const char cs[]); + +void ds_create_substr(struct string *dst, const struct string *src, + int first, int last); + + #endif /* str_h */ diff --git a/src/output/ChangeLog b/src/output/ChangeLog index a33c27f9..0560dd88 100644 --- a/src/output/ChangeLog +++ b/src/output/ChangeLog @@ -1,3 +1,8 @@ +Tue Mar 28 13:50:53 WST 2006 John Darrington + + * html.c, postscript.c, output.c: Changed to fit the new signature + of fn_interp_vars + Sun Mar 5 13:19:32 2006 Ben Pfaff * postscript.c: (postopen) Fix segfault when the active file has diff --git a/src/output/html.c b/src/output/html.c index 69222f5e..658858be 100644 --- a/src/output/html.c +++ b/src/output/html.c @@ -299,7 +299,7 @@ postopen (struct file_ext *f) html_var_tab = dict; while (-1 != getline (&buf, &buf_size, prologue_file)) { - char *buf2; + int len; if (strstr (buf, "!!!")) @@ -328,12 +328,14 @@ postopen (struct file_ext *f) } /* PORTME: Line terminator. */ - buf2 = fn_interp_vars (buf, html_get_var); - len = strlen (buf2); - fwrite (buf2, len, 1, f->file); - if (buf2[len - 1] != '\n') + struct string line; + ds_create(&line, buf); + fn_interp_vars(&line, html_get_var); + len = ds_length(&line); + fwrite (ds_c_str(&line), len, 1, f->file); + if (ds_c_str(&line)[len - 1] != '\n') putc ('\n', f->file); - free (buf2); + ds_destroy(&line); } if (ferror (f->file)) msg (IE, _("Reading `%s': %s."), prologue_fn, strerror (errno)); diff --git a/src/output/output.c b/src/output/output.c index 4a915fe2..716f7c10 100644 --- a/src/output/output.c +++ b/src/output/output.c @@ -61,7 +61,7 @@ struct outp_names struct outp_defn { char *key; - char *value; + struct string value; struct outp_defn *next, *prev; }; @@ -79,7 +79,7 @@ char *outp_subtitle; static int disabled_devices; static void destroy_driver (struct outp_driver *); -static void configure_driver_line (char *); +static void configure_driver_line (struct string *); static void configure_driver (const char *, const char *, const char *, const char *); @@ -200,7 +200,7 @@ find_defn_value (const char *key) for (d = outp_macros; d; d = d->next) if (!strcmp (key, d->key)) - return d->value; + return ds_c_str(&d->value); if (!strcmp (key, "viewwidth")) { sprintf (buf, "%d", get_viewwidth ()); @@ -244,7 +244,7 @@ delete_macros (void) { next = d->next; free (d->key); - free (d->value); + ds_destroy (&d->value); free (d); } } @@ -322,7 +322,7 @@ outp_read_devices (void) struct outp_names *n = search_names (cp, ep); if (n) { - configure_driver_line (cp); + configure_driver_line (&line); delete_name (n); } } @@ -411,7 +411,9 @@ outp_configure_macro (char *bp) ep++; while (isspace ((unsigned char) *ep)) ep++; - d->value = fn_interp_vars (ep, find_defn_value); + + ds_create(&d->value, ep); + fn_interp_vars(&d->value, find_defn_value); d->next = outp_macros; d->prev = NULL; if (outp_macros) @@ -662,37 +664,58 @@ find_driver (char *name) return NULL; } -/* Tokenize string S into colon-separated fields, removing leading and - trailing whitespace on tokens. Returns a pointer to the - null-terminated token, which is formed by setting a NUL character - into the string. After the first call, subsequent calls should set - S to NULL. CP should be consistent across calls. Returns NULL - after all fields have been used up. +/* Tokenize string SRC into colon-separated fields, removing leading and + trailing whitespace on tokens. Tokens are placed into DEST. + + CP should remain unchanged throughout. + It is the callers responsibility to destroy CP and DEST. + + + Returns true if there are more fields, false otherwise. FIXME: Should ignore colons inside double quotes. */ -static const char * -colon_tokenize (char *s, char **cp) +static bool +colon_tokenize(const struct string *src, struct string *dest, + struct string *cp) { - char *token; + int last; + + if ( src ) + ds_create(cp, ds_c_str(src)); + + int first = ds_n_find(cp, "\t "); + int delim = ds_find(cp, ":") ; - if (!s) + if ( delim < 0 ) + last = ds_length(cp); + else + last = delim - 1; + + if ( delim == first) { - s = *cp; - if (*s == 0) - return NULL; + ds_create(dest,""); } - token = s += strspn (s, " \t\v\r"); - *cp = strchr (s, ':'); - if (*cp == NULL) - s = *cp = strchr (s, 0); else - s = (*cp)++; - while (s > token && strchr (" \t\v\r", s[-1])) - s--; - *s = 0; - return token; + { + ds_create_substr(dest, cp, first, last); + } + + if ( last < ds_length(cp) ) + { + struct string temp; + ds_create_substr(&temp, cp, last + 2, ds_length(cp)); + ds_swap(cp, &temp); + ds_destroy(&temp); + return true; + } + else + { + ds_clear(cp); + return false; + } } + /* String S is in format: DRIVERNAME:CLASSNAME:DEVICETYPE:OPTIONS Adds a driver to outp_driver_list pursuant to the specification @@ -791,31 +814,41 @@ error: return; } -/* String S is in format: +/* String LINE is in format: DRIVERNAME:CLASSNAME:DEVICETYPE:OPTIONS Adds a driver to outp_driver_list pursuant to the specification provided. */ static void -configure_driver_line (char *s) +configure_driver_line (struct string *line) { - char *cp; - const char *driver_name, *class_name, *device_type, *options; + fn_interp_vars(line, find_defn_value); - s = fn_interp_vars (s, find_defn_value); + struct string driver_name; + struct string class_name; + struct string device_type; + struct string options; - /* Driver name. */ - driver_name = colon_tokenize (s, &cp); - class_name = colon_tokenize (NULL, &cp); - device_type = colon_tokenize (NULL, &cp); - options = colon_tokenize (NULL, &cp); - if (driver_name == NULL || class_name == NULL) + struct string sss; + colon_tokenize (line, &driver_name, &sss); + colon_tokenize (NULL, &class_name, &sss); + colon_tokenize (NULL, &device_type, &sss); + colon_tokenize (NULL, &options, &sss); + + if (ds_is_empty(&driver_name) || ds_is_empty(&class_name)) { msg (IS, _("Driver definition line contains fewer fields " "than expected")); return; } - configure_driver (driver_name, class_name, device_type, options); + configure_driver (ds_c_str(&driver_name), ds_c_str(&class_name), + ds_c_str(&device_type), ds_c_str(&options)); + + ds_destroy(&driver_name); + ds_destroy(&class_name); + ds_destroy(&device_type); + ds_destroy(&options); + ds_destroy(&sss); } /* Destroys output driver D. */ diff --git a/src/output/postscript.c b/src/output/postscript.c index e6ce8614..5d0d5776 100644 --- a/src/output/postscript.c +++ b/src/output/postscript.c @@ -1406,7 +1406,7 @@ postopen (struct file_ext *f) while (-1 != getline (&buf, &buf_size, prologue_file)) { char *cp; - char *buf2; + int len; cp = strstr (buf, "!eps"); @@ -1436,18 +1436,16 @@ postopen (struct file_ext *f) output_encodings (this); else { - char *beg; - beg = buf2 = fn_interp_vars (buf, ps_get_var); - len = strlen (buf2); - while (isspace ((unsigned char) *beg)) - beg++, len--; - if (beg[len - 1] == '\n') - len--; - if (beg[len - 1] == '\r') - len--; - fwrite (beg, len, 1, f->file); + struct string line; + ds_create(&line, buf); + fn_interp_vars(&line, ps_get_var); + ds_ltrim_spaces(&line); + len = ds_length(&line); + fwrite (ds_c_str(&line), len, 1, f->file); + + ds_destroy(&line); + fputs (x->eol, f->file); - free (buf2); } } if (ferror (f->file)) -- 2.30.2