src/verilogPreproc/verilogPreproc.cpp
//method call when `macro is found in the source code
method call when `macro is found in the source code
method call when ` macro is found in the source code
antlrcpp::Any VerilogPreproc::visitMacro_call(
		verilogPreprocParser::Macro_callContext *ctx) {
	string macro_name;
	vector<string> args;
	bool has_args = false;
	auto no_args = ctx->OTHER_MACRO_CALL_NO_ARGS();
	if (no_args) {
		macro_name = no_args->getText();
	} else {
		auto with_args = ctx->OTHER_MACRO_CALL_WITH_ARGS();
		assert(with_args);
		auto _macro_name = with_args->getText();
		size_t name_len = 1;
		for (; name_len < _macro_name.size(); name_len++) {
			auto c = _macro_name[name_len];
			if (!isalnum(c) && c != '_')
				break;
		}
		macro_name = _macro_name.substr(0, name_len);
		has_args = true;
	}
	auto m = container.defineDB.find(macro_name);
	if (m == container.defineDB.end()) {
		throw_input_caused_error(ctx, macro_name + " is not defined");
	}
	bool _has_args = has_args;
	if (m->second->requires_args()) {
		if (has_args) {
			parse_macro_args(ctx, args);
		}
	} else {
		_has_args = false;
	}
	string replacement;
	try {
		replacement = m->second->replace(args, _has_args, this, ctx);
	} catch (const ParseException &e) {
		throw_input_caused_error(ctx, e.what());
	}
	if (!m->second->requires_args() && has_args) {
		auto a = ctx->start->getStartIndex() + macro_name.size();
		auto b = ctx->stop->getStopIndex();
		auto args_str = ctx->start->getInputStream()->getText(
				misc::Interval(a, b));
		replacement += args_str;
	}
	if (container.lang >= Language::SV2005) {
		replace_substring(replacement, "``", "");
		replace_substring(replacement, "`\\`", "\\");
	}
	if (replacement.find("`", 0) != string::npos) {
		if (container.macro_call_stack.size()
				>= container.max_macro_call_stack_size) {
			throw_input_caused_error(ctx,
					std::string("Macro call stack overflow ")
							+ vector_to_string(container.macro_call_stack)
							+ ".");
		}
		container.macro_call_stack.push_back(macro_name);
		replacement = container.run_preproc_str(replacement,
				ctx->start->getLine() - 1);
		container.macro_call_stack.pop_back();
	}
	if (container.lang >= Language::SV2005) {
		unescape_string_dblquotes(replacement);
	}
	misc::Interval token = ctx->getSourceInterval();
	_rewriter.replace(token.a, token.b, replacement);
	return replacement;
}
antlrcpp :: Any VerilogPreproc :: visitMacro_call ( verilogPreprocParser :: Macro_callContext * ctx ) { string macro_name ; vector < string > args ; bool has_args = false ; auto no_args = ctx -> OTHER_MACRO_CALL_NO_ARGS ( ) ; if ( no_args ) { macro_name = no_args -> getText ( ) ; } else { auto with_args = ctx -> OTHER_MACRO_CALL_WITH_ARGS ( ) ; assert ( with_args ) ; auto _macro_name = with_args -> getText ( ) ; size_t name_len = 1 ; for ( ; name_len < _macro_name . size ( ) ; name_len ++ ) { auto c = _macro_name [ name_len ] ; if ( ! isalnum ( c ) && c != ' ' ) break ; } macro_name = _macro_name . substr ( 0 , name_len ) ; has_args = true ; } auto m = container . defineDB . find ( macro_name ) ; if ( m == container . defineDB . end ( ) ) { throw_input_caused_error ( ctx , macro_name + " " ) ; } bool _has_args = has_args ; if ( m -> second -> requires_args ( ) ) { if ( has_args ) { parse_macro_args ( ctx , args ) ; } } else { _has_args = false ; } string replacement ; try { replacement = m -> second -> replace ( args , _has_args , this , ctx ) ; } catch ( const ParseException & e ) { throw_input_caused_error ( ctx , e . what ( ) ) ; } if ( ! m -> second -> requires_args ( ) && has_args ) { auto a = ctx -> start -> getStartIndex ( ) + macro_name . size ( ) ; auto b = ctx -> stop -> getStopIndex ( ) ; auto args_str = ctx -> start -> getInputStream ( ) -> getText ( misc :: Interval ( a , b ) ) ; replacement += args_str ; } if ( container . lang >= Language :: SV2005 ) { replace_substring ( replacement , " " , " " ) ; replace_substring ( replacement , " \\ " , " \\ " ) ; } if ( replacement . find ( " " , 0 ) != string :: npos ) { if ( container . macro_call_stack . size ( ) >= container . max_macro_call_stack_size ) { throw_input_caused_error ( ctx , std :: string ( " " ) + vector_to_string ( container . macro_call_stack ) + " " ) ; } container . macro_call_stack . push_back ( macro_name ) ; replacement = container . run_preproc_str ( replacement , ctx -> start -> getLine ( ) - 1 ) ; container . macro_call_stack . pop_back ( ) ; } if ( container . lang >= Language :: SV2005 ) { unescape_string_dblquotes ( replacement ) ; } misc :: Interval token = ctx -> getSourceInterval ( ) ; _rewriter . replace ( token . a , token . b , replacement ) ; return replacement ; }
method call when `macro is found in the source code
method call when ` macro is found in the source code
// printf("@%s %s\n",__PRETTY_FUNCTION__,ctx->getText().c_str()); // macro_call: // 	OTHER_MACRO_CALL_NO_ARGS // 	| OTHER_MACRO_CALL_WITH_ARGS value? (COMMA value? )* RP // ; //test if the macro has already been defined //build the replacement string by calling the replacement method of the //macro_replace object and the provided argument of the macro. // args belongs to the code and not to macro // replace the original macro in the source code by the replacement string // we just setup