}
/**
- * simple_strtoul - convert a string to an unsigned long
+ * simple_strtoull - convert a string to an unsigned long long
* @cp: The start of the string
* @endp: A pointer to the end of the parsed string will be placed here
* @base: The number base to use
*/
-unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
+unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
{
- unsigned long result = 0;
+ unsigned long long result = 0;
if (!base)
base = simple_guess_base(cp);
return result;
}
-EXPORT_SYMBOL(simple_strtoul);
+EXPORT_SYMBOL(simple_strtoull);
/**
- * simple_strtol - convert a string to a signed long
+ * simple_strtoul - convert a string to an unsigned long
* @cp: The start of the string
* @endp: A pointer to the end of the parsed string will be placed here
* @base: The number base to use
*/
-long simple_strtol(const char *cp, char **endp, unsigned int base)
+unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
{
- if (*cp == '-')
- return -simple_strtoul(cp + 1, endp, base);
-
- return simple_strtoul(cp, endp, base);
+ return simple_strtoull(cp, endp, base);
}
-EXPORT_SYMBOL(simple_strtol);
+EXPORT_SYMBOL(simple_strtoul);
/**
- * simple_strtoull - convert a string to an unsigned long long
+ * simple_strtol - convert a string to a signed long
* @cp: The start of the string
* @endp: A pointer to the end of the parsed string will be placed here
* @base: The number base to use
*/
-unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
+long simple_strtol(const char *cp, char **endp, unsigned int base)
{
- unsigned long long result = 0;
-
- if (!base)
- base = simple_guess_base(cp);
-
- if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
- cp += 2;
-
- while (isxdigit(*cp)) {
- unsigned int value;
-
- value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
- if (value >= base)
- break;
- result = result * base + value;
- cp++;
- }
- if (endp)
- *endp = (char *)cp;
+ if (*cp == '-')
+ return -simple_strtoul(cp + 1, endp, base);
- return result;
+ return simple_strtoul(cp, endp, base);
}
-EXPORT_SYMBOL(simple_strtoull);
+EXPORT_SYMBOL(simple_strtol);
/**
* simple_strtoll - convert a string to a signed long long
char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
char *p = mac_addr;
int i;
+ char separator;
+
+ if (fmt[1] == 'F') { /* FDDI canonical format */
+ separator = '-';
+ } else {
+ separator = ':';
+ }
for (i = 0; i < 6; i++) {
p = pack_hex_byte(p, addr[i]);
if (fmt[0] == 'M' && i != 5)
- *p++ = ':';
+ *p++ = separator;
}
*p = '\0';
return string(buf, end, mac_addr, spec);
}
-static char *ip4_string(char *p, const u8 *addr, bool leading_zeros)
+static char *ip4_string(char *p, const u8 *addr, const char *fmt)
{
int i;
-
+ bool leading_zeros = (fmt[0] == 'i');
+ int index;
+ int step;
+
+ switch (fmt[2]) {
+ case 'h':
+#ifdef __BIG_ENDIAN
+ index = 0;
+ step = 1;
+#else
+ index = 3;
+ step = -1;
+#endif
+ break;
+ case 'l':
+ index = 3;
+ step = -1;
+ break;
+ case 'n':
+ case 'b':
+ default:
+ index = 0;
+ step = 1;
+ break;
+ }
for (i = 0; i < 4; i++) {
char temp[3]; /* hold each IP quad in reverse order */
- int digits = put_dec_trunc(temp, addr[i]) - temp;
+ int digits = put_dec_trunc(temp, addr[index]) - temp;
if (leading_zeros) {
if (digits < 3)
*p++ = '0';
*p++ = temp[digits];
if (i < 3)
*p++ = '.';
+ index += step;
}
*p = '\0';
if (useIPv4) {
if (needcolon)
*p++ = ':';
- p = ip4_string(p, &in6.s6_addr[12], false);
+ p = ip4_string(p, &in6.s6_addr[12], "I4");
}
*p = '\0';
{
char ip4_addr[sizeof("255.255.255.255")];
- ip4_string(ip4_addr, addr, fmt[0] == 'i');
+ ip4_string(ip4_addr, addr, fmt);
return string(buf, end, ip4_addr, spec);
}
+static char *uuid_string(char *buf, char *end, const u8 *addr,
+ struct printf_spec spec, const char *fmt)
+{
+ char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
+ char *p = uuid;
+ int i;
+ static const u8 be[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ static const u8 le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
+ const u8 *index = be;
+ bool uc = false;
+
+ switch (*(++fmt)) {
+ case 'L':
+ uc = true; /* fall-through */
+ case 'l':
+ index = le;
+ break;
+ case 'B':
+ uc = true;
+ break;
+ }
+
+ for (i = 0; i < 16; i++) {
+ p = pack_hex_byte(p, addr[index[i]]);
+ switch (i) {
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ *p++ = '-';
+ break;
+ }
+ }
+
+ *p = 0;
+
+ if (uc) {
+ p = uuid;
+ do {
+ *p = toupper(*p);
+ } while (*(++p));
+ }
+
+ return string(buf, end, uuid, spec);
+}
+
/*
* Show a '%p' thing. A kernel extension is that the '%p' is followed
* by an extra set of alphanumeric characters that are extended format
* - 'M' For a 6-byte MAC address, it prints the address in the
* usual colon-separated hex notation
* - 'm' For a 6-byte MAC address, it prints the hex address without colons
+ * - 'MF' For a 6-byte MAC FDDI address, it prints the address
+ * with a dash-separated hex notation
* - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
* IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
* IPv6 uses colon separated network-order 16 bit hex with leading 0's
* - 'i' [46] for 'raw' IPv4/IPv6 addresses
* IPv6 omits the colons (01020304...0f)
* IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
+ * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order
* - 'I6c' for IPv6 addresses printed as specified by
- * http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
+ * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
+ * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
+ * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+ * Options for %pU are:
+ * b big endian lower case hex (default)
+ * B big endian UPPER case hex
+ * l little endian lower case hex
+ * L little endian UPPER case hex
+ * big endian output byte order is:
+ * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15]
+ * little endian output byte order is:
+ * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15]
+ *
* Note: The difference between 'S' and 'F' is that on ia64 and ppc64
* function pointers are really function descriptors, which contain a
* pointer to the real address.
case 'f':
ptr = dereference_function_descriptor(ptr);
/* Fallthrough */
- case 's':
case 'S':
+ case 's':
return symbol_string(buf, end, ptr, spec, *fmt);
case 'R':
case 'r':
return resource_string(buf, end, ptr, spec, fmt);
case 'M': /* Colon separated: 00:01:02:03:04:05 */
case 'm': /* Contiguous: 000102030405 */
+ /* [mM]F (FDDI, bit reversed) */
return mac_address_string(buf, end, ptr, spec, fmt);
case 'I': /* Formatted IP supported
* 4: 1.2.3.4
return ip4_addr_string(buf, end, ptr, spec, fmt);
}
break;
+ case 'U':
+ return uuid_string(buf, end, ptr, spec, fmt);
}
spec.flags |= SMALL;
if (spec.field_width == -1) {
* %ps output the name of a text symbol without offset
* %pF output the name of a function pointer with its offset
* %pf output the name of a function pointer without its offset
- * %pR output the address range in a struct resource
+ * %pR output the address range in a struct resource with decoded flags
+ * %pr output the address range in a struct resource with raw flags
+ * %pM output a 6-byte MAC address with colons
+ * %pm output a 6-byte MAC address without colons
+ * %pI4 print an IPv4 address without leading zeros
+ * %pi4 print an IPv4 address with leading zeros
+ * %pI6 print an IPv6 address with colons
+ * %pi6 print an IPv6 address without colons
+ * %pI6c print an IPv6 address as specified by
+ * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
+ * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
+ * case.
* %n is ignored
*
* The return value is the number of characters which would
#endif /* CONFIG_BINARY_PRINTF */
-static noinline char *skip_space(const char *str)
-{
- while (isspace(*str))
- ++str;
- return (char *)str;
-}
-
/**
* vsscanf - Unformat a buffer into a list of arguments
* @buf: input buffer
* white space, including none, in the input.
*/
if (isspace(*fmt)) {
- fmt = skip_space(fmt);
- str = skip_space(str);
+ fmt = skip_spaces(++fmt);
+ str = skip_spaces(str);
}
/* anything that is not a conversion must match exactly */
if (field_width == -1)
field_width = INT_MAX;
/* first, skip leading white space in buffer */
- str = skip_space(str);
+ str = skip_spaces(str);
/* now copy until next white space */
while (*str && !isspace(*str) && field_width--)
/* have some sort of integer conversion.
* first, skip white space in buffer.
*/
- str = skip_space(str);
+ str = skip_spaces(str);
digit = *str;
if (is_sign && digit == '-')