main.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  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/File.h>
  13. #include <ctype.h>
  14. #include <stdio.h>
  15. #ifndef GENERATE_DEBUG_CODE
  16. # define GENERATE_DEBUG_CODE 0
  17. #endif
  18. struct Parameter {
  19. Vector<String> attributes;
  20. String type;
  21. String name;
  22. };
  23. struct Message {
  24. String name;
  25. bool is_synchronous { false };
  26. Vector<Parameter> inputs;
  27. Vector<Parameter> outputs;
  28. String response_name() const
  29. {
  30. StringBuilder builder;
  31. builder.append(name);
  32. builder.append("Response");
  33. return builder.to_string();
  34. }
  35. };
  36. struct Endpoint {
  37. String name;
  38. u32 magic;
  39. Vector<Message> messages;
  40. };
  41. int main(int argc, char** argv)
  42. {
  43. if (argc != 2) {
  44. outln("usage: {} <IPC endpoint definition file>", argv[0]);
  45. return 0;
  46. }
  47. auto file = Core::File::construct(argv[1]);
  48. if (!file->open(Core::IODevice::ReadOnly)) {
  49. warnln("Error: Cannot open {}: {}", argv[1], file->error_string());
  50. return 1;
  51. }
  52. auto file_contents = file->read_all();
  53. GenericLexer lexer(file_contents);
  54. Vector<Endpoint> endpoints;
  55. auto assert_specific = [&](char ch) {
  56. if (lexer.peek() != ch)
  57. warnln("assert_specific: wanted '{}', but got '{}' at index {}", ch, lexer.peek(), lexer.tell());
  58. bool saw_expected = lexer.consume_specific(ch);
  59. VERIFY(saw_expected);
  60. };
  61. auto consume_whitespace = [&] {
  62. lexer.ignore_while([](char ch) { return isspace(ch); });
  63. if (lexer.peek() == '/' && lexer.peek(1) == '/')
  64. lexer.ignore_until([](char ch) { return ch == '\n'; });
  65. };
  66. auto parse_parameter = [&](Vector<Parameter>& storage) {
  67. for (;;) {
  68. Parameter parameter;
  69. consume_whitespace();
  70. if (lexer.peek() == ')')
  71. break;
  72. if (lexer.consume_specific('[')) {
  73. for (;;) {
  74. if (lexer.consume_specific(']')) {
  75. consume_whitespace();
  76. break;
  77. }
  78. if (lexer.consume_specific(',')) {
  79. consume_whitespace();
  80. }
  81. auto attribute = lexer.consume_until([](char ch) { return ch == ']' || ch == ','; });
  82. parameter.attributes.append(attribute);
  83. consume_whitespace();
  84. }
  85. }
  86. parameter.type = lexer.consume_until([](char ch) { return isspace(ch); });
  87. consume_whitespace();
  88. parameter.name = lexer.consume_until([](char ch) { return isspace(ch) || ch == ',' || ch == ')'; });
  89. consume_whitespace();
  90. storage.append(move(parameter));
  91. if (lexer.consume_specific(','))
  92. continue;
  93. if (lexer.peek() == ')')
  94. break;
  95. }
  96. };
  97. auto parse_parameters = [&](Vector<Parameter>& storage) {
  98. for (;;) {
  99. consume_whitespace();
  100. parse_parameter(storage);
  101. consume_whitespace();
  102. if (lexer.consume_specific(','))
  103. continue;
  104. if (lexer.peek() == ')')
  105. break;
  106. }
  107. };
  108. auto parse_message = [&] {
  109. Message message;
  110. consume_whitespace();
  111. message.name = lexer.consume_until([](char ch) { return isspace(ch) || ch == '('; });
  112. consume_whitespace();
  113. assert_specific('(');
  114. parse_parameters(message.inputs);
  115. assert_specific(')');
  116. consume_whitespace();
  117. assert_specific('=');
  118. auto type = lexer.consume();
  119. if (type == '>')
  120. message.is_synchronous = true;
  121. else if (type == '|')
  122. message.is_synchronous = false;
  123. else
  124. VERIFY_NOT_REACHED();
  125. consume_whitespace();
  126. if (message.is_synchronous) {
  127. assert_specific('(');
  128. parse_parameters(message.outputs);
  129. assert_specific(')');
  130. }
  131. consume_whitespace();
  132. endpoints.last().messages.append(move(message));
  133. };
  134. auto parse_messages = [&] {
  135. for (;;) {
  136. consume_whitespace();
  137. parse_message();
  138. consume_whitespace();
  139. if (lexer.peek() == '}')
  140. break;
  141. }
  142. };
  143. auto parse_endpoint = [&] {
  144. endpoints.empend();
  145. consume_whitespace();
  146. lexer.consume_specific("endpoint");
  147. consume_whitespace();
  148. endpoints.last().name = lexer.consume_while([](char ch) { return !isspace(ch); });
  149. endpoints.last().magic = Traits<String>::hash(endpoints.last().name);
  150. consume_whitespace();
  151. if (lexer.peek() == '[') {
  152. // This only supports a single parameter for now, and adding multiple
  153. // endpoint parameter support is left as an exercise for the reader. :^)
  154. lexer.consume_specific('[');
  155. consume_whitespace();
  156. auto parameter = lexer.consume_while([](char ch) { return !isspace(ch) && ch != '='; });
  157. consume_whitespace();
  158. assert_specific('=');
  159. consume_whitespace();
  160. if (parameter == "magic") {
  161. // "magic" overwrites the default magic with a hardcoded one.
  162. auto magic_string = lexer.consume_while([](char ch) { return !isspace(ch) && ch != ']'; });
  163. endpoints.last().magic = magic_string.to_uint().value();
  164. } else {
  165. warnln("parse_endpoint: unknown parameter '{}' passed", parameter);
  166. VERIFY_NOT_REACHED();
  167. }
  168. assert_specific(']');
  169. consume_whitespace();
  170. }
  171. assert_specific('{');
  172. parse_messages();
  173. assert_specific('}');
  174. consume_whitespace();
  175. };
  176. while (lexer.tell() < file_contents.size())
  177. parse_endpoint();
  178. StringBuilder builder;
  179. SourceGenerator generator { builder };
  180. generator.append(R"~~~(
  181. #pragma once
  182. #include <AK/MemoryStream.h>
  183. #include <AK/OwnPtr.h>
  184. #include <AK/URL.h>
  185. #include <AK/Utf8View.h>
  186. #include <LibCore/AnonymousBuffer.h>
  187. #include <LibGfx/Color.h>
  188. #include <LibGfx/Rect.h>
  189. #include <LibGfx/ShareableBitmap.h>
  190. #include <LibIPC/Decoder.h>
  191. #include <LibIPC/Dictionary.h>
  192. #include <LibIPC/Encoder.h>
  193. #include <LibIPC/Endpoint.h>
  194. #include <LibIPC/File.h>
  195. #include <LibIPC/Message.h>
  196. )~~~");
  197. for (auto& endpoint : endpoints) {
  198. auto endpoint_generator = generator.fork();
  199. endpoint_generator.set("endpoint.name", endpoint.name);
  200. endpoint_generator.set("endpoint.magic", String::number(endpoint.magic));
  201. endpoint_generator.append(R"~~~(
  202. namespace Messages::@endpoint.name@ {
  203. )~~~");
  204. HashMap<String, int> message_ids;
  205. endpoint_generator.append(R"~~~(
  206. enum class MessageID : i32 {
  207. )~~~");
  208. for (auto& message : endpoint.messages) {
  209. auto message_generator = endpoint_generator.fork();
  210. message_ids.set(message.name, message_ids.size() + 1);
  211. message_generator.set("message.name", message.name);
  212. message_generator.set("message.id", String::number(message_ids.size()));
  213. message_generator.append(R"~~~(
  214. @message.name@ = @message.id@,
  215. )~~~");
  216. if (message.is_synchronous) {
  217. message_ids.set(message.response_name(), message_ids.size() + 1);
  218. message_generator.set("message.name", message.response_name());
  219. message_generator.set("message.id", String::number(message_ids.size()));
  220. message_generator.append(R"~~~(
  221. @message.name@ = @message.id@,
  222. )~~~");
  223. }
  224. }
  225. endpoint_generator.append(R"~~~(
  226. };
  227. )~~~");
  228. auto constructor_for_message = [&](const String& name, const Vector<Parameter>& parameters) {
  229. StringBuilder builder;
  230. builder.append(name);
  231. if (parameters.is_empty()) {
  232. builder.append("() {}");
  233. return builder.to_string();
  234. }
  235. builder.append('(');
  236. for (size_t i = 0; i < parameters.size(); ++i) {
  237. auto& parameter = parameters[i];
  238. builder.append(parameter.type);
  239. builder.append(" ");
  240. builder.append(parameter.name);
  241. if (i != parameters.size() - 1)
  242. builder.append(", ");
  243. }
  244. builder.append(") : ");
  245. for (size_t i = 0; i < parameters.size(); ++i) {
  246. auto& parameter = parameters[i];
  247. builder.append("m_");
  248. builder.append(parameter.name);
  249. builder.append("(move(");
  250. builder.append(parameter.name);
  251. builder.append("))");
  252. if (i != parameters.size() - 1)
  253. builder.append(", ");
  254. }
  255. builder.append(" {}");
  256. return builder.to_string();
  257. };
  258. auto do_message = [&](const String& name, const Vector<Parameter>& parameters, const String& response_type = {}) {
  259. auto message_generator = endpoint_generator.fork();
  260. message_generator.set("message.name", name);
  261. message_generator.set("message.response_type", response_type);
  262. message_generator.set("message.constructor", constructor_for_message(name, parameters));
  263. message_generator.append(R"~~~(
  264. class @message.name@ final : public IPC::Message {
  265. public:
  266. )~~~");
  267. if (!response_type.is_null())
  268. message_generator.append(R"~~~(
  269. typedef class @message.response_type@ ResponseType;
  270. )~~~");
  271. message_generator.append(R"~~~(
  272. @message.name@(decltype(nullptr)) : m_ipc_message_valid(false) { }
  273. @message.constructor@
  274. virtual ~@message.name@() override {}
  275. virtual u32 endpoint_magic() const override { return @endpoint.magic@; }
  276. virtual i32 message_id() const override { return (int)MessageID::@message.name@; }
  277. static i32 static_message_id() { return (int)MessageID::@message.name@; }
  278. virtual const char* message_name() const override { return "@endpoint.name@::@message.name@"; }
  279. static OwnPtr<@message.name@> decode(InputMemoryStream& stream, int sockfd)
  280. {
  281. IPC::Decoder decoder { stream, sockfd };
  282. )~~~");
  283. for (auto& parameter : parameters) {
  284. auto parameter_generator = message_generator.fork();
  285. parameter_generator.set("parameter.type", parameter.type);
  286. parameter_generator.set("parameter.name", parameter.name);
  287. if (parameter.type == "bool")
  288. parameter_generator.set("parameter.initial_value", "false");
  289. else
  290. parameter_generator.set("parameter.initial_value", "{}");
  291. parameter_generator.append(R"~~~(
  292. @parameter.type@ @parameter.name@ = @parameter.initial_value@;
  293. if (!decoder.decode(@parameter.name@))
  294. return {};
  295. )~~~");
  296. if (parameter.attributes.contains_slow("UTF8")) {
  297. parameter_generator.append(R"~~~(
  298. if (!Utf8View(@parameter.name@).validate())
  299. return {};
  300. )~~~");
  301. }
  302. }
  303. StringBuilder builder;
  304. for (size_t i = 0; i < parameters.size(); ++i) {
  305. auto& parameter = parameters[i];
  306. builder.append("move(");
  307. builder.append(parameter.name);
  308. builder.append(")");
  309. if (i != parameters.size() - 1)
  310. builder.append(", ");
  311. }
  312. message_generator.set("message.constructor_call_parameters", builder.build());
  313. message_generator.append(R"~~~(
  314. return make<@message.name@>(@message.constructor_call_parameters@);
  315. }
  316. )~~~");
  317. message_generator.append(R"~~~(
  318. virtual IPC::MessageBuffer encode() const override
  319. {
  320. IPC::MessageBuffer buffer;
  321. IPC::Encoder stream(buffer);
  322. stream << endpoint_magic();
  323. stream << (int)MessageID::@message.name@;
  324. )~~~");
  325. for (auto& parameter : parameters) {
  326. auto parameter_generator = message_generator.fork();
  327. parameter_generator.set("parameter.name", parameter.name);
  328. parameter_generator.append(R"~~~(
  329. stream << m_@parameter.name@;
  330. )~~~");
  331. }
  332. message_generator.append(R"~~~(
  333. return buffer;
  334. }
  335. )~~~");
  336. for (auto& parameter : parameters) {
  337. auto parameter_generator = message_generator.fork();
  338. parameter_generator.set("parameter.type", parameter.type);
  339. parameter_generator.set("parameter.name", parameter.name);
  340. parameter_generator.append(R"~~~(
  341. const @parameter.type@& @parameter.name@() const { return m_@parameter.name@; }
  342. )~~~");
  343. }
  344. message_generator.append(R"~~~(
  345. private:
  346. bool m_ipc_message_valid { true };
  347. )~~~");
  348. for (auto& parameter : parameters) {
  349. auto parameter_generator = message_generator.fork();
  350. parameter_generator.set("parameter.type", parameter.type);
  351. parameter_generator.set("parameter.name", parameter.name);
  352. parameter_generator.append(R"~~~(
  353. @parameter.type@ m_@parameter.name@;
  354. )~~~");
  355. }
  356. message_generator.append(R"~~~(
  357. };
  358. )~~~");
  359. };
  360. for (auto& message : endpoint.messages) {
  361. String response_name;
  362. if (message.is_synchronous) {
  363. response_name = message.response_name();
  364. do_message(response_name, message.outputs);
  365. }
  366. do_message(message.name, message.inputs, response_name);
  367. }
  368. endpoint_generator.append(R"~~~(
  369. } // namespace Messages::@endpoint.name@
  370. )~~~");
  371. endpoint_generator.append(R"~~~(
  372. class @endpoint.name@Endpoint : public IPC::Endpoint {
  373. public:
  374. @endpoint.name@Endpoint() { }
  375. virtual ~@endpoint.name@Endpoint() override { }
  376. static u32 static_magic() { return @endpoint.magic@; }
  377. virtual u32 magic() const override { return @endpoint.magic@; }
  378. static String static_name() { return "@endpoint.name@"; }
  379. virtual String name() const override { return "@endpoint.name@"; }
  380. static OwnPtr<IPC::Message> decode_message(ReadonlyBytes buffer, int sockfd)
  381. {
  382. InputMemoryStream stream { buffer };
  383. u32 message_endpoint_magic = 0;
  384. stream >> message_endpoint_magic;
  385. if (stream.handle_any_error()) {
  386. )~~~");
  387. if constexpr (GENERATE_DEBUG_CODE) {
  388. endpoint_generator.append(R"~~~(
  389. dbgln("Failed to read message endpoint magic");
  390. )~~~");
  391. }
  392. endpoint_generator.append(R"~~~(
  393. return {};
  394. }
  395. if (message_endpoint_magic != @endpoint.magic@) {
  396. )~~~");
  397. if constexpr (GENERATE_DEBUG_CODE) {
  398. endpoint_generator.append(R"~~~(
  399. dbgln("@endpoint.name@: Endpoint magic number message_endpoint_magic != @endpoint.magic@, not my message! (the other endpoint may have handled it)");
  400. )~~~");
  401. }
  402. endpoint_generator.append(R"~~~(
  403. return {};
  404. }
  405. i32 message_id = 0;
  406. stream >> message_id;
  407. if (stream.handle_any_error()) {
  408. )~~~");
  409. if constexpr (GENERATE_DEBUG_CODE) {
  410. endpoint_generator.append(R"~~~(
  411. dbgln("Failed to read message ID");
  412. )~~~");
  413. }
  414. endpoint_generator.append(R"~~~(
  415. return {};
  416. }
  417. OwnPtr<IPC::Message> message;
  418. switch (message_id) {
  419. )~~~");
  420. for (auto& message : endpoint.messages) {
  421. auto do_decode_message = [&](const String& name) {
  422. auto message_generator = endpoint_generator.fork();
  423. message_generator.set("message.name", name);
  424. message_generator.append(R"~~~(
  425. case (int)Messages::@endpoint.name@::MessageID::@message.name@:
  426. message = Messages::@endpoint.name@::@message.name@::decode(stream, sockfd);
  427. break;
  428. )~~~");
  429. };
  430. do_decode_message(message.name);
  431. if (message.is_synchronous)
  432. do_decode_message(message.response_name());
  433. }
  434. endpoint_generator.append(R"~~~(
  435. default:
  436. )~~~");
  437. if constexpr (GENERATE_DEBUG_CODE) {
  438. endpoint_generator.append(R"~~~(
  439. dbgln("Failed to decode @endpoint.name@.({})", message_id);
  440. )~~~");
  441. }
  442. endpoint_generator.append(R"~~~(
  443. return {};
  444. }
  445. if (stream.handle_any_error()) {
  446. )~~~");
  447. if constexpr (GENERATE_DEBUG_CODE) {
  448. endpoint_generator.append(R"~~~(
  449. dbgln("Failed to read the message");
  450. )~~~");
  451. }
  452. endpoint_generator.append(R"~~~(
  453. return {};
  454. }
  455. return message;
  456. }
  457. virtual OwnPtr<IPC::MessageBuffer> handle(const IPC::Message& message) override
  458. {
  459. switch (message.message_id()) {
  460. )~~~");
  461. for (auto& message : endpoint.messages) {
  462. auto do_decode_message = [&](const String& name, bool returns_something) {
  463. auto message_generator = endpoint_generator.fork();
  464. message_generator.set("message.name", name);
  465. message_generator.append(R"~~~(
  466. case (int)Messages::@endpoint.name@::MessageID::@message.name@: {
  467. )~~~");
  468. if (returns_something) {
  469. message_generator.append(R"~~~(
  470. auto response = handle(static_cast<const Messages::@endpoint.name@::@message.name@&>(message));
  471. return make<IPC::MessageBuffer>(response.encode());
  472. }
  473. )~~~");
  474. } else {
  475. message_generator.append(R"~~~(
  476. handle(static_cast<const Messages::@endpoint.name@::@message.name@&>(message));
  477. return {};
  478. }
  479. )~~~");
  480. }
  481. };
  482. do_decode_message(message.name, message.is_synchronous);
  483. if (message.is_synchronous)
  484. do_decode_message(message.response_name(), false);
  485. }
  486. endpoint_generator.append(R"~~~(
  487. default:
  488. return {};
  489. }
  490. }
  491. )~~~");
  492. for (auto& message : endpoint.messages) {
  493. auto message_generator = endpoint_generator.fork();
  494. message_generator.set("message.name", message.name);
  495. String return_type = "void";
  496. if (message.is_synchronous) {
  497. StringBuilder builder;
  498. builder.append("Messages::");
  499. builder.append(endpoint.name);
  500. builder.append("::");
  501. builder.append(message.name);
  502. builder.append("Response");
  503. return_type = builder.to_string();
  504. }
  505. message_generator.set("message.complex_return_type", return_type);
  506. message_generator.append(R"~~~(
  507. virtual @message.complex_return_type@ handle(const Messages::@endpoint.name@::@message.name@&) = 0;
  508. )~~~");
  509. }
  510. endpoint_generator.append(R"~~~(
  511. private:
  512. };
  513. )~~~");
  514. }
  515. outln("{}", generator.as_string_view());
  516. #ifdef DEBUG
  517. for (auto& endpoint : endpoints) {
  518. warnln("Endpoint '{}' (magic: {})", endpoint.name, endpoint.magic);
  519. for (auto& message : endpoint.messages) {
  520. warnln(" Message: '{}'", message.name);
  521. warnln(" Sync: {}", message.is_synchronous);
  522. warnln(" Inputs:");
  523. for (auto& parameter : message.inputs)
  524. warnln(" Parameter: {} ({})", parameter.name, parameter.type);
  525. if (message.inputs.is_empty())
  526. warnln(" (none)");
  527. if (message.is_synchronous) {
  528. warnln(" Outputs:");
  529. for (auto& parameter : message.outputs)
  530. warnln(" Parameter: {} ({})", parameter.name, parameter.type);
  531. if (message.outputs.is_empty())
  532. warnln(" (none)");
  533. }
  534. }
  535. }
  536. #endif
  537. }