"Fossies" - the Fresh Open Source Software Archive

Member "aqsis-1.8.2/tools/aqsl/aqsl.cpp" (24 Aug 2012, 10117 Bytes) of package /linux/privat/aqsis-1.8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Aqsis
    2 // Copyright (C) 1997 - 2001, Paul C. Gregory
    3 //
    4 // Contact: pgregory@aqsis.org
    5 //
    6 // This library is free software; you can redistribute it and/or
    7 // modify it under the terms of the GNU General Public
    8 // License as published by the Free Software Foundation; either
    9 // version 2 of the License, or (at your option) any later version.
   10 //
   11 // This library is distributed in the hope that it will be useful,
   12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14 // General Public License for more details.
   15 //
   16 // You should have received a copy of the GNU General Public
   17 // License along with this library; if not, write to the Free Software
   18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19 
   20 
   21 /** \file
   22         \brief Implements a Renderman Shading Language compiler that generates Aqsis bytecode 
   23         \author Paul C. Gregory (pgregory@aqsis.org)
   24         \author Timothy M. Shead (tshead@k-3d.com)
   25 */
   26 
   27 #include    <aqsis/aqsis.h>
   28 #include    <aqsis/util/logging.h>
   29 #include    <aqsis/util/logging_streambufs.h>
   30 #include    <aqsis/util/file.h>
   31 
   32 #include    <iostream>
   33 #include    <fstream>
   34 #include    <sstream>
   35 #include    <cstdlib>
   36 #include    <cstring>
   37 #include    <string>
   38 #include    <vector>
   39 #include    <boost/scoped_ptr.hpp>
   40 
   41 #ifdef  AQSIS_SYSTEM_WIN32
   42 #include    "io.h"
   43 #else
   44 #include    "unistd.h"
   45 #endif //AQSIS_SYSTEM_WIN32
   46 
   47 #include    <aqsis/slcomp/libslparse.h>
   48 #include    <aqsis/slcomp/icodegen.h>
   49 #include    <aqsis/util/argparse.h>
   50 
   51 #include    <aqsis/version.h>
   52 
   53 //  Setup wave, and the cpp lexer
   54 #include <boost/wave.hpp>
   55 #include <boost/wave/cpplexer/cpp_lex_token.hpp>    // token class
   56 #include <boost/wave/cpplexer/cpp_lex_iterator.hpp> // lexer class
   57 
   58 //
   59 using namespace Aqsis;
   60 
   61 extern "C" void PreProcess(int argc, char** argv);
   62 
   63 ArgParse::apstring  g_stroutname = "";
   64 bool    g_help = 0;
   65 bool    g_version = 0;
   66 ArgParse::apstringvec g_defines; // Filled in with strings to pass to the preprocessor
   67 ArgParse::apstringvec g_includes; // Filled in with strings to pass to the preprocessor
   68 ArgParse::apstringvec g_undefines; // Filled in with strings to pass to the preprocessor
   69 ArgParse::apstring g_backendName = "slx"; /// Name for the comipler backend.
   70 
   71 bool g_dumpsl = 0;
   72 bool g_cl_no_color = false;
   73 bool g_cl_syslog = false;
   74 ArgParse::apint g_cl_verbose = 1;
   75 
   76 void version( std::ostream& Stream )
   77 {
   78     Stream << "aqsl version " << AQSIS_VERSION_STR_FULL << std::endl << "compiled " << __DATE__ << " " << __TIME__ << std::endl;
   79 }
   80 
   81 
   82 /** Process the sl file from stdin and produce an slx bytestream.
   83  */
   84 int main( int argc, const char** argv )
   85 {
   86     ArgParse ap;
   87     boost::scoped_ptr<IqCodeGen> codeGenerator;
   88     bool error = false; ///! Couldn't compile shader
   89 
   90     ap.usageHeader( ArgParse::apstring( "Usage: " ) + argv[ 0 ] + " [options] <filename>" );
   91     ap.argString( "o", " %s \aspecify output filename", &g_stroutname );
   92     ap.argStrings( "i", "%s \aSet path for #include files.", &g_includes );
   93     ap.argStrings( "I", "%s \aSet path for #include files.", &g_includes );
   94     ap.argStrings( "D", "Sym[=value] \adefine symbol <string> to have value <value> (default: 1).", &g_defines );
   95     ap.argStrings( "U", "Sym \aUndefine an initial symbol.", &g_undefines );
   96     ap.argString( "backend", " %s \aCompiler backend (default %default).  Possibilities include \"slx\" or \"dot\":\a"
   97                   "slx - produce a compiled shader (in the aqsis shader VM stack language)\a"
   98                   "dot - make a graphviz visualization of the parse tree (useful for debugging only).", &g_backendName );
   99     ap.argFlag( "help", "\aPrint this help and exit", &g_help );
  100     ap.alias("help", "h");
  101     ap.argFlag( "version", "\aPrint version information and exit", &g_version );
  102     ap.argFlag( "nocolor", "\aDisable colored output", &g_cl_no_color );
  103     ap.alias( "nocolor" , "nc" );
  104     ap.argFlag( "d", "\adump sl data", &g_dumpsl );
  105     ap.argInt( "verbose", "=integer\aSet log output level\n"
  106                "\a0 = errors\n"
  107                "\a1 = warnings (default)\n"
  108                "\a2 = information\n"
  109                "\a3 = debug", &g_cl_verbose );
  110     ap.alias( "verbose", "v" );
  111 
  112     if ( argc > 1 && !ap.parse( argc - 1, argv + 1 ) )
  113     {
  114         Aqsis::log() << ap.errmsg() << std::endl << ap.usagemsg();
  115         exit( 1 );
  116     }
  117 
  118     if ( g_version )
  119     {
  120         version( std::cout );
  121         exit( 0 );
  122     }
  123 
  124     if ( g_help )
  125     {
  126         std::cout << ap.usagemsg();
  127         exit( 0 );
  128     }
  129 
  130 #ifdef  AQSIS_SYSTEM_WIN32
  131     std::auto_ptr<std::streambuf> ansi( new Aqsis::ansi_buf(Aqsis::log()) );
  132 #endif
  133 
  134     std::auto_ptr<std::streambuf> reset_level( new Aqsis::reset_level_buf(Aqsis::log()) );
  135     std::auto_ptr<std::streambuf> show_timestamps( new Aqsis::timestamp_buf(Aqsis::log()) );
  136     std::auto_ptr<std::streambuf> fold_duplicates( new Aqsis::fold_duplicates_buf(Aqsis::log()) );
  137     std::auto_ptr<std::streambuf> color_level;
  138     if(!g_cl_no_color)
  139     {
  140         std::auto_ptr<std::streambuf> temp_color_level( new Aqsis::color_level_buf(Aqsis::log()) );
  141         color_level = temp_color_level;
  142     }
  143     std::auto_ptr<std::streambuf> show_level( new Aqsis::show_level_buf(Aqsis::log()) );
  144     Aqsis::log_level_t level = Aqsis::ERROR;
  145     if( g_cl_verbose > 0 )
  146         level = Aqsis::WARNING;
  147     if( g_cl_verbose > 1 )
  148         level = Aqsis::INFO;
  149     if( g_cl_verbose > 2 )
  150         level = Aqsis::DEBUG;
  151     std::auto_ptr<std::streambuf> filter_level( new Aqsis::filter_by_level_buf(level, Aqsis::log()) );
  152 #ifdef  AQSIS_SYSTEM_POSIX
  153 
  154     if( g_cl_syslog )
  155         std::auto_ptr<std::streambuf> use_syslog( new Aqsis::syslog_buf(Aqsis::log()) );
  156 #endif  // AQSIS_SYSTEM_POSIX
  157 
  158     if ( ap.leftovers().size() == 0 )
  159     {
  160         std::cout << ap.usagemsg();
  161         exit( 0 );
  162     }
  163     else
  164     {
  165         for ( ArgParse::apstringvec::const_iterator e = ap.leftovers().begin(); e != ap.leftovers().end(); e++ )
  166         {
  167             //Expand filenames
  168             std::vector<std::string> files = Aqsis::cliGlob(*e);
  169             std::vector<std::string>::iterator it;
  170             for(it = files.begin(); it != files.end(); ++it){ 
  171                 ResetParser();
  172                 // Create a code generator for the requested backend.
  173                 if(g_backendName == "slx")
  174                     codeGenerator.reset(new CqCodeGenVM());
  175                 else if(g_backendName == "dot")
  176                     codeGenerator.reset(new CqCodeGenGraphviz());
  177                 else
  178                 {
  179                     std::cout << "Unknown backend type: \"" << g_backendName << "\", assuming slx.";
  180                     codeGenerator.reset(new CqCodeGenVM());
  181                 }
  182                 // current file position is saved for exception handling
  183                 boost::wave::util::file_position_type current_position;
  184 
  185                 try
  186                 {
  187                     //  Open and read in the specified input file.
  188                     std::ifstream instream(it->c_str());
  189                     std::string instring;
  190     
  191                     if (!instream.is_open()) 
  192                     {
  193                         std::cerr << "Could not open input file: " << *it << std::endl;
  194                         continue;
  195                     }
  196                     instream.unsetf(std::ios::skipws);
  197                     instring = std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
  198                         std::istreambuf_iterator<char>());
  199     
  200                     typedef boost::wave::cpplexer::lex_token<> token_type;
  201                     typedef boost::wave::cpplexer::lex_iterator<token_type> lex_iterator_type;
  202                     typedef boost::wave::context<std::string::iterator, lex_iterator_type>
  203                         context_type;
  204                     context_type ctx (instring.begin(), instring.end(), it->c_str());
  205 
  206                     // Append the -i arguments passed in to forward them to the preprocessor.
  207                     for ( ArgParse::apstringvec::const_iterator include = g_includes.begin(); include != g_includes.end(); include++ )
  208                     {
  209                         ctx.add_sysinclude_path( include->c_str() );
  210                         ctx.add_include_path( include->c_str() );
  211                     }
  212   
  213                     // Setup the default defines.
  214                     ctx.add_macro_definition( "AQSIS" );
  215                     ctx.add_macro_definition( "PI=3.141592654" );
  216   
  217                     // Append the -d arguments passed in to forward them to the preprocessor.
  218                     for ( ArgParse::apstringvec::const_iterator define = g_defines.begin(); define != g_defines.end(); define++ )
  219                     {
  220                         ctx.add_macro_definition( define->c_str() );
  221                     }
  222   
  223                     // Append the -u arguments passed in to forward them to the preprocessor.
  224                     for ( ArgParse::apstringvec::const_iterator undefine = g_undefines.begin(); undefine != g_undefines.end(); undefine++ )
  225                     {
  226                         ctx.remove_macro_definition( undefine->c_str() );
  227                     }
  228   
  229                     // analyze the input file
  230                     context_type::iterator_type first = ctx.begin();
  231                     context_type::iterator_type last = ctx.end();
  232 
  233                     std::stringstream preprocessed(std::stringstream::in | std::stringstream::out);
  234                     std::ofstream dumpfile;
  235                     if( g_dumpsl )
  236                     {
  237                         std::string dumpfname(*it);
  238                         dumpfname.append(".pp");
  239                         dumpfile.open(dumpfname.c_str());
  240                     };
  241 
  242                     while (first != last) 
  243                     {
  244                         current_position = (*first).get_position();
  245                         preprocessed << (*first).get_value();
  246                         dumpfile << (*first).get_value();
  247 
  248                         try
  249                         {
  250                             ++first ;
  251                         }
  252                         catch (boost::wave::preprocess_exception &e) 
  253                         {
  254                             Aqsis::log() 
  255                             << e.file_name() << "(" << e.line_no() << "): "
  256                             << e.description() << std::endl;
  257                             if (e.get_errorcode() == ::boost::wave::preprocess_exception::last_line_not_terminated )
  258                             {
  259                                 preprocessed << std::endl;
  260                                 dumpfile << std::endl;
  261                                 break;
  262                             };
  263                         }
  264                         catch (...) 
  265                         {
  266                             throw &e;
  267                         }
  268 
  269                     };
  270   
  271                     if( dumpfile.is_open() )
  272                         dumpfile.close();
  273   
  274                     if ( Parse( preprocessed, e->c_str(), Aqsis::log() ) )
  275                         codeGenerator->OutputTree( GetParseTree(), g_stroutname );
  276                     else
  277                         error = true;
  278                 }
  279                 catch (boost::wave::cpp_exception &e) 
  280                 {
  281                     // some preprocessing error
  282                     Aqsis::log() 
  283                     << e.file_name() << "(" << e.line_no() << "): "
  284                     << e.description() << std::endl;
  285                     continue;
  286                 }
  287                 catch (std::exception &e)
  288                 {
  289                     // use last recognized token to retrieve the error position
  290                     Aqsis::log() << current_position.get_file()
  291                         << "(" << current_position.get_line() << "): "
  292                         << "exception caught: " << e.what()
  293                         << std::endl;
  294                     continue;
  295                 }
  296                 catch (...) {
  297                     // use last recognized token to retrieve the error position
  298                     Aqsis::log() << current_position.get_file()
  299                     << "(" << current_position.get_line() << "): "
  300                     << "unexpected exception caught." << std::endl;
  301                     continue;
  302                 }
  303             }
  304         };
  305     }
  306 
  307     return error;
  308 }
  309 
  310