Esempio n. 1
0
int main( int argc, const char** argv )
{
	std::signal(SIGINT, aqsisSignalHandler);
	std::signal(SIGABRT, aqsisSignalHandler);
	RtInt returnCode = 0;

	StartMemoryDebugging();
	{
		ArgParse ap;
		ap.usageHeader( ArgParse::apstring( "Aqsis command line renderer\nUsage: " ) + argv[ 0 ] + " [options] [RIB file...]" );
		ap.argFlag( "help", "\aPrint this help and exit", &g_cl_help );
		ap.alias( "help" , "h" );
		ap.argFlag( "version", "\aPrint version information and exit", &g_cl_version );
		ap.argFlag( "pause", "\aWait for a keypress on completion", &g_cl_pause );
		ap.argFlag( "progress", "\aPrint progress information", &g_cl_progress );
		ap.argFlag( "Progress", "\aPrint PRMan-compatible progress information (ignores -progressformat)", &g_cl_Progress );
		ap.argString( "progressformat", "=string\aprintf-style format string for -progress", &g_cl_strprogress );
		ap.argInt( "endofframe", "=integer\aEquivalent to \"endofframe\" RIB option", &g_cl_endofframe );
		ap.argInt( "verbose", "=integer\aSet log output level\n"
		           "\a0 = errors\n"
		           "\a1 = warnings (default)\n"
		           "\a2 = information\n"
		           "\a3 = debug", &g_cl_verbose );
		ap.alias( "verbose", "v" );
		ap.argFlag( "echoapi", "\aEcho all RI API calls to the log output (experimental)", &g_cl_echoapi);

		ap.argInt( "priority", "=integer\aControl the priority class of aqsis.\n"
			"\a0 = idle\n"
			"\a1 = normal\n"
			"\a2 = high\n"
			"\a3 = RT", &g_cl_priority);
		ap.alias( "priority", "z");
		
		ap.argString( "type", "=string\aSpecify a display device type to use", &g_cl_type );
		ap.argString( "addtype", "=string\aSpecify a display device type to add", &g_cl_addtype );
		ap.argString( "mode", "=string\aSpecify a display device mode to use", &g_cl_mode );
		ap.argFlag( "fb", "\aSame as --type=\"framebuffer\" --mode=\"rgb\"", &g_cl_fb );
		ap.alias( "fb", "d" );
		ap.argFloats( "crop", " x1 x2 y1 y2\aSpecify a crop window, values are in screen space.", &g_cl_cropWindow, ArgParse::SEP_ARGV, 4);
		ap.argFlag( "nocolor", "\aDisable colored output", &g_cl_no_color );
		ap.argFlag( "beep", "\aBeep on completion of all ribs", &g_cl_beep );
		ap.alias( "nocolor", "nc" );
		ap.argInts( "res", " x y\aSpecify the resolution of the render.", &g_cl_res, ArgParse::SEP_ARGV, 2);
		ap.argStrings( "option", "=string\aA valid RIB Option string, can be specified multiple times.", &g_cl_options);
#		ifdef AQSIS_SYSTEM_POSIX
		ap.argFlag( "syslog", "\aLog messages to syslog", &g_cl_syslog );
#		endif // AQSIS_SYSTEM_POSIX
#		if ENABLE_MPDUMP
		ap.argFlag( "mpdump", "\aOutput MP list to a custom 'dump' file", &g_cl_mpdump );
#		endif // ENABLE_MPDUMP

		ap.argString( "shaders", "=string\aOverride the default shader searchpath(s)", &g_cl_shader_path );
		ap.argString( "archives", "=string\aOverride the default archive searchpath(s)", &g_cl_archive_path );
		ap.argString( "textures", "=string\aOverride the default texture searchpath(s)", &g_cl_texture_path );
		ap.argString( "displays", "=string\aOverride the default display searchpath(s)", &g_cl_display_path );
		ap.argString( "procedurals", "=string\aOverride the default procedural searchpath(s)", &g_cl_procedural_path );
		ap.allowUnrecognizedOptions();

		if ( argc > 1 && !ap.parse( argc - 1, argv + 1 ) )
		{
			Aqsis::log() << ap.errmsg() << std::endl << ap.usagemsg();
			return( 1 );
		}

		// Check that the number of arguments to crop are valid if specified.
		if ( g_cl_cropWindow.size() > 0 && g_cl_cropWindow.size() != 4 )
		{
			Aqsis::log() << Aqsis::error << "Invalid number of arguments to -crop, expected 4, got " << g_cl_cropWindow.size() << std::endl;
			g_cl_help = true;
		}

		if ( g_cl_help )
		{
			std::cout << ap.usagemsg();
			return( 0 );
		}

		if ( g_cl_version )
		{
			std::cout << "aqsis version " << AQSIS_VERSION_STR_FULL
#			ifdef _DEBUG
			<< " (debug build)"
#			endif
			<< "\n"
			<< "compiled " << __DATE__ << " " << __TIME__ << "\n";
			return( 0 );
		}

#		ifdef	AQSIS_SYSTEM_WIN32
		std::auto_ptr<std::streambuf> ansi( new Aqsis::ansi_buf(Aqsis::log()) );
#		endif

		std::auto_ptr<std::streambuf> reset_level( new Aqsis::reset_level_buf(Aqsis::log()) );
		std::auto_ptr<std::streambuf> show_timestamps( new Aqsis::timestamp_buf(Aqsis::log()) );
		std::auto_ptr<std::streambuf> fold_duplicates( new Aqsis::fold_duplicates_buf(Aqsis::log()) );
		std::auto_ptr<std::streambuf> color_level;
		if(!g_cl_no_color)
		{
			std::auto_ptr<std::streambuf> temp_color_level( new Aqsis::color_level_buf(Aqsis::log()) );
			color_level = temp_color_level;
		}
		std::auto_ptr<std::streambuf> show_level( new Aqsis::show_level_buf(Aqsis::log()) );
		Aqsis::log_level_t level = Aqsis::ERROR;
		if( g_cl_verbose > 0 )
			level = Aqsis::WARNING;
		if( g_cl_verbose > 1 )
			level = Aqsis::INFO;
		if( g_cl_verbose > 2 )
			level = Aqsis::DEBUG;
		std::auto_ptr<std::streambuf> filter_level( new Aqsis::filter_by_level_buf(level, Aqsis::log()) );
#		ifdef AQSIS_SYSTEM_POSIX
		if( g_cl_syslog )
			std::auto_ptr<std::streambuf> use_syslog( new Aqsis::syslog_buf(Aqsis::log()) );
#		endif // AQSIS_SYSTEM_POSIX

		if (g_cl_priority != 1)
		{
			// Set the priority on the main thread
			setPriority(g_cl_priority);
		}

		RiBegin(RI_NULL);
		setupOptions();
		try
		{
			if ( ap.leftovers().size() == 0 )
			{
				// If no files specified, take input from stdin.
				//
				// TODO: We'd like to turn off stdio synchronisation to allow fast
				// buffering... unfortunately this causes very odd problems with
				// the aqsis logging facility as of svn r2804
				//
				//std::ios_base::sync_with_stdio(false);
				Aqsis::QGetRenderContextI()->parseRibStream(std::cin, "stdin");
			}
			else
			{
				for(ArgParse::apstringvec::const_iterator fileName = ap.leftovers().begin();
						fileName != ap.leftovers().end(); fileName++)
				{
					std::ifstream inFile(fileName->c_str());
					if(inFile)
					{
						Aqsis::QGetRenderContextI()->parseRibStream(inFile, *fileName);
						returnCode = RiLastError;
					}
					else
					{
						Aqsis::log() << Aqsis::error
							<< "Cannot open file \"" << *fileName << "\"\n";
						returnCode = RIE_NOFILE;
					}
				}
			}
		}
		catch(const std::exception& e)
		{
			Aqsis::log() << Aqsis::error << e.what() << std::endl;
			returnCode = RIE_BUG;
		}
		catch(...)
		{
			Aqsis::log() << Aqsis::error
				<< "unknown exception has been encountered\n";
			returnCode = RIE_BUG;
		}
		RiEnd();
	}

	StopMemoryDebugging();

	if(g_cl_beep)
		std::cout << "\a" << std::ends;

	if(g_cl_pause)
	{
		std::cout << "Press any key..." << std::ends;
		std::cin.ignore(std::cin.rdbuf()->in_avail() + 1);
	}

	return returnCode;
}
Esempio n. 2
0
/** Process the sl file from stdin and produce an slx bytestream.
 */
int main( int argc, const char** argv )
{
	ArgParse ap;
	boost::scoped_ptr<IqCodeGen> codeGenerator;
	bool error = false; ///! Couldn't compile shader

	ap.usageHeader( ArgParse::apstring( "Usage: " ) + argv[ 0 ] + " [options] <filename>" );
	ap.argString( "o", " %s \aspecify output filename", &g_stroutname );
	ap.argStrings( "i", "%s \aSet path for #include files.", &g_includes );
	ap.argStrings( "I", "%s \aSet path for #include files.", &g_includes );
	ap.argStrings( "D", "Sym[=value] \adefine symbol <string> to have value <value> (default: 1).", &g_defines );
	ap.argStrings( "U", "Sym \aUndefine an initial symbol.", &g_undefines );
	ap.argString( "backend", " %s \aCompiler backend (default %default).  Possibilities include \"slx\" or \"dot\":\a"
			      "slx - produce a compiled shader (in the aqsis shader VM stack language)\a"
				  "dot - make a graphviz visualization of the parse tree (useful for debugging only).", &g_backendName );
	ap.argFlag( "help", "\aPrint this help and exit", &g_help );
	ap.alias("help", "h");
	ap.argFlag( "version", "\aPrint version information and exit", &g_version );
	ap.argFlag( "nocolor", "\aDisable colored output", &g_cl_no_color );
	ap.alias( "nocolor" , "nc" );
	ap.argFlag( "d", "\adump sl data", &g_dumpsl );
	ap.argInt( "verbose", "=integer\aSet log output level\n"
			   "\a0 = errors\n"
			   "\a1 = warnings (default)\n"
			   "\a2 = information\n"
			   "\a3 = debug", &g_cl_verbose );
	ap.alias( "verbose", "v" );

	if ( argc > 1 && !ap.parse( argc - 1, argv + 1 ) )
	{
		Aqsis::log() << ap.errmsg() << std::endl << ap.usagemsg();
		exit( 1 );
	}

	if ( g_version )
	{
		version( std::cout );
		exit( 0 );
	}

	if ( g_help )
	{
		std::cout << ap.usagemsg();
		exit( 0 );
	}

#ifdef	AQSIS_SYSTEM_WIN32
	std::auto_ptr<std::streambuf> ansi( new Aqsis::ansi_buf(Aqsis::log()) );
#endif

	std::auto_ptr<std::streambuf> reset_level( new Aqsis::reset_level_buf(Aqsis::log()) );
	std::auto_ptr<std::streambuf> show_timestamps( new Aqsis::timestamp_buf(Aqsis::log()) );
	std::auto_ptr<std::streambuf> fold_duplicates( new Aqsis::fold_duplicates_buf(Aqsis::log()) );
	std::auto_ptr<std::streambuf> color_level;
	if(!g_cl_no_color)
	{
		std::auto_ptr<std::streambuf> temp_color_level( new Aqsis::color_level_buf(Aqsis::log()) );
		color_level = temp_color_level;
	}
	std::auto_ptr<std::streambuf> show_level( new Aqsis::show_level_buf(Aqsis::log()) );
	Aqsis::log_level_t level = Aqsis::ERROR;
	if( g_cl_verbose > 0 )
		level = Aqsis::WARNING;
	if( g_cl_verbose > 1 )
		level = Aqsis::INFO;
	if( g_cl_verbose > 2 )
		level = Aqsis::DEBUG;
	std::auto_ptr<std::streambuf> filter_level( new Aqsis::filter_by_level_buf(level, Aqsis::log()) );
#ifdef	AQSIS_SYSTEM_POSIX

	if( g_cl_syslog )
		std::auto_ptr<std::streambuf> use_syslog( new Aqsis::syslog_buf(Aqsis::log()) );
#endif	// AQSIS_SYSTEM_POSIX

	if ( ap.leftovers().size() == 0 )
	{
		std::cout << ap.usagemsg();
		exit( 0 );
	}
	else
	{
		for ( ArgParse::apstringvec::const_iterator e = ap.leftovers().begin(); e != ap.leftovers().end(); e++ )
		{
			//Expand filenames
			std::vector<std::string> files = Aqsis::cliGlob(*e);
			std::vector<std::string>::iterator it;
			for(it = files.begin(); it != files.end(); ++it){ 
				ResetParser();
				// Create a code generator for the requested backend.
				if(g_backendName == "slx")
					codeGenerator.reset(new CqCodeGenVM());
				else if(g_backendName == "dot")
					codeGenerator.reset(new CqCodeGenGraphviz());
				else
				{
					std::cout << "Unknown backend type: \"" << g_backendName << "\", assuming slx.";
					codeGenerator.reset(new CqCodeGenVM());
				}
				// current file position is saved for exception handling
				boost::wave::util::file_position_type current_position;

				try
				{
					//  Open and read in the specified input file.
					std::ifstream instream(it->c_str());
					std::string instring;
	
					if (!instream.is_open()) 
					{
						std::cerr << "Could not open input file: " << *it << std::endl;
						continue;
					}
					instream.unsetf(std::ios::skipws);
					instring = std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
					    std::istreambuf_iterator<char>());
	
					typedef boost::wave::cpplexer::lex_token<> token_type;
					typedef boost::wave::cpplexer::lex_iterator<token_type> lex_iterator_type;
					typedef boost::wave::context<std::string::iterator, lex_iterator_type>
					    context_type;
					context_type ctx (instring.begin(), instring.end(), it->c_str());

					// Append the -i arguments passed in to forward them to the preprocessor.
					for ( ArgParse::apstringvec::const_iterator include = g_includes.begin(); include != g_includes.end(); include++ )
					{
						ctx.add_sysinclude_path( include->c_str() );
						ctx.add_include_path( include->c_str() );
					}
  
					// Setup the default defines.
					ctx.add_macro_definition( "AQSIS" );
					ctx.add_macro_definition( "PI=3.141592654" );
  
					// Append the -d arguments passed in to forward them to the preprocessor.
					for ( ArgParse::apstringvec::const_iterator define = g_defines.begin(); define != g_defines.end(); define++ )
					{
						ctx.add_macro_definition( define->c_str() );
					}
  
					// Append the -u arguments passed in to forward them to the preprocessor.
					for ( ArgParse::apstringvec::const_iterator undefine = g_undefines.begin(); undefine != g_undefines.end(); undefine++ )
					{
						ctx.remove_macro_definition( undefine->c_str() );
					}
  
					// analyze the input file
					context_type::iterator_type first = ctx.begin();
					context_type::iterator_type last = ctx.end();

					std::stringstream preprocessed(std::stringstream::in | std::stringstream::out);
					std::ofstream dumpfile;
					if( g_dumpsl )
					{
						std::string dumpfname(*it);
						dumpfname.append(".pp");
						dumpfile.open(dumpfname.c_str());
					};

					while (first != last) 
					{
						current_position = (*first).get_position();
						preprocessed << (*first).get_value();
						dumpfile << (*first).get_value();

						try
						{
							++first	;
						}
						catch (boost::wave::preprocess_exception &e) 
  						{
							Aqsis::log() 
							<< e.file_name() << "(" << e.line_no() << "): "
							<< e.description() << std::endl;
							if (e.get_errorcode() == ::boost::wave::preprocess_exception::last_line_not_terminated )
							{
								preprocessed << std::endl;
								dumpfile << std::endl;
								break;
							};
  						}
						catch (...) 
						{
							throw &e;
						}

					};
  
					if( dumpfile.is_open() )
						dumpfile.close();
  
					if ( Parse( preprocessed, e->c_str(), Aqsis::log() ) )
						codeGenerator->OutputTree( GetParseTree(), g_stroutname );
					else
						error = true;
				}
				catch (boost::wave::cpp_exception &e) 
				{
					// some preprocessing error
					Aqsis::log() 
					<< e.file_name() << "(" << e.line_no() << "): "
					<< e.description() << std::endl;
					continue;
				}
				catch (std::exception &e)
				{
					// use last recognized token to retrieve the error position
					Aqsis::log() << current_position.get_file()
				        << "(" << current_position.get_line() << "): "
				        << "exception caught: " << e.what()
				        << std::endl;
					continue;
				}
				catch (...) {
					// use last recognized token to retrieve the error position
					Aqsis::log() << current_position.get_file()
					<< "(" << current_position.get_line() << "): "
					<< "unexpected exception caught." << std::endl;
					continue;
				}
			}
		};
	}

	return error;
}