pspp-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Pspp-cvs] Changes to pspp/src/data-in.c


From: Ben Pfaff
Subject: [Pspp-cvs] Changes to pspp/src/data-in.c
Date: Mon, 07 Mar 2005 01:25:37 -0500

Index: pspp/src/data-in.c
diff -u pspp/src/data-in.c:1.13 pspp/src/data-in.c:1.14
--- pspp/src/data-in.c:1.13     Tue Mar  1 08:16:15 2005
+++ pspp/src/data-in.c  Mon Mar  7 06:25:36 2005
@@ -81,6 +81,8 @@
   vdls_error (i, format, args);
   va_end (args);
 }
+
+/* Parsing utility functions. */
 
 /* Excludes leading and trailing whitespace from I by adjusting
    pointers. */
@@ -101,6 +103,15 @@
 {
   return i->s < i->e;
 }
+
+/* If implied decimal places are enabled, apply them to
+   I->v->f. */
+static void
+apply_implied_decimals (struct data_in *i) 
+{
+  if ((i->flags & DI_IMPLIED_DECIMALS) && i->format.d > 0)
+    i->v->f /= pow (10., i->format.d);
+}
 
 /* Format parsers. */ 
 
@@ -110,7 +121,7 @@
 static int
 parse_numeric (struct data_in *i)
 {
-  short int sign;              /* +1 or -1. */
+  int sign;                     /* +1 or -1. */
   double num;                  /* The number so far.  */
 
   int got_dot;                 /* Found a decimal point.  */
@@ -196,7 +207,9 @@
          i->v->f = SYSMIS;
          return 1;
        }
-      goto noconv;
+      dls_error (i, _("Field does not form a valid floating-point constant."));
+      i->v->f = SYSMIS;
+      return 0;
     }
   
   if (have_char (i)
@@ -209,11 +222,14 @@
       if (isalpha (*i->s))
        i->s++;
       if (!parse_int (i, &exp))
-       goto noconv;
+        {
+          i->v->f = SYSMIS;
+          return 0;
+        }
 
       exponent += exp;
     }
-  else if (!got_dot)
+  else if (!got_dot && (i->flags & DI_IMPLIED_DECIMALS))
     exponent -= i->format.d;
 
   if (type == FMT_PCT && have_char (i) && *i->s == '%')
@@ -233,41 +249,32 @@
 
   /* Multiply NUM by 10 to the EXPONENT power, checking for overflow
      and underflow.  */
-
   if (exponent < 0)
     {
       if (-exponent + got_digit > -(DBL_MIN_10_EXP) + 5
-         || num < DBL_MIN * pow (10.0, (double) -exponent))
-       goto underflow;
+         || num < DBL_MIN * pow (10.0, (double) -exponent)) 
+        {
+          dls_error (i, _("Underflow in floating-point constant."));
+          i->v->f = 0.0;
+          return 0;
+        }
+
       num *= pow (10.0, (double) exponent);
     }
   else if (exponent > 0)
     {
       if (num > DBL_MAX * pow (10.0, (double) -exponent))
-       goto overflow;
+        {
+          dls_error (i, _("Overflow in floating-point constant."));
+          i->v->f = SYSMIS;
+          return 0;
+        }
+      
       num *= pow (10.0, (double) exponent);
     }
 
-  i->v->f = sign * num;
+  i->v->f = sign > 0 ? num : -num;
   return 1;
-
-overflow:
-  /* Return an overflow error.  */
-  dls_error (i, _("Overflow in floating-point constant."));
-  i->v->f = SYSMIS;
-  return 0;
-
-underflow:
-  /* Return an underflow error.  */
-  dls_error (i, _("Underflow in floating-point constant."));
-  i->v->f = 0.0;
-  return 0;
-
-noconv:
-  /* There was no number.  */
-  dls_error (i, _("Field does not form a valid floating-point constant."));
-  i->v->f = SYSMIS;
-  return 0;
 }
 
 /* Returns the integer value of hex digit C. */
@@ -298,8 +305,7 @@
       i->v->f = i->v->f * 10.0 + *cp - '0';
     }
 
-  if (i->format.d)
-    i->v->f /= pow (10.0, i->format.d);
+  apply_implied_decimals (i);
   return 1;
 }
 
@@ -374,6 +380,7 @@
 parse_Z (struct data_in *i)
 {
   char buf[64];
+  bool got_dot = false;
 
   /* Warn user that we suck. */
   {
@@ -413,8 +420,11 @@
     char *dp;
 
     for (sp = i->s, dp = buf + 1; sp < i->e - 1; sp++, dp++)
-      if (*sp == '.')
-       *dp = '.';
+      if (*sp == '.') 
+        {
+          *dp = '.';
+          got_dot = true;
+        }
       else if ((*sp & 0xf0) == 0xf0 && (*sp & 0xf) < 10)
        *dp = (*sp & 0xf) + '0';
       else
@@ -437,7 +447,10 @@
        return 0;
       }
   }
-  
+
+  if (!got_dot)
+    apply_implied_decimals (i);
+
   return 1;
 }
 
@@ -479,8 +492,7 @@
   if (p[0] & 0x80)
     i->v->f = -(i->v->f + 1.0);
 
-  if (i->format.d)
-    i->v->f /= pow (10.0, i->format.d);
+  apply_implied_decimals (i);
 
   return 1;
 }
@@ -499,8 +511,7 @@
     i->v->f = i->v->f * 256.0 + i->s[j];
 #endif
 
-  if (i->format.d)
-    i->v->f /= pow (10.0, i->format.d);
+  apply_implied_decimals (i);
 
   return 1;
 }
@@ -520,8 +531,7 @@
   if ((*cp ^ (*cp >> 1)) & 0x10)
       i->v->f = -i->v->f;
 
-  if (i->format.d)
-    i->v->f /= pow (10.0, i->format.d);
+  apply_implied_decimals (i);
 
   return 1;
 }
@@ -538,8 +548,7 @@
       i->v->f = i->v->f * 10 + (*cp & 15);
     }
 
-  if (i->format.d)
-    i->v->f /= pow (10.0, i->format.d);
+  apply_implied_decimals (i);
 
   return 1;
 }
@@ -714,89 +723,89 @@
   return 0;
 }
 
-/* Formats NUMBER as Roman numerals in ROMAN, or as Arabic numerals if
-   the Roman expansion would be too long. */
-static void
-to_roman (int number, char roman[32])
-{
-  int save_number = number;
-
-  struct roman_digit
-    {
-      int value;               /* Value corresponding to this digit. */
-      char name;               /* Digit name. */
-    };
-
-  static const struct roman_digit roman_tab[7] =
+/* Association between a name and a value. */
+struct enum_name
   {
-    {1000, 'M'},
-    {500, 'D'},
-    {100, 'C'},
-    {50, 'L'},
-    {10, 'X'},
-    {5, 'V'},
-    {1, 'I'},
+    const char *name;           /* Name. */
+    bool can_abbreviate;        /* True if name may be abbreviated. */
+    int value;                  /* Value associated with name. */
   };
 
-  char *cp = roman;
-
-  int i, j;
-
-  assert (32 >= INT_DIGITS + 1);
-  if (number == 0)
-    goto arabic;
+/* Reads a name from I and sets *OUTPUT to the value associated
+   with that name.  Returns true if successful, false otherwise. */
+static bool
+parse_enum (struct data_in *i, const char *what,
+            const struct enum_name *enum_names,
+            long *output) 
+{
+  const char *name;
+  size_t length;
+  const struct enum_name *ep;
 
-  if (number < 0)
+  /* Consume alphabetic characters. */
+  name = i->s;
+  length = 0;
+  while (have_char (i) && isalpha (*i->s)) 
     {
-      *cp++ = '-';
-      number = -number;
+      length++;
+      i->s++; 
     }
-
-  for (i = 0; i < 7; i++)
+  if (length == 0) 
     {
-      int digit = roman_tab[i].value;
-      while (number >= digit)
-       {
-         number -= digit;
-         if (cp > &roman[30])
-           goto arabic;
-         *cp++ = roman_tab[i].name;
-       }
-
-      for (j = i + 1; j < 7; j++)
-       {
-         if (i == 4 && j == 5) /* VX is not a shortened form of V. */
-           break;
-
-         digit = roman_tab[i].value - roman_tab[j].value;
-         while (number >= digit)
-           {
-             number -= digit;
-             if (cp > &roman[29])
-               goto arabic;
-             *cp++ = roman_tab[j].name;
-             *cp++ = roman_tab[i].name;
-           }
-       }
+      dls_error (i, _("Parse error at `%c' expecting %s."), *i->s, what);
+      return 0;
     }
-  *cp = 0;
-  return;
 
-arabic:
-  sprintf (roman, "%d", save_number);
-}
-
-/* Returns true if C is a (lowercase) roman numeral. */
-#define CHAR_IS_ROMAN(C)                               \
-       ((C) == 'x' || (C) == 'v' || (C) == 'i')
+  for (ep = enum_names; ep->name != NULL; ep++)
+    if ((ep->can_abbreviate
+         && lex_id_match_len (ep->name, strlen (ep->name), name, length))
+        || (!ep->can_abbreviate && length == strlen (ep->name)
+            && !memcmp (name, ep->name, length)))
+      {
+        *output = ep->value;
+        return 1;
+      }
 
-/* Returns the value of a single (lowercase) roman numeral. */
-#define ROMAN_VALUE(C)                         \
-       ((C) == 'x' ? 10 : ((C) == 'v' ? 5 : 1))
+  dls_error (i, _("Unknown %s `%.*s'."), what, (int) length, name);
+  return 0;
+}
 
 static int
 parse_month (struct data_in *i, long *month)
 {
+  static const struct enum_name month_names[] = 
+    {
+      {"january", true, 1},
+      {"february", true, 2},
+      {"march", true, 3},
+      {"april", true, 4},
+      {"may", true, 5},
+      {"june", true, 6},
+      {"july", true, 7},
+      {"august", true, 8},
+      {"september", true, 9},
+      {"october", true, 10},
+      {"november", true, 11},
+      {"december", true, 12},
+
+      {"i", false, 1},
+      {"ii", false, 2},
+      {"iii", false, 3},
+      {"iv", false, 4},
+      {"iiii", false, 4},
+      {"v", false, 5},
+      {"vi", false, 6},
+      {"vii", false, 7},
+      {"viii", false, 8},
+      {"ix", false, 9},
+      {"viiii", false, 9},
+      {"x", false, 10},
+      {"xi", false, 11},
+      {"xii", false, 12},
+
+      {NULL, false, 0},
+    };
+
   if (!force_have_char (i))
     return 0;
   
@@ -810,85 +819,8 @@
       dls_error (i, _("Month (%ld) must be between 1 and 12."), *month);
       return 0;
     }
-
-  if (CHAR_IS_ROMAN (tolower (*i->s)))
-    {
-      int last = ROMAN_VALUE (tolower (*i->s));
-
-      *month = 0;
-      for (;;)
-       {
-         int value;
-
-         i->s++;
-         if (!have_char || !CHAR_IS_ROMAN (tolower (*i->s)))
-           {
-             if (last != INT_MAX)
-               *month += last;
-             break;
-           }
-
-         value = ROMAN_VALUE (tolower (*i->s));
-         if (last == INT_MAX)
-           *month += value;
-         else if (value > last)
-           {
-             *month += value - last;
-             last = INT_MAX;
-           }
-         else
-           {
-             *month += last;
-             last = value;
-           }
-       }
-
-      if (*month < 1 || *month > 12)
-       {
-         char buf[32];
-
-         to_roman (*month, buf);
-         dls_error (i, _("Month (%s) must be between I and XII."), buf);
-         return 0;
-       }
-      
-      return 1;
-    }
-  
-  {
-    static const char *months[12] =
-      {
-       "january", "february", "march", "april", "may", "june",
-       "july", "august", "september", "october", "november", "december",
-      };
-
-    char month_buf[32];
-    char *mp;
-
-    int j;
-
-    for (mp = month_buf;
-        have_char (i) && isalpha (*i->s) && mp < &month_buf[31];
-        i->s++)
-      *mp++ = tolower (*i->s);
-    *mp = '\0';
-
-    if (have_char (i) && isalpha (*i->s))
-      {
-       dls_error (i, _("Month name (%s...) is too long."), month_buf);
-       return 0;
-      }
-
-    for (j = 0; j < 12; j++)
-      if (lex_id_match (months[j], month_buf))
-       {
-         *month = j + 1;
-         return 1;
-       }
-
-    dls_error (i, _("Bad month name (%s)."), month_buf);
-    return 0;
-  }
+  else 
+    return parse_enum (i, _("month"), month_names, month);
 }
 
 static int
@@ -1093,59 +1025,29 @@
 
      
 static int
-parse_weekday (struct data_in *i, int *weekday)
+parse_weekday (struct data_in *i, long *weekday)
 {
-  /* PORTME */
-  #define TUPLE(A,B)                           \
-         (((A) << 8) + (B))
-
-  if (i->s + 1 >= i->e)
-    {
-      dls_error (i, _("Day of the week expected in date value."));
-      return 0;
-    }
-
-  switch (TUPLE (tolower (i->s[0]), tolower (i->s[1])))
+  static const struct enum_name weekday_names[] = 
     {
-    case TUPLE ('s', 'u'):
-      *weekday = 1;
-      break;
-
-    case TUPLE ('m', 'o'):
-      *weekday = 2;
-      break;
-
-    case TUPLE ('t', 'u'):
-      *weekday = 3;
-      break;
-
-    case TUPLE ('w', 'e'):
-      *weekday = 4;
-      break;
-
-    case TUPLE ('t', 'h'):
-      *weekday = 5;
-      break;
-
-    case TUPLE ('f', 'r'):
-      *weekday = 6;
-      break;
-
-    case TUPLE ('s', 'a'):
-      *weekday = 7;
-      break;
-
-    default:
-      dls_error (i, _("Day of the week expected in date value."));
-      return 0;
-    }
-
-  while (have_char (i) && isalpha (*i->s))
-    i->s++;
-
-  return 1;
+      {"sunday", true, 1},
+      {"su", true, 1},
+      {"monday", true, 2},
+      {"mo", true, 2},
+      {"tuesday", true, 3},
+      {"tu", true, 3},
+      {"wednesday", true, 4},
+      {"we", true, 4},
+      {"thursday", true, 5},
+      {"th", true, 5},
+      {"friday", true, 6},
+      {"fr", true, 6},
+      {"saturday", true, 7},
+      {"sa", true, 7},
+      
+      {NULL, false, 0},
+    };
 
-  #undef TUPLE
+  return parse_enum (i, _("weekday"), weekday_names, weekday);
 }
 
 static int
@@ -1418,7 +1320,7 @@
 static int
 parse_WKDAY (struct data_in *i)
 {
-  int weekday;
+  long weekday;
 
   if (!parse_leader (i)
       || !parse_weekday (i, &weekday)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]