toolchain: replace ifc interface compiler with xpcg

xpcg is used to generate xpc interfaces
This commit is contained in:
2026-03-10 19:12:14 +00:00
parent 3a06c18e10
commit 26a49162e6
24 changed files with 427 additions and 878 deletions

View File

@@ -14,4 +14,4 @@ add_subdirectory(
../kernel/tools
${CMAKE_CURRENT_BINARY_DIR}/kernel-tools)
add_subdirectory(ifc)
add_subdirectory(xpcg)

View File

@@ -1,7 +0,0 @@
file(GLOB sources
*.c *.h
backend/c-mpc/*.c backend/c-mpc/*.h)
add_executable(ifc ${sources})
target_link_libraries(ifc Bluelib::Core Bluelib::Ds Bluelib::Cmd Bluelib::Io)

View File

@@ -0,0 +1,7 @@
file(GLOB sources
*.c *.h
backend/c-mpc/*.c backend/c-mpc/*.h)
add_executable(xpcg ${sources})
target_link_libraries(xpcg Bluelib::Core Bluelib::Ds Bluelib::Cmd Bluelib::Io)

View File

@@ -1,5 +1,5 @@
#ifndef IFC_BACKEND_H_
#define IFC_BACKEND_H_
#ifndef XPCG_BACKEND_H_
#define XPCG_BACKEND_H_
struct interface_definition;

View File

@@ -43,6 +43,14 @@ const struct type *ctx_get_type(struct ctx *ctx, const char *name)
return ctx_get_builtin_type(ctx, TYPE_HANDLE);
}
if (!strcmp(name, "size")) {
return ctx_get_builtin_type(ctx, TYPE_SIZE);
}
if (!strcmp(name, "buffer")) {
return ctx_get_builtin_type(ctx, TYPE_BUFFER);
}
return NULL;
}

View File

@@ -1,5 +1,5 @@
#ifndef IFC_CTX_H_
#define IFC_CTX_H_
#ifndef XPCG_CTX_H_
#define XPCG_CTX_H_
#include "type.h"

View File

@@ -1,5 +1,5 @@
#ifndef IFC_FILE_SPAN_H_
#define IFC_FILE_SPAN_H_
#ifndef XPCG_FILE_SPAN_H_
#define XPCG_FILE_SPAN_H_
struct file_cell {
unsigned int c_row, c_col;

View File

@@ -6,7 +6,9 @@
#include <stdlib.h>
#include <string.h>
struct interface_definition *interface_definition_create(const char *name)
struct interface_definition *interface_definition_create(
const char *name,
long long id)
{
struct interface_definition *out = malloc(sizeof *out);
if (!out) {
@@ -16,6 +18,7 @@ struct interface_definition *interface_definition_create(const char *name)
memset(out, 0x0, sizeof *out);
out->if_name = b_strdup(name);
out->if_id = id;
return out;
}

View File

@@ -1,5 +1,5 @@
#ifndef IFC_INTERFACE_H_
#define IFC_INTERFACE_H_
#ifndef XPCG_INTERFACE_H_
#define XPCG_INTERFACE_H_
#include <blue/core/queue.h>
@@ -7,11 +7,13 @@ struct msg_definition;
struct interface_definition {
char *if_name;
long long if_id;
b_queue if_msg;
};
extern struct interface_definition *interface_definition_create(
const char *name);
const char *name,
long long id);
extern void interface_definition_destroy(struct interface_definition *iface);
extern bool interface_definition_has_msg(

View File

@@ -29,18 +29,21 @@
static struct lex_token_def symbols[] = {
LEX_TOKEN_DEF(SYM_COMMA, ","),
LEX_TOKEN_DEF(SYM_HYPHEN, "-"),
LEX_TOKEN_DEF(SYM_LEFT_BRACKET, "["),
LEX_TOKEN_DEF(SYM_RIGHT_BRACKET, "]"),
LEX_TOKEN_DEF(SYM_LEFT_BRACE, "{"),
LEX_TOKEN_DEF(SYM_RIGHT_BRACE, "}"),
LEX_TOKEN_DEF(SYM_LEFT_PAREN, "("),
LEX_TOKEN_DEF(SYM_RIGHT_PAREN, ")"),
LEX_TOKEN_DEF(SYM_SEMICOLON, ";"),
LEX_TOKEN_DEF(SYM_COLON, ":"),
LEX_TOKEN_DEF(SYM_HYPHEN_RIGHT_ANGLE, "->"),
};
static const size_t nr_symbols = sizeof symbols / sizeof symbols[0];
static struct lex_token_def keywords[] = {
LEX_TOKEN_DEF(KW_INTERFACE, "interface"),
LEX_TOKEN_DEF(KW_MSG, "msg"),
LEX_TOKEN_DEF(KW_FUNC, "func"),
};
static const size_t nr_keywords = sizeof keywords / sizeof keywords[0];

View File

@@ -1,5 +1,5 @@
#ifndef IFC_LEX_H_
#define IFC_LEX_H_
#ifndef XPCG_LEX_H_
#define XPCG_LEX_H_
#include "status.h"
#include "token.h"

View File

@@ -64,7 +64,10 @@ static void print_interface(struct interface_definition *iface)
}
}
static int ifc(const b_command *self, const b_arglist *opt, const b_array *args)
static int xpcg(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
const char *path = NULL;
b_arglist_get_string(opt, B_COMMAND_INVALID_ID, ARG_SRCPATH, 0, &path);
@@ -132,10 +135,10 @@ static int ifc(const b_command *self, const b_arglist *opt, const b_array *args)
B_COMMAND(CMD_ID, B_COMMAND_INVALID_ID)
{
B_COMMAND_NAME("ifc");
B_COMMAND_DESC("interface definition compiler.");
B_COMMAND_NAME("xpcg");
B_COMMAND_DESC("xpc interface generator.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(ifc);
B_COMMAND_FUNCTION(xpcg);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_SRCPATH)

View File

@@ -4,7 +4,7 @@
#include <stdlib.h>
#include <string.h>
struct msg_definition *msg_definition_create(const char *name)
struct msg_definition *msg_definition_create(const char *name, long long id)
{
struct msg_definition *out = malloc(sizeof *out);
if (!out) {
@@ -14,6 +14,7 @@ struct msg_definition *msg_definition_create(const char *name)
memset(out, 0x0, sizeof *out);
out->msg_name = b_strdup(name);
out->msg_id = id;
return out;
}

View File

@@ -1,5 +1,5 @@
#ifndef IFC_MSG_H_
#define IFC_MSG_H_
#ifndef XPCG_MSG_H_
#define XPCG_MSG_H_
#include <blue/core/queue.h>
@@ -13,13 +13,16 @@ struct msg_parameter {
struct msg_definition {
char *msg_name;
long long msg_id;
b_queue_entry msg_entry;
b_queue msg_params;
b_queue msg_results;
};
extern struct msg_definition *msg_definition_create(const char *name);
extern struct msg_definition *msg_definition_create(
const char *name,
long long id);
extern void msg_definition_destroy(struct msg_definition *msg);
extern bool msg_definition_has_param(

View File

@@ -48,26 +48,55 @@ static bool parse_word(struct lex *lex, char **out)
return true;
}
static bool parse_int(struct lex *lex, long long *out)
{
struct token *tok = lex_peek(lex);
if (!tok || tok->tok_type != TOK_INT) {
return false;
}
*out = tok->tok_int;
lex_advance(lex);
return true;
}
struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
{
struct msg_definition *msg = NULL;
if (!parse_keyword(lex, KW_MSG)) {
report_error("expected `msg` keyword\n");
if (!parse_keyword(lex, KW_FUNC)) {
report_error("expected `func` keyword\n");
goto fail;
}
char *msg_name = NULL;
if (!parse_word(lex, &msg_name)) {
report_error("expected message identifier\n");
report_error("expected function identifier\n");
goto fail;
}
msg = msg_definition_create(msg_name);
long long msg_id = 0;
if (!parse_symbol(lex, SYM_LEFT_BRACKET)) {
report_error("expected `[` after function identifier\n");
goto fail;
}
if (!parse_int(lex, &msg_id)) {
report_error("expected function id number after `[`\n");
goto fail;
}
if (!parse_symbol(lex, SYM_RIGHT_BRACKET)) {
report_error("expected `]` after function id number\n");
goto fail;
}
msg = msg_definition_create(msg_name, msg_id);
free(msg_name);
if (!parse_symbol(lex, SYM_LEFT_PAREN)) {
report_error("expected `(` after message identifier\n");
report_error(
"expected `(` after function id number specifier\n");
goto fail;
}
@@ -79,14 +108,31 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
}
if (i > 0 && !parse_symbol(lex, SYM_COMMA)) {
report_error("expected `,` after message parameter\n");
report_error(
"expected `,` after function "
"parameter\n");
ok = false;
break;
}
char *param_name;
if (!parse_word(lex, &param_name)) {
report_error("expected function parameter name\n");
ok = false;
break;
}
if (!parse_symbol(lex, SYM_COLON)) {
report_error(
"expected `:` after function parameter "
"name\n");
ok = false;
break;
}
char *type_name;
if (!parse_word(lex, &type_name)) {
report_error("expected message parameter type\n");
report_error("expected function parameter type\n");
ok = false;
break;
}
@@ -94,7 +140,7 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
const struct type *type = ctx_get_type(ctx, type_name);
if (!type) {
report_error(
"message parameter has unknown type "
"function parameter has unknown type "
"'%s'\n",
type_name);
free(type_name);
@@ -104,19 +150,13 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
free(type_name);
char *param_name;
if (!parse_word(lex, &param_name)) {
report_error("expected message parameter name\n");
ok = false;
break;
}
bool duplicate = msg_definition_has_param(msg, param_name)
|| msg_definition_has_result(msg, param_name);
if (duplicate) {
free(param_name);
report_error(
"message has multiple parameters/results with "
"function has multiple "
"parameters/results with "
"name '%s'\n",
param_name);
ok = false;
@@ -133,12 +173,14 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
}
if (!parse_symbol(lex, SYM_HYPHEN_RIGHT_ANGLE)) {
report_error("expected `->` after message parameter list\n");
report_error(
"expected `->` after function parameter "
"list\n");
goto fail;
}
if (!parse_symbol(lex, SYM_LEFT_PAREN)) {
report_error("expected `(` for message results list\n");
report_error("expected `(` for function results list\n");
goto fail;
}
@@ -150,14 +192,30 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
if (i > 0 && !parse_symbol(lex, SYM_COMMA)) {
report_error(
"expected `,` or `)` after message result\n");
"expected `,` or `)` after function "
"result\n");
ok = false;
break;
}
char *result_name;
if (!parse_word(lex, &result_name)) {
report_error("expected function parameter name\n");
ok = false;
break;
}
if (!parse_symbol(lex, SYM_COLON)) {
report_error(
"expected `:` after function result "
"name\n");
ok = false;
break;
}
char *type_name;
if (!parse_word(lex, &type_name)) {
report_error("expected message result type\n");
report_error("expected function result type\n");
ok = false;
break;
}
@@ -165,7 +223,7 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
const struct type *type = ctx_get_type(ctx, type_name);
if (!type) {
report_error(
"message result has unknown type "
"function result has unknown type "
"'%s'\n",
type_name);
free(type_name);
@@ -174,18 +232,12 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
}
free(type_name);
char *result_name;
if (!parse_word(lex, &result_name)) {
report_error("expected message parameter name\n");
ok = false;
break;
}
bool duplicate = msg_definition_has_param(msg, result_name)
|| msg_definition_has_result(msg, result_name);
if (duplicate) {
report_error(
"message has multiple parameters/results with "
"function has multiple "
"parameters/results with "
"name '%s'\n",
result_name);
free(result_name);
@@ -199,7 +251,7 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
}
if (!parse_symbol(lex, SYM_SEMICOLON)) {
report_error("expected `;` after message definition\n");
report_error("expected `;` after function definition\n");
goto fail;
}
@@ -226,29 +278,35 @@ struct interface_definition *parse_interface_definition(
char *if_name = NULL;
if (!parse_word(lex, &if_name)) {
report_error("expected interface identifier");
report_error("expected interface name");
goto fail;
}
iface = interface_definition_create(if_name);
long long if_id = 0;
if (!parse_int(lex, &if_id)) {
report_error("expected interface id number");
goto fail;
}
if (!parse_symbol(lex, SYM_SEMICOLON)) {
report_error("expected `;` after interface definition");
goto fail;
}
iface = interface_definition_create(if_name, if_id);
free(if_name);
if (!iface) {
goto fail;
}
if (!parse_symbol(lex, SYM_LEFT_BRACE)) {
report_error("expected `{` after interface identifier");
goto fail;
}
bool ok = true;
while (ok) {
if (parse_symbol(lex, SYM_RIGHT_BRACE)) {
if (!lex_peek(lex) && lex_get_status(lex) == ERR_EOF) {
break;
}
if (peek_keyword(lex, KW_MSG)) {
if (peek_keyword(lex, KW_FUNC)) {
struct msg_definition *msg
= parse_msg_definition(ctx, lex);
if (!msg) {
@@ -268,7 +326,7 @@ struct interface_definition *parse_interface_definition(
continue;
}
report_error("expected `}` or message definition\n");
report_error("expected eof or function definition\n");
ok = false;
break;
}

View File

@@ -1,5 +1,5 @@
#ifndef IFC_PARSE_H_
#define IFC_PARSE_H_
#ifndef XPCG_PARSE_H_
#define XPCG_PARSE_H_
struct ctx;
struct lex;

View File

@@ -1,5 +1,5 @@
#ifndef IFC_STATUS_H_
#define IFC_STATUS_H_
#ifndef XPCG_STATUS_H_
#define XPCG_STATUS_H_
enum status {
SUCCESS = 0,

View File

@@ -40,6 +40,7 @@ const char *token_symbol_to_string(enum token_symbol sym)
ENUM_STR(SYM_NONE);
ENUM_STR(SYM_COMMA);
ENUM_STR(SYM_SEMICOLON);
ENUM_STR(SYM_COLON);
ENUM_STR(SYM_HYPHEN);
ENUM_STR(SYM_LEFT_BRACE);
ENUM_STR(SYM_RIGHT_BRACE);
@@ -56,7 +57,7 @@ const char *token_keyword_to_string(enum token_keyword kw)
switch (kw) {
ENUM_STR(KW_NONE);
ENUM_STR(KW_INTERFACE);
ENUM_STR(KW_MSG);
ENUM_STR(KW_FUNC);
default:
return "";
}

View File

@@ -1,5 +1,5 @@
#ifndef IFC_TOKEN_H_
#define IFC_TOKEN_H_
#ifndef XPCG_TOKEN_H_
#define XPCG_TOKEN_H_
#include "file-span.h"
@@ -34,6 +34,9 @@ enum token_symbol {
SYM_COMMA = __TOK_UBOUND,
SYM_HYPHEN,
SYM_SEMICOLON,
SYM_COLON,
SYM_LEFT_BRACKET,
SYM_RIGHT_BRACKET,
SYM_LEFT_BRACE,
SYM_RIGHT_BRACE,
SYM_LEFT_PAREN,
@@ -45,7 +48,7 @@ enum token_symbol {
enum token_keyword {
KW_NONE = 0,
KW_INTERFACE = __SYM_UBOUND,
KW_MSG,
KW_FUNC,
};
struct token {

View File

@@ -11,6 +11,12 @@ void type_print(const struct type *ty)
case TYPE_STRING:
printf("string");
break;
case TYPE_SIZE:
printf("size");
break;
case TYPE_BUFFER:
printf("buffer");
break;
case TYPE_HANDLE:
printf("handle");
break;

View File

@@ -1,10 +1,12 @@
#ifndef IFC_TYPE_H_
#define IFC_TYPE_H_
#ifndef XPCG_TYPE_H_
#define XPCG_TYPE_H_
enum type_id {
TYPE_NONE,
TYPE_INT,
TYPE_SIZE,
TYPE_STRING,
TYPE_BUFFER,
TYPE_HANDLE,
TYPE_OTHER,
};