1 /* string.c
2 * (c) 2002 Mikulas Patocka
3 * This file is a part of the Links program, released under GPL.
4 */
5
6 #include "links.h"
7
snprint(unsigned char * s,int n,my_uintptr_t num)8 int snprint(unsigned char *s, int n, my_uintptr_t num)
9 {
10 my_uintptr_t q = 1;
11 while (q <= num / 10) q *= 10;
12 while (n-- > 1 && q) {
13 *(s++) = (unsigned char)(num / q + '0');
14 num %= q;
15 #ifdef __DECC_VER
16 do_not_optimize_here(&q); /* compiler bug */
17 #endif
18 q /= 10;
19 }
20 *s = 0;
21 return !!q;
22 }
23
snzprint(unsigned char * s,int n,off_t num)24 int snzprint(unsigned char *s, int n, off_t num)
25 {
26 off_t q = 1;
27 if (n > 1 && num < 0) *(s++) = '-', num = -num, n--;
28 while (q <= num / 10) q *= 10;
29 while (n-- > 1 && q) {
30 *(s++) = (unsigned char)(num / q + '0');
31 num %= q;
32 #ifdef __DECC_VER
33 do_not_optimize_here(&q); /* compiler bug */
34 #endif
35 q /= 10;
36 }
37 *s = 0;
38 return !!q;
39 }
40
add_to_strn(unsigned char ** s,unsigned char * a)41 void add_to_strn(unsigned char **s, unsigned char *a)
42 {
43 unsigned char *p;
44 size_t l1 = strlen(cast_const_char *s), l2 = strlen(cast_const_char a);
45 if (((l1 | l2) | (l1 + l2 + 1)) > MAXINT) overalloc();
46 p = (unsigned char *)mem_realloc(*s, l1 + l2 + 1);
47 strcat(cast_char p, cast_const_char a);
48 *s = p;
49 }
50
extend_str(unsigned char ** s,int n)51 void extend_str(unsigned char **s, int n)
52 {
53 size_t l = strlen(cast_const_char *s);
54 if (((l | n) | (l + n + 1)) > MAXINT) overalloc();
55 *s = (unsigned char *)mem_realloc(*s, l + n + 1);
56 }
57
add_bytes_to_str(unsigned char ** s,int * l,unsigned char * a,size_t ll)58 void add_bytes_to_str(unsigned char **s, int *l, unsigned char *a, size_t ll)
59 {
60 unsigned char *p;
61 size_t old_length;
62 size_t new_length;
63 size_t x;
64
65 if (!ll)
66 return;
67
68 p = *s;
69 old_length = (unsigned)*l;
70 if (ll + old_length >= (unsigned)MAXINT / 2 || ll + old_length < ll) overalloc();
71 new_length = old_length + ll;
72 *l = (int)new_length;
73 x = old_length ^ new_length;
74 if (x >= old_length) {
75 /* Need to realloc */
76 #ifdef HAVE___BUILTIN_CLZ
77 #if !( \
78 defined(__tune_i386__) || \
79 defined(__tune_i486__) || \
80 defined(__tune_i586__) || \
81 defined(__tune_k6__) || \
82 defined(__tune_lakemont__) || \
83 (defined(__alpha__) && !defined(__alpha_cix__)) || \
84 (defined(__mips) && __mips < 32) || \
85 (defined(__ARM_ARCH) && __ARM_ARCH < 5) || \
86 (defined(__sparc__) && (!defined(__VIS__) || __VIS__ < 0x300)) ||\
87 defined(__hppa) || \
88 defined(__riscv) || \
89 defined(__sh__))
90 if (!(sizeof(unsigned) & (sizeof(unsigned) - 1))) {
91 new_length = 2U << ((sizeof(unsigned) * 8 - 1)
92 #ifdef __ICC
93 -
94 #else
95 ^
96 #endif
97 __builtin_clz(new_length));
98 } else
99 #endif
100 #endif
101 {
102 new_length |= new_length >> 1;
103 new_length |= new_length >> 2;
104 new_length |= new_length >> 4;
105 new_length |= new_length >> 8;
106 new_length |= new_length >> 16;
107 new_length++;
108 }
109 p = (unsigned char *)mem_realloc(p, new_length);
110 *s = p;
111 }
112 p[*l] = 0;
113 memcpy(p + old_length, a, ll);
114 }
115
add_to_str(unsigned char ** s,int * l,unsigned char * a)116 void add_to_str(unsigned char **s, int *l, unsigned char *a)
117 {
118 add_bytes_to_str(s, l, a, strlen(cast_const_char a));
119 }
120
add_chr_to_str(unsigned char ** s,int * l,unsigned char a)121 void add_chr_to_str(unsigned char **s, int *l, unsigned char a)
122 {
123 add_bytes_to_str(s, l, &a, 1);
124 }
125
add_unsigned_long_num_to_str(unsigned char ** s,int * l,my_uintptr_t n)126 void add_unsigned_long_num_to_str(unsigned char **s, int *l, my_uintptr_t n)
127 {
128 unsigned char a[64];
129 snprint(a, 64, n);
130 add_to_str(s, l, a);
131 }
132
add_num_to_str(unsigned char ** s,int * l,off_t n)133 void add_num_to_str(unsigned char **s, int *l, off_t n)
134 {
135 unsigned char a[64];
136 if (n >= 0 && n < 1000) {
137 unsigned sn = (unsigned)n;
138 unsigned char *p = a;
139 if (sn >= 100) {
140 *p++ = '0' + sn / 100;
141 sn %= 100;
142 goto d10;
143 }
144 if (sn >= 10) {
145 d10:
146 *p++ = '0' + sn / 10;
147 sn %= 10;
148 }
149 *p++ = '0' + sn;
150 add_bytes_to_str(s, l, a, p - a);
151 } else {
152 snzprint(a, 64, n);
153 add_to_str(s, l, a);
154 }
155 }
156
add_knum_to_str(unsigned char ** s,int * l,off_t n)157 void add_knum_to_str(unsigned char **s, int *l, off_t n)
158 {
159 unsigned char a[13];
160 if (n && n / (1024 * 1024) * (1024 * 1024) == n) snzprint(a, 12, n / (1024 * 1024)), a[strlen(cast_const_char a) + 1] = 0, a[strlen(cast_const_char a)] = 'M';
161 else if (n && n / 1024 * 1024 == n) snzprint(a, 12, n / 1024), a[strlen(cast_const_char a) + 1] = 0, a[strlen(cast_const_char a)] = 'k';
162 else snzprint(a, 13, n);
163 add_to_str(s, l, a);
164 }
165
strtolx(unsigned char * c,unsigned char ** end)166 long strtolx(unsigned char *c, unsigned char **end)
167 {
168 char *end_c;
169 long l;
170 if (c[0] == '0' && upcase(c[1]) == 'X' && c[2]) l = strtol(cast_const_char(c + 2), &end_c, 16);
171 else l = strtol(cast_const_char c, &end_c, 10);
172 *end = cast_uchar end_c;
173 if (upcase(**end) == 'K') {
174 (*end)++;
175 if (l < -MAXINT / 1024) return -MAXINT;
176 if (l > MAXINT / 1024) return MAXINT;
177 return l * 1024;
178 }
179 if (upcase(**end) == 'M') {
180 (*end)++;
181 if (l < -MAXINT / (1024 * 1024)) return -MAXINT;
182 if (l > MAXINT / (1024 * 1024)) return MAXINT;
183 return l * (1024 * 1024);
184 }
185 return l;
186 }
187
my_strtoll(unsigned char * string,unsigned char ** end)188 my_strtoll_t my_strtoll(unsigned char *string, unsigned char **end)
189 {
190 char *end_c;
191 my_strtoll_t f;
192 errno = 0;
193 #if defined(HAVE_STRTOLL)
194 f = strtoll(cast_const_char string, &end_c, 10);
195 #elif defined(HAVE_STRTOQ)
196 f = strtoq(cast_const_char string, &end_c, 10);
197 #elif defined(HAVE_STRTOIMAX)
198 f = strtoimax(cast_const_char string, &end_c, 10);
199 #else
200 f = strtol(cast_const_char string, &end_c, 10);
201 #endif
202 if (end)
203 *end = cast_uchar end_c;
204 if (f < 0 || errno) return -1;
205 return f;
206 }
207
208 /* Copies at most dst_size chars into dst. Ensures null termination of dst. */
safe_strncpy(unsigned char * dst,const unsigned char * src,size_t dst_size)209 void safe_strncpy(unsigned char *dst, const unsigned char *src, size_t dst_size)
210 {
211 dst[dst_size - 1] = 0;
212 strncpy(cast_char dst, cast_const_char src, dst_size - 1);
213 }
214
215 #ifdef JS
216 /* deletes all nonprintable characters from string */
skip_nonprintable(unsigned char * txt)217 void skip_nonprintable(unsigned char *txt)
218 {
219 unsigned char *txt1=txt;
220
221 if (!txt||!*txt)return;
222 for (;*txt;txt++)
223 switch(*txt)
224 {
225 case 1:
226 case 2:
227 case 3:
228 case 4:
229 case 5:
230 case 6:
231 case 7:
232 case 8:
233 case 11:
234 case 12:
235 case 13:
236 case 14:
237 case 15:
238 case 16:
239 case 17:
240 case 18:
241 case 19:
242 case 20:
243 case 21:
244 case 22:
245 case 23:
246 case 24:
247 case 25:
248 case 26:
249 case 27:
250 case 28:
251 case 29:
252 case 30:
253 case 31:
254 break;
255
256 case 9:
257 *txt1=' ';
258 txt1++;
259 break;
260
261 default:
262 *txt1=*txt;
263 txt1++;
264 break;
265 }
266 *txt1=0;
267 }
268 #endif
269
270 /* don't use strcasecmp because it depends on locale */
casestrcmp(const unsigned char * s1,const unsigned char * s2)271 int casestrcmp(const unsigned char *s1, const unsigned char *s2)
272 {
273 while (1) {
274 unsigned char c1 = *s1;
275 unsigned char c2 = *s2;
276 c1 = locase(c1);
277 c2 = locase(c2);
278 if (c1 != c2) {
279 return (int)c1 - (int)c2;
280 }
281 if (!*s1) break;
282 s1++, s2++;
283 }
284 return 0;
285 }
286
287 /* case insensitive compare of 2 strings */
288 /* comparison ends after len (or less) characters */
289 /* return value: 1=strings differ, 0=strings are same */
casecmp(const unsigned char * c1,const unsigned char * c2,size_t len)290 int casecmp(const unsigned char *c1, const unsigned char *c2, size_t len)
291 {
292 size_t i;
293 for (i = 0; i < len; i++) if (srch_cmp(c1[i], c2[i])) return 1;
294 return 0;
295 }
296
casestrstr(const unsigned char * h,const unsigned char * n)297 int casestrstr(const unsigned char *h, const unsigned char *n)
298 {
299 const unsigned char *p;
300
301 for (p=h;*p;p++)
302 {
303 if (!srch_cmp(*p,*n)) /* same */
304 {
305 const unsigned char *q, *r;
306 for (q=n, r=p;*r&&*q;)
307 {
308 if (!srch_cmp(*q,*r)) r++,q++; /* same */
309 else break;
310 }
311 if (!*q) return 1;
312 }
313 }
314
315 return 0;
316 }
317
hash_string(unsigned char * u)318 unsigned hash_string(unsigned char *u)
319 {
320 unsigned hash = 0;
321 for (; *u; u++)
322 hash = hash * 0x11 + *u;
323 return hash;
324 }
325