Fix rest of PR 13054.
authorBen Pfaff <blp@gnu.org>
Mon, 16 May 2005 07:33:16 +0000 (07:33 +0000)
committerBen Pfaff <blp@gnu.org>
Mon, 16 May 2005 07:33:16 +0000 (07:33 +0000)
Regularize string and buffer function names so that they make some
kind of sense.

28 files changed:
src/ChangeLog
src/aggregate.c
src/command.c
src/compute.c
src/count.c
src/data-in.c
src/data-list.c
src/data-out.c
src/descript.c
src/dictionary.c
src/expressions/evaluate.c
src/expressions/parse.c
src/file-handle.q
src/file-type.c
src/filename.c
src/flip.c
src/format.c
src/format.def
src/lexer.c
src/matrix-data.c
src/pfm-read.c
src/recode.c
src/sfm-write.c
src/str.c
src/str.h
src/title.c
src/val-labs.c
src/vars-atr.c

index 38401f8d68fec202bff9ba44238289cc60957cbe..9039838edb3287d4bd821aaddea9dc73feaae287 100644 (file)
@@ -1,3 +1,39 @@
+Sun May 15 23:38:10 2005  Ben Pfaff  <blp@gnu.org>
+
+       Fix rest of PR 13054.
+       
+       * format.def: FMT_A should allow 255-character output.  FMT_AHEX
+       should allow 510-character input and output.
+
+       * data-out.c: (num_to_string) Get rid of NEW_STYLE option.
+       (convert_E) Handle non-finite values.
+       (try_F) Rewrite.
+       (format_and_round) New function.
+       (convert_infinite) New function used by try_F() and convert_E().
+
+Sun May 15 23:36:55 2005  Ben Pfaff  <blp@gnu.org>
+
+       Regularize string and buffer function names so that they make some
+       kind of sense.
+
+       * str.c: (mm_reverse) Rename buf_reverse().  Update all
+       references.
+       (mm_find_reverse) Rename buf_find_reverse().  Update all
+       references.
+       (mm_case_compare) Rename buf_compare_case().  Update all
+       references.
+       (st_compare_pad) Rename buf_compare_rpad().  Update all
+       references.
+       (str_compare_rpad) New function.
+       (st_bare_pad_copy) Rename buf_copy_str_rpad().  Update all
+       references.
+       (buf_copy_str_lpad) New function.
+       (st_bare_pad_len_copy) Rename buf_copy_rpad().  Update all
+       references.
+       (st_pad_copy) Rename str_copy_rpad().  Update all references.
+       (st_trim_copy) Rename str_copy_trunc().  Update all references.
+       (st_uppercase) Renamed str_uppercase().  Update all references.
+       
 Sat May 14 08:22:26 WST 2005 John Darrington <john@darrington.wattle.id.au>
 
        * dfm-read.c: Fixed polarity of test in dfm-close-reader.  Closes 
@@ -11,7 +47,7 @@ Tue May 10 20:08:18 2005  Ben Pfaff  <blp@gnu.org>
 
 Tue May 10 19:56:35 2005  Ben Pfaff  <blp@gnu.org>
 
-       Fix PR 13054.
+       Start to fix PR 13054.
 
        * format.c: (check_input_specifier) Improve error message.
        (check_input_specifier) Check F, COMMA, and DOLLAR formats for
index 154256f5e59b96260b2c4ea713f427ee44e7c78a..7f34309c5354da7cdcc31f4c1d7ccb12ecead7a5 100644 (file)
@@ -491,8 +491,7 @@ parse_aggregate_functions (struct agr_proc *agr)
               || func_index == FIN || func_index == FOUT) 
               && ((src[0]->type == NUMERIC && arg[0].f > arg[1].f)
                   || (src[0]->type == ALPHA
-                      && st_compare_pad (arg[0].c, strlen (arg[0].c),
-                                         arg[1].c, strlen (arg[1].c)) > 0)))
+                      && str_compare_rpad (arg[0].c, arg[1].c) > 0)))
             {
               union value t = arg[0];
               arg[0] = arg[1];
index 1e9fd570a6d8b3fbb0c7a11cb6d51273d2dda6ba..3185446789b5073ae0b225ce2bdd855152214e3e 100644 (file)
@@ -343,14 +343,14 @@ conflicting_3char_prefixes (const char *a, const char *b)
   assert (aw != NULL && bw != NULL);
 
   /* Words that are the same don't conflict. */
-  if (aw_len == bw_len && !mm_case_compare (aw, bw, aw_len))
+  if (aw_len == bw_len && !buf_compare_case (aw, bw, aw_len))
     return 0;
   
   /* Words that are otherwise the same in the first three letters
      do conflict. */
   return ((aw_len > 3 && bw_len > 3)
           || (aw_len == 3 && bw_len > 3)
-          || (bw_len == 3 && aw_len > 3)) && !mm_case_compare (aw, bw, 3);
+          || (bw_len == 3 && aw_len > 3)) && !buf_compare_case (aw, bw, 3);
 }
 
 /* Returns nonzero if CMD can be confused with another command
@@ -392,7 +392,7 @@ cmd_match_words (const struct command *cmd,
        word != NULL && word_idx < word_cnt;
        word = find_word (word + word_len, &word_len), word_idx++)
     if (word_len != strlen (words[word_idx])
-        || mm_case_compare (word, words[word_idx], word_len))
+        || buf_compare_case (word, words[word_idx], word_len))
       {
         size_t match_chars = match_strings (word, word_len,
                                             words[word_idx],
index 24148fe68f94b55af0a1d0b3941dc6f10ebb0139..256b6a7e3eec3be34d1590c6b88974b661c1b1e4 100644 (file)
@@ -353,7 +353,7 @@ lvalue_parse (void)
   else
     {
       /* Variable name. */
-      st_trim_copy (lvalue->var_name, tokid, sizeof lvalue->var_name);
+      str_copy_trunc (lvalue->var_name, sizeof lvalue->var_name, tokid);
       lex_get ();
     }
   return lvalue;
index 82085d6fe0f6e476d74b9e2d653dfaca34e06ca4..e3220d79485a5d94ea9c39f8c24374897c46fcd0 100644 (file)
@@ -158,7 +158,7 @@ cmd_count (void)
            }
        }
       else
-       st_trim_copy (cnt->n, tokid, sizeof cnt->n);
+       str_copy_trunc (cnt->n, sizeof cnt->n, tokid);
 
       lex_get ();
       if (!lex_force_match ('='))
@@ -349,7 +349,7 @@ parse_string_criteria (struct counting * c)
       cur = &c->crit.s[n++];
       cur->type = CNT_SINGLE;
       cur->s = malloc (len + 1);
-      st_pad_copy (cur->s, ds_c_str (&tokstr), len + 1);
+      str_copy_rpad (cur->s, len + 1, ds_c_str (&tokstr));
       lex_get ();
 
       lex_match (',');
index d17a2cf7d67746e54032b42b3b8d41841862b9c9..3a49fa23706e8537881c204ffaeb9f83b99204d7 100644 (file)
@@ -468,7 +468,7 @@ parse_IB (struct data_in *i)
   p = i->s;
 #else
   memcpy (buf, i->s, i->e - i->s);
-  mm_reverse (buf, i->e - i->s);
+  buf_reverse (buf, i->e - i->s);
   p = buf;
 #endif
 
@@ -760,7 +760,7 @@ parse_enum (struct data_in *i, const char *what,
     if ((ep->can_abbreviate
          && lex_id_match_len (ep->name, strlen (ep->name), name, length))
         || (!ep->can_abbreviate && length == strlen (ep->name)
-            && !mm_case_compare (name, ep->name, length)))
+            && !buf_compare_case (name, ep->name, length)))
       {
         *output = ep->value;
         return true;
index 1e9deb8006f613c501b9a108e4db8bcdc31dce8c..a6a68dc687942f5964afada2b132a3dd42d94c15 100644 (file)
@@ -879,7 +879,7 @@ parse_free (struct dls_var_spec **first, struct dls_var_spec **last)
           spec->input = input;
           spec->v = v;
          spec->fv = v->fv;
-         st_trim_copy (spec->name, v->name, sizeof spec->name);
+         str_copy_trunc (spec->name, sizeof spec->name, v->name);
          append_var_spec (first, last, spec);
        }
       for (i = 0; i < name_cnt; i++)
index 4289490bd9fc9d4b6f0943ad6565731c0628ec07..6439b607045f18e5566deec8a438b9197f88d03e 100644 (file)
 #include "var.h"
 
 #include "debug-print.h"
-
-/* In older versions, numbers got their trailing zeros stripped.
-   Newer versions leave them on when there's room.  Comment this next
-   line out for retro styling. */
-#define NEW_STYLE 1
 \f
 /* Public functions. */
 
@@ -48,7 +43,9 @@ static numeric_converter convert_F, convert_N, convert_E, convert_F_plus;
 static numeric_converter convert_Z, convert_IB, convert_P, convert_PIB;
 static numeric_converter convert_PIBHEX, convert_PK, convert_RB;
 static numeric_converter convert_RBHEX, convert_CCx, convert_date;
-static numeric_converter convert_time, convert_WKDAY, convert_MONTH, try_F;
+static numeric_converter convert_time, convert_WKDAY, convert_MONTH;
+
+static numeric_converter try_F, convert_infinite;
 
 typedef int string_converter (char *, const struct fmt_spec *, const char *);
 static string_converter convert_A, convert_AHEX;
@@ -196,92 +193,11 @@ data_out (char *s, const struct fmt_spec *fp, const union value *v)
 void
 num_to_string (double v, char *s, int w, int d)
 {
-  /* Dummy to pass to convert_F. */
   struct fmt_spec f;
-
-#if !NEW_STYLE
-  /* Pointer to `.' in S. */
-  char *decp;
-
-  /* Pointer to `E' in S. */
-  char *expp;
-
-  /* Number of characters to delete. */
-  int n = 0;
-#endif
-
+  f.type = FMT_F;
   f.w = w;
   f.d = d;
-
-  /* Cut out the jokers. */
-  if (!finite (v))
-    {
-      char temp[9];
-      int len;
-
-      if (isnan (v))
-       {
-         memcpy (temp, "NaN", 3);
-         len = 3;
-       }
-      else if (isinf (v))
-       {
-         memcpy (temp, "+Infinity", 9);
-         if (v < 0)
-           temp[0] = '-';
-         len = 9;
-       }
-      else
-       {
-         memcpy (temp, _("Unknown"), 7);
-         len = 7;
-       }
-      if (w > len)
-       {
-         int pad = w - len;
-         memset (s, ' ', pad);
-         s += pad;
-         w -= pad;
-       }
-      memcpy (s, temp, w);
-      return;
-    }
-
-  try_F (s, &f, v);
-
-#if !NEW_STYLE
-  decp = memchr (s, set_decimal, w);
-  if (!decp)
-    return;
-
-  /* If there's an `E' we can only delete 0s before the E. */
-  expp = memchr (s, 'E', w);
-  if (expp)
-    {
-      while (expp[-n - 1] == '0')
-       n++;
-      if (expp[-n - 1] == set_decimal)
-       n++;
-      memmove (&s[n], s, expp - s - n);
-      memset (s, ' ', n);
-      return;
-    }
-
-  /* Otherwise delete all trailing 0s. */
-  n++;
-  while (s[w - n] == '0')
-    n++;
-  if (s[w - n] != set_decimal)
-    {
-      /* Avoid stripping `.0' to `'. */
-      if (w == n || !isdigit ((unsigned char) s[w - n - 1]))
-       n -= 2;
-    }
-  else
-    n--;
-  memmove (&s[n], s, w - n);
-  memset (s, ' ', n);
-#endif
+  convert_F (s, &f, v);
 }
 \f
 /* Main conversion functions. */
@@ -295,21 +211,6 @@ static int try_CCx (char *s, const struct fmt_spec *fp, double v);
 #error Write your own floating-point output routines.
 #endif
 
-/* PORTME:
-
-   Some of the routines in this file are likely very specific to
-   base-2 representation of floating-point numbers, most notably the
-   routines that use frexp() or ldexp().  These attempt to extract
-   individual digits by setting the base-2 exponent and
-   multiplying/dividing by powers of 2.  In base-2 numeration systems,
-   this just nudges the exponent up or down, but in base-10 floating
-   point, such multiplications/division can cause catastrophic loss of
-   precision.
-
-   The author has never personally used a machine that didn't use
-   binary floating point formats, so he is unwilling, and perhaps
-   unable, to code around this "problem".  */
-
 /* Converts a number between 0 and 15 inclusive to a `hexit'
    [0-9A-F]. */
 #define MAKE_HEXIT(X) ("0123456789ABCDEF"[X])
@@ -369,7 +270,10 @@ convert_E (char *dst, const struct fmt_spec *fp, double number)
   /* Ranged number of decimal places. */
   int d;
 
-  /* Check that the format is width enough.
+  if (!finite (number))
+    return convert_infinite (dst, fp, number);
+
+  /* Check that the format is wide enough.
      Although PSPP generally checks this, convert_E() can be called as
      a fallback from other formats which do not check. */
   if (fp->w < 6)
@@ -561,7 +465,7 @@ convert_IB (char *dst, const struct fmt_spec *fp, double number)
     }
   memcpy (dst, temp, fp->w);
 #ifndef WORDS_BIGENDIAN
-  mm_reverse (dst, fp->w);
+  buf_reverse (dst, fp->w);
 #endif
 
   return 1;
@@ -625,7 +529,7 @@ convert_PIB (char *dst, const struct fmt_spec *fp, double number)
       ((unsigned char *) dst)[i] = floor (frac);
     }
 #ifndef WORDS_BIGENDIAN
-  mm_reverse (dst, fp->w);
+  buf_reverse (dst, fp->w);
 #endif
 
   return 1;
@@ -852,7 +756,7 @@ convert_date (char *dst, const struct fmt_spec *fp, double number)
 
   if (buf[0] == 0)
     return 0;
-  st_bare_pad_copy (dst, buf, fp->w);
+  buf_copy_str_rpad (dst, fp->w, buf);
   return 1;
 }
 
@@ -902,7 +806,7 @@ convert_time (char *dst, const struct fmt_spec *fp, double number)
 
       cp = spprintf (cp, ":%0*.*f", w, d, fmod (time, 60.));
     }
-  st_bare_pad_copy (dst, temp_buf, fp->w);
+  buf_copy_str_rpad (dst, fp->w, temp_buf);
 
   return 1;
 }
@@ -922,7 +826,7 @@ convert_WKDAY (char *dst, const struct fmt_spec *fp, double wkday)
            (double) wkday);
       return 0;
     }
-  st_bare_pad_copy (dst, weekdays[(int) wkday - 1], fp->w);
+  buf_copy_str_rpad (dst, fp->w, weekdays[(int) wkday - 1]);
 
   return 1;
 }
@@ -943,7 +847,7 @@ convert_MONTH (char *dst, const struct fmt_spec *fp, double month)
       return 0;
     }
   
-  st_bare_pad_copy (dst, months[(int) month - 1], fp->w);
+  buf_copy_str_rpad (dst, fp->w, months[(int) month - 1]);
 
   return 1;
 }
@@ -1121,201 +1025,225 @@ try_CCx (char *dst, const struct fmt_spec *fp, double number)
   return 1;
 }
 
-/* This routine relies on the underlying implementation of sprintf:
-
-   If the number has a magnitude 1e40 or greater, then we needn't
-   bother with it, since it's guaranteed to need processing in
-   scientific notation.
-
-   Otherwise, do a binary search for the base-10 magnitude of the
-   thing.  log10() is not accurate enough, and the alternatives are
-   frightful.  Besides, we never need as many as 6 (pairs of)
-   comparisons.  The algorithm used for searching is Knuth's Algorithm
-   6.2.1C (Uniform binary search).
+static int
+format_and_round (char *dst, double number, const struct fmt_spec *fp,
+                  int decimals);
 
-   DON'T CHANGE ANYTHING HERE UNLESS YOU'VE THOUGHT ABOUT IT FOR A
-   LONG TIME!  The rest of the program is heavily dependent on
-   specific properties of this routine's output.  LOG ALL CHANGES! */
+/* Tries to format NUMBER into DST as the F format specified in
+   *FP.  Return true if successful, false on failure. */
 static int
 try_F (char *dst, const struct fmt_spec *fp, double number)
 {
-  /* This is the DELTA array from Knuth.
-     DELTA[j] = floor((40+2**(j-1))/(2**j)). */
-  static const int delta[8] =
-  {
-    0, (40 + 1) / 2, (40 + 2) / 4, (40 + 4) / 8, (40 + 8) / 16,
-    (40 + 16) / 32, (40 + 32) / 64, (40 + 64) / 128,
-  };
+  assert (fp->w <= 40);
+  if (finite (number)) 
+    {
+      if (fabs (number) < power10[fp->w])
+        {
+          /* The value may fit in the field. */
+          if (fp->d == 0) 
+            {
+              /* There are no decimal places, so there's no way
+                 that the value can be shortened.  Either it fits
+                 or it doesn't. */
+              char buf[40];
+              sprintf (buf, "%*.0f", fp->w, number);
+              if (strlen (buf) <= fp->w) 
+                {
+                  buf_copy_str_lpad (dst, fp->w, buf);
+                  return true; 
+                }
+              else 
+                return false;
+            }
+          else 
+            {
+              /* First try to format it with 2 extra decimal
+                 places.  This gives us a good chance of not
+                 needing even more decimal places, but it also
+                 avoids wasting too much time formatting more
+                 decimal places on the first try. */
+              int result = format_and_round (dst, number, fp, fp->d + 2);
+              if (result >= 0)
+                return result;
+
+              /* 2 extra decimal places weren't enough to
+                 correctly round.  Try again with the maximum
+                 number of places. */
+              return format_and_round (dst, number, fp, LDBL_DIG + 1);
+            }
+        }
+      else 
+        {
+          /* The value is too big to fit in the field. */
+          return false;
+        }
+    }
+  else
+    return convert_infinite (dst, fp, number);
+}
 
-  /* The number of digits in floor(number), including sign.  This
-     is `i' from Knuth. */
-  int n_int = (40 + 1) / 2;
+/* Tries to compose NUMBER into DST in format FP by first
+   formatting it with DECIMALS decimal places, then rounding off
+   to as many decimal places will fit or the number specified in
+   FP, whichever is fewer.
 
-  /* Used to step through delta[].  This is `j' from Knuth. */
-  int j = 2;
+   Returns 1 if conversion succeeds, 0 if this try at conversion
+   failed and so will any other tries (because the integer part
+   of the number is too long), or -1 if this try failed but
+   another with higher DECIMALS might succeed (because we'd be
+   able to properly round). */
+static int
+format_and_round (char *dst, double number, const struct fmt_spec *fp,
+                  int decimals)
+{
+  /* Number of characters before the decimal point,
+     which includes digits and possibly a minus sign. */
+  int predot_chars;
 
-  /* Magnitude of number.  This is `K' from Knuth. */
-  double mag;
+  /* Number of digits in the output fraction,
+     which may be smaller than fp->d if there's not enough room. */
+  int fraction_digits;
 
-  /* Number of characters for the fractional part, including the
-     decimal point. */
-  int n_dec;
+  /* Points to last digit that will remain in the fraction after
+     rounding. */
+  char *final_frac_dig;
 
-  /* Pointer into buf used for formatting. */
-  char *cp;
+  /* Round up? */
+  bool round_up;
+  
+  char buf[128];
+  
+  assert (decimals > fp->d);
+  if (decimals > LDBL_DIG)
+    decimals = LDBL_DIG + 1;
 
-  /* Used to count characters formatted by nsprintf(). */
-  int n;
+  sprintf (buf, "%.*f", decimals, number);
 
-  /* Temporary buffer. */
-  char buf[128];
+  if (!memcmp (buf, "0.", 2))
+    memmove (buf, buf + 1, strlen (buf));
+  else if (!memcmp (buf, "-0.", 3))
+    memmove (buf + 1, buf + 2, strlen (buf + 1));
 
-  /* First check for infinities and NaNs.  12/13/96. */
-  if (!finite (number))
+  predot_chars = strcspn (buf, ".");
+  if (predot_chars > fp->w) 
     {
-      n = nsprintf (buf, "%f", number);
-      if (n > fp->w)
-       memset (buf, '*', fp->w);
-      else if (n < fp->w)
-       {
-         memmove (&buf[fp->w - n], buf, n);
-         memset (buf, ' ', fp->w - n);
-       }
+      /* Can't possibly fit. */
+      return 0; 
+    }
+  else if (predot_chars == fp->w)
+    {
+      /* Exact fit for integer part and sign. */
       memcpy (dst, buf, fp->w);
       return 1;
     }
+  else if (predot_chars + 1 == fp->w) 
+    {
+      /* There's room for the decimal point, but not for any
+         digits of the fraction.
+         Right-justify the integer part and sign. */
+      dst[0] = ' ';
+      memcpy (dst + 1, buf, fp->w);
+      return 1;
+    }
 
-  /* Then check for radically out-of-range values. */
-  mag = fabs (number);
-  if (mag >= power10[fp->w])
-    return 0;
+  /* It looks like we have room for at least one digit of the
+     fraction.  Figure out how many. */
+  fraction_digits = fp->w - predot_chars - 1;
+  if (fraction_digits > fp->d)
+    fraction_digits = fp->d;
+  final_frac_dig = buf + predot_chars + fraction_digits;
 
-  if (mag < 1.0)
+  /* Decide rounding direction and truncate string. */
+  if (final_frac_dig[1] == '5'
+      && strspn (final_frac_dig + 2, "0") == strlen (final_frac_dig + 2)) 
     {
-      n_int = 0;
-
-      /* Avoid printing `-.000'. 7/6/96. */
-      if (mag < EPSILON)
-       number = 0.0;
+      /* Exactly 1/2. */
+      if (decimals <= LDBL_DIG)
+        {
+          /* Don't have enough fractional digits to know which way to
+             round.  We can format with more decimal places, so go
+             around again. */
+          return -1;
+        }
+      else 
+        {
+          /* We used up all our fractional digits and still don't
+             know.  Round to even. */
+          round_up = (final_frac_dig[0] - '0') % 2 != 0;
+        }
     }
   else
-    /* Now perform a `uniform binary search' based on the tables
-       power10[] and delta[].  After this step, nint is the number of
-       digits in floor(number), including any sign.  */
-    for (;;)
-      {
-       if (mag >= power10[n_int])
-         {
-           assert (delta[j]);
-           n_int += delta[j++];
-         }
-       else if (mag < power10[n_int - 1])
-         {
-           assert (delta[j]);
-           n_int -= delta[j++];
-         }
-       else
-         break;
-      }
-
-  /* If we have any decimal places, then there is a decimal point,
-     too. */
-  n_dec = fp->d;
-  if (n_dec)
-    n_dec++;
+    round_up = final_frac_dig[1] >= '5';
+  final_frac_dig[1] = '\0';
 
-  /* 1/10/96: If there aren't any digits at all, add one.  This occurs
-     only when fabs(number) < 1.0. */
-  if (n_int + n_dec == 0)
-    n_int++;
+  /* Do rounding. */
+  if (round_up) 
+    {
+      char *cp = final_frac_dig;
+      for (;;) 
+        {
+          if (*cp >= '0' && *cp <= '8')
+            {
+              (*cp)++;
+              break; 
+            }
+          else if (*cp == '9') 
+            *cp = '0';
+          else
+            assert (*cp == '.');
+
+          if (cp == buf || *--cp == '-')
+            {
+              size_t length;
+              
+              /* Tried to go past the leftmost digit.  Insert a 1. */
+              memmove (cp + 1, cp, strlen (cp) + 1);
+              *cp = '1';
+
+              length = strlen (buf);
+              if (length > fp->w) 
+                {
+                  /* Inserting the `1' overflowed our space.
+                     Drop a decimal place. */
+                  buf[--length] = '\0';
+
+                  /* If that was the last decimal place, drop the
+                     decimal point too. */
+                  if (buf[length - 1] == '.')
+                    buf[length - 1] = '\0';
+                }
+              
+              break;
+            }
+        }
+    }
 
-  /* Give space for a minus sign.  Moved 1/10/96. */
-  if (number < 0)
-    n_int++;
+  buf_copy_str_lpad (dst, fp->w, buf);
+  return 1;
+}
 
-  /* Normally we only go through the loop once; occasionally twice.
-     Three times or more indicates a very serious bug somewhere. */
-  for (;;)
+/* Formats non-finite NUMBER into DST according to the width
+   given in FP. */
+static int
+convert_infinite (char *dst, const struct fmt_spec *fp, double number)
+{
+  assert (!finite (number));
+  
+  if (fp->w >= 3)
     {
-      /* Check out the total length of the string. */
-      cp = buf;
-      if (n_int + n_dec > fp->w)
-       {
-         /* The string is too long.  Let's see what can be done. */
-         if (n_int <= fp->w)
-           /* If we can, just reduce the number of decimal places. */
-           n_dec = fp->w - n_int;
-         else
-           return 0;
-       }
-      else if (n_int + n_dec < fp->w)
-       {
-         /* The string is too short.  Left-pad with spaces. */
-         int n_spaces = fp->w - n_int - n_dec;
-         memset (cp, ' ', n_spaces);
-         cp += n_spaces;
-       }
+      const char *s;
 
-      /* Finally, format the number. */
-      if (n_dec)
-       n = nsprintf (cp, "%.*f", n_dec - 1, number);
+      if (isnan (number))
+        s = "NaN";
+      else if (isinf (number))
+        s = number > 0 ? "+Infinity" : "-Infinity";
       else
-       n = nsprintf (cp, "%.0f", number);
+        s = "Unknown";
 
-      /* If number is positive and its magnitude is less than
-         1...  */
-      if (n_int == 0)
-       {
-         if (*cp == '0')
-           {
-             /* The value rounds to `.###'. */
-             memmove (cp, &cp[1], n - 1);
-             n--;
-           }
-         else
-           {
-             /* The value rounds to `1.###'. */
-             n_int = 1;
-             continue;
-           }
-       }
-      /* Else if number is negative and its magnitude is less
-         than 1...  */
-      else if (number < 0 && n_int == 1)
-       {
-         if (cp[1] == '0')
-           {
-             /* The value rounds to `-.###'. */
-             memmove (&cp[1], &cp[2], n - 2);
-             n--;
-           }
-         else
-           {
-             /* The value rounds to `-1.###'. */
-             n_int = 2;
-             continue;
-           }
-       }
-
-      /* Check for a correct number of digits & decimal places & stuff.
-         This is just a desperation check.  Hopefully it won't fail too
-         often, because then we have to run through the whole loop again:
-         sprintf() is not a fast operation with floating-points! */
-      if (n == n_int + n_dec)
-       {
-         /* Convert periods `.' to commas `,' for our foreign friends. */
-         if ((get_decimal() == ',' && fp->type != FMT_DOT)
-             || (get_decimal() == '.' && fp->type == FMT_DOT))
-           {
-             cp = strchr (cp, '.');
-             if (cp)
-               *cp = ',';
-           }
-
-         memcpy (dst, buf, fp->w);
-         return 1;
-       }
-
-      n_int = n - n_dec; /* FIXME?  Need an idiot check on resulting n_int? */
+      buf_copy_str_lpad (dst, fp->w, s);
     }
+  else 
+    memset (dst, '*', fp->w);
+
+  return true;
 }
index 57782c579a17249340cfd870db75d16bd64c6cd6..ba33b263ea51e609116b13548d1bf0c3e0674257 100644 (file)
@@ -482,7 +482,7 @@ generate_z_varname (struct dsc_proc *dsc, char *z_name,
 
   /* Try a name based on the original variable name. */
   name[0] = 'Z';
-  st_trim_copy (name + 1, var_name, sizeof name - 1);
+  str_copy_trunc (name + 1, sizeof name - 1, var_name);
   if (try_name (dsc, name))
     {
       strcpy (z_name, name);
index d4ff2256e541dbfcf0738b094a2538e7c2e7ce18..0fd59e1172113cd1f8754b82c3b08a48d5072943 100644 (file)
@@ -268,7 +268,7 @@ dict_create_var (struct dictionary *d, const char *name, int width)
 
   /* Allocate and initialize variable. */
   v = xmalloc (sizeof *v);
-  st_trim_copy (v->name, name, sizeof v->name);
+  str_copy_trunc (v->name, sizeof v->name, name);
   v->type = width == 0 ? NUMERIC : ALPHA;
   v->width = width;
   v->fv = d->next_value_idx;
@@ -395,7 +395,7 @@ dict_lookup_var (const struct dictionary *d, const char *name)
   assert (d != NULL);
   assert (name != NULL);
 
-  st_trim_copy (v.name, name, sizeof v.name);
+  str_copy_trunc (v.name, sizeof v.name, name);
   return hsh_find (d->name_tab, &v);
 }
 
@@ -569,7 +569,7 @@ dict_rename_var (struct dictionary *d, struct variable *v,
           || dict_lookup_var (d, new_name) == NULL);
 
   hsh_force_delete (d->name_tab, v);
-  st_trim_copy (v->name, new_name, sizeof v->name);
+  str_copy_trunc (v->name, sizeof v->name, new_name);
   hsh_force_insert (d->name_tab, v);
 
   if (get_algorithm () == ENHANCED)
@@ -970,7 +970,7 @@ dict_create_vector (struct dictionary *d,
   d->vector = xrealloc (d->vector, (d->vector_cnt + 1) * sizeof *d->vector);
   vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);
   vector->idx = d->vector_cnt++;
-  st_trim_copy (vector->name, name, sizeof vector->name);
+  str_copy_trunc (vector->name, sizeof vector->name, name);
   vector->var = xmalloc (cnt * sizeof *var);
   for (i = 0; i < cnt; i++)
     {
index b7f665d49bc461ff2366700516fd43e88315d415..1607681604357b075e92ff2397ed99ca24c95f26 100644 (file)
@@ -102,7 +102,7 @@ expr_evaluate_str (struct expression *e, const struct ccase *c, int case_idx,
   assert (e->type == OP_string);
   assert ((dst == NULL) == (dst_size == 0));
   expr_evaluate (e, c, case_idx, &s);
-  st_bare_pad_len_copy (dst, s.string, dst_size, s.length);
+  buf_copy_rpad (dst, dst_size, s.string, s.length);
 }
 \f
 #include "lexer.h"
index 15efe00bed59f56a8bddeeee0b3ef6fe374fb8cd..a7064e034c8728b05e3b1264367e7a8075379fe0 100644 (file)
@@ -881,14 +881,14 @@ word_matches (const char **test, const char **name)
   size_t name_len = strcspn (*name, ".");
   if (test_len == name_len) 
     {
-      if (mm_case_compare (*test, *name, test_len))
+      if (buf_compare_case (*test, *name, test_len))
         return false;
     }
   else if (test_len < 3 || test_len > name_len)
     return false;
   else 
     {
-      if (mm_case_compare (*test, *name, test_len))
+      if (buf_compare_case (*test, *name, test_len))
         return false;
     }
 
index 688fbb89b509b1af790611cb52853525d5ba9fcd..3f09d1946fecd87ddb6b8daefebbc044d7a49d2b 100644 (file)
@@ -116,7 +116,7 @@ cmd_file_handle (void)
 
   if (!lex_force_id ())
     return CMD_FAILURE;
-  st_trim_copy (handle_name, tokid, sizeof handle_name);
+  str_copy_trunc (handle_name, sizeof handle_name, tokid);
 
   handle = get_handle_with_name (handle_name);
   if (handle != NULL)
index 6a706eec5c2d5a01412d007773450796e858f459..b90ae1840dbc1b7a462086ea85fcdb4ee76c5326 100644 (file)
@@ -450,8 +450,8 @@ cmd_record_type (void)
              if (!lex_force_string ())
                goto error;
              rct->v[rct->nv].c = xmalloc (fty->record.nc + 1);
-             st_bare_pad_copy (rct->v[rct->nv].c, ds_c_str (&tokstr),
-                               fty->record.nc + 1);
+             buf_copy_str_rpad (rct->v[rct->nv].c, fty->record.nc + 1,
+                                 ds_c_str (&tokstr));
            }
          else
            {
index 4db36adebe27c1bf11928cc812a81d6333812d5b..3b25b99c9e768452916412083f05b65643fc5c86 100644 (file)
@@ -502,7 +502,7 @@ fn_dirname (const char *filename)
   if (len == 1 && filename[0] == '/')
     p = filename + 1;
   else if (len && filename[len - 1] == DIR_SEPARATOR)
-    p = mm_find_reverse (filename, len - 1, filename + len - 1, 1);
+    p = buf_find_reverse (filename, len - 1, filename + len - 1, 1);
   else
     p = strrchr (filename, DIR_SEPARATOR);
   if (p == NULL)
index 73e1e7cb1140fcc45628c3e3c1a47d23d4dd484d..b352f1b23301f4689e449fe61ed1cb9cde1c081e 100644 (file)
@@ -204,7 +204,7 @@ make_new_var (char name[])
           *cp = '_'; 
       }
   *cp = '\0';
-  st_uppercase (name);
+  str_uppercase (name);
   
   if (dict_create_var (default_dict, name, 0))
     return 1;
@@ -290,7 +290,8 @@ flip_sink_create (struct flip_pgm *flip)
 
   /* Write variable names as first case. */
   for (i = 0; i < flip->var_cnt; i++) 
-    st_bare_pad_copy (info->output_buf[i].s, flip->var[i]->name, MAX_SHORT_STRING);
+    buf_copy_str_rpad (info->output_buf[i].s, MAX_SHORT_STRING,
+                       flip->var[i]->name);
   if (fwrite (info->output_buf, sizeof *info->output_buf,
               flip->var_cnt, flip->file) != (size_t) flip->var_cnt)
     msg (FE, _("Error writing FLIP file: %s."), strerror (errno));
@@ -328,7 +329,7 @@ flip_sink_write (struct case_sink *sink, const struct ccase *c)
             {
               char name[INT_DIGITS + 2];
               sprintf (name, "V%d", (int) f);
-              st_trim_copy (v->name, name, sizeof v->name);
+              str_copy_trunc (v->name, sizeof v->name, name);
             }
         }
       else
index 9c6bbea48e77bfd0163384b289fe37c1219ac672..87be7b08430bfffddbc6ddbbcdd537927604fdfe 100644 (file)
@@ -59,7 +59,7 @@ parse_format_specifier_name (const char **cp, enum fmt_parse_flags flags)
       /* Find format. */
       for (idx = 0; idx < FMT_NUMBER_OF_FORMATS; idx++)
         if (strlen (formats[idx].name) == ep - sp
-            && !mm_case_compare (formats[idx].name, sp, ep - sp))
+            && !buf_compare_case (formats[idx].name, sp, ep - sp))
           break;
 
       /* Check format. */
index 4b8d0c9b0004b0ffaf7eb9692219307354ddd4c1..e6f1725ba9d4168adeea8f6c4375991d61936862 100644 (file)
@@ -26,8 +26,8 @@ DEFFMT (FMT_DOT,        "DOT",       2,  1,  40,  1,   40, 0001, FMT_DOT, 32)
 DEFFMT (FMT_DOLLAR,      "DOLLAR",    2,  1,  40,  2,   40, 0001, FMT_DOLLAR, 4)
 DEFFMT (FMT_PCT,         "PCT",       2,  1,  40,  2,   40, 0001, FMT_PCT, 31)
 DEFFMT (FMT_Z,           "Z",         2,  1,  40,  1,   40, 0011, FMT_F, 15)
-DEFFMT (FMT_A,           "A",         1,  1, 255,  1,  254, 0004, FMT_A, 1)
-DEFFMT (FMT_AHEX,        "AHEX",      1,  2, 254,  2,  510, 0006, FMT_A, 2)
+DEFFMT (FMT_A,           "A",         1,  1, 255,  1,  255, 0004, FMT_A, 1)
+DEFFMT (FMT_AHEX,        "AHEX",      1,  2, 510,  2,  510, 0006, FMT_A, 2)
 DEFFMT (FMT_IB,                  "IB",        2,  1,   8,  1,    8, 0010, FMT_F, 6)
 DEFFMT (FMT_P,           "P",         2,  1,  16,  1,   16, 0011, FMT_F, 8)
 DEFFMT (FMT_PIB,         "PIB",       2,  1,   8,  1,    8, 0010, FMT_F, 9)
index 53b702c4e8bb1ba851d4f767ef463b55d7d71ba1..ff93e0d9f42f9aa27520e4434f50377de7a8145e 100644 (file)
@@ -116,7 +116,7 @@ restore_token (void)
   assert (put_token != 0);
   token = put_token;
   ds_replace (&tokstr, ds_c_str (&put_tokstr));
-  st_trim_copy (tokid, ds_c_str (&tokstr), sizeof tokid);
+  str_copy_trunc (tokid, sizeof tokid, ds_c_str (&tokstr));
   tokval = put_tokval;
   put_token = 0;
 }
@@ -358,7 +358,7 @@ lex_get (void)
            ds_putc (&tokstr, *prog++);
 
          /* Copy tokstr to tokid, possibly truncating it.*/
-         st_trim_copy (tokid, ds_c_str (&tokstr), sizeof tokid);
+         str_copy_trunc (tokid, sizeof tokid, ds_c_str (&tokstr));
 
           /* Determine token type. */
          token = lex_id_to_token (ds_c_str (&tokstr), ds_length (&tokstr));
@@ -720,7 +720,7 @@ lex_put_back_id (const char *id)
   save_token ();
   token = T_ID;
   ds_replace (&tokstr, id);
-  st_trim_copy (tokid, ds_c_str (&tokstr), sizeof tokid);
+  str_copy_trunc (tokid, sizeof tokid, ds_c_str (&tokstr));
 }
 \f
 /* Weird line processing functions. */
index 73d473d177c2f90f8597f2fa73896a5cdf2695f3..776dfa5b1c5908bfe21d8fd21583e83f23d01039 100644 (file)
@@ -1347,8 +1347,8 @@ dump_cell_content (struct matrix_data_pgm *mx, int content, double *cp,
   int type = content_type[content];
 
   {
-    st_bare_pad_copy (case_data_rw (c, mx->rowtype_->fv)->s,
-                     content_names[content], 8);
+    buf_copy_str_rpad (case_data_rw (c, mx->rowtype_->fv)->s, 8,
+                       content_names[content]);
     
     if (type != 1)
       memset (case_data_rw (c, mx->varname_->fv)->s, ' ', 8);
@@ -1369,10 +1369,9 @@ dump_cell_content (struct matrix_data_pgm *mx, int content, double *cp,
            cp++;
          }
        if (type == 1)
-         st_bare_pad_copy (case_data_rw (c, mx->varname_->fv)->s,
-                            dict_get_var (default_dict,
-                                          mx->first_continuous + i)->name,
-                           8);
+         buf_copy_str_rpad (case_data_rw (c, mx->varname_->fv)->s, 8,
+                             dict_get_var (default_dict,
+                                           mx->first_continuous + i)->name);
        write_case (wc_data);
       }
   }
index 766e214063d26f72aa6ead2e98eac7158186338a..7967926e600c0cb33a99859f487b85eac1483d48 100644 (file)
@@ -448,8 +448,8 @@ read_version_data (struct pfm_reader *r, struct pfm_read_info *info)
       info->creation_time[8] = 0;
 
       /* Product. */
-      st_trim_copy (info->product, product, sizeof info->product);
-      st_trim_copy (info->subproduct, subproduct, sizeof info->subproduct);
+      str_copy_trunc (info->product, sizeof info->product, product);
+      str_copy_trunc (info->subproduct, sizeof info->subproduct, subproduct);
     }
 }
 
@@ -523,7 +523,7 @@ read_variables (struct pfm_reader *r, struct dictionary *dict)
 
       if (!var_is_valid_name (name, false) || *name == '#' || *name == '$')
         error (r, _("position %d: Invalid variable name `%s'."), name);
-      st_uppercase (name);
+      str_uppercase (name);
 
       if (width < 0 || width > 255)
        error (r, "Bad width %d for variable %s.", width, name);
@@ -605,7 +605,7 @@ parse_value (struct pfm_reader *r, struct variable *vv)
     {
       char string[256];
       read_string (r, string);
-      st_bare_pad_copy (v.s, string, 8); 
+      buf_copy_str_rpad (v.s, 8, string); 
     }
   else
     v.f = read_float (r);
@@ -699,7 +699,7 @@ pfm_read_case (struct pfm_reader *r, struct ccase *c)
         {
           char string[256];
           read_string (r, string);
-          st_bare_pad_copy (case_data_rw (c, idx)->s, string, width);
+          buf_copy_str_rpad (case_data_rw (c, idx)->s, width, string);
           idx += DIV_RND_UP (width, MAX_SHORT_STRING);
         }
     }
index a8574c9919199e7dcb79be27edf09cbffd139fd1..90792afa4197d5a204423b312847e3c2d4d51127 100644 (file)
@@ -378,7 +378,7 @@ cmd_recode (void)
                    /* The NULL is only really necessary for the
                       debugging code. */
                    char *repl = xmalloc (max_dst_width + 1);
-                   st_pad_copy (repl, cp->t.c, max_dst_width + 1);
+                   str_copy_rpad (repl, max_dst_width + 1, cp->t.c);
                    free (cp->t.c);
                    cp->t.c = repl;
                  }
@@ -463,7 +463,7 @@ parse_dest_spec (struct rcd_var * rcd, union value * v, size_t *max_dst_width)
       if (toklen > max)
        max = toklen;
       v->c = xmalloc (max + 1);
-      st_pad_copy (v->c, ds_c_str (&tokstr), max + 1);
+      str_copy_rpad (v->c, max + 1, ds_c_str (&tokstr));
       flags = RCD_DEST_STRING;
       *max_dst_width = max;
       lex_get ();
@@ -626,7 +626,7 @@ parse_src_spec (struct rcd_var * rcd, int type, size_t max_src_width)
              if (!lex_force_string ())
                return 0;
              c->f1.c = xmalloc (max_src_width + 1);
-             st_pad_copy (c->f1.c, ds_c_str (&tokstr), max_src_width + 1);
+             str_copy_rpad (c->f1.c, max_src_width + 1, ds_c_str (&tokstr));
              lex_get ();
            }
        }
@@ -811,9 +811,9 @@ recode_trns_proc (struct trns_header * t, struct ccase * c,
          if (val == NULL) 
             {
               if (v->dest->fv != v->src->fv)
-                st_bare_pad_len_copy (case_data_rw (c, v->dest->fv)->s,
-                                      case_str (c, v->src->fv),
-                                      v->dest->width, v->src->width); 
+                buf_copy_rpad (case_data_rw (c, v->dest->fv)->s,
+                               v->dest->width,
+                               case_str (c, v->src->fv), v->src->width); 
             }
          else
            memcpy (case_data_rw (c, v->dest->fv)->s, cp->t.c, v->dest->width);
index 0c8ebf01d110ef5034135d95eaa8d3d72cb91eea..99dd47bdfa65c25c20ad2231518f76e119795d30 100644 (file)
@@ -333,7 +333,7 @@ write_header (struct sfm_writer *w, const struct dictionary *d)
     if (label == NULL)
       label = "";
 
-    st_bare_pad_copy (hdr.file_label, label, sizeof hdr.file_label); 
+    buf_copy_str_rpad (hdr.file_label, sizeof hdr.file_label, label); 
   }
   
   memset (hdr.padding, 0, sizeof hdr.padding);
@@ -418,7 +418,7 @@ write_variable (struct sfm_writer *w, struct variable *v)
   sv.n_missing_values = nm;
   write_format_spec (&v->print, &sv.print);
   write_format_spec (&v->write, &sv.write);
-  st_bare_pad_copy (sv.name, v->short_name, sizeof sv.name);
+  buf_copy_str_rpad (sv.name, sizeof sv.name, v->short_name);
   if (!buf_write (w, &sv, sizeof sv))
     return 0;
 
index 0ad0e2f5899647d7b923afd1fe59e9d7f8ec6bef..2a766520b135f8d01b01b7ca0a638c589fe459de 100644 (file)
--- a/src/str.c
+++ b/src/str.c
@@ -77,7 +77,7 @@ nvsprintf (char *buf, const char *format, va_list args)
 /* Reverses the order of NBYTES bytes at address P, thus converting
    between little- and big-endian byte orders.  */
 void
-mm_reverse (void *p, size_t nbytes)
+buf_reverse (char *p, size_t nbytes)
 {
   unsigned char *h = p, *t = &h[nbytes - 1];
   unsigned char temp;
@@ -94,7 +94,7 @@ mm_reverse (void *p, size_t nbytes)
 /* Finds the last NEEDLE of length NEEDLE_LEN in a HAYSTACK of length
    HAYSTACK_LEN.  Returns a pointer to the needle found. */
 char *
-mm_find_reverse (const char *haystack, size_t haystack_len,
+buf_find_reverse (const char *haystack, size_t haystack_len,
                  const char *needle, size_t needle_len)
 {
   int i;
@@ -107,10 +107,10 @@ mm_find_reverse (const char *haystack, size_t haystack_len,
 /* Compares the SIZE bytes in A to those in B, disregarding case,
    and returns a strcmp()-type result. */
 int
-mm_case_compare (const void *a_, const void *b_, size_t size)
+buf_compare_case (const char *a_, const char *b_, size_t size)
 {
-  const unsigned char *a = a_;
-  const unsigned char *b = b_;
+  const unsigned char *a = (unsigned char *) a_;
+  const unsigned char *b = (unsigned char *) b_;
 
   while (size-- > 0) 
     {
@@ -128,7 +128,7 @@ mm_case_compare (const void *a_, const void *b_, size_t size)
    string is considered to be padded with spaces to the length of
    the longer. */
 int
-st_compare_pad (const char *a, size_t a_len, const char *b, size_t b_len)
+buf_compare_rpad (const char *a, size_t a_len, const char *b, size_t b_len)
 {
   size_t min_len;
   int result;
@@ -157,84 +157,101 @@ st_compare_pad (const char *a, size_t a_len, const char *b, size_t b_len)
     }
 }
 
-/* Copies SRC to DEST, truncating to N characters or right-padding
-   with spaces to N characters as necessary.  Does not append a null
-   character.  SRC must be null-terminated. */
-void
-st_bare_pad_copy (char *dest, const char *src, size_t n)
+/* Compares strin A to string B.  The shorter string is
+   considered to be padded with spaces to the length of the
+   longer. */
+int
+str_compare_rpad (const char *a, const char *b)
 {
-  size_t len;
+  return buf_compare_rpad (a, strlen (a), b, strlen (b));
+}
 
-  len = strlen (src);
-  if (len >= n)
-    memcpy (dest, src, n);
+/* Copies string SRC to buffer DST, of size DST_SIZE bytes.
+   DST is truncated to DST_SIZE bytes or padded on the right with
+   spaces as needed. */
+void
+buf_copy_str_rpad (char *dst, size_t dst_size, const char *src)
+{
+  size_t src_len = strlen (src);
+  if (src_len >= dst_size)
+    memcpy (dst, src, dst_size);
   else
     {
-      memcpy (dest, src, len);
-      memset (&dest[len], ' ', n - len);
+      memcpy (dst, src, src_len);
+      memset (&dst[src_len], ' ', dst_size - src_len);
     }
 }
 
-/* Copies SRC to DEST, truncating SRC to N characters or right-padding
-   with spaces to N characters if necessary.  Does not append a null
-   character.  SRC must be LEN characters long but does not need to be
-   null-terminated. */
+/* Copies string SRC to buffer DST, of size DST_SIZE bytes.
+   DST is truncated to DST_SIZE bytes or padded on the left with
+   spaces as needed. */
 void
-st_bare_pad_len_copy (char *dest, const char *src, size_t n, size_t len)
+buf_copy_str_lpad (char *dst, size_t dst_size, const char *src)
 {
-  if (len >= n)
-    memmove (dest, src, n);
+  size_t src_len = strlen (src);
+  if (src_len >= dst_size)
+    memcpy (dst, src, dst_size);
   else
     {
-      memmove (dest, src, len);
-      memset (&dest[len], ' ', n - len);
+      size_t pad_cnt = dst_size - src_len;
+      memset (&dst[0], ' ', pad_cnt);
+      memcpy (dst + pad_cnt, src, src_len);
     }
 }
 
-/* Copies SRC to DEST, truncating SRC to N-1 characters or
-   right-padding with spaces to N-1 characters if necessary.  Always
-   appends a null character. */
+/* Copies buffer SRC, of SRC_SIZE bytes, to DST, of DST_SIZE bytes.
+   DST is truncated to DST_SIZE bytes or padded on the right with
+   spaces as needed. */
 void
-st_pad_copy (char *dest, const char *src, size_t n)
+buf_copy_rpad (char *dst, size_t dst_size,
+               const char *src, size_t src_size)
 {
-  size_t len;
-
-  len = strlen (src);
-  if (len == n - 1)
-    strcpy (dest, src);
-  else if (len < n - 1)
+  if (src_size >= dst_size)
+    memmove (dst, src, dst_size);
+  else
     {
-      memcpy (dest, src, len);
-      memset (&dest[len], ' ', n - 1 - len);
-      dest[n - 1] = 0;
+      memmove (dst, src, src_size);
+      memset (&dst[src_size], ' ', dst_size - src_size);
     }
-  else
+}
+
+/* Copies string SRC to string DST, which is in a buffer DST_SIZE
+   bytes long.
+   Truncates DST to DST_SIZE - 1 characters or right-pads with
+   spaces to DST_SIZE - 1 characters if necessary. */
+void
+str_copy_rpad (char *dst, size_t dst_size, const char *src)
+{
+  size_t src_len = strlen (src);
+  if (src_len < dst_size - 1)
     {
-      memcpy (dest, src, n - 1);
-      dest[n - 1] = 0;
+      memcpy (dst, src, src_len);
+      memset (&dst[src_len], ' ', dst_size - 1 - src_len);
     }
+  else
+    memcpy (dst, src, dst_size - 1);
+  dst[dst_size - 1] = 0;
 }
 
-/* Copies SRC to DST, truncating DST to N-1 characters if
-   necessary.  Always appends a null character. */
+/* Copies SRC to DST, which is in a buffer DST_SIZE bytes long.
+   Truncates DST to DST_SIZE - 1 characters, if necessary. */
 void
-st_trim_copy (char *dst, const char *src, size_t n
+str_copy_trunc (char *dst, size_t dst_size, const char *src
 {
-  size_t len = strlen (src);
-  assert (n > 0);
-  if (len + 1 < n)
-    memcpy (dst, src, len + 1);
+  size_t src_len = strlen (src);
+  assert (dst_size > 0);
+  if (src_len + 1 < dst_size)
+    memcpy (dst, src, src_len + 1);
   else 
     {
-      memcpy (dst, src, n - 1);
-      dst[n - 1] = '\0';
+      memcpy (dst, src, dst_size - 1);
+      dst[dst_size - 1] = '\0';
     }
 }
 
-
 /* Converts each character in S to uppercase. */
 void
-st_uppercase (char *s) 
+str_uppercase (char *s) 
 {
   for (; *s != '\0'; s++)
     *s = toupper ((unsigned char) *s);
index c53b2f4659c37f016ff50bdf8f434c902e2d6c17..7816acf2ec78fb4ba290f3d42b2230b10ae4d373 100644 (file)
--- a/src/str.h
+++ b/src/str.h
@@ -118,17 +118,18 @@ long getdelim (char **lineptr, size_t * n, int delimiter, FILE * stream);
 \f
 /* Miscellaneous. */
 
-void mm_reverse (void *, size_t);
-char *mm_find_reverse (const char *, size_t, const char *, size_t);
-int mm_case_compare (const void *, const void *, size_t);
-
-int st_compare_pad (const char *, size_t, const char *, size_t);
-char *st_spaces (int);
-void st_bare_pad_copy (char *dest, const char *src, size_t n);
-void st_bare_pad_len_copy (char *dest, const char *src, size_t n, size_t len);
-void st_pad_copy (char *dest, const char *src, size_t n);
-void st_trim_copy (char *dest, const char *src, size_t n);
-void st_uppercase (char *);
+void buf_reverse (char *, size_t);
+char *buf_find_reverse (const char *, size_t, const char *, size_t);
+int buf_compare_case (const char *, const char *, size_t);
+int buf_compare_rpad (const char *, size_t, const char *, size_t);
+void buf_copy_rpad (char *, size_t, const char *, size_t);
+void buf_copy_str_lpad (char *, size_t, const char *);
+void buf_copy_str_rpad (char *, size_t, const char *);
+
+int str_compare_rpad (const char *, const char *);
+void str_copy_rpad (char *, size_t, const char *);
+void str_copy_trunc (char *, size_t, const char *);
+void str_uppercase (char *);
 \f
 /* Fixed-length strings. */
 struct fixed_string 
index e403841d253bb2c5b0cd351b4af5132b4f653e91..e8d95bf0e58a26c7cc02c578428f9bc4d01cb60f 100644 (file)
@@ -117,7 +117,7 @@ add_document_line (const char *line, int indent)
 
   memcpy (new_documents, old_documents, old_len);
   memset (new_documents + old_len, ' ', indent);
-  st_bare_pad_copy (new_documents + old_len + indent, line, 80 - indent);
+  buf_copy_str_rpad (new_documents + old_len + indent, 80 - indent, line);
   new_documents[old_len + 80] = '\0';
 
   dict_set_documents (default_dict, new_documents);
index 2fa02e646e06d413b41875cd9ccc207f0fdd2ba5..3dc4254f6d1c74ad89d37a623578c8244f17b152 100644 (file)
@@ -154,7 +154,7 @@ get_label (struct variable **vars, int var_cnt)
               lex_error (_("expecting string"));
              return 0;
            }
-         st_bare_pad_copy (value.s, ds_c_str (&tokstr), MAX_SHORT_STRING);
+         buf_copy_str_rpad (value.s, MAX_SHORT_STRING, ds_c_str (&tokstr));
        }
       else
        {
index a1b8276fcb2987fa064a89a8e1c60d0320a6a61c..356f51a46afef3843b8311ddb29e24e005c96a43 100644 (file)
@@ -346,8 +346,8 @@ var_set_short_name (struct variable *v, const char *short_name)
   assert (v != NULL);
   assert (short_name[0] == '\0' || var_is_valid_name (short_name, false));
   
-  st_trim_copy (v->short_name, short_name, sizeof v->short_name);
-  st_uppercase (v->short_name);
+  str_copy_trunc (v->short_name, sizeof v->short_name, short_name);
+  str_uppercase (v->short_name);
 }
 
 /* Clears V's short name. */