… | |
… | |
20 | * This file provides replacements for some handy functions that aren't |
20 | * This file provides replacements for some handy functions that aren't |
21 | * available on all systems, like most of the <string.h> functions. They |
21 | * available on all systems, like most of the <string.h> functions. They |
22 | * should behave exactly as their counterparts. There are also extensions |
22 | * should behave exactly as their counterparts. There are also extensions |
23 | * that aren't portable at all (like strirstr etc.). |
23 | * that aren't portable at all (like strirstr etc.). |
24 | * The proper behaviour in a configure script is as follows: |
24 | * The proper behaviour in a configure script is as follows: |
25 | * AC_CHECK_FUNC(strrchr,AC_DEFINE(strrchr,_FP_strrchr)) |
25 | * AC_CHECK_FUNC(strrchr,AC_DEFINE(strrchr,FP_strrchr)) |
26 | * This way, the (probably less efficient) replacements will only be used |
26 | * This way, the (probably less efficient) replacements will only be used |
27 | * where it is not provided by the default libraries. Be aware that this |
27 | * where it is not provided by the default libraries. Be aware that this |
28 | * does not work with replacements that just shadow wrong behaviour (like |
28 | * does not work with replacements that just shadow wrong behaviour (like |
29 | * _FP_free) or provide extended functionality (FP_gets). |
29 | * FP_free) or provide extended functionality (FP_gets). |
30 | * The above is not used in the uuenview/uudeview configuration script, |
30 | * The above is not used in the uuenview/uudeview configuration script, |
31 | * since both only use the replacement functions in non-performance-cri- |
31 | * since both only use the replacement functions in non-performance-cri- |
32 | * tical sections (except for _FP_tempnam and FP_strerror, where some |
32 | * tical sections (except for FP_tempnam and FP_strerror, where some |
33 | * functionality of the original would be lost). |
33 | * functionality of the original would be lost). |
34 | */ |
34 | */ |
35 | |
35 | |
36 | #include <stdio.h> |
36 | #include <stdio.h> |
37 | #include <ctype.h> |
37 | #include <ctype.h> |
… | |
… | |
62 | return TRUE; |
62 | return TRUE; |
63 | } |
63 | } |
64 | #endif |
64 | #endif |
65 | #endif |
65 | #endif |
66 | |
66 | |
67 | char * fptools_id = "$Id: fptools.c,v 1.12 2020/02/14 08:02:26 root Exp $"; |
67 | char * fptools_id = "$Id: fptools.c,v 1.13 2020/12/11 20:09:23 root Exp $"; |
68 | |
68 | |
69 | /* |
69 | /* |
70 | * some versions of free can't handle a NULL pointer properly |
70 | * some versions of free can't handle a NULL pointer properly |
71 | * (ANSI says, free ignores a NULL pointer, but some machines |
71 | * (ANSI says, free ignores a NULL pointer, but some machines |
72 | * prefer to SIGSEGV on it) |
72 | * prefer to SIGSEGV on it) |
73 | */ |
73 | */ |
74 | |
74 | |
75 | void TOOLEXPORT |
75 | void TOOLEXPORT |
76 | _FP_free (void *ptr) |
76 | FP_free (void *ptr) |
77 | { |
77 | { |
78 | if (ptr) free (ptr); |
78 | if (ptr) free (ptr); |
79 | } |
79 | } |
80 | |
80 | |
81 | /* |
81 | /* |
82 | * This is non-standard, so I'm defining my own |
82 | * This is non-standard, so I'm defining my own |
83 | */ |
83 | */ |
84 | |
84 | |
85 | char * TOOLEXPORT |
85 | char * TOOLEXPORT |
86 | _FP_strdup (char *string) |
86 | FP_strdup (char *string) |
87 | { |
87 | { |
88 | char *result; |
88 | char *result; |
89 | |
89 | |
90 | if (string == NULL) |
90 | if (string == NULL) |
91 | return NULL; |
91 | return NULL; |
… | |
… | |
102 | * the original in that the dest string is always terminated with a |
102 | * the original in that the dest string is always terminated with a |
103 | * NULL character. |
103 | * NULL character. |
104 | */ |
104 | */ |
105 | |
105 | |
106 | char * TOOLEXPORT |
106 | char * TOOLEXPORT |
107 | _FP_strncpy (char *dest, char *src, int length) |
107 | FP_strncpy (char *dest, char *src, int length) |
108 | { |
108 | { |
109 | char *odest=dest; |
109 | char *odest=dest; |
110 | if (src == NULL || dest == NULL || length-- <= 0) |
110 | if (src == NULL || dest == NULL || length-- <= 0) |
111 | return dest; |
111 | return dest; |
112 | |
112 | |
… | |
… | |
120 | /* |
120 | /* |
121 | * duplicate a memory area |
121 | * duplicate a memory area |
122 | */ |
122 | */ |
123 | |
123 | |
124 | void * TOOLEXPORT |
124 | void * TOOLEXPORT |
125 | _FP_memdup (void *ptr, int len) |
125 | FP_memdup (void *ptr, int len) |
126 | { |
126 | { |
127 | void *result; |
127 | void *result; |
128 | |
128 | |
129 | if (ptr == NULL) |
129 | if (ptr == NULL) |
130 | return NULL; |
130 | return NULL; |
… | |
… | |
140 | * case-insensitive compare |
140 | * case-insensitive compare |
141 | */ |
141 | */ |
142 | |
142 | |
143 | #ifndef FP_stricmp |
143 | #ifndef FP_stricmp |
144 | int TOOLEXPORT |
144 | int TOOLEXPORT |
145 | _FP_stricmp (const char *str1, const char *str2) |
145 | FP_stricmp (const char *str1, const char *str2) |
146 | { |
146 | { |
147 | if (str1==NULL || str2==NULL) |
147 | if (str1==NULL || str2==NULL) |
148 | return -1; |
148 | return -1; |
149 | |
149 | |
150 | while (*str1) { |
150 | while (*str1) { |
… | |
… | |
157 | } |
157 | } |
158 | #endif |
158 | #endif |
159 | |
159 | |
160 | #ifndef FP_strnicmp |
160 | #ifndef FP_strnicmp |
161 | int TOOLEXPORT |
161 | int TOOLEXPORT |
162 | _FP_strnicmp (const char *str1, const char *str2, int count) |
162 | FP_strnicmp (const char *str1, const char *str2, int count) |
163 | { |
163 | { |
164 | if (str1==NULL || str2==NULL) |
164 | if (str1==NULL || str2==NULL) |
165 | return -1; |
165 | return -1; |
166 | |
166 | |
167 | while (*str1 && count) { |
167 | while (*str1 && count) { |
… | |
… | |
174 | return count ? (tolower (*str1) - tolower (*str2)) : 0; |
174 | return count ? (tolower (*str1) - tolower (*str2)) : 0; |
175 | } |
175 | } |
176 | #endif |
176 | #endif |
177 | |
177 | |
178 | char * TOOLEXPORT |
178 | char * TOOLEXPORT |
179 | _FP_strpbrk (char *str, char *accept) |
179 | FP_strpbrk (char *str, char *accept) |
180 | { |
180 | { |
181 | char *ptr; |
181 | char *ptr; |
182 | |
182 | |
183 | if (str == NULL) |
183 | if (str == NULL) |
184 | return NULL; |
184 | return NULL; |
… | |
… | |
196 | /* |
196 | /* |
197 | * autoconf also complains about this one |
197 | * autoconf also complains about this one |
198 | */ |
198 | */ |
199 | |
199 | |
200 | char * TOOLEXPORT |
200 | char * TOOLEXPORT |
201 | _FP_strtok (char *str1, char *str2) |
201 | FP_strtok (char *str1, char *str2) |
202 | { |
202 | { |
203 | static char *optr; |
203 | static char *optr; |
204 | char *ptr; |
204 | char *ptr; |
205 | |
205 | |
206 | if (str2 == NULL) |
206 | if (str2 == NULL) |
… | |
… | |
234 | * case insensitive strstr. |
234 | * case insensitive strstr. |
235 | */ |
235 | */ |
236 | |
236 | |
237 | #ifndef FP_stristr |
237 | #ifndef FP_stristr |
238 | char * TOOLEXPORT |
238 | char * TOOLEXPORT |
239 | _FP_stristr (char *str1, char *str2) |
239 | FP_stristr (char *str1, char *str2) |
240 | { |
240 | { |
241 | char *ptr1, *ptr2; |
241 | char *ptr1, *ptr2; |
242 | |
242 | |
243 | if (str1==NULL) |
243 | if (str1==NULL) |
244 | return NULL; |
244 | return NULL; |
… | |
… | |
262 | /* |
262 | /* |
263 | * Nice fake of the real (non-standard) one |
263 | * Nice fake of the real (non-standard) one |
264 | */ |
264 | */ |
265 | |
265 | |
266 | char * TOOLEXPORT |
266 | char * TOOLEXPORT |
267 | _FP_strrstr (char *ptr, char *str) |
267 | FP_strrstr (char *ptr, char *str) |
268 | { |
268 | { |
269 | char *found=NULL, *new, *iter=ptr; |
269 | char *found=NULL, *new, *iter=ptr; |
270 | |
270 | |
271 | if (ptr==NULL || str==NULL) |
271 | if (ptr==NULL || str==NULL) |
272 | return NULL; |
272 | return NULL; |
273 | |
273 | |
274 | if (*str == '\0') |
274 | if (*str == '\0') |
275 | return ptr; |
275 | return ptr; |
276 | |
276 | |
277 | while ((new = _FP_strstr (iter, str)) != NULL) { |
277 | while ((new = FP_strstr (iter, str)) != NULL) { |
278 | found = new; |
278 | found = new; |
279 | iter = new + 1; |
279 | iter = new + 1; |
280 | } |
280 | } |
281 | return found; |
281 | return found; |
282 | } |
282 | } |
283 | |
283 | |
284 | char * TOOLEXPORT |
284 | char * TOOLEXPORT |
285 | _FP_strirstr (char *ptr, char *str) |
285 | FP_strirstr (char *ptr, char *str) |
286 | { |
286 | { |
287 | char *found=NULL, *iter=ptr, *new; |
287 | char *found=NULL, *iter=ptr, *new; |
288 | |
288 | |
289 | if (ptr==NULL || str==NULL) |
289 | if (ptr==NULL || str==NULL) |
290 | return NULL; |
290 | return NULL; |
291 | if (*str == '\0') |
291 | if (*str == '\0') |
292 | return ptr; |
292 | return ptr; |
293 | |
293 | |
294 | while ((new = _FP_stristr (iter, str)) != NULL) { |
294 | while ((new = FP_stristr (iter, str)) != NULL) { |
295 | found = new; |
295 | found = new; |
296 | iter = new + 1; |
296 | iter = new + 1; |
297 | } |
297 | } |
298 | return found; |
298 | return found; |
299 | } |
299 | } |
… | |
… | |
301 | /* |
301 | /* |
302 | * convert whole string to case |
302 | * convert whole string to case |
303 | */ |
303 | */ |
304 | |
304 | |
305 | char * TOOLEXPORT |
305 | char * TOOLEXPORT |
306 | _FP_stoupper (char *input) |
306 | FP_stoupper (char *input) |
307 | { |
307 | { |
308 | char *iter = input; |
308 | char *iter = input; |
309 | |
309 | |
310 | if (input == NULL) |
310 | if (input == NULL) |
311 | return NULL; |
311 | return NULL; |
… | |
… | |
316 | } |
316 | } |
317 | return input; |
317 | return input; |
318 | } |
318 | } |
319 | |
319 | |
320 | char * TOOLEXPORT |
320 | char * TOOLEXPORT |
321 | _FP_stolower (char *input) |
321 | FP_stolower (char *input) |
322 | { |
322 | { |
323 | char *iter = input; |
323 | char *iter = input; |
324 | |
324 | |
325 | if (input == NULL) |
325 | if (input == NULL) |
326 | return NULL; |
326 | return NULL; |
… | |
… | |
335 | /* |
335 | /* |
336 | * string matching with wildcards |
336 | * string matching with wildcards |
337 | */ |
337 | */ |
338 | |
338 | |
339 | int TOOLEXPORT |
339 | int TOOLEXPORT |
340 | _FP_strmatch (char *string, char *pattern) |
340 | FP_strmatch (char *string, char *pattern) |
341 | { |
341 | { |
342 | char *p1 = string, *p2 = pattern; |
342 | char *p1 = string, *p2 = pattern; |
343 | |
343 | |
344 | if (pattern==NULL || string==NULL) |
344 | if (pattern==NULL || string==NULL) |
345 | return 0; |
345 | return 0; |
… | |
… | |
365 | |
365 | |
366 | return 1; |
366 | return 1; |
367 | } |
367 | } |
368 | |
368 | |
369 | char * TOOLEXPORT |
369 | char * TOOLEXPORT |
370 | _FP_strrchr (char *string, int tc) |
370 | FP_strrchr (char *string, int tc) |
371 | { |
371 | { |
372 | char *ptr; |
372 | char *ptr; |
373 | |
373 | |
374 | if (string == NULL || !*string) |
374 | if (string == NULL || !*string) |
375 | return NULL; |
375 | return NULL; |
… | |
… | |
389 | * strip directory information from a filename. Works only on DOS and |
389 | * strip directory information from a filename. Works only on DOS and |
390 | * Unix systems so far ... |
390 | * Unix systems so far ... |
391 | */ |
391 | */ |
392 | |
392 | |
393 | char * TOOLEXPORT |
393 | char * TOOLEXPORT |
394 | _FP_cutdir (char *filename) |
394 | FP_cutdir (char *filename) |
395 | { |
395 | { |
396 | char *ptr; |
396 | char *ptr; |
397 | |
397 | |
398 | if (filename == NULL) |
398 | if (filename == NULL) |
399 | return NULL; |
399 | return NULL; |
400 | |
400 | |
401 | if ((ptr = _FP_strrchr (filename, '/')) != NULL) |
401 | if ((ptr = FP_strrchr (filename, '/')) != NULL) |
402 | ptr++; |
402 | ptr++; |
403 | else if ((ptr = _FP_strrchr (filename, '\\')) != NULL) |
403 | else if ((ptr = FP_strrchr (filename, '\\')) != NULL) |
404 | ptr++; |
404 | ptr++; |
405 | else |
405 | else |
406 | ptr = filename; |
406 | ptr = filename; |
407 | |
407 | |
408 | return ptr; |
408 | return ptr; |
… | |
… | |
413 | * properly: LF (Unix), CRLF (DOS) and CR (Mac). |
413 | * properly: LF (Unix), CRLF (DOS) and CR (Mac). |
414 | */ |
414 | */ |
415 | /* (schmorp) the buffer is always written to, and no LF is stored at the end */ |
415 | /* (schmorp) the buffer is always written to, and no LF is stored at the end */ |
416 | /* also, if the buffer is too short, the remaining line is skipped */ |
416 | /* also, if the buffer is too short, the remaining line is skipped */ |
417 | char * TOOLEXPORT |
417 | char * TOOLEXPORT |
418 | _FP_fgets (char *buf, int n, FILE *stream) |
418 | FP_fgets (char *buf, int n, FILE *stream) |
419 | { |
419 | { |
420 | char *ptr = buf; |
420 | char *ptr = buf; |
421 | char *end = buf + n - 1; |
421 | char *end = buf + n - 1; |
422 | |
422 | |
423 | /* shield against buffer overflows caused by "255 - bytes_left"-kind of bugs when bytes_left > 255 */ |
423 | /* shield against buffer overflows caused by "255 - bytes_left"-kind of bugs when bytes_left > 255 */ |
424 | if (n <= 0) |
424 | if (n <= 0) |
425 | return 0; |
425 | return 0; |
426 | |
426 | |
427 | for (;;) |
427 | for (;;) |
428 | { |
428 | { |
429 | int c = FP_fgetc (stream); |
429 | int c = FP_getc (stream); |
430 | |
430 | |
431 | if (ecb_expect_false (c <= '\015')) /* EOF is < 0x20, too */ |
431 | if (ecb_expect_false (c <= '\015')) /* EOF is < 0x20, too */ |
432 | { |
432 | { |
433 | /* ctlchar */ |
433 | /* ctlchar */ |
434 | |
434 | |
… | |
… | |
436 | /* LF, nothing following */ |
436 | /* LF, nothing following */ |
437 | break; |
437 | break; |
438 | else if (c == '\015') |
438 | else if (c == '\015') |
439 | { |
439 | { |
440 | /* CR, possibly CRLF, skip following LF */ |
440 | /* CR, possibly CRLF, skip following LF */ |
441 | c = FP_fgetc (stream); |
441 | c = FP_getc (stream); |
442 | |
442 | |
443 | if (c != '\012') /* CR LF? */ |
443 | if (c != '\012') /* CR LF? */ |
444 | ungetc (c, stream); |
444 | ungetc (c, stream); |
445 | |
445 | |
446 | break; |
446 | break; |
… | |
… | |
463 | /* |
463 | /* |
464 | * A replacement strerror function that just returns the error code |
464 | * A replacement strerror function that just returns the error code |
465 | */ |
465 | */ |
466 | |
466 | |
467 | char * TOOLEXPORT |
467 | char * TOOLEXPORT |
468 | _FP_strerror (int errcode) |
468 | FP_strerror (int errcode) |
469 | { |
469 | { |
470 | static char number[8]; |
470 | static char number[8]; |
471 | |
471 | |
472 | sprintf (number, "%03d", errcode); |
472 | sprintf (number, "%03d", errcode); |
473 | |
473 | |
… | |
… | |
477 | /* |
477 | /* |
478 | * tempnam is not ANSI, but tmpnam is. Ignore the prefix here. |
478 | * tempnam is not ANSI, but tmpnam is. Ignore the prefix here. |
479 | */ |
479 | */ |
480 | |
480 | |
481 | char * TOOLEXPORT |
481 | char * TOOLEXPORT |
482 | _FP_tempnam (char *dir, char *pfx) |
482 | FP_tempnam (char *dir, char *pfx) |
483 | { |
483 | { |
484 | return _FP_strdup (tmpnam (NULL)); |
484 | return FP_strdup (tmpnam (NULL)); |
485 | } |
485 | } |
486 | #endif /* HAVE_MKSTEMP */ |
486 | #endif /* HAVE_MKSTEMP */ |