ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-UUlib/uulib/fptools.c
Revision: 1.21
Committed: Sat Sep 24 06:22:47 2022 UTC (20 months, 1 week ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.20: +0 -6 lines
Log Message:
*** empty log message ***

File Contents

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