1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 01:57:44 +00:00

AK: Add out() and warn() streams that forward to stdout and stderr

Our C++ code generator tools have been relying on host-side dbg() being
forwarded to stdout until now. Now they use out() instead.

Hopefully this will make it easier and more enticing to use streams in
userspace programs as well. :^)
This commit is contained in:
Andreas Kling 2020-04-06 10:12:10 +02:00
parent 63b11e094d
commit 0d48fb9a87
6 changed files with 219 additions and 176 deletions

View file

@ -100,7 +100,7 @@ int main(int argc, char** argv)
auto consume_specific = [&](char ch) {
if (peek() != ch) {
dbg() << "consume_specific: wanted '" << ch << "', but got '" << peek() << "' at index " << index;
warn() << "consume_specific: wanted '" << ch << "', but got '" << peek() << "' at index " << index;
}
ASSERT(peek() == ch);
++index;
@ -223,36 +223,36 @@ int main(int argc, char** argv)
while (index < file_contents.size())
parse_endpoint();
dbg() << "#pragma once";
dbg() << "#include <AK/BufferStream.h>";
dbg() << "#include <AK/OwnPtr.h>";
dbg() << "#include <LibGfx/Color.h>";
dbg() << "#include <LibGfx/Rect.h>";
dbg() << "#include <LibGfx/ShareableBitmap.h>";
dbg() << "#include <LibIPC/Decoder.h>";
dbg() << "#include <LibIPC/Encoder.h>";
dbg() << "#include <LibIPC/Endpoint.h>";
dbg() << "#include <LibIPC/Message.h>";
dbg();
out() << "#pragma once";
out() << "#include <AK/BufferStream.h>";
out() << "#include <AK/OwnPtr.h>";
out() << "#include <LibGfx/Color.h>";
out() << "#include <LibGfx/Rect.h>";
out() << "#include <LibGfx/ShareableBitmap.h>";
out() << "#include <LibIPC/Decoder.h>";
out() << "#include <LibIPC/Encoder.h>";
out() << "#include <LibIPC/Endpoint.h>";
out() << "#include <LibIPC/Message.h>";
out();
for (auto& endpoint : endpoints) {
dbg() << "namespace Messages {";
dbg() << "namespace " << endpoint.name << " {";
dbg();
out() << "namespace Messages {";
out() << "namespace " << endpoint.name << " {";
out();
HashMap<String, int> message_ids;
dbg() << "enum class MessageID : i32 {";
out() << "enum class MessageID : i32 {";
for (auto& message : endpoint.messages) {
message_ids.set(message.name, message_ids.size() + 1);
dbg() << " " << message.name << " = " << message_ids.size() << ",";
out() << " " << message.name << " = " << message_ids.size() << ",";
if (message.is_synchronous) {
message_ids.set(message.response_name(), message_ids.size() + 1);
dbg() << " " << message.response_name() << " = " << message_ids.size() << ",";
out() << " " << message.response_name() << " = " << message_ids.size() << ",";
}
}
dbg() << "};";
dbg();
out() << "};";
out();
auto constructor_for_message = [&](const String& name, const Vector<Parameter>& parameters) {
StringBuilder builder;
@ -289,39 +289,39 @@ int main(int argc, char** argv)
};
auto do_message = [&](const String& name, const Vector<Parameter>& parameters, const String& response_type = {}) {
dbg() << "class " << name << " final : public IPC::Message {";
dbg() << "public:";
out() << "class " << name << " final : public IPC::Message {";
out() << "public:";
if (!response_type.is_null())
dbg() << " typedef class " << response_type << " ResponseType;";
dbg() << " " << constructor_for_message(name, parameters);
dbg() << " virtual ~" << name << "() override {}";
dbg() << " virtual i32 endpoint_magic() const override { return " << endpoint.magic << "; }";
dbg() << " virtual i32 message_id() const override { return (int)MessageID::" << name << "; }";
dbg() << " static i32 static_message_id() { return (int)MessageID::" << name << "; }";
dbg() << " virtual const char* message_name() const override { return \"" << endpoint.name << "::" << name << "\"; }";
dbg() << " static OwnPtr<" << name << "> decode(BufferStream& stream, size_t& size_in_bytes)";
dbg() << " {";
out() << " typedef class " << response_type << " ResponseType;";
out() << " " << constructor_for_message(name, parameters);
out() << " virtual ~" << name << "() override {}";
out() << " virtual i32 endpoint_magic() const override { return " << endpoint.magic << "; }";
out() << " virtual i32 message_id() const override { return (int)MessageID::" << name << "; }";
out() << " static i32 static_message_id() { return (int)MessageID::" << name << "; }";
out() << " virtual const char* message_name() const override { return \"" << endpoint.name << "::" << name << "\"; }";
out() << " static OwnPtr<" << name << "> decode(BufferStream& stream, size_t& size_in_bytes)";
out() << " {";
dbg() << " IPC::Decoder decoder(stream);";
out() << " IPC::Decoder decoder(stream);";
for (auto& parameter : parameters) {
String initial_value = "{}";
if (parameter.type == "bool")
initial_value = "false";
dbg() << " " << parameter.type << " " << parameter.name << " = " << initial_value << ";";
out() << " " << parameter.type << " " << parameter.name << " = " << initial_value << ";";
if (parameter.type == "Vector<Gfx::Rect>") {
dbg() << " u64 " << parameter.name << "_size = 0;";
dbg() << " stream >> " << parameter.name << "_size;";
dbg() << " for (size_t i = 0; i < " << parameter.name << "_size; ++i) {";
dbg() << " Gfx::Rect rect;";
dbg() << " if (!decoder.decode(rect))";
dbg() << " return nullptr;";
dbg() << " " << parameter.name << ".append(move(rect));";
dbg() << " }";
out() << " u64 " << parameter.name << "_size = 0;";
out() << " stream >> " << parameter.name << "_size;";
out() << " for (size_t i = 0; i < " << parameter.name << "_size; ++i) {";
out() << " Gfx::Rect rect;";
out() << " if (!decoder.decode(rect))";
out() << " return nullptr;";
out() << " " << parameter.name << ".append(move(rect));";
out() << " }";
} else {
dbg() << " if (!decoder.decode(" << parameter.name << "))";
dbg() << " return nullptr;";
out() << " if (!decoder.decode(" << parameter.name << "))";
out() << " return nullptr;";
}
}
@ -332,56 +332,56 @@ int main(int argc, char** argv)
if (i != parameters.size() - 1)
builder.append(", ");
}
dbg() << " size_in_bytes = stream.offset();";
dbg() << " return make<" << name << ">(" << builder.to_string() << ");";
dbg() << " }";
dbg() << " virtual IPC::MessageBuffer encode() const override";
dbg() << " {";
dbg() << " IPC::MessageBuffer buffer;";
dbg() << " IPC::Encoder stream(buffer);";
dbg() << " stream << endpoint_magic();";
dbg() << " stream << (int)MessageID::" << name << ";";
out() << " size_in_bytes = stream.offset();";
out() << " return make<" << name << ">(" << builder.to_string() << ");";
out() << " }";
out() << " virtual IPC::MessageBuffer encode() const override";
out() << " {";
out() << " IPC::MessageBuffer buffer;";
out() << " IPC::Encoder stream(buffer);";
out() << " stream << endpoint_magic();";
out() << " stream << (int)MessageID::" << name << ";";
for (auto& parameter : parameters) {
if (parameter.type == "Gfx::Color") {
dbg() << " stream << m_" << parameter.name << ".value();";
out() << " stream << m_" << parameter.name << ".value();";
} else if (parameter.type == "Gfx::Size") {
dbg() << " stream << m_" << parameter.name << ".width();";
dbg() << " stream << m_" << parameter.name << ".height();";
out() << " stream << m_" << parameter.name << ".width();";
out() << " stream << m_" << parameter.name << ".height();";
} else if (parameter.type == "Gfx::Point") {
dbg() << " stream << m_" << parameter.name << ".x();";
dbg() << " stream << m_" << parameter.name << ".y();";
out() << " stream << m_" << parameter.name << ".x();";
out() << " stream << m_" << parameter.name << ".y();";
} else if (parameter.type == "Gfx::Rect") {
dbg() << " stream << m_" << parameter.name << ".x();";
dbg() << " stream << m_" << parameter.name << ".y();";
dbg() << " stream << m_" << parameter.name << ".width();";
dbg() << " stream << m_" << parameter.name << ".height();";
out() << " stream << m_" << parameter.name << ".x();";
out() << " stream << m_" << parameter.name << ".y();";
out() << " stream << m_" << parameter.name << ".width();";
out() << " stream << m_" << parameter.name << ".height();";
} else if (parameter.type == "Vector<Gfx::Rect>") {
dbg() << " stream << (u64)m_" << parameter.name << ".size();";
dbg() << " for (auto& rect : m_" << parameter.name << ") {";
dbg() << " stream << rect.x();";
dbg() << " stream << rect.y();";
dbg() << " stream << rect.width();";
dbg() << " stream << rect.height();";
dbg() << " }";
out() << " stream << (u64)m_" << parameter.name << ".size();";
out() << " for (auto& rect : m_" << parameter.name << ") {";
out() << " stream << rect.x();";
out() << " stream << rect.y();";
out() << " stream << rect.width();";
out() << " stream << rect.height();";
out() << " }";
} else if (parameter.type == "Gfx::ShareableBitmap") {
dbg() << " stream << m_" << parameter.name << ".shbuf_id();";
dbg() << " stream << m_" << parameter.name << ".width();";
dbg() << " stream << m_" << parameter.name << ".height();";
out() << " stream << m_" << parameter.name << ".shbuf_id();";
out() << " stream << m_" << parameter.name << ".width();";
out() << " stream << m_" << parameter.name << ".height();";
} else {
dbg() << " stream << m_" << parameter.name << ";";
out() << " stream << m_" << parameter.name << ";";
}
}
dbg() << " return buffer;";
dbg() << " }";
out() << " return buffer;";
out() << " }";
for (auto& parameter : parameters) {
dbg() << " const " << parameter.type << "& " << parameter.name << "() const { return m_" << parameter.name << "; }";
out() << " const " << parameter.type << "& " << parameter.name << "() const { return m_" << parameter.name << "; }";
}
dbg() << "private:";
out() << "private:";
for (auto& parameter : parameters) {
dbg() << " " << parameter.type << " m_" << parameter.name << ";";
out() << " " << parameter.type << " m_" << parameter.name << ";";
}
dbg() << "};";
dbg();
out() << "};";
out();
};
for (auto& message : endpoint.messages) {
String response_name;
@ -391,72 +391,72 @@ int main(int argc, char** argv)
}
do_message(message.name, message.inputs, response_name);
}
dbg() << "} // namespace " << endpoint.name;
dbg() << "} // namespace Messages";
dbg();
out() << "} // namespace " << endpoint.name;
out() << "} // namespace Messages";
out();
dbg() << "class " << endpoint.name << "Endpoint : public IPC::Endpoint {";
dbg() << "public:";
dbg() << " " << endpoint.name << "Endpoint() {}";
dbg() << " virtual ~" << endpoint.name << "Endpoint() override {}";
dbg() << " static int static_magic() { return " << endpoint.magic << "; }";
dbg() << " virtual int magic() const override { return " << endpoint.magic << "; }";
dbg() << " static String static_name() { return \"" << endpoint.name << "\"; };";
dbg() << " virtual String name() const override { return \"" << endpoint.name << "\"; };";
dbg() << " static OwnPtr<IPC::Message> decode_message(const ByteBuffer& buffer, size_t& size_in_bytes)";
dbg() << " {";
dbg() << " BufferStream stream(const_cast<ByteBuffer&>(buffer));";
dbg() << " i32 message_endpoint_magic = 0;";
dbg() << " stream >> message_endpoint_magic;";
dbg() << " if (message_endpoint_magic != " << endpoint.magic << ") {";
out() << "class " << endpoint.name << "Endpoint : public IPC::Endpoint {";
out() << "public:";
out() << " " << endpoint.name << "Endpoint() {}";
out() << " virtual ~" << endpoint.name << "Endpoint() override {}";
out() << " static int static_magic() { return " << endpoint.magic << "; }";
out() << " virtual int magic() const override { return " << endpoint.magic << "; }";
out() << " static String static_name() { return \"" << endpoint.name << "\"; };";
out() << " virtual String name() const override { return \"" << endpoint.name << "\"; };";
out() << " static OwnPtr<IPC::Message> decode_message(const ByteBuffer& buffer, size_t& size_in_bytes)";
out() << " {";
out() << " BufferStream stream(const_cast<ByteBuffer&>(buffer));";
out() << " i32 message_endpoint_magic = 0;";
out() << " stream >> message_endpoint_magic;";
out() << " if (message_endpoint_magic != " << endpoint.magic << ") {";
#ifdef GENERATE_DEBUG_CODE
dbg() << " dbg() << \"endpoint magic \" << message_endpoint_magic << \" != " << endpoint.magic << "\";";
sout() << " sout() << \"endpoint magic \" << message_endpoint_magic << \" != " << endpoint.magic << "\";";
#endif
dbg() << " return nullptr;";
dbg() << " }";
dbg() << " i32 message_id = 0;";
dbg() << " stream >> message_id;";
dbg() << " switch (message_id) {";
out() << " return nullptr;";
out() << " }";
out() << " i32 message_id = 0;";
out() << " stream >> message_id;";
out() << " switch (message_id) {";
for (auto& message : endpoint.messages) {
auto do_decode_message = [&](const String& name) {
dbg() << " case (int)Messages::" << endpoint.name << "::MessageID::" << name << ":";
dbg() << " return Messages::" << endpoint.name << "::" << name << "::decode(stream, size_in_bytes);";
out() << " case (int)Messages::" << endpoint.name << "::MessageID::" << name << ":";
out() << " return Messages::" << endpoint.name << "::" << name << "::decode(stream, size_in_bytes);";
};
do_decode_message(message.name);
if (message.is_synchronous)
do_decode_message(message.response_name());
}
dbg() << " default:";
out() << " default:";
#ifdef GENERATE_DEBUG_CODE
dbg() << " dbg() << \"Failed to decode " << endpoint.name << ".(\" << message_id << \")\";";
sout() << " sout() << \"Failed to decode " << endpoint.name << ".(\" << message_id << \")\";";
#endif
dbg() << " return nullptr;";
out() << " return nullptr;";
dbg() << " }";
dbg() << " }";
dbg();
dbg() << " virtual OwnPtr<IPC::Message> handle(const IPC::Message& message) override";
dbg() << " {";
dbg() << " switch (message.message_id()) {";
out() << " }";
out() << " }";
out();
out() << " virtual OwnPtr<IPC::Message> handle(const IPC::Message& message) override";
out() << " {";
out() << " switch (message.message_id()) {";
for (auto& message : endpoint.messages) {
auto do_decode_message = [&](const String& name, bool returns_something) {
dbg() << " case (int)Messages::" << endpoint.name << "::MessageID::" << name << ":";
out() << " case (int)Messages::" << endpoint.name << "::MessageID::" << name << ":";
if (returns_something) {
dbg() << " return handle(static_cast<const Messages::" << endpoint.name << "::" << name << "&>(message));";
out() << " return handle(static_cast<const Messages::" << endpoint.name << "::" << name << "&>(message));";
} else {
dbg() << " handle(static_cast<const Messages::" << endpoint.name << "::" << name << "&>(message));";
dbg() << " return nullptr;";
out() << " handle(static_cast<const Messages::" << endpoint.name << "::" << name << "&>(message));";
out() << " return nullptr;";
}
};
do_decode_message(message.name, message.is_synchronous);
if (message.is_synchronous)
do_decode_message(message.response_name(), false);
}
dbg() << " default:";
dbg() << " return nullptr;";
out() << " default:";
out() << " return nullptr;";
dbg() << " }";
dbg() << " }";
out() << " }";
out() << " }";
for (auto& message : endpoint.messages) {
String return_type = "void";
@ -470,30 +470,30 @@ int main(int argc, char** argv)
builder.append(">");
return_type = builder.to_string();
}
dbg() << " virtual " << return_type << " handle(const Messages::" << endpoint.name << "::" << message.name << "&) = 0;";
out() << " virtual " << return_type << " handle(const Messages::" << endpoint.name << "::" << message.name << "&) = 0;";
}
dbg() << "private:";
dbg() << "};";
out() << "private:";
out() << "};";
}
#ifdef DEBUG
for (auto& endpoint : endpoints) {
dbg() << "Endpoint: '" << endpoint.name << "' (magic: " << endpoint.magic << ")";
warn() << "Endpoint: '" << endpoint.name << "' (magic: " << endpoint.magic << ")";
for (auto& message : endpoint.messages) {
dbg() << " Message: '" << message.name << "'";
dbg() << " Sync: " << message.is_synchronous;
dbg() << " Inputs:";
warn() << " Message: '" << message.name << "'";
warn() << " Sync: " << message.is_synchronous;
warn() << " Inputs:";
for (auto& parameter : message.inputs)
dbg() << " Parameter: " << parameter.name << " (" << parameter.type << ")";
warn() << " Parameter: " << parameter.name << " (" << parameter.type << ")";
if (message.inputs.is_empty())
dbg() << " (none)";
warn() << " (none)";
if (message.is_synchronous) {
dbg() << " Outputs:";
warn() << " Outputs:";
for (auto& parameter : message.outputs)
dbg() << " Parameter: " << parameter.name << " (" << parameter.type << ")";
warn() << " Parameter: " << parameter.name << " (" << parameter.type << ")";
if (message.outputs.is_empty())
dbg() << " (none)";
warn() << " (none)";
}
}
}