blob: 37186e0e3b927503f523c4f12fda5ce8dbf9c716 [file] [log] [blame]
%{
/*
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "odin_error.h"
#include "odin_types.h"
#include "odin_util.h"
#include "odin_globals.h"
#include "verilog_bison.h"
#include "vtr_util.h"
#include "scope_util.h"
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <string.h>
#define RECURSIVE_LIMIT 256
#define YY_USER_ACTION {my_yycolumn = current_yycolumn; current_yycolumn = yyleng;}
/* the define below helps with watching the parser go token by token */
#define UNSUPPORTED_TOKEN { delayed_error_message(PARSE_ERROR, my_yycolumn, my_yylineno, current_parse_file, "%s", "Unsuported token"); }
#define _STATE_TOP(str) { BEGIN(_state_top(str)); }
#define POP_STATE() { _pop_state(); _STATE_TOP("Popped to "); }
#define PUSH_STATE(state) { _push_state(state); _STATE_TOP("Pushed to ");}
#define CHANGE_STATE(state) { _pop_state(); _push_state(state); _STATE_TOP("Switched to "); }
struct defines_t
{
std::vector<std::string> args;
std::string body;
};
void MP();
int _state_top(const char *str);
void _pop_state();
void _push_state(int state);
void push_include(const char *file_name);
bool pop_include();
void pop_buffer_state();
void lex_string(const char * str);
bool ifdef(const char* id);
void new_define_t(const char* id);
void free_define_map();
void add_args_to_define(const char* str);
void append_to_define_body(char c);
void finalize_define();
std::string get_simple_define(const char *str);
std::string get_complex_define();
void next_define_arg();
void define_arg_push_back(char c);
void load_define(const char *str);
void initialize_defaults();
int my_yylineno = 0;
int my_yycolumn = 1;
int current_yycolumn = 1;
std::unordered_map<std::string, defines_t*> defines_map;
defines_t *current_define = NULL;
std::vector<int> current_include_stack;
std::vector<int> state_stack = { 0 };
std::vector<std::string> current_args;
std::string current_define_body;
%}
%x INCLUDE BRACKET_MATCH COMMENT MULTI_LINE_COMMENT DEFINE_BODY SKIP ELIFCONDITION NEG_CONDITION CONDITION DEFINE_REMOVAL VAR_PARSE PARSE_DEFINE DEFINE_ARGS
%option noyywrap
%option nounput
%option noinput
%option never-interactive
%option nounistd
%option nodefault
%option case-sensitive
vBIN [Bb][_]*[ZzXx0-1][ZzXx0-1_]*
vOCT [Oo][_]*[ZzXx0-7][ZzXx0-7_]*
vDEC [Dd][_]*[[:digit:]][[:digit:]_]*
vHEX [Hh][_]*[ZzXx[:xdigit:]][ZzXx[:xdigit:]_]*
vINT [[:digit:]][[:digit:]_]*
vWORD [[:alpha:]_][[:alnum:]_$]*
vSTRING ["][^"]*["]
vPUNCT [\?\:\|\^\&\<\>\-\*\/\%\(\)\{\}\[\]\~\!\;\#\,\.\@\=\+]
%%
/* preproc helpers */
<VAR_PARSE>{vWORD} { MP(); add_args_to_define(yytext); }
<VAR_PARSE>[\,] { }
<VAR_PARSE>[\)] { CHANGE_STATE(DEFINE_BODY); }
<PARSE_DEFINE>{vWORD}[\(] { MP(); new_define_t(yytext); CHANGE_STATE(VAR_PARSE);}
<PARSE_DEFINE>{vWORD} { MP(); new_define_t(yytext); CHANGE_STATE(DEFINE_BODY);}
<INITIAL>"`define" { MP(); PUSH_STATE(PARSE_DEFINE); }
<DEFINE_REMOVAL>{vWORD} { MP(); defines_map.erase(yytext); POP_STATE();}
<INITIAL>"`undef" { MP(); PUSH_STATE(DEFINE_REMOVAL); }
<CONDITION>{vWORD} { MP(); CHANGE_STATE( ((ifdef(yytext))? INITIAL: SKIP) ); }
<NEG_CONDITION>{vWORD} { MP(); CHANGE_STATE( ((ifdef(yytext))? SKIP: INITIAL) ); }
/* since the condition did not hold true, we evaluate these statement */
<SKIP>"`elsif" { MP(); CHANGE_STATE(CONDITION); }
<SKIP>"`else" { MP(); CHANGE_STATE(INITIAL);}
/* since the condition held true, we need to skip these */
<INITIAL>"`elsif" { MP(); CHANGE_STATE(SKIP); }
<INITIAL>"`else" { MP(); CHANGE_STATE(SKIP);}
/* entry point */
<INITIAL>"`ifdef" { MP(); PUSH_STATE(CONDITION);}
<INITIAL>"`ifndef" { MP(); PUSH_STATE(NEG_CONDITION);}
/* exit point */
<INITIAL,SKIP>"`endif" { MP(); POP_STATE();}
<INITIAL>"`include" { MP(); PUSH_STATE(INCLUDE); }
<INCLUDE>{vSTRING} { MP(); push_include(yytext); POP_STATE(); }
<INITIAL>"`default_nettype" { MP(); return preDEFAULT_NETTYPE;}
<INITIAL>"`resetall" { MP(); initialize_defaults();}
/* unsupported commands, we skip the rest of the line */
<INITIAL>"`timescale" { MP(); PUSH_STATE(COMMENT); }
<INITIAL>"`pragma" { MP(); PUSH_STATE(COMMENT); }
<INITIAL>"`line" { MP(); PUSH_STATE(COMMENT); }
<INITIAL>"`celldefine" { MP(); PUSH_STATE(COMMENT); }
<INITIAL>"`endcelldefine" { MP(); PUSH_STATE(COMMENT); }
<INITIAL>"`begin_keywords" { MP(); PUSH_STATE(COMMENT); }
<INITIAL>"`end_keywords" { MP(); PUSH_STATE(COMMENT); }
<INITIAL>"`nounconnected_drive" { MP(); PUSH_STATE(COMMENT); }
<INITIAL>"`unconnected_drive" { MP(); PUSH_STATE(COMMENT); }
<DEFINE_ARGS>[\)] { MP(); POP_STATE(); lex_string(get_complex_define().c_str()); }
<DEFINE_ARGS>[\,] { MP(); next_define_arg(); }
<BRACKET_MATCH>[\)] { MP(); POP_STATE(); define_arg_push_back(yytext[0]); }
<DEFINE_ARGS,BRACKET_MATCH>[\(] { MP(); PUSH_STATE(BRACKET_MATCH); define_arg_push_back(yytext[0]);}
<INITIAL>[\`]{vWORD}[\(] { MP(); load_define(yytext); PUSH_STATE(DEFINE_ARGS); }
<INITIAL>[\`]{vWORD} { MP(); lex_string(get_simple_define(yytext).c_str());}
/* Begin Scoped items */
<INITIAL>"begin" { MP(); push_scope(); return vBEGIN;}
<INITIAL>"function" { MP(); push_scope(); return vFUNCTION;}
<INITIAL>"module" { MP(); push_scope(); return vMODULE;}
<INITIAL>"macromodule" { MP(); push_scope(); return vMODULE;}
<INITIAL>"task" { MP(); push_scope(); return vTASK;}
/* End Scoped items */
<INITIAL>"end" { MP(); return vEND;}
<INITIAL>"endfunction" { MP(); return vENDFUNCTION;}
<INITIAL>"endmodule" { MP(); return vENDMODULE;}
<INITIAL>"endtask" { MP(); return vENDTASK;}
/* Keywords */
<INITIAL>"always" { MP(); return vALWAYS;}
<INITIAL>"and" { MP(); return vAND;}
<INITIAL>"assign" { MP(); return vASSIGN;}
<INITIAL>"automatic" { MP(); return vAUTOMATIC;}
<INITIAL>"case" { MP(); return vCASE;}
<INITIAL>"default" { MP(); return vDEFAULT;}
<INITIAL>"defparam" { MP(); return vDEFPARAM;}
<INITIAL>"else" { MP(); return vELSE;}
<INITIAL>"endcase" { MP(); return vENDCASE;}
<INITIAL>"endspecify" { MP(); return vENDSPECIFY;}
<INITIAL>"endgenerate" { MP(); return vENDGENERATE;}
<INITIAL>"for" { MP(); return vFOR;}
<INITIAL>"if" { MP(); return vIF;}
<INITIAL>"initial" { MP(); return vINITIAL;}
<INITIAL>"inout" { MP(); return vINOUT;}
<INITIAL>"input" { MP(); return vINPUT;}
<INITIAL>"integer" { MP(); return vINTEGER;}
<INITIAL>"generate" { MP(); return vGENERATE;}
<INITIAL>"genvar" { MP(); return vGENVAR;}
<INITIAL>"nand" { MP(); return vNAND;}
<INITIAL>"negedge" { MP(); return vNEGEDGE;}
<INITIAL>"nor" { MP(); return vNOR;}
<INITIAL>"not" { MP(); return vNOT;}
<INITIAL>"or" { MP(); return vOR;}
<INITIAL>"output" { MP(); return vOUTPUT;}
<INITIAL>"parameter" { MP(); return vPARAMETER;}
<INITIAL>"localparam" { MP(); return vLOCALPARAM;}
<INITIAL>"posedge" { MP(); return vPOSEDGE;}
<INITIAL>"signed" { MP(); return vSIGNED;}
<INITIAL>"specify" { MP(); return vSPECIFY;}
<INITIAL>"while" { MP(); return vWHILE;}
<INITIAL>"xnor" { MP(); return vXNOR;}
<INITIAL>"xor" { MP(); return vXOR;}
<INITIAL>"specparam" { MP(); return vSPECPARAM;}
/* Net types */
<INITIAL>"wire" { MP(); return netWIRE;}
<INITIAL>"tri" { MP(); return netTRI;}
<INITIAL>"tri0" { MP(); return netTRI0;}
<INITIAL>"tri1" { MP(); return netTRI1;}
<INITIAL>"wand" { MP(); return netWAND;}
<INITIAL>"wor" { MP(); return netWOR;}
<INITIAL>"triand" { MP(); return netTRIAND;}
<INITIAL>"trior" { MP(); return netTRIOR;}
<INITIAL>"trireg" { MP(); return netTRIREG;}
<INITIAL>"uwire" { MP(); return netUWIRE;}
<INITIAL>"none" { MP(); return netNONE;}
<INITIAL>"reg" { MP(); return netREG;}
/* unsupported Keywords */
<INITIAL>"buf" { UNSUPPORTED_TOKEN;}
<INITIAL>"casex" { UNSUPPORTED_TOKEN;}
<INITIAL>"casez" { UNSUPPORTED_TOKEN;}
<INITIAL>"disable" { UNSUPPORTED_TOKEN;}
<INITIAL>"edge" { UNSUPPORTED_TOKEN;}
<INITIAL>"scalared" { UNSUPPORTED_TOKEN;}
<INITIAL>"bufif0" { UNSUPPORTED_TOKEN;}
<INITIAL>"bufif1" { UNSUPPORTED_TOKEN;}
<INITIAL>"cmos" { UNSUPPORTED_TOKEN;}
<INITIAL>"deassign" { UNSUPPORTED_TOKEN;}
<INITIAL>"endprimitive" { UNSUPPORTED_TOKEN;}
<INITIAL>"endtable" { UNSUPPORTED_TOKEN;}
<INITIAL>"event" { UNSUPPORTED_TOKEN;}
<INITIAL>"force" { UNSUPPORTED_TOKEN;}
<INITIAL>"forever" { UNSUPPORTED_TOKEN;}
<INITIAL>"fork" { UNSUPPORTED_TOKEN;}
<INITIAL>"highz0" { UNSUPPORTED_TOKEN;}
<INITIAL>"highz1" { UNSUPPORTED_TOKEN;}
<INITIAL>"join" { UNSUPPORTED_TOKEN;}
<INITIAL>"large" { UNSUPPORTED_TOKEN;}
<INITIAL>"medium" { UNSUPPORTED_TOKEN;}
<INITIAL>"nmos" { UNSUPPORTED_TOKEN;}
<INITIAL>"notif0" { UNSUPPORTED_TOKEN;}
<INITIAL>"notif1" { UNSUPPORTED_TOKEN;}
<INITIAL>"pmos" { UNSUPPORTED_TOKEN;}
<INITIAL>"primitive" { UNSUPPORTED_TOKEN;}
<INITIAL>"pull0" { UNSUPPORTED_TOKEN;}
<INITIAL>"pull1" { UNSUPPORTED_TOKEN;}
<INITIAL>"pulldown" { UNSUPPORTED_TOKEN;}
<INITIAL>"pullup" { UNSUPPORTED_TOKEN;}
<INITIAL>"rcmos" { UNSUPPORTED_TOKEN;}
<INITIAL>"release" { UNSUPPORTED_TOKEN;}
<INITIAL>"repeat" { UNSUPPORTED_TOKEN;}
<INITIAL>"rnmos" { UNSUPPORTED_TOKEN;}
<INITIAL>"rpmos" { UNSUPPORTED_TOKEN;}
<INITIAL>"rtran" { UNSUPPORTED_TOKEN;}
<INITIAL>"rtranif0" { UNSUPPORTED_TOKEN;}
<INITIAL>"rtranif1" { UNSUPPORTED_TOKEN;}
<INITIAL>"small" { UNSUPPORTED_TOKEN;}
<INITIAL>"strong0" { UNSUPPORTED_TOKEN;}
<INITIAL>"strong1" { UNSUPPORTED_TOKEN;}
<INITIAL>"supply0" { UNSUPPORTED_TOKEN;}
<INITIAL>"supply1" { UNSUPPORTED_TOKEN;}
<INITIAL>"table" { UNSUPPORTED_TOKEN;}
<INITIAL>"time" { UNSUPPORTED_TOKEN;}
<INITIAL>"tran" { UNSUPPORTED_TOKEN;}
<INITIAL>"tranif0" { UNSUPPORTED_TOKEN;}
<INITIAL>"tranif1" { UNSUPPORTED_TOKEN;}
<INITIAL>"vectored" { UNSUPPORTED_TOKEN;}
<INITIAL>"wait" { UNSUPPORTED_TOKEN;}
<INITIAL>"weak0" { UNSUPPORTED_TOKEN;}
<INITIAL>"weak1" { UNSUPPORTED_TOKEN;}
/* Operators */
<INITIAL>"**" { MP(); return voPOWER;}
<INITIAL>"&&" { MP(); return voANDAND;}
<INITIAL>"||" { MP(); return voOROR;}
<INITIAL>"<=" { MP(); return voLTE;}
<INITIAL>"=>" { MP(); return voPAL;}
<INITIAL>">=" { MP(); return voGTE;}
<INITIAL>"<<" { MP(); return voSLEFT;}
<INITIAL>"<<<" { MP(); return voSLEFT;}
<INITIAL>">>" { MP(); return voSRIGHT;}
<INITIAL>">>>" { MP(); return voASRIGHT;}
<INITIAL>"==" { MP(); return voEQUAL;}
<INITIAL>"!=" { MP(); return voNOTEQUAL;}
<INITIAL>"===" { MP(); return voCASEEQUAL;}
<INITIAL>"!==" { MP(); return voCASENOTEQUAL;}
<INITIAL>"^~" { MP(); return voXNOR;}
<INITIAL>"~^" { MP(); return voXNOR;}
<INITIAL>"~&" { MP(); return voNAND;}
<INITIAL>"~|" { MP(); return voNOR;}
<INITIAL>"+:" { MP(); return vPLUS_COLON;}
<INITIAL>"-:" { MP(); return vMINUS_COLON;}
/* unsupported Operators */
<INITIAL>"&&&" { UNSUPPORTED_TOKEN;}
/* C functions */
<INITIAL>"$clog2" { MP(); return vCLOG2;}
<INITIAL>"$unsigned" { MP(); return voUNSIGNED;}
<INITIAL>"$signed" { MP(); return voSIGNED;}
<INITIAL>[\$]{vWORD} { MP(); return vCFUNC;}
/* Delay */
<INITIAL>#{vINT} { MP(); yylval.num_value = vtr::strdup(yytext+1); return vDELAY_ID; }
/* Integers */
<INITIAL>{vINT} { MP(); yylval.num_value = vtr::strdup(yytext); return vNUMBER; }
/* Strings */
<INITIAL>{vSTRING} { MP(); yylval.num_value = vtr::strdup(yytext); return vNUMBER; }
/* Numbers */
<INITIAL>[[:digit:]]*'[sS]?{vBIN} { MP(); yylval.num_value = vtr::strdup(yytext); return vNUMBER; }
<INITIAL>[[:digit:]]*'[sS]?{vHEX} { MP(); yylval.num_value = vtr::strdup(yytext); return vNUMBER; }
<INITIAL>[[:digit:]]*'[sS]?{vOCT} { MP(); yylval.num_value = vtr::strdup(yytext); return vNUMBER; }
<INITIAL>[[:digit:]]*'[sS]?{vDEC} { MP(); yylval.num_value = vtr::strdup(yytext); return vNUMBER; }
/* operands */
<INITIAL>{vWORD}(\.{vWORD})* { MP(); yylval.id_name = vtr::strdup(yytext); return vSYMBOL_ID; }
/* return operators */
<INITIAL>{vPUNCT} { MP(); return yytext[0]; }
/* general stuff */
/* single line comment */
<*>[\/][\/] {
int state = _state_top("");
if (state == DEFINE_BODY)
{
/**
* single line comments will automaticaly continue on if we
* escape the new line, to prevent issues, we stop processing the macro body
*/
finalize_define();
_pop_state();
}
if(state != COMMENT
&& state != MULTI_LINE_COMMENT)
{
PUSH_STATE(COMMENT);
}
}
/* multi line comment */
<*>[\/][\*] {
int state = _state_top("");
if(state != COMMENT
&& state != MULTI_LINE_COMMENT)
{
PUSH_STATE(MULTI_LINE_COMMENT);
}
}
<MULTI_LINE_COMMENT>[\*][\/] { POP_STATE(); }
<*>[[:blank:]]+ {
int state = _state_top("");
if(state == DEFINE_BODY)
{
append_to_define_body(' ');
}
}
<*><<EOF>> { if ( ! pop_include() ){ free_define_map(); yyterminate(); } }
/* skip escapped newline */
<*>\\\r?\n { my_yylineno++; my_yycolumn = 1; }
/* deal with new lines */
<*>\r?\n {
bool done = false;
do{
int state = _state_top("");
if(state == DEFINE_BODY)
{
finalize_define();
}
done = ( state != DEFINE_BODY && state != COMMENT );
if(!done)
{
POP_STATE();
}
}while(!done);
my_yylineno++;
my_yycolumn = 1;
}
/* catch all */
<*>. {
MP();
int state = _state_top("");
if(state == DEFINE_BODY)
{
append_to_define_body(yytext[0]);
}
else if(state == DEFINE_ARGS
|| state == BRACKET_MATCH)
{
define_arg_push_back(yytext[0]);
}
}
%%
void MP()
{
if (configuration.print_parse_tokens)
{
printf("%d %s\n", my_yylineno, yytext);
}
}
int _state_top(const char *str)
{
int state = state_stack.back();
if (configuration.print_parse_tokens && strlen(str))
{
printf("%s state: %s\n", str,
(state == INCLUDE)? "INCLUDE":
(state == COMMENT)? "COMMENT":
(state == MULTI_LINE_COMMENT)? "MULTI_LINE_COMMENT":
(state == DEFINE_BODY)? "DEFINE_BODY":
(state == SKIP)? "SKIP":
(state == ELIFCONDITION)? "ELIFCONDITION":
(state == NEG_CONDITION)? "NEG_CONDITION":
(state == CONDITION)? "CONDITION":
(state == DEFINE_REMOVAL)? "DEFINE_REMOVAL":
(state == VAR_PARSE)? "VAR_PARSE":
(state == PARSE_DEFINE)? "PARSE_DEFINE":
(state == DEFINE_ARGS)? "DEFINE_ARGS":
"INITIAL"
);
}
return state;
}
void _pop_state()
{
state_stack.pop_back();
if(state_stack.empty())
{
state_stack.push_back(INITIAL);
}
}
void _push_state(int state)
{
state_stack.push_back(state);
}
static bool has_current_parse_file()
{
return (
current_parse_file < include_file_names.size()
&& current_parse_file >= 0
);
}
void lex_string(const char * str)
{
if (configuration.print_parse_tokens)
{
printf("Processing define %s\n", str);
}
if(has_current_parse_file()
&& current_include_stack.back() == current_parse_file)
{
include_file_names[current_parse_file].second = my_yylineno;
}
/* check current depth, prevent too much macro recursion */
if(current_include_stack.size() > RECURSIVE_LIMIT)
{
error_message(PARSE_ERROR, include_file_names[current_parse_file].second, current_parse_file,
"Reached upper macro recursion limit of %d",
RECURSIVE_LIMIT);
}
else if(current_include_stack.size() > (RECURSIVE_LIMIT/2))
{
warning_message(PARSE_ERROR, include_file_names[current_parse_file].second, current_parse_file,
"Reached halfway to upper macro recursion limit of %d",
RECURSIVE_LIMIT);
}
current_include_stack.push_back(-1);
my_yylineno = 0;
YY_BUFFER_STATE cur = YY_CURRENT_BUFFER;
YY_BUFFER_STATE yybuff = yy_scan_string(str);
yy_switch_to_buffer(cur);
yypush_buffer_state(yybuff);
}
void push_include(const char *file_name)
{
printf("Adding file %s to parse list\n", file_name);
std::string tmp(file_name);
if(tmp[0] == '"')
{
tmp.erase(0,1);
}
if(tmp.back() == '"')
{
tmp.pop_back();
}
std::string current_file = "";
if(has_current_parse_file())
{
current_file = include_file_names[current_parse_file].first;
if(current_include_stack.back() == current_parse_file)
{
include_file_names[current_parse_file].second = my_yylineno;
}
}
/* we add the path from the current file */
size_t loc = current_file.find_last_of("/");
if(loc == std::string::npos)
{
current_file = tmp;
}
else
{
current_file = current_file.substr(0, loc + 1) + tmp;
}
yyin = fopen(current_file.c_str(), "r");
if(yyin == NULL)
{
printf("Unable to open %s, trying %s\n", current_file.c_str(), tmp.c_str());
current_file = tmp;
yyin = open_file(current_file.c_str(), "r");
}
my_yylineno = 0;
current_include_stack.push_back(include_file_names.size());
include_file_names.push_back({current_file,my_yylineno});
current_parse_file = current_include_stack.back();
assert_supported_file_extension(include_file_names.back().first.c_str() , my_yylineno, current_parse_file);
YY_BUFFER_STATE yybuff = yy_create_buffer( yyin, YY_BUF_SIZE );
yypush_buffer_state(yybuff);
}
bool pop_include()
{
if(has_current_parse_file())
{
if(configuration.print_parse_tokens)
{
printf("Poping file %s from parse list\n", include_file_names[current_parse_file].first.c_str());
}
if(yyin)
{
fflush(yyin);
fclose(yyin);
yyin = NULL;
}
}
if(!current_include_stack.empty())
{
current_include_stack.pop_back();
}
if(!current_include_stack.empty())
{
if(current_include_stack.back() != -1)
{
current_parse_file = current_include_stack.back();
}
}
else
{
current_parse_file = -1;
}
if(has_current_parse_file() && current_parse_file >= 0)
{
my_yylineno = include_file_names[current_parse_file].second;
if(configuration.print_parse_tokens)
{
printf("Reading file %s from line %d\n", include_file_names[current_parse_file].first.c_str(), my_yylineno);
}
}
else
{
my_yylineno = -1;
}
yypop_buffer_state();
return ( YY_CURRENT_BUFFER );
}
void initialize_defaults()
{
default_net_type = WIRE;
current_define = NULL;
free_define_map();
}
void new_define_t(const char* id)
{
std::string tmp(id);
if(tmp.back() == '(')
{
tmp.pop_back();
}
defines_t *new_define = new defines_t();
new_define->args = std::vector<std::string>();
new_define->body = "";
if(defines_map.find(tmp) != defines_map.end())
{
warning_message(PARSE_ERROR, my_yylineno, current_parse_file, "%s is redefined, overwritting its value", id);
delete defines_map[tmp];
}
defines_map[tmp] = new_define;
current_define = new_define;
}
void free_define_map()
{
for(auto kv: defines_map)
{
delete kv.second;
}
}
std::string get_simple_define(const char *str)
{
load_define(str);
return get_complex_define();
}
std::string get_complex_define()
{
if( current_args.size() != current_define->args.size())
{
error_message(PARSE_ERROR, my_yylineno, current_parse_file,
"define is being used with wrong number of arguments, Expected %ld, got %ld",
current_args.size(),
current_define->args.size());
}
for(int i=0; i<current_define->args.size(); i++)
{
std::string original_arg = current_define->args[i];
std::string replacement_arg = current_args[i];
size_t pos = current_define_body.find( original_arg, 0 );
while ( pos != std::string::npos )
{
current_define_body.erase(pos, original_arg.size());
current_define_body.insert( pos, replacement_arg );
pos += replacement_arg.size();
pos = current_define_body.find( replacement_arg, pos );
}
}
if(configuration.print_parse_tokens )
{
printf("DEFINE = %s\n", current_define_body.c_str());
}
return current_define_body;
}
void next_define_arg()
{
current_args.push_back("");
}
void define_arg_push_back(char c)
{
if(current_args.empty())
{
next_define_arg();
}
current_args.back().push_back(c);
}
void load_define(const char *str)
{
std::string tmp(str);
if(tmp[0] == '`')
{
tmp.erase(0,1);
}
if(tmp.back() == '(')
{
tmp.pop_back();
}
auto itter = defines_map.find(tmp);
if(itter == defines_map.end())
{
error_message(PARSE_ERROR, my_yylineno, current_parse_file, "%s define cannot be found", tmp.c_str());
}
current_define = itter->second;
current_define_body = current_define->body;
current_args = std::vector<std::string>();
}
void append_to_define_body(char c)
{
current_define->body.push_back(c);
}
void add_args_to_define(const char* str)
{
std::string tmp(str);
for(int i=0; i < current_define->args.size(); i++)
{
if(tmp == current_define->args[i])
{
error_message(PARSE_ERROR, my_yylineno, current_parse_file,
"%s","define has two argument with same name");
}
}
current_define->args.push_back(std::string(str));
}
void finalize_define()
{
current_define = NULL;
}
bool ifdef(const char* id)
{
return ( defines_map.find(std::string(id)) != defines_map.end() );
}