static double get_multiplier(sge_rlim_t *rlimp, char **dptr, 
                             const char *where, char *err_str, int err_len)
{
   double mul = 1;
   *rlimp = 1;

   /* parse for k,K,m,M multipliers at the end of the value
    * string; strtod returns dptr to point to this location
    */
   switch (**dptr) {
   case 'k':
      mul = 1000;
      *rlimp = 1000;
      (*dptr)++;
      break;
   case 'K':
      mul = 1024;
      *rlimp = 1024;
      (*dptr)++;
      break;
   case 'm':
      mul = 1000 * 1000;
      *rlimp = 1000 * 1000;
      (*dptr)++;
      break;
   case 'M':
      mul = 1024 * 1024;
      *rlimp = 1024 * 1024;
      (*dptr)++;
      break;
   case 'g':
      mul = 1000 * 1000 * 1000;
      *rlimp = mul_infinity(mul_infinity(1000, 1000), 1000);
      (*dptr)++;
      break;
   case 'G':
      mul = 1024 * 1024 * 1024;
      *rlimp = mul_infinity(mul_infinity(1024, 1024), 1024);
      (*dptr)++;
      break;
   case ',':                    /* no multiplier */
   case '\0':                   /* no multiplier */
   case '/':                    /* no multiplier */
   case ' ':                    /* no multiplier */
      break;
   default:
      snprintf(err_str, err_len, MSG_GDI_UNRECOGNIZEDVALUETRAILER_SS , *dptr, where);
      return 0;
   }

   if ((**dptr != ',') && (**dptr != '\0') && (**dptr != '/')) {
      snprintf(err_str, err_len, MSG_GDI_UNEXPECTEDENDOFNUMERICALVALUE_SC , where, **dptr);
      return 0;
   }

   return mul;
}
u_long32 
sge_parse_num_val(sge_rlim_t *rlimp, double *dvalp, 
                  const char *str, const char *where, 
                  char *err_str, int err_len)
{
   double dummy;
   sge_rlim_t rlim, rlmuli;
   double dval;
   u_long32 ldummy;
   char *dptr;
   double muli;

   if (!rlimp)
      rlimp = &rlim;
   if (!dvalp)
      dvalp = &dval;

   if (err_str)
      err_str[0] = '\0';

   if (!strcasecmp(str, "true")) {
      /* C-language says bool is a numeric. For reasons of simplicity we 
         agree. */
      *dvalp = 1;
      *rlimp = 1;
      return 1;
   } else if (!strcasecmp(str, "false")) {
      *dvalp = 0;
      *rlimp = 0;
      return 0;
   } else if (!strcasecmp(str, "infinity")) {
      *dvalp = DBL_MAX;       /* use this for comparing limits */
      *rlimp = RLIM_INFINITY; /* use this for limit setting */
      return 0xFFFFFFFF;      /* return max ulong in 32 bit */
   } else if (strchr(str, ':')) {
      /* This is a time value in the format hr:min:sec */

      /* find the hours first */
      double t = strtod(str, &dptr);
      if (t > 0x7fffffff) {
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEFORHOUREXCEEDED_SS , where, str);
         return 0;
      }
      ldummy = (u_long32)(3600 * t);
      *rlimp = (sge_rlim_t)(long)mul_infinity(t, 3600.0);
      *dvalp = 3600 * t;

      if ((*dptr) != ':') {  
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALID_SS , where, str);
         return 0;
      }
      /* now go for the minutes */
      dptr++;
      t = strtod(dptr, &dptr);
      if (t > 0x7fffffff) {
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEFORMINUTEEXCEEDED_SS , where, str);
         return 0;
      }
      ldummy += (u_long32)(60 * t);
      *rlimp = add_infinity(*rlimp, (sge_rlim_t)(60*t));
      *dvalp += 60 * t;

      if ((*dptr) != ':') {
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALID_SS , where, str);
         return 0;
      }
      /* the seconds finally */
      dptr++;

      t = strtod(dptr, &dptr);
      ldummy += (u_long32)t;
      *rlimp = (sge_rlim_t)(long)add_infinity(*rlimp, t);
      *dvalp += t;

      while(*dptr) {
         if (!isspace((int) *dptr)) {
            snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALID_SS , where, str);
            return 0;
         }
         dptr++;
      }

      return (ldummy);

   } else if (strchr(str, '.') || *str != '0') {
      /* obviously this is no hex and no oct
       * ==> allow for both decimal and fixed float
       */
       
      double t = strtod(str, &dptr);
      
      if (t > 0x7fffffff)
         dummy = 0x7fffffff;
      else
         dummy = t;
   
      if ((dummy == 0.0) && (dptr == str)) {    /* no valid number ==> bail */
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALIDNONUMBER_SS , where, str);
         return 0;
      }

      /* OK, we got it */
      if (!(muli = get_multiplier(&rlmuli, &dptr, where, err_str, err_len)))
         return 0;
      dummy =    (u_long32) (dummy * muli);
      *dvalp =              t * muli;

      if (t > RLIM_MAX || rlmuli>= RLIM_MAX || (double)(RLIM_MAX/muli)<t)
         *rlimp = RLIM_INFINITY;
      else 
         *rlimp = (sge_rlim_t)(t*rlmuli);

      return (u_long32)dummy;

   } else { /* if (strchr(str, '.') || *str != '0') */
      /* This is either a hex or an octal ==> no fixed float allowed;
       * just use strtol
       */
      u_long32 t = strtol(str, &dptr, 0);   /* base=0 will handle both hex and oct */
      ldummy = t;
      *rlimp = t;
      *dvalp = t;

      if (dptr == str) {        /* no valid number ==> bail */
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALIDNOHEXOCTNUMBER_SS , where, str);
         return 0;
      }
      /* OK, we got it */
      if (!(muli = get_multiplier(&rlmuli, &dptr, where, err_str, err_len)))
         return 0;
      ldummy *= (u_long32)muli;
      *rlimp = mul_infinity(*rlimp, rlmuli);
      *dvalp *= muli;

      return (u_long32)ldummy;
   }
}