Files
rosetta/toolchain/xpcg/main.c
Max Wash 26a49162e6 toolchain: replace ifc interface compiler with xpcg
xpcg is used to generate xpc interfaces
2026-03-10 19:12:14 +00:00

170 lines
3.4 KiB
C

#include "backend.h"
#include "ctx.h"
#include "interface.h"
#include "lex.h"
#include "line-source.h"
#include "msg.h"
#include "parse.h"
#include <blue/cmd.h>
#include <blue/io/file.h>
#include <blue/io/path.h>
#define CMD_ID 0
enum {
ARG_SRCPATH,
OPT_BACKEND,
OPT_BACKEND_ARG_NAME,
};
int main(int argc, const char **argv)
{
return b_command_dispatch(CMD_ID, argc, argv);
}
static void print_msg(struct msg_definition *msg)
{
printf(" msg: %s\n", msg->msg_name);
b_queue_entry *entry = b_queue_first(&msg->msg_params);
while (entry) {
struct msg_parameter *param
= b_unbox(struct msg_parameter, entry, p_entry);
printf(" param:");
type_print(param->p_type);
printf(" %s\n", param->p_name);
entry = b_queue_next(entry);
}
entry = b_queue_first(&msg->msg_results);
while (entry) {
struct msg_parameter *param
= b_unbox(struct msg_parameter, entry, p_entry);
printf(" result:");
type_print(param->p_type);
printf(" %s\n", param->p_name);
entry = b_queue_next(entry);
}
}
static void print_interface(struct interface_definition *iface)
{
printf("interface: %s\n", iface->if_name);
b_queue_entry *entry = b_queue_first(&iface->if_msg);
while (entry) {
struct msg_definition *msg
= b_unbox(struct msg_definition, entry, msg_entry);
print_msg(msg);
entry = b_queue_next(entry);
}
}
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);
if (!path) {
b_arglist_report_missing_args(
opt,
B_COMMAND_INVALID_ID,
ARG_SRCPATH,
0);
return -1;
}
b_file *file = NULL;
b_result result
= b_file_open(NULL, B_RV_PATH(path), B_FILE_READ_ONLY, &file);
if (b_result_is_error(result)) {
b_throw(result);
return -1;
}
struct line_source src;
line_source_init(&src, path, file);
struct ctx *ctx = ctx_create();
struct lex *lex = lex_create(&src);
#if 0
struct token *tok = lex_peek(lex);
while (tok) {
printf("%s", token_type_to_string(tok->tok_type));
switch (tok->tok_value_type) {
case TOK_V_INT:
printf(" %lld", tok->tok_int);
break;
case TOK_V_STRING:
printf(" %s", tok->tok_str);
break;
case TOK_V_SYMBOL:
printf(" %s", token_symbol_to_string(tok->tok_sym));
break;
case TOK_V_KEYWORD:
printf(" %s", token_keyword_to_string(tok->tok_kw));
break;
default:
break;
}
printf("\n");
lex_advance(lex);
tok = lex_peek(lex);
}
#endif
struct interface_definition *iface
= parse_interface_definition(ctx, lex);
if (!iface) {
return -1;
}
const struct backend *backend = c_mpc_backend();
int err = backend->b_emit(iface);
return err;
}
B_COMMAND(CMD_ID, B_COMMAND_INVALID_ID)
{
B_COMMAND_NAME("xpcg");
B_COMMAND_DESC("xpc interface generator.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(xpcg);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_SRCPATH)
{
B_ARG_NAME("source-file");
B_ARG_DESC("the interface file to compile.");
B_ARG_NR_VALUES(1);
}
B_COMMAND_OPTION(OPT_BACKEND)
{
B_OPTION_LONG_NAME("backend");
B_OPTION_SHORT_NAME('b');
B_OPTION_DESC("which backend to use.");
B_OPTION_ARG(OPT_BACKEND_ARG_NAME)
{
B_ARG_NAME("backend-name");
B_ARG_NR_VALUES(1);
B_ARG_ALLOWED_VALUES("c-mpc");
}
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_ARG(ARG_SRCPATH);
B_COMMAND_USAGE_OPT(OPT_BACKEND);
}
}