From a9f8d52e596fbe521d4cb1d4b191d869b57e4c4c Mon Sep 17 00:00:00 2001 From: pancake Date: Tue, 14 Sep 2010 01:29:09 +0200 Subject: [PATCH] * Many fixes in ARM assembler and rarc2 support for ARM - Still not yet usable, but * Add .byte and .hex in r_asm as directives * Add test case for r_word api - Fix r_word_count() * Also handle .globl (and .global) to keep GAS compatibility - TODO: add .word .fill .align and others --- binr/rarc2/emit_arm.c | 208 +++++++++++++------------------------ binr/rarc2/rarc2.c | 2 +- libr/asm/arch/arm/armass.c | 129 ++++++++++++----------- libr/asm/asm.c | 48 +++++++-- libr/asm/p/asm_arm.c | 2 +- libr/util/str.c | 3 +- libr/util/t/Makefile | 4 + libr/util/t/array.c | 2 +- libr/util/t/set0.c | 17 +++ 9 files changed, 204 insertions(+), 211 deletions(-) create mode 100644 libr/util/t/set0.c diff --git a/binr/rarc2/emit_arm.c b/binr/rarc2/emit_arm.c index d64f904253..f97fb243fd 100644 --- a/binr/rarc2/emit_arm.c +++ b/binr/rarc2/emit_arm.c @@ -6,41 +6,31 @@ #define EMIT_NAME emit_arm #define R_ARCH "arm" #define R_SZ 8 -#define R_SP "r14" -#define R_BP "rbp" // XXX +#define R_SP "sp" +#define R_BP "fp" #define R_AX "r0" -#define R_GP { "r0", "r1", "r2", "r3" } -#define R_NGP 4 - +#define R_GP { "r0", "r1", "r2", "r3", "r4" } +#define R_TMP "r9" +#define R_NGP 5 +// no attsyntax for arm static char *regs[] = R_GP; static char *emit_syscall (int num) { - if (attsyntax) return strdup (": mov $`.arg`, %"R_AX"\n: int $0x80\n"); - return strdup (": mov "R_AX", `.arg`\n: int 0x80\n"); + return strdup (": mov "R_AX", `.arg`\n: svc 0x8000\n"); } static void emit_frame (int sz) { - if (sz>0) { - if (attsyntax) - rcc_printf ( - " push {lr}\n" - " sub sp, sp, %d\n", sz); - else rcc_printf ( // XXX - " push "R_BP"\n" - " mov "R_BP", "R_SP"\n" - " sub "R_SP", %d\n", sz); - } + if (sz>0) rcc_printf ( + " push {fp,lr}\n" + //" mov "R_BP", "R_SP"\n" + " add fp, sp, 4\n" // huh? + " sub sp, %d\n", sz); // 8, 16, .. } static void emit_frame_end (int sz, int ctx) { - if (sz>0) { - if (attsyntax) - rcc_printf (" add "R_SP", "R_SP", %d\n", sz); - else rcc_printf (" add "R_SP", "R_SP", %d\n", sz); - } - if (ctx>0) - rcc_puts (" pop {pc}\n"); + if (sz>0) rcc_printf (" add "R_SP", %d\n", sz); + if (ctx>0) rcc_puts (" pop {fp,pc}\n"); } static void emit_comment(const char *fmt, ...) { @@ -48,8 +38,7 @@ static void emit_comment(const char *fmt, ...) { char buf[1024]; va_start (ap, fmt); vsnprintf (buf, sizeof (buf), fmt, ap); - if (attsyntax) rcc_printf (" /* %s */\n", buf); - else rcc_printf ("# %s\n", buf); + rcc_printf ("# %s\n", buf); va_end (ap); } @@ -61,116 +50,82 @@ static void emit_syscall_args(int nargs) { int j, k; for (j=0; j0?'+':' ', k); - else rcc_printf (" ldr %s, ["R_SP", #%c%d]\n", regs[j+1], k>0?'+':' ', k); } } static void emit_set_string(const char *dstvar, const char *str, int j) { - char *p, str2[64]; - int i, oj = j; - for (i=0; i0?' ':'+', -idx); break; /* variable */ - case 1: sprintf(out, "dword ["R_SP"%c%d]", idx>0?'+':' ', idx); break; /* argument */ - } + switch (type) { + case 0: sprintf (out, "fp,%c%d", idx>0?' ':'+', -idx); break; /* variable */ + case 1: sprintf (out, "sp,%c%d", idx>0?'+':' ', idx); break; /* argument */ } } static void emit_trap () { - rcc_printf (" int3\n"); + rcc_printf (" svc 3\n"); } static void emit_load_ptr(const char *dst) { int d = atoi (dst); eprintf ("HACK HACK HACK\n"); // XXX: 32/64bit care - if (attsyntax) rcc_printf (" leal %d(%%"R_BP"), %%"R_AX"\n", d); - else rcc_printf (" leal "R_AX", dword ["R_BP"+%d]\n", d); + rcc_printf (" ldr "R_AX", ["R_BP", %d]\n", d); //rcc_printf (" movl %%"R_BP", %%"R_AX"\n"); //rcc_printf (" addl $%d, %%"R_AX"\n", d); } @@ -178,28 +133,25 @@ static void emit_load_ptr(const char *dst) { static void emit_branch(char *b, char *g, char *e, char *n, int sz, const char *dst) { char *p, str[64]; char *arg = NULL; - char *op = "jz"; + char *op = "beq"; /* NOTE that jb/ja are inverted to fit cmp opcode */ if (b) { *b = '\0'; - if (e) op = "jae"; - else op = "ja"; + op = e?"bge":"bgt"; arg = b+1; } else if (g) { *g = '\0'; - if (e) op = "jbe"; - else op = "jb"; + op = e?"ble":"blt"; arg = g+1; } if (arg == NULL) { if (e) { arg = e+1; - op = "jne"; + op = "bne"; } else { - arg = "$0"; - if (n) op = "jnz"; - else op ="jz"; + arg = "0"; + op = n?"bne":"beq"; } } @@ -217,40 +169,24 @@ static void emit_branch(char *b, char *g, char *e, char *n, int sz, const char * } static void emit_load(const char *dst, int sz) { - if (attsyntax) { - switch (sz) { - case 'l': - rcc_printf (" movl %s, %%"R_AX"\n", dst); - rcc_printf (" movl (%%"R_AX"), %%"R_AX"\n"); - case 'b': - rcc_printf (" movl %s, %%"R_AX"\n", dst); - rcc_printf (" movzb (%%"R_AX"), %%"R_AX"\n"); - break; - default: - // TODO: unhandled?!? - rcc_printf (" mov%c %s, %%"R_AX"\n", sz, dst); - rcc_printf (" mov%c (%%"R_AX"), %%"R_AX"\n", sz); - } - } else { - switch (sz) { - case 'l': - rcc_printf (" mov "R_AX", %s\n", dst); - rcc_printf (" mov "R_AX", ["R_AX"]\n"); - case 'b': - rcc_printf (" mov "R_AX", %s\n", dst); - rcc_printf (" movz "R_AX", ["R_AX"]\n"); - break; - default: - // TODO: unhandled?!? - rcc_printf (" mov "R_AX", %s\n", dst); - rcc_printf (" mov "R_AX", ["R_AX"]\n"); - } + switch (sz) { + case 'l': + rcc_printf (" mov "R_AX", %s\n", dst); + rcc_printf (" mov "R_AX", ["R_AX"]\n"); + case 'b': + rcc_printf (" mov "R_AX", %s\n", dst); + rcc_printf (" movz "R_AX", ["R_AX"]\n"); + break; + default: + // TODO: unhandled?!? + rcc_printf (" mov "R_AX", %s\n", dst); + rcc_printf (" mov "R_AX", ["R_AX"]\n"); } } static void emit_mathop(int ch, int vs, int type, const char *eq, const char *p) { char *op; - switch(ch) { + switch (ch) { case '^': op = "xor"; break; case '&': op = "and"; break; case '|': op = "or"; break; @@ -260,20 +196,16 @@ static void emit_mathop(int ch, int vs, int type, const char *eq, const char *p) case '/': op = "div"; break; default: op = "mov"; break; } - if (attsyntax) { - if (eq == NULL) eq = "%"R_AX; - if (p == NULL) p = "%"R_AX; - rcc_printf (" %s%c %c%s, %s\n", op, vs, type, eq, p); - } else { - if (eq == NULL) eq = R_AX; - if (p == NULL) p = R_AX; + if (eq == NULL) eq = R_AX; + if (p == NULL) p = R_AX; +#if 0 // TODO: - eprintf ("TYPE = %c\n", type); - eprintf (" %s%c %c%s, %s\n", op, vs, type, eq, p); - eprintf (" %s %s, [%s]\n", op, p, eq); - if (type == '*') rcc_printf (" %s %s, [%s]\n", op, p, eq); - else rcc_printf (" %s %s, %s\n", op, p, eq); - } + eprintf ("TYPE = %c\n", type); + eprintf (" %s%c %c%s, %s\n", op, vs, type, eq, p); + eprintf (" %s %s, [%s]\n", op, p, eq); +#endif + if (type == '*') rcc_printf (" %s %s, [%s]\n", op, p, eq); + else rcc_printf (" %s %s, %s\n", op, p, eq); } static const char* emit_regs(int idx) { diff --git a/binr/rarc2/rarc2.c b/binr/rarc2/rarc2.c index 332637960a..c13e2491f3 100644 --- a/binr/rarc2/rarc2.c +++ b/binr/rarc2/rarc2.c @@ -760,7 +760,7 @@ int main(int argc, char **argv) { } if (!once) { once++; - if (!attsyntax) + if (!attsyntax && (emit==&emit_x86 || emit==&emit_x64)) rcc_printf (".intel_syntax noprefix\n"); if (showmain) { emit->call ("main", 0); diff --git a/libr/asm/arch/arm/armass.c b/libr/asm/arch/arm/armass.c index a121ba9133..8c02b0d219 100644 --- a/libr/asm/arch/arm/armass.c +++ b/libr/asm/arch/arm/armass.c @@ -24,11 +24,14 @@ enum { TYPE_TST = 2, TYPE_SWI = 3, TYPE_BRA = 4, - TYPE_ARI = 5, - TYPE_IMM = 6, - TYPE_MEM = 7, + TYPE_BRR = 5, + TYPE_ARI = 6, + TYPE_IMM = 7, + TYPE_MEM = 8, }; +// static const char *const arm_shift[] = {"lsl", "lsr", "asr", "ror"}; + static ArmOp ops[] = { { "adc", 0xa000, TYPE_ARI }, { "adcs", 0xb000, TYPE_ARI }, @@ -52,13 +55,18 @@ static ArmOp ops[] = { { "ldr", 0x9000, TYPE_MEM }, { "str", 0x8000, TYPE_MEM }, - { "blx", 0x30ff2fe1, TYPE_BRA }, + { "blx", 0x30ff2fe1, TYPE_BRR }, + { "bx", 0x10ff2fe1, TYPE_BRR }, + { "bl", 0xb, TYPE_BRA }, - { "bx", 0x10ff2fe1, TYPE_BRA }, +// bx/blx - to register, b, bne,.. justjust offset +// 2220: e12fff1e bx lr +// 2224: e12fff12 bx r2 +// 2228: e12fff13 bx r3 + //{ "bx", 0xb, TYPE_BRA }, { "b", 0xa, TYPE_BRA }, - //{ "mov", 0x3, TYPE_MOV }, //{ "mov", 0x0a3, TYPE_MOV }, { "mov", 0xa001, TYPE_MOV }, @@ -80,11 +88,13 @@ static ArmOp ops[] = { }; static int getnum(const char *str) { - while (str&&(*str=='$'||*str=='#')) + if (!str) + return 0; + while (*str=='$'||*str=='#') str++; if (*str=='0'&&str[1]=='x') { int x; - if(sscanf(str+2, "%x", &x)) + if (sscanf (str+2, "%x", &x)) return x; } return atoi(str); @@ -98,7 +108,7 @@ static char *getrange(char *s) { *p=0; } if (*s=='[' || *s==']') - strcpy(s, s+1); + strcpy (s, s+1); if (*s=='}') *s=0; s++; @@ -108,28 +118,21 @@ static char *getrange(char *s) { } static int getreg(const char *str) { + int i; + const char *aliases[] = { "sl", "fp", "ip", "sp", "lr", "pc", NULL }; if (!str) return -1; if (*str=='r') return atoi (str+1); - if (!strcmp(str, "pc")) - return 15; - if (!strcmp(str, "lr")) - return 14; - if (!strcmp(str, "sp")) - return 13; - if (!strcmp(str, "ip")) - return 12; - if (!strcmp(str, "fp")) - return 11; - if (!strcmp(str, "sl")) - return 10; - return -1; // XXX + for(i=0;aliases[i];i++) + if (!strcmp (str, aliases[i])) + return 10+i; + return -1; } static int getshift(const char *str) { if(!str) return 0; - while (str&&*str&&!atoi(str)) + while (str&&*str&&!atoi (str)) str++; return atoi(str)/2; } @@ -162,8 +165,8 @@ static void arm_opcode_cond(ArmOpcode *ao, int delta) { }; int i, cond = 14; // 'always' is default char *c = ao->op+delta; - for(i=0;conds[i];i++) { - if (!strcmp(c, conds[i])) { + for (i=0;conds[i];i++) { + if (!strcmp (c, conds[i])) { cond = i; break; } @@ -191,7 +194,7 @@ static int arm_opcode_name(ArmOpcode *ao, const char *str) { ao->o |= (ret&0x0f)<<24;//(getreg(ao->a2)&0x0f); } else { ao->o |= (strstr(str,"],"))?4:5; - ao->o |= (getnum(ao->a2)&0x7f)<<24; // delta + ao->o |= (getnum (ao->a2)&0x7f)<<24; // delta } break; case TYPE_IMM: @@ -207,40 +210,50 @@ static int arm_opcode_name(ArmOpcode *ao, const char *str) { } else ao->o |= getnum(ao->a0)<<24; // ??? break; case TYPE_BRA: - if ((ret = getreg(ao->a0)) != -1) { - // XXX: Needs to calc (eip-off-8)>>2 - arm_opcode_cond(ao, strlen(ops[i].name)); - ao->o = (ao->o&0x70) | 0xb | (getnum(ao->a0)<<24); - } else { + if ((ret = getreg(ao->a0)) == -1) { + // TODO: control if branch out of range ret = (getnum(ao->a0)-ao->off-8)/4; ao->o |= ((ret>>8)&0xff)<<16; ao->o |= ((ret)&0xff)<<24; + } else { + printf("This branch does not accept reg as arg\n"); + return 0; + } + break; + case TYPE_BRR: + if ((ret = getreg(ao->a0)) != -1) { + ao->o |= (getreg (ao->a0)<<24); + } else { + printf("This branch does not accept off as arg\n"); + return 0; } break; case TYPE_SWI: - ao->o |= getnum(ao->a0)<<24; + ao->o |= (getnum (ao->a0)&0xff)<<24; + ao->o |= ((getnum (ao->a0)>>8)&0xff)<<16; + ao->o |= ((getnum (ao->a0)>>16)&0xff)<<8; break; case TYPE_ARI: if (!ao->a2) { ao->a2 = ao->a1; ao->a1 = ao->a0; } - ao->o |= getreg(ao->a0)<<20; - ao->o |= getreg(ao->a1)<<8; - ret = getreg(ao->a2); + ao->o |= getreg (ao->a0)<<20; + ao->o |= getreg (ao->a1)<<8; + ret = getreg (ao->a2); ao->o |= (ret!=-1)? ret<<24 : 2 | getnum(ao->a2)<<24; break; case TYPE_MOV: - ao->o |= getreg(ao->a0)<<20; - ret = getreg(ao->a1); + ao->o |= getreg (ao->a0)<<20; + ret = getreg (ao->a1); if (ret!=-1) ao->o |= ret<<24; - else ao->o |= 0xa003 | getnum(ao->a1)<<24; + else ao->o |= 0xa003 | getnum (ao->a1)<<24; break; case TYPE_TST: //ao->o |= getreg(ao->a0)<<20; // ??? - ao->o |= getreg(ao->a0)<<8; - ao->o |= getreg(ao->a1)<<24; - ao->o |= getshift(ao->a2)<<16; // shift + ao->o |= getreg (ao->a0)<<8; + ao->o |= getreg (ao->a1)<<24; + ao->o |= getshift (ao->a2)<<16; // shift break; } return 1; @@ -249,7 +262,6 @@ static int arm_opcode_name(ArmOpcode *ao, const char *str) { return 0; } -// XXX: check endian stuff int armass_assemble(const char *str, unsigned long off) { ArmOpcode aop = {0}; aop.off = off; @@ -265,10 +277,10 @@ int armass_assemble(const char *str, unsigned long off) { #ifdef MAIN void display(const char *str) { char cmd[32]; - int op = armass_assemble(str, 0x1000); - printf("%08x %s\n", op, str); - snprintf(cmd, sizeof(cmd), "rasm2 -d -a arm %08x", op); - system(cmd); + int op = armass_assemble (str, 0x1000); + printf ("%08x %s\n", op, str); + snprintf (cmd, sizeof(cmd), "rasm2 -d -a arm %08x", op); + system (cmd); } main() { @@ -288,6 +300,7 @@ main() { display("bx pc"); display("blx fp"); display("pop {pc}"); + display("add lr, pc, lr"); display("adds r3, #8"); display("adds r3, r2, #8"); display("subs r2, #1"); @@ -306,11 +319,20 @@ main() { display("str r1, [pc], 2"); display("str r1, [pc, 3]"); display("str r1, [pc, r4]"); -#endif - display("b r3"); + display("bx r3"); display("bcc 33"); - display("bne r3"); + display("blx r3"); display("bne 0x1200"); + display("str r0, [r1]"); +#endif + + //10ab4: 00047e30 andeq r7, r4, r0, lsr lr + //10ab8: 00036e70 andeq r6, r3, r0, ror lr + + display("andeq r7, r4, r0, lsr lr"); + display("andeq r6, r3, r0, ror lr"); + display("push {fp,lr}"); + display("pop {fp,lr}"); #if 0 @@ -325,12 +347,3 @@ main() { #endif } #endif -#if 0 -[pancake@dazo ~]$ rasm2 -o 0 -a arm -d 000080e5 -str r0, [r0] - -[pancake@dazo ~]$ rasm2 -o 0 -a arm -d 000081e5 -str r0, [r1] - -[pancake@dazo ~]$ rasm2 -o 0 -a arm -d 000081e5 -#endif diff --git a/libr/asm/asm.c b/libr/asm/asm.c index 9e28c7a9da..a32624ccd5 100644 --- a/libr/asm/asm.c +++ b/libr/asm/asm.c @@ -11,6 +11,11 @@ static RAsmPlugin *asm_static_plugins[] = { R_ASM_STATIC_PLUGINS }; +static int r_asm_pseudo_align(struct r_asm_aop_t *aop, char *input) { + eprintf ("TODO: .align\n"); + return 0; +} + static int r_asm_pseudo_string(struct r_asm_aop_t *aop, char *input) { int len = strlen (input)+1; r_hex_bin2str ((ut8*)input, len, aop->buf_hex); @@ -38,12 +43,34 @@ static inline int r_asm_pseudo_org(RAsm *a, char *input) { return 0; } -static inline int r_asm_pseudo_byte(struct r_asm_aop_t *aop, char *input) { +static inline int r_asm_pseudo_hex(struct r_asm_aop_t *aop, char *input) { int len = r_hex_str2bin (input, aop->buf); - strncpy (aop->buf_hex, r_str_trim(input), R_ASM_BUFSIZE); + strncpy (aop->buf_hex, r_str_trim (input), R_ASM_BUFSIZE); return len; } +// TODO: add .short, .word, .dword, ... +static inline int r_asm_pseudo_byte(struct r_asm_aop_t *aop, char *input) { + int i, len = 0; + r_str_subchr (input, ',', ' '); + len = r_str_word_count (input); + r_str_word_set0 (input); + for(i=0;ibuf[i] = num; + } + r_hex_bin2str (aop->buf, len, aop->buf_hex); + return len; +} + +static inline int r_asm_pseudo_fill(struct r_asm_aop_t *aop, char *input) { + // repeat, size, value + // TODO + eprintf ("TODO: .fill\n"); + return 0; +} + R_API RAsm *r_asm_new() { int i; RAsmPlugin *static_plugin; @@ -53,8 +80,8 @@ R_API RAsm *r_asm_new() { a->cur = NULL; a->bits = 32; a->big_endian = 0; - a->syntax = R_ASM_SYNTAX_INTEL; a->pc = 0; + a->syntax = R_ASM_SYNTAX_INTEL; a->plugins = r_list_new (); for (i=0; asm_static_plugins[i]; i++) { static_plugin = R_NEW (RAsmPlugin); @@ -67,7 +94,7 @@ R_API RAsm *r_asm_new() { R_API void r_asm_free(RAsm *a) { // TODO: free plugins and so on - free(a); + free (a); } /* return fastcall register argument 'idx' for a syscall with 'num' args */ @@ -220,18 +247,13 @@ R_API RAsmCode* r_asm_mdisassemble(RAsm *a, ut8 *buf, ut64 len) { eprintf ("error disassemble at offset %"PFMT64d"\n", idx); return r_asm_code_free (acode); } - //eprintf ("++ %d %d\n", ret, aop.inst_len); - //ret = aop.inst_len; // are always equal?? slen += strlen (aop.buf_asm) + 2; if(!(acode->buf_asm = realloc (acode->buf_asm, slen))) return r_asm_code_free (acode); strcat (acode->buf_asm, aop.buf_asm); strcat (acode->buf_asm, "\n"); - //if (idx + ret < len) } - acode->len = idx; - return acode; } @@ -322,13 +344,19 @@ R_API RAsmCode* r_asm_massemble(RAsm *a, const char *buf) { a->syntax = R_ASM_SYNTAX_ATT; else if (!memcmp (ptr, ".string ", 8)) ret = r_asm_pseudo_string (&aop, ptr+8); + else if (!memcmp (ptr, ".align", 7)) + ret = r_asm_pseudo_align (&aop, ptr+7); else if (!memcmp (ptr, ".arch ", 6)) ret = r_asm_pseudo_arch (a, ptr+6); else if (!memcmp (ptr, ".bits ", 6)) ret = r_asm_pseudo_bits (a, ptr+6); + else if (!memcmp (ptr, ".fill ", 6)) + ret = r_asm_pseudo_fill (&aop, ptr+6); + else if (!memcmp (ptr, ".hex ", 5)) + ret = r_asm_pseudo_hex (&aop, ptr+5); else if (!memcmp (ptr, ".byte ", 6)) ret = r_asm_pseudo_byte (&aop, ptr+6); - else if (!memcmp (ptr, ".global ", 8)) { + else if (!memcmp (ptr, ".glob", 5)) { // .global .globl // eprintf (".global directive not yet implemented\n"); ret = 0; continue; diff --git a/libr/asm/p/asm_arm.c b/libr/asm/p/asm_arm.c index 121ad17308..ab80c12971 100644 --- a/libr/asm/p/asm_arm.c +++ b/libr/asm/p/asm_arm.c @@ -85,7 +85,7 @@ static int assemble(RAsm *a, RAsmAop *aop, const char *buf) { int op = armass_assemble(buf, a->pc); if (op==-1) return -1; - r_mem_copyendian (aop->buf, &op, 4, a->big_endian); + r_mem_copyendian (aop->buf, (void *)&op, 4, a->big_endian); return (a->bits/8); } diff --git a/libr/util/str.c b/libr/util/str.c index 76adba4596..ad9bdfcb82 100644 --- a/libr/util/str.c +++ b/libr/util/str.c @@ -152,9 +152,8 @@ R_API int r_str_word_count(const char *string) { for (word = 0; *text; word++) { for (;*text && !isseparator (*text); text++); for (tmp = text; *text && isseparator (*text); text++); - if (tmp == text) word--; } - return word-1; + return word; } R_API char *r_str_ichr(char *str, char chr) { diff --git a/libr/util/t/Makefile b/libr/util/t/Makefile index 2a6d939c1b..a3817a8bbc 100644 --- a/libr/util/t/Makefile +++ b/libr/util/t/Makefile @@ -10,6 +10,7 @@ EFLAGS=../libr_util.a endif BINS=test${EXT_EXE} +BINS=set0${EXT_EXE} BINS+=rax2${EXT_EXE} BINS+=ralloc${EXT_EXE} BINS+=array${EXT_EXE} @@ -28,6 +29,9 @@ ralloc${EXT_EXE}: test${EXT_EXE}: ${CC} ${FLAGS} test.c ${EFLAGS} -o test${EXT_EXE} +set0${EXT_EXE}: + ${CC} ${FLAGS} set0.c ${EFLAGS} -o set0${EXT_EXE} + argv${EXT_EXE}: ${CC} ${FLAGS} argv.c ${EFLAGS} -o argv${EXT_EXE} diff --git a/libr/util/t/array.c b/libr/util/t/array.c index 502c625e4b..43775265d6 100644 --- a/libr/util/t/array.c +++ b/libr/util/t/array.c @@ -1,4 +1,4 @@ -/* radare - LGPL - Copyright 2009 pancake */ +/* radare - LGPL - Copyright 2009-2010 pancake */ #include "r_util.h" int main() { diff --git a/libr/util/t/set0.c b/libr/util/t/set0.c new file mode 100644 index 0000000000..9dc3c90faa --- /dev/null +++ b/libr/util/t/set0.c @@ -0,0 +1,17 @@ +#include + +void test(const char *s) { + int n; + printf("STR: %s\n", s); + n = r_str_word_count(s); + printf("NUM: %d\n", n); +} + +void main() { + test("1"); + test(""); + test("1 2 3"); + test("1,2,3"); + test("1, 2, 3"); + test(" 1, 2, 3 "); +}