main.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Debug.h>
  7. #include <AK/Function.h>
  8. #include <AK/GenericLexer.h>
  9. #include <AK/HashMap.h>
  10. #include <AK/SourceGenerator.h>
  11. #include <AK/StringBuilder.h>
  12. #include <LibCore/ArgsParser.h>
  13. #include <LibCore/File.h>
  14. #include <LibMain/Main.h>
  15. #include <ctype.h>
  16. #include <stdio.h>
  17. struct Parameter {
  18. Vector<DeprecatedString> attributes;
  19. DeprecatedString type;
  20. DeprecatedString name;
  21. };
  22. static DeprecatedString pascal_case(DeprecatedString const& identifier)
  23. {
  24. StringBuilder builder;
  25. bool was_new_word = true;
  26. for (auto ch : identifier) {
  27. if (ch == '_') {
  28. was_new_word = true;
  29. continue;
  30. }
  31. if (was_new_word) {
  32. builder.append(toupper(ch));
  33. was_new_word = false;
  34. } else
  35. builder.append(ch);
  36. }
  37. return builder.to_deprecated_string();
  38. }
  39. struct Message {
  40. DeprecatedString name;
  41. bool is_synchronous { false };
  42. Vector<Parameter> inputs;
  43. Vector<Parameter> outputs;
  44. DeprecatedString response_name() const
  45. {
  46. StringBuilder builder;
  47. builder.append(pascal_case(name));
  48. builder.append("Response"sv);
  49. return builder.to_deprecated_string();
  50. }
  51. };
  52. struct Endpoint {
  53. Vector<DeprecatedString> includes;
  54. DeprecatedString name;
  55. u32 magic;
  56. Vector<Message> messages;
  57. };
  58. static bool is_primitive_type(DeprecatedString const& type)
  59. {
  60. return type.is_one_of("u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "size_t", "bool", "double", "float", "int", "unsigned", "unsigned int");
  61. }
  62. static bool is_simple_type(DeprecatedString const& type)
  63. {
  64. // Small types that it makes sense just to pass by value.
  65. return type.is_one_of("Gfx::Color", "Gfx::IntPoint", "Gfx::FloatPoint", "Web::DevicePixelPoint", "Gfx::IntSize", "Gfx::FloatSize", "Web::DevicePixelSize", "Core::File::OpenMode");
  66. }
  67. static bool is_primitive_or_simple_type(DeprecatedString const& type)
  68. {
  69. return is_primitive_type(type) || is_simple_type(type);
  70. }
  71. static DeprecatedString message_name(DeprecatedString const& endpoint, DeprecatedString const& message, bool is_response)
  72. {
  73. StringBuilder builder;
  74. builder.append("Messages::"sv);
  75. builder.append(endpoint);
  76. builder.append("::"sv);
  77. builder.append(pascal_case(message));
  78. if (is_response)
  79. builder.append("Response"sv);
  80. return builder.to_deprecated_string();
  81. }
  82. Vector<Endpoint> parse(ByteBuffer const& file_contents)
  83. {
  84. GenericLexer lexer(file_contents);
  85. Vector<Endpoint> endpoints;
  86. auto assert_specific = [&lexer](char ch) {
  87. if (lexer.peek() != ch)
  88. warnln("assert_specific: wanted '{}', but got '{}' at index {}", ch, lexer.peek(), lexer.tell());
  89. bool saw_expected = lexer.consume_specific(ch);
  90. VERIFY(saw_expected);
  91. };
  92. auto consume_whitespace = [&lexer] {
  93. lexer.ignore_while([](char ch) { return isspace(ch); });
  94. if (lexer.peek() == '/' && lexer.peek(1) == '/')
  95. lexer.ignore_until('\n');
  96. };
  97. auto parse_parameter = [&](Vector<Parameter>& storage) {
  98. for (;;) {
  99. Parameter parameter;
  100. if (lexer.is_eof()) {
  101. warnln("EOF when parsing parameter");
  102. VERIFY_NOT_REACHED();
  103. }
  104. consume_whitespace();
  105. if (lexer.peek() == ')')
  106. break;
  107. if (lexer.consume_specific('[')) {
  108. for (;;) {
  109. if (lexer.consume_specific(']')) {
  110. consume_whitespace();
  111. break;
  112. }
  113. if (lexer.consume_specific(',')) {
  114. consume_whitespace();
  115. }
  116. auto attribute = lexer.consume_until([](char ch) { return ch == ']' || ch == ','; });
  117. parameter.attributes.append(attribute);
  118. consume_whitespace();
  119. }
  120. }
  121. // FIXME: This is not entirely correct. Types can have spaces, for example `HashMap<int, DeprecatedString>`.
  122. // Maybe we should use LibCpp::Parser for parsing types.
  123. parameter.type = lexer.consume_until([](char ch) { return isspace(ch); });
  124. if (parameter.type.ends_with(',')) {
  125. warnln("Parameter type '{}' looks invalid!", parameter.type);
  126. warnln("Note that templates must not include spaces.");
  127. VERIFY_NOT_REACHED();
  128. }
  129. VERIFY(!lexer.is_eof());
  130. consume_whitespace();
  131. parameter.name = lexer.consume_until([](char ch) { return isspace(ch) || ch == ',' || ch == ')'; });
  132. consume_whitespace();
  133. storage.append(move(parameter));
  134. if (lexer.consume_specific(','))
  135. continue;
  136. if (lexer.peek() == ')')
  137. break;
  138. }
  139. };
  140. auto parse_parameters = [&](Vector<Parameter>& storage) {
  141. for (;;) {
  142. consume_whitespace();
  143. parse_parameter(storage);
  144. consume_whitespace();
  145. if (lexer.consume_specific(','))
  146. continue;
  147. if (lexer.peek() == ')')
  148. break;
  149. }
  150. };
  151. auto parse_message = [&] {
  152. Message message;
  153. consume_whitespace();
  154. message.name = lexer.consume_until([](char ch) { return isspace(ch) || ch == '('; });
  155. consume_whitespace();
  156. assert_specific('(');
  157. parse_parameters(message.inputs);
  158. assert_specific(')');
  159. consume_whitespace();
  160. assert_specific('=');
  161. auto type = lexer.consume();
  162. if (type == '>')
  163. message.is_synchronous = true;
  164. else if (type == '|')
  165. message.is_synchronous = false;
  166. else
  167. VERIFY_NOT_REACHED();
  168. consume_whitespace();
  169. if (message.is_synchronous) {
  170. assert_specific('(');
  171. parse_parameters(message.outputs);
  172. assert_specific(')');
  173. }
  174. consume_whitespace();
  175. endpoints.last().messages.append(move(message));
  176. };
  177. auto parse_messages = [&] {
  178. for (;;) {
  179. consume_whitespace();
  180. if (lexer.peek() == '}')
  181. break;
  182. parse_message();
  183. consume_whitespace();
  184. }
  185. };
  186. auto parse_include = [&] {
  187. DeprecatedString include;
  188. consume_whitespace();
  189. include = lexer.consume_while([](char ch) { return ch != '\n'; });
  190. consume_whitespace();
  191. endpoints.last().includes.append(move(include));
  192. };
  193. auto parse_includes = [&] {
  194. for (;;) {
  195. consume_whitespace();
  196. if (lexer.peek() != '#')
  197. break;
  198. parse_include();
  199. consume_whitespace();
  200. }
  201. };
  202. auto parse_endpoint = [&] {
  203. endpoints.empend();
  204. consume_whitespace();
  205. parse_includes();
  206. consume_whitespace();
  207. lexer.consume_specific("endpoint");
  208. consume_whitespace();
  209. endpoints.last().name = lexer.consume_while([](char ch) { return !isspace(ch); });
  210. endpoints.last().magic = Traits<DeprecatedString>::hash(endpoints.last().name);
  211. consume_whitespace();
  212. assert_specific('{');
  213. parse_messages();
  214. assert_specific('}');
  215. consume_whitespace();
  216. };
  217. while (lexer.tell() < file_contents.size())
  218. parse_endpoint();
  219. return endpoints;
  220. }
  221. HashMap<DeprecatedString, int> build_message_ids_for_endpoint(SourceGenerator generator, Endpoint const& endpoint)
  222. {
  223. HashMap<DeprecatedString, int> message_ids;
  224. generator.appendln("\nenum class MessageID : i32 {");
  225. for (auto const& message : endpoint.messages) {
  226. message_ids.set(message.name, message_ids.size() + 1);
  227. generator.set("message.pascal_name", pascal_case(message.name));
  228. generator.set("message.id", DeprecatedString::number(message_ids.size()));
  229. generator.appendln(" @message.pascal_name@ = @message.id@,");
  230. if (message.is_synchronous) {
  231. message_ids.set(message.response_name(), message_ids.size() + 1);
  232. generator.set("message.pascal_name", pascal_case(message.response_name()));
  233. generator.set("message.id", DeprecatedString::number(message_ids.size()));
  234. generator.appendln(" @message.pascal_name@ = @message.id@,");
  235. }
  236. }
  237. generator.appendln("};");
  238. return message_ids;
  239. }
  240. DeprecatedString constructor_for_message(DeprecatedString const& name, Vector<Parameter> const& parameters)
  241. {
  242. StringBuilder builder;
  243. builder.append(name);
  244. if (parameters.is_empty()) {
  245. builder.append("() {}"sv);
  246. return builder.to_deprecated_string();
  247. }
  248. builder.append('(');
  249. for (size_t i = 0; i < parameters.size(); ++i) {
  250. auto const& parameter = parameters[i];
  251. builder.appendff("{} {}", parameter.type, parameter.name);
  252. if (i != parameters.size() - 1)
  253. builder.append(", "sv);
  254. }
  255. builder.append(") : "sv);
  256. for (size_t i = 0; i < parameters.size(); ++i) {
  257. auto const& parameter = parameters[i];
  258. builder.appendff("m_{}(move({}))", parameter.name, parameter.name);
  259. if (i != parameters.size() - 1)
  260. builder.append(", "sv);
  261. }
  262. builder.append(" {}"sv);
  263. return builder.to_deprecated_string();
  264. }
  265. void do_message(SourceGenerator message_generator, DeprecatedString const& name, Vector<Parameter> const& parameters, DeprecatedString const& response_type = {})
  266. {
  267. auto pascal_name = pascal_case(name);
  268. message_generator.set("message.name", name);
  269. message_generator.set("message.pascal_name", pascal_name);
  270. message_generator.set("message.response_type", response_type);
  271. message_generator.set("message.constructor", constructor_for_message(pascal_name, parameters));
  272. message_generator.appendln(R"~~~(
  273. class @message.pascal_name@ final : public IPC::Message {
  274. public:)~~~");
  275. if (!response_type.is_empty())
  276. message_generator.appendln(R"~~~(
  277. typedef class @message.response_type@ ResponseType;)~~~");
  278. message_generator.appendln(R"~~~(
  279. @message.pascal_name@(decltype(nullptr)) : m_ipc_message_valid(false) { }
  280. @message.pascal_name@(@message.pascal_name@ const&) = default;
  281. @message.pascal_name@(@message.pascal_name@&&) = default;
  282. @message.pascal_name@& operator=(@message.pascal_name@ const&) = default;
  283. @message.constructor@)~~~");
  284. if (parameters.size() == 1) {
  285. auto const& parameter = parameters[0];
  286. message_generator.set("parameter.type"sv, parameter.type);
  287. message_generator.set("parameter.name"sv, parameter.name);
  288. message_generator.appendln(R"~~~(
  289. template <typename WrappedReturnType>
  290. requires(!SameAs<WrappedReturnType, @parameter.type@>)
  291. @message.pascal_name@(WrappedReturnType&& value)
  292. : m_@parameter.name@(forward<WrappedReturnType>(value))
  293. {
  294. })~~~");
  295. }
  296. message_generator.appendln(R"~~~(
  297. virtual ~@message.pascal_name@() override {}
  298. virtual u32 endpoint_magic() const override { return @endpoint.magic@; }
  299. virtual i32 message_id() const override { return (int)MessageID::@message.pascal_name@; }
  300. static i32 static_message_id() { return (int)MessageID::@message.pascal_name@; }
  301. virtual const char* message_name() const override { return "@endpoint.name@::@message.pascal_name@"; }
  302. static ErrorOr<NonnullOwnPtr<@message.pascal_name@>> decode(Stream& stream, Core::LocalSocket& socket)
  303. {
  304. IPC::Decoder decoder { stream, socket };)~~~");
  305. for (auto const& parameter : parameters) {
  306. auto parameter_generator = message_generator.fork();
  307. parameter_generator.set("parameter.type", parameter.type);
  308. parameter_generator.set("parameter.name", parameter.name);
  309. if (parameter.type == "bool")
  310. parameter_generator.set("parameter.initial_value", "false");
  311. else
  312. parameter_generator.set("parameter.initial_value", "{}");
  313. parameter_generator.appendln(R"~~~(
  314. auto @parameter.name@ = TRY((decoder.decode<@parameter.type@>()));)~~~");
  315. if (parameter.attributes.contains_slow("UTF8")) {
  316. parameter_generator.appendln(R"~~~(
  317. if (!Utf8View(@parameter.name@).validate())
  318. return Error::from_string_literal("Decoded @parameter.name@ is invalid UTF-8");)~~~");
  319. }
  320. }
  321. StringBuilder builder;
  322. for (size_t i = 0; i < parameters.size(); ++i) {
  323. auto const& parameter = parameters[i];
  324. builder.appendff("move({})", parameter.name);
  325. if (i != parameters.size() - 1)
  326. builder.append(", "sv);
  327. }
  328. message_generator.set("message.constructor_call_parameters", builder.to_deprecated_string());
  329. message_generator.appendln(R"~~~(
  330. return make<@message.pascal_name@>(@message.constructor_call_parameters@);
  331. })~~~");
  332. message_generator.appendln(R"~~~(
  333. virtual bool valid() const override { return m_ipc_message_valid; }
  334. virtual ErrorOr<IPC::MessageBuffer> encode() const override
  335. {
  336. VERIFY(valid());
  337. IPC::MessageBuffer buffer;
  338. IPC::Encoder stream(buffer);
  339. TRY(stream.encode(endpoint_magic()));
  340. TRY(stream.encode((int)MessageID::@message.pascal_name@));)~~~");
  341. for (auto const& parameter : parameters) {
  342. auto parameter_generator = message_generator.fork();
  343. parameter_generator.set("parameter.name", parameter.name);
  344. parameter_generator.appendln(R"~~~(
  345. TRY(stream.encode(m_@parameter.name@));)~~~");
  346. }
  347. message_generator.appendln(R"~~~(
  348. return buffer;
  349. })~~~");
  350. for (auto const& parameter : parameters) {
  351. auto parameter_generator = message_generator.fork();
  352. parameter_generator.set("parameter.type", parameter.type);
  353. parameter_generator.set("parameter.name", parameter.name);
  354. parameter_generator.appendln(R"~~~(
  355. const @parameter.type@& @parameter.name@() const { return m_@parameter.name@; }
  356. @parameter.type@ take_@parameter.name@() { return move(m_@parameter.name@); })~~~");
  357. }
  358. message_generator.appendln(R"~~~(
  359. private:
  360. bool m_ipc_message_valid { true };)~~~");
  361. for (auto const& parameter : parameters) {
  362. auto parameter_generator = message_generator.fork();
  363. parameter_generator.set("parameter.type", parameter.type);
  364. parameter_generator.set("parameter.name", parameter.name);
  365. parameter_generator.appendln(R"~~~(
  366. @parameter.type@ m_@parameter.name@ {};)~~~");
  367. }
  368. message_generator.appendln("\n};");
  369. }
  370. void do_message_for_proxy(SourceGenerator message_generator, Endpoint const& endpoint, Message const& message)
  371. {
  372. auto do_implement_proxy = [&](DeprecatedString const& name, Vector<Parameter> const& parameters, bool is_synchronous, bool is_try) {
  373. DeprecatedString return_type = "void";
  374. if (is_synchronous) {
  375. if (message.outputs.size() == 1)
  376. return_type = message.outputs[0].type;
  377. else if (!message.outputs.is_empty())
  378. return_type = message_name(endpoint.name, message.name, true);
  379. }
  380. DeprecatedString inner_return_type = return_type;
  381. if (is_try)
  382. return_type = DeprecatedString::formatted("IPC::IPCErrorOr<{}>", return_type);
  383. message_generator.set("message.name", message.name);
  384. message_generator.set("message.pascal_name", pascal_case(message.name));
  385. message_generator.set("message.complex_return_type", return_type);
  386. message_generator.set("async_prefix_maybe", is_synchronous ? "" : "async_");
  387. message_generator.set("try_prefix_maybe", is_try ? "try_" : "");
  388. message_generator.set("handler_name", name);
  389. message_generator.appendln(R"~~~(
  390. @message.complex_return_type@ @try_prefix_maybe@@async_prefix_maybe@@handler_name@()~~~");
  391. for (size_t i = 0; i < parameters.size(); ++i) {
  392. auto const& parameter = parameters[i];
  393. auto argument_generator = message_generator.fork();
  394. argument_generator.set("argument.type", parameter.type);
  395. argument_generator.set("argument.name", parameter.name);
  396. argument_generator.append("@argument.type@ @argument.name@");
  397. if (i != parameters.size() - 1)
  398. argument_generator.append(", ");
  399. }
  400. message_generator.append(") {");
  401. if (is_synchronous && !is_try) {
  402. if (return_type != "void") {
  403. message_generator.append(R"~~~(
  404. return )~~~");
  405. if (message.outputs.size() != 1)
  406. message_generator.append("move(*");
  407. } else {
  408. message_generator.append(R"~~~(
  409. (void) )~~~");
  410. }
  411. message_generator.append("m_connection.template send_sync<Messages::@endpoint.name@::@message.pascal_name@>(");
  412. } else if (is_try) {
  413. message_generator.append(R"~~~(
  414. auto result = m_connection.template send_sync_but_allow_failure<Messages::@endpoint.name@::@message.pascal_name@>()~~~");
  415. } else {
  416. message_generator.append(R"~~~(
  417. // FIXME: Handle post_message failures.
  418. (void) m_connection.post_message(Messages::@endpoint.name@::@message.pascal_name@ { )~~~");
  419. }
  420. for (size_t i = 0; i < parameters.size(); ++i) {
  421. auto const& parameter = parameters[i];
  422. auto argument_generator = message_generator.fork();
  423. argument_generator.set("argument.name", parameter.name);
  424. if (is_primitive_or_simple_type(parameters[i].type))
  425. argument_generator.append("@argument.name@");
  426. else
  427. argument_generator.append("move(@argument.name@)");
  428. if (i != parameters.size() - 1)
  429. argument_generator.append(", ");
  430. }
  431. if (is_synchronous && !is_try) {
  432. if (return_type != "void") {
  433. message_generator.append(")");
  434. }
  435. if (message.outputs.size() == 1) {
  436. message_generator.append("->take_");
  437. message_generator.append(message.outputs[0].name);
  438. message_generator.append("()");
  439. } else
  440. message_generator.append(")");
  441. message_generator.append(";");
  442. } else if (is_try) {
  443. message_generator.append(R"~~~();
  444. if (!result)
  445. return IPC::ErrorCode::PeerDisconnected;)~~~");
  446. if (inner_return_type != "void") {
  447. message_generator.appendln(R"~~~(
  448. return move(*result);)~~~");
  449. } else {
  450. message_generator.appendln(R"~~~(
  451. return { };)~~~");
  452. }
  453. } else {
  454. message_generator.appendln(" });");
  455. }
  456. message_generator.appendln(R"~~~(
  457. })~~~");
  458. };
  459. do_implement_proxy(message.name, message.inputs, message.is_synchronous, false);
  460. if (message.is_synchronous) {
  461. do_implement_proxy(message.name, message.inputs, false, false);
  462. do_implement_proxy(message.name, message.inputs, true, true);
  463. }
  464. }
  465. void build_endpoint(SourceGenerator generator, Endpoint const& endpoint)
  466. {
  467. generator.set("endpoint.name", endpoint.name);
  468. generator.set("endpoint.magic", DeprecatedString::number(endpoint.magic));
  469. generator.appendln("\nnamespace Messages::@endpoint.name@ {");
  470. HashMap<DeprecatedString, int> message_ids = build_message_ids_for_endpoint(generator.fork(), endpoint);
  471. for (auto const& message : endpoint.messages) {
  472. DeprecatedString response_name;
  473. if (message.is_synchronous) {
  474. response_name = message.response_name();
  475. do_message(generator.fork(), response_name, message.outputs);
  476. }
  477. do_message(generator.fork(), message.name, message.inputs, response_name);
  478. }
  479. generator.appendln(R"~~~(
  480. } // namespace Messages::@endpoint.name@
  481. template<typename LocalEndpoint, typename PeerEndpoint>
  482. class @endpoint.name@Proxy {
  483. public:
  484. // Used to disambiguate the constructor call.
  485. struct Tag { };
  486. @endpoint.name@Proxy(IPC::Connection<LocalEndpoint, PeerEndpoint>& connection, Tag)
  487. : m_connection(connection)
  488. { })~~~");
  489. for (auto const& message : endpoint.messages)
  490. do_message_for_proxy(generator.fork(), endpoint, message);
  491. generator.appendln(R"~~~(
  492. private:
  493. IPC::Connection<LocalEndpoint, PeerEndpoint>& m_connection;
  494. };)~~~");
  495. generator.append(R"~~~(
  496. template<typename LocalEndpoint, typename PeerEndpoint>
  497. class @endpoint.name@Proxy;
  498. class @endpoint.name@Stub;
  499. class @endpoint.name@Endpoint {
  500. public:
  501. template<typename LocalEndpoint>
  502. using Proxy = @endpoint.name@Proxy<LocalEndpoint, @endpoint.name@Endpoint>;
  503. using Stub = @endpoint.name@Stub;
  504. static u32 static_magic() { return @endpoint.magic@; }
  505. static ErrorOr<NonnullOwnPtr<IPC::Message>> decode_message(ReadonlyBytes buffer, [[maybe_unused]] Core::LocalSocket& socket)
  506. {
  507. FixedMemoryStream stream { buffer };
  508. auto message_endpoint_magic = TRY(stream.read_value<u32>());)~~~");
  509. generator.append(R"~~~(
  510. if (message_endpoint_magic != @endpoint.magic@) {)~~~");
  511. if constexpr (GENERATE_DEBUG) {
  512. generator.append(R"~~~(
  513. dbgln("@endpoint.name@: Endpoint magic number message_endpoint_magic != @endpoint.magic@, not my message! (the other endpoint may have handled it)");)~~~");
  514. }
  515. generator.appendln(R"~~~(
  516. return Error::from_string_literal("Endpoint magic number mismatch, not my message!");
  517. }
  518. auto message_id = TRY(stream.read_value<i32>());)~~~");
  519. generator.appendln(R"~~~(
  520. switch (message_id) {)~~~");
  521. for (auto const& message : endpoint.messages) {
  522. auto do_decode_message = [&](DeprecatedString const& name) {
  523. auto message_generator = generator.fork();
  524. message_generator.set("message.name", name);
  525. message_generator.set("message.pascal_name", pascal_case(name));
  526. message_generator.append(R"~~~(
  527. case (int)Messages::@endpoint.name@::MessageID::@message.pascal_name@:
  528. return TRY(Messages::@endpoint.name@::@message.pascal_name@::decode(stream, socket));)~~~");
  529. };
  530. do_decode_message(message.name);
  531. if (message.is_synchronous)
  532. do_decode_message(message.response_name());
  533. }
  534. generator.append(R"~~~(
  535. default:)~~~");
  536. if constexpr (GENERATE_DEBUG) {
  537. generator.append(R"~~~(
  538. dbgln("Failed to decode @endpoint.name@.({})", message_id);)~~~");
  539. }
  540. generator.appendln(R"~~~(
  541. return Error::from_string_literal("Failed to decode @endpoint.name@ message");
  542. })~~~");
  543. generator.appendln(R"~~~(
  544. VERIFY_NOT_REACHED();
  545. }
  546. };
  547. class @endpoint.name@Stub : public IPC::Stub {
  548. public:
  549. @endpoint.name@Stub() { }
  550. virtual ~@endpoint.name@Stub() override { }
  551. virtual u32 magic() const override { return @endpoint.magic@; }
  552. virtual DeprecatedString name() const override { return "@endpoint.name@"; }
  553. virtual ErrorOr<OwnPtr<IPC::MessageBuffer>> handle(const IPC::Message& message) override
  554. {
  555. switch (message.message_id()) {)~~~");
  556. for (auto const& message : endpoint.messages) {
  557. auto do_handle_message = [&](DeprecatedString const& name, Vector<Parameter> const& parameters, bool returns_something) {
  558. auto message_generator = generator.fork();
  559. StringBuilder argument_generator;
  560. for (size_t i = 0; i < parameters.size(); ++i) {
  561. auto const& parameter = parameters[i];
  562. argument_generator.append("request."sv);
  563. argument_generator.append(parameter.name);
  564. argument_generator.append("()"sv);
  565. if (i != parameters.size() - 1)
  566. argument_generator.append(", "sv);
  567. }
  568. message_generator.set("message.pascal_name", pascal_case(name));
  569. message_generator.set("message.response_type", pascal_case(message.response_name()));
  570. message_generator.set("handler_name", name);
  571. message_generator.set("arguments", argument_generator.to_deprecated_string());
  572. message_generator.appendln(R"~~~(
  573. case (int)Messages::@endpoint.name@::MessageID::@message.pascal_name@: {)~~~");
  574. if (returns_something) {
  575. if (message.outputs.is_empty()) {
  576. message_generator.appendln(R"~~~(
  577. [[maybe_unused]] auto& request = static_cast<const Messages::@endpoint.name@::@message.pascal_name@&>(message);
  578. @handler_name@(@arguments@);
  579. auto response = Messages::@endpoint.name@::@message.response_type@ { };
  580. return make<IPC::MessageBuffer>(TRY(response.encode()));)~~~");
  581. } else {
  582. message_generator.appendln(R"~~~(
  583. [[maybe_unused]] auto& request = static_cast<const Messages::@endpoint.name@::@message.pascal_name@&>(message);
  584. auto response = @handler_name@(@arguments@);
  585. if (!response.valid())
  586. return Error::from_string_literal("Failed to handle @endpoint.name@::@message.pascal_name@ message");
  587. return make<IPC::MessageBuffer>(TRY(response.encode()));)~~~");
  588. }
  589. } else {
  590. message_generator.appendln(R"~~~(
  591. [[maybe_unused]] auto& request = static_cast<const Messages::@endpoint.name@::@message.pascal_name@&>(message);
  592. @handler_name@(@arguments@);
  593. return nullptr;)~~~");
  594. }
  595. message_generator.appendln(R"~~~(
  596. })~~~");
  597. };
  598. do_handle_message(message.name, message.inputs, message.is_synchronous);
  599. }
  600. generator.appendln(R"~~~(
  601. default:
  602. return Error::from_string_literal("Unknown message ID for @endpoint.name@ endpoint");
  603. }
  604. })~~~");
  605. for (auto const& message : endpoint.messages) {
  606. auto message_generator = generator.fork();
  607. auto do_handle_message_decl = [&](DeprecatedString const& name, Vector<Parameter> const& parameters, bool is_response) {
  608. DeprecatedString return_type = "void";
  609. if (message.is_synchronous && !message.outputs.is_empty() && !is_response)
  610. return_type = message_name(endpoint.name, message.name, true);
  611. message_generator.set("message.complex_return_type", return_type);
  612. message_generator.set("handler_name", name);
  613. message_generator.appendln(R"~~~(
  614. virtual @message.complex_return_type@ @handler_name@()~~~");
  615. auto make_argument_type = [](DeprecatedString const& type) {
  616. StringBuilder builder;
  617. bool const_ref = !is_primitive_or_simple_type(type);
  618. builder.append(type);
  619. if (const_ref)
  620. builder.append(" const&"sv);
  621. return builder.to_deprecated_string();
  622. };
  623. for (size_t i = 0; i < parameters.size(); ++i) {
  624. auto const& parameter = parameters[i];
  625. auto argument_generator = message_generator.fork();
  626. argument_generator.set("argument.type", make_argument_type(parameter.type));
  627. argument_generator.set("argument.name", parameter.name);
  628. argument_generator.append("[[maybe_unused]] @argument.type@ @argument.name@");
  629. if (i != parameters.size() - 1)
  630. argument_generator.append(", ");
  631. }
  632. if (is_response) {
  633. message_generator.append(") { };");
  634. } else {
  635. message_generator.appendln(") = 0;");
  636. }
  637. };
  638. do_handle_message_decl(message.name, message.inputs, false);
  639. }
  640. generator.appendln(R"~~~(
  641. private:
  642. };
  643. #if defined(AK_COMPILER_CLANG)
  644. #pragma clang diagnostic pop
  645. #endif)~~~");
  646. }
  647. void build(StringBuilder& builder, Vector<Endpoint> const& endpoints)
  648. {
  649. SourceGenerator generator { builder };
  650. generator.appendln("#pragma once");
  651. // This must occur before LibIPC/Decoder.h
  652. for (auto const& endpoint : endpoints) {
  653. for (auto const& include : endpoint.includes) {
  654. generator.appendln(include);
  655. }
  656. }
  657. generator.appendln(R"~~~(#include <AK/Error.h>
  658. #include <AK/MemoryStream.h>
  659. #include <AK/OwnPtr.h>
  660. #include <AK/Result.h>
  661. #include <AK/Utf8View.h>
  662. #include <LibIPC/Connection.h>
  663. #include <LibIPC/Decoder.h>
  664. #include <LibIPC/Encoder.h>
  665. #include <LibIPC/File.h>
  666. #include <LibIPC/Message.h>
  667. #include <LibIPC/Stub.h>
  668. #if defined(AK_COMPILER_CLANG)
  669. #pragma clang diagnostic push
  670. #pragma clang diagnostic ignored "-Wdefaulted-function-deleted"
  671. #endif)~~~");
  672. for (auto const& endpoint : endpoints)
  673. build_endpoint(generator.fork(), endpoint);
  674. }
  675. ErrorOr<int> serenity_main(Main::Arguments arguments)
  676. {
  677. StringView ipc_file;
  678. StringView output_file = "-"sv;
  679. Core::ArgsParser parser;
  680. parser.add_positional_argument(ipc_file, "IPC endpoint definition file", "input");
  681. parser.add_option(output_file, "Place to write file", "output", 'o', "output-file");
  682. parser.parse(arguments);
  683. auto output = TRY(Core::File::open_file_or_standard_stream(output_file, Core::File::OpenMode::Write));
  684. auto file = TRY(Core::File::open(ipc_file, Core::File::OpenMode::Read));
  685. auto file_contents = TRY(file->read_until_eof());
  686. auto endpoints = parse(file_contents);
  687. StringBuilder builder;
  688. build(builder, endpoints);
  689. TRY(output->write_until_depleted(builder.string_view().bytes()));
  690. if constexpr (GENERATE_DEBUG) {
  691. for (auto& endpoint : endpoints) {
  692. warnln("Endpoint '{}' (magic: {})", endpoint.name, endpoint.magic);
  693. for (auto& message : endpoint.messages) {
  694. warnln(" Message: '{}'", message.name);
  695. warnln(" Sync: {}", message.is_synchronous);
  696. warnln(" Inputs:");
  697. for (auto& parameter : message.inputs)
  698. warnln(" Parameter: {} ({})", parameter.name, parameter.type);
  699. if (message.inputs.is_empty())
  700. warnln(" (none)");
  701. if (message.is_synchronous) {
  702. warnln(" Outputs:");
  703. for (auto& parameter : message.outputs)
  704. warnln(" Parameter: {} ({})", parameter.name, parameter.type);
  705. if (message.outputs.is_empty())
  706. warnln(" (none)");
  707. }
  708. }
  709. }
  710. }
  711. return 0;
  712. }