2
2
// Distributed under the MIT software license, see the accompanying
3
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
4
5
+ #include < mp/config.h>
6
+ #include < mp/util.h>
7
+
5
8
#include < boost/optional.hpp>
6
9
#include < capnp/schema-parser.h>
7
10
#include < fstream>
@@ -66,49 +69,95 @@ bool BoxedType(const ::capnp::Type& type)
66
69
type.isFloat64 () || type.isEnum ());
67
70
}
68
71
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)
70
76
{
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
+
71
121
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);
73
123
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 " ;
78
127
cpp_server << " #include <" << PROXY_TYPES << " >\n\n " ;
79
128
cpp_server << " namespace mp {\n " ;
80
129
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 " ;
84
133
cpp_client << " #include <" << PROXY_TYPES << " >\n\n " ;
85
134
cpp_client << " namespace mp {\n " ;
86
135
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 " ;
90
139
cpp_types << " #include <" << PROXY_TYPES << " >\n\n " ;
91
140
cpp_types << " namespace mp {\n " ;
92
141
93
- std::string guard = stem ;
142
+ std::string guard = output_path ;
94
143
std::transform (guard.begin (), guard.end (), guard.begin (), [](unsigned char c) {
95
144
return (' 0' <= c && c <= ' 9' ) ? c : (' A' <= c && c <= ' Z' ) ? c : (' a' <= c && c <= ' z' ) ? c - ' a' + ' A' : ' _' ;
96
145
});
97
146
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 " ;
104
153
inl << " namespace mp {\n " ;
105
154
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 " ;
112
161
h << " #include <" << PROXY_DECL << " >\n\n " ;
113
162
h << " namespace mp {\n " ;
114
163
@@ -117,10 +166,10 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
117
166
message_namespace = value->getText ();
118
167
}
119
168
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 (" /" );
122
171
if (output_slash != std::string::npos) {
123
- output_name .erase (0 , output_slash + 1 );
172
+ base_name .erase (0 , output_slash + 1 );
124
173
}
125
174
126
175
std::ostringstream methods;
@@ -182,7 +231,7 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
182
231
for (const auto field : struc.getFields ()) {
183
232
auto field_name = field.getProto ().getName ();
184
233
add_accessor (field_name);
185
- dec << " using " << Cap (field_name) << " Accessor = Accessor<" << output_name
234
+ dec << " using " << Cap (field_name) << " Accessor = Accessor<" << base_name
186
235
<< " _fields::" << Cap (field_name) << " , FIELD_IN | FIELD_OUT" ;
187
236
if (BoxedType (field.getType ())) dec << " | FIELD_BOXED" ;
188
237
dec << " >;\n " ;
@@ -385,7 +434,7 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
385
434
client_invoke << " MakeClientParam<" ;
386
435
}
387
436
388
- client_invoke << " Accessor<" << output_name << " _fields::" << Cap (field_name) << " , "
437
+ client_invoke << " Accessor<" << base_name << " _fields::" << Cap (field_name) << " , "
389
438
<< field_flags.str () << " >>(" ;
390
439
391
440
if (field.retval || field.args == 1 ) {
@@ -405,7 +454,7 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
405
454
} else {
406
455
server_invoke_start << " MakeServerField<" << field.args ;
407
456
}
408
- server_invoke_start << " , Accessor<" << output_name << " _fields::" << Cap (field_name) << " , "
457
+ server_invoke_start << " , Accessor<" << base_name << " _fields::" << Cap (field_name) << " , "
409
458
<< field_flags.str () << " >>(" ;
410
459
server_invoke_end << " )" ;
411
460
}
@@ -452,8 +501,8 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
452
501
}
453
502
}
454
503
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 "
457
506
<< dec.str ();
458
507
459
508
cpp_server << def_server.str ();
@@ -475,13 +524,13 @@ void Generate(kj::StringPtr output_stem, kj::StringPtr input_schema, kj::ArrayPt
475
524
int main (int argc, char ** argv)
476
525
{
477
526
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 " );
479
528
exit (1 );
480
529
}
481
530
std::vector<kj::StringPtr > import_paths;
482
- for (size_t i = 3 ; i < argc; ++i) {
531
+ for (size_t i = 4 ; i < argc; ++i) {
483
532
import_paths.push_back (argv[i]);
484
533
}
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 ()});
486
535
return 0 ;
487
536
}
0 commit comments