#ifdef WIN32 #pragma warning(disable: 4786) // Stop warnings about truncated identifiers in //debug info #endif #include "parser2.h" #include "debug.h" #include void parser::function_param_value_t::output( outstream_t& out) const { // we don't output any initial `virtual'. //out.out << "vviirrttuuaall\n"; debug0 << "parser::function_param_value_t::Output ignoring virtual. expr=`" << *this->expression << "'\n"; //debug_output_backtraces( std::cerr); output_node( *this->expression, out); if ( this->comma) output_node( *this->comma, out); } void parser::function_param_values_t::output( outstream_t& out) const { if ( this->open) output_node( *this->open, out); for ( params_t::const_iterator it=this->params.begin(); it!=this->params.end(); ++it) { if ( *it) output_node( *(*it), out); } if ( this->close) output_node( *this->close, out); } void parser::named_functioncall_expression_t::output( outstream_t& out) const { output_node( *this->name, out); output_node( *this->params, out); } namespace { using namespace parser; struct ArrayOp : misc_t { ArrayOp() : open( NULL), index( NULL), close( NULL) {} keyword_OPENSQUARE* open; expression_t* index; keyword_CLOSESQUARE* close; }; struct Cast : expression_t { static const char* static_description() { return ""; } virtual const char* description() const { return static_description(); } Cast() : open( NULL), type( NULL), close( NULL), expression( NULL) {} keyword_OPENROUND* open; declarator_name_t* type; // should be anonymous keyword_CLOSEROUND* close; expression_t* expression; }; struct StringExpression : expression_t { static const char* static_description() { return "..."; } virtual const char* description() const { return static_description(); } StringExpression() : string( NULL) {} string_t* string; }; struct NewExpressionOp : misc_t { static const char* static_description() { return "new ..."; } virtual const char* description() const { return static_description(); } NewExpressionOp() : ne( NULL), params( NULL) {} keyword_new* ne; function_param_values_t* params; // can be null }; void FindTypes( function_param_values_t& params, lexer_t& lexer, context_t& context) /* does crude name lookup to find types of all parameters in the given function call.*/ { debug0 << "FindTypes, num params=" << params.params.size() << "\n"; for ( function_param_values_t::params_t::iterator it=params.params.begin(); it!=params.params.end(); ++it) { if ( expression_list_t* explist=dynamic_cast< expression_list_t*>( (*it)->expression)) { debug0 << "explist->items.size()=" << explist->items.size() << "\n"; if ( explist->items.size()==1) { debug0 << "explist->items.front() is type " << typeid( *explist->items.front()).name() << "\n"; if ( expression_list_item_t* expritem=dynamic_cast< expression_list_item_t*>( explist->items.front())) { debug0 << "expritem->expression is type " << typeid( *expritem->expression).name() << "\n"; if ( name_expression_t* nameexpr=dynamic_cast< name_expression_t*>( expritem->expression)) { declarator_t* virtual_type = lookup_name( *context.parentnamespace, *nameexpr->name); if ( !virtual_type) throw parser::error_t( lexer, "Couldn't find declaration of name"); (*it)->virtual_type = virtual_type->is_simple_reference(); if ( !(*it)->virtual_type) (*it)->virtual_type = virtual_type->is_simple_type(); if ( !(*it)->virtual_type) { throw parser::error_t( lexer, "virtual param should be simple type or reference to simple type"); } } } } } if ( !(*it)->virtual_type) { throw parser::error_t( lexer, "Can't deduce type of parameter"); } } } function_param_values_t* TryGetFnParams( lexer_t& lexer, context_t& context0) { debug_TRACE_PRETTY; debug0 << "TryGetFnParams called, next lex item is " << (*lexer.PeekNext()) << "\n"; if ( context0.location == context_t::TEMPLATESPEC) { debug0 << debug_PLACE "refusing to look for fn pararms inside templatespec\n"; return NULL; } lexer_mark_t lexmark( lexer); keyword_OPENROUND* open=TryGet< keyword_OPENROUND>( lexer); if ( !open) return NULL; function_param_values_t* fnparamvalues = new function_param_values_t; fnparamvalues->open = open; context_t context( context0); context.location = context_t::FNPARAMS; for(;;) { debug0 << debug_PLACE << "fnparamvalues=`" << *fnparamvalues << "\n"; fnparamvalues->close=TryGet< keyword_CLOSEROUND>( lexer); if ( fnparamvalues->close) { fnparamvalues->set_text( fnparamvalues->open->begin, fnparamvalues->close->end); debug0 << "TryGetFnParams returning " << *fnparamvalues << "\n"; break; } function_param_value_t* param=new function_param_value_t; lexer_mark_t lexmark_startofthisparam( lexer); if ( context.caller_dispatch) { if ( (param->virtua=TryGet< keyword_virtual>( lexer))) { debug0 << "found virtual keyword before parameter\n"; ++fnparamvalues->num_virtual_params; } } param->expression = tryget_expression( lexer, context); if ( param->expression) debug0 << "tryget_expression returned `" << *param->expression << "'\n"; else debug0 << "tryget_expression returned NULL\n"; if ( param->expression && !TryPeek< keyword_COMMA>( lexer) && !TryPeek< keyword_CLOSEROUND>( lexer)) { debug0 << "expression `" << *param->expression << "' can't be function call value, because followed by `" << *lexer.PeekNext() << "', not `,' or `)'\n"; param->expression = NULL; lexmark_startofthisparam.Backtrack(); // carry on looking - next if will be true. } if ( param->expression) { debug0 << debug_PLACE << " param->expression is non-null\n"; } else { if ( !context.support_embedded_functions_in_expressions) { debug0 << "Invalid expression in call to function but -embeddedfns not specified, so we don't look for fn defintion.\n"; lexmark_startofthisparam.Backtrack(); lexmark.Backtrack(); return NULL; } debug0 << "looking for a function definition - extesion to allow embedded functions in STL algorithm calls.\n"; bool have_found_embedded_fn_definition = false; declarator_names_t* declnames = NULL; if ( !declnames) declnames = tryget_declaratornames( lexer, context); if ( !declnames) declnames = tryget_declarator_names_newsyntax( lexer, context); if ( !declnames) { debug0 << debug_PLACE << "!declnames - backtracking\n"; lexmark_startofthisparam.Backtrack(); lexmark.Backtrack(); return NULL; } if ( declnames->items.size()!=1) { debug0 << debug_PLACE << "declnames->items.size()!=1\n"; lexmark_startofthisparam.Backtrack(); lexmark.Backtrack(); return NULL; } declarator_terminator_t* declterm = declnames->items.back(); debug0 << "Found possible embedded fn\n"; if ( function_t* fn=declterm->declarator->is_simple_function()) { debug0 << "IsSimpleFn returned non-NULL\n"; (void) fn; // only used in debug builds' assert. assert( fn->parent==context.parentnamespace); if ( declterm->terminator && typeid( *declterm->terminator)==typeid( fnbody_t)) { debug0 << "Found nested function `" << *declterm << "'\n"; // move it to the first non-function parent namespace. for ( logical_namespace_t* lns=context.parentnamespace; ; lns=lns->parent) { if ( !lns) { std::cerr << "Can't find parent namespace for nested function to be moved into\n"; break; } if ( !dynamic_cast< function_t*>( lns) && !dynamic_cast< compound_t*>( lns)) { // this is a namespace that we can move the function into. //if ( lns->leafname) debug0 << "moving function to namespace " << *lns->leafname << "\n"; //else debug0 << "moving function to unnamed namespace\n"; lns->append_item( declnames); declarator_name_t* declname=dynamic_cast< declarator_name_t*>( declterm->declarator); if ( !declname) { // embedded function is anonymous, so we give it a unique name declname = new declarator_name_t; declname->subtype = declterm->declarator; std::stringstream uniquename; uniquename << "cmm_uniquename_" << lexer.GetLineNumber() << "_" << lexer.GetColumnNumber(); declname->name = name_t::MakeName( uniquename.str().c_str(), context); declterm->declarator = declname; } debug0 << "embedded fn def is: " << *declnames << "\n"; name_expression_t* nameexpression = new name_expression_t; nameexpression->name = declname->name; param->expression = nameexpression; have_found_embedded_fn_definition = true; break; } } } } if ( !have_found_embedded_fn_definition) { lexmark_startofthisparam.Backtrack(); lexmark.Backtrack(); return NULL; } else { debug0 << "Found embedded fn def\n"; } } param->comma = TryGet< keyword_COMMA>( lexer); param->set_text( param->expression->begin, lexer.GetPos()); if ( !param->comma && !TryPeek< keyword_CLOSEROUND>( lexer)) { debug0 << debug_PLACE << "!param->comma && !TryPeek< keyword_CLOSEROUND>( lexer)\n"; lexmark_startofthisparam.Backtrack(); lexmark.Backtrack(); return NULL; } fnparamvalues->params.push_back( param); debug0 << debug_PLACE << " fnparamvalues="<<*fnparamvalues<<"\n"; } debug0 << debug_PLACE << "\n"; if ( context.caller_dispatch && fnparamvalues->num_virtual_params > 0) { FindTypes( *fnparamvalues, lexer, context); // invent virtual fn and put it in the first non-fn parent namespace. } return fnparamvalues; } expression_t* TryGetExpression2( lexer_t& lexer, context_t& context); Cast* TryGetCast( lexer_t& lexer, context_t& context) { debug_TRACE_PRETTY; lexer_mark_t lexmark( lexer); Cast* cast = new Cast; context_t context2 = context; context2.location = context_t::EXPRESSION; debug0 << "TryGetCast, next token is " << *lexer.PeekNext() << "\n"; if ( ( cast->open = TryGet< keyword_OPENROUND>( lexer)) && ( cast->type = parser::tryget_declarator_name( lexer, context2)) && ( cast->type->name == NULL) && ( cast->close = TryGet< keyword_CLOSEROUND>( lexer)) && ( cast->expression = tryget_expression/*TryGetExpression2*/( lexer, context)) ) { cast->begin = cast->open->begin; cast->end = lexer.GetPos(); debug0 << "found cast: " << *cast << "\n"; return cast; } else { lexmark.Backtrack(); delete cast; return NULL; } } named_functioncall_expression_t* TryGetNamedFnCallExpression( lexer_t& lexer, context_t& context) { debug_TRACE_PRETTY; lexer_mark_t lexmark( lexer); name_t* name = tryget_name( lexer, context); if ( !name) return NULL; debug0 << "TryGetNamedFnCallExpression: found name " << *name << "\n"; function_param_values_t* params = TryGetFnParams( lexer, context); if ( !params) { lexmark.Backtrack(); return NULL; } named_functioncall_expression_t* fncall = new named_functioncall_expression_t; fncall->name = name; fncall->params = params; if ( fncall->params->num_virtual_params > 0) { debug0 << "found named function call with virtual param(s): " << *fncall << "\n"; } debug0 << "found named function call: " << *fncall << "\n"; return fncall; } expression_t* TryGetExpression2( lexer_t& lexer, context_t& context) { debug_TRACE_PRETTY; lexer_mark_t lexmark( lexer); expression_t* ret = NULL; debug0 << "TryGetExpression2, item is " << (*lexer.PeekNext()) << ", context.location=" << context.location <<"\n"; if ( context.location!=context_t::TEMPLATESPEC) { if ( 0) ; else if ( named_functioncall_expression_t* fncall=TryGetNamedFnCallExpression( lexer, context)) { debug0 << "TryGetNamedFnCallExpression returned " << *fncall << "\n"; ret = fncall; } /*else if ( keyword_TILDE* tilde=TryPeek< keyword_TILDE>( lexer)) { debug0 << "found tilde\n"; ret = tilde; }*/ else if ( Cast* cast = TryGetCast( lexer, context)) { debug0 << "found cast\n"; ret = cast; } } if ( ret) { // do nothing. } else if ( keyword_OPENROUND* open = TryGet< keyword_OPENROUND>( lexer)) { debug0 << debug_PLACE << "found bracket expr\n"; context_t context2( context); context2.location = context_t::EXPRESSION; bracket_expression_t* bracketexpression = new bracket_expression_t; bracketexpression->open = open; bracketexpression->expression = tryget_expression( lexer, context2); if ( !bracketexpression->expression) { lexmark.Backtrack(); return NULL; } bracketexpression->close = TryGet< keyword_CLOSEROUND>( lexer); if ( !bracketexpression->close) { lexmark.Backtrack(); return NULL; } bracketexpression->set_text( open->begin, lexer.GetPos()); ret = bracketexpression; } else if ( name_t* name = tryget_name( lexer, context)) { debug0 << "read name `" << *name << "'\n"; name_expression_t* nameexpr = new name_expression_t; nameexpr->name = name; nameexpr->set_text( name->begin, lexer.GetPos()); ret = nameexpr; } else if ( node_t* type = tryget_typename( lexer, context)) { typename_expression_t* typenameexpr = new typename_expression_t; typenameexpr->type = type; typenameexpr->set_text( type->begin, type->end); ret = typenameexpr; debug0 << "read typenameexpr: " << *typenameexpr << "\n"; } else if ( string_t* string = TryGet< string_t>( lexer)) { StringExpression* stringexpr = new StringExpression; stringexpr->string = string; stringexpr->set_text( string->begin, string->end); ret = stringexpr; } else if ( number_t* number = TryGet< number_t>( lexer)) { debug0 << "found number: `" << *number << "'\n"; numerical_expression_t* num = new numerical_expression_t; num->number = number; num->set_text( number->begin, lexer.GetPos()); ret = num; } else { debug0 << "failed to read expression2\n"; return NULL; } debug0 << "TryGetExpression2 returning " << *ret << "\n"; return ret; } ArrayOp* TryGetArrayOp( lexer_t& lexer, context_t& context0) { debug_TRACE_PRETTY; lexer_mark_t lexmark( lexer); if ( keyword_OPENSQUARE* open = TryGet< keyword_OPENSQUARE>( lexer)) { ArrayOp* arrayop = new ArrayOp; arrayop->begin = open->begin; arrayop->open = open; context_t context( context0); context.location = context_t::EXPRESSION; debug0 << "TryGetArrayOp calling tryget_expression\n"; arrayop->index = tryget_expression( lexer, context); if ( !arrayop->index) { delete arrayop; lexmark.Backtrack(); return NULL; } arrayop->close = Get< keyword_CLOSESQUARE>( lexer); arrayop->end = lexer.GetPos(); return arrayop; } else return NULL; } node_t* TryGetOperator( lexer_t& lexer, context_t& context, int& question_depth) { debug_TRACE_PRETTY; if ( context.location==context_t::TEMPLATESPEC) { if ( TryPeek< keyword_GT>( lexer)) return NULL; if ( TryPeek< keyword_OR>( lexer)) return lexer.GetNext(); if ( TryPeek< keyword_AMP>( lexer)) return lexer.GetNext(); if ( TryPeek< keyword_XOR>( lexer)) return lexer.GetNext(); if ( TryPeek< keyword_PLUS>( lexer)) return lexer.GetNext(); if ( TryPeek< keyword_MINUS>( lexer)) return lexer.GetNext(); if ( TryPeek< keyword_STAR>( lexer)) return lexer.GetNext(); if ( TryPeek< keyword_DIV>( lexer)) return lexer.GetNext(); if ( TryPeek< keyword_PERCENT>( lexer)) return lexer.GetNext(); if ( TryPeek< keyword_GTGT>( lexer)) return lexer.GetNext(); if ( TryPeek< keyword_LTLT>( lexer)) return lexer.GetNext(); if ( TryPeek< keyword_TILDE>( lexer)) return lexer.GetNext(); return NULL; } debug0 << "TryGetOperator called, next token is " << *lexer.PeekNext() << "\n"; if ( 0) ; else if ( context.location==context_t::TEMPLATESPEC && TryPeek< keyword_GT>( lexer)) { debug0 << "TryGetOperator, found `>' in context_t::TEMPLATESPEC\n"; return NULL; } else if ( TryPeek< keyword_CLOSESQUARE>( lexer)) { debug0 << "TryGetOperator found ']' - returing NULL\n"; return NULL; } else if ( ArrayOp* arrayop = TryGetArrayOp( lexer, context)) { debug0 << "TryGetOperator, found array op: " << *arrayop << "\n"; return arrayop; } else if ( operator_keyword_t* op=TryGet< operator_keyword_t>( lexer)) { debug0 << "TryGetOperator, found keyword op: " << *op << "\n"; return op; } else if ( question_depth && TryPeek< keyword_COLON>( lexer)) { --question_depth; return lexer.GetNext(); } else if ( TryPeek< keyword_QUESTION>( lexer)) { ++question_depth; return lexer.GetNext(); } else if ( function_param_values_t* fnparamvalues = TryGetFnParams( lexer, context)) { debug0 << "TryGetOperator: TryGetFnParams succeeded: " << *fnparamvalues <<"\n"; return fnparamvalues; } else if ( keyword_new* ne = TryGet< keyword_new>( lexer)) { NewExpressionOp* newexpr = new NewExpressionOp; newexpr->ne = ne; newexpr->params = TryGetFnParams( lexer, context); newexpr->set_text( ne->begin, lexer.GetPos()); return newexpr; } else if ( context.location!=context_t::FNPARAMS && TryPeek< keyword_COMMA>( lexer)) { return lexer.GetNext(); } else if ( TryGet< keyword_delete>( lexer)) { return lexer.GetNext(); } return NULL; } node_t* TryGetOperators( lexer_t& lexer, context_t& context, int& question_depth) { debug_TRACE_PRETTY; multiple_nodes_t* ops = new multiple_nodes_t; for(;;) { if ( context.location==context_t::FNPARAMS || context.location==context_t::TEMPLATESPEC) { if ( TryPeek< keyword_COMMA>( lexer)) { debug0 << debug_PLACE << "TryGetOperators: comma found, so returning NULL\n"; break; } } node_t* op = TryGetOperator( lexer, context, question_depth); if ( !op) break; debug0 << debug_PLACE << "found op, context=" << context << ": " << (*op) << "\n"; ops->items.push_back( op); } if ( ops->items.size()==0) { delete ops; return NULL; } debug0 << "TryGetOperators returning " << *ops << "\n"; return ops; } } namespace parser { expression_t* tryget_expression( lexer_t& lexer, context_t& context) /* todo: need to be able to not match `,' separators (for fn arguments) */ { debug_TRACE_PRETTY; lexer_mark_t lexmark( lexer); debug0 << "tryget_expression, context=" << context << ", next item=" << (*lexer.PeekNext()) << "\n"; expression_list_t* expr2list = new expression_list_t; expr2list->begin = lexer.GetPos(); /* We don't treat `:' as operator by default, because this confuses the parsing of `case :'. Instead, we remember if we saw `?', and look for a corresponding `:'. */ int question_depth = 0; for( bool firsttime=true;; firsttime=false) { debug0 << debug_PLACE << "tryget_expression loop: `" << *expr2list << "'\n"; debug0 << "question depth=" << question_depth << "\n"; expression_t* expression = NULL; node_t* op = NULL; if ( firsttime) { expression = TryGetExpression2( lexer, context); if ( expression) debug0 << debug_PLACE << "read expression `" << *expression << "'\n"; } if ( !expression) { debug0 << debug_PLACE << "next is: " << *lexer.PeekNext() << "\n"; op = TryGetOperators( lexer, context, question_depth); if ( op) debug0 << debug_PLACE << "op=`" << *op << "'\n"; else debug0 << debug_PLACE << "op=nil\n"; } if ( !firsttime && !op) break; if ( !expression) { expression = TryGetExpression2( lexer, context); if ( expression) debug0 << debug_PLACE << "after ops `" << *op << "', TryGetExpression2 returned " << *expression << "\n"; else debug0 << debug_PLACE << "TryGetExpression2 returned NULL\n"; } if ( !expression && !op) break; expr2list->items.push_back( new expression_list_item_t); expr2list->items.back()->preop = op; expr2list->items.back()->expression = expression; if ( !expression) break; } debug0 << debug_PLACE << "expr2list=" << *expr2list << "\n"; if ( expr2list->items.size()==0) { delete expr2list; lexmark.Backtrack(); return NULL; } expr2list->end = lexer.GetPos(); debug0 << "Found expression, context=" << context << ": " << *expr2list << "\n"; return expr2list; } expression_terminator_t* tryget_terminated_expression( lexer_t& lexer, context_t& context) { debug_TRACE_PRETTY; lexer_mark_t lexmark( lexer); expression_terminator_t* exprt = new expression_terminator_t; exprt->begin = lexer.GetPos(); exprt->expr = tryget_expression( lexer, context); if ( !exprt) { delete exprt->expr; delete exprt; lexmark.Backtrack(); return NULL; } exprt->semicolon = TryGet< keyword_SEMICOLON>( lexer); if ( !exprt->semicolon) { delete exprt->expr; delete exprt; lexmark.Backtrack(); return NULL; } exprt->end = exprt->semicolon->end; return exprt; } expression_t* get_expression( lexer_t& lexer, context_t& context) { debug_TRACE_PRETTY; expression_t* ret = tryget_expression( lexer, context); if ( !ret) throw parser::error_t( lexer, "Expecting expression"); return ret; } for_loop_initstatement_t* get_for_loop_initstatement( lexer_t& lexer, context_t& context) { debug_TRACE_PRETTY; // need to add support for declarations. for_loop_initstatement_t* ret = new for_loop_initstatement_t; ret->begin = lexer.GetPos(); if ( keyword_SEMICOLON* semicolon=TryGet< keyword_SEMICOLON>( lexer)) { debug0 << "found semi in for\n"; ret->simpledeclaration = semicolon; } else { debug0 << "Looking for for expr, " << *lexer.PeekNext() << "\n"; ret->expression = tryget_terminated_expression( lexer, context); if ( !ret->expression) { debug0 << "looking for for declnames, " << *lexer.PeekNext() << "\n"; ret->simpledeclaration = tryget_declaratornames( lexer, context); } if ( !ret->simpledeclaration && !ret->expression) throw parser::error_t( lexer, "Expecting declarator or expression"); } ret->end = lexer.GetPos(); debug0 << "get_for_loop_initstatement returning " << *ret << "\n"; return ret; } node_t* get_if_expression( lexer_t& lexer, context_t& context0) { debug_TRACE_PRETTY; context_t context( context0); context.location = context_t::EXPRESSION; lexer_mark_t lexmark( lexer); node_t* ret = NULL; if ( !ret) { ret = tryget_expression( lexer, context); if ( ret) debug0 << "get_if_expression, tryget_expression returned " << *ret << "\n"; if ( ret && !TryPeek< keyword_CLOSEROUND>( lexer)) { ret = NULL; lexmark.Backtrack(); } } if ( !ret) ret = tryget_declarator_names_internal( lexer, context, true); if ( !ret) return NULL; if ( TryPeek< keyword_CLOSEROUND>( lexer)) return ret; lexmark.Backtrack(); return NULL; } void bracket_expression_t::output( outstream_t& out) const { debug_TRACE_PRETTY; output_node( *this->open, out); output_node( *this->expression, out); output_node( *this->close, out); } void name_expression_t::output( outstream_t& out) const { debug_TRACE_PRETTY; output_node( *this->name, out); } void typename_expression_t::output( outstream_t& out) const { debug_TRACE_PRETTY; output_node( *this->type, out); } void numerical_expression_t::output( outstream_t& out) const { debug_TRACE_PRETTY; output_node( *this->number, out); } void expression_list_item_t::output( outstream_t& out) const { debug_TRACE_PRETTY; if ( this->preop) output_node( *this->preop, out); if ( this->expression) output_node( *this->expression, out); } void expression_list_t::output( outstream_t& out) const { debug_TRACE_PRETTY; for ( items_t::const_iterator it=this->items.begin(); it!=this->items.end(); ++it) { output_node( *(*it), out); } } void expression_terminator_t::output( outstream_t& out) const { debug_TRACE_PRETTY; assert( this->semicolon); assert( this->expr); output_node( *this->expr, out); output_node( *this->semicolon, out); } void for_loop_initstatement_t::output( outstream_t& out) const { debug_TRACE_PRETTY; if ( this->expression) output_node( *this->expression, out); if ( this->simpledeclaration) output_node( *this->simpledeclaration, out); } void for_loop_t::output( outstream_t& out) const { debug_TRACE_PRETTY; output_node( *this->fo, out); output_node( *this->open, out); output_node( *this->expr1, out); if ( this->expr2) output_node( *this->expr2, out); output_node( *this->semicolon2, out); if ( this->expr3) output_node( *this->expr3, out); output_node( *this->close, out); debug0 << "type of for's contents is " << typeid( *this->contents).name() << "\n"; output_node( *this->contents, out); } void ensure_parameter_names( function_parameters_t*& fnparams0) { debug_TRACE; function_parameters_t* fnparams = new function_parameters_t( *fnparams0); fnparams0 = fnparams; for ( unsigned int i=0; iparams.size(); ++i) { //std::stringstream buffer; // gcc 2.95.3 fails with internal error if this defined inside the for() loop. //buffer.clear(); // doesn't work. grr. char buffer[ 32]; sprintf( buffer, "cmm_%i", i); std::string& s = *new std::string( buffer); parser::context_t context; name_t* name = name_t::MakeName( s.c_str(), context); declarator_name_t* declname = new declarator_name_t; declname->name = name; if ( dynamic_cast< declarator_name_t*>( fnparams->params[i]->items.front()->declarator)) { declname->subtype = fnparams->params[i]->items.front()->declarator->subtype; } else { declname->subtype = fnparams->params[i]->items.front()->declarator; } fnparams->params[i]->items.front()->declarator = declname; //std::cerr << "new param name is: " << *name << "\n"; //std::cerr << "end buffer is: " << s << "\n"; } } declarator_name_t* make_function_pointer( const char* pointername, function_t* function) // would like to use 'const function_t*', but bracketdecl->subtype is a non-const pointer... Umm. { debug0 << "Making fnptr for " << *function << "\n"; debug0 << "Making fnptr for " << function->output_complete_tostring() << "\n"; assert( function->get_declarator_left()); /*outstream_t out( std::cerr); function->declarator_t::output_complete( out);*/ debug_TRACE; declarator_name_t* fnptr = new declarator_name_t; pointer_t* ptr = new pointer_t; ptr->star = new keyword_STAR( "*"); bracket_declarator_t* bracketdecl = new bracket_declarator_t; ptr->subtype = bracketdecl; bracketdecl->open = new keyword_OPENROUND( "("); bracketdecl->close = new keyword_CLOSEROUND( ")"); bracketdecl->subtype = function; lexer_t lexer( "", pointername); parser::context_t context; fnptr->name = get_name( lexer, context); fnptr->subtype = ptr; debug0 << "generated fnptr is: " << fnptr->output_complete_tostring() << "\n"; assert( fnptr->get_declarator_left()); debug0 << "generated fnpre'sdeclleft is: " << *fnptr->get_declarator_left() << "\n"; return fnptr; } }