kernel: add helpers for ascii character conversion
Subsystems (2)
PATCH 1/1 kernel: add helpers for ascii character conversion
Add helpers for getting an ascii hex char for the high and low nibble of a byte. Also add a small helper to get an integer value from a given hex char.
Included here are a few of the current places that roll their own versions being moved to the common helper.
---
Maybe I should call this RFC, but people have rolled their own all over the place in tree, so this should go in somewhere.
arch/cris/arch-v10/kernel/kgdb.c | 94 +++++++++++--------------------------- arch/cris/arch-v32/kernel/kgdb.c | 84 +++++++++------------------------- drivers/pnp/support.c | 8 ++-- include/linux/kernel.h | 15 ++++++ lib/hexdump.c | 4 +- 5 files changed, 70 insertions(+), 135 deletions(-)
arch/cris/arch-v10/kernel/kgdb.c +27 -67
@@ -278,17 +278,6 @@ void putDebugChar (int val);void enableDebugIRQ (void ); -/* Returns the character equivalent of a nibble, bit 7, 6, 5, and 4 of a byte, -represented by int x. */ -static char highhex (int x); - -/* Returns the character equivalent of a nibble, bit 3, 2, 1, and 0 of a byte, -represented by int x. */ -static char lowhex (int x); - -/* Returns the integer equivalent of a hexadecimal character. */ -static int hex (char ch); -/* Convert the memory, pointed to by mem into hexadecimal representation. Put the result in buf, and return a pointer to the last character in buf (null). */
@@ -670,35 +659,6 @@ read_register (char regno, unsigned int *valptr) }/********************************** Packet I/O ******************************/ -/* Returns the character equivalent of a nibble, bit 7, 6, 5, and 4 of a byte, -represented by int x. */ -static inline char -highhex (int x) -{ -return hexchars[(x >>4 ) &0xf ]; -} - -/* Returns the character equivalent of a nibble, bit 3, 2, 1, and 0 of a byte, -represented by int x. */ -static inline char -lowhex (int x) -{ -return hexchars[x &0xf ]; -} - -/* Returns the integer equivalent of a hexadecimal character. */ -static int -hex (char ch) -{ -if ((ch >='a' ) && (ch <='f' )) -return (ch -'a' +10 ); -if ((ch >='0' ) && (ch <='9' )) -return (ch -'0' ); -if ((ch >='A' ) && (ch <='F' )) -return (ch -'A' +10 ); -return (-1 ); -} -/* Convert the memory, pointed to by mem into hexadecimal representation. Put the result in buf, and return a pointer to the last character in buf (null). */
@@ -721,8 +681,8 @@ mem2hex(char *buf, unsigned char *mem, int count)/* Valid mem address. */ for (i =0 ; i < count; i++) { ch = *mem++; - *buf++ =highhex (ch); - *buf++ =lowhex (ch); + *buf++ =asc_hex_hi (ch); + *buf++ =asc_hex_lo (ch); } }
@@ -740,8 +700,8 @@ hex2mem (unsigned char *mem, char *buf, int count)int i;unsigned char ch;for (i =0 ; i < count; i++) { - ch =hex (*buf++) <<4 ; - ch = ch +hex (*buf++); + ch =hex_to_int (*buf++) <<4 ; + ch = ch +hex_to_int (*buf++); *mem++ = ch; }return (mem);
@@ -800,8 +760,8 @@ getpacket (char *buffer) buffer[count] ='\0' ;if (ch =='#' ) { - xmitcsum =hex (getDebugChar ()) <<4 ; - xmitcsum +=hex (getDebugChar ()); + xmitcsum =hex_to_int (getDebugChar ()) <<4 ; + xmitcsum +=hex_to_int (getDebugChar ());if (checksum != xmitcsum) {/* Wrong checksum */ putDebugChar ('-' );
@@ -858,8 +818,8 @@ putpacket(char *buffer) } }putDebugChar ('#' ); -putDebugChar (highhex (checksum)); -putDebugChar (lowhex (checksum)); +putDebugChar (asc_hex_hi (checksum)); +putDebugChar (asc_hex_lo (checksum)); }while (kgdb_started && (getDebugChar () !='+' )); }
@@ -896,8 +856,8 @@ stub_is_stopped(int sigval)/* Send trap type (converted to signal) */ *ptr++ ='T' ; - *ptr++ =highhex (sigval); - *ptr++ =lowhex (sigval); + *ptr++ =asc_hex_hi (sigval); + *ptr++ =asc_hex_lo (sigval);/* Send register contents. We probably only need to send the * PC, frame pointer and stack pointer here. Other registers will be
@@ -911,8 +871,8 @@ stub_is_stopped(int sigval)if (status ==SUCCESS ) { - *ptr++ =highhex (regno); - *ptr++ =lowhex (regno); + *ptr++ =asc_hex_hi (regno); + *ptr++ =asc_hex_lo (regno); *ptr++ =':' ; ptr = mem2hex(ptr, (unsigned char *)®_cont,
@@ -937,8 +897,8 @@ stub_is_stopped(int sigval)/* Store thread:r...; with the executing task TID. */ gdb_cris_strcpy (&remcomOutBuffer[pos],"thread:" ); pos +=gdb_cris_strlen ("thread:" ); - remcomOutBuffer[pos++] =highhex (executing_task); - remcomOutBuffer[pos++] =lowhex (executing_task); + remcomOutBuffer[pos++] =asc_hex_hi (executing_task); + remcomOutBuffer[pos++] =asc_hex_lo (executing_task);gdb_cris_strcpy (&remcomOutBuffer[pos],";" );#endif
@@ -1126,8 +1086,8 @@ handle_exception (int sigval)Success: SAA, where AA is the signal number. Failure: void. */ remcomOutBuffer[0 ] ='S' ; - remcomOutBuffer[1 ] =highhex (sigval); - remcomOutBuffer[2 ] =lowhex (sigval); + remcomOutBuffer[1 ] =asc_hex_hi (sigval); + remcomOutBuffer[2 ] =asc_hex_lo (sigval); remcomOutBuffer[3 ] =0 ;break ;
@@ -1224,23 +1184,23 @@ handle_exception (int sigval)case 'C' :/* Identify the remote current thread. */ gdb_cris_strcpy (&remcomOutBuffer[0 ],"QC" ); - remcomOutBuffer[2 ] =highhex (current_thread_c); - remcomOutBuffer[3 ] =lowhex (current_thread_c); + remcomOutBuffer[2 ] =asc_hex_hi (current_thread_c); + remcomOutBuffer[3 ] =asc_hex_lo (current_thread_c); remcomOutBuffer[4 ] ='\0' ;break ;case 'L' :gdb_cris_strcpy (&remcomOutBuffer[0 ],"QM" );/* Reply with number of threads. */ if (os_is_started ()) { - remcomOutBuffer[2 ] =highhex (number_of_tasks); - remcomOutBuffer[3 ] =lowhex (number_of_tasks); + remcomOutBuffer[2 ] =asc_hex_hi (number_of_tasks); + remcomOutBuffer[3 ] =asc_hex_lo (number_of_tasks); }else { - remcomOutBuffer[2 ] =highhex (0 ); - remcomOutBuffer[3 ] =lowhex (1 ); + remcomOutBuffer[2 ] =asc_hex_hi (0 ); + remcomOutBuffer[3 ] =asc_hex_lo (1 ); }/* Done with the reply. */ - remcomOutBuffer[4 ] =lowhex (1 ); + remcomOutBuffer[4 ] =asc_hex_lo (1 ); pos =5 ;/* Expects the argument thread id. */ for (; pos < (5 +HEXCHARS_IN_THREAD_ID ); pos++)
@@ -1251,16 +1211,16 @@ handle_exception (int sigval)for (thread_id =0 ; thread_id < number_of_tasks; thread_id++) { nextpos = pos +HEXCHARS_IN_THREAD_ID -1 ;for (; pos < nextpos; pos ++) - remcomOutBuffer[pos] =lowhex (0 ); - remcomOutBuffer[pos++] =lowhex (thread_id); + remcomOutBuffer[pos] =asc_hex_lo (0 ); + remcomOutBuffer[pos++] =asc_hex_lo (thread_id); } }else {/* Store the thread identifier of the boot task. */ nextpos = pos +HEXCHARS_IN_THREAD_ID -1 ;for (; pos < nextpos; pos ++) - remcomOutBuffer[pos] =lowhex (0 ); - remcomOutBuffer[pos++] =lowhex (current_thread_c); + remcomOutBuffer[pos] =asc_hex_lo (0 ); + remcomOutBuffer[pos++] =asc_hex_lo (current_thread_c); } remcomOutBuffer[pos] ='\0' ;break ;
arch/cris/arch-v32/kernel/kgdb.c +22 -62
160 lines not on this page · raw message
drivers/pnp/support.c +4 -4
@@ -45,10 +45,10 @@ void pnp_eisa_id_to_string(u32 id, char *str) str[0 ] ='A' + ((id >>26 ) &0x3f ) -1 ; str[1 ] ='A' + ((id >>21 ) &0x1f ) -1 ; str[2 ] ='A' + ((id >>16 ) &0x1f ) -1 ; - str[3 ] =hex_asc ((id >>12 ) &0xf ); - str[4 ] =hex_asc ((id >>8 ) &0xf ); - str[5 ] =hex_asc ((id >>4 ) &0xf ); - str[6 ] =hex_asc ((id >>0 ) &0xf ); + str[3 ] =hex_asc_hi (id >>8 ); + str[4 ] =hex_asc_lo (id >>8 ); + str[5 ] =hex_asc_hi (id); + str[6 ] =hex_asc_lo (id); str[7 ] ='\0' ; }
include/linux/kernel.h +15 -0
@@ -277,6 +277,21 @@ extern void print_hex_dump(const char *level, const char *prefix_str,extern void print_hex_dump_bytes (const char *prefix_str,int prefix_type,const void *buf,size_t len);#define hex_asc (x) "0123456789abcdef"[x] +#define hex_asc_lo (x) hex_asc(((x) & 0x0f)) +#define hex_asc_hi (x) hex_asc(((x) & 0xf0) >> 4) + +static inline u8 hex_to_int (char ch) +{ +/* +* Make ch lower-case, works only for digits and letters +*/ + ch |=0x20 ; +if ((ch >='a' ) && (ch <='f' )) +return (ch -'a' +10 ); +if ((ch >='0' ) && (ch <='9' )) +return (ch -'0' ); +return (-1 ); +} #define pr_emerg(fmt, arg...) \ printk(KERN_EMERG fmt, ##arg)
lib/hexdump.c +2 -2
@@ -93,8 +93,8 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,for (j =0 ; (j < rowsize) && (j < len) && (lx +4 ) < linebuflen; j++) { ch = ptr[j]; - linebuf[lx++] =hex_asc (ch >>4 ); - linebuf[lx++] =hex_asc (ch &0x0f ); + linebuf[lx++] =hex_asc_hi (ch); + linebuf[lx++] =hex_asc_lo (ch); linebuf[lx++] =' ' ; } ascii_column =3 * rowsize +2 ;
Signature · 1 line
1.5.5.1.305.g7c84
Andrew Morton
maintainerQuoted 6 lines · On Thu, 01 May 2008 12:23:00 -0700 Harvey Harrison <[email protected]>…
Add helpers for getting an ascii hex char for the high and low nibble of a byte. Also add a small helper to get an integer value from a given hex char.
Included here are a few of the current places that roll their own versions being moved to the common helper.
ahh, someone cares ;)
Does this mean that
y:/usr/src/linux-2.6.25> grep -ri '"0123456789abcdef"' . | wc -l 40
will decrease?
include/linux/kernel.h extern void print_hex_dump(const char *level, const char *prefix_str, · line 281
Quoted 8 lines
include/linux/kernel.h +2
-0@@ -277,6 +277,21 @@ extern void print_hex_dump(const char *level, const char *prefix_str,extern void print_hex_dump_bytes (const char *prefix_str,int prefix_type,const void *buf,size_t len);#define hex_asc (x) "0123456789abcdef"[x] +#define hex_asc_lo (x) hex_asc(((x) & 0x0f)) +#define hex_asc_hi (x) hex_asc(((x) & 0xf0) >> 4)
umm, this might mean that each .c file which uses hex_asc_lo/hi gets its own copy of "0123456789abcdef". I believe that gcc/ld are getting better at handling this, but I haven't checked, and I don't know which versions get it right nor in which way. etc.
So it might be better to give the kernel the One True Digitstring in lib/something.c and export that to modules.
include/linux/kernel.h extern void print_hex_dump(const char *level, const char *prefix_str, · line 294
Quoted 12 lines
include/linux/kernel.h +12
-0+static inline u8 hex_to_int (char ch) +{ +/* +* Make ch lower-case, works only for digits and letters +*/ + ch |=0x20 ; +if ((ch >='a' ) && (ch <='f' )) +return (ch -'a' +10 ); +if ((ch >='0' ) && (ch <='9' )) +return (ch -'0' ); +return (-1 ); +}
probably should be uninlined.
return-is-not-a-function ;)
Quoted 17 lines
include/linux/kernel.h +0
-0#define pr_emerg(fmt, arg...) \ printk(KERN_EMERG fmt, ##arg)lib/hexdump.c +2
-2@@ -93,8 +93,8 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,for (j =0 ; (j < rowsize) && (j < len) && (lx +4 ) < linebuflen; j++) { ch = ptr[j]; - linebuf[lx++] =hex_asc (ch >>4 ); - linebuf[lx++] =hex_asc (ch &0x0f ); + linebuf[lx++] =hex_asc_hi (ch); + linebuf[lx++] =hex_asc_lo (ch); linebuf[lx++] =' ' ; } ascii_column =3 * rowsize +2 ;
Quoted 11 lines · Andrew Morton
Quoted 6 lines · On Thu, 01 May 2008 12:23:00 -0700 Harvey Harrison <[email protected]>…
Add helpers for getting an ascii hex char for the high and low nibble of a byte. Also add a small helper to get an integer value from a given hex char.
Included here are a few of the current places that roll their own versions being moved to the common helper.
ahh, someone cares ;)
Well, I have an interest in collecting bits of useful infrastructure everyone and their dog has reimplemented somewhere in the tree.
Quoted 7 lines
Does this mean that
y:/usr/src/linux-2.6.25> grep -ri '"
0123456789abcdef"' . | wc -l 40will decrease?
Somewhat, I debated between the kernel.h route and adding an out-of-line version to hexdump.c. While gcc/ld has gotten better about this, may as well make it easy.
Quoted 33 lines
include/linux/kernel.h extern void print_hex_dump(const char *level, const char *prefix_str, · line 281
Quoted 9 lines
include/linux/kernel.h +2
-0@@ -277,6 +277,21 @@ extern void print_hex_dump(const char *level, const char *prefix_str,extern void print_hex_dump_bytes (const char *prefix_str,int prefix_type,const void *buf,size_t len);#define hex_asc (x) "0123456789abcdef"[x] +#define hex_asc_lo (x) hex_asc(((x) & 0x0f)) +#define hex_asc_hi (x) hex_asc(((x) & 0xf0) >> 4)umm, this might mean that each .c file which uses hex_asc_lo/hi gets its own copy of "
0123456789abcdef". I believe that gcc/ld are getting better at handling this, but I haven't checked, and I don't know which versions get it right nor in which way. etc.So it might be better to give the kernel the One True Digitstring in
lib/something.cand export that to modules.include/linux/kernel.h extern void print_hex_dump(const char *level, const char *prefix_str, · line 294
Quoted 12 lines
include/linux/kernel.h +12
-0+static inline u8 hex_to_int (char ch) +{ +/* +* Make ch lower-case, works only for digits and letters +*/ + ch |=0x20 ; +if ((ch >='a' ) && (ch <='f' )) +return (ch -'a' +10 ); +if ((ch >='0' ) && (ch <='9' )) +return (ch -'0' ); +return (-1 ); +}probably should be uninlined.
Quoted 1 line
return-is-not-a-function ;)
...you didn't even blink at my last-minute change from returning int to u8 that was, how to say, ill-advised now that I look again :(
In any event, I'll go the lib/hexdump route and send that in a bit.
Cheers,
Harvey