mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Feature/add target (#1) project add-target command
This commit is contained in:
@@ -3,8 +3,8 @@
|
||||
// Use of this source code is governed by the GNU LGPLv3.0 license
|
||||
// a copy of which can be found in the LICENSE file.
|
||||
|
||||
#include "../version.h"
|
||||
#include "../utils/lib.h"
|
||||
#include "../version.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAX_BUILD_LIB_DIRS 1024
|
||||
@@ -48,16 +48,16 @@ typedef enum
|
||||
COMMAND_PROJECT,
|
||||
} CompilerCommand;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SUBCOMMAND_MISSING = 0,
|
||||
SUBCOMMAND_VIEW
|
||||
SUBCOMMAND_VIEW,
|
||||
SUBCOMMAND_ADD
|
||||
} ProjectSubcommand;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DIAG_NONE = 0, // Don't use!
|
||||
DIAG_NONE = 0, // Don't use!
|
||||
DIAG_WARNING_TYPE, // Don't use!
|
||||
DIAG_UNUSED,
|
||||
DIAG_UNUSED_PARAMETER,
|
||||
@@ -133,10 +133,10 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
OPTIMIZATION_NOT_SET = -1,
|
||||
OPTIMIZATION_NONE = 0, // -O0
|
||||
OPTIMIZATION_LESS = 1, // -O1
|
||||
OPTIMIZATION_MORE = 2, // -O2
|
||||
OPTIMIZATION_AGGRESSIVE = 3, // -O3
|
||||
OPTIMIZATION_NONE = 0, // -O0
|
||||
OPTIMIZATION_LESS = 1, // -O1
|
||||
OPTIMIZATION_MORE = 2, // -O2
|
||||
OPTIMIZATION_AGGRESSIVE = 3, // -O3
|
||||
} OptimizationLevel;
|
||||
|
||||
typedef enum
|
||||
@@ -149,7 +149,7 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
SINGLE_MODULE_NOT_SET = -1,
|
||||
SINGLE_MODULE_OFF = 0, // NOLINT
|
||||
SINGLE_MODULE_OFF = 0, // NOLINT
|
||||
SINGLE_MODULE_ON = 1
|
||||
} SingleModule;
|
||||
|
||||
@@ -211,9 +211,9 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
SIZE_OPTIMIZATION_NOT_SET = -1,
|
||||
SIZE_OPTIMIZATION_NONE = 0, // None
|
||||
SIZE_OPTIMIZATION_SMALL = 1, // -Os
|
||||
SIZE_OPTIMIZATION_TINY = 2, // -Oz
|
||||
SIZE_OPTIMIZATION_NONE = 0, // None
|
||||
SIZE_OPTIMIZATION_SMALL = 1, // -Os
|
||||
SIZE_OPTIMIZATION_TINY = 2, // -Oz
|
||||
} SizeOptimizationLevel;
|
||||
|
||||
typedef enum
|
||||
@@ -233,7 +233,7 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
STRUCT_RETURN_DEFAULT = -1,
|
||||
STRUCT_RETURN_STACK = 0, // NOLINT
|
||||
STRUCT_RETURN_STACK = 0, // NOLINT
|
||||
STRUCT_RETURN_REG = 1
|
||||
} StructReturn;
|
||||
|
||||
@@ -351,6 +351,34 @@ typedef enum
|
||||
|
||||
#define ANY_WINDOWS_ARCH_OS WINDOWS_AARCH64: case WINDOWS_X64: case MINGW_X64
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TARGET_TYPE_EXECUTABLE,
|
||||
TARGET_TYPE_STATIC_LIB,
|
||||
TARGET_TYPE_DYNAMIC_LIB,
|
||||
TARGET_TYPE_OBJECT_FILES,
|
||||
TARGET_TYPE_BENCHMARK,
|
||||
TARGET_TYPE_TEST,
|
||||
} TargetType;
|
||||
|
||||
static const char *targets[6] = {
|
||||
[TARGET_TYPE_EXECUTABLE] = "executable",
|
||||
[TARGET_TYPE_STATIC_LIB] = "static-lib",
|
||||
[TARGET_TYPE_DYNAMIC_LIB] = "dynamic-lib",
|
||||
[TARGET_TYPE_BENCHMARK] = "benchmark",
|
||||
[TARGET_TYPE_TEST] = "test",
|
||||
[TARGET_TYPE_OBJECT_FILES] = "object-files"
|
||||
};
|
||||
static const char *target_desc[6] = {
|
||||
[TARGET_TYPE_EXECUTABLE] = "Executable",
|
||||
[TARGET_TYPE_STATIC_LIB] = "Static library",
|
||||
[TARGET_TYPE_DYNAMIC_LIB] = "Dynamic library",
|
||||
[TARGET_TYPE_BENCHMARK] = "benchmark suite",
|
||||
[TARGET_TYPE_TEST] = "test suite",
|
||||
[TARGET_TYPE_OBJECT_FILES] = "object files"
|
||||
};
|
||||
|
||||
|
||||
typedef struct BuildOptions_
|
||||
{
|
||||
const char *lib_dir[MAX_BUILD_LIB_DIRS];
|
||||
@@ -365,17 +393,20 @@ typedef struct BuildOptions_
|
||||
size_t linker_lib_count;
|
||||
const char* std_lib_dir;
|
||||
VectorConv vector_conv;
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
const char *sdk;
|
||||
const char *def;
|
||||
WinCrtLinking crt_linking;
|
||||
} win;
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
const char *sysroot;
|
||||
const char *min_version;
|
||||
const char *sdk_version;
|
||||
} macos;
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
const char *crt;
|
||||
const char *crtbegin;
|
||||
} linuxpaths;
|
||||
@@ -397,7 +428,12 @@ typedef struct BuildOptions_
|
||||
bool silence_deprecation;
|
||||
CompilerBackend backend;
|
||||
CompilerCommand command;
|
||||
ProjectSubcommand subcommand;
|
||||
struct
|
||||
{
|
||||
ProjectSubcommand command;
|
||||
const char *target_name;
|
||||
TargetType target_type;
|
||||
} project_options;
|
||||
CompileOption compile_option;
|
||||
TrustLevel trust_level;
|
||||
DiagnosticsSeverity severity[DIAG_END_SENTINEL];
|
||||
@@ -459,16 +495,6 @@ typedef struct BuildOptions_
|
||||
bool testing;
|
||||
} BuildOptions;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TARGET_TYPE_EXECUTABLE,
|
||||
TARGET_TYPE_STATIC_LIB,
|
||||
TARGET_TYPE_DYNAMIC_LIB,
|
||||
TARGET_TYPE_OBJECT_FILES,
|
||||
TARGET_TYPE_BENCHMARK,
|
||||
TARGET_TYPE_TEST,
|
||||
} TargetType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct Library__ *parent;
|
||||
@@ -500,7 +526,6 @@ typedef struct Library__
|
||||
LibraryTarget **targets;
|
||||
} Library;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TargetType type;
|
||||
@@ -681,8 +706,10 @@ BuildOptions parse_arguments(int argc, const char *argv[]);
|
||||
ArchOsTarget arch_os_target_from_string(const char *target);
|
||||
bool command_accepts_files(CompilerCommand command);
|
||||
bool command_passes_args(CompilerCommand command);
|
||||
void update_build_target_with_opt_level(BuildTarget *target, OptimizationSetting level);
|
||||
void update_build_target_with_opt_level(BuildTarget *target,
|
||||
OptimizationSetting level);
|
||||
void create_project(BuildOptions *build_options);
|
||||
void create_library(BuildOptions *build_options);
|
||||
void resolve_libraries(BuildTarget *build_target);
|
||||
void view_project(BuildOptions *build_options);
|
||||
void view_project(BuildOptions *build_options);
|
||||
void add_target_project(BuildOptions *build_options);
|
||||
|
||||
@@ -104,7 +104,7 @@ BuildTarget *project_select_target(Project *project, const char *optional_target
|
||||
void update_feature_flags(const char ***flags, const char ***removed_flag, const char *arg, bool add);
|
||||
|
||||
const char *get_string(const char *file, const char *category, JSONObject *table, const char *key,
|
||||
const char *default_value);
|
||||
const char *default_value);
|
||||
int get_valid_bool(const char *file, const char *target, JSONObject *json, const char *key, int default_val);
|
||||
const char *get_optional_string(const char *file, const char *category, JSONObject *table, const char *key);
|
||||
const char *get_mandatory_string(const char *file, const char *category, JSONObject *object, const char *key);
|
||||
@@ -112,7 +112,8 @@ const char **get_string_array(const char *file, const char *category, JSONObject
|
||||
const char **get_optional_string_array(const char *file, const char *target, JSONObject *table, const char *key);
|
||||
const char *get_cflags(const char *file, const char *target, JSONObject *json, const char *original_flags);
|
||||
void get_list_append_strings(const char *file, const char *target, JSONObject *json, const char ***list_ptr,
|
||||
const char *base, const char *override, const char *add);
|
||||
int get_valid_string_setting(const char *file, const char *target, JSONObject *json, const char *key, const char** values, int first_result, int count, const char *expected);
|
||||
void check_json_keys(const char* valid_keys[][2], size_t key_count, const char* deprecated_keys[], size_t deprecated_key_count, JSONObject *json, const char *target_name, const char *option);
|
||||
const char *base, const char *override, const char *add);
|
||||
int get_valid_string_setting(const char *file, const char *target, JSONObject *json, const char *key, const char **values, int first_result, int count, const char *expected);
|
||||
int get_valid_enum_from_string(const char *str, const char *target, const char **values, int count, const char *expected);
|
||||
void check_json_keys(const char *valid_keys[][2], size_t key_count, const char *deprecated_keys[], size_t deprecated_key_count, JSONObject *json, const char *target_name, const char *option);
|
||||
long get_valid_integer(JSONObject *table, const char *key, const char *category, bool mandatory);
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
// Use of this source code is governed by the GNU LGPLv3.0 license
|
||||
// a copy of which can be found in the LICENSE file.
|
||||
|
||||
#include "build_internal.h"
|
||||
#include "../utils/whereami.h"
|
||||
#include "build.h"
|
||||
#include "build_internal.h"
|
||||
|
||||
extern int llvm_version_major;
|
||||
bool silence_deprecation;
|
||||
@@ -216,7 +217,6 @@ static inline const char *next_arg()
|
||||
return current_arg;
|
||||
}
|
||||
|
||||
|
||||
static inline bool next_is_opt()
|
||||
{
|
||||
return args[arg_index + 1][0] == '-';
|
||||
@@ -283,26 +283,43 @@ static void project_usage()
|
||||
PRINTF("Usage: %s [<options>] project <subcommand> [<args>]", args[0]);
|
||||
PRINTF("");
|
||||
PRINTF("Project Subcommands:");
|
||||
PRINTF(" view view the current projects structure");
|
||||
PRINTF(" view view the current projects structure");
|
||||
PRINTF(" add-target <name> <target_type> add a new target to the project");
|
||||
}
|
||||
|
||||
static void parse_project_subcommand(BuildOptions *options)
|
||||
{
|
||||
if (arg_match("view"))
|
||||
{
|
||||
options->subcommand = SUBCOMMAND_VIEW;
|
||||
options->project_options.command = SUBCOMMAND_VIEW;
|
||||
return;
|
||||
}
|
||||
PROJECT_FAIL_WITH_ERR("Cannot process the unknown subcommand \"%s\".", current_arg);
|
||||
if (arg_match("add-target"))
|
||||
{
|
||||
options->project_options.command = SUBCOMMAND_ADD;
|
||||
|
||||
if (at_end() || next_is_opt()) error_exit("Expected a target name");
|
||||
options->project_options.target_name = next_arg();
|
||||
|
||||
if (at_end() || next_is_opt()) error_exit("Expected a target type like 'executable' or 'static-lib'");
|
||||
options->project_options.target_type = (TargetType)get_valid_enum_from_string(next_arg(), "type", targets, ELEMENTLEN(targets), "a target type like 'executable' or 'static-lib'");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PROJECT_FAIL_WITH_ERR("Cannot process the unknown subcommand \"%s\".",
|
||||
current_arg);
|
||||
}
|
||||
|
||||
static void parse_project_options(BuildOptions *options)
|
||||
{
|
||||
options->project_options.command = SUBCOMMAND_MISSING;
|
||||
if (at_end())
|
||||
{
|
||||
project_usage();
|
||||
return;
|
||||
}
|
||||
|
||||
next_arg();
|
||||
parse_project_subcommand(options);
|
||||
}
|
||||
@@ -437,7 +454,6 @@ static void parse_command(BuildOptions *options)
|
||||
if (arg_match("project"))
|
||||
{
|
||||
options->command = COMMAND_PROJECT;
|
||||
options->subcommand = SUBCOMMAND_MISSING;
|
||||
parse_project_options(options);
|
||||
return;
|
||||
}
|
||||
@@ -1185,7 +1201,6 @@ static void parse_option(BuildOptions *options)
|
||||
FAIL_WITH_ERR("Cannot process the unknown option \"%s\".", current_arg);
|
||||
}
|
||||
|
||||
|
||||
BuildOptions parse_arguments(int argc, const char *argv[])
|
||||
{
|
||||
arg_count = argc;
|
||||
@@ -1284,7 +1299,6 @@ BuildOptions parse_arguments(int argc, const char *argv[])
|
||||
return build_options;
|
||||
}
|
||||
|
||||
|
||||
ArchOsTarget arch_os_target_from_string(const char *target)
|
||||
{
|
||||
for (unsigned i = 1; i <= ARCH_OS_TARGET_LAST; i++)
|
||||
|
||||
@@ -180,6 +180,17 @@ int get_valid_string_setting(const char *file, const char *target, JSONObject *j
|
||||
error_exit("In file '%s': Invalid value for '%s', expected %s", file, key, expected);
|
||||
}
|
||||
|
||||
int get_valid_enum_from_string(const char *str, const char *target, const char **values, int count, const char *expected)
|
||||
{
|
||||
int res = str_findlist(str, count, values);
|
||||
if (res >= 0) return res;
|
||||
if (target)
|
||||
{
|
||||
error_exit("'%s' had an invalid value, expected %s", target, expected);
|
||||
}
|
||||
error_exit("Invalid value, expected %s", expected);
|
||||
}
|
||||
|
||||
long get_valid_integer(JSONObject *table, const char *key, const char *category, bool mandatory)
|
||||
{
|
||||
JSONObject *value = json_obj_get(table, key);
|
||||
|
||||
@@ -423,22 +423,6 @@ static void project_add_target(Project *project, BuildTarget *default_target, J
|
||||
static void project_add_targets(Project *project, JSONObject *project_data)
|
||||
{
|
||||
assert(project_data->type == J_OBJECT);
|
||||
static const char* targets[6] = {
|
||||
[TARGET_TYPE_EXECUTABLE] = "executable",
|
||||
[TARGET_TYPE_STATIC_LIB] = "static-lib",
|
||||
[TARGET_TYPE_DYNAMIC_LIB] = "dynamic-lib",
|
||||
[TARGET_TYPE_BENCHMARK] = "benchmark",
|
||||
[TARGET_TYPE_TEST] = "test",
|
||||
[TARGET_TYPE_OBJECT_FILES] = "object-files"
|
||||
};
|
||||
static const char *target_desc[6] = {
|
||||
[TARGET_TYPE_EXECUTABLE] = "Executable",
|
||||
[TARGET_TYPE_STATIC_LIB] = "Static library",
|
||||
[TARGET_TYPE_DYNAMIC_LIB] = "Dynamic library",
|
||||
[TARGET_TYPE_BENCHMARK] = "benchmark suite",
|
||||
[TARGET_TYPE_TEST] = "test suite",
|
||||
[TARGET_TYPE_OBJECT_FILES] = "object files"
|
||||
};
|
||||
|
||||
BuildTarget default_target = default_build_target;
|
||||
load_into_build_target(project_data, NULL, &default_target);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "build_internal.h"
|
||||
#define PRINTFN(string, ...) fprintf(stdout, string "\n", ##__VA_ARGS__) // NOLINT
|
||||
#define PRINTF(string, ...) fprintf(stdout, string, ##__VA_ARGS__) // NOLINT
|
||||
static JSONObject* read_project()
|
||||
static JSONObject *read_project()
|
||||
{
|
||||
size_t size;
|
||||
char *read = file_read_all(PROJECT_JSON, &size);
|
||||
@@ -19,52 +19,52 @@ static JSONObject* read_project()
|
||||
return json;
|
||||
}
|
||||
|
||||
static void print_vec(const char* header, const char** vec, bool opt)
|
||||
static void print_vec(const char *header, const char **vec, bool opt)
|
||||
{
|
||||
if (opt && !vec) return;
|
||||
PRINTF("%s: ", header);
|
||||
if (!vec_size(vec))
|
||||
if (!vec_size(vec))
|
||||
{
|
||||
PRINTFN("*none*");
|
||||
return;
|
||||
}
|
||||
FOREACH_IDX(i, const char *, item, vec)
|
||||
}
|
||||
FOREACH_IDX(i, const char *, item, vec)
|
||||
{
|
||||
if (i > 0) PRINTF(", ");
|
||||
PRINTF("%s",item);
|
||||
PRINTF("%s", item);
|
||||
}
|
||||
PRINTFN("");
|
||||
}
|
||||
|
||||
static void print_opt_str(const char* header, const char* str)
|
||||
static void print_opt_str(const char *header, const char *str)
|
||||
{
|
||||
if (!str) return;
|
||||
PRINTFN("%s: %s", header, str);
|
||||
}
|
||||
|
||||
static void print_opt_setting(const char* header, int setting, const char** values)
|
||||
static void print_opt_setting(const char *header, int setting, const char **values)
|
||||
{
|
||||
if (setting < 0) return;
|
||||
PRINTFN("%s: %s", header, values[setting]);
|
||||
}
|
||||
|
||||
static void print_opt_bool(const char* header, int b)
|
||||
static void print_opt_bool(const char *header, int b)
|
||||
{
|
||||
if (b == -1) return;
|
||||
PRINTF("%s: ", header);
|
||||
PRINTFN(b ? "true" : "false");
|
||||
}
|
||||
|
||||
static void print_opt_int(const char* header, long v)
|
||||
static void print_opt_int(const char *header, long v)
|
||||
{
|
||||
if (v < 0) return;
|
||||
PRINTFN("%s: %ld", header, v);
|
||||
}
|
||||
|
||||
static const char* generate_expected(const char** options, size_t n)
|
||||
static const char *generate_expected(const char **options, size_t n)
|
||||
{
|
||||
scratch_buffer_clear();
|
||||
for (size_t i = 0; i < n; i++)
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
if (i > 0) scratch_buffer_append(", ");
|
||||
if (i == n - 1) scratch_buffer_append(" or ");
|
||||
@@ -74,7 +74,7 @@ static const char* generate_expected(const char** options, size_t n)
|
||||
}
|
||||
|
||||
|
||||
const char* optimization_levels[] = {
|
||||
const char *optimization_levels[] = {
|
||||
[OPT_SETTING_O0] = "O0",
|
||||
[OPT_SETTING_O1] = "O1",
|
||||
[OPT_SETTING_O2] = "O2",
|
||||
@@ -82,10 +82,10 @@ const char* optimization_levels[] = {
|
||||
[OPT_SETTING_O4] = "O4",
|
||||
[OPT_SETTING_O5] = "O5",
|
||||
[OPT_SETTING_OSMALL] = "Os",
|
||||
[OPT_SETTING_OTINY] = "Oz"
|
||||
[OPT_SETTING_OTINY] = "Oz"
|
||||
};
|
||||
|
||||
const char* debug_levels[] = {
|
||||
const char *debug_levels[] = {
|
||||
[DEBUG_INFO_NONE] = "none",
|
||||
[DEBUG_INFO_LINE_TABLES] = "line-tables",
|
||||
[DEBUG_INFO_FULL] = "full"
|
||||
@@ -171,12 +171,12 @@ do {\
|
||||
print_opt_int("\t" header, v);\
|
||||
} while(0);
|
||||
|
||||
static void view_target(const char* name, JSONObject* target)
|
||||
static void view_target(const char *name, JSONObject *target)
|
||||
{
|
||||
/* General target information */
|
||||
PRINTFN("- %s",name);
|
||||
PRINTFN("- %s", name);
|
||||
print_opt_str("\tName", name);
|
||||
TARGET_VIEW_MANDATORY_STRING("Type","type");
|
||||
TARGET_VIEW_MANDATORY_STRING("Type", "type");
|
||||
TARGET_VIEW_STRING("Target language target", "langrev");
|
||||
TARGET_VIEW_STRING_ARRAY("Warnings used", "warnings");
|
||||
TARGET_VIEW_STRING_ARRAY("Additional c3l library search paths", "dependency-search-paths");
|
||||
@@ -204,7 +204,7 @@ static void view_target(const char* name, JSONObject* target)
|
||||
TARGET_VIEW_SETTING("Floating point behaviour", "fp-math", fp_math);
|
||||
TARGET_VIEW_STRING_ARRAY("Additional linked libraries", "linked-libraries");
|
||||
TARGET_VIEW_STRING_ARRAY("Linked libraries (override)", "linked-libraries-override");
|
||||
TARGET_VIEW_STRING("Linker","linker");
|
||||
TARGET_VIEW_STRING("Linker", "linker");
|
||||
TARGET_VIEW_STRING_ARRAY("Additional linker search paths", "linker-search-paths");
|
||||
TARGET_VIEW_STRING_ARRAY("Linker search paths (override)", "linker-search-paths-override");
|
||||
TARGET_VIEW_STRING_ARRAY("Additional linker arguments", "link-args");
|
||||
@@ -236,13 +236,52 @@ static void view_target(const char* name, JSONObject* target)
|
||||
TARGET_VIEW_BOOL("Return structs on the stack", "x86-stack-struct-return");
|
||||
}
|
||||
|
||||
void view_project(BuildOptions *build_options)
|
||||
void add_target_project(BuildOptions *build_options)
|
||||
{
|
||||
JSONObject* project_json = read_project();
|
||||
JSONObject *project_json = read_project();
|
||||
JSONObject *targets_json = json_obj_get(project_json, "targets");
|
||||
|
||||
for (unsigned i = 0; i < targets_json->member_len; i++)
|
||||
{
|
||||
JSONObject *object = targets_json->members[i];
|
||||
const char *key = targets_json->keys[i];
|
||||
|
||||
if (str_eq(key, build_options->project_options.target_name))
|
||||
{
|
||||
error_exit("Target with name '%s' already exists", key);
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject *target_type_obj = json_new_object(&malloc_arena, J_STRING);
|
||||
target_type_obj->str = targets[build_options->project_options.target_type];
|
||||
|
||||
|
||||
JSONObject *new_target = json_new_object(&malloc_arena, J_OBJECT);
|
||||
new_target->members = malloc_arena(sizeof(JSONObject) * 16);
|
||||
new_target->keys = malloc_arena(sizeof(JSONObject) * 16);
|
||||
|
||||
new_target->keys[0] = "type";
|
||||
new_target->members[0] = target_type_obj;
|
||||
new_target->member_len = 1;
|
||||
|
||||
|
||||
size_t index = targets_json->member_len;
|
||||
targets_json->members[index] = new_target;
|
||||
targets_json->keys[index] = build_options->project_options.target_name;
|
||||
targets_json->member_len++;
|
||||
|
||||
FILE *file = fopen(PROJECT_JSON, "w");
|
||||
print_json_to_file(project_json, file);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
void view_project(BuildOptions *build_options)
|
||||
{
|
||||
JSONObject *project_json = read_project();
|
||||
|
||||
/* General information */
|
||||
VIEW_MANDATORY_STRING_ARRAY("Authors","authors");
|
||||
VIEW_MANDATORY_STRING("Version","version");
|
||||
VIEW_MANDATORY_STRING_ARRAY("Authors", "authors");
|
||||
VIEW_MANDATORY_STRING("Version", "version");
|
||||
VIEW_MANDATORY_STRING("Project language target", "langrev");
|
||||
VIEW_MANDATORY_STRING_ARRAY("Warnings used", "warnings");
|
||||
VIEW_MANDATORY_STRING_ARRAY("c3l library search paths", "dependency-search-paths");
|
||||
@@ -262,7 +301,7 @@ void view_project(BuildOptions *build_options)
|
||||
VIEW_STRING_ARRAY("Enabled features", "features");
|
||||
VIEW_SETTING("Floating point behaviour", "fp-math", fp_math);
|
||||
VIEW_STRING_ARRAY("Linked libraries", "linked-libraries");
|
||||
VIEW_STRING("Linker","linker");
|
||||
VIEW_STRING("Linker", "linker");
|
||||
VIEW_STRING_ARRAY("Linker search paths", "linker-search-paths");
|
||||
VIEW_STRING_ARRAY("Linker arguments", "link-args");
|
||||
VIEW_BOOL("Link libc", "link-libc");
|
||||
@@ -303,14 +342,15 @@ void view_project(BuildOptions *build_options)
|
||||
error_exit("'targets' did not contain map of targets.");
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < targets_json->member_len; i++)
|
||||
for (unsigned i = 0; i < targets_json->member_len; i++)
|
||||
{
|
||||
JSONObject *object = targets_json->members[i];
|
||||
const char *key = targets_json->keys[i];
|
||||
|
||||
if (object->type != J_OBJECT)
|
||||
{
|
||||
error_exit("Invalid data in target '%s'", key);
|
||||
}
|
||||
view_target(key,object);
|
||||
view_target(key, object);
|
||||
}
|
||||
}
|
||||
|
||||
21
src/main.c
21
src/main.c
@@ -1,8 +1,9 @@
|
||||
#include <compiler_tests/benchmark.h>
|
||||
#include "compiler/compiler.h"
|
||||
#include "build/build.h"
|
||||
#include "compiler/compiler.h"
|
||||
#include "compiler_tests/tests.h"
|
||||
#include "utils/lib.h"
|
||||
#include <compiler_tests/benchmark.h>
|
||||
|
||||
|
||||
bool debug_log = false;
|
||||
bool debug_stats = false;
|
||||
@@ -99,13 +100,16 @@ int main_real(int argc, const char *argv[])
|
||||
compile_file_list(&build_options);
|
||||
break;
|
||||
case COMMAND_PROJECT:
|
||||
switch (build_options.subcommand)
|
||||
switch (build_options.project_options.command)
|
||||
{
|
||||
case SUBCOMMAND_VIEW:
|
||||
view_project(&build_options);
|
||||
break;
|
||||
case SUBCOMMAND_ADD:
|
||||
add_target_project(&build_options);
|
||||
break;
|
||||
case SUBCOMMAND_MISSING:
|
||||
UNREACHABLE
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case COMMAND_MISSING:
|
||||
@@ -121,7 +125,7 @@ int main_real(int argc, const char *argv[])
|
||||
|
||||
int wmain(int argc, const uint16_t *argv[])
|
||||
{
|
||||
char** args = malloc(sizeof(void*) * (unsigned)argc);
|
||||
char **args = malloc(sizeof(void *) * (unsigned)argc);
|
||||
for (unsigned i = 0; i < (unsigned)argc; i++)
|
||||
{
|
||||
args[i] = win_utf16to8(argv[i]);
|
||||
@@ -131,9 +135,6 @@ int wmain(int argc, const uint16_t *argv[])
|
||||
|
||||
#else
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
return main_real(argc, argv);
|
||||
}
|
||||
int main(int argc, const char *argv[]) { return main_real(argc, argv); }
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
136
src/utils/json.c
136
src/utils/json.c
@@ -2,6 +2,8 @@
|
||||
#include "json.h"
|
||||
|
||||
|
||||
#define PRINTF(file, string, ...) fprintf(file, string, ##__VA_ARGS__) /* NOLINT */
|
||||
|
||||
JSONObject error = { .type = J_ERROR };
|
||||
JSONObject true_val = { .type = J_BOOL, .b = true };
|
||||
JSONObject false_val = { .type = J_BOOL, .b = false };
|
||||
@@ -16,7 +18,7 @@ static inline void json_skip_whitespace(JsonParser *parser)
|
||||
char c;
|
||||
while (1)
|
||||
{
|
||||
RETRY:
|
||||
RETRY:
|
||||
switch (parser->current[0])
|
||||
{
|
||||
case '/':
|
||||
@@ -24,7 +26,7 @@ static inline void json_skip_whitespace(JsonParser *parser)
|
||||
if (c == '/')
|
||||
{
|
||||
parser->current++;
|
||||
while ((c = (++parser->current)[0]) && c != '\n') {}
|
||||
while ((c = (++parser->current)[0]) && c != '\n') { }
|
||||
goto RETRY;
|
||||
}
|
||||
if (c == '*')
|
||||
@@ -259,6 +261,7 @@ static inline void json_lexer_advance(JsonParser *parser)
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
static inline bool consume(JsonParser *parser, JSONTokenType token)
|
||||
{
|
||||
if (parser->current_token_type == token)
|
||||
@@ -272,27 +275,27 @@ static inline bool consume(JsonParser *parser, JSONTokenType token)
|
||||
JSONObject *json_parse_array(JsonParser *parser)
|
||||
{
|
||||
CONSUME(T_LBRACKET);
|
||||
if (consume(parser, T_RBRACKET))
|
||||
{
|
||||
return &empty_array_val;
|
||||
}
|
||||
if (consume(parser, T_RBRACKET)) return &empty_array_val;
|
||||
|
||||
size_t capacity = 16;
|
||||
JSONObject *array = json_new_object(parser->allocator, J_ARRAY);
|
||||
JSONObject** elements = parser->allocator(sizeof(JSONObject*) * capacity);
|
||||
JSONObject **elements = parser->allocator(sizeof(JSONObject *) * capacity);
|
||||
size_t index = 0;
|
||||
while (1)
|
||||
{
|
||||
JSONObject *parsed = json_parse(parser);
|
||||
|
||||
if (parser->error_message) return &error;
|
||||
if (index >= capacity)
|
||||
{
|
||||
JSONObject **elements_old = elements;
|
||||
size_t copy_size = capacity * sizeof(JSONObject*);
|
||||
size_t copy_size = capacity * sizeof(JSONObject *);
|
||||
capacity *= 2;
|
||||
elements = parser->allocator(sizeof(JSONObject*) * capacity);
|
||||
elements = parser->allocator(sizeof(JSONObject *) * capacity);
|
||||
memcpy(elements, elements_old, copy_size);
|
||||
}
|
||||
elements[index++] = parsed;
|
||||
|
||||
if (consume(parser, T_RBRACKET)) break;
|
||||
CONSUME(T_COMMA);
|
||||
// Allow trailing comma
|
||||
@@ -306,35 +309,42 @@ JSONObject *json_parse_array(JsonParser *parser)
|
||||
JSONObject *json_parse_object(JsonParser *parser)
|
||||
{
|
||||
CONSUME(T_LBRACE);
|
||||
|
||||
if (consume(parser, T_RBRACE))
|
||||
{
|
||||
return &empty_obj_val;
|
||||
}
|
||||
|
||||
size_t capacity = 16;
|
||||
JSONObject *obj = json_new_object(parser->allocator, J_OBJECT);
|
||||
JSONObject** elements = parser->allocator(sizeof(JSONObject*) * capacity);
|
||||
const char** keys = parser->allocator(sizeof(JSONObject*) * capacity);
|
||||
JSONObject **elements = parser->allocator(sizeof(JSONObject *) * capacity);
|
||||
const char **keys = parser->allocator(sizeof(JSONObject *) * capacity);
|
||||
size_t index = 0;
|
||||
while (1)
|
||||
{
|
||||
const char *key = parser->last_string;
|
||||
|
||||
CONSUME(T_STRING);
|
||||
CONSUME(T_COLON);
|
||||
|
||||
JSONObject *value = json_parse(parser);
|
||||
|
||||
if (parser->error_message) return NULL;
|
||||
if (index >= capacity)
|
||||
{
|
||||
JSONObject **elements_old = elements;
|
||||
const char **keys_old = keys;
|
||||
size_t copy_size = capacity * sizeof(void*);
|
||||
size_t copy_size = capacity * sizeof(void *);
|
||||
capacity *= 2;
|
||||
elements = parser->allocator(sizeof(JSONObject*) * capacity);
|
||||
keys = parser->allocator(sizeof(JSONObject*) * capacity);
|
||||
elements = parser->allocator(sizeof(JSONObject *) * capacity);
|
||||
keys = parser->allocator(sizeof(JSONObject *) * capacity);
|
||||
memcpy(elements, elements_old, copy_size);
|
||||
memcpy(keys, keys_old, copy_size);
|
||||
}
|
||||
|
||||
keys[index] = key;
|
||||
elements[index++] = value;
|
||||
|
||||
if (consume(parser, T_RBRACE)) break;
|
||||
if (!consume(parser, T_COMMA))
|
||||
{
|
||||
@@ -391,7 +401,7 @@ JSONObject *json_parse(JsonParser *parser)
|
||||
case T_NUMBER:
|
||||
{
|
||||
JSONObject *obj = NULL;
|
||||
if (parser->last_number == 0)
|
||||
if (parser->last_number == 0)
|
||||
{
|
||||
json_lexer_advance(parser);
|
||||
return &zero_val;
|
||||
@@ -441,13 +451,13 @@ void json_free(JsonDeallocator *deallocator, JSONObject **ptr)
|
||||
|
||||
if (!is_freable(obj)) return;
|
||||
|
||||
switch(obj->type)
|
||||
switch (obj->type)
|
||||
{
|
||||
case J_OBJECT:
|
||||
for (size_t i = 0; i < obj->member_len; i++)
|
||||
{
|
||||
json_free(deallocator, &obj->members[i]);
|
||||
deallocator((char*)obj->keys[i]);
|
||||
deallocator((char *)obj->keys[i]);
|
||||
}
|
||||
deallocator(obj->keys);
|
||||
deallocator(obj->members);
|
||||
@@ -460,7 +470,7 @@ void json_free(JsonDeallocator *deallocator, JSONObject **ptr)
|
||||
deallocator(obj->elements);
|
||||
break;
|
||||
case J_STRING:
|
||||
deallocator((char*)obj->str);
|
||||
deallocator((char *)obj->str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -468,3 +478,93 @@ void json_free(JsonDeallocator *deallocator, JSONObject **ptr)
|
||||
deallocator(*ptr);
|
||||
*ptr = NULL;
|
||||
}
|
||||
|
||||
static inline void print_indent(int indent_level, FILE *file)
|
||||
{
|
||||
for (int i = 0; i < indent_level; i++)
|
||||
{
|
||||
fputs(" ", file);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void print_json(JSONObject *obj, int indent_level, FILE *file)
|
||||
{
|
||||
if (obj == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (obj->type)
|
||||
{
|
||||
case J_BOOL:
|
||||
PRINTF(file, "%s", obj->b ? "true" : "false");
|
||||
break;
|
||||
case J_STRING:
|
||||
PRINTF(file, "\"%s\"", obj->str);
|
||||
break;
|
||||
case J_NUMBER:
|
||||
PRINTF(file, "%f", obj->f);
|
||||
break;
|
||||
case J_ARRAY:
|
||||
fputs(" [ ", file);
|
||||
|
||||
if (obj->array_len == 0)
|
||||
{
|
||||
fputs(" ]", file);
|
||||
break;
|
||||
}
|
||||
|
||||
bool should_print_item_per_line = false;
|
||||
|
||||
for (size_t i = 0; i < obj->array_len; i++)
|
||||
{
|
||||
if (obj->elements[i]->type == J_OBJECT)
|
||||
{
|
||||
should_print_item_per_line = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!should_print_item_per_line && obj->array_len < 5)
|
||||
{
|
||||
for (size_t i = 0; i < obj->array_len; i++)
|
||||
{
|
||||
if (i != 0) fputs(", ", file);
|
||||
print_json(obj->elements[i], indent_level, file);
|
||||
}
|
||||
fputs(" ]", file);
|
||||
break;
|
||||
}
|
||||
|
||||
fputs("\n", file);
|
||||
for (size_t i = 0; i < obj->array_len; i++)
|
||||
{
|
||||
print_indent(indent_level + 1, file);
|
||||
print_json(obj->elements[i], indent_level + 1, file);
|
||||
fputs(",\n", file);
|
||||
}
|
||||
|
||||
fputs(" ]", file);
|
||||
break;
|
||||
case J_OBJECT:
|
||||
fputs("{\n", file);
|
||||
for (size_t i = 0; i < obj->member_len; i++)
|
||||
{
|
||||
print_indent(indent_level + 1, file);
|
||||
PRINTF(file, "\"%s\": ", obj->keys[i]);
|
||||
print_json(obj->members[i], indent_level + 1, file);
|
||||
fputs(",\n", file);
|
||||
}
|
||||
print_indent(indent_level, file);
|
||||
fputs("}", file);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void print_json_to_file(JSONObject *obj, FILE *file)
|
||||
{
|
||||
print_json(obj, 0, file);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ typedef enum
|
||||
J_ARRAY,
|
||||
J_NUMBER,
|
||||
J_BOOL,
|
||||
J_ERROR,
|
||||
J_ERROR
|
||||
} JSONType;
|
||||
|
||||
|
||||
@@ -46,11 +46,11 @@ typedef enum JSONTokenType_
|
||||
T_TRUE,
|
||||
T_FALSE,
|
||||
T_NULL,
|
||||
T_EOF,
|
||||
T_EOF
|
||||
} JSONTokenType;
|
||||
|
||||
typedef void*(JsonAllocator)(size_t);
|
||||
typedef void*(JsonDeallocator)(void*);
|
||||
typedef void *(JsonAllocator)(size_t);
|
||||
typedef void *(JsonDeallocator)(void *);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -68,6 +68,7 @@ JSONObject *json_parse(JsonParser *parser);
|
||||
JSONObject *json_obj_get(JSONObject *obj, const char *key);
|
||||
INLINE JSONObject *json_new_object(JsonAllocator *allocator, JSONType type);
|
||||
void json_free(JsonDeallocator *deallocator, JSONObject **ptr);
|
||||
void print_json_to_file(JSONObject *obj, FILE *file);
|
||||
|
||||
|
||||
INLINE JSONObject *json_new_object(JsonAllocator *allocator, JSONType type)
|
||||
|
||||
Reference in New Issue
Block a user