1 /* radare - LGPL - Copyright 2009-2020 - pancake */
2
3 #include <r_util.h>
4
5 /* Validate if char is printable , why not use ISPRINTABLE() ?? */
r_name_validate_print(const char ch)6 R_API bool r_name_validate_print(const char ch) {
7 // TODO: support utf8
8 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || IS_DIGIT (ch)) {
9 return true;
10 }
11 switch (ch) {
12 case '(':
13 case ')':
14 case '[':
15 case ']':
16 case '<':
17 case '+':
18 case '-':
19 case '>':
20 case '$':
21 case '%':
22 case '@':
23 case ' ':
24 case '.':
25 case ',':
26 case ':':
27 case '_':
28 return true;
29 case '\b':
30 case '\t':
31 case '\n':
32 case '\r':
33 // must be replaced with ' ' and trimmed later
34 return false;
35 }
36 return false;
37 }
38
39 // used to determine if we want to replace those chars with '_' in r_name_filter()
r_name_validate_dash(const char ch)40 R_API bool r_name_validate_dash(const char ch) {
41 switch (ch) {
42 case ' ':
43 case '-':
44 case '_':
45 case '/':
46 case '\\':
47 case '(':
48 case ')':
49 case '[':
50 case ']':
51 case '<':
52 case '>':
53 case '!':
54 case '?':
55 case '$':
56 case ';':
57 case '%':
58 case '@':
59 case '`':
60 case ',':
61 case '"':
62 return true;
63 }
64 return false;
65 }
66
r_name_validate_char(const char ch)67 R_API bool r_name_validate_char(const char ch) {
68 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || IS_DIGIT (ch)) {
69 return true;
70 }
71 switch (ch) {
72 case '.':
73 case ':':
74 case '_':
75 return true;
76 }
77 return false;
78 }
79
r_name_validate_first(const char ch)80 R_API bool r_name_validate_first(const char ch) {
81 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
82 return true;
83 }
84 switch (ch) {
85 case '_':
86 case ':':
87 return true;
88 }
89 return false;
90 }
91
r_name_check(const char * s)92 R_API bool r_name_check(const char *s) {
93 if (!r_name_validate_first (*s)) {
94 return false;
95 }
96 for (s++; *s; s++) {
97 if (!r_name_validate_char (*s)) {
98 return false;
99 }
100 }
101 return true;
102 }
103
is_special_char(char n)104 static inline bool is_special_char(char n) {
105 return (n == 'b' || n == 'f' || n == 'n' || n == 'r' || n == 't' || n == 'v' || n == 'a');
106 }
107
r_name_filter_ro(const char * a)108 R_API const char *r_name_filter_ro(const char *a) {
109 while (*a++ == '_');
110 return a - 1;
111 }
112
113 // filter string for printing purposes
r_name_filter_print(char * s)114 R_API bool r_name_filter_print(char *s) {
115 char *es = s + strlen (s);
116 char *os = s;
117 while (*s && s < es) {
118 int us = r_utf8_size ((const ut8*)s);
119 if (us > 1) {
120 s += us;
121 continue;
122 }
123 if (!r_name_validate_print (*s)) {
124 r_str_cpy (s, s + 1);
125 }
126 s++;
127 }
128 return os;
129 }
130
r_name_filter(char * s,int maxlen)131 R_API bool r_name_filter(char *s, int maxlen) {
132 // if maxlen == -1 : R_FLAG_NAME_SIZE
133 // maxlen is ignored, the function signature must change
134 if (maxlen > 0) {
135 int slen = strlen (s);
136 if (slen > maxlen) {
137 s[maxlen] = 0;
138 }
139 }
140 char *os = s;
141 while (*s) {
142 if (r_name_validate_first (*s)) {
143 break;
144 }
145 if (r_name_validate_dash (*s)) {
146 *s = '_';
147 break;
148 }
149 r_str_cpy (s, s + 1);
150 }
151 for (s++; *s; s++) {
152 if (*s == '\\') {
153 if (is_special_char (s[1])) {
154 *s = '_';
155 } else {
156 r_str_cpy (s, s + 1);
157 s--;
158 }
159 }
160 if (!r_name_validate_char (*s)) {
161 if (r_name_validate_dash (*s)) {
162 *s = '_';
163 } else {
164 r_str_cpy (s, s + 1);
165 s--;
166 }
167 }
168 }
169 r_str_trim (os);
170 return r_name_check (os);
171 }
172
r_name_filter2(const char * name)173 R_API char *r_name_filter2(const char *name) {
174 char *s = strdup (name);
175 r_name_filter (s, -1);
176 return s;
177 }
178