diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-12-22 01:01:40 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-12-22 01:01:40 +0000 |
commit | 4274e516239b34c5cd9ea2c60c11802e28244c99 (patch) | |
tree | 4fa9f8d784803d3927757f7eaa6e95ad5ae5ca5e | |
parent | c6df9c945232b76340e298946b51684441f549fc (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.txt | 7 | ||||
-rw-r--r-- | libc/inet/ether_addr.c | 52 | ||||
-rw-r--r-- | libc/inet/ntop.c | 86 |
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 */ } |