bool OSLCompilerImpl::compile (const std::string &filename, const std::vector<std::string> &options) { if (! boost::filesystem::exists (filename)) { error (ustring(), 0, "Input file \"%s\" not found", filename.c_str()); return false; } std::string stdinclude; #ifdef USE_BOOST_WAVE std::vector<std::string> defines; std::vector<std::string> undefines; std::vector<std::string> includepaths; #else std::string cppoptions; #endif // Determine where the installed shader include directory is, and // look for ../shaders/stdosl.h and force it to include. std::string program = Sysutil::this_program_path (); if (program.size()) { boost::filesystem::path path (program); // our program #if BOOST_VERSION >= 103600 path = path.parent_path (); // now the bin dir of our program path = path.parent_path (); // now the parent dir #else path = path.branch_path (); // now the bin dir of our program path = path.branch_path (); // now the parent dir #endif path = path / "shaders"; bool found = false; if (boost::filesystem::exists (path)) { path = path / "stdosl.h"; if (boost::filesystem::exists (path)) { stdinclude = path.string(); found = true; } } if (! found) warning (ustring(filename), 0, "Unable to find \"%s\"", path.string().c_str()); } m_output_filename.clear (); bool preprocess_only = false; for (size_t i = 0; i < options.size(); ++i) { if (options[i] == "-v") { // verbose mode m_verbose = true; } else if (options[i] == "-q") { // quiet mode m_quiet = true; } else if (options[i] == "-d") { // debug mode m_debug = true; } else if (options[i] == "-E") { preprocess_only = true; } else if (options[i] == "-o" && i < options.size()-1) { ++i; m_output_filename = options[i]; } else if (options[i] == "-O0") { m_optimizelevel = 0; } else if (options[i] == "-O" || options[i] == "-O1") { m_optimizelevel = 1; } else if (options[i] == "-O2") { m_optimizelevel = 2; #ifdef USE_BOOST_WAVE } else if (options[i].c_str()[0] == '-' && options[i].size() > 2) { // options meant for the preprocessor if(options[i].c_str()[1] == 'D') defines.push_back(options[i].substr(2)); else if(options[i].c_str()[1] == 'U') undefines.push_back(options[i].substr(2)); else if(options[i].c_str()[1] == 'I') includepaths.push_back(options[i].substr(2)); #else } else { // something meant for the cpp command cppoptions += "\""; cppoptions += options[i]; cppoptions += "\" "; #endif } } std::string preprocess_result; #ifdef USE_BOOST_WAVE if (! preprocess(filename, stdinclude, defines, undefines, includepaths, preprocess_result)) { #else if (! preprocess(filename, stdinclude, cppoptions, preprocess_result)) { #endif return false; } else if (preprocess_only) { std::cout << preprocess_result; } else { std::istringstream in (preprocess_result); oslcompiler = this; // Create a lexer, parse the file, delete the lexer m_lexer = new oslFlexLexer (&in); oslparse (); bool parseerr = error_encountered(); delete m_lexer; if (! parseerr) { shader()->typecheck (); } // Print the parse tree if there were no errors if (m_debug) { symtab().print (); if (shader()) shader()->print (std::cout); } if (! error_encountered()) { shader()->codegen (); // add_useparam (); track_variable_dependencies (); track_variable_lifetimes (); check_for_illegal_writes (); // if (m_optimizelevel >= 1) // coalesce_temporaries (); } if (! error_encountered()) { if (m_output_filename.size() == 0) m_output_filename = default_output_filename (); write_oso_file (m_output_filename); } oslcompiler = NULL; } return ! error_encountered(); } struct GlobalTable { const char *name; TypeSpec type; }; static GlobalTable globals[] = { { "P", TypeDesc::TypePoint }, { "I", TypeDesc::TypeVector }, { "N", TypeDesc::TypeNormal }, { "Ng", TypeDesc::TypeNormal }, { "u", TypeDesc::TypeFloat }, { "v", TypeDesc::TypeFloat }, { "dPdu", TypeDesc::TypeVector }, { "dPdv", TypeDesc::TypeVector }, #if 0 // Light variables -- we don't seem to be on a route to support this // kind of light shader, so comment these out for now. { "L", TypeDesc::TypeVector }, { "Cl", TypeDesc::TypeColor }, { "Ns", TypeDesc::TypeNormal }, { "Pl", TypeDesc::TypePoint }, { "Nl", TypeDesc::TypeNormal }, #endif { "Ps", TypeDesc::TypePoint }, { "Ci", TypeSpec (TypeDesc::TypeColor, true) }, { "time", TypeDesc::TypeFloat }, { "dtime", TypeDesc::TypeFloat }, { "dPdtime", TypeDesc::TypeVector }, { NULL } }; void OSLCompilerImpl::initialize_globals () { for (int i = 0; globals[i].name; ++i) { Symbol *s = new Symbol (ustring(globals[i].name), globals[i].type, SymTypeGlobal); symtab().insert (s); } } std::string OSLCompilerImpl::default_output_filename () { if (m_shader && shader_decl()) return shader_decl()->shadername().string() + ".oso"; return std::string(); } void OSLCompilerImpl::write_oso_metadata (const ASTNode *metanode) const { ASSERT (metanode->nodetype() == ASTNode::variable_declaration_node); const ASTvariable_declaration *metavar = static_cast<const ASTvariable_declaration *>(metanode); Symbol *metasym = metavar->sym(); ASSERT (metasym); TypeSpec ts = metasym->typespec(); oso ("%%meta{%s,%s,", ts.string().c_str(), metasym->name().c_str()); const ASTNode *init = metavar->init().get(); ASSERT (init); if (ts.is_string() && init->nodetype() == ASTNode::literal_node) oso ("\"%s\"", ((const ASTliteral *)init)->strval()); else if (ts.is_int() && init->nodetype() == ASTNode::literal_node) oso ("%d", ((const ASTliteral *)init)->intval()); else if (ts.is_float() && init->nodetype() == ASTNode::literal_node) oso ("%.8g", ((const ASTliteral *)init)->floatval()); // FIXME -- what about type constructors? else { std::cout << "Error, don't know how to print metadata " << ts.string() << " with node type " << init->nodetypename() << "\n"; ASSERT (0); // FIXME } oso ("} "); }
bool OSLCompilerImpl::compile_buffer (string_view sourcecode, std::string &osobuffer, const std::vector<std::string> &options, string_view stdoslpath) { string_view filename ("<buffer>"); #if OIIO_VERSION >= 10604 m_cwd = OIIO::Filesystem::current_path(); #else m_cwd = boost::filesystem::current_path().string(); #endif m_main_filename = filename; // Determine where the installed shader include directory is, and // look for ../shaders/stdosl.h and force it to include. if (stdoslpath.empty()) { // look in $OSLHOME/shaders const char *OSLHOME = getenv ("OSLHOME"); if (OSLHOME && OSLHOME[0]) { std::string path = std::string(OSLHOME) + "/shaders"; if (OIIO::Filesystem::exists (path)) { path = path + "/stdosl.h"; if (OIIO::Filesystem::exists (path)) stdoslpath = ustring(path); } } } if (stdoslpath.empty() || ! OIIO::Filesystem::exists(stdoslpath)) warning (ustring(filename), 0, "Unable to find \"stdosl.h\""); std::vector<std::string> defines; std::vector<std::string> includepaths; read_compile_options (options, defines, includepaths); std::string preprocess_result; if (! preprocess_buffer (sourcecode, filename, stdoslpath, defines, includepaths, preprocess_result)) { return false; } else if (m_preprocess_only) { std::cout << preprocess_result; } else { bool parseerr = osl_parse_buffer (preprocess_result); if (! parseerr) { if (shader()) shader()->typecheck (); else error (ustring(), 0, "No shader function defined"); } // Print the parse tree if there were no errors if (m_debug) { symtab().print (); if (shader()) shader()->print (std::cout); } if (! error_encountered()) { shader()->codegen (); track_variable_dependencies (); track_variable_lifetimes (); check_for_illegal_writes (); // if (m_optimizelevel >= 1) // coalesce_temporaries (); } if (! error_encountered()) { m_output_filename = "<buffer>"; std::ostringstream oso_output; ASSERT (m_osofile == NULL); m_osofile = &oso_output; write_oso_file (m_output_filename, OIIO::Strutil::join(options," ")); osobuffer = oso_output.str(); ASSERT (m_osofile == NULL); } oslcompiler = NULL; } return ! error_encountered(); }