summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-12-22 01:01:40 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-12-22 01:01:40 +0000
commit4274e516239b34c5cd9ea2c60c11802e28244c99 (patch)
tree4fa9f8d784803d3927757f7eaa6e95ad5ae5ca5e
parentc6df9c945232b76340e298946b51684441f549fc (diff)
docs/defines.txt: document _extern_inline
libc/inet/ether_addr.c: optimize tolower, we ever use it on 0-9a-f libc/inet/ntop.c: optimize tolower, we ever use it on 0-9a-f with locale support on, code size change is: text data bss dec hex filename - 396 0 24 420 1a4 libc/inet/ether_addr.os + 306 0 24 330 14a libc/inet/ether_addr.os - 1453 0 0 1453 5ad libc/inet/ntop.os + 1430 0 0 1430 596 libc/inet/ntop.os
-rw-r--r--docs/defines.txt7
-rw-r--r--libc/inet/ether_addr.c52
-rw-r--r--libc/inet/ntop.c86
3 files changed, 70 insertions, 75 deletions
diff --git a/docs/defines.txt b/docs/defines.txt
index 677335e2f..2af8f0cae 100644
--- a/docs/defines.txt
+++ b/docs/defines.txt
@@ -40,10 +40,15 @@ __USE_EXTERN_INLINES
out-of-line version of every inlined function in case user program
calls it instead of using an inline.
_EXTERN_INLINE
- Define it to replace "extern __inline" string in inline definitions
+ If not defined by user prior to #include, will be defined to
+ "extern inline" or equivalent. IOW, if user defines it prior
+ #include, it replaces "extern __inline" string in inline definitions
(those enabled by __USE_EXTERN_INLINES) with something else.
A few uclibc .c files use it to create non-inlined functions
by defining it to "".
+__extern_inline
+ Defined to "extern inline", modulo gcc/C standard deviations.
+ Can't be used by user to play tricks as with _EXTERN_INLINE.
_LIBC
UCLIBC_INTERNAL
diff --git a/libc/inet/ether_addr.c b/libc/inet/ether_addr.c
index 82b067157..621c62989 100644
--- a/libc/inet/ether_addr.c
+++ b/libc/inet/ether_addr.c
@@ -31,49 +31,45 @@
#include <netinet/ether.h>
#include <netinet/if_ether.h>
-/* libc_hidden_proto(ether_ntoa_r) */
-/* libc_hidden_proto(sprintf) */
-#ifdef __UCLIBC_HAS_XLOCALE__
-/* libc_hidden_proto(__ctype_b_loc) */
-/* libc_hidden_proto(__ctype_tolower_loc) */
-#elif defined __UCLIBC_HAS_CTYPE_TABLES__
-/* libc_hidden_proto(__ctype_b) */
-/* libc_hidden_proto(__ctype_tolower) */
-#endif
-
struct ether_addr *ether_aton_r(const char *asc, struct ether_addr *addr)
{
- size_t cnt;
+ /* asc is "X:XX:XX:x:xx:xX" */
+ int cnt;
for (cnt = 0; cnt < 6; ++cnt) {
- unsigned int number;
+ unsigned char number;
char ch;
- ch = _tolower(*asc++);
+ /* | 0x20 is cheap tolower(), valid for letters/numbers only */
+ ch = (*asc++) | 0x20;
if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f'))
return NULL;
- number = isdigit(ch) ? (ch - '0') : (ch - 'a' + 10);
-
- ch = _tolower(*asc);
- if ((cnt < 5 && ch != ':')
- || (cnt == 5 && ch != '\0' && !isspace(ch))) {
- ++asc;
+ number = !(ch > '9') ? (ch - '0') : (ch - 'a' + 10);
+
+ ch = *asc++;
+ if ((cnt != 5 && ch != ':') /* not last group */
+ /* What standard says ASCII ether address representation
+ * may also finish with whitespace, not only NUL?
+ * We can get rid of isspace() otherwise */
+ || (cnt == 5 && ch != '\0' /*&& !isspace(ch)*/)
+ ) {
+ ch |= 0x20; /* cheap tolower() */
if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f'))
return NULL;
- number <<= 4;
- number += isdigit(ch) ? (ch - '0') : (ch - 'a' + 10);
+ number = (number << 4) + (!(ch > '9') ? (ch - '0') : (ch - 'a' + 10));
- ch = *asc;
- if (cnt < 5 && ch != ':')
- return NULL;
+ if (cnt != 5) {
+ ch = *asc++;
+ if (ch != ':')
+ return NULL;
+ }
}
/* Store result. */
- addr->ether_addr_octet[cnt] = (unsigned char) number;
-
- /* Skip ':'. */
- ++asc;
+ addr->ether_addr_octet[cnt] = number;
}
+ /* Looks like we allow garbage after last group?
+ * "1:2:3:4:5:66anything_at_all"? */
return addr;
}
diff --git a/libc/inet/ntop.c b/libc/inet/ntop.c
index dbc71815a..4583fc47f 100644
--- a/libc/inet/ntop.c
+++ b/libc/inet/ntop.c
@@ -67,8 +67,8 @@ inet_ntop4(const u_char *src, char *dst, size_t size)
#if 0 /* since src is unsigned char, it will never be > 255 ... */
if (src[octet] > 255) {
- __set_errno (ENOSPC);
- return (NULL);
+ __set_errno(ENOSPC);
+ return NULL;
}
#endif
tmp[i++] = '0' + src[octet] / 100;
@@ -83,9 +83,9 @@ inet_ntop4(const u_char *src, char *dst, size_t size)
}
tmp[i - 1] = '\0';
- if (strlen (tmp) > size) {
- __set_errno (ENOSPC);
- return (NULL);
+ if (strlen(tmp) > size) {
+ __set_errno(ENOSPC);
+ return NULL;
}
return strcpy(dst, tmp);
@@ -168,7 +168,7 @@ inet_ntop6(const u_char *src, char *dst, size_t size)
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
- return (NULL);
+ return NULL;
tp += strlen(tp);
break;
}
@@ -183,8 +183,8 @@ inet_ntop6(const u_char *src, char *dst, size_t size)
* Check for overflow, copy, and we're done.
*/
if ((size_t)(tp - tmp) > size) {
- __set_errno (ENOSPC);
- return (NULL);
+ __set_errno(ENOSPC);
+ return NULL;
}
return strcpy(dst, tmp);
}
@@ -216,25 +216,25 @@ inet_pton4(const char *src, u_char *dst)
u_int new = *tp * 10 + (ch - '0');
if (new > 255)
- return (0);
+ return 0;
*tp = new;
if (! saw_digit) {
if (++octets > 4)
- return (0);
+ return 0;
saw_digit = 1;
}
} else if (ch == '.' && saw_digit) {
if (octets == 4)
- return (0);
+ return 0;
*++tp = 0;
saw_digit = 0;
} else
- return (0);
+ return 0;
}
if (octets < 4)
- return (0);
+ return 0;
memcpy(dst, tmp, 4);
- return (1);
+ return 1;
}
/* int
@@ -253,13 +253,6 @@ inet_pton4(const char *src, u_char *dst)
#ifdef __UCLIBC_HAS_IPV6__
-/* We cannot use the macro version of tolower() or very bad
- * things happen when '*src++' gets evaluated multiple times.
- * So undef it here so we get the function version of tolower
- * instead.
- */
-#undef tolower
-
static int
inet_pton6(const char *src, u_char *dst)
{
@@ -276,19 +269,20 @@ inet_pton6(const char *src, u_char *dst)
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
- return (0);
+ return 0;
curtok = src;
saw_xdigit = 0;
val = 0;
- while ((ch = tolower (*src++)) != '\0') {
+ while ((ch = *src++) != '\0') {
const char *pch;
- pch = strchr(xdigits, ch);
+ /* | 0x20 is cheap tolower(), valid for letters/numbers only */
+ pch = strchr(xdigits, (ch | 0x20));
if (pch != NULL) {
val <<= 4;
val |= (pch - xdigits);
if (val > 0xffff)
- return (0);
+ return 0;
saw_xdigit = 1;
continue;
}
@@ -296,16 +290,16 @@ inet_pton6(const char *src, u_char *dst)
curtok = src;
if (!saw_xdigit) {
if (colonp)
- return (0);
+ return 0;
colonp = tp;
continue;
- } else if (*src == '\0') {
- return (0);
}
+ if (*src == '\0')
+ return 0;
if (tp + 2 > endp)
- return (0);
- *tp++ = (u_char) (val >> 8) & 0xff;
- *tp++ = (u_char) val & 0xff;
+ return 0;
+ *tp++ = (u_char) (val >> 8);
+ *tp++ = (u_char) val;
saw_xdigit = 0;
val = 0;
continue;
@@ -316,13 +310,13 @@ inet_pton6(const char *src, u_char *dst)
saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
- return (0);
+ return 0;
}
if (saw_xdigit) {
if (tp + 2 > endp)
- return (0);
- *tp++ = (u_char) (val >> 8) & 0xff;
- *tp++ = (u_char) val & 0xff;
+ return 0;
+ *tp++ = (u_char) (val >> 8);
+ *tp++ = (u_char) val;
}
if (colonp != NULL) {
/*
@@ -333,7 +327,7 @@ inet_pton6(const char *src, u_char *dst)
int i;
if (tp == endp)
- return (0);
+ return 0;
for (i = 1; i <= n; i++) {
endp[- i] = colonp[n - i];
colonp[n - i] = 0;
@@ -341,9 +335,9 @@ inet_pton6(const char *src, u_char *dst)
tp = endp;
}
if (tp != endp)
- return (0);
+ return 0;
memcpy(dst, tmp, 16);
- return (1);
+ return 1;
}
#endif /* __UCLIBC_HAS_IPV6__ */
@@ -364,14 +358,14 @@ inet_ntop(int af, const void *src, char *dst, socklen_t size)
{
switch (af) {
case AF_INET:
- return (inet_ntop4(src, dst, size));
+ return inet_ntop4(src, dst, size);
#ifdef __UCLIBC_HAS_IPV6__
case AF_INET6:
- return (inet_ntop6(src, dst, size));
+ return inet_ntop6(src, dst, size);
#endif
default:
- __set_errno (EAFNOSUPPORT);
- return (NULL);
+ __set_errno(EAFNOSUPPORT);
+ return NULL;
}
/* NOTREACHED */
}
@@ -395,14 +389,14 @@ inet_pton(int af, const char *src, void *dst)
{
switch (af) {
case AF_INET:
- return (inet_pton4(src, dst));
+ return inet_pton4(src, dst);
#ifdef __UCLIBC_HAS_IPV6__
case AF_INET6:
- return (inet_pton6(src, dst));
+ return inet_pton6(src, dst);
#endif
default:
- __set_errno (EAFNOSUPPORT);
- return (-1);
+ __set_errno(EAFNOSUPPORT);
+ return -1;
}
/* NOTREACHED */
}