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 ../kernel/tools
${CMAKE_CURRENT_BINARY_DIR}/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_ #ifndef XPCG_BACKEND_H_
#define IFC_BACKEND_H_ #define XPCG_BACKEND_H_
struct interface_definition; 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); 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; return NULL;
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -29,18 +29,21 @@
static struct lex_token_def symbols[] = { static struct lex_token_def symbols[] = {
LEX_TOKEN_DEF(SYM_COMMA, ","), LEX_TOKEN_DEF(SYM_COMMA, ","),
LEX_TOKEN_DEF(SYM_HYPHEN, "-"), 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_LEFT_BRACE, "{"),
LEX_TOKEN_DEF(SYM_RIGHT_BRACE, "}"), LEX_TOKEN_DEF(SYM_RIGHT_BRACE, "}"),
LEX_TOKEN_DEF(SYM_LEFT_PAREN, "("), LEX_TOKEN_DEF(SYM_LEFT_PAREN, "("),
LEX_TOKEN_DEF(SYM_RIGHT_PAREN, ")"), LEX_TOKEN_DEF(SYM_RIGHT_PAREN, ")"),
LEX_TOKEN_DEF(SYM_SEMICOLON, ";"), LEX_TOKEN_DEF(SYM_SEMICOLON, ";"),
LEX_TOKEN_DEF(SYM_COLON, ":"),
LEX_TOKEN_DEF(SYM_HYPHEN_RIGHT_ANGLE, "->"), LEX_TOKEN_DEF(SYM_HYPHEN_RIGHT_ANGLE, "->"),
}; };
static const size_t nr_symbols = sizeof symbols / sizeof symbols[0]; static const size_t nr_symbols = sizeof symbols / sizeof symbols[0];
static struct lex_token_def keywords[] = { static struct lex_token_def keywords[] = {
LEX_TOKEN_DEF(KW_INTERFACE, "interface"), 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]; static const size_t nr_keywords = sizeof keywords / sizeof keywords[0];

View File

@@ -1,5 +1,5 @@
#ifndef IFC_LEX_H_ #ifndef XPCG_LEX_H_
#define IFC_LEX_H_ #define XPCG_LEX_H_
#include "status.h" #include "status.h"
#include "token.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; const char *path = NULL;
b_arglist_get_string(opt, B_COMMAND_INVALID_ID, ARG_SRCPATH, 0, &path); 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(CMD_ID, B_COMMAND_INVALID_ID)
{ {
B_COMMAND_NAME("ifc"); B_COMMAND_NAME("xpcg");
B_COMMAND_DESC("interface definition compiler."); B_COMMAND_DESC("xpc interface generator.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT); B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(ifc); B_COMMAND_FUNCTION(xpcg);
B_COMMAND_HELP_OPTION(); B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_SRCPATH) B_COMMAND_ARG(ARG_SRCPATH)

View File

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

View File

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

View File

@@ -48,26 +48,55 @@ static bool parse_word(struct lex *lex, char **out)
return true; 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 *parse_msg_definition(struct ctx *ctx, struct lex *lex)
{ {
struct msg_definition *msg = NULL; struct msg_definition *msg = NULL;
if (!parse_keyword(lex, KW_MSG)) { if (!parse_keyword(lex, KW_FUNC)) {
report_error("expected `msg` keyword\n"); report_error("expected `func` keyword\n");
goto fail; goto fail;
} }
char *msg_name = NULL; char *msg_name = NULL;
if (!parse_word(lex, &msg_name)) { if (!parse_word(lex, &msg_name)) {
report_error("expected message identifier\n"); report_error("expected function identifier\n");
goto fail; 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); free(msg_name);
if (!parse_symbol(lex, SYM_LEFT_PAREN)) { 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; 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)) { 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; ok = false;
break; break;
} }
char *type_name; char *type_name;
if (!parse_word(lex, &type_name)) { if (!parse_word(lex, &type_name)) {
report_error("expected message parameter type\n"); report_error("expected function parameter type\n");
ok = false; ok = false;
break; 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); const struct type *type = ctx_get_type(ctx, type_name);
if (!type) { if (!type) {
report_error( report_error(
"message parameter has unknown type " "function parameter has unknown type "
"'%s'\n", "'%s'\n",
type_name); type_name);
free(type_name); free(type_name);
@@ -104,19 +150,13 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
free(type_name); 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) bool duplicate = msg_definition_has_param(msg, param_name)
|| msg_definition_has_result(msg, param_name); || msg_definition_has_result(msg, param_name);
if (duplicate) { if (duplicate) {
free(param_name); free(param_name);
report_error( report_error(
"message has multiple parameters/results with " "function has multiple "
"parameters/results with "
"name '%s'\n", "name '%s'\n",
param_name); param_name);
ok = false; 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)) { 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; goto fail;
} }
if (!parse_symbol(lex, SYM_LEFT_PAREN)) { 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; 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)) { if (i > 0 && !parse_symbol(lex, SYM_COMMA)) {
report_error( 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; ok = false;
break; break;
} }
char *type_name; char *type_name;
if (!parse_word(lex, &type_name)) { if (!parse_word(lex, &type_name)) {
report_error("expected message result type\n"); report_error("expected function result type\n");
ok = false; ok = false;
break; 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); const struct type *type = ctx_get_type(ctx, type_name);
if (!type) { if (!type) {
report_error( report_error(
"message result has unknown type " "function result has unknown type "
"'%s'\n", "'%s'\n",
type_name); type_name);
free(type_name); free(type_name);
@@ -174,18 +232,12 @@ struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex)
} }
free(type_name); 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) bool duplicate = msg_definition_has_param(msg, result_name)
|| msg_definition_has_result(msg, result_name); || msg_definition_has_result(msg, result_name);
if (duplicate) { if (duplicate) {
report_error( report_error(
"message has multiple parameters/results with " "function has multiple "
"parameters/results with "
"name '%s'\n", "name '%s'\n",
result_name); result_name);
free(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)) { if (!parse_symbol(lex, SYM_SEMICOLON)) {
report_error("expected `;` after message definition\n"); report_error("expected `;` after function definition\n");
goto fail; goto fail;
} }
@@ -226,29 +278,35 @@ struct interface_definition *parse_interface_definition(
char *if_name = NULL; char *if_name = NULL;
if (!parse_word(lex, &if_name)) { if (!parse_word(lex, &if_name)) {
report_error("expected interface identifier"); report_error("expected interface name");
goto fail; 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); free(if_name);
if (!iface) { if (!iface) {
goto fail; goto fail;
} }
if (!parse_symbol(lex, SYM_LEFT_BRACE)) {
report_error("expected `{` after interface identifier");
goto fail;
}
bool ok = true; bool ok = true;
while (ok) { while (ok) {
if (parse_symbol(lex, SYM_RIGHT_BRACE)) { if (!lex_peek(lex) && lex_get_status(lex) == ERR_EOF) {
break; break;
} }
if (peek_keyword(lex, KW_MSG)) { if (peek_keyword(lex, KW_FUNC)) {
struct msg_definition *msg struct msg_definition *msg
= parse_msg_definition(ctx, lex); = parse_msg_definition(ctx, lex);
if (!msg) { if (!msg) {
@@ -268,7 +326,7 @@ struct interface_definition *parse_interface_definition(
continue; continue;
} }
report_error("expected `}` or message definition\n"); report_error("expected eof or function definition\n");
ok = false; ok = false;
break; break;
} }

View File

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

View File

@@ -1,5 +1,5 @@
#ifndef IFC_STATUS_H_ #ifndef XPCG_STATUS_H_
#define IFC_STATUS_H_ #define XPCG_STATUS_H_
enum status { enum status {
SUCCESS = 0, 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_NONE);
ENUM_STR(SYM_COMMA); ENUM_STR(SYM_COMMA);
ENUM_STR(SYM_SEMICOLON); ENUM_STR(SYM_SEMICOLON);
ENUM_STR(SYM_COLON);
ENUM_STR(SYM_HYPHEN); ENUM_STR(SYM_HYPHEN);
ENUM_STR(SYM_LEFT_BRACE); ENUM_STR(SYM_LEFT_BRACE);
ENUM_STR(SYM_RIGHT_BRACE); ENUM_STR(SYM_RIGHT_BRACE);
@@ -56,7 +57,7 @@ const char *token_keyword_to_string(enum token_keyword kw)
switch (kw) { switch (kw) {
ENUM_STR(KW_NONE); ENUM_STR(KW_NONE);
ENUM_STR(KW_INTERFACE); ENUM_STR(KW_INTERFACE);
ENUM_STR(KW_MSG); ENUM_STR(KW_FUNC);
default: default:
return ""; return "";
} }

View File

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

View File

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

View File

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