blob: c774bd724c6680ed785b4da73ed16010edd06d04 [file] [log] [blame]
Alistair Delvabeaee832021-02-24 11:27:23 -08001/* Copyright 1991 Free Software Foundation, Inc.
2 * Copyright 1997,1999-2002,2007-2009 Alain Knaff.
3 * This file is part of mtools.
4 *
5 * Mtools is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Mtools is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
17 */
18#include "sysincludes.h"
19#include "mtools.h"
20
21#ifndef HAVE_STRDUP
22
23
24char *strdup(const char *str)
25{
26 char *nstr;
27
28 if (str == (char*)0)
29 return 0;
30
31 nstr = (char*)malloc((strlen(str) + 1));
32
33 if (nstr == (char*)0)
34 {
35 (void)fprintf(stderr, "strdup(): not enough memory to duplicate `%s'\n",
36 str);
37 exit(1);
38 }
39
40 (void)strcpy(nstr, str);
41
42 return nstr;
43}
44#endif /* HAVE_STRDUP */
45
46#ifndef HAVE_STRNDUP
47char *strndup( const char *s, size_t n )
48{
49 size_t nAvail;
50 char *p;
51
52 if ( !s )
53 return 0;
54
55 nAvail = min( strlen(s) + 1, n + 1 );
56 p = malloc( nAvail );
57 if ( !p )
58 return 0;
59 memcpy( p, s, nAvail );
60 p[nAvail - 1] = '\0';
61
62 return p;
63}
64#endif /* HAVE_STRNDUP */
65
66
67#ifdef HAVE_WCHAR_H
68#ifndef HAVE_WCSDUP
69wchar_t *wcsdup(const wchar_t *wcs)
70{
71 wchar_t *nwcs;
72
73 if (wcs == (wchar_t*)0)
74 return 0;
75
76 nwcs = (wchar_t*)calloc(wcslen(wcs) + 1, sizeof(wchar_t));
77
78 if (nwcs == (wchar_t*)0)
79 {
80 (void)fprintf(stderr, "wcsdup(): not enough memory to duplicate `%ls'\n",
81 wcs);
82 exit(1);
83 }
84
85 (void)wcscpy(nwcs, wcs);
86
87 return nwcs;
88}
89#endif /* HAVE_WCSDUP */
90#endif
91
92#ifndef HAVE_MEMCPY
93/*
94 * Copy contents of memory (with possible overlapping).
95 */
96char *memcpy(char *s1, const char *s2, size_t n)
97{
98 bcopy(s2, s1, n);
99 return(s1);
100}
101#endif
102
103#ifndef HAVE_MEMSET
104/*
105 * Copies the character c, n times to string s
106 */
107char *memset(char *s, char c, size_t n)
108{
109 char *s1 = s;
110
111 while (n > 0) {
112 --n;
113 *s++ = c;
114 }
115 return(s1);
116}
117#endif /* HAVE_MEMSET */
118
119
120#ifndef HAVE_STRCHR
121
122char * strchr (const char* s, int c)
123{
124 if (!s) return NULL;
125 while (*s && *s != c) s++;
Yi Kong39bbd962022-01-09 19:41:38 +0800126 if (*s)
Alistair Delvabeaee832021-02-24 11:27:23 -0800127 return (char*) s;
128 else
129 return NULL;
130}
131
132#endif
133
134#ifndef HAVE_STRRCHR
135
Yi Kong39bbd962022-01-09 19:41:38 +0800136char * strrchr (const char* s1, int c)
Alistair Delvabeaee832021-02-24 11:27:23 -0800137{
138 char* s = (char*) s1;
139 char* start = (char*) s;
140 if (!s) return NULL;
141 s += strlen(s)-1;
142 while (*s != c && (unsigned long) s != (unsigned long) start) s--;
143 if ((unsigned long) s == (unsigned long) start && *s != c)
144 return NULL;
145 else
146 return s;
147}
148
149#endif
150
151#ifndef HAVE_STRPBRK
152/*
153 * Return ptr to first occurrence of any character from `brkset'
154 * in the character string `string'; NULL if none exists.
155 */
156char *strpbrk(const char *string, const char *brkset)
157{
158 register char *p;
159
160 if (!string || !brkset)
161 return(0);
162 do {
163 for (p = brkset; *p != '\0' && *p != *string; ++p)
164 ;
165 if (*p != '\0')
166 return(string);
167 }
168 while (*string++);
169 return(0);
170}
171#endif /* HAVE_STRPBRK */
172
173
174#ifndef HAVE_STRTOUL
175static int getdigit(char a, int max)
176{
177 int dig;
Yi Kong39bbd962022-01-09 19:41:38 +0800178
Alistair Delvabeaee832021-02-24 11:27:23 -0800179 if(a < '0')
180 return -1;
181 if(a <= '9') {
182 dig = a - '0';
183 } else if(a >= 'a')
184 dig = a - 'a' + 10;
185 else if(a >= 'A')
186 dig = a - 'A' + 10;
187 if(dig >= max)
188 return -1;
189 else
190 return dig;
191}
192
193unsigned long strtoul(const char *string, char **eptr, int base)
194{
195 int accu, dig;
196
197 if(base < 1 || base > 36) {
198 if(string[0] == '0') {
199 switch(string[1]) {
200 case 'x':
201 case 'X':
202 return strtoul(string+2, eptr, 16);
203 case 'b':
204 case 'B':
205 return strtoul(string+2, eptr, 2);
206 default:
207 return strtoul(string, eptr, 8);
208 }
209 }
210 return strtoul(string, eptr, 10);
211 }
212 if(base == 16 && string[0] == '0' &&
213 (string[1] == 'x' || string[1] == 'X'))
214 string += 2;
215
216 if(base == 2 && string[0] == '0' &&
217 (string[1] == 'b' || string[1] == 'B'))
218 string += 2;
219 accu = 0;
220 while( (dig = getdigit(*string, base)) != -1 ) {
221 accu = accu * base + dig;
222 string++;
223 }
224 if(eptr)
225 *eptr = (char *) string;
226 return accu;
227}
228#endif /* HAVE_STRTOUL */
229
230#ifndef HAVE_STRTOL
231long strtol(const char *string, char **eptr, int base)
232{
233 long l;
234
235 if(*string == '-') {
236 return -(long) strtoul(string+1, eptr, base);
237 } else {
238 if (*string == '+')
239 string ++;
240 return (long) strtoul(string, eptr, base);
241 }
242}
243#endif
244
245
246
247#ifndef HAVE_STRSPN
248/* Return the length of the maximum initial segment
249 of S which contains only characters in ACCEPT. */
250size_t strspn(const char *s, const char *accept)
251{
252 register char *p;
253 register char *a;
254 register size_t count = 0;
255
256 for (p = s; *p != '\0'; ++p)
257 {
258 for (a = accept; *a != '\0'; ++a)
259 if (*p == *a)
260 break;
261 if (*a == '\0')
262 return count;
263 else
264 ++count;
265 }
266
267 return count;
268}
269#endif /* HAVE_STRSPN */
270
271#ifndef HAVE_STRCSPN
272/* Return the length of the maximum initial segment of S
273 which contains no characters from REJECT. */
274size_t strcspn (const char *s, const char *reject)
275{
276 register size_t count = 0;
277
278 while (*s != '\0')
279 if (strchr (reject, *s++) == NULL)
280 ++count;
281 else
282 return count;
283
284 return count;
285}
286
287#endif /* HAVE_STRCSPN */
288
289#ifndef HAVE_STRERROR
290
291#ifndef DECL_SYS_ERRLIST
292extern char *sys_errlist[];
293#endif
294
295char *strerror(int errno)
296{
297 return sys_errlist[errno];
298}
299#endif
300
301#ifndef HAVE_STRCASECMP
302/* Compare S1 and S2, ignoring case, returning less than, equal to or
303 greater than zero if S1 is lexiographically less than,
304 equal to or greater than S2. */
305int strcasecmp(const char *s1, const char *s2)
306{
307 register const unsigned char *p1 = (const unsigned char *) s1;
308 register const unsigned char *p2 = (const unsigned char *) s2;
309 unsigned char c1, c2;
310
311 if (p1 == p2)
312 return 0;
313
314 do
315 {
316 c1 = tolower (*p1++);
317 c2 = tolower (*p2++);
318 if (c1 == '\0')
319 break;
320 }
321 while (c1 == c2);
322
323 return c1 - c2;
324}
325#endif
326
327#ifdef HAVE_WCHAR_H
328#ifndef HAVE_WCSCASECMP
329/* Compare S1 and S2, ignoring case, returning less than, equal to or
330 greater than zero if S1 is lexiographically less than,
331 equal to or greater than S2. */
332int wcscasecmp(const wchar_t *s1, const wchar_t *s2)
333{
334 register const wchar_t *p1 = s1;
335 register const wchar_t *p2 = s2;
336 wchar_t c1, c2;
337
338 if (p1 == p2)
339 return 0;
340
341 do
342 {
343 c1 = towlower (*p1++);
344 c2 = towlower (*p2++);
345 if (c1 == '\0')
346 break;
347 }
348 while (c1 == c2);
349
350 return c1 - c2;
351}
352#endif
353#endif
354
355
356#ifndef HAVE_STRCASECMP
357/* Compare S1 and S2, ignoring case, returning less than, equal to or
358 greater than zero if S1 is lexiographically less than,
359 equal to or greater than S2. */
360int strncasecmp(const char *s1, const char *s2, size_t n)
361{
362 register const unsigned char *p1 = (const unsigned char *) s1;
363 register const unsigned char *p2 = (const unsigned char *) s2;
364 unsigned char c1, c2;
365
366 if (p1 == p2)
367 return 0;
368
369 c1 = c2 = 1;
370 while (c1 && c1 == c2 && n-- > 0)
371 {
372 c1 = tolower (*p1++);
373 c2 = tolower (*p2++);
374 }
375
376 return c1 - c2;
377}
378#endif
379
380#ifndef HAVE_GETPASS
381char *getpass(const char *prompt)
382{
383 static char password[129];
384 int l;
385
386 fprintf(stderr,"%s",prompt);
387 fgets(password, 128, stdin);
388 l = strlen(password);
389 if(l && password[l-1] == '\n')
390 password[l-1] = '\0';
391 return password;
392
393}
394#endif
395
396#ifndef HAVE_ATEXIT
397
398#ifdef HAVE_ON_EXIT
399int atexit(void (*function)(void))
400{
401 return on_exit( (void(*)(int,void*)) function, 0);
402}
403#else
404
405typedef struct exitCallback {
406 void (*function) (void);
407 struct exitCallback *next;
408} exitCallback_t;
409
410static exitCallback_t *callback = 0;
411
412int atexit(void (*function) (void))
413{
414 exitCallback_t *newCallback;
Yi Kong39bbd962022-01-09 19:41:38 +0800415
Alistair Delvabeaee832021-02-24 11:27:23 -0800416 newCallback = New(exitCallback_t);
417 if(!newCallback) {
418 printOom();
419 exit(1);
420 }
421 newCallback->function = function;
422 newCallback->next = callback;
423 callback = newCallback;
424 return 0;
425}
426#undef exit
427
428void myexit(int code)
429{
430 void (*function)(void);
431
432 while(callback) {
433 function = callback->function;
434 callback = callback->next;
435 function();
436 }
437 exit(code);
438}
439
440#endif
441
442#endif
443
444static const char PATH_SEP = '/';
445
446/*#ifndef HAVE_BASENAME*/
447const char *_basename(const char *filename)
448{
449 char *ptr;
450
451 ptr = strrchr(filename, PATH_SEP);
452 if(ptr)
453 filename = ptr + 1;
454
455#ifdef OS_mingw32msvc
456 ptr = strrchr(filename, '\\');
457 if(ptr)
458 filename = ptr + 1;
459#endif
460
461 return filename;
462}
463/*#endif*/
464
465/* Strip the suffix ".exe" from the argument, if present. */
466void _stripexe(char *filename)
467{
468 char *ptr;
469 ptr = strrchr(filename, '.');
470 if(ptr && !strcasecmp(ptr, ".exe"))
471 *ptr = '\0';
472}
473
474#ifndef HAVE_STRNLEN
475size_t strnlen(const char *str, size_t l)
476{
477 size_t i;
478 for(i=0; i<l; i++) {
479 if(str[i] == 0)
480 break;
481 }
482 return i;
483}
484#endif /* HAVE_STRNLEN */
485
486#ifdef HAVE_WCHAR_H
487#ifndef HAVE_WCSNLEN
488size_t wcsnlen(const wchar_t *wcs, size_t l)
489{
490 size_t i;
491 for(i=0; i<l; i++) {
492 if(wcs[i] == 0)
493 break;
494 }
495 return i;
496}
497#endif /* HAVE_WCSNLEN */
498#endif