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.
26 # define MIN(a,b) (((a)>(b))?(b):(a))
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
)
47 assert( Str_len( name
) >= length
);
48 ptr
= Str_makeTSD( length
);
51 memcpy( ptr
->value
, name
->value
, length
);
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
)
64 assert( Str_len( name
) >= ( offset
+ length
) );
65 ptr
= Str_makeTSD( length
);
66 memcpy( ptr
->value
, name
->value
+ offset
, length
);
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
)
80 output
= Str_makeTSD( input
->len
);
81 output
->len
= input
->len
;
82 memcpy( output
->value
, input
->value
, input
->len
);
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
)
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';
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
)
116 assert( Str_len(from
) >= length
);
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
130 if ( length
> Str_len( from
) )
131 length
= Str_len( from
);
132 memcpy( newstr
->value
, from
->value
, length
);
133 newstr
->len
+= length
;
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
)
147 assert( length
>= 0 );
149 result
= Str_makeTSD( length
);
150 memcpy( result
->value
, from
, length
);
152 result
->len
= length
;
157 int Str_ncmp( const streng
*first
, const streng
*second
, int limit
)
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
] );
168 return (first
->len
!= second
->len
);
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
)
184 len
= strlen( input
);
186 result
= Str_makeTSD( len
);
188 memcpy( result
->value
, input
, len
);
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
)
202 len
= strlen( input
) + 1;
204 result
= Str_makeTSD( len
);
205 result
->len
= len
- 1;
206 memcpy( result
->value
, input
, len
);
211 #if !defined(FLISTS) || defined(TRACEMEM)
212 streng
*__regina_Str_make( int size
)
214 return Str_make_TSD( __regina_get_tsd(), size
);
218 streng
*__regina_Str_make_TSD( const tsd_t
*TSD
, int size
)
222 retval
= MallocTSD( sizeof( streng
) );
223 if ( retval
!= NULL
)
228 size
= 1; /* Don't allow malloc(0), Checker doesn't like it */
229 if ( ( retval
->value
= MallocTSD( size
) ) == NULL
)
233 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
237 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
241 streng
*__regina_Str_make_TSD( const tsd_t
*TSD
, int size
)
245 result
= (streng
*) MallocTSD( size
+ STRHEAD
);
251 # endif /* CHECK_MEMORY */
252 #endif /* !defined(FLISTS) || defined(TRACEMEM) */
255 static streng
*assure( const tsd_t
*TSD
, const streng
*str
, int length
)
259 if ( length
<= str
->max
)
260 return (streng
*) str
;
262 ptr
= Str_makeTSD( length
);
263 memcpy( ptr
->value
, str
->value
, str
->len
);
266 /* We don't free str. */
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
)
281 tmp
= strlen( append
);
282 ptr
= assure( TSD
, base
, tmp
+ base
->len
);
283 memcpy( ptr
->value
+ ptr
->len
, append
, tmp
);
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
)
299 assert( second
->len
+ 1 >= offset
+ length
);
301 tmp
= second
->len
- offset
;
302 if ( ( tmp
< 0 ) || ( tmp
> length
) )
305 ptr
= assure( TSD
, first
, first
->len
+ tmp
);
306 memcpy( &ptr
->value
[first
->len
], &second
->value
[offset
], tmp
);
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
)
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
) );
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
)
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
);
352 int Str_cmp( const streng
*first
, const streng
*second
)
356 lim
= Str_len( first
);
357 if ( lim
!= Str_len( second
) )
360 return memcmp( first
->value
, second
->value
, lim
);
365 int Str_ccmp( const streng
*first
, const streng
*second
)
369 lim
= Str_len( first
);
370 if ( lim
!= Str_len( second
) )
373 return ( mem_cmpic( first
->value
, second
->value
, lim
) ) ? 1 : 0;
377 int Str_cncmp( const streng
*first
, const streng
*second
, int length
)
381 shorter
= MIN( Str_len( first
), Str_len( second
) );
382 if ( ( shorter
< length
) && ( Str_len( first
) != Str_len( second
) ) )
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
)
394 shorter
= MIN( Str_len( first
), Str_len( second
) - offset
);
395 if ( ( shorter
< length
) &&
396 ( Str_len( first
) != Str_len( second
) - offset
) )
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';
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
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
)
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;
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
)
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
);
479 streng
*Str_upper( streng
*input
)
481 mem_upper( input
->value
, Str_len( input
) );
485 streng
*Str_lower( streng
*input
)
487 mem_lower( input
->value
, Str_len( input
) );
491 streng
*Str_strp( streng
*input
, char chr
, char opt
)
495 if ( input
->len
== 0 )
498 if ( opt
& STRIP_TRAILING
)
500 for ( i
= input
->len
- 1; i
> -1; i
-- )
502 if ( input
->value
[i
] != chr
)
507 if ( opt
& STRIP_LEADING
)
509 for ( j
= 0; j
< input
->len
; j
++ )
510 if ( input
->value
[j
] != chr
)
512 for ( i
= 0; j
< input
->len
; i
++, j
++ )
513 input
->value
[i
] = input
->value
[j
];
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()