static int findWord(const char *zText, const char **pzWordStart, const char **pzWordEnd){ int r; while( ascii_isspace(*zText) ){ zText++; } *pzWordStart = zText; while( ascii_isalnum(*zText) || *zText=='_' ){ zText++; } r = zText>*pzWordStart; *pzWordEnd = zText; return r; }
static void collect_data (char *hexdata, const char *address, unsigned int lineno) { size_t length; int is_bi; char *s; unsigned int value; is_bi = (*address && address[1] == 'i'); if (databuffer.is_bi != is_bi || strcmp (databuffer.address, address)) flush_data (); databuffer.is_bi = is_bi; if (strlen (address) >= sizeof databuffer.address) die ("address field too long"); strcpy (databuffer.address, address); length = databuffer.count; for (s=hexdata; *s; s++ ) { if (ascii_isspace (*s)) continue; if (!hexdigitp (*s)) { err ("invalid hex digit in line %u - line skipped", lineno); break; } value = xtoi_1 (*s) * 16; s++; if (!hexdigitp (*s)) { err ("invalid hex digit in line %u - line skipped", lineno); break; } value += xtoi_1 (*s); if (length >= sizeof (databuffer.data)) { err ("too much data at line %u - can handle only up to % bytes", lineno, sizeof (databuffer.data)); break; } databuffer.data[length++] = value; } databuffer.count = length; }
/* * Convert a string to an unsigned long long integer. * * Assumes that the upper and lower case * alphabets and digits are each contiguous. */ unsigned long long qt_strtoull(const char * nptr, char **endptr, int base) { const char *s; unsigned long long acc; char c; unsigned long long cutoff; int neg, any, cutlim; /* * See strtoq for comments as to the logic used. */ s = nptr; do { c = *s++; } while (ascii_isspace(c)); if (c == '-') { neg = 1; c = *s++; } else { neg = 0; if (c == '+') c = *s++; } if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X') && ((s[1] >= '0' && s[1] <= '9') || (s[1] >= 'A' && s[1] <= 'F') || (s[1] >= 'a' && s[1] <= 'f'))) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; acc = any = 0; if (base < 2 || base > 36) goto noconv; cutoff = ULLONG_MAX / base; cutlim = ULLONG_MAX % base; for ( ; ; c = *s++) { if (c >= '0' && c <= '9') c -= '0'; else if (c >= 'A' && c <= 'Z') c -= 'A' - 10; else if (c >= 'a' && c <= 'z') c -= 'a' - 10; else break; if (c >= base) break; if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) any = -1; else { any = 1; acc *= base; acc += c; } } if (any < 0) { acc = ULLONG_MAX; errno = ERANGE; } else if (!any) { noconv: errno = EINVAL; } else if (neg) acc = (unsigned long long) -(long long)acc; if (endptr != NULL) *endptr = const_cast<char *>(any ? s - 1 : nptr); return (acc); }
/* * Convert a string to a long long integer. * * Assumes that the upper and lower case * alphabets and digits are each contiguous. */ long long qt_strtoll(const char * nptr, char **endptr, int base) { const char *s; unsigned long long acc; char c; unsigned long long cutoff; int neg, any, cutlim; /* * Skip white space and pick up leading +/- sign if any. * If base is 0, allow 0x for hex and 0 for octal, else * assume decimal; if base is already 16, allow 0x. */ s = nptr; do { c = *s++; } while (ascii_isspace(c)); if (c == '-') { neg = 1; c = *s++; } else { neg = 0; if (c == '+') c = *s++; } if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X') && ((s[1] >= '0' && s[1] <= '9') || (s[1] >= 'A' && s[1] <= 'F') || (s[1] >= 'a' && s[1] <= 'f'))) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; acc = any = 0; if (base < 2 || base > 36) goto noconv; /* * Compute the cutoff value between legal numbers and illegal * numbers. That is the largest legal value, divided by the * base. An input number that is greater than this value, if * followed by a legal input character, is too big. One that * is equal to this value may be valid or not; the limit * between valid and invalid numbers is then based on the last * digit. For instance, if the range for quads is * [-9223372036854775808..9223372036854775807] and the input base * is 10, cutoff will be set to 922337203685477580 and cutlim to * either 7 (neg==0) or 8 (neg==1), meaning that if we have * accumulated a value > 922337203685477580, or equal but the * next digit is > 7 (or 8), the number is too big, and we will * return a range error. * * Set 'any' if any `digits' consumed; make it negative to indicate * overflow. */ cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX : LLONG_MAX; cutlim = cutoff % base; cutoff /= base; for ( ; ; c = *s++) { if (c >= '0' && c <= '9') c -= '0'; else if (c >= 'A' && c <= 'Z') c -= 'A' - 10; else if (c >= 'a' && c <= 'z') c -= 'a' - 10; else break; if (c >= base) break; if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) any = -1; else { any = 1; acc *= base; acc += c; } } if (any < 0) { acc = neg ? LLONG_MIN : LLONG_MAX; errno = ERANGE; } else if (!any) { noconv: errno = EINVAL; } else if (neg) acc = (unsigned long long) -(long long)acc; if (endptr != NULL) *endptr = const_cast<char *>(any ? s - 1 : nptr); return (acc); }
/* Take a time string and convert it into an ebus style time. Ebus time is the number of 10 second intervals since Monday 0:00 local time. (uint16_t)(-1) is returned on error. Supported formats are: hh:mm[:sx] - Hour, minute and 10 seconds on Monday w hh:mm[:sx] - Ditto with weekday specified ndhh:mm[:sx] - Ditto with weekday give as Monday (0) to Sunday (6) with hh = Hour mm = Minutes sx = Seconds with the lower digit ignored w = Weekday name (mo,tu,we,th,fr,sa,su) or (mon,tue,wed,thu,fri,sat,sun) in any capitalization. */ uint16_t timestr_to_ebustime (char const *string, char **r_endp) { int i, n; int weekday = 0; int hour = 0; int minute = 0; int second = 0; char const *s; char *endp; if (!string) return INVALID_TIME; for (; *string && ascii_isspace (*string); string++) ; if (*string >= '0' && *string <= '6' && string[1] == 'd') { weekday = *string - '0'; string += 2; } else if ((*string >= 'a' && *string < 'z') || (*string >= 'A' && *string < 'Z')) { static struct { char no; char const * const name; } tbl[] = { { 0, "mo" }, { 0, "mon" }, { 0, "monday" }, { 1, "tu" }, { 1, "tue" }, { 1, "tuesday" }, { 2, "we" }, { 2, "wed" }, { 2, "wednesday" }, { 3, "th" }, { 3, "thu" }, { 3, "thursday" }, { 4, "fr" }, { 4, "fri" }, { 4, "friday" }, { 5, "sa" }, { 5, "sat" }, { 5, "saturday" }, { 6, "su" }, { 6, "sun" }, { 6, "sunday" }}; for (s=string+1; *s; s++) if (ascii_isspace (*s)) break; n = s - string; for (i=0; i < DIM (tbl); i++) if (strlen (tbl[i].name) == n && !ascii_strncasecmp (string, tbl[i].name, n)) break; if (!(i < DIM (tbl))) return INVALID_TIME; weekday = tbl[i].no; for (; *s && ascii_isspace (*s); s++) ; string = s; } if (!digitp (string)) return INVALID_TIME; hour = strtol (string, &endp, 10); if (hour < 0 || hour > 23 || *endp != ':') return INVALID_TIME; string = endp + 1; minute = strtol (string, &endp, 10); if (!digitp (string) || !digitp (string+1) || minute < 0 || minute > 59) return INVALID_TIME; if (*endp == ':') { string = endp + 1; second = strtol (string, &endp, 10); /* Note: We don't care about leap seconds. */ if (!digitp (string) || !digitp (string+1) || second < 0 || second > 59) return INVALID_TIME; } if (!*endp) string = endp; else if (ascii_isspace (*endp)) string = endp + 1; else return INVALID_TIME; if (r_endp) *r_endp = (char *)string; return (weekday * 24 * 60 * 6 + hour * 60 * 6 + minute * 6 + second / 10); }
/* Calls strtod in a locale-independent fashion, by looking at * the locale data and patching the decimal comma to a point. * * Relicensed from glib. */ static double ascii_strtod (const char *nptr, char **endptr) { /* FIXME: The Win32 C library's strtod() doesn't handle hex. * Presumably many Unixes don't either. */ char *fail_pos; double val; struct lconv *locale_data; const char *decimal_point; int decimal_point_len; const char *p, *decimal_point_pos; const char *end = NULL; /* Silence gcc */ fail_pos = NULL; locale_data = localeconv (); decimal_point = locale_data->decimal_point; decimal_point_len = strlen (decimal_point); _dbus_assert (decimal_point_len != 0); decimal_point_pos = NULL; if (decimal_point[0] != '.' || decimal_point[1] != 0) { p = nptr; /* Skip leading space */ while (ascii_isspace (*p)) p++; /* Skip leading optional sign */ if (*p == '+' || *p == '-') p++; if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { p += 2; /* HEX - find the (optional) decimal point */ while (ascii_isxdigit (*p)) p++; if (*p == '.') { decimal_point_pos = p++; while (ascii_isxdigit (*p)) p++; if (*p == 'p' || *p == 'P') p++; if (*p == '+' || *p == '-') p++; while (ascii_isdigit (*p)) p++; end = p; } } else { while (ascii_isdigit (*p)) p++; if (*p == '.') { decimal_point_pos = p++; while (ascii_isdigit (*p)) p++; if (*p == 'e' || *p == 'E') p++; if (*p == '+' || *p == '-') p++; while (ascii_isdigit (*p)) p++; end = p; } } /* For the other cases, we need not convert the decimal point */ } /* Set errno to zero, so that we can distinguish zero results and underflows */ errno = 0; if (decimal_point_pos) { char *copy, *c; /* We need to convert the '.' to the locale specific decimal point */ copy = dbus_malloc (end - nptr + 1 + decimal_point_len); c = copy; memcpy (c, nptr, decimal_point_pos - nptr); c += decimal_point_pos - nptr; memcpy (c, decimal_point, decimal_point_len); c += decimal_point_len; memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1)); c += end - (decimal_point_pos + 1); *c = 0; val = strtod (copy, &fail_pos); if (fail_pos) { if (fail_pos > decimal_point_pos) fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1); else fail_pos = (char *)nptr + (fail_pos - copy); } dbus_free (copy); } else val = strtod (nptr, &fail_pos); if (endptr) *endptr = fail_pos; return val; }