1 /*
2 * Generic Call Interface for Rexx
3 * Copyright � 2003-2004, Florian Gro�e-Coosmann
4 *
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.
9 *
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.
14 *
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.
18 *
19 * ----------------------------------------------------------------------------
20 *
21 * This file contains little helper routines.
22 */
23
24 #include "gci.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <ctype.h>
29
30 /*****************************************************************************
31 *****************************************************************************
32 ** GLOBAL FUNCTIONS *********************************************************
33 *****************************************************************************
34 *****************************************************************************/
35
36 /*
37 * GCI_strlen returns the current length of the string.
38 */
GCI_strlen(const GCI_str * str)39 int GCI_strlen( const GCI_str *str )
40 {
41 return str->used;
42 }
43
44 /*
45 * GCI_strmax returns the maximum length of the string including any
46 * terminators.
47 */
GCI_strmax(const GCI_str * str)48 int GCI_strmax( const GCI_str *str )
49 {
50 return str->max;
51 }
52
53 /*
54 * GCI_content returns a pointer to the content of str. The content may not be
55 * 0-terminated.
56 */
GCI_content(GCI_str * str)57 char * GCI_content( GCI_str *str )
58 {
59 return str->val;
60 }
61
62 /*
63 * GCI_content returns a pointer to the content of str. The content may not be
64 * 0-terminated.
65 */
GCI_ccontent(const GCI_str * str)66 const char * GCI_ccontent( const GCI_str *str )
67 {
68 return str->val;
69 }
70
71 /*
72 * GCI_streq returns 1 if two string have an equal content, 0 otherwise.
73 */
GCI_streq(const GCI_str * s1,const GCI_str * s2)74 int GCI_streq( const GCI_str *s1,
75 const GCI_str *s2 )
76 {
77 int l = s1->used;
78
79 if ( l != s2->used )
80 return 0;
81 return ( memcmp( s1->val, s2->val, l ) == 0 ) ? 1 : 0;
82 }
83
84 /*
85 * concat appends the content of second to first. second_len contains the
86 * length of second. second may not be 0-terminated.
87 * The return value is either GCI_OK or GCI_BufferTooSmall.
88 */
concat(GCI_str * first,const char * second,int size)89 static GCI_result concat( GCI_str *first,
90 const char *second,
91 int size )
92 {
93 if ( first->used + size > first->max )
94 return GCI_BufferTooSmall;
95
96 memcpy( first->val + first->used, second, size );
97 first->used += size;
98 return GCI_OK;
99 }
100
101 /*
102 * GCI_strcat appends the content of second to first.
103 * The return value is either GCI_OK or GCI_BufferTooSmall.
104 */
GCI_strcat(GCI_str * first,const GCI_str * second)105 GCI_result GCI_strcat( GCI_str *first,
106 const GCI_str *second )
107 {
108 return concat( first, second->val, second->used );
109 }
110
111 /*
112 * GCI_strcats appends the content of the 0-terminated string second to first.
113 * The return value is either GCI_OK or GCI_BufferTooSmall.
114 */
GCI_strcats(GCI_str * first,const char * second)115 GCI_result GCI_strcats( GCI_str *first,
116 const char *second )
117 {
118 return concat( first, second, strlen( second ) );
119 }
120
121 /*
122 * GCI_strsetlen sets the length of str to max. If max if bigger than the
123 * string's internal maximum it is set to the string's internal maximum.
124 */
GCI_strsetlen(GCI_str * str,int max)125 void GCI_strsetlen( GCI_str *str,
126 int max )
127 {
128 if ( str->max < max )
129 str->used = str->max;
130 else
131 str->used = max;
132 }
133
134 /*
135 * GCI_strcpy sets the content of first to the content of second.
136 * The return value is either GCI_OK or GCI_BufferTooSmall.
137 */
GCI_strcpy(GCI_str * first,const GCI_str * second)138 GCI_result GCI_strcpy( GCI_str *first,
139 const GCI_str *second )
140 {
141 if ( first->max < second->used )
142 return GCI_BufferTooSmall;
143
144 memcpy( first->val, second->val, second->used );
145 first->used = second->used;
146 return GCI_OK;
147 }
148
149 /*
150 * GCI_strfromascii creates a GCI_str from a character pointer. The content's
151 * maximum is set to max, the content itself is taken from ptr.
152 * The used length is set to 0.
153 * THE FILLED GCI_str MUST NEVER BE PASSED TO GCI_strfree!
154 * The passed string is returned.
155 */
GCI_strfromascii(GCI_str * str,char * ptr,int max)156 GCI_str *GCI_strfromascii( GCI_str *str,
157 char *ptr,
158 int max )
159 {
160 str->val = ptr;
161 str->used = 0;
162 str->max = max;
163
164 return str;
165 }
166
167 /*
168 * GCI_migratefromascii creates a GCI_str from a character pointer.
169 * The content's maximum and its length is set to length of the zero-terminated
170 * string in ptr, the content itself is taken from ptr.
171 * THE FILLED GCI_str MUST NEVER BE PASSED TO GCI_strfree!
172 * The passed string is returned.
173 */
GCI_migratefromascii(GCI_str * str,const char * ptr)174 const GCI_str *GCI_migratefromascii( GCI_str *str,
175 const char *ptr )
176 {
177 str->val = (char *) ptr;
178 str->used = strlen( ptr );
179 str->max = str->used;
180
181 return str;
182 }
183
184 /*
185 * GCI_stralloc allocates the content of a string. The content will have
186 * size bytes. The former content won't be freed if there is something
187 * allocated.
188 * The return value is either GCI_OK or GCI_NoMemory.
189 */
GCI_stralloc(void * hidden,GCI_str * str,unsigned size)190 GCI_result GCI_stralloc( void *hidden,
191 GCI_str *str,
192 unsigned size )
193 {
194 if ( size == 0 )
195 size = 1;
196 if ( ( str->val = (char *) GCI_malloc( hidden, size ) ) == NULL )
197 return GCI_NoMemory;
198
199 str->used = 0;
200 str->max = size;
201 return GCI_OK;
202 }
203
204 /*
205 * GCI_strfree deallocates the content of a string. The string itself isn't
206 * freed. The content is set to NULL.
207 */
GCI_strfree(void * hidden,GCI_str * str)208 void GCI_strfree( void *hidden,
209 GCI_str *str )
210 {
211 if ( str->val != NULL )
212 GCI_free( hidden, str->val );
213
214 str->val = NULL;
215 str->max = str->used = 0;
216 }
217
218 /*
219 * GCI_strdup duplicates the content of a string second and assigns it to
220 * first. The content of first will be overwritten without any cleanup.
221 * This function allocates the needed bytes only.
222 * The return value is either GCI_OK or GCI_NoMemory.
223 */
GCI_strdup(void * hidden,GCI_str * first,const GCI_str * second)224 GCI_result GCI_strdup( void *hidden,
225 GCI_str *first,
226 const GCI_str *second )
227 {
228 if ( ( first->val = (char *) GCI_malloc( hidden, second->used ) ) == NULL )
229 return GCI_NoMemory;
230
231 memcpy( first->val, second->val, second->used );
232 first->used = first->max = second->used;
233 return GCI_OK;
234 }
235
236 /*
237 * GCI_strtoascii duplicates the content of the string str to a newly created
238 * ASCIIZ string which is returned. NULL is returned in case of an error or
239 * if str describes a NULL string (in opposite to an empty string).
240 */
GCI_strtoascii(void * hidden,const GCI_str * str)241 char *GCI_strtoascii( void *hidden,
242 const GCI_str *str )
243 {
244 char *retval;
245
246 if ( ( str == NULL ) || ( str->val == NULL ) )
247 return NULL;
248 if ( ( retval = (char *) GCI_malloc( hidden, str->used + 1 ) ) == NULL )
249 return NULL;
250
251 memcpy( retval, str->val, str->used );
252 retval[str->used] = '\0';
253 return retval;
254 }
255
256 /*
257 * GCI_uppercase transforms the content of str to its uppercased value.
258 * We may or may not convert foreign characters. It depends on the runtime
259 * system and on the environment settings of codepage/language.
260 */
GCI_uppercase(void * hidden,GCI_str * str)261 void GCI_uppercase( void *hidden,
262 GCI_str *str )
263 {
264 int i, len = str->used;
265 char *ptr = str->val;
266
267 for ( i = 0; i < len; i++, ptr++ )
268 *ptr = (char) GCI_toupper( *ptr );
269 }
270
271 /*
272 * GCI_describe converts a GCI_result to a more or less human readable
273 * string. The caller shall provide a string with at least 80 byte.
274 * THIS FUNCTION IS NOT THREAD SAFE.
275 */
GCI_describe(GCI_str * description,GCI_result rc)276 void GCI_describe( GCI_str *description,
277 GCI_result rc )
278 {
279 char *ptr = NULL;
280 static char buf[40];
281
282 switch ( rc )
283 { /* oversized lines! */ /* here is the limit for the text: -->blahblah" */
284 case GCI_OK: ptr = "GCI completed successfully"; break;
285 case GCI_NoMemory: ptr = "Out of memory while processing a GCI request"; break;
286 case GCI_WrongInput: ptr = "Unexpected input, either unknown type or illegal data"; break;
287 case GCI_NumberRange: ptr = "Number out of the allowed range"; break;
288 case GCI_StringRange: ptr = "String too big for the defined buffer"; break;
289 case GCI_UnsupportedType: ptr = "Illegal combination of type/size"; break;
290 case GCI_UnsupportedNumber: ptr = "Unsupported number like NAN, +INF, -INF"; break;
291 case GCI_BufferTooSmall: ptr = "Structure too complex for static internal buffer"; break;
292 case GCI_MissingName: ptr = "An element of the structure is missing"; break;
293 case GCI_MissingValue: ptr = "A value of the structure is missing"; break;
294 case GCI_IllegalName: ptr = "The name or part of the name is illegal for the interpreter"; break;
295 case GCI_RexxError: ptr = "A problem raises when communicating with the interpreter"; break;
296 case GCI_NoBaseType: ptr = "The type won't fit the requirements for basic types (arguments/return value)"; break;
297 case GCI_InternalError: ptr = "An unknown internal GCI error occured"; break;
298 case GCI_FunctionAlreadyKnown: ptr = "New REXX function already registered to the interpreter"; break;
299 case GCI_LibraryNotFound: ptr = "The external library was not found or can't be loaded"; break;
300 case GCI_NoLibraryFunction: ptr = "The external function can't be found in the external library"; break;
301 case GCI_FunctionNotFound: ptr = "The REXX function was not or no longer registered by the interpreter"; break;
302 case GCI_SyntaxError: ptr = "The number of arguments is wrong or an argument is missing"; break;
303 case GCI_CoreConfused: ptr = "The core of GCI can't determine how to invoke generic functions"; break;
304 case GCI_ArgStackOverflow: ptr = "GCI's internal stack for arguments got an overflow"; break;
305 case GCI_NestingOverflow: ptr = "GCI counted too many nested LIKE containers"; break;
306 default:
307 break;
308 }
309
310 if ( ptr == NULL )
311 {
312 ptr = buf;
313 sprintf( buf, "Unknown GCI error %d", rc );
314 }
315 description->val = ptr;
316 description->used = strlen(ptr);
317 description->max = description->used;
318 }
319
320 /*
321 * GCI_strswap exchanges two strings' content completely.
322 */
GCI_strswap(GCI_str * first,GCI_str * second)323 void GCI_strswap( GCI_str *first,
324 GCI_str *second )
325 {
326 GCI_str h;
327
328 h = *first;
329 *first = *second;
330 *second = h;
331 }
332