22// Distributed under the MIT software license, see the accompanying
33// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44
5+ #include < mp/config.h>
6+ #include < mp/util.h>
7+
58#include < boost/optional.hpp>
69#include < capnp/schema-parser.h>
710#include < fstream>
@@ -66,49 +69,95 @@ bool BoxedType(const ::capnp::Type& type)
6669 type.isFloat64 () || type.isEnum ());
6770}
6871
69- void Generate (kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPtr<const kj::StringPtr> import_paths)
72+ void Generate (kj::StringPtr src_prefix,
73+ kj::StringPtr include_prefix,
74+ kj::StringPtr src_file,
75+ kj::ArrayPtr<const kj::StringPtr> import_paths)
7076{
77+ std::string output_path;
78+ if (src_prefix == " ." ) {
79+ output_path = src_file;
80+ } else if (!src_file.startsWith (src_prefix) || src_file.size () <= src_prefix.size () ||
81+ src_file[src_prefix.size ()] != ' /' ) {
82+ throw std::runtime_error (" src_prefix is not src_file prefix" );
83+ } else {
84+ output_path = src_file.slice (src_prefix.size () + 1 );
85+ }
86+
87+ std::string include_path;
88+ if (include_prefix == " ." ) {
89+ include_path = src_file;
90+ } else if (!src_file.startsWith (include_prefix) || src_file.size () <= include_prefix.size () ||
91+ src_file[include_prefix.size ()] != ' /' ) {
92+ throw std::runtime_error (" include_prefix is not src_file prefix" );
93+ } else {
94+ include_path = src_file.slice (include_prefix.size () + 1 );
95+ }
96+
97+ std::string include_base = include_path;
98+ std::string::size_type p = include_base.rfind (" ." );
99+ if (p != std::string::npos) include_base.erase (p);
100+
101+ std::vector<std::string> args;
102+ args.emplace_back (capnp_PREFIX " /bin/capnp" );
103+ args.emplace_back (" compile" );
104+ args.emplace_back (" --src-prefix=" );
105+ args.back ().append (src_prefix.cStr (), src_prefix.size ());
106+ for (const auto & import_path : import_paths) {
107+ args.emplace_back (" --import-path=" );
108+ args.back ().append (import_path.cStr (), import_path.size ());
109+ }
110+ args.emplace_back (" --output=" capnp_PREFIX " /bin/capnpc-c++" );
111+ args.emplace_back (src_file);
112+ int pid = fork ();
113+ if (!pid) {
114+ mp::ExecProcess (args);
115+ }
116+ int status = mp::WaitProcess (pid);
117+ if (status) {
118+ throw std::runtime_error (" Invoking " capnp_PREFIX " /bin/capnp failed" );
119+ }
120+
71121 capnp::SchemaParser parser;
72- auto file_schema = parser.parseDiskFile (input_schema, input_schema , import_paths);
122+ auto file_schema = parser.parseDiskFile (src_file, src_file , import_paths);
73123
74- const std::string stem = output_stem;
75- std::ofstream cpp_server (stem + " .capnp.proxy-server.c++" );
76- cpp_server << " // Generated by " PROXY_BIN " from " << input_schema << " \n\n " ;
77- cpp_server << " #include <" << stem << " .capnp.proxy-types.h>\n " ;
124+ std::ofstream cpp_server (output_path + " .proxy-server.c++" );
125+ cpp_server << " // Generated by " PROXY_BIN " from " << src_file << " \n\n " ;
126+ cpp_server << " #include <" << include_path << " .proxy-types.h>\n " ;
78127 cpp_server << " #include <" << PROXY_TYPES << " >\n\n " ;
79128 cpp_server << " namespace mp {\n " ;
80129
81- std::ofstream cpp_client (stem + " .capnp .proxy-client.c++" );
82- cpp_client << " // Generated by " PROXY_BIN " from " << input_schema << " \n\n " ;
83- cpp_client << " #include <" << stem << " .capnp .proxy-types.h>\n " ;
130+ std::ofstream cpp_client (output_path + " .proxy-client.c++" );
131+ cpp_client << " // Generated by " PROXY_BIN " from " << src_file << " \n\n " ;
132+ cpp_client << " #include <" << include_path << " .proxy-types.h>\n " ;
84133 cpp_client << " #include <" << PROXY_TYPES << " >\n\n " ;
85134 cpp_client << " namespace mp {\n " ;
86135
87- std::ofstream cpp_types (stem + " .capnp .proxy-types.c++" );
88- cpp_types << " // Generated by " PROXY_BIN " from " << input_schema << " \n\n " ;
89- cpp_types << " #include <" << stem << " .capnp .proxy-types.h>\n " ;
136+ std::ofstream cpp_types (output_path + " .proxy-types.c++" );
137+ cpp_types << " // Generated by " PROXY_BIN " from " << src_file << " \n\n " ;
138+ cpp_types << " #include <" << include_path << " .proxy-types.h>\n " ;
90139 cpp_types << " #include <" << PROXY_TYPES << " >\n\n " ;
91140 cpp_types << " namespace mp {\n " ;
92141
93- std::string guard = stem ;
142+ std::string guard = output_path ;
94143 std::transform (guard.begin (), guard.end (), guard.begin (), [](unsigned char c) {
95144 return (' 0' <= c && c <= ' 9' ) ? c : (' A' <= c && c <= ' Z' ) ? c : (' a' <= c && c <= ' z' ) ? c - ' a' + ' A' : ' _' ;
96145 });
97146
98- std::ofstream inl (stem + " .capnp .proxy-types.h" );
99- inl << " // Generated by " PROXY_BIN " from " << input_schema << " \n\n " ;
100- inl << " #ifndef " << guard << " _CAPNP_PROXY_TYPES_H \n " ;
101- inl << " #define " << guard << " _CAPNP_PROXY_TYPES_H \n\n " ;
102- inl << " #include <" << stem << " .capnp .proxy.h>\n " ;
103- inl << " #include <" << stem << " -types.h>\n\n " ;
147+ std::ofstream inl (output_path + " .proxy-types.h" );
148+ inl << " // Generated by " PROXY_BIN " from " << src_file << " \n\n " ;
149+ inl << " #ifndef " << guard << " _PROXY_TYPES_H \n " ;
150+ inl << " #define " << guard << " _PROXY_TYPES_H \n\n " ;
151+ inl << " #include <" << include_path << " .proxy.h>\n " ;
152+ inl << " #include <" << include_base << " -types.h>\n\n " ;
104153 inl << " namespace mp {\n " ;
105154
106- std::ofstream h (stem + " .capnp .proxy.h" );
107- h << " // Generated by " PROXY_BIN " from " << input_schema << " \n\n " ;
108- h << " #ifndef " << guard << " _CAPNP_PROXY_H \n " ;
109- h << " #define " << guard << " _CAPNP_PROXY_H \n\n " ;
110- h << " #include <" << stem << " .h>\n " ;
111- h << " #include <" << stem << " .capnp .h>\n " ;
155+ std::ofstream h (output_path + " .proxy.h" );
156+ h << " // Generated by " PROXY_BIN " from " << src_file << " \n\n " ;
157+ h << " #ifndef " << guard << " _PROXY_H \n " ;
158+ h << " #define " << guard << " _PROXY_H \n\n " ;
159+ h << " #include <" << include_path << " .h>\n " ;
160+ h << " #include <" << include_base << " .h>\n " ;
112161 h << " #include <" << PROXY_DECL << " >\n\n " ;
113162 h << " namespace mp {\n " ;
114163
@@ -117,10 +166,10 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
117166 message_namespace = value->getText ();
118167 }
119168
120- std::string output_name = output_stem ;
121- size_t output_slash = output_name .rfind (" /" );
169+ std::string base_name = include_base ;
170+ size_t output_slash = base_name .rfind (" /" );
122171 if (output_slash != std::string::npos) {
123- output_name .erase (0 , output_slash + 1 );
172+ base_name .erase (0 , output_slash + 1 );
124173 }
125174
126175 std::ostringstream methods;
@@ -182,7 +231,7 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
182231 for (const auto field : struc.getFields ()) {
183232 auto field_name = field.getProto ().getName ();
184233 add_accessor (field_name);
185- dec << " using " << Cap (field_name) << " Accessor = Accessor<" << output_name
234+ dec << " using " << Cap (field_name) << " Accessor = Accessor<" << base_name
186235 << " _fields::" << Cap (field_name) << " , FIELD_IN | FIELD_OUT" ;
187236 if (BoxedType (field.getType ())) dec << " | FIELD_BOXED" ;
188237 dec << " >;\n " ;
@@ -385,7 +434,7 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
385434 client_invoke << " MakeClientParam<" ;
386435 }
387436
388- client_invoke << " Accessor<" << output_name << " _fields::" << Cap (field_name) << " , "
437+ client_invoke << " Accessor<" << base_name << " _fields::" << Cap (field_name) << " , "
389438 << field_flags.str () << " >>(" ;
390439
391440 if (field.retval || field.args == 1 ) {
@@ -405,7 +454,7 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
405454 } else {
406455 server_invoke_start << " MakeServerField<" << field.args ;
407456 }
408- server_invoke_start << " , Accessor<" << output_name << " _fields::" << Cap (field_name) << " , "
457+ server_invoke_start << " , Accessor<" << base_name << " _fields::" << Cap (field_name) << " , "
409458 << field_flags.str () << " >>(" ;
410459 server_invoke_end << " )" ;
411460 }
@@ -452,8 +501,8 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
452501 }
453502 }
454503
455- h << methods.str () << " namespace " << output_name << " _fields {\n "
456- << accessors.str () << " } // namespace " << output_name << " _fields\n "
504+ h << methods.str () << " namespace " << base_name << " _fields {\n "
505+ << accessors.str () << " } // namespace " << base_name << " _fields\n "
457506 << dec.str ();
458507
459508 cpp_server << def_server.str ();
@@ -475,13 +524,13 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
475524int main (int argc, char ** argv)
476525{
477526 if (argc < 3 ) {
478- fprintf (stderr, " Usage: " PROXY_BIN " OUTPUT_STEM INPUT_SCHEMA [IMPORT_PATH...]\n " );
527+ fprintf (stderr, " Usage: " PROXY_BIN " SRC_PREFIX SRC_FILE [IMPORT_PATH...]\n " );
479528 exit (1 );
480529 }
481530 std::vector<kj::StringPtr> import_paths;
482- for (size_t i = 3 ; i < argc; ++i) {
531+ for (size_t i = 4 ; i < argc; ++i) {
483532 import_paths.push_back (argv[i]);
484533 }
485- Generate (argv[1 ], argv[2 ], {import_paths.data (), import_paths.size ()});
534+ Generate (argv[1 ], argv[2 ], argv[ 3 ], {import_paths.data (), import_paths.size ()});
486535 return 0 ;
487536}
0 commit comments