toolchain: replace ifc interface compiler with xpcg
xpcg is used to generate xpc interfaces
This commit is contained in:
@@ -14,4 +14,4 @@ add_subdirectory(
|
||||
../kernel/tools
|
||||
${CMAKE_CURRENT_BINARY_DIR}/kernel-tools)
|
||||
|
||||
add_subdirectory(ifc)
|
||||
add_subdirectory(xpcg)
|
||||
|
||||
@@ -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)
|
||||
7
toolchain/xpcg/CMakeLists.txt
Normal file
7
toolchain/xpcg/CMakeLists.txt
Normal 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)
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef IFC_BACKEND_H_
|
||||
#define IFC_BACKEND_H_
|
||||
#ifndef XPCG_BACKEND_H_
|
||||
#define XPCG_BACKEND_H_
|
||||
|
||||
struct interface_definition;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef IFC_CTX_H_
|
||||
#define IFC_CTX_H_
|
||||
#ifndef XPCG_CTX_H_
|
||||
#define XPCG_CTX_H_
|
||||
|
||||
#include "type.h"
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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(
|
||||
@@ -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];
|
||||
|
||||
@@ -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"
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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(
|
||||
@@ -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, ¶m_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, ¶m_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;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef IFC_PARSE_H_
|
||||
#define IFC_PARSE_H_
|
||||
#ifndef XPCG_PARSE_H_
|
||||
#define XPCG_PARSE_H_
|
||||
|
||||
struct ctx;
|
||||
struct lex;
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef IFC_STATUS_H_
|
||||
#define IFC_STATUS_H_
|
||||
#ifndef XPCG_STATUS_H_
|
||||
#define XPCG_STATUS_H_
|
||||
|
||||
enum status {
|
||||
SUCCESS = 0,
|
||||
@@ -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 "";
|
||||
}
|
||||
@@ -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 {
|
||||
@@ -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;
|
||||
@@ -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,
|
||||
};
|
||||
Reference in New Issue
Block a user