ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/fptools.c
(Generate patch)

Comparing Convert-UUlib/uulib/fptools.c (file contents):
Revision 1.3.2.5 by root, Sun Apr 18 19:55:46 2004 UTC vs.
Revision 1.21 by root, Sat Sep 24 06:22:47 2022 UTC

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>
38
39#ifdef STDC_HEADERS
40#include <stdlib.h> 38#include <stdlib.h>
41#include <string.h> 39#include <string.h>
42#endif 40
43#ifdef HAVE_MALLOC_H
44#include <malloc.h>
45#endif
46#ifdef HAVE_UNISTD_H 41#ifdef HAVE_UNISTD_H
47#include <unistd.h> 42#include <unistd.h>
48#endif
49#ifdef HAVE_MEMORY_H
50#include <memory.h>
51#endif 43#endif
52 44
53#include <fptools.h> 45#include <fptools.h>
54 46
55#if 0 47#if 0
62 return TRUE; 54 return TRUE;
63} 55}
64#endif 56#endif
65#endif 57#endif
66 58
67char * fptools_id = "$Id: fptools.c,v 1.3.2.5 2004/04/18 19:55:46 root Exp $";
68
69/* 59/*
70 * some versions of free can't handle a NULL pointer properly 60 * some versions of free can't handle a NULL pointer properly
71 * (ANSI says, free ignores a NULL pointer, but some machines 61 * (ANSI says, free ignores a NULL pointer, but some machines
72 * prefer to SIGSEGV on it) 62 * prefer to SIGSEGV on it)
73 */ 63 */
74 64
75void TOOLEXPORT 65void TOOLEXPORT
76_FP_free (void *ptr) 66FP_free (void *ptr)
77{ 67{
78 if (ptr) free (ptr); 68 if (ptr) free (ptr);
79} 69}
80 70
81/* 71/*
82 * This is non-standard, so I'm defining my own 72 * This is non-standard, so I'm defining my own
83 */ 73 */
84 74
85char * TOOLEXPORT 75char * TOOLEXPORT
86_FP_strdup (char *string) 76FP_strdup (char *string)
87{ 77{
88 char *result; 78 char *result;
89 79
90 if (string == NULL) 80 if (string == NULL)
91 return NULL; 81 return NULL;
102 * the original in that the dest string is always terminated with a 92 * the original in that the dest string is always terminated with a
103 * NULL character. 93 * NULL character.
104 */ 94 */
105 95
106char * TOOLEXPORT 96char * TOOLEXPORT
107_FP_strncpy (char *dest, char *src, int length) 97FP_strncpy (char *dest, char *src, int length)
108{ 98{
109 char *odest=dest; 99 char *odest=dest;
110 if (src == NULL || dest == NULL || length-- <= 0) 100 if (src == NULL || dest == NULL || length-- <= 0)
111 return dest; 101 return dest;
112 102
120/* 110/*
121 * duplicate a memory area 111 * duplicate a memory area
122 */ 112 */
123 113
124void * TOOLEXPORT 114void * TOOLEXPORT
125_FP_memdup (void *ptr, int len) 115FP_memdup (const void *ptr, int len)
126{ 116{
127 void *result; 117 void *result;
128 118
129 if (ptr == NULL) 119 if (ptr == NULL)
130 return NULL; 120 return NULL;
138 128
139/* 129/*
140 * case-insensitive compare 130 * case-insensitive compare
141 */ 131 */
142 132
133#ifndef FP_stricmp
143int TOOLEXPORT 134int TOOLEXPORT
144_FP_stricmp (char *str1, char *str2) 135FP_stricmp (const char *str1, const char *str2)
145{ 136{
146 if (str1==NULL || str2==NULL) 137 if (str1==NULL || str2==NULL)
147 return -1; 138 return -1;
148 139
149 while (*str1) { 140 while (*str1) {
152 str1++; 143 str1++;
153 str2++; 144 str2++;
154 } 145 }
155 return (tolower (*str1) - tolower (*str2)); 146 return (tolower (*str1) - tolower (*str2));
156} 147}
148#endif
157 149
150#ifndef FP_strnicmp
158int TOOLEXPORT 151int TOOLEXPORT
159_FP_strnicmp (char *str1, char *str2, int count) 152FP_strnicmp (const char *str1, const char *str2, int count)
160{ 153{
161 if (str1==NULL || str2==NULL) 154 int d;
155
156 if (!str1 || !str2)
162 return -1; 157 return -1;
163 158
164 while (*str1 && count) { 159 while (count--) {
160 if (!*str1)
161 return -1;
162
165 if (tolower(*str1) != tolower(*str2)) 163 d = tolower (*str1) - tolower (*str2);
166 break; 164 if (d)
165 return d;
166
167 str1++; 167 str1++;
168 str2++; 168 str2++;
169 count--;
170 } 169 }
171 return count ? (tolower (*str1) - tolower (*str2)) : 0;
172}
173 170
174/* 171 return 0;
175 * autoconf says this function might be a compatibility problem 172}
176 */ 173#endif
177 174
178char * TOOLEXPORT 175int TOOLEXPORT
179_FP_strstr (char *str1, char *str2) 176FP_strnicmp_fast (const char *str1, const char *str2, int count)
180{ 177{
181 char *ptr1, *ptr2; 178 if (!str1 || !str2)
182
183 if (str1==NULL)
184 return NULL;
185 if (str2==NULL)
186 return str1; 179 return -1;
187 180
188 while (*(ptr1=str1)) { 181 while (count--) {
189 for (ptr2=str2; 182 if (!*str1)
190 *ptr1 && *ptr2 && *ptr1==*ptr2;
191 ptr1++, ptr2++)
192 /* empty loop */ ;
193
194 if (*ptr2 == '\0')
195 return str1; 183 return -1;
184
185 if ((*str1 ^ *str2) & 0xdf)
186 return (*str1 & 0xdf) - (*str2 & 0xdf);
187
196 str1++; 188 str1++;
189 str2++;
197 } 190 }
191
198 return NULL; 192 return 0;
199} 193}
200 194
201char * TOOLEXPORT 195char * TOOLEXPORT
202_FP_strpbrk (char *str, char *accept) 196FP_strpbrk (char *str, char *accept)
203{ 197{
204 char *ptr; 198 char *ptr;
205 199
206 if (str == NULL) 200 if (str == NULL)
207 return NULL; 201 return NULL;
219/* 213/*
220 * autoconf also complains about this one 214 * autoconf also complains about this one
221 */ 215 */
222 216
223char * TOOLEXPORT 217char * TOOLEXPORT
224_FP_strtok (char *str1, char *str2) 218FP_strtok (char *str1, char *str2)
225{ 219{
226 static char *optr; 220 static char *optr;
227 char *ptr; 221 char *ptr;
228 222
229 if (str2 == NULL) 223 if (str2 == NULL)
255 249
256/* 250/*
257 * case insensitive strstr. 251 * case insensitive strstr.
258 */ 252 */
259 253
254#ifndef FP_stristr
260char * TOOLEXPORT 255char * TOOLEXPORT
261_FP_stristr (char *str1, char *str2) 256FP_stristr (char *str1, char *str2)
262{ 257{
263 char *ptr1, *ptr2; 258 char *ptr1, *ptr2;
264 259
265 if (str1==NULL) 260 if (str1==NULL)
266 return NULL; 261 return NULL;
277 return str1; 272 return str1;
278 str1++; 273 str1++;
279 } 274 }
280 return NULL; 275 return NULL;
281} 276}
277#endif
282 278
283/* 279/*
284 * Nice fake of the real (non-standard) one 280 * Nice fake of the real (non-standard) one
285 */ 281 */
286 282
287char * TOOLEXPORT 283char * TOOLEXPORT
288_FP_strrstr (char *ptr, char *str) 284FP_strrstr (const char *ptr, const char *str)
289{ 285{
290 char *found=NULL, *new, *iter=ptr; 286 const char *found=NULL, *new, *iter=ptr;
291 287
292 if (ptr==NULL || str==NULL) 288 if (ptr==NULL || str==NULL)
293 return NULL; 289 return NULL;
294 290
291 if (*str == '\0')
292 return (char *)ptr;
293
294 while ((new = FP_strstr (iter, str)) != NULL) {
295 found = new;
296 iter = new + 1;
297 }
298
299 return (char *)found;
300}
301
302char * TOOLEXPORT
303FP_strirstr (char *ptr, char *str)
304{
305 char *found=NULL, *iter=ptr, *new;
306
307 if (ptr==NULL || str==NULL)
308 return NULL;
295 if (*str == '\0') 309 if (*str == '\0')
296 return ptr; 310 return ptr;
297 311
298 while ((new = _FP_strstr (iter, str)) != NULL) { 312 while ((new = FP_stristr (iter, str)) != NULL) {
299 found = new; 313 found = new;
300 iter = new + 1; 314 iter = new + 1;
301 } 315 }
302 return found; 316 return found;
303} 317}
304 318
305char * TOOLEXPORT
306_FP_strirstr (char *ptr, char *str)
307{
308 char *found=NULL, *iter=ptr, *new;
309
310 if (ptr==NULL || str==NULL)
311 return NULL;
312 if (*str == '\0')
313 return ptr;
314
315 while ((new = _FP_stristr (iter, str)) != NULL) {
316 found = new;
317 iter = new + 1;
318 }
319 return found;
320}
321
322/* 319/*
323 * convert whole string to case 320 * convert whole string to case
324 */ 321 */
325 322
326char * TOOLEXPORT 323char * TOOLEXPORT
327_FP_stoupper (char *input) 324FP_stoupper (char *input)
328{ 325{
329 char *iter = input; 326 char *iter = input;
330 327
331 if (input == NULL) 328 if (input == NULL)
332 return NULL; 329 return NULL;
337 } 334 }
338 return input; 335 return input;
339} 336}
340 337
341char * TOOLEXPORT 338char * TOOLEXPORT
342_FP_stolower (char *input) 339FP_stolower (char *input)
343{ 340{
344 char *iter = input; 341 char *iter = input;
345 342
346 if (input == NULL) 343 if (input == NULL)
347 return NULL; 344 return NULL;
356/* 353/*
357 * string matching with wildcards 354 * string matching with wildcards
358 */ 355 */
359 356
360int TOOLEXPORT 357int TOOLEXPORT
361_FP_strmatch (char *string, char *pattern) 358FP_strmatch (char *string, char *pattern)
362{ 359{
363 char *p1 = string, *p2 = pattern; 360 char *p1 = string, *p2 = pattern;
364 361
365 if (pattern==NULL || string==NULL) 362 if (pattern==NULL || string==NULL)
366 return 0; 363 return 0;
386 383
387 return 1; 384 return 1;
388} 385}
389 386
390char * TOOLEXPORT 387char * TOOLEXPORT
391_FP_strrchr (char *string, int tc) 388FP_strrchr (const char *string, int tc)
392{ 389{
393 char *ptr; 390 const char *ptr;
394 391
395 if (string == NULL || !*string) 392 if (string == NULL || !*string)
396 return NULL; 393 return NULL;
397 394
398 ptr = string + strlen (string) - 1; 395 ptr = string + strlen (string) - 1;
399 396
400 while (ptr != string && *ptr != tc) 397 while (ptr != string && *ptr != tc)
401 ptr--; 398 ptr--;
402 399
403 if (*ptr == tc) 400 if (*ptr == tc)
404 return ptr; 401 return (char *)ptr;
405 402
406 return NULL; 403 return NULL;
407} 404}
408 405
409/* 406/*
410 * strip directory information from a filename. Works only on DOS and 407 * strip directory information from a filename. Works only on DOS and
411 * Unix systems so far ... 408 * Unix systems so far ...
412 */ 409 */
413 410
414char * TOOLEXPORT 411char * TOOLEXPORT
415_FP_cutdir (char *filename) 412FP_cutdir (char *filename)
416{ 413{
417 char *ptr; 414 char *ptr;
418 415
419 if (filename == NULL) 416 if (filename == NULL)
420 return NULL; 417 return NULL;
421 418
422 if ((ptr = _FP_strrchr (filename, '/')) != NULL) 419 if ((ptr = FP_strrchr (filename, '/')) != NULL)
423 ptr++; 420 ptr++;
424 else if ((ptr = _FP_strrchr (filename, '\\')) != NULL) 421 else if ((ptr = FP_strrchr (filename, '\\')) != NULL)
425 ptr++; 422 ptr++;
426 else 423 else
427 ptr = filename; 424 ptr = filename;
428 425
429 return ptr; 426 return ptr;
430} 427}
431 428
432/* 429/*
433 * My own fgets function. It handles all kinds of line terminators 430 * My own fgets function. It handles all kinds of line terminators
434 * properly: LF (Unix), CRLF (DOS) and CR (Mac). In all cases, the 431 * properly: LF (Unix), CRLF (DOS) and CR (Mac).
435 * terminator is replaced by a single LF
436 */ 432 */
437 433/* (schmorp) the buffer is always written to, and no LF is stored at the end */
434/* also, if the buffer is too short, the remaining line is skipped */
438char * TOOLEXPORT 435ecb_hot char * TOOLEXPORT
439_FP_fgets (char *buf, int n, FILE *stream) 436FP_fgets (char *buf, int n, FILE *stream)
440{ 437{
441 char *obp = buf; 438 char *ptr = buf;
442 int c; 439 char *end = buf + n - 1;
443 440
444 if (feof (stream)) 441 /* shield against buffer overflows caused by "255 - bytes_left"-kind of bugs when bytes_left > 255 */
442 if (n <= 0)
445 return NULL; 443 return 0;
446 444
447 while (--n && !feof (stream)) { 445 for (;;)
448 if ((c = fgetc (stream)) == EOF) { 446 {
449 if (ferror (stream)) 447 int c = FP_getc (stream);
450 return NULL; 448
449 if (ecb_expect_false (c <= '\015')) /* EOF is < 0x20, too */
451 else { 450 {
452 if (obp == buf) 451 /* ctlchar */
453 return NULL; 452
454 *buf = '\0'; 453 if (c == '\012')
455 return obp; 454 /* LF, nothing following */
455 break;
456 else if (c == '\015')
457 {
458 /* CR, possibly CRLF, skip following LF */
459 c = FP_getc (stream);
460
461 if (c != '\012') /* CR LF? */
462 ungetc (c, stream);
463
464 break;
465 }
466 else if (c == EOF)
467 {
468 *ptr = 0;
469 return 0;
470 }
456 } 471 }
472
473 *ptr = c;
474 ptr += ptr < end; /* this is hopefully branch-free, and fast */
457 } 475 }
458 if (c == '\015') { /* CR */
459 /*
460 * Peek next character. If it's no LF, push it back.
461 * ungetc(EOF, stream) is handled correctly according
462 * to the manual page
463 */
464 if ((c = fgetc (stream)) != '\012')
465 if (!feof (stream))
466 ungetc (c, stream);
467 *buf++ = '\012';
468 *buf = '\0';
469 return obp;
470 }
471 else if (c == '\012') { /* LF */
472 *buf++ = '\012';
473 *buf = '\0';
474 return obp;
475 }
476 /*
477 * just another standard character
478 */
479 *buf++ = c;
480 }
481 476
482 /* 477 *ptr = 0;
483 * n-1 characters already transferred
484 */
485
486 *buf = '\0';
487
488 /*
489 * If a line break is coming up, read it
490 */
491
492 if (!feof (stream)) {
493 if ((c = fgetc (stream)) == '\015' && !feof (stream)) {
494 if ((c = fgetc (stream)) != '\012' && !feof (stream)) {
495 ungetc (c, stream);
496 }
497 }
498 else if (c != '\012' && !feof (stream)) {
499 ungetc (c, stream);
500 }
501 }
502
503 return obp; 478 return buf;
504} 479}
505 480
506/*
507 * A replacement strerror function that just returns the error code
508 */
509
510char * TOOLEXPORT
511_FP_strerror (int errcode)
512{
513 static char number[8];
514
515 sprintf (number, "%03d", errcode);
516
517 return number;
518}
519
520/*
521 * tempnam is not ANSI, but tmpnam is. Ignore the prefix here.
522 */
523
524char * TOOLEXPORT
525_FP_tempnam (char *dir, char *pfx)
526{
527 return _FP_strdup (tmpnam (NULL));
528}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines