// // Copyright (c) ZeroC, Inc. All rights reserved. // #include #include #include #include #include #include using namespace std; using namespace IceRuby; using namespace Slice; using namespace Slice::Ruby; extern "C" VALUE IceRuby_loadSlice(int argc, VALUE* argv, VALUE /*self*/) { ICE_RUBY_TRY { if(argc < 1 || argc > 2) { throw RubyException(rb_eArgError, "wrong number of arguments"); } string cmd = getString(argv[0]); vector argSeq; try { argSeq = IceUtilInternal::Options::split(cmd); } catch(const IceUtilInternal::BadOptException& ex) { throw RubyException(rb_eArgError, "error in Slice options: %s", ex.reason.c_str()); } catch(const IceUtilInternal::APIException& ex) { throw RubyException(rb_eArgError, "error in Slice options: %s", ex.reason.c_str()); } if(argc > 1) { if(!arrayToStringSeq(argv[1], argSeq)) { throw RubyException(rb_eTypeError, "argument 2 is not an array"); } } IceUtilInternal::Options opts; opts.addOpt("D", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("U", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("I", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("d", "debug"); opts.addOpt("", "ice"); opts.addOpt("", "underscore"); opts.addOpt("", "checksum"); opts.addOpt("", "all"); vector files; try { argSeq.insert(argSeq.begin(), ""); // dummy argv[0] files = opts.parse(argSeq); if(files.empty()) { throw RubyException(rb_eArgError, "no Slice files specified in `%s'", cmd.c_str()); } } catch(const IceUtilInternal::BadOptException& ex) { throw RubyException(rb_eArgError, "error in Slice options: %s", ex.reason.c_str()); } catch(const IceUtilInternal::APIException& ex) { throw RubyException(rb_eArgError, "error in Slice options: %s", ex.reason.c_str()); } vector cppArgs; vector includePaths; bool debug = false; bool ice = true; // This must be true so that we can create Ice::Identity when necessary. bool underscore = opts.isSet("underscore"); bool all = false; bool checksum = false; if(opts.isSet("D")) { vector optargs = opts.argVec("D"); for(vector::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { cppArgs.push_back("-D" + *i); } } if(opts.isSet("U")) { vector optargs = opts.argVec("U"); for(vector::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { cppArgs.push_back("-U" + *i); } } if(opts.isSet("I")) { includePaths = opts.argVec("I"); for(vector::const_iterator i = includePaths.begin(); i != includePaths.end(); ++i) { cppArgs.push_back("-I" + *i); } } debug = opts.isSet("d") || opts.isSet("debug"); all = opts.isSet("all"); checksum = opts.isSet("checksum"); bool ignoreRedefs = false; for(vector::const_iterator p = files.begin(); p != files.end(); ++p) { string file = *p; Slice::PreprocessorPtr icecpp = Slice::Preprocessor::create("icecpp", file, cppArgs); FILE* cppHandle = icecpp->preprocess(false, "-D__SLICE2RB__"); if(cppHandle == 0) { throw RubyException(rb_eArgError, "Slice preprocessing failed for `%s'", cmd.c_str()); } UnitPtr u = Slice::Unit::createUnit(ignoreRedefs, all, ice, underscore); int parseStatus = u->parse(file, cppHandle, debug); if(!icecpp->close() || parseStatus == EXIT_FAILURE) { u->destroy(); throw RubyException(rb_eArgError, "Slice parsing failed for `%s'", cmd.c_str()); } // // Generate the Ruby code into a string stream. // ostringstream codeStream; IceUtilInternal::Output out(codeStream); out.setUseTab(false); // // Ruby magic comment to set the file encoding, it must be first or second line // out << "# encoding: utf-8\n"; generate(u, all, checksum, includePaths, out); u->destroy(); string code = codeStream.str(); callRuby(rb_eval_string, code.c_str()); } } ICE_RUBY_CATCH return Qnil; } extern "C" VALUE IceRuby_compile(int argc, VALUE* argv, VALUE /*self*/) { ICE_RUBY_TRY { if(argc != 1) { throw RubyException(rb_eArgError, "wrong number of arguments"); } vector argSeq; if(!arrayToStringSeq(argv[0], argSeq)) { throw RubyException(rb_eTypeError, "argument is not an array"); } // Manufacture a fake argv[0]. argSeq.insert(argSeq.begin(), "slice2rb"); int rc; try { rc = Slice::Ruby::compile(argSeq); } catch(const std::exception& ex) { cerr << argSeq[0] << ": error:" << ex.what() << endl; rc = EXIT_FAILURE; } catch(...) { cerr << argSeq[0] << ": error:" << "unknown exception" << endl; rc = EXIT_FAILURE; } return INT2FIX(rc); } ICE_RUBY_CATCH return Qnil; } void IceRuby::initSlice(VALUE iceModule) { rb_define_module_function(iceModule, "loadSlice", CAST_METHOD(IceRuby_loadSlice), -1); rb_define_module_function(iceModule, "compile", CAST_METHOD(IceRuby_compile), -1); }