/* * readRexx works as a merged version of the function GCI_readRexx and * GCI_readNewRexx below. The difference is the flag allocate. If this is * set, the function works aas GCI_readNewRexx, otherwise is works like * GCI_readRexx. */ static GCI_result readRexx( void *hidden, const GCI_str *name, GCI_str *target, int symbolicAccess, int signalOnNovalue, int allocate, int *novalue ) { tsd_t *TSD = (tsd_t *) hidden; int retval; GCI_result rc; int Lengths[2]; char *Strings[2]; int allocated; Lengths[0] = GCI_strlen( name ); Strings[0] = (char *) GCI_ccontent( name ); if ( !signalOnNovalue ) set_ignore_novalue( (const tsd_t *) hidden ); retval = IfcVarPool( (tsd_t *) hidden, ( symbolicAccess ) ? RX_GETSVAR : RX_GETVAR, Lengths, Strings, &allocated ); if ( !signalOnNovalue ) clear_ignore_novalue( (const tsd_t *) hidden ); switch ( retval ) { case RX_CODE_OK: if ( novalue ) *novalue = 0; rc = GCI_OK; break; case RX_CODE_NOVALUE: if ( novalue ) *novalue = 1; rc = GCI_OK; break; case RX_CODE_INVNAME: return GCI_IllegalName; default: if ( allocated ) FreeTSD( Strings[1] ); return GCI_RexxError; } if ( Lengths[1] == RX_NO_STRING ) return GCI_RexxError; /* * We must copy the value's content (Strings[1]/Lengths[1]) and we must * destroy the value if "allocated" is set. */ if ( allocate ) { if ( ( rc = GCI_stralloc( hidden, target, Lengths[1] ) ) != GCI_OK ) { if ( allocated ) FreeTSD( Strings[1] ); return rc; } } else if ( Lengths[1] > GCI_strmax( target ) ) { if ( allocated ) FreeTSD( Strings[1] ); return GCI_BufferTooSmall; } memcpy( GCI_content( target ), Strings[1], Lengths[1] ); if ( allocated ) FreeTSD( Strings[1] ); GCI_strsetlen( target, Lengths[1] ); return GCI_OK; }
/* * Returns the translated function code from GCI_result to the code that * Regina shall return to the caller. * This function set the textual representation of an error code to that value * that will be accessed by RxFuncErrMsg() and sets the variable GCI_RC to * that value, too. * * dispo is either NULL (or the content is NULL) or contains the position of * the error within the structure. dispo's content will be deallocated. */ static int GCIcode2ReginaFuncCode( tsd_t *TSD, GCI_result rc, GCI_str *dispo, int forceError ) { GCI_str description, fullinfo, *fi = NULL, *out; volatile char *tmpDispo, *tmpFull = NULL, *tmpBest; streng *h; char GCI_RC[7]; GCI_strOfCharBuffer(GCI_RC); GCI_strcats( &str_GCI_RC, "GCI_RC" ); GCI_describe( &description, rc ); if ( ( dispo != NULL ) && ( GCI_content( dispo ) == NULL ) ) dispo = NULL; if ( ( dispo != NULL ) && ( rc != GCI_OK ) ) { if ( GCI_stralloc( TSD, &fullinfo, GCI_strlen( dispo ) + GCI_strlen( &description ) + 3 ) == GCI_OK ) { fi = &fullinfo; GCI_strcpy( fi, &description ); GCI_strcats( fi, ": " ); GCI_strcat( fi, dispo ); } } out = ( fi != NULL ) ? fi : &description; GCI_writeRexx( TSD, &str_GCI_RC, out, 0 ); if ( ( rc == GCI_OK ) && !forceError ) { if ( dispo != NULL ) GCI_strfree( TSD, dispo ); if ( fi != NULL ) GCI_strfree( TSD, fi ); return 0; } h = streng_of( TSD, &description ); tmpDispo = tmpstr_of( TSD, h ); Free_stringTSD( h ); if ( fi != NULL ) { h = streng_of( TSD, fi ); tmpFull = tmpstr_of( TSD, h ); Free_stringTSD( h ); } if ( dispo != NULL ) GCI_strfree( TSD, dispo ); if ( fi != NULL ) GCI_strfree( TSD, fi ); /* * We have two temporary strings describing the error condition. * All stuff we have to deallocate is deallocated. Let's go. */ tmpBest = ( tmpFull != NULL ) ? tmpFull : tmpDispo; set_err_message( TSD, (char *) tmpBest, "" ); switch ( rc ) { case GCI_NoMemory: exiterror( ERR_STORAGE_EXHAUSTED, 0 ); case GCI_WrongInput: exiterror( ERR_INCORRECT_CALL, 980, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_NumberRange: exiterror( ERR_INCORRECT_CALL, 981, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_StringRange: exiterror( ERR_INCORRECT_CALL, 982, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_UnsupportedType: if ( !forceError ) return 71; /* RXFUNC_BADTYPE + 1 */ exiterror( ERR_INCORRECT_CALL, 983, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_UnsupportedNumber: exiterror( ERR_INCORRECT_CALL, 984, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_BufferTooSmall: exiterror( ERR_INCORRECT_CALL, 985, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_MissingName: exiterror( ERR_INCORRECT_CALL, 986, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_MissingValue: exiterror( ERR_INCORRECT_CALL, 987, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_IllegalName: exiterror( ERR_INCORRECT_CALL, 988, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_RexxError: exiterror( ERR_INCORRECT_CALL, 989, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_NoBaseType: exiterror( ERR_INCORRECT_CALL, 990, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_SyntaxError: exiterror( ERR_INCORRECT_CALL, 991, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_ArgStackOverflow: exiterror( ERR_INCORRECT_CALL, 992, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); case GCI_NestingOverflow: exiterror( ERR_INCORRECT_CALL, 993, ( tmpDispo ) ? ": " : "", ( tmpDispo ) ? tmpDispo : "" ); default: break; } exiterror( ERR_INTERPRETER_FAILURE, 1, __FILE__, __LINE__, tmpBest ); return 0; /* Keep the compiler happy */ }
/* * decode decodes one line of the type structure named str into the * a parseinfo block called pi. depth is the current depth which may be 0. * * newName is set in case of ARRAY (to the empty string) or CONTAINER. In this * case is set to the LIKE parameter or to the empty string. * * Leading and trailing spaces are ignored completely, "INDIRECTFLOAT32" is * acceptable. Differences in case are ignored. * * THE GENERATED TYPE MAY HAVE AN ILLEGAL BIT SIZE. IT ISN'T CHECKED ALWAYS! * * Return values: * GCI_OK: Line understood, *pi filled. * GCI_UnsupportedType: Wrong type of input, e.g. FLOAT31 or the empty string. * GCI_NoBaseType: The type won't fit the requirements for basic types. */ static GCI_result decode( void *hidden, const GCI_str *str, GCI_parseinfo *pi, int depth, GCI_str *newName ) { const char *ptr = GCI_ccontent( str ); int size = GCI_strlen( str ); /* * Chop off leading and trailing spaces. We really need it. */ while ( ( size > 0 ) && GCI_isspace( *ptr ) ) { ptr++; size--; } while ( ( size > 0 ) && GCI_isspace( ptr[size - 1] ) ) size--; memset( pi, 0, sizeof( GCI_parseinfo ) ); if ( ( pi->type = checkname( &ptr, &size ) ) == GCI_unknown ) return GCI_UnsupportedType; if ( pi->type == GCI_indirect ) { while ( ( size > 0 ) && GCI_isspace( *ptr ) ) { ptr++; size--; } pi->type = checkname( &ptr, &size ); if ( ( pi->type == GCI_unknown ) || ( pi->type == GCI_indirect ) ) return GCI_UnsupportedType; pi->indirect = 1; } else pi->indirect = 0; /* * Check for a size operand. */ while ( ( size > 0 ) && GCI_isspace( *ptr ) ) { ptr++; size--; } /* * We may have a size operand only if not an array or container is * processed! * This implementation shall support plain types like "INTEGER" without * any bit size. */ switch ( pi->type ) { case GCI_container: if ( size > 0 ) { GCI_str tmp; if ( checkname( &ptr, &size ) != GCI_like ) return GCI_UnsupportedType; while ( ( size > 0 ) && GCI_isspace( *ptr ) ) { ptr++; size--; } if ( size == 0 ) { /* * Single "like" after "container". */ return GCI_UnsupportedType; } while ( GCI_isspace( ptr[size - 1] ) ) size--; /* * Cut off a final dot, we append one later. */ if ( ptr[size - 1] == '.' ) { /* * Check for single "." as stem. */ if ( --size == 0 ) return GCI_UnsupportedType; } if ( GCI_stralloc( hidden, newName, size + 256 ) != GCI_OK ) return GCI_NoMemory; GCI_strfromascii( &tmp, (char *) ptr, size ); GCI_strsetlen( &tmp, size ); GCI_strcpy( newName, &tmp ); size = 0; } /* fall through */ case GCI_array: if ( size > 0 ) return GCI_UnsupportedType; if ( ( depth == 0 ) && !pi->indirect ) { if ( GCI_content( newName ) != NULL ) GCI_strfree( hidden, newName ); return GCI_NoBaseType; } pi->size = 0; return GCI_OK; case GCI_integer: if ( size == 0 ) pi->size = 8 * sizeof( int ); break; case GCI_unsigned: if ( size == 0 ) pi->size = 8 * sizeof( unsigned ); break; case GCI_float: if ( size == 0 ) pi->size = 8 * sizeof( double ); /* surprised? */ break; case GCI_char: if ( size == 0 ) pi->size = 8 * 1; /* always, even in unicode or utf8 systems */ break; case GCI_string: if ( size == 0 ) /* length must be supplied */ return GCI_UnsupportedType; break; // JLF needed for portability: aliases which depend on the system & bitness. // Each alias defines a type and a size, no size accepted after these aliases. case GCI_long: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_integer; pi->size = 8 * sizeof( long ); break; case GCI_llong: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_integer; pi->size = 8 * sizeof( long long ); break; case GCI_pointer: // opaque if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_unsigned; pi->size = 8 * sizeof( void* ); break; case GCI_size_t: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_unsigned; pi->size = 8 * sizeof( size_t ); break; case GCI_ssize_t: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_integer; pi->size = 8 * sizeof( ssize_t ); break; case GCI_ulong: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_unsigned; pi->size = 8 * sizeof( unsigned long ); break; case GCI_ullong: if ( size > 0 ) return GCI_UnsupportedType; pi->type = GCI_unsigned; pi->size = 8 * sizeof( unsigned long long ); break; default: return GCI_UnsupportedType; } if ( size > 0 ) { if ( GCI_string2bin( hidden, ptr, size, &pi->size, sizeof( pi->size ), GCI_unsigned ) != GCI_OK ) return GCI_UnsupportedType; } if ( ( pi->type == GCI_string ) && ( pi->size > 0 ) ) return GCI_OK; /* * A byte has 8 bit, always! We don't support PDP10. */ if ( pi->type != GCI_string ) { if ( pi->size % 8 ) return GCI_UnsupportedType; pi->size /= 8; } return GCI_validate( pi->size, pi->type, depth || pi->indirect ); }