Fixed memory leaks resulting from fn_interp_vars et. al.
authorJohn Darrington <john@darrington.wattle.id.au>
Tue, 28 Mar 2006 06:05:05 +0000 (06:05 +0000)
committerJohn Darrington <john@darrington.wattle.id.au>
Tue, 28 Mar 2006 06:05:05 +0000 (06:05 +0000)
12 files changed:
po/en_GB.po
po/pspp.pot
src/data/ChangeLog
src/data/filename.c
src/data/filename.h
src/libpspp/ChangeLog
src/libpspp/str.c
src/libpspp/str.h
src/output/ChangeLog
src/output/html.c
src/output/output.c
src/output/postscript.c

index 9bc4b370a8271f975fe250f341bc3455dc422c50..82b0f4d4ecd5efcc1ee759e785dd6a77cfe40c8c 100644 (file)
@@ -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 <john@darrington.wattle.id.au>\n"
 "Language-Team: John Darrington <john@darrington.wattle.id.au>\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 ""
index 63379e4c3f314dd6038d85422b3beed619925c88..450ace185fdc7da9821c0b09911bd7eae92419bb 100644 (file)
@@ -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 <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\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 ""
index ce225537832fdd22972bbe76353b9ad765af3ad1..669836c6d729fc51ee47867cccea300bccdf15e6 100644 (file)
@@ -1,3 +1,9 @@
+Tue Mar 28 13:47:16 WST 2006 John Darrington <john@darrington.wattle.id.au>
+       
+       * 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  <jhs@math.gcsu.edu>
 
        * category.c (cat_stored_values_destroy): Fixed memory leak.
index 569d185d223a1313e756cb50ac2b7f7563a7bfd8..728585df11d93ab6b810e75a6990c7b833965fab 100644 (file)
@@ -69,69 +69,87 @@ fn_init (void)
 \f
 /* 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);
index 3ad4d642b932e1376e4bbb9db20154bdef6dc113..93fa6e2a3dbe3662c1722b2674e17f159eece54a 100644 (file)
@@ -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);
index dea90675adb248f1d2883e0cddab51160e483854..1902d196dc261e9aa784a23c837dd60a3df6f00c 100644 (file)
@@ -1,3 +1,8 @@
+Tue Mar 28 13:49:11 WST 2006 John Darrington <john@darrington.wattle.id.au>
+
+       * str.[ch]: New functions ds_create_substr, ds_find, ds_n_find, 
+       ds_ltrim_spaces
+
 Sat Mar  4 12:59:01 2006  Ben Pfaff  <blp@gnu.org>
 
        * compiler.h: New file.
index 6b207ee288f66f4c941ecf8940153ea1e83bd481..b8e55344d3a4ae0bc663d00db6735eba3c78c4d5 100644 (file)
@@ -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
index 7773db022ca69fb54cb0a9a53c3e739330794604..c0643263d36b85075616620a3d2a0662a4e4f4f4 100644 (file)
@@ -20,6 +20,7 @@
 #if !str_h
 #define str_h 1
 
+#include <assert.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -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 */
index a33c27f9221a2a26a8a421f379dfa53db3d0b150..0560dd88a1428b9844233411d947b15cc4f268bf 100644 (file)
@@ -1,3 +1,8 @@
+Tue Mar 28 13:50:53 WST 2006 John Darrington <john@darrington.wattle.id.au>
+
+       * 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  <blp@gnu.org>
 
        * postscript.c: (postopen) Fix segfault when the active file has
index 69222f5e229b60120ca49c4c1a71a39428b8c9b8..658858be3f6ddaca01688759c8e5dd341b1a9a63 100644 (file)
@@ -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));
index 4a915fe2ef6e3acd2635ada098ccf0b6a0b3f982..716f7c10eac7e81ce428ad9f3ea1857a994c3b1d 100644 (file)
@@ -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. */
index e6ce8614825b6554adae61b6ea5478ce642e08b3..5d0d577607687132fb95cf7c5f2db8a23341d215 100644 (file)
@@ -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))