/* * GCI_parsetree tries to interpret the type information of the first * generation. That are the branches "branch.return", "branch.1", * "branch.2", ... The value of "base" is such an identifier. * base must be a string large enough to hold the longest type variable name * which occurs in the tree including the branch name. This argument will * contain the variable's name which forces the error in case of an error. * The buffer is always modified. * * callback is described later. arg is passed to callback without further * interpretation. * * prefixChar is the prefix that must be used in front of stem names. * * The function loops over a type structure tree, the current node name is * placed in cb->buffer. We do a depth-first iteration. The callback function * is called at least for each type declaration. The callback is described * below the error codes. * * THE COMPLETE PARSING IS STOPPED IF THE callback RETURNS ANOTHER VALUE THAN * GCI_OK. * * THE GENERATED TYPES MAY HAVE ILLEGAL BIT SIZES. IT ISN'T CHECKED ALWAYS! * * Return values: * GCI_OK: Everything is fine. * * In case of an error cb->buffer will contain the * variable's name where the problem raises first. * * GCI_MissingName: A variable's name isn't set. This is the equivalence * for GCI_MissingValue in the type parsing step. The * system may or may not raise a NOVALUE condition instead * depending on the implementation. * GCI_BufferTooSmall: The variable's name buffer cb->buffer can't hold the * complete variable's name or the type string exceeds * 256 byte. * GCI_IllegalName: The variables name in cb->buffer is illegal in terms of * Rexx. In general, the basename of GCI_paretree is * wrong. * GCI_RexxError: An unexpected error is returned by the interpreter * while trying to access Rexx variables. * GCI_UnsupportedType: Wrong type of input, e.g. FLOAT31 or the empty string * in a type description string. Another reason is an * internal error since the default sizes for "unsigned" * and "integer" are not supported. * GCI_WrongInput: Strange characters occur in the input string as the * bit size of the type. * GCI_NumberRange: Number to small or big to fit into the desired type * with the desired destbyte-size. This applies to the * element count of an "ARRAY" or "CONTAINER" type size * or the bit size of the plain type. * GCI_NoBaseType: The type won't fit the requirements for basic types. * * And there are numerous other possible errors returned by cb->callback. * ***************************************************************************** * * Description of the callback: * This function will be called when a type string has been parsed. The * GCI_parseinfo structure is filled to allow the caller allocating enough * memory. * * depth is the current depth within the structure starting with 0. itemnumber * is the current number of the item within a structure starting with 1. * Arrays will have an item of 1, not more, not less. The item describes all * identical values in the array. * itemnumber will be 0 for the base element (of depth 0). * * itemnumber may be -1! This happens on containers and arrays after * processing the last subitem. This allows the callback to close the * current container and to do some final processing. * * arg is the copy of the arg parameter of GCI_parsetree. A hidden parameter * must be passed in arg (too) if it is needed. * * The caller of GCI_parsetree is responsible to understand additional * return codes of the callback. */ GCI_result GCI_parsetree( void *hidden, GCI_str *base, GCI_result (*callback)(int depth, int itemnumber, void *arg, const GCI_parseinfo *info), void *arg, const char *prefixChar ) { callblock cb; /* * All simple type values must fit into a static buffer. */ char tmp[256]; GCI_strOfCharBuffer( tmp ); /* * We wrap the parameters in a block to prevent further parameters. * We use the given buffer for all further processing. We'll have the * errorneous string at once in that case. */ cb.hidden = hidden; cb.buffer = base; cb.depth = 0; cb.callback = callback; cb.arg = arg; cb.tempbuf = str_tmp; cb.recurCount = 0; cb.prefixChar = prefixChar; return parse( &cb, 0 ); }
/* * 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 */ }