PageRenderTime 168ms CodeModel.GetById 11ms app.highlight 139ms RepoModel.GetById 1ms app.codeStats 1ms

/vrq-1.0.88/src/main.cc

#
C++ | 1464 lines | 1037 code | 87 blank | 340 comment | 268 complexity | 44fe90e53ee1fc19d5c8c0b6b44be4e6 MD5 | raw file
   1/*****************************************************************************
   2 * Copyright (C) 1997-2007, Mark Hummel
   3 * This file is part of Vrq.
   4 *
   5 * Vrq is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public
   7 * License as published by the Free Software Foundation; either
   8 * version 2 of the License, or (at your option) any later version.
   9 *
  10 * Vrq is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public
  16 * License along with this library; if not, write to the Free Software
  17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
  18 * Boston, MA  02110-1301  USA
  19 *****************************************************************************
  20 */
  21/******************************************************************************
  22 *
  23 *
  24 *	  main.cpp	 
  25 *		- simulator startup code 
  26 *
  27 *
  28 ******************************************************************************
  29 */
  30/**
  31 * \mainpage
  32 * VRQ is modular verilog parser that supports plugin tools to process 
  33 * verilog. Plugin tools are created as independent DLLs. The tools to 
  34 * be invoked are specified on the command line. Multiple tools may be 
  35 * invoke in a pipeline fashion within a single execution of vrq. A few 
  36 * plugin tools are natively compiled into vrq, others are supplied as 
  37 * separate executables. Vrq is pretty close to fully compliant with 
  38 * the verilog 2005 specification, however not all tools support all 
  39 * constructs. 
  40 *
  41 * \section history History
  42 * VRQ was written over 10 years ago as part of my design and verification 
  43 * consulting business. Over the years its been generalized to be a generic 
  44 * front end parser with plugin backend customizable tools. I've choosen to 
  45 * release it as Open Source Software to others may benefit from it as well. 
  46 * It has been used in multiple startups and Fortune 500 companies to develop 
  47 * ASICs and full custom components. In particular the \ref xprop_plugin is 
  48 * one of it's most unique features as when it is used properly it can greatly 
  49 * reduce the need for gate level simulation.
  50 *
  51 * \section further_info Further Info
  52 * - \ref quick_start
  53 * - \ref plugin_list
  54 * - \ref faq 
  55 * - \ref manpage 
  56 * - \ref plugin_info 
  57 *
  58 * \page manpage Man Page
  59 * \htmlinclude vrq.1.html
  60 *
  61 * \page faq Frequently Asked Questions 
  62 * \htmlinclude faq.html
  63 *
  64 * \page plugin_list Plugin List
  65 * - \ref dump_plugin
  66 * - \ref xprop_plugin
  67 * - sim
  68 * - builder
  69 * - coverage
  70 * - stats
  71 * - flatten
  72 * - \ref filter_plugin
  73 * 
  74 * \page quick_start Quick Start
  75 * \section switches Switches
  76 * The parser has a number of switches that control the parsing of files. 
  77 * Below is detail on a subset of the switches. For a complete list see the 
  78 * \ref manpage . 
  79 * - -y <directory> This switch may be used to specify a verilog library 
  80 *   search path for tools that require modules to be resolved.
  81 * - -v <lib_filename> This switch may be used to specify a verilog library 
  82 *   file for tools that require modules to be resolved.
  83 * - +libext+<extension> This switch may be used to specify the library 
  84 *   file suffix (used with the -y switch). Multiple extensions may be 
  85 *   specified by appending more extensions: +libext+<ext1>+<ext2>+...
  86 * - -infervectors This switch will allow the parser to infer register 
  87 *   definitions and vector wire definitions.
  88 * - -macrocheck This switch will cause the use of undefined macros to 
  89 *   be flagged as errors.
  90 * - -keeptickdefines This switch makes a best effort attempt to keep 
  91 *   tick defines and `include statements in the code (EXPERIMENTAL). `include 
  92 *   statements are keep if the include file is composed solely of pragmas,
  93 *   comments and `define statements. `variables are evaluated if their 
  94 *   definition is in the same preprocessor zone as their instantiation. 
  95 *   Command line switches are in zone by themselves. Each compilation unit
  96 *   (e.g. verilog inpug file) starts a new zone. Included files are part of the
  97 *   zone of the including file. -passthru regions start a new zone. `ifdef
  98 *   and `ifndef regions start a new zone if they are dependent upon undefined
  99 *   preprocessor variables or are dependent upon preprocessor variable 
 100 *   defined in another zone. One of the side effects of enabling this 
 101 *   switch is that `define and `include statements can only occur on statement
 102 *   boundries in the source code, otherwise a parsing error will result.
 103 * - +incdir+<directory> This switch will cause 'directory' to be searched 
 104 *   to resolve `include preprocessor directives. Multiple paths may be 
 105 *   specified by either using +incdir+ switches or by specifing multiple i
 106 *   directories: +incdir+<dir1>+<dir2>+....
 107 * - -allowmissingincludes This switch will ignore `include preprocessor 
 108 *   directives that cannot be resolved.
 109 * - +define+<name>=<val> This switch specifies `define variables on 
 110 *   the command line.
 111 * - +<name>+<val> This switch is used to specify plusargs for tools 
 112 *   that use them.
 113 * - -pragma <regexp> This switch is used to identify classes of comments 
 114 *   as pragmas. Vrq will ensure that pragmas are not move relative to the 
 115 *   code they are embedded in. Note a side effect of using pragmas is that 
 116 *   vrq only allows pragmas in very specific locations in the code. Vrq 
 117 *   uses regcomp to process the match. Please see the 'regcomp' man page 
 118 *   for the format of 'regexp'. Multiple -pragma switch may appear on the 
 119 *   command line. If no -pragma switch is specified, vrq will make all i
 120 *   // synopsys ..... and comments as pragmas.
 121 * - -passthru <name> This switch can be used to create a label to identify 
 122 *   regions of the source code that vrq should ignore and pass though 
 123 *   verbatim. These regions of code will be treated as comments and 
 124 *   `define substitution will be performed. To use the label use 
 125 *   `ifdef/`endif and `ifndef/`endif pairs to flags the regions as 
 126 *   shown below:
 127 * \code
 128 * `ifdef label
 129 *      put code here that you want to pass through
 130 * `endif
 131 *
 132 * or
 133 *
 134 * `ifndef
 135 *      put code here that you want to pass through
 136 * `endif
 137 * \endcode
 138 *
 139 * \section tool_pipelines Tool Pipelines
 140 * Vrq parses each file creating an Abstract Syntax Tree (AST) for each file. 
 141 * This vector of AST's is passed on through a filter pipeline. Each filter 
 142 * in the pipeline is specified using the -tool <toolname> switch. A filter 
 143 * always takes a vector of AST's as input and optionally outputs a vector 
 144 * of AST's. If a pipeline is specified where the final filter produces 
 145 * AST's, vrq will automatically append the 'dump' tool to the end of the 
 146 * pipeline.
 147 *
 148 * For instance if the following switches are used; -tool filter1 -tool filter2
 149 * is specified, vrq will create the following pipeline:
 150 * Parser -> filter1 -> filter2 -> dump
 151 *
 152 * Some tools are compiled in, others come with the vrq distribution and 
 153 * are compiled as DLLs placed in the plugin dir specified at vrq install 
 154 * time. The search path for plugins may be augmented by using the PLUGIN_DIR 
 155 * environment variable. ie PLUGIN_DIR=path1:path2:path3. Third parties can 
 156 * create their own filters using the vrq API. If these plugins are placed 
 157 * in the plugin search path, vrq will automatically recognize them.
 158 *
 159 * Each AST is tagged by the parser with the input file name it was 
 160 * derived from. Tools may modify these names and trees. Tools may also 
 161 * expand or contract the number of AST in the vector.
 162 */
 163
 164#include <config.h>
 165#include <stdio.h>
 166#include <string.h>
 167#include <unistd.h>
 168#include <set>
 169#include <vector>
 170#include <list>
 171#include <map>
 172//#include <dlfcn.h>
 173#include <sys/types.h>
 174#include <dirent.h>
 175#include "glue.h"
 176#include "ltdl.h"
 177#include "cobstack.h"
 178#include "csymbol.h"
 179#include "cvector.h"
 180#include "cnode.h"
 181#include "lex.h"
 182#include "main.h"
 183#include "csymtab.h"
 184#include "cmacro.h"
 185#include "cmodule.h"
 186#include "cinstance.h"
 187#include "systask.h"
 188#include "build.h"
 189
 190#ifdef BUILTIN_SIM_PLUGIN
 191#include "../plugin/sim/csim.h"
 192#endif
 193
 194/*
 195 * add tool includes here
 196 */
 197#include "cxprop.h"
 198#include "cdumpverilog.h"
 199
 200
 201map<string,CBackend*>	tools;
 202Message*		mCRMOD;
 203
 204CObstack	thePermStack( "permStack" );
 205CObstack*	permStack = &thePermStack;
 206CObstack 	theUnitStack( "unitStack" );
 207CObstack* 	unitStack = &theUnitStack;
 208CObstack 	thePluginStack( "pluginStack" );
 209CObstack* 	pluginStack = &thePluginStack;
 210CObstack 	theTokenStack( "tokenStack" );
 211CObstack* 	tokenStack = &theTokenStack;
 212/*
 213 * set default logfile to stdout
 214 */
 215FILE*		logfile = stdout;
 216
 217/*
 218 * this must be instantiated here so it will
 219 * have a valid memmgr (permMgr).
 220 */
 221list<CObstack*>	CNode::stackList;
 222
 223/*
 224 * contains current definitions for macros
 225 * this namespace is global
 226 */
 227CSymtab<CMacro> macroSymtab;
 228/*
 229 * contains the definitions for
 230 * instances, functions, named blocks, nets
 231 * and registers for the current compilation unit.
 232 */
 233CSymtab<CDecl> cuSymtab;
 234/*
 235 * top level definitions for resolving all
 236 * non-nested module, macromodule, primitive,
 237 * program and interface identifiers.
 238 */
 239CSymtab<CDecl> definitionSymtab = cuSymtab;
 240/*
 241 * List of specified tools to run
 242 */
 243list<CBackend*>	enabledTools;
 244/* 
 245 * list of pragma templates
 246 */
 247list<string> pragmas;
 248set<string>  pragmaTickDefines;
 249/*
 250 * list of plugin directorys
 251 */
 252list<string> pluginPaths;
 253
 254int		totalMem = 0;
 255const CSymbol**	fileList = NULL;	// list of files to compile
 256const CSymbol**	libSearchList = NULL;	// list of paths to search for libraries
 257const CSymbol**	libFileSearchList = NULL;	// list of library files to search
 258const CSymbol**	incSearchList = NULL;	// list of paths to search for includes
 259const CSymbol**	libExtList = NULL;	// list of library extentions
 260static char	whiteSpace[] = " \t\f\n\r";
 261INT32		argNestLevel;		// all argument parsing to nest
 262vector<const CSymbol*> aFileList;
 263vector<const CSymbol*> aLibSearchList;	
 264vector<const CSymbol*> aLibFileSearchList;	
 265vector<const CSymbol*> aIncSearchList;
 266vector<const CSymbol*> aLibExtList;
 267CNode*		codeList = NULL;
 268CSymtab<CDecl>	portSymtab;
 269CSymtab<CDecl>	frefSymtab;
 270int		errorCount = 0;
 271int		warningCount = 0;
 272int		dumpFlag = FALSE;
 273int		debugFlag = FALSE;
 274int		quietFlag = FALSE;
 275int		inferVectors = FALSE;
 276int		macrocheck   = FALSE;
 277DelayMode_t	delayMode = eTYP_DELAY;
 278const char*	outputPath = NULL;
 279const char*	outputDirectory = NULL;
 280vector<char*>	plusArgs;
 281extern int	modulesDirectlyDefined;
 282extern int	modulesIncluded;
 283int		ignoreVrqComments = 0;
 284int		verboseFlag = FALSE;
 285int		svEnable = FALSE;
 286extern int      keepMacros;
 287extern int 	keepMacroDefinitions;
 288
 289/*
 290 * error messages
 291 */
 292static Message* mILLPA = Message::RegisterWarning( NULL, 
 293		Message::eERROR, "ILLPA",
 294		"%s is an illegal command line plusarg",
 295		"<plusarg>", 0 );
 296static Message* mILLWS = Message::RegisterWarning( NULL, 
 297		Message::eERROR, "ILLWS",
 298		"%s is an illegal warning specification",
 299		"<warning switch>", 0 );
 300static Message* mILLSW = Message::RegisterWarning( NULL, 
 301		Message::eERROR, "ILLSW",
 302		"%s is an illegal command line switch",
 303		"<switch>", 0 );
 304static Message* mINAST = Message::RegisterWarning( NULL, 
 305		Message::eERROR, "INAST",
 306		"%s is not a supported tool",
 307		"<tool>", 0 );
 308
 309CDumpVerilog* 	dumpVerilog;
 310#ifdef BUILTIN_SIM_PLUGIN
 311    CSim* 	sim;	
 312#endif
 313void	ParseArguments( int argc, const char** argv );
 314
 315#define VRQ "Vrq"
 316char copyright[] = "Copyright (C) 1997-2009 Mark Hummel\n\n"
 317	     "Vrq comes with ABSOLUTELY NO WARRANTY; This is free\n"
 318	     "software, and you are welcome to redistribute it under the\n"
 319	     "terms of the GNU General Public License as published by\n"
 320	     "the Free Software Foundation; either version 2 of the License,\n"
 321	     "or (at your option) any later version. "
 322	     "\n\n";
 323
 324/*************************************************
 325	library interface routines
 326 *************************************************/
 327void shell_assert( const char* filename, int linenumber ) {
 328	fatal( NULL, "Assertion Failure -> %s[%d]\n", filename, linenumber );
 329}
 330void shell_xfree( void* p, int s ){
 331	free( p );
 332	totalMem -= s;
 333}
 334void* shell_xmalloc( int s ) {
 335	totalMem += s;
 336	return malloc(s);
 337}
 338
 339/*************************************************
 340	PrintUsage 
 341	- print command line help 
 342 *************************************************/
 343
 344void 	PrintUsage( void )
 345{
 346	INT32	i;
 347
 348	printf( "\n" );
 349	printf( "'Vrq' is a framework for creating verilog based tools.\n\n" );
 350	printf( "Usage: vrq [options] <file1> [<file2>...]\n\n" );
 351	printf( "Options:\n" );
 352	printf( " --version                  Print version\n" );
 353	printf( " --help                     This message\n" );
 354        printf( " --bindir                   Binary install path\n");
 355        printf( " --libdir                   Library install path\n");
 356        printf( " --pkglibdir                Plugin install path\n");
 357        printf( " --includedir               Include install path\n");
 358        printf( " --cflags                   Compiler flags used\n");
 359        printf( " --ldflags                  Linker flags used\n");
 360        printf( " --libs                     Libraries used\n");
 361
 362	printf( " -V                         Verbose\n" );
 363	printf( " -y <directory>             Search directory for module definitions\n" );
 364	printf( " -f <filename>              Read options from <filename>\n" );
 365	printf( " -v <lib_filename>	     Search file for module definitions\n" );
 366	printf( " -l <filename>              Set log file to <filename>\n" );
 367	printf( " -w <message>=<policy>      Set policy for warning <message> to <policy>; ignore, warning, error, info\n" );
 368	printf( " -w all=<policy>            Set policy for all warnings to <policy>; ignore, warning, error, info\n" );
 369	printf( " -wl                        List all warning messages\n" );
 370	printf( " +libext+<extension>        Specify library suffix to <extension>\n" );
 371	printf( " -sv                        Enable System Verilog support\n" );
 372	printf( " -dump                      Dump internal tree\n" );
 373	printf( " -debug                     Print debug/statistics info\n" );
 374	printf( " -quiet                     Print minimal runtime info\n" );
 375	printf( " -infervectors              Infer reg and wire vectors\n" );
 376	printf( " -keeptickdefines           Best effort attempt to keep tick defines and `include statements in code (EXPERIMENTAL)\n" );
 377	printf( " -macrocheck                Do not allow undefined macros\n" );
 378	printf( " -o <filename>              Specify output file\n" );
 379	printf( " -dir <directory>           Specify output directory\n" );
 380	printf( " -pragma <regexp>           Extended regular expression template for pragma comments\n" );
 381	printf( " -passthru <name>           Pass through ifdef blocks with label\n" );
 382	printf( " +incdir+<directory>        Specify include search path\n" );
 383	printf( " +define+<name>=<value>     Define `define\n" );
 384	printf( " +<name>+<value>            Define plusargs\n" );
 385    	map<string,CBackend*>::iterator ptr;
 386	for( ptr = tools.begin(); ptr != tools.end(); ++ptr ) {
 387	    if( ptr->second->HideTool() ) {
 388		continue;
 389	    }
 390	    printf( " -tool %-20s %s\n", 
 391				(*ptr).second->GetToolName(),
 392				(*ptr).second->GetToolDescription() );
 393	} 
 394	for( ptr = tools.begin(); ptr != tools.end(); ++ptr ) {
 395	    if( ptr->second->HideTool() ) {
 396		continue;
 397	    }
 398	    list<string>& switches = ptr->second->GetSwitches();
 399	    if( switches.size() == 0 ) {
 400		continue;
 401	    }
 402	    printf( "\n* '%s' Options\n", (*ptr).second->GetToolName() );
 403	    list<string>::iterator swPtr;
 404	    for( swPtr = switches.begin(); swPtr != switches.end(); ++swPtr ) {
 405	        printf( " %-26s %s\n", 
 406				swPtr->c_str(),				
 407				(*ptr).second->GetSwitchDescription(swPtr->c_str()) );
 408	    }
 409	} 
 410	printf( "\n" );
 411	printf( "Report bugs at <http://sourceforge.net/projects/vrq>\n" );
 412}
 413
 414/*************************************************
 415 	VrqVersionString
 416 ************************************************/
 417static const char* vrqVersion = VERSION;
 418const char* VrqVersionString()
 419{
 420   return vrqVersion;
 421}
 422
 423/*************************************************
 424	GetPluginPaths
 425	- retrieve list of plugin location paths
 426 *************************************************/
 427
 428void GetPluginPaths( list<string>& paths )
 429{
 430    paths = pluginPaths;
 431}
 432
 433/*************************************************
 434	GetPlusArgs 
 435	- retrieve plus arg list from command line
 436	  args matching prefix
 437 *************************************************/
 438
 439void GetPlusArgs( const char* prefix, list<string>& args )
 440{
 441	args.erase( args.begin(), args.end() );
 442	vector<char*>::iterator ptr;
 443	for( ptr = plusArgs.begin(); ptr != plusArgs.end(); ++ptr ) {
 444		int len = strlen( prefix );
 445		if( !strncmp( *ptr, prefix, len ) ) {
 446			args.push_back(*ptr+len);
 447		}
 448	}
 449}
 450
 451/*************************************************
 452	GetPlusArg 
 453	- retrieve plus arg from command line matching
 454	  prefix
 455 *************************************************/
 456
 457char* GetPlusArg( const char* prefix )
 458{
 459	vector<char*>::iterator ptr;
 460
 461	for( ptr = plusArgs.begin(); ptr != plusArgs.end(); ++ptr ) {
 462		int len = strlen( prefix );
 463		if( !strncmp( *ptr, prefix, len ) ) {
 464			return (*ptr+len);
 465		}
 466	}
 467	return NULL;
 468}
 469
 470/*************************************************
 471	AddPlusArg 
 472	- add plus arg to list 
 473 *************************************************/
 474
 475void AddPlusArg( const char* s )
 476{
 477	plusArgs.push_back(strdup(s+1));
 478}
 479
 480/*************************************************
 481	PlusArgMatch
 482	- return TRUE if plus arg matches string
 483 *************************************************/
 484int 	PlusArgMatch( const char* s1, const char* s2 )
 485{
 486    int   l1 = strlen( s1 );
 487    int   l2 = strlen( s2 );
 488    const char* p1 = strpbrk( s1, "+=" );
 489    if( p1 ) {
 490        l1 = p1 - s1;
 491    }
 492    const char* p2 = strpbrk( s2, "+=" );
 493    if( p2 ) {
 494        l2 = p2 - s2;
 495    }
 496    if( l1 == l2  && !strncmp(s1,s2,l1) ) {
 497	return TRUE;
 498    }
 499    return FALSE;
 500}
 501
 502/*************************************************
 503	ValidatePlusArgs
 504	- validate all plus args
 505 *************************************************/
 506
 507void 	ValidatePlusArgs()
 508{
 509    vector<char*>::iterator paPtr;
 510    for( paPtr = plusArgs.begin(); paPtr != plusArgs.end(); ++paPtr ) {
 511        list<CBackend*>::iterator ptr;
 512	if( PlusArgMatch( *paPtr, "define" ) ) {
 513	     goto FOUND;
 514	}
 515	if( PlusArgMatch( *paPtr, "incdir" ) ) {
 516	     goto FOUND;
 517	}
 518	if( PlusArgMatch( *paPtr, "libext" ) ) {
 519	     goto FOUND;
 520	}
 521	if( PlusArgMatch( *paPtr, "xprop-allow-casex" ) ) {
 522	     goto FOUND;
 523	}
 524	for( list<string>::iterator sPtr = dumpVerilog->GetSwitches().begin(); 
 525		 sPtr != dumpVerilog->GetSwitches().end(); ++sPtr ) {
 526	    if( PlusArgMatch( *paPtr, &sPtr->c_str()[1] ) ) {
 527	        goto FOUND;
 528	    }
 529	}
 530        for( ptr = enabledTools.begin(); ptr != enabledTools.end(); ++ptr ) {
 531	    if( (*ptr)->AcceptAllPlusArgs() ) {
 532		goto FOUND;
 533	    }
 534	    list<string>::iterator sPtr;
 535	    for( sPtr = (*ptr)->GetSwitches().begin(); 
 536		 sPtr != (*ptr)->GetSwitches().end(); ++sPtr ) {
 537		if( PlusArgMatch( *paPtr, &sPtr->c_str()[1] ) ) {
 538		    goto FOUND;
 539		}
 540	    }
 541	}
 542        message( NULL, mILLPA, *paPtr );
 543	if( errorCount ) {
 544            PrintUsage();
 545            exit(1);
 546	}
 547FOUND:
 548	continue;
 549    }
 550}
 551
 552/*************************************************
 553	DumpWarningList
 554	- output a list of all possible warnings
 555 *************************************************/
 556
 557void DumpWarningList()
 558{
 559    list<Message*>& warnings = Message::MessageList();
 560    list<Message*>::iterator ptr;
 561    printf( "List of warning messages:\n" );
 562    for( ptr = warnings.begin(); ptr != warnings.end(); ++ptr ) {
 563	Message* message = *ptr;
 564	const char* policy;
 565	switch( message->Action() ) {
 566	case Message::eINFO:
 567	    policy = "info";
 568	    break;
 569	case Message::eIGNORE:
 570	    policy = "ignore";
 571	    break;
 572	case Message::eERROR:
 573	    policy = "error";
 574	    break;
 575	case Message::eWARNING:
 576	    policy = "warning";
 577	    break;
 578	default:
 579	    MASSERT( FALSE );
 580	}
 581	printf( "%s[%s]: %s\n", message->Abbreviation(), 
 582		policy, message->HelpText() );
 583    }
 584    exit(0);
 585}
 586
 587/*************************************************
 588	ParseWarningSwitch 
 589	- handle switch to modify warning policy
 590 *************************************************/
 591
 592void ParseWarningSwitch( const char* s )
 593{
 594    string abbrev = s;
 595    string policy;
 596    const char* ptr;
 597
 598    ptr = strchr( s, '=' );
 599    if( ptr ) {
 600	policy = ptr+1;
 601	abbrev = abbrev.substr(0, ptr-s);
 602	Message::Action_t action;
 603
 604	if( !policy.compare( "ignore" ) ) {
 605	    action =  Message::eIGNORE;
 606	} else if( !policy.compare( "info" ) ) {
 607	    action = Message::eINFO;
 608	} else if( !policy.compare( "error" ) ) {
 609	    action = Message::eERROR;
 610	} else if( !policy.compare( "warning" ) ) {
 611	    action =  Message::eWARNING;
 612	} else {
 613	    error( (Coord_t*)NULL, "illegal warning policy '%s'", policy.c_str() );    
 614	    goto ERROR;
 615	}
 616
 617	if( !abbrev.compare( "all" ) ) {
 618	    list<Message*>::iterator ptr;
 619	    for( ptr = Message::MessageList().begin();
 620		 ptr != Message::MessageList().end(); ++ ptr ) {
 621		if( (*ptr)->Locked() ) {
 622		    continue;
 623		}
 624		(*ptr)->Action( action );
 625	    }
 626	    return;
 627	}
 628
 629	Message* message = Message::Find( abbrev.c_str() );
 630	if( !message ) {
 631	    error( (Coord_t*)NULL, "unknown warning message '%s'", 
 632							abbrev.c_str() );    
 633	    goto ERROR;
 634	}
 635	if( message->Locked() ) {
 636	    error( (Coord_t*)NULL, "message policy for '%s' cannot be changed",
 637							 abbrev.c_str() );    
 638	    goto ERROR;
 639	}
 640	message->Action( action );
 641	return;
 642    } 
 643    message( NULL, mILLWS, s );
 644    if( !errorCount ) {
 645	return;
 646    }
 647    PrintUsage();
 648ERROR:
 649    exit(1);
 650}
 651
 652/*************************************************
 653	ReadArgumentFile 
 654	- read command line argument file
 655 *************************************************/
 656void ReadArgumentFile( const char* filename )
 657{
 658	int		newArgc;
 659	const char**  	newArgv;
 660	const CSymbol**	newArgvSymbol;
 661	vector<const CSymbol*> argList;
 662	FILE* fin = fopen( filename, "r" );
 663	if( fin == NULL ) {
 664		error( (Coord_t*)NULL, "Couldn't open file '%s'", filename );
 665		exit( 2 );
 666	}
 667	int strip = TRUE;
 668	newArgc = 1;
 669	argList.push_back( CSymbol::Lookup( "dummy" ) );
 670	while( TRUE ) {
 671		int c = fgetc( fin );
 672		int marker = (strchr( whiteSpace, c ) || c == EOF); 
 673		if( c == '/' ) {	
 674		    int c1 = fgetc( fin );
 675		    if( c1 == '/' ) {
 676			do {
 677			    c1 = fgetc( fin );
 678			} while( c1 != EOF && c1 != '\n' && c1 != '\r' );
 679		    	marker = TRUE;
 680		    } else if( c1 == '*' ) {
 681			while( 1 ) {
 682			    c1 = fgetc( fin );
 683			    if( c1 == EOF ) {
 684				break;
 685			    }
 686			    if( c1 != '*' ) {
 687				continue;
 688			    }
 689			    c1 = fgetc( fin );
 690			    if( c1 == EOF ) {
 691				break;
 692			    }
 693			    if( c1 != '/' ) {
 694				continue;
 695			    }
 696			    break;
 697			} 
 698			marker = TRUE;
 699		    } else {
 700			ungetc( c1, fin );
 701		    }
 702		}
 703		int done = (c == EOF);
 704		if( marker || done ) { 
 705			if( strip ) {
 706				if( done ) {
 707				    break;
 708				} else {
 709				    continue;
 710				}
 711			}
 712			c = 0;
 713			strip = TRUE;
 714			permStack->Grow( &c, 1 );
 715			const CSymbol* sym = CSymbol::Lookup( (char*) permStack->Finish() );
 716			argList.push_back( sym );
 717			newArgc++;
 718		} else {
 719			strip = FALSE;
 720			permStack->Grow( &c, 1 );
 721		}
 722		if( done ) {
 723			break;
 724		}
 725	}
 726	newArgvSymbol = Finalize( permStack, argList );
 727	newArgv = (const char**)newArgvSymbol;
 728	fclose( fin );
 729	for( int j = 0; newArgvSymbol[j]; j++ ) {
 730		newArgv[j] = newArgvSymbol[j]->GetName();	
 731	} 
 732	ParseArguments( newArgc, newArgv );
 733}
 734
 735/*************************************************
 736	ParseArguments 
 737	- parse command line arguments
 738 *************************************************/
 739
 740void	ParseArguments( int argc, const char** argv ) 
 741{
 742	INT32		i;
 743	INT32		j;
 744	int		c;
 745	FILE*		fin;
 746
 747	argNestLevel++;
 748
 749	for( i = 1; i < argc; i++ ) {
 750		switch( argv[i][0] ) {
 751		case '-':
 752			if( !strcmp( &argv[i][1], "dump" ) ) {
 753				dumpFlag = TRUE;
 754			} else if( !strcmp( &argv[i][1], "sv" ) ) {
 755				svEnable = TRUE;
 756			} else if( !strcmp( &argv[i][1], "-version" ) ) {
 757        			printf("%s %s, \n\n", VRQ, VERSION );
 758        			printf( copyright );
 759				printf( "\nWritten by Mark Hummel\n" );
 760				exit(0);
 761			} else if( !strcmp( &argv[i][1], "-help" ) ) {
 762				PrintUsage();
 763				exit(0);
 764			} else if (!strcmp( &argv[i][1], "-bindir" ) ) {
 765				printf( "%s\n", BINDIR );
 766				exit(0);
 767			} else if (!strcmp( &argv[i][1], "-libdir" ) ) {
 768				printf( "%s\n", LIBDIR );
 769				exit(0);
 770			} else if (!strcmp( &argv[i][1], "-includedir" ) ) {
 771				printf( "%s\n", INCLUDEDIR );
 772				exit(0);
 773			} else if (!strcmp( &argv[i][1], "-pkglibdir" ) ) {
 774				printf( "%s\n", PKGLIBDIR );
 775				exit(0);
 776			} else if (!strcmp( &argv[i][1], "-cflags" ) ) {
 777				printf( "%s\n", CFLAGS );
 778				exit(0);
 779			} else if (!strcmp( &argv[i][1], "-ldflags" ) ) {
 780				printf( "%s\n", LDFLAGS );
 781				exit(0);
 782			} else if (!strcmp( &argv[i][1], "-libs" ) ) {
 783				printf( "%s\n", LIBS );
 784				exit(0);
 785			} else if( !strcmp( &argv[i][1], "macrocheck" ) ) {
 786				macrocheck = TRUE;
 787			} else if( !strcmp( &argv[i][1], "infervectors" ) ) {
 788				inferVectors = TRUE;
 789			} else if( !strcmp( &argv[i][1], "keeptickdefines" ) ) {
 790				keepMacros = TRUE;
 791				keepMacroDefinitions = TRUE;
 792			} else if( !strcmp( &argv[i][1], "debug" ) ) {
 793				debugFlag = TRUE;
 794			} else if( !strcmp( &argv[i][1], "quiet" ) ) {
 795				quietFlag = TRUE;
 796			} else if( !strcmp( &argv[i][1], "V" ) ) {
 797				verboseFlag = TRUE;
 798			} else if( !strcmp( &argv[i][1], "y" ) ) {
 799				aLibSearchList.push_back( CSymbol::Lookup( argv[i+1] ) );
 800				i++;
 801			} else if( !strcmp( &argv[i][1], "f" ) ) {
 802				ReadArgumentFile( argv[i+1] );
 803				i++;
 804			} else if( !strcmp( &argv[i][1], "w" ) ) {
 805				ParseWarningSwitch( argv[i+1] );
 806				i++;
 807			} else if( !strcmp( &argv[i][1], "wl" ) ) {
 808				DumpWarningList();
 809			} else if( !strcmp( &argv[i][1], "v" ) ) {
 810				aLibFileSearchList.push_back( CSymbol::Lookup( argv[i+1] ) );
 811				i++;
 812			} else if( !strcmp( &argv[i][1], "o" ) ) {
 813				outputPath = argv[i+1];
 814				i++;
 815			} else if( !strcmp( &argv[i][1], "dir" ) ) {
 816				outputDirectory = argv[i+1];
 817				i++;
 818			} else if( !strcmp( &argv[i][1], "pragma" ) ) {
 819				pragmas.push_back( argv[i+1] );
 820				i++;
 821			} else if( !strcmp( &argv[i][1], "passthru" ) ) {
 822				pragmaTickDefines.insert( argv[i+1] );
 823				i++;
 824			} else if( !strcmp( &argv[i][1], 
 825						"allowmissingincludes" ) ) {
 826				ParseWarningSwitch( "vrq-COIDF=ignore" );
 827				warning( (Coord_t*)NULL, "switch '%s' is depreciated and will be removed in a future release", argv[i] );
 828			} else if( !strcmp( &argv[i][1], "l" ) ) {
 829				logfile = fopen( argv[i+1], "w" );
 830				if( logfile == NULL ) {
 831					logfile = stdout;
 832					error( (Coord_t*)NULL, "Couldn't open logfile '%s'", argv[i+1] );
 833				}
 834				i++;
 835			} else if( !strcmp( &argv[i][1], "tool" ) ) {
 836				INT32	j;
 837                		map<string,CBackend*>::iterator ptr;
 838				for( ptr = tools.begin(); ptr != tools.end(); ++ptr ) {
 839					if( !strcmp( (*ptr).second->GetToolName(), argv[i+1] ) ) {
 840						enabledTools.push_back( (*ptr).second );
 841						i++;
 842						break;
 843					}
 844				}
 845				if( ptr == tools.end() ) {
 846                               		message( NULL, mINAST, argv[i+1] );
 847					if( errorCount ) {
 848					    PrintUsage();
 849					    exit(1);
 850					}
 851				}
 852					
 853			} else {	
 854                               message( NULL, mILLSW, argv[i] );
 855	                       if( errorCount ) {
 856                                   PrintUsage();
 857                                   exit(1);
 858	                       }
 859			}
 860			break;
 861		case '+':
 862			AddPlusArg( argv[i] );
 863			if( !strncmp( argv[i], "+incdir", 7 ) ) {
 864				const char* ptr = &argv[i][7];
 865				const char* ptr1;
 866				char	c;
 867
 868				while( ptr && *ptr == '+' ) {
 869					ptr++;
 870					ptr1 = strchr( ptr, '+' );
 871					if( ptr1 == NULL ) {
 872						ptr1 = ptr + strlen(ptr);
 873						if( ptr1 == ptr ) {
 874							break;
 875						}
 876					} 
 877					permStack->Grow( ptr, ptr1-ptr );
 878					c = 0;
 879					permStack->Grow( &c, 1 );
 880					const CSymbol* sym = CSymbol::Lookup( (char*)permStack->Finish() );
 881					aIncSearchList.push_back( sym );
 882					ptr = ptr1;
 883				}
 884			} 
 885			if( !strncmp( argv[i], "+define", 7 ) ) {
 886				const char*	ptr = &argv[i][7];
 887				const char* 	ptr1;
 888				const char*   ptr2;
 889				const char*   ptr3;
 890				char*	key;
 891				char*   value;
 892
 893				while( ptr && *ptr == '+' ) {
 894					ptr++;
 895					ptr3 = strchr( ptr, '+' );
 896					if( ptr3 == NULL ) {
 897						ptr3 = ptr + strlen(ptr);
 898						if( ptr3 == ptr ) {
 899							break;
 900						}
 901					} 
 902					ptr1 = strchr( ptr, '=' );
 903					if( !ptr1 ) {
 904					    ptr1 = ptr3;
 905					    ptr2 = ptr3;
 906					} else if( ptr1 > ptr3 ) {
 907					    ptr1 = ptr3;
 908					    ptr2 = ptr3;
 909					} else {
 910					    ptr2 = ptr1+1;
 911					}
 912					permStack->Grow( ptr, ptr1-ptr );
 913					c = 0;
 914					permStack->Grow( &c, 1 );
 915					key = (char*)permStack->Finish();
 916					permStack->Grow( ptr2, ptr3-ptr2 );
 917					c = 0;
 918					permStack->Grow( &c, 1 );
 919					value = (char*)permStack->Finish();
 920					CMacro* macro;
 921					CSymbol* symbol;
 922					macro = CMacro::LookupMacro( key ); 
 923					if( macro == NULL ) {
 924					    symbol = CSymbol::Lookup( key ); 	
 925					    Coord_t  loc = { 0, "" };
 926					    macro  = new(permStack) CMacro( symbol, &loc );
 927					} else {
 928					    Coord_t  loc = { 0, "" };
 929					    macro->SetCoord( &loc );
 930					}
 931					macro->SetComplex(FALSE);
 932					macro->SetDefined(TRUE);
 933					macro->SetBody( value );
 934					macro->SetZone( 0 );
 935					ptr = ptr3;
 936				}
 937			} 
 938			if( !strncmp( argv[i], "+libext", 7 ) ) {
 939				const char*	ptr = &argv[i][7];
 940				const char* 	ptr1;
 941				char	c;
 942
 943				while( ptr && *ptr == '+' ) {
 944					ptr++;
 945					ptr1 = strchr( ptr, '+' );
 946					if( ptr1 == NULL ) {
 947						ptr1 = ptr + strlen(ptr);
 948						if( ptr1 == ptr ) {
 949							break;
 950						}
 951					} 
 952					permStack->Grow( ptr, ptr1-ptr );
 953					c = 0;
 954					permStack->Grow( &c, 1 );
 955					const CSymbol* sym = CSymbol::Lookup( (char*) permStack->Finish() );
 956					aLibExtList.push_back( sym );
 957					ptr = ptr1;
 958				}
 959			} 
 960			if( !strncmp( argv[i], "+xprop-allow-casex", 18 ) ) {
 961				ParseWarningSwitch( "xprop-CCBMS=ignore" );
 962			}
 963			break;
 964		default:
 965			aFileList.push_back( CSymbol::Lookup( argv[i] ) );
 966			break;
 967		}
 968	}
 969	argNestLevel--;
 970
 971	if( argNestLevel == 0 ) {
 972		libSearchList   = Finalize( permStack, aLibSearchList );
 973		libFileSearchList = Finalize( permStack, aLibFileSearchList );
 974		fileList        = Finalize( permStack, aFileList );
 975		incSearchList   = Finalize( permStack, aIncSearchList );
 976		libExtList      = Finalize( permStack, aLibExtList );
 977	}
 978	ValidatePlusArgs();
 979}
 980/************************************************
 981	Load
 982	- load and compile a file, 
 983	  return a parse tree
 984*************************************************/
 985
 986set<string> loadedFiles;
 987CNode*  Load( const char* filename, int direct, int included ) 
 988{
 989	if( loadedFiles.find(filename) != loadedFiles.end() ) {
 990	   return NULL;
 991	} 
 992	loadedFiles.insert(filename);
 993	MASSERT( codeList == NULL );
 994	CNode* code;
 995	modulesDirectlyDefined = direct;
 996	modulesIncluded = included;
 997	int success = lex_openFile( strdup(filename) );
 998	if( success ) {
 999	    prog_parse();
1000	}
1001	code = codeList;
1002	codeList = NULL;
1003	tokenStack->Free(NULL);
1004	return code;
1005}
1006/*************************************************
1007 	_Resolve
1008	- attempt of search of module in a library
1009	  returns code for loaded module, NULL if
1010	  not found
1011*************************************************/
1012
1013static CNode* _Resolve( CModule* module, int reportError ) 
1014{
1015	INT32	i;
1016	INT32	j;
1017	
1018	MASSERT( !module->IsDefined() || !module->ModuleIncluded() );
1019	if( module->IsDefined() ) {
1020	    module->ModuleIncluded(TRUE);
1021	    return cMODULE_DEF(module);
1022	}
1023	for( i = 0; libSearchList[i]; i++ ) {
1024		for( j = 0; libExtList[j] || j == 0; j++ ) {
1025			string	path = libSearchList[i]->GetName();
1026			path += PATH_SEPARATOR;	
1027			path += module->GetName();
1028			if( libExtList[j] ) {
1029				path += libExtList[j]->GetName();
1030			}
1031			if( access( path.c_str(), R_OK ) != 0 ) {
1032				continue;
1033			}
1034			CNode* code = Load( path.c_str(), FALSE, FALSE );
1035			if( module->IsDefined() && 
1036			    !module->ModuleIncluded() ) {
1037				if( !quietFlag ) {
1038				    logprintf( "Loaded '%s' from library '%s'\n",
1039					module->GetName(), path.c_str() );
1040				}
1041				module->ModuleIncluded( TRUE );
1042				return cMODULE_DEF(module);
1043			}
1044		}
1045	}
1046	for( i = 0; libFileSearchList[i]; i++ ) {
1047		const char* path = libFileSearchList[i]->GetName();
1048		if( access( path, R_OK ) != 0 ) {
1049			continue;
1050		}
1051		CNode* code = Load( path, FALSE, FALSE );
1052		if( module->IsDefined() && !module->ModuleIncluded() ) {
1053			if( !quietFlag ) {
1054			    logprintf( "Loaded '%s' from library '%s'\n",
1055					module->GetName(), path );
1056			}
1057			module->ModuleIncluded( TRUE );
1058			return cMODULE_DEF(module);
1059		}
1060	}
1061
1062	if( reportError ) {
1063	     message( module->GetCoord(), mCRMOD, module->GetName() );
1064	}
1065	return NULL;
1066}
1067
1068/************************************************
1069        ResolveModuleList
1070        - attempt to resolve all referenced modules
1071	  return code for resolved modules
1072 ************************************************/
1073
1074static CNode* ResolveModuleList( CBackend* tool, CNode* n, int reportError )
1075{
1076	CNode* result = NULL;
1077        if( n == NULL ) {
1078                return result;
1079        }
1080        switch( n->GetOp() ) {
1081        case eLIST:
1082                result = ResolveModuleList( tool, 
1083					n->Arg<CNode*>(0), reportError );
1084                result = cLINK( ResolveModuleList( tool, 
1085					n->Arg<CNode*>(1), reportError ), 
1086				result );
1087                break;
1088        case eMODULE_DEF:
1089                {
1090                        CModule* m = n->Arg<CModule*>(0);
1091                        vector<CInstance*>& inst = *m->GetInstanceList();
1092                        vector<CInstance*>::iterator p;
1093                        for( p = inst.begin(); p != inst.end(); ++p ) {
1094				if( !tool->ResolveInstance( m, *p ) ) {
1095				    continue;
1096				}
1097                                CModule* def = (*p)->GetDefinition();
1098				if( !def->IsDefined() || 
1099				    !def->ModuleIncluded() ) {
1100				    result = cLINK( result, 
1101					_Resolve( def, reportError ) );
1102				}
1103                        }
1104                }
1105                break;
1106        case ePRAGMA:
1107        case eCOMMENT:
1108	case eVRQ:
1109                break;
1110        default:
1111                MASSERT( FALSE );
1112        }
1113        return result;
1114}
1115
1116/************************************************
1117        ModulesResolved
1118        - returns TRUE if all modules are resolved
1119 ************************************************/
1120
1121static int ModulesResolved( CBackend* tool, CNode* n )
1122{
1123	int result = TRUE;
1124        if( n == NULL ) {
1125                return result;
1126        }
1127        switch( n->GetOp() ) {
1128        case eLIST:
1129                result &= ModulesResolved( tool, n->Arg<CNode*>(0) );
1130                result &= ModulesResolved( tool, n->Arg<CNode*>(1) );
1131                break;
1132        case eMODULE_DEF:
1133                {
1134                        CModule* m = n->Arg<CModule*>(0);
1135                        vector<CInstance*>& inst = *m->GetInstanceList();
1136                        vector<CInstance*>::iterator p;
1137                        for( p = inst.begin(); p != inst.end(); ++p ) {
1138				if( !tool->ResolveInstance( m, *p ) ) {
1139				    continue;
1140				}
1141                                CModule* def = (*p)->GetDefinition();
1142				if( !def->IsDefined() || 
1143			            !def->ModuleIncluded() ) {
1144				   	return FALSE;
1145				}
1146                        }
1147                }
1148                break;
1149        case ePRAGMA:
1150        case eCOMMENT:
1151	case eVRQ:
1152	case eATTRIBUTE:
1153                break;
1154        default:
1155                MASSERT( FALSE );
1156        }
1157	return result;
1158}
1159
1160/*************************************************
1161	LoadTools
1162	- load available tools
1163 *************************************************/
1164static set<lt_dlhandle> toolHandles;
1165void LoadTools()
1166{
1167   CBackend* tool;
1168    
1169   /*
1170    * add vrq specific lib directory to search list
1171    */
1172   char* pld = getenv("PLUGIN_DIR");
1173   if( pld ) {
1174       char* ptr;
1175       ptr = strtok( strdup(pld), ":" );
1176       while( ptr != NULL ) {
1177            pluginPaths.push_back( ptr );
1178       	    ptr = strtok( NULL, ":" );
1179       }
1180   } else { 
1181       pluginPaths.push_back( PKGLIBDIR );
1182   }
1183
1184   /*
1185    * create built-in plugins
1186    */
1187   dumpVerilog = new CDumpVerilog();
1188   tools[dumpVerilog->GetToolName()] = dumpVerilog;
1189   tool = new CXProp();
1190   tools[tool->GetToolName()] = tool;
1191
1192#ifdef BUILTIN_SIM_PLUGIN
1193   sim = new CSim();
1194   tools[sim->GetToolName()] = sim;
1195#endif
1196
1197    
1198    int errors = lt_dlinit();
1199    if( errors ) {
1200	fprintf( stderr, "%s\n", lt_dlerror() );
1201	return;
1202    }
1203    list<string>::iterator pluginPath;
1204    for( pluginPath = pluginPaths.begin(); pluginPath != pluginPaths.end();
1205							++pluginPath ) {
1206        DIR* dir;
1207        dir = opendir(pluginPath->c_str());
1208        if( dir ) {
1209            while(1) {
1210       	        struct dirent* entry = readdir( dir );
1211        	if( !entry ) {
1212        	    break;
1213                }
1214                string path;
1215                path = *pluginPath;
1216                path += "/";
1217                path += entry->d_name;
1218                lt_dlhandle handle = lt_dlopen( path.c_str() );
1219                if( !handle ) {
1220                    continue;
1221                }
1222                CBackend* (*sym)() = (CBackend*(*)())lt_dlsym( handle, 
1223            					"CreateToolInstance" );
1224                if( !sym ) {
1225		    lt_dlclose( handle );
1226            	    continue;
1227                }	
1228		/*
1229		 * don't reinitialize tool twice. This can happen
1230		 * because both *.la and *.so files are installed 
1231		 * in the plugin dir
1232		 */
1233		if( toolHandles.count( handle ) ) {
1234		    continue;
1235		}
1236                CBackend* t = (*sym)();
1237		if( !t ) {
1238		    continue;	
1239	 	}
1240                tools[t->GetToolName()] = t;		
1241		toolHandles.insert( handle );
1242            }
1243            closedir( dir );
1244        }
1245    }
1246}
1247
1248/*************************************************
1249 	initial entry point
1250 *************************************************/
1251
1252static void DumpCode( FILE* f, CNode* n )
1253{
1254	switch( n->GetOp() ) {
1255	case eLIST:
1256		if( n->Arg<CNode*>(0) )  DumpCode( f, n->Arg<CNode*>(0) );
1257		if( n->Arg<CNode*>(1) ) DumpCode( f, n->Arg<CNode*>(1) );
1258		break;
1259	case eMODULE_DEF:
1260		n->Arg<CModule*>(0)->Dump( f );
1261		break;
1262	case eCOMMENT:
1263	case eVRQ:
1264		break;
1265	default:
1266		fprintf( f, "unknown object or type %d\n", n->GetOp() );
1267	}
1268}
1269
1270
1271// #define DEFINE_TEST_HARNESS
1272// #include "cnode_def.h"
1273// #undef DEFINE_TEST_HARNESS
1274
1275int	main( int argc, char** argv )
1276{
1277	INT32	  i;
1278	INT32	  j;
1279	INT32	  pass;
1280	CBackend* tool;
1281
1282
1283//	CNodeTestHarness();
1284	/*
1285  	 * error messages
1286  	 */
1287	mCRMOD = Message::RegisterWarning( NULL, Message::eERROR,
1288		"CRMOD", "cannot resolve module %s" );
1289	
1290	/*
1291	 * load tools
1292	 */
1293	LoadTools();
1294
1295	/*
1296	 * initialize global structures
1297	 */
1298	CSymbol::SetObstack( permStack );
1299	Systask::Initialize();
1300
1301	/*
1302	 * parse command line arguments
1303	 */
1304
1305	argNestLevel = 0;
1306	ParseArguments( argc, const_cast<const char**>(argv) );
1307
1308	if( debugFlag ) {
1309	    CObstack::OnExitDumpStats();
1310	}
1311
1312	/*
1313 	 * activate selected tools
1314 	 */
1315        list<CBackend*>::iterator ptr;
1316	for( ptr = enabledTools.begin(); ptr != enabledTools.end(); ++ptr ) {
1317	    (*ptr)->Activate();
1318	    ignoreVrqComments |= (*ptr)->IgnoreVrqComments();
1319	}
1320
1321	/*
1322	 * print copyright banner
1323	 */
1324	if( !quietFlag ) {
1325	    logprintf( "\n%s version %s, \n", VRQ, VERSION );
1326	    logprintf( copyright );
1327	}
1328
1329	/*
1330	 * intialize subsystems
1331	 */
1332
1333	lex_init();
1334	parse_init();
1335
1336	/*
1337	 * parse each file and hand off to tools 
1338	 */
1339	list<CElement> input;
1340	list<CElement> output;
1341	int consumed = 0;
1342	if( !quietFlag ) {
1343	    logprintf( "Parsing...\n" );
1344	}
1345	for( i = 0; fileList[i] != NULL; i++ ) {
1346	    CNode* code = Load( fileList[i]->GetName(), TRUE, TRUE );
1347	    const char* name = rindex( fileList[i]->GetName(), '/' );
1348	    if( !name ) {
1349		name = fileList[i]->GetName();
1350	    }
1351	    output.push_back( CElement( name, 1, code ) );
1352  	    if( dumpFlag ) {
1353  	        fprintf( stdout, "MACRO definitions:\n" );
1354  	        fprintf( stdout, "------------------\n" );
1355  	        macroSymtab.Dump( stdout, 1 );
1356  	        fprintf( stdout, "global definitions:\n" );
1357  	        fprintf( stdout, "------------------\n" );
1358  	        definitionSymtab.Dump( stdout, 1 );
1359  	        fprintf( stdout, "MODULE definitions:\n" );
1360  	        fprintf( stdout, "------------------\n" );
1361  	        DumpCode( stdout, code );
1362  	    }
1363	}
1364	// CSymbol::DumpStats();
1365	/* 
1366	 * bail out if errors occurred
1367	 */
1368	if( errorCount ) {
1369	    goto DONE;
1370	}
1371	/* 
1372	 * run each tool in chain
1373 	 */
1374	for( ptr = enabledTools.begin(); ptr != enabledTools.end(); ++ptr ) {
1375	    input.erase( input.begin(), input.end() );
1376	    list<CElement>::iterator eptr;
1377  	    for( eptr = output.begin(); eptr != output.end(); ++eptr ) {
1378    	        /*
1379    	         * if tools requires it resolve all module references
1380    	         * Make 2 pass to see if search found other modules
1381    	         */
1382		int pass = 1;
1383		CNode* code = eptr->Code();
1384    	        while( (*ptr)->ResolveModules() && 
1385    	               !ModulesResolved( *ptr, code ) ) {
1386    	            CNode* rcode = ResolveModuleList( *ptr, code, 
1387				(*ptr)->RequireModuleResolution() && pass>1 );
1388    	            if( pass > 1 && !rcode ) {
1389    	                break;	
1390    	            }
1391		    pass++;
1392    	            code = cLINK( rcode, code );
1393    	        }
1394	 	eptr->Code( code );	
1395		input.push_back( *eptr );
1396	    }
1397	    output.erase( output.begin(), output.end() );
1398	    if( errorCount ) {
1399	        goto DONE;
1400	    }
1401
1402            CBackend* tool = (*ptr);
1403	    if( !quietFlag ) {
1404	        logprintf( "Executing tool %s...\n", tool->GetToolName() );
1405	    }
1406	    /* 
1407             * use plugin storage manager by default
1408             */
1409            CNode::SetBuildStack( pluginStack );
1410
1411	    try { 
1412	        tool->Process( input, output  );
1413	    } catch( CBackendAbort ) {
1414		abort();
1415	    } catch( CBackendFail ) {
1416		goto DONE;
1417	    } catch( CBackendExit ) {
1418		// success!
1419	    } catch( ... ) {
1420		abort();
1421	    }
1422
1423	    /*
1424             * restore environment
1425             */
1426           CNode::ResetBuildStack();
1427
1428
1429	    if( output.size() == 0 ) {
1430		output = input;
1431		consumed = 1;
1432	    }
1433	}
1434	/* 
1435	 * If output hasn't be consumed run dump tool
1436  	 */
1437	if( !consumed && output.size() && errorCount == 0 ) {
1438	    if( !quietFlag ) {
1439	        logprintf( "Executing tool %s...\n", 
1440					dumpVerilog->GetToolName() );
1441	    }
1442	    list<CElement> dummy;
1443	    try { 
1444	        dumpVerilog->Process( output, dummy  );
1445	    } catch( CBackendAbort ) {
1446		abort();
1447	    } catch( CBackendFail ) {
1448		goto DONE;
1449	    } catch( CBackendExit ) {
1450		// success!
1451	    } catch( ... ) {
1452		abort();
1453	    } 
1454	}
1455
1456DONE:
1457//	logprintf( "Total Memory Allocated = %d\n", totalMem );
1458	if( !quietFlag ) {
1459	    logprintf( "%d Errors, %d Warnings\n", errorCount, warningCount );
1460	}
1461
1462	return (errorCount != 0);
1463}
1464