Fetch Flex from Sourceforge.
[AROS-Contrib.git] / regina / strings.c
blob151570029ca2591b0372acece749e7db5d98ffc4
1 #ifndef lint
2 static char *RCSid = "$Id$";
3 #endif
5 /*
6 * The Regina Rexx Interpreter
7 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "rexx.h"
25 #include <string.h>
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <assert.h>
30 #if !defined(MIN)
31 # define MIN(a,b) (((a)>(b))?(b):(a))
32 #endif
35 streng *Str_ndup( const streng *name, int length )
37 return Str_ndup_TSD(__regina_get_tsd(), name, length) ;
40 streng *Str_ndup_TSD( const tsd_t *TSD, const streng *name, int length )
42 streng *ptr=NULL ;
44 assert( Str_len(name) >= length) ;
45 ptr = Str_makeTSD( length ) ;
46 ptr->len = length ;
48 memcpy( ptr->value, name->value, length ) ;
49 return ptr ;
52 streng *Str_nodup( const streng *name, int offset, int length )
54 return Str_nodup_TSD(__regina_get_tsd(), name, offset, length) ;
57 streng *Str_nodup_TSD( const tsd_t *TSD, const streng *name, int offset, int length )
59 streng *ptr=NULL ;
61 assert( Str_len(name) >= (offset+length) ) ;
62 ptr = Str_makeTSD( length ) ;
63 memcpy( ptr->value, name->value+offset, length ) ;
64 ptr->len = length ;
65 return ptr ;
68 streng *Str_dup( const streng *name )
70 return Str_dup_TSD(__regina_get_tsd(), name) ;
73 streng *Str_dup_TSD( const tsd_t *TSD, const streng *input )
75 streng *output=NULL ;
77 output = Str_makeTSD( input->len ) ;
78 output->len = input->len ;
79 memcpy( output->value, input->value, input->len ) ;
81 return output ;
84 streng *Str_dupstr( const streng *name )
86 return Str_dupstr_TSD(__regina_get_tsd(), name) ;
89 /* Str_dupstr works like Str_dup but appends a hidden '\0' at the end. The
90 * terminator will be deleted by further Str_... operations.
92 streng *Str_dupstr_TSD( const tsd_t *TSD, const streng *input )
94 streng *output=NULL ;
96 output = Str_makeTSD( input->len + 1 ) ;
97 output->len = input->len ;
98 memcpy( output->value, input->value, input->len ) ;
99 output->value[input->len] = '\0';
101 return output ;
104 streng *Str_ncpy( streng *to, const streng *from, int length )
106 return Str_ncpy_TSD( __regina_get_tsd(), to, from, length ) ;
109 streng *Str_ncpy_TSD( const tsd_t *TSD, streng *to, const streng *from, int length )
111 streng *new=NULL ;
113 assert( Str_len(from) >= length ) ;
114 if ((new=to)->max<(to->len + length))
116 new = Str_makeTSD( to->len + length ) ;
117 memcpy(new->value, to->value, to->len) ;
118 new->len = to->len ;
119 /* FreeTSD( to ) ; */
122 length = (length>Str_len(from)) ? Str_len(from) : length ;
123 memcpy(new->value, from->value, length ) ;
124 new->len += length ;
126 return new ;
129 streng *Str_ncre( const char *from, int length )
131 return Str_ncre_TSD( __regina_get_tsd(), from, length ) ;
134 streng *Str_ncre_TSD( const tsd_t *TSD, const char *from, int length )
136 streng *result=NULL ;
138 assert( length >= 0 ) ;
140 result = Str_makeTSD( length ) ;
141 memcpy( result->value, from, length ) ;
143 result->len = length ;
144 return result ;
148 int Str_ncmp( const streng *first, const streng *second, int limit )
150 int i=0, rlim=0 ;
152 rlim = MIN( limit, MIN( first->len, second->len ) ) ;
153 for (i=0 ; i<rlim; i++)
154 if (first->value[i] != second->value[i])
155 return (first->value[i] - second->value[i]) ;
157 if (rlim<limit)
158 return (first->len != second->len ) ;
160 return (0) ;
164 streng *Str_cre( const char *input )
166 return Str_cre_TSD( __regina_get_tsd(), input ) ;
169 streng *Str_cre_TSD( const tsd_t *TSD, const char *input )
171 streng *result=NULL ;
172 register int len=strlen(input);
174 result = Str_makeTSD( len ) ;
175 memcpy( result->value, input, result->len=len ) ;
176 return result ;
179 streng *Str_crestr( const char *input )
181 return Str_crestr_TSD( __regina_get_tsd(), input ) ;
184 streng *Str_crestr_TSD( const tsd_t *TSD, const char *input )
186 streng *result ;
187 register int len=1+strlen(input);
189 result = Str_makeTSD( len ) ;
190 memcpy( result->value, input, result->len=len-1 ) ;
191 return result ;
195 #if !defined(FLISTS) || defined(TRACEMEM)
196 streng *__regina_Str_make( int size )
198 return Str_make_TSD( __regina_get_tsd(), size ) ;
201 # ifdef CHECK_MEMORY
202 streng *__regina_Str_make_TSD( const tsd_t *TSD, int size )
204 streng *retval;
206 retval = MallocTSD(sizeof(streng));
207 if (retval != NULL)
209 retval->len = 0 ;
210 retval->max = size ;
211 if (size == 0)
212 size = 1; /* Don't allow malloc(0), Checker doesn't like it */
213 if ((retval->value = MallocTSD(size)) == NULL)
215 FreeTSD(retval);
216 retval = NULL;
217 exiterror( ERR_STORAGE_EXHAUSTED, 0 ) ;
220 else
221 exiterror( ERR_STORAGE_EXHAUSTED, 0 ) ;
222 return(retval);
224 # else
225 streng *__regina_Str_make_TSD( const tsd_t *TSD, int size )
227 streng *result=NULL ;
229 result = MallocTSD( size + STRHEAD ) ;
230 result->max = size ;
231 result->len = 0 ;
233 return result ;
235 # endif /* CHECK_MEMORY */
236 #endif /* !defined(FLISTS) || defined(TRACEMEM) */
239 static streng *assure( const tsd_t *TSD, const streng *str, int length )
241 streng *ptr=NULL ;
243 if (length <= str->max)
244 return (streng *) str ;
246 ptr = Str_makeTSD( length ) ;
247 memcpy( ptr->value, str->value, str->len ) ;
248 ptr->len = str->len ;
250 /* We don't free str. */
251 return ptr ;
255 streng *Str_catstr( streng *base, const char *append )
257 return Str_catstr_TSD( __regina_get_tsd(), base, append ) ;
260 streng *Str_catstr_TSD( const tsd_t *TSD, streng *base, const char *append )
262 streng *ptr=NULL ;
263 int tmp=0 ;
265 ptr = assure( TSD, base, (tmp=strlen(append)) + base->len ) ;
266 memcpy( &ptr->value[ptr->len], append, tmp ) ;
267 ptr->len += tmp ;
268 return ptr ;
272 streng *Str_nocat( streng *first, const streng *second, int length, int offset )
274 return Str_nocat_TSD( __regina_get_tsd(), first, second, length, offset ) ;
277 streng *Str_nocat_TSD( const tsd_t *TSD, streng *first, const streng *second, int length, int offset )
279 streng *ptr=NULL ;
280 int tmp=0 ;
282 assert( second->len + 1 >= offset + length ) ;
284 tmp = second->len - offset ;
285 if (tmp<0 || tmp>length)
286 tmp = length ;
288 ptr = assure( TSD, first, first->len + tmp);
289 memcpy( &first->value[first->len], &second->value[offset], tmp ) ;
291 ptr->len += tmp ;
292 return ptr ;
296 streng *Str_cat( streng *first, const streng *second )
298 return Str_cat_TSD( __regina_get_tsd(), first, second ) ;
301 streng *Str_cat_TSD( const tsd_t *TSD, streng *first, const streng *second )
303 streng *ptr=NULL ;
304 int tmp=0 ;
306 ptr = assure( TSD, first, (tmp=Str_len(first)+Str_len(second)) ) ;
307 memcpy( &ptr->value[Str_len(first)], second->value, Str_len(second) ) ;
308 ptr->len = tmp ;
310 return ptr ;
314 streng *Str_ncat( streng *first, const streng *second, int length )
316 return Str_ncat_TSD( __regina_get_tsd(), first, second, length ) ;
319 streng *Str_ncat_TSD( const tsd_t *TSD, streng *first, const streng *second, int length )
321 streng *ptr=NULL ;
322 int tmp=0 ;
324 ptr = assure( TSD, first, Str_len(first) + (tmp=MIN(length,Str_len(second))) ) ;
325 memcpy( &ptr->value[Str_len(first)], second->value, tmp ) ;
327 ptr->len += tmp ;
328 return ptr ;
333 int Str_cmp( const streng *first, const streng *second )
335 register int lim=0 ;
337 lim = first->len ;
338 if (lim != second->len)
339 return 1 ;
341 return memcmp( first->value, second->value, lim ) ;
346 int Str_ccmp( const streng *first, const streng *second )
348 int tmp=0 ;
350 if (Str_len(first) != Str_len(second))
351 return 1 ;
353 for (tmp=0; tmp<Str_len(first); tmp++ )
354 if (RXTOLOW(first->value[tmp]) != RXTOLOW(second->value[tmp]))
355 return 1 ;
357 return 0 ;
361 int Str_cncmp( const streng *first, const streng *second, int length )
363 int tmp=0, top=0, shorter=0 ;
365 shorter = MIN( Str_len(first), Str_len(second) ) ;
366 if ( ( shorter<length) && (Str_len(first) != Str_len(second)) )
367 return 1 ;
369 top = MIN( shorter, length ) ;
370 for (tmp=0; tmp<top; tmp++ )
371 if (RXTOLOW(first->value[tmp]) != RXTOLOW(second->value[tmp]))
372 return 1 ;
374 return 0 ;
378 int Str_cnocmp( const streng *first, const streng *second, int length, int offset )
380 int tmp=0, top=0, shorter=0 ;
382 shorter = MIN( Str_len(first), Str_len(second)-offset ) ;
383 if ( ( shorter<length) && (Str_len(first) != Str_len(second)-offset) )
384 return 1 ;
386 top = MIN( shorter, length ) ;
387 for (tmp=0; tmp<top; tmp++ )
388 if (RXTOLOW(first->value[tmp]) != RXTOLOW(second->value[offset+tmp]))
389 return 1 ;
391 return 0 ;
395 char *str_of( const tsd_t *TSD, const streng *input )
396 /* returns a 0-terminated copy of the string-value of input. Free it with
397 * function Free.
400 char *retval = MallocTSD( Str_len(input) + 1 ) ;
402 memcpy( retval, input->value, Str_len(input) ) ;
403 retval[Str_len(input)] = '\0' ;
404 return retval;
407 volatile char *tmpstr_of( tsd_t *TSD, const streng *input )
408 /* returns a temporarily allocated 0-terminated copy of the string-value of
409 * input. Never free it explicitely. There is storage for 7 parallel living
410 * strings. The oldest will be deleted first. The main purpose of this function
411 * is to get a 0-terminated string of a streng for a very short time,
412 * e.g. exiterror. Since exiterror longjmp's back to another place, you
413 * don't have any chance to free up the allocated string. This is done now
414 * automatically.
415 * Call this function with NULL as the argument to free all temporary strings.
416 * WARNING: This function insn't thread-safe and won't ever be! Move the
417 * variable strs to the thread-specific memory to be thread-safe.
420 int i;
422 if (input == NULL)
424 for (i = 0; i < sizeof(TSD->tmp_strs) / sizeof(TSD->tmp_strs[0]); i++)
426 if (TSD->tmp_strs[i] != NULL)
428 FreeTSD( (char *) TSD->tmp_strs[i] ) ;
429 TSD->tmp_strs[i] = NULL ;
432 TSD->next_tmp_str = 0;
433 return NULL;
436 /* allocate a new one */
437 if (TSD->tmp_strs[TSD->next_tmp_str] != NULL)
438 FreeTSD( (char *) TSD->tmp_strs[TSD->next_tmp_str] ) ;
439 /* keep exiterror within Malloc in mind */
440 TSD->tmp_strs[TSD->next_tmp_str] = NULL ;
441 TSD->tmp_strs[TSD->next_tmp_str] = str_of( TSD, input ) ;
442 i = TSD->next_tmp_str ;
444 if (++TSD->next_tmp_str >= sizeof(TSD->tmp_strs) / sizeof(TSD->tmp_strs[0]))
445 TSD->next_tmp_str = 0 ;
447 return TSD->tmp_strs[i] ;
450 streng *Str_ncatstr( streng *base, const char *input, int length )
452 return Str_ncatstr_TSD( __regina_get_tsd(), base, input, length ) ;
455 streng *Str_ncatstr_TSD( const tsd_t *TSD, streng *base, const char *input, int length )
457 streng *ptr=NULL ;
458 int top=0 ;
460 top = MIN( (int) strlen(input), length ) ;
461 ptr = assure( TSD, base, Str_len(base) + top ) ;
462 memcpy( &ptr->value[Str_len(ptr)], input, top ) ;
463 ptr->len += top ;
464 return ptr ;
468 streng *Str_upper( streng *input )
470 register int len = Str_len(input);
471 char *val = input->value;
473 while (len-- > 0)
475 /* I think we don't need to check for islower before the toupper, FGC */
476 *val = (char) toupper(*val);
477 val++;
479 return input ;
482 streng *Str_strp( streng *input , char chr, char opt)
484 register int i=0,j=0;
486 if (input->len == 0)
487 return(input);
489 if (opt & STRIP_TRAILING)
491 for (i=(input->len)-1;i>-1;i--)
493 if (input->value[i] != chr)
494 break;
496 input->len = i + 1;
498 if (opt & STRIP_LEADING)
500 for (j=0;j<input->len;j++)
501 if (input->value[j] != chr)
502 break;
503 for (i=0;j<input->len;i++,j++)
504 input->value[i] = input->value[j];
505 input->len = i;
507 return(input);
510 char *str_trans(char *str,char oldch,char newch)
512 * Function : Translate all occurrences of oldch to newch in str
513 * Parameters: *str - string to be amended
514 * oldch - character to be replaced
515 * newch - character to replace oldch
516 * Return : same string but with characters translated
519 register int len=0;
520 register int i=0;
522 len = strlen(str);
523 for (i=0;i<len; i++)
525 if (*(str+i) == oldch)
526 *(str+i) = newch;
528 return(str);
531 int mem_cmpic( const char *buf1, const char *buf2, int len )
533 * Function : Compares two memory buffers for equality;
534 * case insensitive. Same as memicmp() Microsoft C.
535 * Parameters: buf1 - first buffer
536 * buf2 - second buffer
537 * len - number of characters to compare.
538 * Return : <0 if buf1 < buf2
539 * =0 if buf1 = buf2
540 * >0 if buf1 > buf2
543 register short i=0;
544 unsigned char c1,c2; /* allow 8-bit characters to order correctly */
546 for( i = 0; i < len; i++ )
548 c1 = (unsigned char) ((isupper(*buf1)) ? tolower(*buf1) : *buf1);
549 c2 = (unsigned char) ((isupper(*buf2)) ? tolower(*buf2) : *buf2);
550 if (c1 != c2)
551 return(c1-c2);
552 ++buf1;
553 ++buf2;
555 return 0 ;