ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/fptools.c
Revision: 1.20
Committed: Sat Sep 24 06:05:03 2022 UTC (20 months, 2 weeks ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.19: +1 -3 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * fptools.c, some helper functions for getcgi.c and uu(en|de)view
3 *
4 * Distributed under the terms of the GNU General Public License.
5 * Use and be happy.
6 */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #ifdef SYSTEM_WINDLL
13 #include <windows.h>
14 #endif
15 #ifdef SYSTEM_OS2
16 #include <os2.h>
17 #endif
18
19 /*
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
22 * should behave exactly as their counterparts. There are also extensions
23 * that aren't portable at all (like strirstr etc.).
24 * The proper behaviour in a configure script is as follows:
25 * AC_CHECK_FUNC(strrchr,AC_DEFINE(strrchr,FP_strrchr))
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
28 * does not work with replacements that just shadow wrong behaviour (like
29 * FP_free) or provide extended functionality (FP_gets).
30 * The above is not used in the uuenview/uudeview configuration script,
31 * since both only use the replacement functions in non-performance-cri-
32 * tical sections (except for FP_tempnam and FP_strerror, where some
33 * functionality of the original would be lost).
34 */
35
36 #include <stdio.h>
37 #include <ctype.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #ifdef HAVE_MALLOC_H
42 #include <malloc.h>
43 #endif
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif
47 #ifdef HAVE_MEMORY_H
48 #include <memory.h>
49 #endif
50
51 #include <fptools.h>
52
53 #if 0
54 #ifdef SYSTEM_WINDLL
55 BOOL _export WINAPI
56 DllEntryPoint (HINSTANCE hInstance, DWORD seginfo,
57 LPVOID lpCmdLine)
58 {
59 /* Don't do anything, so just return true */
60 return TRUE;
61 }
62 #endif
63 #endif
64
65 /*
66 * some versions of free can't handle a NULL pointer properly
67 * (ANSI says, free ignores a NULL pointer, but some machines
68 * prefer to SIGSEGV on it)
69 */
70
71 void TOOLEXPORT
72 FP_free (void *ptr)
73 {
74 if (ptr) free (ptr);
75 }
76
77 /*
78 * This is non-standard, so I'm defining my own
79 */
80
81 char * TOOLEXPORT
82 FP_strdup (char *string)
83 {
84 char *result;
85
86 if (string == NULL)
87 return NULL;
88
89 if ((result = (char *) malloc (strlen (string) + 1)) == NULL)
90 return NULL;
91
92 strcpy (result, string);
93 return result;
94 }
95
96 /*
97 * limited-length string copy. this function behaves differently from
98 * the original in that the dest string is always terminated with a
99 * NULL character.
100 */
101
102 char * TOOLEXPORT
103 FP_strncpy (char *dest, char *src, int length)
104 {
105 char *odest=dest;
106 if (src == NULL || dest == NULL || length-- <= 0)
107 return dest;
108
109 while (length-- && *src)
110 *dest++ = *src++;
111
112 *dest++ = '\0';
113 return odest;
114 }
115
116 /*
117 * duplicate a memory area
118 */
119
120 void * TOOLEXPORT
121 FP_memdup (const void *ptr, int len)
122 {
123 void *result;
124
125 if (ptr == NULL)
126 return NULL;
127
128 if ((result = malloc (len)) == NULL)
129 return NULL;
130
131 memcpy (result, ptr, len);
132 return result;
133 }
134
135 /*
136 * case-insensitive compare
137 */
138
139 #ifndef FP_stricmp
140 int TOOLEXPORT
141 FP_stricmp (const char *str1, const char *str2)
142 {
143 if (str1==NULL || str2==NULL)
144 return -1;
145
146 while (*str1) {
147 if (tolower(*str1) != tolower(*str2))
148 break;
149 str1++;
150 str2++;
151 }
152 return (tolower (*str1) - tolower (*str2));
153 }
154 #endif
155
156 #ifndef FP_strnicmp
157 int TOOLEXPORT
158 FP_strnicmp (const char *str1, const char *str2, int count)
159 {
160 int d;
161
162 if (!str1 || !str2)
163 return -1;
164
165 while (count--) {
166 if (!*str1)
167 return -1;
168
169 d = tolower (*str1) - tolower (*str2);
170 if (d)
171 return d;
172
173 str1++;
174 str2++;
175 }
176
177 return 0;
178 }
179 #endif
180
181 int TOOLEXPORT
182 FP_strnicmp_fast (const char *str1, const char *str2, int count)
183 {
184 if (!str1 || !str2)
185 return -1;
186
187 while (count--) {
188 if (!*str1)
189 return -1;
190
191 if ((*str1 ^ *str2) & 0xdf)
192 return (*str1 & 0xdf) - (*str2 & 0xdf);
193
194 str1++;
195 str2++;
196 }
197
198 return 0;
199 }
200
201 char * TOOLEXPORT
202 FP_strpbrk (char *str, char *accept)
203 {
204 char *ptr;
205
206 if (str == NULL)
207 return NULL;
208 if (accept == NULL || *accept == '\0')
209 return str;
210
211 for (; *str; str++)
212 for (ptr=accept; *ptr; ptr++)
213 if (*str == *ptr)
214 return str;
215
216 return NULL;
217 }
218
219 /*
220 * autoconf also complains about this one
221 */
222
223 char * TOOLEXPORT
224 FP_strtok (char *str1, char *str2)
225 {
226 static char *optr;
227 char *ptr;
228
229 if (str2 == NULL)
230 return NULL;
231
232 if (str1) {
233 optr = str1;
234 }
235 else {
236 if (*optr == '\0')
237 return NULL;
238 }
239
240 while (*optr && strchr (str2, *optr)) /* look for beginning of token */
241 optr++;
242
243 if (*optr == '\0') /* no token found */
244 return NULL;
245
246 ptr = optr;
247 while (*optr && strchr (str2, *optr) == NULL) /* look for end of token */
248 optr++;
249
250 if (*optr) {
251 *optr++ = '\0';
252 }
253 return ptr;
254 }
255
256 /*
257 * case insensitive strstr.
258 */
259
260 #ifndef FP_stristr
261 char * TOOLEXPORT
262 FP_stristr (char *str1, char *str2)
263 {
264 char *ptr1, *ptr2;
265
266 if (str1==NULL)
267 return NULL;
268 if (str2==NULL)
269 return str1;
270
271 while (*(ptr1=str1)) {
272 for (ptr2=str2;
273 *ptr1 && *ptr2 && tolower(*ptr1)==tolower(*ptr2);
274 ptr1++, ptr2++)
275 /* empty loop */ ;
276
277 if (*ptr2 == '\0')
278 return str1;
279 str1++;
280 }
281 return NULL;
282 }
283 #endif
284
285 /*
286 * Nice fake of the real (non-standard) one
287 */
288
289 char * TOOLEXPORT
290 FP_strrstr (const char *ptr, const char *str)
291 {
292 const char *found=NULL, *new, *iter=ptr;
293
294 if (ptr==NULL || str==NULL)
295 return NULL;
296
297 if (*str == '\0')
298 return (char *)ptr;
299
300 while ((new = FP_strstr (iter, str)) != NULL) {
301 found = new;
302 iter = new + 1;
303 }
304
305 return (char *)found;
306 }
307
308 char * TOOLEXPORT
309 FP_strirstr (char *ptr, char *str)
310 {
311 char *found=NULL, *iter=ptr, *new;
312
313 if (ptr==NULL || str==NULL)
314 return NULL;
315 if (*str == '\0')
316 return ptr;
317
318 while ((new = FP_stristr (iter, str)) != NULL) {
319 found = new;
320 iter = new + 1;
321 }
322 return found;
323 }
324
325 /*
326 * convert whole string to case
327 */
328
329 char * TOOLEXPORT
330 FP_stoupper (char *input)
331 {
332 char *iter = input;
333
334 if (input == NULL)
335 return NULL;
336
337 while (*iter) {
338 *iter = toupper (*iter);
339 iter++;
340 }
341 return input;
342 }
343
344 char * TOOLEXPORT
345 FP_stolower (char *input)
346 {
347 char *iter = input;
348
349 if (input == NULL)
350 return NULL;
351
352 while (*iter) {
353 *iter = tolower (*iter);
354 iter++;
355 }
356 return input;
357 }
358
359 /*
360 * string matching with wildcards
361 */
362
363 int TOOLEXPORT
364 FP_strmatch (char *string, char *pattern)
365 {
366 char *p1 = string, *p2 = pattern;
367
368 if (pattern==NULL || string==NULL)
369 return 0;
370
371 while (*p1 && *p2) {
372 if (*p2 == '?') {
373 p1++; p2++;
374 }
375 else if (*p2 == '*') {
376 if (*++p2 == '\0')
377 return 1;
378 while (*p1 && *p1 != *p2)
379 p1++;
380 }
381 else if (*p1 == *p2) {
382 p1++; p2++;
383 }
384 else
385 return 0;
386 }
387 if (*p1 || *p2)
388 return 0;
389
390 return 1;
391 }
392
393 char * TOOLEXPORT
394 FP_strrchr (const char *string, int tc)
395 {
396 const char *ptr;
397
398 if (string == NULL || !*string)
399 return NULL;
400
401 ptr = string + strlen (string) - 1;
402
403 while (ptr != string && *ptr != tc)
404 ptr--;
405
406 if (*ptr == tc)
407 return (char *)ptr;
408
409 return NULL;
410 }
411
412 /*
413 * strip directory information from a filename. Works only on DOS and
414 * Unix systems so far ...
415 */
416
417 char * TOOLEXPORT
418 FP_cutdir (char *filename)
419 {
420 char *ptr;
421
422 if (filename == NULL)
423 return NULL;
424
425 if ((ptr = FP_strrchr (filename, '/')) != NULL)
426 ptr++;
427 else if ((ptr = FP_strrchr (filename, '\\')) != NULL)
428 ptr++;
429 else
430 ptr = filename;
431
432 return ptr;
433 }
434
435 /*
436 * My own fgets function. It handles all kinds of line terminators
437 * properly: LF (Unix), CRLF (DOS) and CR (Mac).
438 */
439 /* (schmorp) the buffer is always written to, and no LF is stored at the end */
440 /* also, if the buffer is too short, the remaining line is skipped */
441 ecb_hot char * TOOLEXPORT
442 FP_fgets (char *buf, int n, FILE *stream)
443 {
444 char *ptr = buf;
445 char *end = buf + n - 1;
446
447 /* shield against buffer overflows caused by "255 - bytes_left"-kind of bugs when bytes_left > 255 */
448 if (n <= 0)
449 return 0;
450
451 for (;;)
452 {
453 int c = FP_getc (stream);
454
455 if (ecb_expect_false (c <= '\015')) /* EOF is < 0x20, too */
456 {
457 /* ctlchar */
458
459 if (c == '\012')
460 /* LF, nothing following */
461 break;
462 else if (c == '\015')
463 {
464 /* CR, possibly CRLF, skip following LF */
465 c = FP_getc (stream);
466
467 if (c != '\012') /* CR LF? */
468 ungetc (c, stream);
469
470 break;
471 }
472 else if (c == EOF)
473 {
474 *ptr = 0;
475 return 0;
476 }
477 }
478
479 *ptr = c;
480 ptr += ptr < end; /* this is hopefully branch-free, and fast */
481 }
482
483 *ptr = 0;
484 return buf;
485 }
486