/[pspp]/pspp/src/data-in.c
ViewVC logotype

Diff of /pspp/src/data-in.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.13 by blp, Tue Mar 1 08:16:15 2005 UTC revision 1.14 by blp, Mon Mar 7 06:25:36 2005 UTC
# Line 81  dls_error (const struct data_in *i, cons Line 81  dls_error (const struct data_in *i, cons
81    vdls_error (i, format, args);    vdls_error (i, format, args);
82    va_end (args);    va_end (args);
83  }  }
84    
85    /* Parsing utility functions. */
86    
87  /* Excludes leading and trailing whitespace from I by adjusting  /* Excludes leading and trailing whitespace from I by adjusting
88     pointers. */     pointers. */
# Line 101  have_char (struct data_in *i) Line 103  have_char (struct data_in *i)
103  {  {
104    return i->s < i->e;    return i->s < i->e;
105  }  }
106    
107    /* If implied decimal places are enabled, apply them to
108       I->v->f. */
109    static void
110    apply_implied_decimals (struct data_in *i)
111    {
112      if ((i->flags & DI_IMPLIED_DECIMALS) && i->format.d > 0)
113        i->v->f /= pow (10., i->format.d);
114    }
115    
116  /* Format parsers. */  /* Format parsers. */
117    
# Line 110  static int parse_int (struct data_in *i, Line 121  static int parse_int (struct data_in *i,
121  static int  static int
122  parse_numeric (struct data_in *i)  parse_numeric (struct data_in *i)
123  {  {
124    short int sign;               /* +1 or -1. */    int sign;                     /* +1 or -1. */
125    double num;                   /* The number so far.  */    double num;                   /* The number so far.  */
126    
127    int got_dot;                  /* Found a decimal point.  */    int got_dot;                  /* Found a decimal point.  */
# Line 196  parse_numeric (struct data_in *i) Line 207  parse_numeric (struct data_in *i)
207            i->v->f = SYSMIS;            i->v->f = SYSMIS;
208            return 1;            return 1;
209          }          }
210        goto noconv;        dls_error (i, _("Field does not form a valid floating-point constant."));
211          i->v->f = SYSMIS;
212          return 0;
213      }      }
214        
215    if (have_char (i)    if (have_char (i)
# Line 209  parse_numeric (struct data_in *i) Line 222  parse_numeric (struct data_in *i)
222        if (isalpha (*i->s))        if (isalpha (*i->s))
223          i->s++;          i->s++;
224        if (!parse_int (i, &exp))        if (!parse_int (i, &exp))
225          goto noconv;          {
226              i->v->f = SYSMIS;
227              return 0;
228            }
229    
230        exponent += exp;        exponent += exp;
231      }      }
232    else if (!got_dot)    else if (!got_dot && (i->flags & DI_IMPLIED_DECIMALS))
233      exponent -= i->format.d;      exponent -= i->format.d;
234    
235    if (type == FMT_PCT && have_char (i) && *i->s == '%')    if (type == FMT_PCT && have_char (i) && *i->s == '%')
# Line 233  parse_numeric (struct data_in *i) Line 249  parse_numeric (struct data_in *i)
249    
250    /* Multiply NUM by 10 to the EXPONENT power, checking for overflow    /* Multiply NUM by 10 to the EXPONENT power, checking for overflow
251       and underflow.  */       and underflow.  */
   
252    if (exponent < 0)    if (exponent < 0)
253      {      {
254        if (-exponent + got_digit > -(DBL_MIN_10_EXP) + 5        if (-exponent + got_digit > -(DBL_MIN_10_EXP) + 5
255            || num < DBL_MIN * pow (10.0, (double) -exponent))            || num < DBL_MIN * pow (10.0, (double) -exponent))
256          goto underflow;          {
257              dls_error (i, _("Underflow in floating-point constant."));
258              i->v->f = 0.0;
259              return 0;
260            }
261    
262        num *= pow (10.0, (double) exponent);        num *= pow (10.0, (double) exponent);
263      }      }
264    else if (exponent > 0)    else if (exponent > 0)
265      {      {
266        if (num > DBL_MAX * pow (10.0, (double) -exponent))        if (num > DBL_MAX * pow (10.0, (double) -exponent))
267          goto overflow;          {
268              dls_error (i, _("Overflow in floating-point constant."));
269              i->v->f = SYSMIS;
270              return 0;
271            }
272          
273        num *= pow (10.0, (double) exponent);        num *= pow (10.0, (double) exponent);
274      }      }
275    
276    i->v->f = sign * num;    i->v->f = sign > 0 ? num : -num;
277    return 1;    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;  
278  }  }
279    
280  /* Returns the integer value of hex digit C. */  /* Returns the integer value of hex digit C. */
# Line 298  parse_N (struct data_in *i) Line 305  parse_N (struct data_in *i)
305        i->v->f = i->v->f * 10.0 + *cp - '0';        i->v->f = i->v->f * 10.0 + *cp - '0';
306      }      }
307    
308    if (i->format.d)    apply_implied_decimals (i);
     i->v->f /= pow (10.0, i->format.d);  
309    return 1;    return 1;
310  }  }
311    
# Line 374  static inline int Line 380  static inline int
380  parse_Z (struct data_in *i)  parse_Z (struct data_in *i)
381  {  {
382    char buf[64];    char buf[64];
383      bool got_dot = false;
384    
385    /* Warn user that we suck. */    /* Warn user that we suck. */
386    {    {
# Line 413  parse_Z (struct data_in *i) Line 420  parse_Z (struct data_in *i)
420      char *dp;      char *dp;
421    
422      for (sp = i->s, dp = buf + 1; sp < i->e - 1; sp++, dp++)      for (sp = i->s, dp = buf + 1; sp < i->e - 1; sp++, dp++)
423        if (*sp == '.')        if (*sp == '.')
424          *dp = '.';          {
425              *dp = '.';
426              got_dot = true;
427            }
428        else if ((*sp & 0xf0) == 0xf0 && (*sp & 0xf) < 10)        else if ((*sp & 0xf0) == 0xf0 && (*sp & 0xf) < 10)
429          *dp = (*sp & 0xf) + '0';          *dp = (*sp & 0xf) + '0';
430        else        else
# Line 437  parse_Z (struct data_in *i) Line 447  parse_Z (struct data_in *i)
447          return 0;          return 0;
448        }        }
449    }    }
450      
451      if (!got_dot)
452        apply_implied_decimals (i);
453    
454    return 1;    return 1;
455  }  }
456    
# Line 479  parse_IB (struct data_in *i) Line 492  parse_IB (struct data_in *i)
492    if (p[0] & 0x80)    if (p[0] & 0x80)
493      i->v->f = -(i->v->f + 1.0);      i->v->f = -(i->v->f + 1.0);
494    
495    if (i->format.d)    apply_implied_decimals (i);
     i->v->f /= pow (10.0, i->format.d);  
496    
497    return 1;    return 1;
498  }  }
# Line 499  parse_PIB (struct data_in *i) Line 511  parse_PIB (struct data_in *i)
511      i->v->f = i->v->f * 256.0 + i->s[j];      i->v->f = i->v->f * 256.0 + i->s[j];
512  #endif  #endif
513    
514    if (i->format.d)    apply_implied_decimals (i);
     i->v->f /= pow (10.0, i->format.d);  
515    
516    return 1;    return 1;
517  }  }
# Line 520  parse_P (struct data_in *i) Line 531  parse_P (struct data_in *i)
531    if ((*cp ^ (*cp >> 1)) & 0x10)    if ((*cp ^ (*cp >> 1)) & 0x10)
532        i->v->f = -i->v->f;        i->v->f = -i->v->f;
533    
534    if (i->format.d)    apply_implied_decimals (i);
     i->v->f /= pow (10.0, i->format.d);  
535    
536    return 1;    return 1;
537  }  }
# Line 538  parse_PK (struct data_in *i) Line 548  parse_PK (struct data_in *i)
548        i->v->f = i->v->f * 10 + (*cp & 15);        i->v->f = i->v->f * 10 + (*cp & 15);
549      }      }
550    
551    if (i->format.d)    apply_implied_decimals (i);
     i->v->f /= pow (10.0, i->format.d);  
552    
553    return 1;    return 1;
554  }  }
# Line 714  parse_date_delimiter (struct data_in *i) Line 723  parse_date_delimiter (struct data_in *i)
723    return 0;    return 0;
724  }  }
725    
726  /* Formats NUMBER as Roman numerals in ROMAN, or as Arabic numerals if  /* Association between a name and a value. */
727     the Roman expansion would be too long. */  struct enum_name
 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] =  
728    {    {
729      {1000, 'M'},      const char *name;           /* Name. */
730      {500, 'D'},      bool can_abbreviate;        /* True if name may be abbreviated. */
731      {100, 'C'},      int value;                  /* Value associated with name. */
     {50, 'L'},  
     {10, 'X'},  
     {5, 'V'},  
     {1, 'I'},  
732    };    };
733    
734    char *cp = roman;  /* Reads a name from I and sets *OUTPUT to the value associated
735       with that name.  Returns true if successful, false otherwise. */
736    int i, j;  static bool
737    parse_enum (struct data_in *i, const char *what,
738    assert (32 >= INT_DIGITS + 1);              const struct enum_name *enum_names,
739    if (number == 0)              long *output)
740      goto arabic;  {
741      const char *name;
742      size_t length;
743      const struct enum_name *ep;
744    
745    if (number < 0)    /* Consume alphabetic characters. */
746      name = i->s;
747      length = 0;
748      while (have_char (i) && isalpha (*i->s))
749      {      {
750        *cp++ = '-';        length++;
751        number = -number;        i->s++;
752      }      }
753      if (length == 0)
   for (i = 0; i < 7; i++)  
754      {      {
755        int digit = roman_tab[i].value;        dls_error (i, _("Parse error at `%c' expecting %s."), *i->s, what);
756        while (number >= digit)        return 0;
         {  
           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;  
             }  
         }  
757      }      }
   *cp = 0;  
   return;  
   
 arabic:  
   sprintf (roman, "%d", save_number);  
 }  
758    
759  /* Returns true if C is a (lowercase) roman numeral. */    for (ep = enum_names; ep->name != NULL; ep++)
760  #define CHAR_IS_ROMAN(C)                                \      if ((ep->can_abbreviate
761          ((C) == 'x' || (C) == 'v' || (C) == 'i')           && lex_id_match_len (ep->name, strlen (ep->name), name, length))
762            || (!ep->can_abbreviate && length == strlen (ep->name)
763                && !memcmp (name, ep->name, length)))
764          {
765            *output = ep->value;
766            return 1;
767          }
768    
769  /* Returns the value of a single (lowercase) roman numeral. */    dls_error (i, _("Unknown %s `%.*s'."), what, (int) length, name);
770  #define ROMAN_VALUE(C)                          \    return 0;
771          ((C) == 'x' ? 10 : ((C) == 'v' ? 5 : 1))  }
772    
773  static int  static int
774  parse_month (struct data_in *i, long *month)  parse_month (struct data_in *i, long *month)
775  {  {
776      static const struct enum_name month_names[] =
777        {
778          {"january", true, 1},
779          {"february", true, 2},
780          {"march", true, 3},
781          {"april", true, 4},
782          {"may", true, 5},
783          {"june", true, 6},
784          {"july", true, 7},
785          {"august", true, 8},
786          {"september", true, 9},
787          {"october", true, 10},
788          {"november", true, 11},
789          {"december", true, 12},
790    
791          {"i", false, 1},
792          {"ii", false, 2},
793          {"iii", false, 3},
794          {"iv", false, 4},
795          {"iiii", false, 4},
796          {"v", false, 5},
797          {"vi", false, 6},
798          {"vii", false, 7},
799          {"viii", false, 8},
800          {"ix", false, 9},
801          {"viiii", false, 9},
802          {"x", false, 10},
803          {"xi", false, 11},
804          {"xii", false, 12},
805    
806          {NULL, false, 0},
807        };
808    
809    if (!force_have_char (i))    if (!force_have_char (i))
810      return 0;      return 0;
811        
# Line 810  parse_month (struct data_in *i, long *mo Line 819  parse_month (struct data_in *i, long *mo
819        dls_error (i, _("Month (%ld) must be between 1 and 12."), *month);        dls_error (i, _("Month (%ld) must be between 1 and 12."), *month);
820        return 0;        return 0;
821      }      }
822      else
823    if (CHAR_IS_ROMAN (tolower (*i->s)))      return parse_enum (i, _("month"), month_names, month);
     {  
       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;  
   }  
824  }  }
825    
826  static int  static int
# Line 1093  parse_hour24 (struct data_in *i, long *h Line 1025  parse_hour24 (struct data_in *i, long *h
1025    
1026            
1027  static int  static int
1028  parse_weekday (struct data_in *i, int *weekday)  parse_weekday (struct data_in *i, long *weekday)
1029  {  {
1030    /* PORTME */    static const struct enum_name weekday_names[] =
   #define TUPLE(A,B)                            \  
           (((A) << 8) + (B))  
   
   if (i->s + 1 >= i->e)  
1031      {      {
1032        dls_error (i, _("Day of the week expected in date value."));        {"sunday", true, 1},
1033        return 0;        {"su", true, 1},
1034      }        {"monday", true, 2},
1035          {"mo", true, 2},
1036    switch (TUPLE (tolower (i->s[0]), tolower (i->s[1])))        {"tuesday", true, 3},
1037      {        {"tu", true, 3},
1038      case TUPLE ('s', 'u'):        {"wednesday", true, 4},
1039        *weekday = 1;        {"we", true, 4},
1040        break;        {"thursday", true, 5},
1041          {"th", true, 5},
1042      case TUPLE ('m', 'o'):        {"friday", true, 6},
1043        *weekday = 2;        {"fr", true, 6},
1044        break;        {"saturday", true, 7},
1045          {"sa", true, 7},
1046      case TUPLE ('t', 'u'):        
1047        *weekday = 3;        {NULL, false, 0},
1048        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;  
1049    
1050    #undef TUPLE    return parse_enum (i, _("weekday"), weekday_names, weekday);
1051  }  }
1052    
1053  static int  static int
# Line 1418  parse_DATETIME (struct data_in *i) Line 1320  parse_DATETIME (struct data_in *i)
1320  static int  static int
1321  parse_WKDAY (struct data_in *i)  parse_WKDAY (struct data_in *i)
1322  {  {
1323    int weekday;    long weekday;
1324    
1325    if (!parse_leader (i)    if (!parse_leader (i)
1326        || !parse_weekday (i, &weekday)        || !parse_weekday (i, &weekday)

Legend:
Removed from v.1.13  
changed lines
  Added in v.1.14

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26