mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
IPCCompiler: Start working on a simple IPC definition language
Instead of doing everything manually in C++, let's do some codegen. This patch adds a crude but effective IPC definition parser, along with two initial definition files for the AudioServer's client and server endpoints.
This commit is contained in:
parent
c5903ec4bb
commit
aa8a3d4a89
Notes:
sideshowbarker
2024-07-19 12:55:32 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/aa8a3d4a894
5 changed files with 244 additions and 0 deletions
34
DevTools/IPCCompiler/Makefile
Normal file
34
DevTools/IPCCompiler/Makefile
Normal file
|
@ -0,0 +1,34 @@
|
|||
PROGRAM = IPCCompiler
|
||||
|
||||
OBJS = \
|
||||
main.o \
|
||||
../../AK/String.o \
|
||||
../../AK/StringImpl.o \
|
||||
../../AK/StringBuilder.o \
|
||||
../../AK/StringView.o \
|
||||
../../AK/JsonObject.o \
|
||||
../../AK/JsonValue.o \
|
||||
../../AK/JsonArray.o \
|
||||
../../AK/JsonParser.o \
|
||||
../../AK/LogStream.o \
|
||||
../../Libraries/LibCore/CIODevice.o \
|
||||
../../Libraries/LibCore/CFile.o \
|
||||
../../Libraries/LibCore/CObject.o \
|
||||
../../Libraries/LibCore/CEvent.o \
|
||||
../../Libraries/LibCore/CSocket.o \
|
||||
../../Libraries/LibCore/CLocalSocket.o \
|
||||
../../Libraries/LibCore/CNotifier.o \
|
||||
../../Libraries/LibCore/CEventLoop.o
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
CXXFLAGS = -std=c++17 -Wall -Wextra -ggdb3
|
||||
|
||||
%.o: %.cpp
|
||||
$(PRE_CXX) $(CXX) $(CXXFLAGS) -I../ -I../../ -I../../Libraries/ -o $@ -c $<
|
||||
|
||||
$(PROGRAM): $(OBJS)
|
||||
$(CXX) $(LDFLAGS) -I../ -I../../ -I../../Libraries/ -o $(PROGRAM) $(OBJS)
|
||||
|
||||
clean:
|
||||
rm -f $(PROGRAM) $(OBJS)
|
196
DevTools/IPCCompiler/main.cpp
Normal file
196
DevTools/IPCCompiler/main.cpp
Normal file
|
@ -0,0 +1,196 @@
|
|||
#include <AK/StringBuilder.h>
|
||||
#include <LibCore/CFile.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct Parameter {
|
||||
String type;
|
||||
String name;
|
||||
};
|
||||
|
||||
struct Message {
|
||||
String name;
|
||||
bool is_synchronous { false };
|
||||
Vector<Parameter> inputs;
|
||||
Vector<Parameter> outputs;
|
||||
};
|
||||
|
||||
struct Endpoint {
|
||||
String name;
|
||||
Vector<Message> messages;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
printf("usage: %s <IPC endpoint definition file>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CFile file(argv[1]);
|
||||
if (!file.open(CIODevice::ReadOnly)) {
|
||||
fprintf(stderr, "Error: Cannot open %s: %s\n", argv[1], file.error_string());
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto file_contents = file.read_all();
|
||||
|
||||
Vector<Endpoint> endpoints;
|
||||
|
||||
Vector<char> buffer;
|
||||
|
||||
int index = 0;
|
||||
|
||||
auto peek = [&]() -> char {
|
||||
if (index < file_contents.size())
|
||||
return file_contents[index];
|
||||
return 0;
|
||||
};
|
||||
|
||||
auto consume_one = [&]() -> char {
|
||||
return file_contents[index++];
|
||||
};
|
||||
|
||||
auto extract_while = [&](Function<bool(char)> condition) -> String {
|
||||
StringBuilder builder;
|
||||
while (condition(peek()))
|
||||
builder.append(consume_one());
|
||||
return builder.to_string();
|
||||
};
|
||||
|
||||
auto consume_specific = [&](char ch) {
|
||||
if (peek() != ch) {
|
||||
dbg() << "consume_specific: wanted '" << ch << "', but got '" << peek() << "'";
|
||||
}
|
||||
ASSERT(peek() == ch);
|
||||
++index;
|
||||
return ch;
|
||||
};
|
||||
|
||||
auto consume_string = [&](const char* str) {
|
||||
for (size_t i = 0, length = strlen(str); i < length; ++i)
|
||||
consume_specific(str[i]);
|
||||
};
|
||||
|
||||
auto consume_whitespace = [&] {
|
||||
while (isspace(peek()))
|
||||
++index;
|
||||
};
|
||||
|
||||
auto parse_parameter = [&](Vector<Parameter>& storage) {
|
||||
for (;;) {
|
||||
Parameter parameter;
|
||||
consume_whitespace();
|
||||
if (peek() == ')')
|
||||
break;
|
||||
parameter.type = extract_while([](char ch) { return !isspace(ch); });
|
||||
consume_whitespace();
|
||||
parameter.name = extract_while([](char ch) { return !isspace(ch) && ch != ')'; });
|
||||
consume_whitespace();
|
||||
storage.append(move(parameter));
|
||||
if (peek() == ',') {
|
||||
consume_one();
|
||||
continue;
|
||||
}
|
||||
if (peek() == ')')
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
auto parse_parameters = [&](Vector<Parameter>& storage) {
|
||||
for (;;) {
|
||||
consume_whitespace();
|
||||
parse_parameter(storage);
|
||||
consume_whitespace();
|
||||
if (peek() == ',') {
|
||||
consume_one();
|
||||
continue;
|
||||
}
|
||||
if (peek() == ')')
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
auto parse_message = [&] {
|
||||
Message message;
|
||||
consume_whitespace();
|
||||
Vector<char> buffer;
|
||||
while (!isspace(peek()) && peek() != '(')
|
||||
buffer.append(consume_one());
|
||||
message.name = String::copy(buffer);
|
||||
consume_whitespace();
|
||||
consume_specific('(');
|
||||
parse_parameters(message.inputs);
|
||||
consume_specific(')');
|
||||
consume_whitespace();
|
||||
consume_specific('=');
|
||||
|
||||
auto type = consume_one();
|
||||
if (type == '>')
|
||||
message.is_synchronous = true;
|
||||
else if (type == '|')
|
||||
message.is_synchronous = false;
|
||||
else
|
||||
ASSERT_NOT_REACHED();
|
||||
|
||||
consume_whitespace();
|
||||
|
||||
if (message.is_synchronous) {
|
||||
consume_specific('(');
|
||||
parse_parameters(message.outputs);
|
||||
consume_specific(')');
|
||||
}
|
||||
|
||||
consume_whitespace();
|
||||
|
||||
endpoints.last().messages.append(move(message));
|
||||
};
|
||||
|
||||
auto parse_messages = [&] {
|
||||
for (;;) {
|
||||
consume_whitespace();
|
||||
parse_message();
|
||||
consume_whitespace();
|
||||
if (peek() == '}')
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
auto parse_endpoint = [&] {
|
||||
endpoints.empend();
|
||||
consume_whitespace();
|
||||
consume_string("endpoint");
|
||||
consume_whitespace();
|
||||
endpoints.last().name = extract_while([](char ch) { return !isspace(ch); });
|
||||
consume_whitespace();
|
||||
consume_specific('{');
|
||||
parse_messages();
|
||||
consume_specific('}');
|
||||
consume_whitespace();
|
||||
};
|
||||
|
||||
while (index < file_contents.size())
|
||||
parse_endpoint();
|
||||
|
||||
for (auto& endpoint : endpoints) {
|
||||
dbg() << "Endpoint: '" << endpoint.name << "'";
|
||||
for (auto& message : endpoint.messages) {
|
||||
dbg() << " Message: '" << message.name << "'";
|
||||
dbg() << " Sync: " << message.is_synchronous;
|
||||
dbg() << " Inputs:";
|
||||
for (auto& parameter : message.inputs)
|
||||
dbg() << " Parameter: " << parameter.name << " (" << parameter.type << ")";
|
||||
if (message.inputs.is_empty())
|
||||
dbg() << " (none)";
|
||||
if (message.is_synchronous) {
|
||||
dbg() << " Outputs:";
|
||||
for (auto& parameter : message.outputs)
|
||||
dbg() << " Parameter: " << parameter.name << " (" << parameter.type << ")";
|
||||
if (message.outputs.is_empty())
|
||||
dbg() << " (none)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -15,6 +15,7 @@ make_cmd="make -j $MAKEJOBS"
|
|||
|
||||
build_targets=""
|
||||
build_targets="$build_targets ../DevTools/FormCompiler"
|
||||
build_targets="$build_targets ../DevTools/IPCCompiler"
|
||||
build_targets="$build_targets ../Libraries/LibC"
|
||||
build_targets="$build_targets ../Libraries/LibM"
|
||||
build_targets="$build_targets ../Libraries/LibCore"
|
||||
|
|
4
Servers/AudioServer/AudioClient.ipc
Normal file
4
Servers/AudioServer/AudioClient.ipc
Normal file
|
@ -0,0 +1,4 @@
|
|||
endpoint AudioClient
|
||||
{
|
||||
FinishedPlayingBuffer(i32 buffer_id) =|
|
||||
}
|
9
Servers/AudioServer/AudioServer.ipc
Normal file
9
Servers/AudioServer/AudioServer.ipc
Normal file
|
@ -0,0 +1,9 @@
|
|||
endpoint AudioServer
|
||||
{
|
||||
Greet(i32 client_pid) => (i32 server_pid, i32 client_id)
|
||||
|
||||
GetMainMixVolume() => (i32 volume)
|
||||
SetMainMixVolume(i32 volume) => ()
|
||||
|
||||
EnqueueBuffer(i32 buffer_id) => ()
|
||||
}
|
Loading…
Reference in a new issue