reenabled swaptest. quake should now load data and start on big endian architectures...
[AROS-Contrib.git] / regina / strings.c
blobdd61ba9fdd54baafe2b67d1e3158cacfa5517140
1 /*
2 * The Regina Rexx Interpreter
3 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "rexx.h"
21 #include <string.h>
22 #include <stdio.h>
23 #include <assert.h>
25 #if !defined(MIN)
26 # define MIN(a,b) (((a)>(b))?(b):(a))
27 #endif
29 void __regina_Str_first( void )
32 * Together with __regina_Str_last it defines a region of function
33 * which should not be mentioned in the list of allocator addresses.
34 * See memory.c:mymallocTSD()
38 streng *Str_ndup( const streng *name, int length )
40 return Str_ndup_TSD(__regina_get_tsd(), name, length);
43 streng *Str_ndup_TSD( const tsd_t *TSD, const streng *name, int length )
45 streng *ptr;
47 assert( Str_len( name ) >= length );
48 ptr = Str_makeTSD( length );
49 ptr->len = length;
51 memcpy( ptr->value, name->value, length );
52 return ptr;
55 streng *Str_nodup( const streng *name, int offset, int length )
57 return Str_nodup_TSD( __regina_get_tsd(), name, offset, length );
60 streng *Str_nodup_TSD( const tsd_t *TSD, const streng *name, int offset, int length )
62 streng *ptr;
64 assert( Str_len( name ) >= ( offset + length ) );
65 ptr = Str_makeTSD( length );
66 memcpy( ptr->value, name->value + offset, length );
67 ptr->len = length;
68 return ptr;
71 streng *Str_dup( const streng *name )
73 return Str_dup_TSD( __regina_get_tsd(), name );
76 streng *Str_dup_TSD( const tsd_t *TSD, const streng *input )
78 streng *output;
80 output = Str_makeTSD( input->len );
81 output->len = input->len;
82 memcpy( output->value, input->value, input->len );
84 return output;
87 streng *Str_dupstr( const streng *name )
89 return Str_dupstr_TSD( __regina_get_tsd(), name );
92 /* Str_dupstr works like Str_dup but appends a hidden '\0' at the end. The
93 * terminator will be deleted by further Str_... operations.
95 streng *Str_dupstr_TSD( const tsd_t *TSD, const streng *input )
97 streng *output;
99 output = Str_makeTSD( input->len + 1 );
100 output->len = input->len;
101 memcpy( output->value, input->value, input->len );
102 output->value[input->len] = '\0';
104 return output;
107 streng *Str_ncpy( streng *to, const streng *from, int length )
109 return Str_ncpy_TSD( __regina_get_tsd(), to, from, length );
112 streng *Str_ncpy_TSD( const tsd_t *TSD, streng *to, const streng *from, int length )
114 streng *newstr;
116 assert( Str_len(from) >= length );
117 newstr = to;
118 if ( to->max < to->len + length )
120 newstr = Str_makeTSD( to->len + length );
121 memcpy( newstr->value, to->value, to->len );
122 newstr->len = to->len;
124 * Freeing the string is a bad idea if the string is bound to
125 * something yet.
126 * FreeTSD( to );
130 if ( length > Str_len( from ) )
131 length = Str_len( from );
132 memcpy( newstr->value, from->value, length );
133 newstr->len += length;
135 return newstr;
138 streng *Str_ncre( const char *from, int length )
140 return Str_ncre_TSD( __regina_get_tsd(), from, length );
143 streng *Str_ncre_TSD( const tsd_t *TSD, const char *from, int length )
145 streng *result;
147 assert( length >= 0 );
149 result = Str_makeTSD( length );
150 memcpy( result->value, from, length );
152 result->len = length;
153 return result;
157 int Str_ncmp( const streng *first, const streng *second, int limit )
159 int i,rlim;
161 rlim = MIN( limit, MIN( first->len, second->len ) );
162 for ( i = 0; i < rlim; i++)
163 if (first->value[i] != second->value[i])
164 return (int) ( (unsigned char) first->value[i] -
165 (unsigned char) second->value[i] );
167 if ( rlim < limit )
168 return (first->len != second->len );
170 return 0;
174 streng *Str_cre( const char *input )
176 return Str_cre_TSD( __regina_get_tsd(), input );
179 streng *Str_cre_TSD( const tsd_t *TSD, const char *input )
181 streng *result;
182 int len;
184 len = strlen( input );
186 result = Str_makeTSD( len );
187 result->len = len;
188 memcpy( result->value, input, len );
189 return result;
192 streng *Str_crestr( const char *input )
194 return Str_crestr_TSD( __regina_get_tsd(), input );
197 streng *Str_crestr_TSD( const tsd_t *TSD, const char *input )
199 streng *result;
200 int len;
202 len = strlen( input ) + 1;
204 result = Str_makeTSD( len );
205 result->len = len - 1;
206 memcpy( result->value, input, len );
207 return result;
211 #if !defined(FLISTS) || defined(TRACEMEM)
212 streng *__regina_Str_make( int size )
214 return Str_make_TSD( __regina_get_tsd(), size );
217 # ifdef CHECK_MEMORY
218 streng *__regina_Str_make_TSD( const tsd_t *TSD, int size )
220 streng *retval;
222 retval = MallocTSD( sizeof( streng ) );
223 if ( retval != NULL )
225 retval->len = 0;
226 retval->max = size;
227 if (size == 0)
228 size = 1; /* Don't allow malloc(0), Checker doesn't like it */
229 if ( ( retval->value = MallocTSD( size ) ) == NULL )
231 FreeTSD( retval );
232 retval = NULL;
233 exiterror( ERR_STORAGE_EXHAUSTED, 0 );
236 else
237 exiterror( ERR_STORAGE_EXHAUSTED, 0 );
238 return retval;
240 # else
241 streng *__regina_Str_make_TSD( const tsd_t *TSD, int size )
243 streng *result;
245 result = (streng *) MallocTSD( size + STRHEAD );
246 result->max = size;
247 result->len = 0;
249 return result;
251 # endif /* CHECK_MEMORY */
252 #endif /* !defined(FLISTS) || defined(TRACEMEM) */
255 static streng *assure( const tsd_t *TSD, const streng *str, int length )
257 streng *ptr;
259 if ( length <= str->max )
260 return (streng *) str;
262 ptr = Str_makeTSD( length );
263 memcpy( ptr->value, str->value, str->len );
264 ptr->len = str->len;
266 /* We don't free str. */
267 return ptr;
271 streng *Str_catstr( streng *base, const char *append )
273 return Str_catstr_TSD( __regina_get_tsd(), base, append );
276 streng *Str_catstr_TSD( const tsd_t *TSD, streng *base, const char *append )
278 streng *ptr;
279 int tmp;
281 tmp = strlen( append );
282 ptr = assure( TSD, base, tmp + base->len );
283 memcpy( ptr->value + ptr->len, append, tmp );
284 ptr->len += tmp;
285 return ptr;
289 streng *Str_nocat( streng *first, const streng *second, int length, int offset )
291 return Str_nocat_TSD( __regina_get_tsd(), first, second, length, offset );
294 streng *Str_nocat_TSD( const tsd_t *TSD, streng *first, const streng *second, int length, int offset )
296 streng *ptr;
297 int tmp;
299 assert( second->len + 1 >= offset + length );
301 tmp = second->len - offset;
302 if ( ( tmp < 0 ) || ( tmp > length ) )
303 tmp = length;
305 ptr = assure( TSD, first, first->len + tmp );
306 memcpy( &ptr->value[first->len], &second->value[offset], tmp );
308 ptr->len += tmp;
309 return ptr;
313 streng *Str_cat( streng *first, const streng *second )
315 return Str_cat_TSD( __regina_get_tsd(), first, second );
318 streng *Str_cat_TSD( const tsd_t *TSD, streng *first, const streng *second )
320 streng *ptr;
321 int tmp;
323 tmp = Str_len( first ) + Str_len( second );
324 ptr = assure( TSD, first, tmp );
325 memcpy( ptr->value + Str_len( first ), second->value, Str_len( second ) );
326 ptr->len = tmp;
328 return ptr;
332 streng *Str_ncat( streng *first, const streng *second, int length )
334 return Str_ncat_TSD( __regina_get_tsd(), first, second, length );
337 streng *Str_ncat_TSD( const tsd_t *TSD, streng *first, const streng *second, int length )
339 streng *ptr;
340 int tmp;
342 tmp = MIN( length, Str_len( second ) );
343 ptr = assure( TSD, first, Str_len( first ) + tmp );
344 memcpy( ptr->value + Str_len( first ), second->value, tmp );
346 ptr->len += tmp;
347 return ptr;
352 int Str_cmp( const streng *first, const streng *second )
354 int lim;
356 lim = Str_len( first );
357 if ( lim != Str_len( second ) )
358 return 1;
360 return memcmp( first->value, second->value, lim );
365 int Str_ccmp( const streng *first, const streng *second )
367 int lim;
369 lim = Str_len( first );
370 if ( lim != Str_len( second ) )
371 return 1;
373 return ( mem_cmpic( first->value, second->value, lim ) ) ? 1 : 0;
377 int Str_cncmp( const streng *first, const streng *second, int length )
379 int top, shorter;
381 shorter = MIN( Str_len( first ), Str_len( second ) );
382 if ( ( shorter < length ) && ( Str_len( first ) != Str_len( second ) ) )
383 return 1;
385 top = MIN( shorter, length );
386 return ( mem_cmpic( first->value, second->value, top ) ) ? 1 : 0;
390 int Str_cnocmp( const streng *first, const streng *second, int length, int offset )
392 int top, shorter;
394 shorter = MIN( Str_len( first ), Str_len( second ) - offset );
395 if ( ( shorter < length ) &&
396 ( Str_len( first ) != Str_len( second ) - offset ) )
397 return 1;
399 top = MIN( shorter, length );
400 return ( mem_cmpic( first->value, second->value + offset, top ) ) ? 1 : 0;
405 * str_of() returns a 0-terminated copy of the string-value of input. Free it
406 * with function Free.
408 char *str_of( const tsd_t *TSD, const streng *input )
410 char *retval = (char *)MallocTSD( Str_len( input ) + 1 );
412 memcpy( retval, input->value, Str_len( input ) );
413 retval[Str_len( input )] = '\0';
414 return retval;
418 * tmpstr_of() returns a temporarily allocated 0-terminated copy of the
419 * string-value of input. Never free it explicitely. There is storage for 7
420 * parallel living strings. The oldest will be deleted first. The main purpose
421 * of this function is to get a 0-terminated string of a streng for a very
422 * short time, e.g. exiterror. Since exiterror longjmp's back to another place,
423 * you don't have any chance to free up the allocated string. This is done now
424 * automatically.
425 * Call this function with NULL as the argument to free all temporary strings.
426 * WARNING: This function insn't thread-safe and won't ever be! Move the
427 * variable strs to the thread-specific memory to be thread-safe.
429 volatile char *tmpstr_of( tsd_t *TSD, const streng *input )
431 unsigned i;
433 if ( input == NULL )
435 for ( i = 0; i < sizeof( TSD->tmp_strs ) / sizeof( TSD->tmp_strs[0] ); i++ )
437 if ( TSD->tmp_strs[i] != NULL )
439 FreeTSD( (char *) TSD->tmp_strs[i] );
440 TSD->tmp_strs[i] = NULL;
443 TSD->next_tmp_str = 0;
444 return NULL;
447 /* allocate a new one */
448 if ( TSD->tmp_strs[TSD->next_tmp_str] != NULL )
449 FreeTSD( (char *) TSD->tmp_strs[TSD->next_tmp_str] );
450 /* keep exiterror within Malloc in mind */
451 TSD->tmp_strs[TSD->next_tmp_str] = NULL;
452 TSD->tmp_strs[TSD->next_tmp_str] = str_of( TSD, input );
453 i = TSD->next_tmp_str;
455 if ( ++TSD->next_tmp_str >= (int) (sizeof( TSD->tmp_strs ) / sizeof( TSD->tmp_strs[0]) ) )
456 TSD->next_tmp_str = 0;
458 return TSD->tmp_strs[i];
461 streng *Str_ncatstr( streng *base, const char *input, int length )
463 return Str_ncatstr_TSD( __regina_get_tsd(), base, input, length );
466 streng *Str_ncatstr_TSD( const tsd_t *TSD, streng *base, const char *input, int length )
468 streng *ptr;
469 int top;
471 top = MIN( (int) strlen( input ), length );
472 ptr = assure( TSD, base, Str_len( base ) + top );
473 memcpy( ptr->value + Str_len( ptr ), input, top );
474 ptr->len += top;
475 return ptr;
479 streng *Str_upper( streng *input )
481 mem_upper( input->value, Str_len( input ) );
482 return input;
485 streng *Str_lower( streng *input )
487 mem_lower( input->value, Str_len( input ) );
488 return input;
491 streng *Str_strp( streng *input , char chr, char opt )
493 int i,j;
495 if ( input->len == 0 )
496 return input;
498 if ( opt & STRIP_TRAILING )
500 for ( i = input->len - 1; i > -1; i-- )
502 if ( input->value[i] != chr )
503 break;
505 input->len = i + 1;
507 if ( opt & STRIP_LEADING )
509 for ( j = 0; j < input->len; j++ )
510 if ( input->value[j] != chr )
511 break;
512 for ( i = 0; j < input->len; i++, j++ )
513 input->value[i] = input->value[j];
514 input->len = i;
516 return input;
519 void __regina_Str_last( void )
522 * Together with __regina_Str_first it defines a region of function
523 * which should not be mentioned in the list of allocator addresses.
524 * See memory.c:mymallocTSD()