示例#1
0
int
c_strcasecmp (const char *s1, const char *s2)
{
  register const unsigned char *p1 = (const unsigned char *) s1;
  register const unsigned char *p2 = (const unsigned char *) s2;
  unsigned char c1, c2;

  if (p1 == p2)
    return 0;

  do
    {
      c1 = c_tolower (*p1);
      c2 = c_tolower (*p2);

      if (c1 == '\0')
	break;

      ++p1;
      ++p2;
    }
  while (c1 == c2);

  return c1 - c2;
}
/* Compare two MAC addresses, ignoring differences in case,
 * as well as leading zeros.
 */
int
virMacAddrCompare(const char *p, const char *q)
{
    unsigned char c, d;
    do {
        while (*p == '0' && c_isxdigit(p[1]))
            ++p;
        while (*q == '0' && c_isxdigit(q[1]))
            ++q;
        c = c_tolower(*p);
        d = c_tolower(*q);

        if (c == 0 || d == 0)
            break;

        ++p;
        ++q;
    } while (c == d);

    if (UCHAR_MAX <= INT_MAX)
        return c - d;

    /* On machines where 'char' and 'int' are types of the same size, the
       difference of two 'unsigned char' values - including the sign bit -
       doesn't fit in an 'int'.  */
    return c > d ? 1 : c < d ? -1 : 0;
}
示例#3
0
文件: host.c 项目: mirror/wget
/* Check whether WHAT is matched in LIST, each element of LIST being a
   pattern to match WHAT against, using backward matching (see
   match_backwards() in utils.c).

   If an element of LIST matched, 1 is returned, 0 otherwise.  */
bool
sufmatch (const char **list, const char *what)
{
  int i, j, k, lw;

  lw = strlen (what);

  for (i = 0; list[i]; i++)
    {
      j = strlen (list[i]);
      if (lw < j)
        continue; /* what is no (sub)domain of list[i] */

      for (k = lw; j >= 0 && k >= 0; j--, k--)
        if (c_tolower (list[i][j]) != c_tolower (what[k]))
          break;

      /* Domain or subdomain match
       * k == -1: exact match
       * k >= 0 && what[k] == '.': subdomain match
       * k >= 0 && list[i][0] == '.': dot-prefixed subdomain match
       */
      if (j == -1 && (k == -1 || what[k] == '.' || list[i][0] == '.'))
        return true;
    }

  return false;
}
示例#4
0
文件: openssl.c 项目: DonCN/haiku
static bool
pattern_match (const char *pattern, const char *string)
{
  const char *p = pattern, *n = string;
  char c;
  for (; (c = c_tolower (*p++)) != '\0'; n++)
    if (c == '*')
      {
        for (c = c_tolower (*p); c == '*'; c = c_tolower (*++p))
          ;
        for (; *n != '\0'; n++)
          if (c_tolower (*n) == c && pattern_match (p, n))
            return true;
#ifdef ASTERISK_EXCLUDES_DOT
          else if (*n == '.')
            return false;
#endif
        return c == '\0';
      }
    else
      {
        if (c != c_tolower (*n))
          return false;
      }
  return *n == '\0';
}
示例#5
0
extern int c_strcasecmp(const char *__T42873616, const char *__T42873944); static void __zvm_this_file_init(void); static __attribute__((__constructor__)) void __zvm_file_constructor(void); int c_strcasecmp( const char *s1,  const char *s2)
{ auto void *__zvm_prev_stack_end; auto int __T42941400;
register const unsigned char *p1;
register const unsigned char *p2;
auto unsigned char c1; auto unsigned char c2;
# 31
__ZVM_DECL_LOCAL_MLS(); __zvm_mls_scope_in(__zvm_cc_var, 2, s1, (__zvm_varinfo + 1U), s2, (__zvm_varinfo + 2U)); __ZVM_PUSH_FUNC_INIT((__zvm_funcinfo + 2U)); __zcov_update_counter(0);
p1 = (((void *)(__zvm_mls_set_instrumented(__zvm_cc_var))) , ((const unsigned char *)(__zvm_mls_ptr_init(((const unsigned char *)s1)))));
p2 = (((void *)(__zvm_mls_set_instrumented(__zvm_cc_var))) , ((const unsigned char *)(__zvm_mls_ptr_init(((const unsigned char *)s2))))); {


if ((p1 == p2)) { __zcov_update_counter(1); { __T42941400 = 0; __zvm_mls_scope_out("/home/release/apps/grep2.5.3/grep-2.9/lib/c-strcasecmp.c", 36, __zvm_cc_var, __zvm_mls_return_unused, 0, 4, 0, p1, "p1", p2, "p2", s1, "s1", s2, "s2"); __ZVM_POP_FUNC_END(); return __T42941400; } } else  { __zcov_update_counter(2); } } __zcov_update_counter(3); {


do
{ __zcov_update_counter(4); __ZVM_PUSH_FUNC((__zvm_funcinfo + 0U));
c1 = ((unsigned char)(c_tolower(((int)((*((const unsigned char *)(__zvm_component_reference_inline((__zvm_varinfo + 3U), ((void *)((unsigned long)p1)), ((long)0L), ((int)1), ((void *)((unsigned long)__zvm_cc_var))))))))))); __ZVM_PUSH_FUNC((__zvm_funcinfo + 1U));
c2 = ((unsigned char)(c_tolower(((int)((*((const unsigned char *)(__zvm_component_reference_inline((__zvm_varinfo + 4U), ((void *)((unsigned long)p2)), ((long)0L), ((int)1), ((void *)((unsigned long)__zvm_cc_var))))))))))); {

if ((((int)c1) == 0)) { __zcov_update_counter(5);
goto __T42933264; } else  { __zcov_update_counter(6); } } __zcov_update_counter(7);

++p1;
++p2;
} while ((((int)c1) == ((int)c2))); __T42933264:; __zcov_update_counter(8); } __zcov_update_counter(9); {


if ((1)) { __zcov_update_counter(10); { __T42941400 = (((int)c1) - ((int)c2)); __zvm_mls_scope_out("/home/release/apps/grep2.5.3/grep-2.9/lib/c-strcasecmp.c", 53, __zvm_cc_var, __zvm_mls_return_unused, 0, 4, 0, p1, "p1", p2, "p2", s1, "s1", s2, "s2"); __ZVM_POP_FUNC_END(); return __T42941400; } } else  { __zcov_update_counter(11); { __T42941400 = ((((int)c1) > ((int)c2)) ? 1 : ((((int)c1) < ((int)c2)) ? (-1) : 0)); __zvm_mls_scope_out("/home/release/apps/grep2.5.3/grep-2.9/lib/c-strcasecmp.c", 58, __zvm_cc_var, __zvm_mls_return_unused, 0, 4, 0, p1, "p1", p2, "p2", s1, "s1", s2, "s2"); __ZVM_POP_FUNC_END(); return __T42941400; } } }
# 59
} static void __zvm_this_file_init(void) {   } static __attribute__((__constructor__)) void __zvm_file_constructor(void) {  __zvm_file_ctr(((void *)__zvm_dirnames)); __zvm_this_file_init(); __zvm_local_init_inline(); __zvm_dr_varinfo_init(((void *)__zvm_varinfo), zvm_file_option); __zvm_update_align(4U); }
示例#6
0
int
c_strncasecmp (const char *s1, const char *s2, size_t n)
{
  register const unsigned char *p1 = (const unsigned char *) s1;
  register const unsigned char *p2 = (const unsigned char *) s2;
  unsigned char c1, c2;

  if (p1 == p2 || n == 0)
    return 0;

  do
    {
      c1 = c_tolower (*p1);
      c2 = c_tolower (*p2);

      if (--n == 0 || c1 == '\0')
        break;

      ++p1;
      ++p2;
    }
  while (c1 == c2);

  if (UCHAR_MAX <= INT_MAX)
    return c1 - c2;
  else
    /* On machines where 'char' and 'int' are types of the same size, the
       difference of two 'unsigned char' values - including the sign bit -
       doesn't fit in an 'int'.  */
    return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
}
示例#7
0
/* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive
   comparison from the C locale, regardless of the current locale.  */
char *
c_strcasestr (const char *haystack_start, const char *needle_start)
{
  const char *haystack = haystack_start;
  const char *needle = needle_start;
  size_t needle_len; /* Length of NEEDLE.  */
  size_t haystack_len; /* Known minimum length of HAYSTACK.  */
  bool ok = true; /* True if NEEDLE is prefix of HAYSTACK.  */

  /* Determine length of NEEDLE, and in the process, make sure
     HAYSTACK is at least as long (no point processing all of a long
     NEEDLE if HAYSTACK is too short).  */
  while (*haystack && *needle)
    ok &= (c_tolower ((unsigned char) *haystack++)
           == c_tolower ((unsigned char) *needle++));
  if (*needle)
    return NULL;
  if (ok)
    return (char *) haystack_start;
  needle_len = needle - needle_start;
  haystack = haystack_start + 1;
  haystack_len = needle_len - 1;

  /* Perform the search.  Abstract memory is considered to be an array
     of 'unsigned char' values, not an array of 'char' values.  See
     ISO C 99 section 6.2.6.1.  */
  if (needle_len < LONG_NEEDLE_THRESHOLD)
    return two_way_short_needle ((const unsigned char *) haystack,
                                 haystack_len,
                                 (const unsigned char *) needle_start,
                                 needle_len);
  return two_way_long_needle ((const unsigned char *) haystack, haystack_len,
                              (const unsigned char *) needle_start,
                              needle_len);
}
示例#8
0
static unsigned long
hash_string_nocase (const void *key)
{
  const char *p = key;
  unsigned int h = c_tolower (*p);

  if (h)
    for (p += 1; *p != '\0'; p++)
      h = (h << 5) - h + c_tolower (*p);

  return h;
}
示例#9
0
/* Return a copy of the filename, with an extra ".bin" at the end.
   More generally, it replaces "${EXEEXT}" at the end with ".bin${EXEEXT}".  */
static char *
add_dotbin (const char *filename)
{
  size_t filename_len = strlen (filename);
  char *result = (char *) malloc (filename_len + 4 + 1);

  if (result != NULL)
    {
      if (sizeof (EXEEXT) > sizeof (""))
        {
          /* EXEEXT handling.  */
          const size_t exeext_len = sizeof (EXEEXT) - sizeof ("");
          static const char exeext[] = EXEEXT;
          if (filename_len > exeext_len)
            {
              /* Compare using an inlined copy of c_strncasecmp(), because
                 the filenames may have undergone a case conversion since
                 they were packaged.  In other words, EXEEXT may be ".exe"
                 on one system and ".EXE" on another.  */
              const char *s1 = filename + filename_len - exeext_len;
              const char *s2 = exeext;
              for (; *s1 != '\0'; s1++, s2++)
                {
                  unsigned char c1 = *s1;
                  unsigned char c2 = *s2;
                  if (c_tolower (c1) != c_tolower (c2))
                    goto simple_append;
                }
              /* Insert ".bin" before EXEEXT or its equivalent.  */
              memcpy (result, filename, filename_len - exeext_len);
              memcpy (result + filename_len - exeext_len, ".bin", 4);
              memcpy (result + filename_len - exeext_len + 4,
                      filename + filename_len - exeext_len,
                      exeext_len + 1);
              return result;
            }
        }
     simple_append:
      /* Simply append ".bin".  */
      memcpy (result, filename, filename_len);
      memcpy (result + filename_len, ".bin", 4 + 1);
      return result;
    }
  else
    {
      fprintf (stderr, "%s: %s\n", program_name, "memory exhausted");
      exit (1);
    }
}
示例#10
0
unsigned char *_nl_normalize_codeset( unsigned char *codeset, size_t name_len )
{
  int ecx;
  int edx;
  int dh;
  int len;
  int only_digit;
  unsigned char *wp;
  size_t cnt;
  if ( name_len )
  {
    only_digit = 1;
    len = 0;
    cnt = 0;
    codeset[0] = codeset[0];
    do
    {
      cnt++;
    }
    while ( cnt + 1 < name_len );
    if ( malloc( len + 1 + 1 ) )
    {
      wp[0] = malloc( len + 1 + 1 );
      if ( only_digit )
      {
        *(int*)(malloc( len )) = 0x6f7369;
        wp[0] = wp[3];
      }
      if ( name_len )
      {
        cnt = 0;
        do
        {
          if ( ( *(char*)(*(int*)(__ctype_b_loc(  )) + ( *(char*)(codeset[0] + cnt) * 2 ) + 1) & 4 ) & 255 )
          {
            wp[0] = c_tolower( *(char*)(codeset[0] + cnt) );
            wp[0] = wp[1];
            cnt++;
          }
          else
          {
            if ( __ctype_b_loc(  ) - 48 >= 9 )
            {
              wp[0] = __ctype_b_loc(  );
              wp[0] = wp[1];
            }
            cnt++;
            if ( name_len <= cnt + 1 )
              break;
          }
        }
        while ( cnt < name_len );
        wp[0] = wp[0];
      }
      wp[0] = 0;
    }
    return ebp_32;
  }
  only_digit = 1;
}
示例#11
0
文件: pkg-hash.c 项目: guillemj/dpkg
/**
 * Return the package set with the given name.
 *
 * If the package already exists in the internal database, then it returns
 * the existing structure. Otherwise it allocates a new one and will return
 * it. The actual name associated to the package set is a lowercase version
 * of the name given in parameter.
 *
 * A package set (struct pkgset) can be composed of multiple package instances
 * (struct pkginfo) where each instance is distinguished by its architecture
 * (as recorded in pkg.installed.arch and pkg.available.arch).
 *
 * @param inname Name of the package set.
 *
 * @return The package set.
 */
struct pkgset *
pkg_hash_find_set(const char *inname)
{
  struct pkgset **setp, *new_set;
  char *name = m_strdup(inname), *p;

  p= name;
  while (*p) {
    *p = c_tolower(*p);
    p++;
  }

  setp = bins + (str_fnv_hash(name) % (BINS));
  while (*setp && strcasecmp((*setp)->name, name))
    setp = &(*setp)->next;
  if (*setp) {
    free(name);
    return *setp;
  }

  new_set = nfmalloc(sizeof(*new_set));
  pkgset_blank(new_set);
  new_set->name = nfstrsave(name);
  new_set->next = NULL;
  *setp = new_set;
  nset++;
  npkg++;

  free(name);

  return new_set;
}
示例#12
0
/*
 * normalize_lcname(): remove any '_' and '-' and convert any character
 * to lower case after the <language>_<territory> part. If result is identical
 * to argument, free result and
 * return NULL.
 */
static char *
normalize_lcname (const char *name)
{
    char *p, *ret;
    const char *tmp = name;

    p = ret = Xmalloc(strlen(name) + 1);
    if (!p)
	return NULL;

    if (tmp) {
	while (*tmp && *tmp != '.' && *tmp != '@')
	    *p++ = *tmp++;
	while (*tmp) {
	    if (*tmp != '-')
		*p++ = c_tolower(*tmp);
	    tmp++;
	}
    }
    *p = '\0';

    if (strcmp(ret, name) == 0) {
	Xfree(ret);
	return NULL;
    }

    return ret;
}
示例#13
0
/* Compare no more than N characters of S1 and S2,
   ignoring case, returning less than, equal to or
   greater than zero if S1 is lexicographically less
   than, equal to or greater than S2.  */
int
strncasecmp (const char *s1, const char *s2, size_t n)
{
  register const unsigned char *p1 = (const unsigned char *) s1;
  register const unsigned char *p2 = (const unsigned char *) s2;
  unsigned char c1, c2;

  if (p1 == p2 || n == 0)
    return 0;

  do
    {
      c1 = c_tolower (*p1++);
      c2 = c_tolower (*p2++);
      if (c1 == '\0' || c1 != c2)
        return c1 - c2;
    } while (--n > 0);

  return c1 - c2;
}
示例#14
0
文件: host.c 项目: AOSC-Dev/wget
/* Check whether WHAT is matched in LIST, each element of LIST being a
   pattern to match WHAT against, using backward matching (see
   match_backwards() in utils.c).

   If an element of LIST matched, 1 is returned, 0 otherwise.  */
bool
sufmatch (const char **list, const char *what)
{
  int i, j, k, lw;

  lw = strlen (what);
  for (i = 0; list[i]; i++)
    {
      if (list[i][0] == '\0')
        continue;

      for (j = strlen (list[i]), k = lw; j >= 0 && k >= 0; j--, k--)
        if (c_tolower (list[i][j]) != c_tolower (what[k]))
          break;
      /* The domain must be first to reach to beginning.  */
      if (j == -1)
        return true;
    }
  return false;
}
示例#15
0
/* Attempts to parse an identifier found in a date at the
   beginning of S.  Advances *S past the end of the token.
   Returns the parsed token, or 0 if no valid token was
   found.  */
static enum date_token
recognize_identifier_token (struct substring *s)
{
  size_t length = ss_span (*s, ss_cstr (CC_LETTERS));
  enum date_token token = 0;
  switch (length)
    {
    case 0:
      break;

    case 1:
      switch (c_tolower (s->string[0]))
        {
        case 'i':
        case 'v':
        case 'x':
          token = DT_MONTH;
          break;

        case 'q':
          token = DT_Q;
          break;
        }
      break;

    case 2:
      {
        int s0 = c_tolower ((unsigned char) s->string[0]);
        int s1 = c_tolower ((unsigned char) s->string[1]);
        token = recognize_id2 (s0, s1, false);
        if (!token && s0 == 'w' && s1 == 'k')
          token = DT_WK;
      }
      break;

    default:
      {
        int s0 = c_tolower ((unsigned char) s->string[0]);
        int s1 = c_tolower ((unsigned char) s->string[1]);
        int s2 = c_tolower ((unsigned char) s->string[2]);
        token = recognize_id2 (s0, s1, true);
        if (!token)
          token = recognize_id3 (s0, s1, s2, length > 3);
        if (!token && length == 4)
          {
            int s3 = c_tolower ((unsigned char) s->string[3]);
            if (s0 == 'v' && s1 == 'i' && s2 == 'i' && s3 == 'i')
              token = DT_MONTH;
          }
      }
      break;
    }
  if (token)
    ss_advance (s, length);
  return token;
}
示例#16
0
static char *
lowercase(
    char *dst,
    const char *src)
{
    const char *s;
    char *t;

    for (s = src, t = dst; *s; ++s, ++t)
	*t = c_tolower(*s);
    *t = '\0';
    return dst;
}
示例#17
0
static void
test_casing(void)
{
	test_pass(c_tolower('A') == 'a');
	test_pass(c_tolower('Z') == 'z');

	test_pass(c_tolower('a') == 'a');
	test_pass(c_tolower('z') == 'z');

	test_pass(c_tolower('0') == '0');
	test_pass(c_tolower('9') == '9');

	/* Test if we can handle the value for EOF. */
	test_pass(c_tolower(-1) == -1);
}
示例#18
0
文件: response.c 项目: Efreak/elinks
static void
add_header_to_string(struct string *str, unsigned char *header)
{
	unsigned char *end;

	while ((end = strstr((const char *)header, "=?")) != NULL) {
		int encoding;
		unsigned char *cp, *sp;

		if (header != end) {
			add_html_to_string(str, header, end - header);
			header = end;
		}

		/* E.g.
		 * ep : "=?iso-2022-jp?B?GyR...?= foo"
		 * ep : "=?ISO-8859-1?Q?Foo=FCbar?= baz"
		 */
		end += 2;
		cp = strchr((const char *)end, '?');
		if (!cp)
			break;

		for (sp = end; sp < cp; sp++)
			/* charset */;
		encoding = c_tolower(cp[1]);

		if (!encoding || cp[2] != '?')
			break;
		cp += 3;
		end = strstr((const char *)(cp + 3), "?=");
		if (!end)
			break;
		if (encoding == 'b')
			decode_b_segment(str, cp, end);
		else if (encoding == 'q')
			decode_q_segment(str, cp, end);
		else
			break;

		header = end + 2;
	}

	add_html_to_string(str, header, strlen(header));
}
示例#19
0
static char *
windows_path (guestfs_h *g, const char *root, const char *path)
{
  char *ret;
  size_t i;

  /* If there is a drive letter, rewrite the path. */
  if (c_isalpha (path[0]) && path[1] == ':') {
    char drive_letter = c_tolower (path[0]);
    /* This returns the newly allocated string. */
    mount_drive_letter (drive_letter, root);
    ret = strdup (path + 2);
    if (ret == NULL) {
      perror ("strdup");
      exit (EXIT_FAILURE);
    }
  }
  else if (!*path) {
    ret = strdup ("/");
    if (ret == NULL) {
      perror ("strdup");
      exit (EXIT_FAILURE);
    }
  }
  else {
    ret = strdup (path);
    if (ret == NULL) {
      perror ("strdup");
      exit (EXIT_FAILURE);
    }
  }

  /* Blindly convert any backslashes into forward slashes.  Is this good? */
  for (i = 0; i < strlen (ret); ++i)
    if (ret[i] == '\\')
      ret[i] = '/';

  char *t = guestfs_case_sensitive_path (g, ret);
  free (ret);
  ret = t;
  if (ret == NULL)
    exit (EXIT_FAILURE);

  return ret;
}
示例#20
0
static void
mount_drive_letter (char drive_letter, const char *root)
{
  char **drives;
  char *device;
  size_t i;

  /* Resolve the drive letter using the drive mappings table. */
  drives = guestfs_inspect_get_drive_mappings (g, root);
  if (drives == NULL || drives[0] == NULL) {
    fprintf (stderr, _("%s: to use Windows drive letters, this must be a Windows guest\n"),
             program_name);
    exit (EXIT_FAILURE);
  }

  device = NULL;
  for (i = 0; drives[i] != NULL; i += 2) {
    if (c_tolower (drives[i][0]) == drive_letter && drives[i][1] == '\0') {
      device = drives[i+1];
      break;
    }
  }

  if (device == NULL) {
    fprintf (stderr, _("%s: drive '%c:' not found.\n"),
             program_name, drive_letter);
    exit (EXIT_FAILURE);
  }

  /* Unmount current disk and remount device. */
  if (guestfs_umount_all (g) == -1)
    exit (EXIT_FAILURE);

  if (guestfs_mount_options (g, "", device, "/") == -1)
    exit (EXIT_FAILURE);

  for (i = 0; drives[i] != NULL; ++i)
    free (drives[i]);
  free (drives);
  /* Don't need to free (device) because that string was in the
   * drives array.
   */
}
示例#21
0
static void
mount_drive_letter (guestfs_h *g, char drive_letter, const char *root,
                    int readonly)
{
  char *device;
  size_t i;

  /* Resolve the drive letter using the drive mappings table. */
  CLEANUP_FREE_STRING_LIST char **drives =
    guestfs_inspect_get_drive_mappings (g, root);
  if (drives == NULL || drives[0] == NULL)
    error (EXIT_FAILURE, 0,
           _("to use Windows drive letters, this must be a Windows guest"));

  device = NULL;
  for (i = 0; drives[i] != NULL; i += 2) {
    if (c_tolower (drives[i][0]) == drive_letter && drives[i][1] == '\0') {
      device = drives[i+1];
      break;
    }
  }

  if (device == NULL)
    error (EXIT_FAILURE, 0, _("drive '%c:' not found."), drive_letter);

  /* Unmount current disk and remount device. */
  if (guestfs_umount_all (g) == -1)
    exit (EXIT_FAILURE);

  if ((readonly ? guestfs_mount_ro : guestfs_mount) (g, device, "/") == -1)
    exit (EXIT_FAILURE);

  /* Don't need to free (device) because that string was in the
   * drives array.
   */
}
示例#22
0
文件: strtod.c 项目: 4solo/cs35
/* Convert NPTR to a double.  If ENDPTR is not NULL, a pointer to the
   character after the last one used in the number is put in *ENDPTR.  */
double
strtod (const char *nptr, char **endptr)
{
  const unsigned char *s;
  bool negative = false;

  /* The number so far.  */
  double num;

  bool got_dot;			/* Found a decimal point.  */
  bool got_digit;		/* Seen any digits.  */
  bool hex = false;		/* Look for hex float exponent.  */

  /* The exponent of the number.  */
  long int exponent;

  if (nptr == NULL)
    {
      errno = EINVAL;
      goto noconv;
    }

  /* Use unsigned char for the ctype routines.  */
  s = (unsigned char *) nptr;

  /* Eat whitespace.  */
  while (isspace (*s))
    ++s;

  /* Get the sign.  */
  negative = *s == '-';
  if (*s == '-' || *s == '+')
    ++s;

  num = 0.0;
  got_dot = false;
  got_digit = false;
  exponent = 0;

  /* Check for hex float.  */
  if (*s == '0' && c_tolower (s[1]) == 'x'
      && (c_isxdigit (s[2]) || ('.' == s[2] && c_isxdigit (s[3]))))
    {
      hex = true;
      s += 2;
      for (;; ++s)
	{
	  if (c_isxdigit (*s))
	    {
	      got_digit = true;

	      /* Make sure that multiplication by 16 will not overflow.  */
	      if (num > DBL_MAX / 16)
		/* The value of the digit doesn't matter, since we have already
		   gotten as many digits as can be represented in a `double'.
		   This doesn't necessarily mean the result will overflow.
		   The exponent may reduce it to within range.

		   We just need to record that there was another
		   digit so that we can multiply by 16 later.  */
		++exponent;
	      else
		num = ((num * 16.0)
		       + (c_tolower (*s) - (c_isdigit (*s) ? '0' : 'a' - 10)));

	      /* Keep track of the number of digits after the decimal point.
		 If we just divided by 16 here, we would lose precision.  */
	      if (got_dot)
		--exponent;
	    }
	  else if (!got_dot && *s == '.')
	    /* Record that we have found the decimal point.  */
	    got_dot = true;
	  else
	    /* Any other character terminates the number.  */
	    break;
	}
    }

  /* Not a hex float.  */
  else
    {
      for (;; ++s)
	{
	  if (c_isdigit (*s))
	    {
	      got_digit = true;

	      /* Make sure that multiplication by 10 will not overflow.  */
	      if (num > DBL_MAX * 0.1)
		/* The value of the digit doesn't matter, since we have already
		   gotten as many digits as can be represented in a `double'.
		   This doesn't necessarily mean the result will overflow.
		   The exponent may reduce it to within range.

		   We just need to record that there was another
		   digit so that we can multiply by 10 later.  */
		++exponent;
	      else
		num = (num * 10.0) + (*s - '0');

	      /* Keep track of the number of digits after the decimal point.
		 If we just divided by 10 here, we would lose precision.  */
	      if (got_dot)
		--exponent;
	    }
	  else if (!got_dot && *s == '.')
	    /* Record that we have found the decimal point.  */
	    got_dot = true;
	  else
	    /* Any other character terminates the number.  */
	    break;
	}
    }

  if (!got_digit)
    {
      /* Check for infinities and NaNs.  */
      if (c_tolower (*s) == 'i'
	  && c_tolower (s[1]) == 'n'
	  && c_tolower (s[2]) == 'f')
	{
	  s += 3;
	  num = HUGE_VAL;
	  if (c_tolower (*s) == 'i'
	      && c_tolower (s[1]) == 'n'
	      && c_tolower (s[2]) == 'i'
	      && c_tolower (s[3]) == 't'
	      && c_tolower (s[4]) == 'y')
	    s += 5;
	  goto valid;
	}
#ifdef NAN
      else if (c_tolower (*s) == 'n'
	       && c_tolower (s[1]) == 'a'
	       && c_tolower (s[2]) == 'n')
	{
	  s += 3;
	  num = NAN;
	  /* Since nan(<n-char-sequence>) is implementation-defined,
	     we define it by ignoring <n-char-sequence>.  A nicer
	     implementation would populate the bits of the NaN
	     according to interpreting n-char-sequence as a
	     hexadecimal number, but the result is still a NaN.  */
	  if (*s == '(')
	    {
	      const unsigned char *p = s + 1;
	      while (c_isalnum (*p))
		p++;
	      if (*p == ')')
		s = p + 1;
	    }
	  goto valid;
	}
#endif
      goto noconv;
    }

  if (c_tolower (*s) == (hex ? 'p' : 'e') && !isspace (s[1]))
    {
      /* Get the exponent specified after the `e' or `E'.  */
      int save = errno;
      char *end;
      long int value;

      errno = 0;
      ++s;
      value = strtol ((char *) s, &end, 10);
      if (errno == ERANGE && num)
	{
	  /* The exponent overflowed a `long int'.  It is probably a safe
	     assumption that an exponent that cannot be represented by
	     a `long int' exceeds the limits of a `double'.  */
	  if (endptr != NULL)
	    *endptr = end;
	  if (value < 0)
	    goto underflow;
	  else
	    goto overflow;
	}
      else if (end == (char *) s)
	/* There was no exponent.  Reset END to point to
	   the 'e' or 'E', so *ENDPTR will be set there.  */
	end = (char *) s - 1;
      errno = save;
      s = (unsigned char *) end;
      exponent += value;
    }

  if (num == 0.0)
    goto valid;

  if (hex)
    {
      /* ldexp takes care of range errors.  */
      num = ldexp (num, exponent);
      goto valid;
    }

  /* Multiply NUM by 10 to the EXPONENT power,
     checking for overflow and underflow.  */

  if (exponent < 0)
    {
      if (num < DBL_MIN * pow (10.0, (double) -exponent))
	goto underflow;
    }
  else if (exponent > 0)
    {
      if (num > DBL_MAX * pow (10.0, (double) -exponent))
	goto overflow;
    }

  num *= pow (10.0, (double) exponent);

 valid:
  if (endptr != NULL)
    *endptr = (char *) s;
  return negative ? -num : num;

 overflow:
  /* Return an overflow error.  */
  if (endptr != NULL)
    *endptr = (char *) s;
  errno = ERANGE;
  return negative ? -HUGE_VAL : HUGE_VAL;

 underflow:
  /* Return an underflow error.  */
  if (endptr != NULL)
    *endptr = (char *) s;
  errno = ERANGE;
  return negative ? -0.0 : 0.0;

 noconv:
  /* There was no number.  */
  if (endptr != NULL)
    *endptr = (char *) nptr;
  errno = EINVAL;
  return 0.0;
}
示例#23
0
/* Parse a number at NPTR; this is a bit like strtol (NPTR, ENDPTR)
   except there are no leading spaces or signs or "0x", and ENDPTR is
   nonnull.  The number uses a base BASE (either 10 or 16) fraction, a
   radix RADIX (either 10 or 2) exponent, and exponent character
   EXPCHAR.  To convert from a number of digits to a radix exponent,
   multiply by RADIX_MULTIPLIER (either 1 or 4).  */
static double
parse_number (const char *nptr,
              int base, int radix, int radix_multiplier, char expchar,
              char **endptr)
{
  const char *s = nptr;
  bool got_dot = false;
  long int exponent = 0;
  double num = 0;

  for (;; ++s)
    {
      int digit;
      if (c_isdigit (*s))
        digit = *s - '0';
      else if (base == 16 && c_isxdigit (*s))
        digit = c_tolower (*s) - ('a' - 10);
      else if (! got_dot && *s == '.')
        {
          /* Record that we have found the decimal point.  */
          got_dot = true;
          continue;
        }
      else
        /* Any other character terminates the number.  */
        break;

      /* Make sure that multiplication by base will not overflow.  */
      if (num <= DBL_MAX / base)
        num = num * base + digit;
      else
        {
          /* The value of the digit doesn't matter, since we have already
             gotten as many digits as can be represented in a 'double'.
             This doesn't necessarily mean the result will overflow.
             The exponent may reduce it to within range.

             We just need to record that there was another
             digit so that we can multiply by 10 later.  */
          exponent += radix_multiplier;
        }

      /* Keep track of the number of digits after the decimal point.
         If we just divided by base here, we might lose precision.  */
      if (got_dot)
        exponent -= radix_multiplier;
    }

  if (c_tolower (*s) == expchar && ! locale_isspace (s[1]))
    {
      /* Add any given exponent to the implicit one.  */
      int save = errno;
      char *end;
      long int value = strtol (s + 1, &end, 10);
      errno = save;

      if (s + 1 != end)
        {
          /* Skip past the exponent, and add in the implicit exponent,
             resulting in an extreme value on overflow.  */
          s = end;
          exponent =
            (exponent < 0
             ? (value < LONG_MIN - exponent ? LONG_MIN : exponent + value)
             : (LONG_MAX - exponent < value ? LONG_MAX : exponent + value));
        }
    }

  *endptr = (char *) s;
  return scale_radix_exp (num, radix, exponent);
}
示例#24
0
/* Convert NPTR to a double.  If ENDPTR is not NULL, a pointer to the
   character after the last one used in the number is put in *ENDPTR.  */
double
strtod (const char *nptr, char **endptr)
{
  bool negative = false;

  /* The number so far.  */
  double num;

  const char *s = nptr;
  const char *end;
  char *endbuf;
  int saved_errno;

  /* Eat whitespace.  */
  while (locale_isspace (*s))
    ++s;

  /* Get the sign.  */
  negative = *s == '-';
  if (*s == '-' || *s == '+')
    ++s;

  saved_errno = errno;
  num = underlying_strtod (s, &endbuf);
  end = endbuf;

  if (c_isdigit (s[*s == '.']))
    {
      /* If a hex float was converted incorrectly, do it ourselves.
         If the string starts with "0x" but does not contain digits,
         consume the "0" ourselves.  If a hex float is followed by a
         'p' but no exponent, then adjust the end pointer.  */
      if (*s == '0' && c_tolower (s[1]) == 'x')
        {
          if (! c_isxdigit (s[2 + (s[2] == '.')]))
            end = s + 1;
          else if (end <= s + 2)
            {
              num = parse_number (s + 2, 16, 2, 4, 'p', &endbuf);
              end = endbuf;
            }
          else
            {
              const char *p = s + 2;
              while (p < end && c_tolower (*p) != 'p')
                p++;
              if (p < end && ! c_isdigit (p[1 + (p[1] == '-' || p[1] == '+')]))
                end = p;
            }
        }
      else
        {
          /* If "1e 1" was misparsed as 10.0 instead of 1.0, re-do the
             underlying strtod on a copy of the original string
             truncated to avoid the bug.  */
          const char *e = s + 1;
          while (e < end && c_tolower (*e) != 'e')
            e++;
          if (e < end && ! c_isdigit (e[1 + (e[1] == '-' || e[1] == '+')]))
            {
              char *dup = strdup (s);
              errno = saved_errno;
              if (!dup)
                {
                  /* Not really our day, is it.  Rounding errors are
                     better than outright failure.  */
                  num = parse_number (s, 10, 10, 1, 'e', &endbuf);
                }
              else
                {
                  dup[e - s] = '\0';
                  num = underlying_strtod (dup, &endbuf);
                  saved_errno = errno;
                  free (dup);
                  errno = saved_errno;
                }
              end = e;
            }
        }

      s = end;
    }

  /* Check for infinities and NaNs.  */
  else if (c_tolower (*s) == 'i'
           && c_tolower (s[1]) == 'n'
           && c_tolower (s[2]) == 'f')
    {
      s += 3;
      if (c_tolower (*s) == 'i'
          && c_tolower (s[1]) == 'n'
          && c_tolower (s[2]) == 'i'
          && c_tolower (s[3]) == 't'
          && c_tolower (s[4]) == 'y')
        s += 5;
      num = HUGE_VAL;
      errno = saved_errno;
    }
  else if (c_tolower (*s) == 'n'
           && c_tolower (s[1]) == 'a'
           && c_tolower (s[2]) == 'n')
    {
      s += 3;
      if (*s == '(')
        {
          const char *p = s + 1;
          while (c_isalnum (*p))
            p++;
          if (*p == ')')
            s = p + 1;
        }

      /* If the underlying implementation misparsed the NaN, assume
         its result is incorrect, and return a NaN.  Normally it's
         better to use the underlying implementation's result, since a
         nice implementation populates the bits of the NaN according
         to interpreting n-char-sequence as a hexadecimal number.  */
      if (s != end)
        num = NAN;
      errno = saved_errno;
    }
  else
    {
      /* No conversion could be performed.  */
      errno = EINVAL;
      s = nptr;
    }

  if (endptr != NULL)
    *endptr = (char *) s;
  /* Special case -0.0, since at least ICC miscompiles negation.  We
     can't use copysign(), as that drags in -lm on some platforms.  */
  if (!num && negative)
    return minus_zero;
  return negative ? -num : num;
}
示例#25
0
文件: pop.c 项目: JJJollyjim/remacs
/*
 * Function: socket_connection
 *
 * Purpose: Opens the network connection with the mail host, without
 * 	doing any sort of I/O with it or anything.
 *
 * Arguments:
 * 	host	The host to which to connect.
 *	flags	Option flags.
 *
 * Return value: A file descriptor indicating the connection, or -1
 * 	indicating failure, in which case an error has been copied
 * 	into pop_error.
 */
static int
socket_connection (char *host, int flags)
{
  struct addrinfo *res, *it;
  struct addrinfo hints;
  int ret;
  struct servent *servent;
  struct sockaddr_in addr;
  char found_port = 0;
  const char *service;
  int sock;
  char *realhost;
#ifdef KERBEROS
#ifdef KERBEROS5
  krb5_error_code rem;
  krb5_context kcontext = 0;
  krb5_auth_context auth_context = 0;
  krb5_ccache ccdef;
  krb5_principal client, server;
  krb5_error *err_ret;
  register char *cp;
#else
  KTEXT ticket;
  MSG_DAT msg_data;
  CREDENTIALS cred;
  Key_schedule schedule;
  int rem;
#endif /* KERBEROS5 */
#endif /* KERBEROS */

  int try_count = 0;
  int connect_ok;

#ifdef WINDOWSNT
  {
    WSADATA winsockData;
    if (WSAStartup (0x101, &winsockData) == 0)
      have_winsock = 1;
  }
#endif

  memset (&addr, 0, sizeof (addr));
  addr.sin_family = AF_INET;

  /** "kpop" service is  never used: look for 20060515 to see why **/
#ifdef KERBEROS
  service = (flags & POP_NO_KERBEROS) ? POP_SERVICE : KPOP_SERVICE;
#else
  service = POP_SERVICE;
#endif

#ifdef HESIOD
  if (! (flags & POP_NO_HESIOD))
    {
      servent = hes_getservbyname (service, "tcp");
      if (servent)
	{
	  addr.sin_port = servent->s_port;
	  found_port = 1;
	}
    }
#endif
  if (! found_port)
    {
      servent = getservbyname (service, "tcp");
      if (servent)
	{
	  addr.sin_port = servent->s_port;
	}
      else
	{
  /** "kpop" service is  never used: look for 20060515 to see why **/
#ifdef KERBEROS
	  addr.sin_port = htons ((flags & POP_NO_KERBEROS) ?
				POP_PORT : KPOP_PORT);
#else
	  addr.sin_port = htons (POP_PORT);
#endif
	}
    }

#define POP_SOCKET_ERROR "Could not create socket for POP connection: "

  sock = socket (PF_INET, SOCK_STREAM, 0);
  if (sock < 0)
    {
      snprintf (pop_error, ERROR_MAX, "%s%s",
		POP_SOCKET_ERROR, strerror (errno));
      return (-1);

    }

  memset (&hints, 0, sizeof (hints));
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_CANONNAME;
  hints.ai_family = AF_INET;
  do
    {
      ret = getaddrinfo (host, service, &hints, &res);
      try_count++;
      if (ret != 0 && (ret != EAI_AGAIN || try_count == 5))
	{
	  strcpy (pop_error, "Could not determine POP server's address");
	  return (-1);
	}
    } while (ret != 0);

  for (it = res; it; it = it->ai_next)
    if (it->ai_addrlen == sizeof addr)
      {
	struct sockaddr_in *in_a = (struct sockaddr_in *) it->ai_addr;
	addr.sin_addr = in_a->sin_addr;
	if (! connect (sock, (struct sockaddr *) &addr, sizeof addr))
	  break;
      }
  connect_ok = it != NULL;
  if (connect_ok)
    {
      realhost = alloca (strlen (it->ai_canonname) + 1);
      strcpy (realhost, it->ai_canonname);
    }
  freeaddrinfo (res);

#define CONNECT_ERROR "Could not connect to POP server: "

  if (! connect_ok)
    {
      CLOSESOCKET (sock);
      snprintf (pop_error, ERROR_MAX, "%s%s", CONNECT_ERROR, strerror (errno));
      return (-1);

    }

#ifdef KERBEROS

#define KRB_ERROR "Kerberos error connecting to POP server: "
  if (! (flags & POP_NO_KERBEROS))
    {
#ifdef KERBEROS5
      rem = krb5_init_context (&kcontext);
      if (rem)
	{
	krb5error:
	  if (auth_context)
	    krb5_auth_con_free (kcontext, auth_context);
	  if (kcontext)
	    krb5_free_context (kcontext);
	  snprintf (pop_error, ERROR_MAX, "%s%s",
		    KRB_ERROR, error_message (rem));
	  CLOSESOCKET (sock);
	  return (-1);
	}

      rem = krb5_auth_con_init (kcontext, &auth_context);
      if (rem)
	goto krb5error;

      rem = krb5_cc_default (kcontext, &ccdef);
      if (rem)
	goto krb5error;

      rem = krb5_cc_get_principal (kcontext, ccdef, &client);
      if (rem)
	goto krb5error;

      for (cp = realhost; *cp; cp++)
	*cp = c_tolower (*cp);

      rem = krb5_sname_to_principal (kcontext, realhost,
				     POP_SERVICE, FALSE, &server);
      if (rem)
	goto krb5error;

      rem = krb5_sendauth (kcontext, &auth_context,
			   (krb5_pointer) &sock, (char *) "KPOPV1.0",
			   client, server,
			  AP_OPTS_MUTUAL_REQUIRED,
			  0,	/* no checksum */
			  0,	/* no creds, use ccache instead */
			  ccdef,
			  &err_ret,
			  0,	/* don't need subsession key */
			  0);	/* don't need reply */
      krb5_free_principal (kcontext, server);
      if (rem)
	{
	  int pop_error_len = snprintf (pop_error, ERROR_MAX, "%s%s",
					KRB_ERROR, error_message (rem));
#if defined HAVE_KRB5_ERROR_TEXT
	  if (err_ret && err_ret->text.length)
	    {
	      int errlen = err_ret->text.length;
	      snprintf (pop_error + pop_error_len, ERROR_MAX - pop_error_len,
			" [server says '%.*s']", errlen, err_ret->text.data);
	    }
#elif defined HAVE_KRB5_ERROR_E_TEXT
	  if (err_ret && err_ret->e_text && **err_ret->e_text)
	    snprintf (pop_error + pop_error_len, ERROR_MAX - pop_error_len,
		      " [server says '%s']", *err_ret->e_text);
#endif
	  if (err_ret)
	    krb5_free_error (kcontext, err_ret);
	  krb5_auth_con_free (kcontext, auth_context);
	  krb5_free_context (kcontext);

	  CLOSESOCKET (sock);
	  return (-1);
	}
#else  /* ! KERBEROS5 */
      ticket = (KTEXT) malloc (sizeof (KTEXT_ST));
      rem = krb_sendauth (0L, sock, ticket, "pop", realhost,
			  (char *) krb_realmofhost (realhost),
			  (unsigned long) 0, &msg_data, &cred, schedule,
			  (struct sockaddr_in *) 0,
			  (struct sockaddr_in *) 0,
			  "KPOPV0.1");
      free ((char *) ticket);
      if (rem != KSUCCESS)
	{
	  snprintf (pop_error, ERROR_MAX, "%s%s", KRB_ERROR, krb_err_txt[rem]);
	  CLOSESOCKET (sock);
	  return (-1);
	}
#endif /* KERBEROS5 */
    }
#endif /* KERBEROS */

  return (sock);
} /* socket_connection */
示例#26
0
/* Knuth-Morris-Pratt algorithm.
   See http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm
   Return a boolean indicating success.  */
static bool
knuth_morris_pratt (const char *haystack, const char *needle,
		    const char **resultp)
{
  size_t m = strlen (needle);

  /* Allocate the table.  */
  size_t *table = (size_t *) malloca (m * sizeof (size_t));
  if (table == NULL)
    return false;
  /* Fill the table.
     For 0 < i < m:
       0 < table[i] <= i is defined such that
       rhaystack[0..i-1] == needle[0..i-1] and rhaystack[i] != needle[i]
       implies
       forall 0 <= x < table[i]: rhaystack[x..x+m-1] != needle[0..m-1],
       and table[i] is as large as possible with this property.
     table[0] remains uninitialized.  */
  {
    size_t i, j;

    table[1] = 1;
    j = 0;
    for (i = 2; i < m; i++)
      {
	unsigned char b = c_tolower ((unsigned char) needle[i - 1]);

	for (;;)
	  {
	    if (b == c_tolower ((unsigned char) needle[j]))
	      {
		table[i] = i - ++j;
		break;
	      }
	    if (j == 0)
	      {
		table[i] = i;
		break;
	      }
	    j = j - table[j];
	  }
      }
  }

  /* Search, using the table to accelerate the processing.  */
  {
    size_t j;
    const char *rhaystack;
    const char *phaystack;

    *resultp = NULL;
    j = 0;
    rhaystack = haystack;
    phaystack = haystack;
    /* Invariant: phaystack = rhaystack + j.  */
    while (*phaystack != '\0')
      if (c_tolower ((unsigned char) needle[j])
	  == c_tolower ((unsigned char) *phaystack))
	{
	  j++;
	  phaystack++;
	  if (j == m)
	    {
	      /* The entire needle has been found.  */
	      *resultp = rhaystack;
	      break;
	    }
	}
      else if (j > 0)
	{
	  /* Found a match of needle[0..j-1], mismatch at needle[j].  */
	  rhaystack += table[j];
	  j -= table[j];
	}
      else
	{
	  /* Found a mismatch at needle[0] already.  */
	  rhaystack++;
	  phaystack++;
	}
  }

  freea (table);
  return true;
}
示例#27
0
/* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive
   comparison.
   Note: This function may, in multibyte locales, return success even if
   strlen (haystack) < strlen (needle) !  */
char *
c_strcasestr (const char *haystack, const char *needle)
{
  /* Be careful not to look at the entire extent of haystack or needle
     until needed.  This is useful because of these two cases:
       - haystack may be very long, and a match of needle found early,
       - needle may be very long, and not even a short initial segment of
         needle may be found in haystack.  */
  if (*needle != '\0')
    {
      /* Minimizing the worst-case complexity:
	 Let n = strlen(haystack), m = strlen(needle).
	 The naïve algorithm is O(n*m) worst-case.
	 The Knuth-Morris-Pratt algorithm is O(n) worst-case but it needs a
	 memory allocation.
	 To achieve linear complexity and yet amortize the cost of the memory
	 allocation, we activate the Knuth-Morris-Pratt algorithm only once
	 the naïve algorithm has already run for some time; more precisely,
	 when
	   - the outer loop count is >= 10,
	   - the average number of comparisons per outer loop is >= 5,
	   - the total number of comparisons is >= m.
	 But we try it only once.  If the memory allocation attempt failed,
	 we don't retry it.  */
      bool try_kmp = true;
      size_t outer_loop_count = 0;
      size_t comparison_count = 0;
      size_t last_ccount = 0;			/* last comparison count */
      const char *needle_last_ccount = needle;	/* = needle + last_ccount */

      /* Speed up the following searches of needle by caching its first
	 character.  */
      unsigned char b = c_tolower ((unsigned char) *needle);

      needle++;
      for (;; haystack++)
	{
	  if (*haystack == '\0')
	    /* No match.  */
	    return NULL;

	  /* See whether it's advisable to use an asymptotically faster
	     algorithm.  */
	  if (try_kmp
	      && outer_loop_count >= 10
	      && comparison_count >= 5 * outer_loop_count)
	    {
	      /* See if needle + comparison_count now reaches the end of
		 needle.  */
	      if (needle_last_ccount != NULL)
		{
		  needle_last_ccount +=
		    strnlen (needle_last_ccount, comparison_count - last_ccount);
		  if (*needle_last_ccount == '\0')
		    needle_last_ccount = NULL;
		  last_ccount = comparison_count;
		}
	      if (needle_last_ccount == NULL)
		{
		  /* Try the Knuth-Morris-Pratt algorithm.  */
		  const char *result;
		  bool success =
		    knuth_morris_pratt (haystack, needle - 1, &result);
		  if (success)
		    return (char *) result;
		  try_kmp = false;
		}
	    }

	  outer_loop_count++;
	  comparison_count++;
	  if (c_tolower ((unsigned char) *haystack) == b)
	    /* The first character matches.  */
	    {
	      const char *rhaystack = haystack + 1;
	      const char *rneedle = needle;

	      for (;; rhaystack++, rneedle++)
		{
		  if (*rneedle == '\0')
		    /* Found a match.  */
		    return (char *) haystack;
		  if (*rhaystack == '\0')
		    /* No match.  */
		    return NULL;
		  comparison_count++;
		  if (c_tolower ((unsigned char) *rhaystack)
		      != c_tolower ((unsigned char) *rneedle))
		    /* Nothing in this round.  */
		    break;
		}
	    }
	}
    }
  else
    return (char *) haystack;
}
示例#28
0
static void
test_all (void)
{
  int c;

  for (c = -0x80; c < 0x100; c++)
    {
      ASSERT (c_isascii (c) == (c >= 0 && c < 0x80));

      switch (c)
        {
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
        case 'Y': case 'Z':
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
        case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
        case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
        case 's': case 't': case 'u': case 'v': case 'w': case 'x':
        case 'y': case 'z':
        case '0': case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9':
          ASSERT (c_isalnum (c) == 1);
          break;
        default:
          ASSERT (c_isalnum (c) == 0);
          break;
        }

      switch (c)
        {
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
        case 'Y': case 'Z':
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
        case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
        case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
        case 's': case 't': case 'u': case 'v': case 'w': case 'x':
        case 'y': case 'z':
          ASSERT (c_isalpha (c) == 1);
          break;
        default:
          ASSERT (c_isalpha (c) == 0);
          break;
        }

      switch (c)
        {
        case '\t': case ' ':
          ASSERT (c_isblank (c) == 1);
          break;
        default:
          ASSERT (c_isblank (c) == 0);
          break;
        }

      ASSERT (c_iscntrl (c) == ((c >= 0 && c < 0x20) || c == 0x7f));

      switch (c)
        {
        case '0': case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9':
          ASSERT (c_isdigit (c) == 1);
          break;
        default:
          ASSERT (c_isdigit (c) == 0);
          break;
        }

      switch (c)
        {
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
        case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
        case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
        case 's': case 't': case 'u': case 'v': case 'w': case 'x':
        case 'y': case 'z':
          ASSERT (c_islower (c) == 1);
          break;
        default:
          ASSERT (c_islower (c) == 0);
          break;
        }

      ASSERT (c_isgraph (c) == ((c >= 0x20 && c < 0x7f) && c != ' '));

      ASSERT (c_isprint (c) == (c >= 0x20 && c < 0x7f));

      ASSERT (c_ispunct (c) == (c_isgraph (c) && !c_isalnum (c)));

      switch (c)
        {
        case ' ': case '\t': case '\n': case '\v': case '\f': case '\r':
          ASSERT (c_isspace (c) == 1);
          break;
        default:
          ASSERT (c_isspace (c) == 0);
          break;
        }

      switch (c)
        {
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
        case 'Y': case 'Z':
          ASSERT (c_isupper (c) == 1);
          break;
        default:
          ASSERT (c_isupper (c) == 0);
          break;
        }

      switch (c)
        {
        case '0': case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9':
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
          ASSERT (c_isxdigit (c) == 1);
          break;
        default:
          ASSERT (c_isxdigit (c) == 0);
          break;
        }

      switch (c)
        {
        case 'A':
          ASSERT (c_tolower (c) == 'a');
          ASSERT (c_toupper (c) == c);
          break;
        case 'B':
          ASSERT (c_tolower (c) == 'b');
          ASSERT (c_toupper (c) == c);
          break;
        case 'C':
          ASSERT (c_tolower (c) == 'c');
          ASSERT (c_toupper (c) == c);
          break;
        case 'D':
          ASSERT (c_tolower (c) == 'd');
          ASSERT (c_toupper (c) == c);
          break;
        case 'E':
          ASSERT (c_tolower (c) == 'e');
          ASSERT (c_toupper (c) == c);
          break;
        case 'F':
          ASSERT (c_tolower (c) == 'f');
          ASSERT (c_toupper (c) == c);
          break;
        case 'G':
          ASSERT (c_tolower (c) == 'g');
          ASSERT (c_toupper (c) == c);
          break;
        case 'H':
          ASSERT (c_tolower (c) == 'h');
          ASSERT (c_toupper (c) == c);
          break;
        case 'I':
          ASSERT (c_tolower (c) == 'i');
          ASSERT (c_toupper (c) == c);
          break;
        case 'J':
          ASSERT (c_tolower (c) == 'j');
          ASSERT (c_toupper (c) == c);
          break;
        case 'K':
          ASSERT (c_tolower (c) == 'k');
          ASSERT (c_toupper (c) == c);
          break;
        case 'L':
          ASSERT (c_tolower (c) == 'l');
          ASSERT (c_toupper (c) == c);
          break;
        case 'M':
          ASSERT (c_tolower (c) == 'm');
          ASSERT (c_toupper (c) == c);
          break;
        case 'N':
          ASSERT (c_tolower (c) == 'n');
          ASSERT (c_toupper (c) == c);
          break;
        case 'O':
          ASSERT (c_tolower (c) == 'o');
          ASSERT (c_toupper (c) == c);
          break;
        case 'P':
          ASSERT (c_tolower (c) == 'p');
          ASSERT (c_toupper (c) == c);
          break;
        case 'Q':
          ASSERT (c_tolower (c) == 'q');
          ASSERT (c_toupper (c) == c);
          break;
        case 'R':
          ASSERT (c_tolower (c) == 'r');
          ASSERT (c_toupper (c) == c);
          break;
        case 'S':
          ASSERT (c_tolower (c) == 's');
          ASSERT (c_toupper (c) == c);
          break;
        case 'T':
          ASSERT (c_tolower (c) == 't');
          ASSERT (c_toupper (c) == c);
          break;
        case 'U':
          ASSERT (c_tolower (c) == 'u');
          ASSERT (c_toupper (c) == c);
          break;
        case 'V':
          ASSERT (c_tolower (c) == 'v');
          ASSERT (c_toupper (c) == c);
          break;
        case 'W':
          ASSERT (c_tolower (c) == 'w');
          ASSERT (c_toupper (c) == c);
          break;
        case 'X':
          ASSERT (c_tolower (c) == 'x');
          ASSERT (c_toupper (c) == c);
          break;
        case 'Y':
          ASSERT (c_tolower (c) == 'y');
          ASSERT (c_toupper (c) == c);
          break;
        case 'Z':
          ASSERT (c_tolower (c) == 'z');
          ASSERT (c_toupper (c) == c);
          break;
        case 'a':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'A');
          break;
        case 'b':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'B');
          break;
        case 'c':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'C');
          break;
        case 'd':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'D');
          break;
        case 'e':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'E');
          break;
        case 'f':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'F');
          break;
        case 'g':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'G');
          break;
        case 'h':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'H');
          break;
        case 'i':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'I');
          break;
        case 'j':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'J');
          break;
        case 'k':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'K');
          break;
        case 'l':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'L');
          break;
        case 'm':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'M');
          break;
        case 'n':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'N');
          break;
        case 'o':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'O');
          break;
        case 'p':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'P');
          break;
        case 'q':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'Q');
          break;
        case 'r':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'R');
          break;
        case 's':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'S');
          break;
        case 't':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'T');
          break;
        case 'u':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'U');
          break;
        case 'v':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'V');
          break;
        case 'w':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'W');
          break;
        case 'x':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'X');
          break;
        case 'y':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'Y');
          break;
        case 'z':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'Z');
          break;
        default:
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == c);
          break;
        }
    }
}
示例#29
0
void fx_Date_parse(txMachine* the)
{
	#define mxDayCount 7
	static char* gxDays[mxDayCount] = {
		"monday", 
		"tuesday", 
		"wednesday", 
		"thursday", 
		"friday",
		"saturday", 
		"sunday"
	};
	#define mxMonthCount 12
	static char* gxMonths[mxMonthCount] = {
		"january",
		"february",
		"march",
		"april",
		"may",
		"june",
		"july",
		"august",
		"september",
		"october",
		"november",
		"december"
	};
	#define mxZoneCount 11
	static char* gxZones[mxZoneCount] = {
		"gmt", "ut", "utc",
		"est", "edt",
		"cst", "cdt",
		"mst", "mdt",
		"pst", "pdt"
	};
	static int gxDeltas[mxZoneCount] = {
		0, 0, 0,
		-5, -4,
		-6, -5,
		-7, -6,
		-8, -7
	};
	
	txString aString;
	txTimeDescription td;
	txString p;
	txString q;
	txByte c;
	char buffer[10];	/* base type should be the same as txString */
	txInteger aComment;
	txInteger aDelta;
	txInteger aValue;
	txInteger aLength;
	txInteger i;
	c_time_t time;
	txNumber number;
	txInteger hasSlash = 0;
		
	if (mxArgc < 1)
		goto fail;
	aString = fxToString(the, mxArgv(0));
	
	td.tm.tm_sec = -1;
	td.tm.tm_min = -1;
	td.tm.tm_hour = -1;
	td.tm.tm_mday = -1;
	td.tm.tm_mon = -1;
	td.tm.tm_year = -1;
	td.ms = 0;
	aComment = 0;
	aDelta = -1;
	
	c = *aString++;
	while (c) {
		if (c == '(') {
			aComment++;
			c = *aString++;
			continue;
		}
		else if (c == ')') {
			if (aComment) {
				aComment--;
				c = *aString++;
				continue;
			}
			else
				goto fail;
		}
		else if (aComment) {
			c = *aString++;
			continue;
		}	
		
		if ((c <= ' ') || (c == ',')) {
			c = *aString++;
			continue;
		}
			
		else if ((c == '-') | (c == '+')) {
            txInteger aSign;
			if ((aDelta != 0) && (aDelta != -1))
				goto fail;
			if (c == '-')	
				aSign = -1;
			else
				aSign = 1;
			c = *aString++;
			if (('0' <= c) && (c <= '9')) {
				aValue = fx_Date_parse_number(&c, &aString);
				if (c == ':') {
					aDelta = 60 * aValue;
					c = *aString++;
					if (('0' <= c) && (c <= '9')) {
						aDelta += fx_Date_parse_number(&c, &aString);
					}
				}
				else {
					if (aValue < 24)
						aDelta = aValue * 60;
					else
						aDelta = (aValue % 100) + ((aValue / 100) * 60);
				}
			}
			else
				goto fail;
			aDelta *= aSign;
		}		
		else if (('0' <= c) && (c <= '9')) {
			aValue = fx_Date_parse_number(&c, &aString);
			if (c == ':') {
				if (td.tm.tm_hour >= 0) 
					goto fail;
				td.tm.tm_hour = aValue;	
				c = *aString++;
				if (('0' <= c) && (c <= '9')) {
					td.tm.tm_min = fx_Date_parse_number(&c, &aString);
					if (c == ':') {
						c = *aString++;
						if (('0' <= c) && (c <= '9')) {
							td.tm.tm_sec = fx_Date_parse_number(&c, &aString);
							if (c == '.') {
								c = *aString++;
								if (('0' <= c) && (c <= '9')) {
									td.ms = fx_Date_parse_fraction(&c, &aString);
								}
							}
						}
						else
							td.tm.tm_sec = 0;
					}
				}
				else
					td.tm.tm_sec = 0;
			}
			else if (c == '/') {
				if (td.tm.tm_year >= 0) 
					goto fail;
				td.tm.tm_year = (aValue < 100) ? aValue : aValue - 1900;
				c = *aString++;
				if (('0' <= c) && (c <= '9')) {
					td.tm.tm_mon = fx_Date_parse_number(&c, &aString) - 1;
					if (c == '/') {
						c = *aString++;
						if (('0' <= c) && (c <= '9')) {
							td.tm.tm_mday = fx_Date_parse_number(&c, &aString);
							hasSlash = 1;
						}
						else
							td.tm.tm_mday = 1;
					}
				}
				else
					td.tm.tm_mon = 0;
			}
			else if (c == '-') {
				if (td.tm.tm_year >= 0) 
					goto fail;
				td.tm.tm_year = (aValue < 100) ? aValue : aValue - 1900;
				c = *aString++;
				if (('0' <= c) && (c <= '9')) {
					td.tm.tm_mon = fx_Date_parse_number(&c, &aString) - 1;
					if (c == '-') {
						c = *aString++;
						if (('0' <= c) && (c <= '9'))
							td.tm.tm_mday = fx_Date_parse_number(&c, &aString);
						else
							td.tm.tm_mday = 1;
					}
				}
				else
					td.tm.tm_mon = 0;
			}
			else {
				if (aValue < 70) {
					if (td.tm.tm_mday < 0)
						td.tm.tm_mday = aValue;
					else
						goto fail;
				}
				else {
					if (td.tm.tm_year < 0)
						td.tm.tm_year = (aValue < 100) ? aValue : aValue - 1900;
					else
						goto fail;
				}
			}
		}				
		else if ((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'))) {
			txInteger	cmpLength;
			p = buffer;
			q = p + sizeof(buffer) - 1;
			do {
				if (p == q) goto fail;
				*p++ = c_tolower(c);
				c = *aString++;
			} while ((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')));
			*p = 0;
			aLength = p - (txString)buffer;
			cmpLength = (aLength >=3)? aLength: 3;
			if (c_strcmp("am", buffer) == 0) {
				if ((td.tm.tm_hour < 0) || (12 <  td.tm.tm_hour))
					goto fail;
				if (td.tm.tm_hour == 12)
					td.tm.tm_hour = 0;
				continue;
			}
			if (c_strcmp("pm", buffer) == 0) {
				if ((td.tm.tm_hour < 0) || (12 <  td.tm.tm_hour))
					goto fail;
				if (td.tm.tm_hour != 12)
					td.tm.tm_hour += 12;
				continue;
			}
			for (i = 0; i < mxDayCount; i++)
				if (c_strncmp(gxDays[i], buffer, cmpLength) == 0)
					break;
			if (i < mxDayCount)
				continue;
			for (i = 0; i < mxMonthCount; i++)
				if (c_strncmp(gxMonths[i], buffer, cmpLength) == 0)
					break;
			if (i < mxMonthCount) {
				if (td.tm.tm_mon < 0) {
					td.tm.tm_mon = i;
					continue;
				}
				else
					goto fail;
			}
			for (i = 0; i < mxZoneCount; i++)
				if (c_strcmp(gxZones[i], buffer) == 0)
					break;
			if (i < mxZoneCount) {
				if (aDelta == -1) {
					aDelta = gxDeltas[i] * 60;
					continue;
				}
				else
					goto fail;
			}
			if (c_strcmp("t", buffer) == 0) {
				if (td.tm.tm_year < 0) 
					goto fail;
				continue;
			}
			if (c_strcmp("z", buffer) == 0) {
				if (td.tm.tm_hour < 0) 
					goto fail;
				aDelta = 0;
				continue;
			}
			goto fail;
		}
		else
			goto fail;
	}
	if (td.tm.tm_year < 0)
		goto fail;
	if (td.tm.tm_mon < 0)
		goto fail;
	if (td.tm.tm_mday < 0)
		td.tm.tm_mday = 1;
	if (td.tm.tm_hour < 0)
		td.tm.tm_hour = 0;
	if (td.tm.tm_min < 0)
		td.tm.tm_min = 0;
	if (td.tm.tm_sec < 0)
		td.tm.tm_sec = 0;
	if (aDelta != -1)
		td.tm.tm_isdst = 0;
	else
		td.tm.tm_isdst = -1;
	// Check "30/3/1999" format
	if (hasSlash) {
    	if ((td.tm.tm_year < 32) && (td.tm.tm_mday >= 32)) {
        	hasSlash = td.tm.tm_year;
        	td.tm.tm_year = (td.tm.tm_mday < 100) ? td.tm.tm_mday : td.tm.tm_mday - 1900;
        	td.tm.tm_mday = hasSlash;
    	}
	}
	
	time = c_mktime(&(td.tm));	
	if (time == -1) {
		// Check again for real NaN : 1969-12-31T23:59:59:999 (ecma/Date/15.9.4.2.js)
		td.tm.tm_sec = 0;
		time = c_mktime(&(td.tm));
		if(-60 == time) {
			number = -1000.0;
			if (aDelta != -1) {
				number -= gxDeltaTime;
				number -= (txNumber)aDelta * 60000.0;
			}
		}
		else
			number = NAN;
	}
	else {
		number = (time * 1000.0);
		if (aDelta != -1) {
			number -= gxDeltaTime;
			number -= (txNumber)aDelta * 60000.0;
		}
	}
	number += td.ms;
	mxResult->value.number = number;
	mxResult->kind = XS_NUMBER_KIND;
	return;
fail:
	mxResult->value.number = C_NAN;
	mxResult->kind = XS_NUMBER_KIND;
	//mxSyntaxError("invalid parameter");
}