diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig.debug | 34 | ||||
-rw-r--r-- | lib/Makefile | 4 | ||||
-rw-r--r-- | lib/extable.c | 6 | ||||
-rw-r--r-- | lib/fault-inject.c | 19 | ||||
-rw-r--r-- | lib/iomap.c | 32 | ||||
-rw-r--r-- | lib/rwsem-spinlock.c | 16 | ||||
-rw-r--r-- | lib/semaphore-sleepers.c | 8 | ||||
-rw-r--r-- | lib/smp_processor_id.c | 4 | ||||
-rw-r--r-- | lib/vsprintf.c | 172 |
9 files changed, 216 insertions, 79 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 0d385be682db..a370fe828a79 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -205,6 +205,19 @@ config SLUB_DEBUG_ON off in a kernel built with CONFIG_SLUB_DEBUG_ON by specifying "slub_debug=-". +config SLUB_STATS + default n + bool "Enable SLUB performance statistics" + depends on SLUB + help + SLUB statistics are useful to debug SLUBs allocation behavior in + order find ways to optimize the allocator. This should never be + enabled for production use since keeping statistics slows down + the allocator by a few percentage points. The slabinfo command + supports the determination of the most active slabs to figure + out which slabs are relevant to a particular load. + Try running: slabinfo -DA + config DEBUG_PREEMPT bool "Debug preemptible kernel" depends on DEBUG_KERNEL && PREEMPT && (TRACE_IRQFLAGS_SUPPORT || PPC64) @@ -391,7 +404,8 @@ config DEBUG_HIGHMEM config DEBUG_BUGVERBOSE bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED depends on BUG - depends on ARM || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG || BLACKFIN + depends on ARM || AVR32 || M32R || M68K || SPARC32 || SPARC64 || \ + FRV || SUPERH || GENERIC_BUG || BLACKFIN || MN10300 default !EMBEDDED help Say Y here to make BUG() panics output the file name and line number @@ -441,7 +455,9 @@ config DEBUG_SG config FRAME_POINTER bool "Compile the kernel with frame pointers" - depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH || BLACKFIN) + depends on DEBUG_KERNEL && \ + (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || \ + AVR32 || SUPERH || BLACKFIN || MN10300) default y if DEBUG_INFO && UML help If you say Y here the resulting kernel image will be slightly larger @@ -449,20 +465,6 @@ config FRAME_POINTER some architectures or if you use external debuggers. If you don't debug the kernel, you can say N. -config FORCED_INLINING - bool "Force gcc to inline functions marked 'inline'" - depends on DEBUG_KERNEL - default y - help - This option determines if the kernel forces gcc to inline the functions - developers have marked 'inline'. Doing so takes away freedom from gcc to - do what it thinks is best, which is desirable for the gcc 3.x series of - compilers. The gcc 4.x series have a rewritten inlining algorithm and - disabling this option will generate a smaller kernel there. Hopefully - this algorithm is so good that allowing gcc4 to make the decision can - become the default in the future, until then this option is there to - test gcc for this. - config BOOT_PRINTK_DELAY bool "Delay each boot printk message by N milliseconds" depends on DEBUG_KERNEL && PRINTK && GENERIC_CALIBRATE_DELAY diff --git a/lib/Makefile b/lib/Makefile index a18062e4633f..23de261a4c83 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -6,7 +6,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o \ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o irq_regs.o reciprocal_div.o argv_split.o \ - proportions.o prio_heap.o scatterlist.o + proportions.o prio_heap.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o @@ -14,7 +14,7 @@ lib-$(CONFIG_SMP) += cpumask.o lib-y += kobject.o kref.o klist.o obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ - bust_spinlocks.o hexdump.o kasprintf.o bitmap.o + bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG diff --git a/lib/extable.c b/lib/extable.c index 463f4560f16d..179c08745595 100644 --- a/lib/extable.c +++ b/lib/extable.c @@ -57,10 +57,10 @@ search_extable(const struct exception_table_entry *first, while (first <= last) { const struct exception_table_entry *mid; - mid = (last - first) / 2 + first; + mid = ((last - first) >> 1) + first; /* - * careful, the distance between entries can be - * larger than 2GB: + * careful, the distance between value and insn + * can be larger than MAX_LONG: */ if (mid->insn < value) first = mid + 1; diff --git a/lib/fault-inject.c b/lib/fault-inject.c index 23985a278bbb..a50a311554cc 100644 --- a/lib/fault-inject.c +++ b/lib/fault-inject.c @@ -134,23 +134,26 @@ bool should_fail(struct fault_attr *attr, ssize_t size) #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS -static void debugfs_ul_set(void *data, u64 val) +static int debugfs_ul_set(void *data, u64 val) { *(unsigned long *)data = val; + return 0; } #ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER -static void debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val) +static int debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val) { *(unsigned long *)data = val < MAX_STACK_TRACE_DEPTH ? val : MAX_STACK_TRACE_DEPTH; + return 0; } #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */ -static u64 debugfs_ul_get(void *data) +static int debugfs_ul_get(void *data, u64 *val) { - return *(unsigned long *)data; + *val = *(unsigned long *)data; + return 0; } DEFINE_SIMPLE_ATTRIBUTE(fops_ul, debugfs_ul_get, debugfs_ul_set, "%llu\n"); @@ -174,14 +177,16 @@ static struct dentry *debugfs_create_ul_MAX_STACK_TRACE_DEPTH( } #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */ -static void debugfs_atomic_t_set(void *data, u64 val) +static int debugfs_atomic_t_set(void *data, u64 val) { atomic_set((atomic_t *)data, val); + return 0; } -static u64 debugfs_atomic_t_get(void *data) +static int debugfs_atomic_t_get(void *data, u64 *val) { - return atomic_read((atomic_t *)data); + *val = atomic_read((atomic_t *)data); + return 0; } DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, diff --git a/lib/iomap.c b/lib/iomap.c index 72c42687ba10..db004a9ff509 100644 --- a/lib/iomap.c +++ b/lib/iomap.c @@ -69,27 +69,27 @@ static void bad_io_access(unsigned long port, const char *access) #define mmio_read32be(addr) be32_to_cpu(__raw_readl(addr)) #endif -unsigned int fastcall ioread8(void __iomem *addr) +unsigned int ioread8(void __iomem *addr) { IO_COND(addr, return inb(port), return readb(addr)); return 0xff; } -unsigned int fastcall ioread16(void __iomem *addr) +unsigned int ioread16(void __iomem *addr) { IO_COND(addr, return inw(port), return readw(addr)); return 0xffff; } -unsigned int fastcall ioread16be(void __iomem *addr) +unsigned int ioread16be(void __iomem *addr) { IO_COND(addr, return pio_read16be(port), return mmio_read16be(addr)); return 0xffff; } -unsigned int fastcall ioread32(void __iomem *addr) +unsigned int ioread32(void __iomem *addr) { IO_COND(addr, return inl(port), return readl(addr)); return 0xffffffff; } -unsigned int fastcall ioread32be(void __iomem *addr) +unsigned int ioread32be(void __iomem *addr) { IO_COND(addr, return pio_read32be(port), return mmio_read32be(addr)); return 0xffffffff; @@ -110,23 +110,23 @@ EXPORT_SYMBOL(ioread32be); #define mmio_write32be(val,port) __raw_writel(be32_to_cpu(val),port) #endif -void fastcall iowrite8(u8 val, void __iomem *addr) +void iowrite8(u8 val, void __iomem *addr) { IO_COND(addr, outb(val,port), writeb(val, addr)); } -void fastcall iowrite16(u16 val, void __iomem *addr) +void iowrite16(u16 val, void __iomem *addr) { IO_COND(addr, outw(val,port), writew(val, addr)); } -void fastcall iowrite16be(u16 val, void __iomem *addr) +void iowrite16be(u16 val, void __iomem *addr) { IO_COND(addr, pio_write16be(val,port), mmio_write16be(val, addr)); } -void fastcall iowrite32(u32 val, void __iomem *addr) +void iowrite32(u32 val, void __iomem *addr) { IO_COND(addr, outl(val,port), writel(val, addr)); } -void fastcall iowrite32be(u32 val, void __iomem *addr) +void iowrite32be(u32 val, void __iomem *addr) { IO_COND(addr, pio_write32be(val,port), mmio_write32be(val, addr)); } @@ -193,15 +193,15 @@ static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count) } #endif -void fastcall ioread8_rep(void __iomem *addr, void *dst, unsigned long count) +void ioread8_rep(void __iomem *addr, void *dst, unsigned long count) { IO_COND(addr, insb(port,dst,count), mmio_insb(addr, dst, count)); } -void fastcall ioread16_rep(void __iomem *addr, void *dst, unsigned long count) +void ioread16_rep(void __iomem *addr, void *dst, unsigned long count) { IO_COND(addr, insw(port,dst,count), mmio_insw(addr, dst, count)); } -void fastcall ioread32_rep(void __iomem *addr, void *dst, unsigned long count) +void ioread32_rep(void __iomem *addr, void *dst, unsigned long count) { IO_COND(addr, insl(port,dst,count), mmio_insl(addr, dst, count)); } @@ -209,15 +209,15 @@ EXPORT_SYMBOL(ioread8_rep); EXPORT_SYMBOL(ioread16_rep); EXPORT_SYMBOL(ioread32_rep); -void fastcall iowrite8_rep(void __iomem *addr, const void *src, unsigned long count) +void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count) { IO_COND(addr, outsb(port, src, count), mmio_outsb(addr, src, count)); } -void fastcall iowrite16_rep(void __iomem *addr, const void *src, unsigned long count) +void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count) { IO_COND(addr, outsw(port, src, count), mmio_outsw(addr, src, count)); } -void fastcall iowrite32_rep(void __iomem *addr, const void *src, unsigned long count) +void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count) { IO_COND(addr, outsl(port, src,count), mmio_outsl(addr, src, count)); } diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c index c4cfd6c0342f..9df3ca56db11 100644 --- a/lib/rwsem-spinlock.c +++ b/lib/rwsem-spinlock.c @@ -125,7 +125,7 @@ __rwsem_wake_one_writer(struct rw_semaphore *sem) /* * get a read lock on the semaphore */ -void fastcall __sched __down_read(struct rw_semaphore *sem) +void __sched __down_read(struct rw_semaphore *sem) { struct rwsem_waiter waiter; struct task_struct *tsk; @@ -168,7 +168,7 @@ void fastcall __sched __down_read(struct rw_semaphore *sem) /* * trylock for reading -- returns 1 if successful, 0 if contention */ -int fastcall __down_read_trylock(struct rw_semaphore *sem) +int __down_read_trylock(struct rw_semaphore *sem) { unsigned long flags; int ret = 0; @@ -191,7 +191,7 @@ int fastcall __down_read_trylock(struct rw_semaphore *sem) * get a write lock on the semaphore * - we increment the waiting count anyway to indicate an exclusive lock */ -void fastcall __sched __down_write_nested(struct rw_semaphore *sem, int subclass) +void __sched __down_write_nested(struct rw_semaphore *sem, int subclass) { struct rwsem_waiter waiter; struct task_struct *tsk; @@ -231,7 +231,7 @@ void fastcall __sched __down_write_nested(struct rw_semaphore *sem, int subclass ; } -void fastcall __sched __down_write(struct rw_semaphore *sem) +void __sched __down_write(struct rw_semaphore *sem) { __down_write_nested(sem, 0); } @@ -239,7 +239,7 @@ void fastcall __sched __down_write(struct rw_semaphore *sem) /* * trylock for writing -- returns 1 if successful, 0 if contention */ -int fastcall __down_write_trylock(struct rw_semaphore *sem) +int __down_write_trylock(struct rw_semaphore *sem) { unsigned long flags; int ret = 0; @@ -260,7 +260,7 @@ int fastcall __down_write_trylock(struct rw_semaphore *sem) /* * release a read lock on the semaphore */ -void fastcall __up_read(struct rw_semaphore *sem) +void __up_read(struct rw_semaphore *sem) { unsigned long flags; @@ -275,7 +275,7 @@ void fastcall __up_read(struct rw_semaphore *sem) /* * release a write lock on the semaphore */ -void fastcall __up_write(struct rw_semaphore *sem) +void __up_write(struct rw_semaphore *sem) { unsigned long flags; @@ -292,7 +292,7 @@ void fastcall __up_write(struct rw_semaphore *sem) * downgrade a write lock into a read lock * - just wake up any readers at the front of the queue */ -void fastcall __downgrade_write(struct rw_semaphore *sem) +void __downgrade_write(struct rw_semaphore *sem) { unsigned long flags; diff --git a/lib/semaphore-sleepers.c b/lib/semaphore-sleepers.c index 128180523860..0198782cdacb 100644 --- a/lib/semaphore-sleepers.c +++ b/lib/semaphore-sleepers.c @@ -48,12 +48,12 @@ * we cannot lose wakeup events. */ -fastcall void __up(struct semaphore *sem) +void __up(struct semaphore *sem) { wake_up(&sem->wait); } -fastcall void __sched __down(struct semaphore * sem) +void __sched __down(struct semaphore *sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); @@ -90,7 +90,7 @@ fastcall void __sched __down(struct semaphore * sem) tsk->state = TASK_RUNNING; } -fastcall int __sched __down_interruptible(struct semaphore * sem) +int __sched __down_interruptible(struct semaphore *sem) { int retval = 0; struct task_struct *tsk = current; @@ -153,7 +153,7 @@ fastcall int __sched __down_interruptible(struct semaphore * sem) * single "cmpxchg" without failure cases, * but then it wouldn't work on a 386. */ -fastcall int __down_trylock(struct semaphore * sem) +int __down_trylock(struct semaphore *sem) { int sleepers; unsigned long flags; diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c index eddc9b3d3876..6c90fb90e19c 100644 --- a/lib/smp_processor_id.c +++ b/lib/smp_processor_id.c @@ -42,7 +42,9 @@ unsigned int debug_smp_processor_id(void) if (!printk_ratelimit()) goto out_enable; - printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid); + printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] " + "code: %s/%d\n", + preempt_count() - 1, current->comm, current->pid); print_symbol("caller is %s\n", (long)__builtin_return_address(0)); dump_stack(); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 7b481cea54ae..fd987b17bda7 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -26,6 +26,9 @@ #include <asm/page.h> /* for PAGE_SIZE */ #include <asm/div64.h> +/* Works only for digits and letters, but small and fast */ +#define TOLOWER(x) ((x) | 0x20) + /** * simple_strtoul - convert a string to an unsigned long * @cp: The start of the string @@ -41,17 +44,17 @@ unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) if (*cp == '0') { base = 8; cp++; - if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { + if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) { cp++; base = 16; } } } else if (base == 16) { - if (cp[0] == '0' && toupper(cp[1]) == 'X') + if (cp[0] == '0' && TOLOWER(cp[1]) == 'x') cp += 2; } while (isxdigit(*cp) && - (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { + (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) { result = result*base + value; cp++; } @@ -92,17 +95,17 @@ unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base) if (*cp == '0') { base = 8; cp++; - if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { + if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) { cp++; base = 16; } } } else if (base == 16) { - if (cp[0] == '0' && toupper(cp[1]) == 'X') + if (cp[0] == '0' && TOLOWER(cp[1]) == 'x') cp += 2; } - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) - ? toupper(*cp) : *cp)-'A'+10) < base) { + while (isxdigit(*cp) + && (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) { result = result*base + value; cp++; } @@ -126,6 +129,129 @@ long long simple_strtoll(const char *cp,char **endp,unsigned int base) return simple_strtoull(cp,endp,base); } + +/** + * strict_strtoul - convert a string to an unsigned long strictly + * @cp: The string to be converted + * @base: The number base to use + * @res: The converted result value + * + * strict_strtoul converts a string to an unsigned long only if the + * string is really an unsigned long string, any string containing + * any invalid char at the tail will be rejected and -EINVAL is returned, + * only a newline char at the tail is acceptible because people generally + * change a module parameter in the following way: + * + * echo 1024 > /sys/module/e1000/parameters/copybreak + * + * echo will append a newline to the tail. + * + * It returns 0 if conversion is successful and *res is set to the converted + * value, otherwise it returns -EINVAL and *res is set to 0. + * + * simple_strtoul just ignores the successive invalid characters and + * return the converted value of prefix part of the string. + */ +int strict_strtoul(const char *cp, unsigned int base, unsigned long *res); + +/** + * strict_strtol - convert a string to a long strictly + * @cp: The string to be converted + * @base: The number base to use + * @res: The converted result value + * + * strict_strtol is similiar to strict_strtoul, but it allows the first + * character of a string is '-'. + * + * It returns 0 if conversion is successful and *res is set to the converted + * value, otherwise it returns -EINVAL and *res is set to 0. + */ +int strict_strtol(const char *cp, unsigned int base, long *res); + +/** + * strict_strtoull - convert a string to an unsigned long long strictly + * @cp: The string to be converted + * @base: The number base to use + * @res: The converted result value + * + * strict_strtoull converts a string to an unsigned long long only if the + * string is really an unsigned long long string, any string containing + * any invalid char at the tail will be rejected and -EINVAL is returned, + * only a newline char at the tail is acceptible because people generally + * change a module parameter in the following way: + * + * echo 1024 > /sys/module/e1000/parameters/copybreak + * + * echo will append a newline to the tail of the string. + * + * It returns 0 if conversion is successful and *res is set to the converted + * value, otherwise it returns -EINVAL and *res is set to 0. + * + * simple_strtoull just ignores the successive invalid characters and + * return the converted value of prefix part of the string. + */ +int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res); + +/** + * strict_strtoll - convert a string to a long long strictly + * @cp: The string to be converted + * @base: The number base to use + * @res: The converted result value + * + * strict_strtoll is similiar to strict_strtoull, but it allows the first + * character of a string is '-'. + * + * It returns 0 if conversion is successful and *res is set to the converted + * value, otherwise it returns -EINVAL and *res is set to 0. + */ +int strict_strtoll(const char *cp, unsigned int base, long long *res); + +#define define_strict_strtoux(type, valtype) \ +int strict_strtou##type(const char *cp, unsigned int base, valtype *res)\ +{ \ + char *tail; \ + valtype val; \ + size_t len; \ + \ + *res = 0; \ + len = strlen(cp); \ + if (len == 0) \ + return -EINVAL; \ + \ + val = simple_strtoul(cp, &tail, base); \ + if ((*tail == '\0') || \ + ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {\ + *res = val; \ + return 0; \ + } \ + \ + return -EINVAL; \ +} \ + +#define define_strict_strtox(type, valtype) \ +int strict_strto##type(const char *cp, unsigned int base, valtype *res) \ +{ \ + int ret; \ + if (*cp == '-') { \ + ret = strict_strtou##type(cp+1, base, res); \ + if (ret != 0) \ + *res = -(*res); \ + } else \ + ret = strict_strtou##type(cp, base, res); \ + \ + return ret; \ +} \ + +define_strict_strtoux(l, unsigned long) +define_strict_strtox(l, long) +define_strict_strtoux(ll, unsigned long long) +define_strict_strtox(ll, long long) + +EXPORT_SYMBOL(strict_strtoul); +EXPORT_SYMBOL(strict_strtol); +EXPORT_SYMBOL(strict_strtoll); +EXPORT_SYMBOL(strict_strtoull); + static int skip_atoi(const char **s) { int i=0; @@ -237,24 +363,25 @@ static noinline char* put_dec(char *buf, unsigned long long num) #define PLUS 4 /* show plus */ #define SPACE 8 /* space if plus */ #define LEFT 16 /* left justified */ -#define SPECIAL 32 /* 0x */ -#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ +#define SMALL 32 /* Must be 32 == 0x20 */ +#define SPECIAL 64 /* 0x */ static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type) { - char sign,tmp[66]; - const char *digits; - /* we are called with base 8, 10 or 16, only, thus don't need "g..." */ - static const char small_digits[] = "0123456789abcdefx"; /* "ghijklmnopqrstuvwxyz"; */ - static const char large_digits[] = "0123456789ABCDEFX"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ + /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ + static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ + + char tmp[66]; + char sign; + char locase; int need_pfx = ((type & SPECIAL) && base != 10); int i; - digits = (type & LARGE) ? large_digits : small_digits; + /* locase = 0 or 0x20. ORing digits or letters with 'locase' + * produces same digits or (maybe lowercased) letters */ + locase = (type & SMALL); if (type & LEFT) type &= ~ZEROPAD; - if (base < 2 || base > 36) - return NULL; sign = 0; if (type & SIGN) { if ((signed long long) num < 0) { @@ -281,7 +408,7 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int tmp[i++] = '0'; /* Generic code, for any base: else do { - tmp[i++] = digits[do_div(num,base)]; + tmp[i++] = (digits[do_div(num,base)] | locase); } while (num != 0); */ else if (base != 10) { /* 8 or 16 */ @@ -289,7 +416,7 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int int shift = 3; if (base == 16) shift = 4; do { - tmp[i++] = digits[((unsigned char)num) & mask]; + tmp[i++] = (digits[((unsigned char)num) & mask] | locase); num >>= shift; } while (num); } else { /* base 10 */ @@ -321,7 +448,7 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int ++buf; if (base == 16) { if (buf < end) - *buf = digits[16]; /* for arbitrary base: digits[33]; */ + *buf = ('X' | locase); ++buf; } } @@ -521,6 +648,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) continue; case 'p': + flags |= SMALL; if (field_width == -1) { field_width = 2*sizeof(void *); flags |= ZEROPAD; @@ -557,9 +685,9 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) base = 8; break; - case 'X': - flags |= LARGE; case 'x': + flags |= SMALL; + case 'X': base = 16; break; |