2009-02-05 21:08:46 +00:00
|
|
|
/* radare - LGPL - Copyright 2007-2009 pancake<nopcode.org> */
|
|
|
|
|
|
|
|
#include "r_types.h"
|
|
|
|
#include "r_util.h"
|
|
|
|
#include <stdio.h>
|
2009-02-16 02:14:19 +00:00
|
|
|
#include <stdarg.h>
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
/* stable code */
|
|
|
|
static const char *nullstr = "";
|
|
|
|
static const char *nullstr_c = "(null)";
|
|
|
|
|
|
|
|
/* int c; ret = hex2int(&c, 'c'); */
|
|
|
|
static int hex2int (unsigned char *val, unsigned char c)
|
|
|
|
{
|
|
|
|
if ('0' <= c && c <= '9') *val = (unsigned char)(*val) * 16 + ( c - '0');
|
|
|
|
else if (c >= 'A' && c <= 'F') *val = (unsigned char)(*val) * 16 + ( c - 'A' + 10);
|
|
|
|
else if (c >= 'a' && c <= 'f') *val = (unsigned char)(*val) * 16 + ( c - 'a' + 10);
|
|
|
|
else return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-20 12:41:04 +00:00
|
|
|
/* TODO: port to w32 and move outside r_str namespace? */
|
2009-06-15 02:44:05 +00:00
|
|
|
R_API char *r_str_home(const char *str)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
const char *home = getenv("HOME");
|
|
|
|
char *dst;
|
|
|
|
if (home == NULL)
|
|
|
|
return NULL;
|
2009-04-02 00:07:58 +00:00
|
|
|
dst = (char *)malloc(strlen(home) + strlen(str)+2);
|
2009-02-05 21:08:46 +00:00
|
|
|
strcpy(dst, home);
|
|
|
|
strcat(dst, "/");
|
|
|
|
strcat(dst, str);
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
2009-04-06 22:53:25 +00:00
|
|
|
R_API int r_str_hash(const char *str)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
int i = 1;
|
|
|
|
int a = 0x31;
|
|
|
|
int b = 0x337;
|
|
|
|
int h = str[0];
|
|
|
|
for(; str[i]; i++) {
|
|
|
|
h+=str[i]*i*a;
|
|
|
|
a*=b;
|
|
|
|
}
|
|
|
|
return h&0x7ffffff;
|
|
|
|
}
|
|
|
|
|
2009-04-06 22:53:25 +00:00
|
|
|
R_API int r_str_delta(char *p, char a, char b)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
char *_a = strchr(p, a);
|
|
|
|
char *_b = strchr(p, b);
|
|
|
|
if (!_a||!_b) return 0;
|
|
|
|
return (_a-_b);
|
|
|
|
}
|
|
|
|
|
2009-04-06 22:53:25 +00:00
|
|
|
R_API int r_str_word_set0(char *str)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *p;
|
|
|
|
if (str[0]=='\0')
|
|
|
|
return 0;
|
2009-05-20 12:41:04 +00:00
|
|
|
/* TODO: sync with r1 code */
|
2009-02-05 21:08:46 +00:00
|
|
|
for(i=1,p=str;p[0];p=p+1)if(*p==' '){i++;*p='\0';} // s/ /\0/g
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2009-04-06 22:53:25 +00:00
|
|
|
R_API const char *r_str_word_get0(const char *str, int idx)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
const char *ptr = str;
|
|
|
|
if (ptr == NULL)
|
|
|
|
return nullstr;
|
|
|
|
for (i=0;*ptr && i != idx;i++)
|
|
|
|
ptr = ptr + strlen(ptr) + 1;
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2009-04-06 22:53:25 +00:00
|
|
|
R_API int r_str_word_count(const char *string)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
char *text = (char *)string;
|
|
|
|
char *tmp = (char *)string;
|
|
|
|
int word = 0;
|
|
|
|
|
2009-04-15 12:37:18 +00:00
|
|
|
for(;(*text)&&(isseparator(*text));text=text+1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
for(word = 0; *text; word++) {
|
2009-04-15 12:37:18 +00:00
|
|
|
for(;*text && !isseparator(*text);text = text +1);
|
2009-02-05 21:08:46 +00:00
|
|
|
tmp = text;
|
2009-04-15 12:37:18 +00:00
|
|
|
for(;*text &&isseparator(*text);text = text +1);
|
2009-02-05 21:08:46 +00:00
|
|
|
if (tmp == text)
|
|
|
|
word-=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return word-1;
|
|
|
|
}
|
|
|
|
|
2009-04-06 22:53:25 +00:00
|
|
|
R_API char *r_str_ichr(char *str, char chr)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
while(*str==chr) {
|
|
|
|
str = str+1;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2009-04-06 22:53:25 +00:00
|
|
|
R_API char *r_str_lchr(char *str, char chr)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
2009-02-16 23:09:40 +00:00
|
|
|
int len = strlen(str)+1;
|
2009-02-05 21:08:46 +00:00
|
|
|
for(;len>=0;len--)
|
|
|
|
if (str[len]==chr)
|
|
|
|
return str+len;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-04-03 11:11:17 +00:00
|
|
|
R_API int r_str_nchr(const char *str, char chr)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
int n = 0;
|
|
|
|
while(str[0]) {
|
|
|
|
if (str[0]==chr)
|
|
|
|
n++;
|
|
|
|
str = str+1;
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2009-04-03 11:11:17 +00:00
|
|
|
R_API int r_str_nstr(char *from, char *to, int size)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0;i<size;i++)
|
|
|
|
if (from==NULL||to==NULL||from[i]!=to[i])
|
|
|
|
break;
|
|
|
|
return (size!=i);
|
|
|
|
}
|
|
|
|
|
2009-04-06 22:53:25 +00:00
|
|
|
R_API const char *r_str_chop_ro(const char *str)
|
|
|
|
{
|
|
|
|
if (str)
|
|
|
|
while(str[0]&&iswhitechar(str[0]))
|
|
|
|
str = str + 1;
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2009-04-03 11:11:17 +00:00
|
|
|
R_API char *r_str_chop(char *str)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
if (str == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
while(str[0]&&iswhitechar(str[0]))
|
|
|
|
str = str + 1;
|
|
|
|
|
|
|
|
len = strlen(str);
|
|
|
|
|
|
|
|
if (len>0)
|
|
|
|
for(ptr = str+len-1;ptr!=str;ptr = ptr - 1) {
|
|
|
|
if (iswhitechar(ptr[0]))
|
|
|
|
ptr[0]='\0';
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2009-04-11 16:49:09 +00:00
|
|
|
R_API char *r_str_trim(char *str)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
if (str == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for(ptr=str, i=0;str[i];i++)
|
|
|
|
if (!iswhitechar(str[i]))
|
|
|
|
*ptr++=str[i];
|
|
|
|
*ptr='\0';
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2009-02-05 21:08:46 +00:00
|
|
|
/* memccmp("foo.bar", "foo.cow, '.') == 0 */
|
|
|
|
int r_str_ccmp(const char *dst, const char *orig, int ch)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0;orig[i] && orig[i] != ch; i++)
|
|
|
|
if (dst[i] != orig[i])
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int r_str_cmp(const char *a, const char *b, int len)
|
|
|
|
{
|
|
|
|
for(;len--;) {
|
|
|
|
if (*a=='\0'||*b=='\0'||*a!=*b)
|
|
|
|
return 1;
|
|
|
|
a=a+1;
|
|
|
|
b=b+1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int r_str_ccpy(char *dst, char *orig, int ch)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0;orig[i] && orig[i] != ch; i++)
|
|
|
|
dst[i] = orig[i];
|
|
|
|
dst[i] = '\0';
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *r_str_word_get_first(const char *string)
|
|
|
|
{
|
|
|
|
char *text = (char *)string;
|
|
|
|
char *start = NULL;
|
|
|
|
char *ret = NULL;
|
|
|
|
int len = 0;
|
|
|
|
|
2009-04-15 12:37:18 +00:00
|
|
|
for(;*text &&isseparator(*text);text = text + 1);
|
2009-02-05 21:08:46 +00:00
|
|
|
start = text;
|
2009-04-15 12:37:18 +00:00
|
|
|
for(;*text &&!isseparator(*text);text = text + 1) len++;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
/* strdup */
|
|
|
|
ret = (char *)malloc(len+1);
|
|
|
|
if (ret == 0) {
|
|
|
|
fprintf(stderr, "Cannot allocate %d bytes.\n", len+1);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
strncpy(ret, start, len);
|
|
|
|
ret[len]='\0';
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *r_str_get(const char *str)
|
|
|
|
{
|
|
|
|
if (str == NULL)
|
|
|
|
return nullstr_c;
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *r_str_dup(char *ptr, const char *string)
|
|
|
|
{
|
|
|
|
if (ptr)
|
|
|
|
free(ptr);
|
|
|
|
ptr = strdup(string);
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2009-02-16 02:14:19 +00:00
|
|
|
char *r_str_concat(char *ptr, const char *string)
|
|
|
|
{
|
|
|
|
if (!ptr)
|
|
|
|
return strdup(string);
|
|
|
|
ptr = realloc(ptr, strlen(string)+strlen(ptr)+1);
|
|
|
|
if (ptr == NULL)
|
|
|
|
return NULL;
|
|
|
|
strcat(ptr, string);
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *r_str_concatf(char *ptr, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
char string[1024];
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
vsnprintf(string, 1023, fmt, ap);
|
|
|
|
ptr = r_str_concat(ptr, string);
|
|
|
|
va_end(ap);
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2009-04-06 12:01:56 +00:00
|
|
|
inline void r_str_concatch(char *x, char y){char b[2]={y,0};strcat(x,b);}
|
|
|
|
|
2009-02-05 21:08:46 +00:00
|
|
|
void *r_str_free(void *ptr)
|
|
|
|
{
|
|
|
|
free (ptr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int r_str_inject(char *begin, char *end, char *str, int maxlen)
|
|
|
|
{
|
|
|
|
int len = strlen(end)+1;
|
|
|
|
char *tmp = alloca(len);
|
|
|
|
if (maxlen > 0 && ((strlen(begin)-(end-begin)+strlen(str)) > maxlen))
|
|
|
|
return 0;
|
|
|
|
memcpy(tmp, end, len);
|
|
|
|
strcpy(begin, str);
|
|
|
|
strcat(begin, tmp);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* unstable code */
|
|
|
|
/*------------------------------------------------*/
|
|
|
|
|
|
|
|
// FROM bash::stringlib
|
|
|
|
#define RESIZE_MALLOCED_BUFFER(str,cind,room,csize,sincr) \
|
|
|
|
if ((cind) + (room) >= csize) { \
|
|
|
|
while ((cind) + (room) >= csize) \
|
|
|
|
csize += (sincr); \
|
|
|
|
str = realloc (str, csize); \
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Replace occurrences of PAT with REP in STRING. If GLOBAL is non-zero,
|
|
|
|
replace all occurrences, otherwise replace only the first.
|
|
|
|
This returns a new string; the caller should free it. */
|
|
|
|
|
|
|
|
static int strsub_memcmp (char *string, char *pat, int len)
|
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
while(len--) {
|
|
|
|
if (*pat!='?')
|
|
|
|
res += *string - *pat;
|
|
|
|
string = string+1;
|
|
|
|
pat = pat+1;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *r_str_sub(char *string, char *pat, char *rep, int global)
|
|
|
|
{
|
|
|
|
int patlen, templen, tempsize, repl, i;
|
|
|
|
char *temp, *r;
|
|
|
|
|
|
|
|
patlen = strlen (pat);
|
|
|
|
for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
|
|
|
|
{
|
|
|
|
// if (repl && !memcmp(string + i, pat, patlen)) {
|
|
|
|
if (repl && !strsub_memcmp(string + i, pat, patlen)) {
|
|
|
|
RESIZE_MALLOCED_BUFFER (temp, templen, patlen, tempsize, 4096); //UGLY HACK (patlen * 2));
|
|
|
|
if (temp == NULL)
|
|
|
|
return NULL;
|
|
|
|
for (r = rep; *r; )
|
|
|
|
temp[templen++] = *r++;
|
|
|
|
|
|
|
|
i += patlen;
|
|
|
|
repl = global != 0;
|
|
|
|
} else {
|
|
|
|
RESIZE_MALLOCED_BUFFER (temp, templen, 1, tempsize, 4096); // UGLY HACK 16);
|
|
|
|
temp[templen++] = string[i++];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (temp != NULL)
|
|
|
|
temp[templen] = 0;
|
|
|
|
return (temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
int r_str_escape(char *buf)
|
|
|
|
{
|
|
|
|
unsigned char ch = 0, ch2 = 0;
|
|
|
|
int err = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i=0;buf[i];i++) {
|
|
|
|
if (buf[i]=='\\') {
|
|
|
|
if (buf[i+1]=='e') {
|
|
|
|
buf[i] = 0x1b;
|
|
|
|
strcpy(buf+i+1, buf+i+2);
|
|
|
|
} else if (buf[i+1]=='r') {
|
|
|
|
buf[i] = 0x0d;
|
|
|
|
strcpy(buf+i+1, buf+i+2);
|
|
|
|
} else if (buf[i+1]=='n') {
|
|
|
|
buf[i] = 0x0a;
|
|
|
|
strcpy(buf+i+1, buf+i+2);
|
|
|
|
} else if (buf[i+1]=='x') {
|
|
|
|
err = ch2 = ch = 0;
|
|
|
|
if (!buf[i+2] || !buf[i+3]) {
|
|
|
|
printf("Unexpected end of string.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
err |= hex2int(&ch, buf[i+2]);
|
|
|
|
err |= hex2int(&ch2, buf[i+3]);
|
|
|
|
if (err) {
|
|
|
|
printf("Incorrect hexadecimal characters for conversion.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
buf[i] = (ch<<4)+ch2;
|
|
|
|
strcpy(buf+i+1, buf+i+4);
|
|
|
|
} else {
|
|
|
|
printf("'\\x' expected.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2009-05-20 12:41:04 +00:00
|
|
|
/* ansi helpers */
|
|
|
|
R_API int r_str_ansi_len(const char *str)
|
|
|
|
{
|
|
|
|
int i=0, len = 0;
|
|
|
|
while(str[i]) {
|
|
|
|
if (str[i]==0x1b && str[i+1]=='[')
|
|
|
|
for(++i;str[i]&&str[i]!='J'&&str[i]!='m'&&str[i]!='H';i++);
|
|
|
|
else len++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API const char *r_str_ansi_chrn(const char *str, int n)
|
|
|
|
{
|
|
|
|
int i=0, len = 0;
|
|
|
|
while(str[i]) {
|
|
|
|
if (n == len)
|
|
|
|
break;
|
|
|
|
if (str[i]==0x1b && str[i+1]=='[')
|
|
|
|
for(++i;str[i]&&str[i]!='J'&&str[i]!='m'&&str[i]!='H';i++);
|
|
|
|
else len++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return str+i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-05 21:08:46 +00:00
|
|
|
#if 0
|
|
|
|
int r_str_argv_parse(const char *str, int argc, char **argv)
|
|
|
|
{
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
char *tmp, *tmp2;
|
|
|
|
free(ps.args);
|
|
|
|
ps.args = strdup(ps.filename);
|
|
|
|
tmp2 = ps.args;
|
|
|
|
// parse argv
|
|
|
|
//eprintf("commandline=\"%s\"\n", ps.args);
|
|
|
|
for(tmp=ps.args;tmp[0];tmp=tmp+1) {
|
|
|
|
if (tmp[0]==' '&&tmp!=ps.args) { if ((tmp[-1]=='\\') || (tmp[-1]=='/'))
|
|
|
|
continue;
|
|
|
|
tmp[0]='\0';
|
|
|
|
ps.argv[i] = tmp2;
|
|
|
|
tmp2 = tmp+1;
|
|
|
|
if (++i>254) {
|
|
|
|
printf("Too many arguments. truncated\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ps.argv[i] = tmp2;
|
|
|
|
ps.argv[i+1] = 0;
|
|
|
|
|
|
|
|
tmp = strchr(config.file, ' ');
|
|
|
|
if (tmp) *tmp = '\0';
|
|
|
|
//config.file = strdup("/bin/ls"); //ps.argv[0];
|
|
|
|
//eprintf("ppa:A0(%s)\n", ps.argv[0]);
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
#endif
|