1 /*
2  This file is part of SLRN.
3 
4  Copyright (c) 1994, 1999, 2007-2016 John E. Davis <jed@jedsoft.org>
5  Copyright (c) 2002-2006 Thomas Schultz <tststs@gmx.de>
6  Copyright (c) 2007 John E. Davis <jed@jedsoft.org>
7 
8  This program is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by the Free
10  Software Foundation; either version 2 of the License, or (at your option)
11  any later version.
12 
13  This program is distributed in the hope that it will be useful, but WITHOUT
14  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  more details.
17 
18  You should have received a copy of the GNU General Public License along
19  with this program; if not, write to the Free Software Foundation, Inc.,
20  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22 
23 #include "config.h"
24 #include "slrnfeat.h"
25 #include <stdio.h>
26 #include <string.h>
27 #include <errno.h>
28 #ifdef HAVE_STDLIB_H
29 # include <stdlib.h>
30 #endif
31 
32 #ifdef HAVE_UNISTD_H
33 # include <unistd.h>
34 #endif
35 #include <slang.h>
36 #include "jdmacros.h"
37 #include "strutil.h"
38 #include "common.h"
39 
40 /* This function allows NULL as a parameter. This fact _is_ exploited */
slrn_skip_whitespace(char * b)41 char *slrn_skip_whitespace (char *b) /*{{{*/
42 {
43    if (b == NULL) return NULL;
44 
45    while (isspace (*b))
46      b++;
47 
48    return b;
49 }
50 
51 /*}}}*/
52 
slrn_bskip_whitespace(char * smin)53 char *slrn_bskip_whitespace (char *smin)
54 {
55    char *s;
56 
57    if (smin == NULL) return NULL;
58    s = smin + strlen (smin);
59 
60    while (s > smin)
61      {
62 	s--;
63 	if (0 == isspace(*s))
64 	  return s + 1;
65      }
66    return s;
67 }
68 
69 /* returns a pointer to the end of the string */
slrn_trim_string(char * s)70 char *slrn_trim_string (char *s) /*{{{*/
71 {
72    s = slrn_bskip_whitespace (s);
73    if (s != NULL)
74      *s = 0;
75 
76    return s;
77 }
78 /*}}}*/
79 
slrn_strbyte(char * s,char ch)80 char *slrn_strbyte (char *s, char ch) /*{{{*/
81 {
82    register char ch1;
83 
84    while (((ch1 = *s) != 0) && (ch != ch1)) s++;
85    if (ch1 == 0) return NULL;
86    return s;
87 }
88 
89 /*}}}*/
90 
91 /* Search for characters from list in string str.  If found, return a pointer
92  * to the first occurrence.  If not found, return NULL. */
slrn_strbrk(char * str,char * list)93 char *slrn_strbrk (char *str, char *list) /*{{{*/
94 {
95    char ch, ch1, *p;
96 
97    while ((ch = *str) != 0)
98      {
99 	p = list;
100 	while ((ch1 = *p) != 0)
101 	  {
102 	     if (ch == ch1) return str;
103 	     p++;
104 	  }
105 	str++;
106      }
107    return NULL;
108 }
109 
110 /*}}}*/
111 
slrn_simple_strtok(char * s,char * chp)112 char *slrn_simple_strtok (char *s, char *chp) /*{{{*/
113 {
114    static char *s1;
115    char ch = *chp;
116 
117    if (s == NULL)
118      {
119 	if (s1 == NULL) return NULL;
120 	s = s1;
121      }
122    else s1 = s;
123 
124    while (*s1 && (*s1 != ch)) s1++;
125 
126    if (*s1 == 0)
127      {
128 	s1 = NULL;
129      }
130    else *s1++ = 0;
131    return s;
132 }
133 
134 /*}}}*/
135 
slrn_case_strncmp(char * a,char * b,unsigned int n)136 int slrn_case_strncmp (char *a, char *b, unsigned int n) /*{{{*/
137 {
138    char *bmax;
139 
140    if (a == NULL)
141      {
142 	if (b == NULL)
143 	  return 0;
144 	else
145 	  return -1;
146      }
147    if (b == NULL)
148      return 1;
149 
150    if (Slrn_UTF8_Mode)
151      return SLutf8_compare((SLuchar_Type *)a, (SLuchar_Type *)a+strlen(a),
152 			   (SLuchar_Type *)b, (SLuchar_Type *)b+strlen(b),
153 			   n, 0);
154    bmax = b + n;
155    while (b < bmax)
156      {
157 	unsigned char cha = UPPER_CASE(*a);
158 	unsigned char chb = UPPER_CASE(*b);
159 	if (cha != chb)
160 	  {
161 	     return (int) cha - (int) chb;
162 	  }
163 	else if (chb == 0) return 0;
164 	b++;
165 	a++;
166      }
167    return 0;
168 }
169 
170 /*}}}*/
171 
slrn_case_strcmp(char * a,char * b)172 int slrn_case_strcmp (char *a, char *b) /*{{{*/
173 {
174    register unsigned char cha, chb;
175    int len_a,len_b;
176 
177    if (a == NULL)
178      {
179 	if (b == NULL)
180 	  return 0;
181 	else
182 	  return -1;
183      }
184 
185    if (b == NULL)
186      return 1;
187 
188    if (Slrn_UTF8_Mode)
189      {
190 	len_a=strlen(a);
191 	len_b=strlen(b);
192 
193 	return SLutf8_compare((SLuchar_Type *)a, (SLuchar_Type *)a+len_a,
194 			      (SLuchar_Type *)b, (SLuchar_Type *)b+len_b,
195 			      ((len_a > len_b) ? len_a : len_b), 0);
196      }
197 
198    while (1)
199      {
200 	cha = UPPER_CASE(*a);
201 	chb = UPPER_CASE(*b);
202 	if (cha != chb)
203 	  {
204 	     return (int) cha - (int) chb;
205 	  }
206 	else if (chb == 0) break;
207 	b++;
208 	a++;
209      }
210    return 0;
211 }
212 
213 /*}}}*/
214 
slrn_strncpy(char * dest,const char * src,size_t n)215 char *slrn_strncpy (char *dest, const char *src, size_t n) /*{{{*/
216 {
217    strncpy (dest, src, n);
218    dest[n-1] = '\0';
219    return dest;
220 }
221 /*}}}*/
222 
223 /*{{{ Memory Allocation Routines */
224 
do_malloc_error(int do_error)225 static char *do_malloc_error (int do_error)
226 {
227    if (do_error) slrn_error (_("Memory allocation failure."));
228    return NULL;
229 }
230 
slrn_safe_strmalloc(char * s)231 char *slrn_safe_strmalloc (char *s) /*{{{*/
232 {
233    s = SLmake_string (s);
234    if (s == NULL) slrn_exit_error (_("Out of memory."));
235    return s;
236 }
237 
238 /*}}}*/
239 
slrn_safe_strnmalloc(char * s,unsigned int len)240 char *slrn_safe_strnmalloc (char *s, unsigned int len)
241 {
242    s = SLmake_nstring (s, len);
243    if (s == NULL) slrn_exit_error (_("Out of memory."));
244    return s;
245 }
246 
slrn_strnmalloc(char * s,unsigned int len,int do_error)247 char *slrn_strnmalloc (char *s, unsigned int len, int do_error)
248 {
249    s = SLmake_nstring (s, len);
250 
251    if (s == NULL)
252      return do_malloc_error (do_error);
253 
254    return s;
255 }
256 
slrn_strmalloc(char * s,int do_error)257 char *slrn_strmalloc (char *s, int do_error)
258 {
259    if (s == NULL) return NULL;
260    return slrn_strnmalloc (s, strlen (s), do_error);
261 }
262 
slrn_malloc(unsigned int len,int do_memset,int do_error)263 char *slrn_malloc (unsigned int len, int do_memset, int do_error)
264 {
265    char *s;
266 
267    s = (char *) SLmalloc (len);
268    if (s == NULL)
269      return do_malloc_error (do_error);
270 
271    if (do_memset)
272      memset (s, 0, len);
273 
274    return s;
275 }
276 
slrn_realloc(char * s,unsigned int len,int do_error)277 char *slrn_realloc (char *s, unsigned int len, int do_error)
278 {
279    if (s == NULL)
280      return slrn_malloc (len, 0, do_error);
281 
282    s = SLrealloc (s, len);
283    if (s == NULL)
284      return do_malloc_error (do_error);
285 
286    return s;
287 }
288 
slrn_safe_malloc(unsigned int len)289 char *slrn_safe_malloc (unsigned int len)
290 {
291    char *s;
292 
293    s = slrn_malloc (len, 1, 0);
294 
295    if (s == NULL)
296      slrn_exit_error (_("Out of memory"));
297 
298    return s;
299 }
300 
slrn_free(char * s)301 void slrn_free (char *s)
302 {
303    if (s != NULL) SLfree (s);
304 }
305 
306 /* return a:amax + s + b:bmax */
slrn_substrjoin(char * a,char * amax,char * b,char * bmax,char * s)307 char *slrn_substrjoin (char *a, char *amax, char *b, char *bmax, char *s)
308 {
309    unsigned int len_a, len_b, len_s, len;
310    char *c;
311 
312    if (a == NULL) a = amax = "";
313    if (b == NULL) b = bmax = "";
314    if (s == NULL) s = "";
315 
316    len_a = (amax == NULL) ? strlen (a) : (unsigned int)(amax - a);
317    len_b = (bmax == NULL) ? strlen (b) : (unsigned int)(bmax - b);
318 
319    if ((len_a == 0) || (len_b == 0))
320      len_s = 0;
321    else
322      len_s = strlen (s);
323 
324    len = len_a + len_s + len_b;
325    c = slrn_malloc (len+1, 0, 1);
326    if (c == NULL)
327      return NULL;
328 
329    strncpy (c, a, len_a);
330    if (len_s != 0)
331      strcpy (c+len_a, s);
332    strncpy (c+len_a+len_s, b, len_b);
333 
334    c[len] = 0;
335    return c;
336 }
337 
338 /* return a + s + b */
slrn_strjoin(char * a,char * b,char * s)339 char *slrn_strjoin (char *a, char *b, char *s)
340 {
341    return slrn_substrjoin (a, NULL, b, NULL, s);
342 }
343 
344