API type check :D
This commit is contained in:
parent
13e8c0aed4
commit
41a67e296d
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Mr. 4th Dimention - Allen Webster
|
||||||
|
*
|
||||||
|
* 06.10.2019
|
||||||
|
*
|
||||||
|
* Type checker that lists errors between two api parses.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TOP
|
||||||
|
|
||||||
|
#include "4coder_base_types.h"
|
||||||
|
#include "4coder_token.h"
|
||||||
|
#include "generated/lexer_cpp.h"
|
||||||
|
#include "4ed_api_definition.h"
|
||||||
|
|
||||||
|
#include "4coder_base_types.cpp"
|
||||||
|
#include "4coder_stringf.cpp"
|
||||||
|
#include "4coder_malloc_allocator.cpp"
|
||||||
|
#include "4coder_token.cpp"
|
||||||
|
#include "generated/lexer_cpp.cpp"
|
||||||
|
#include "4coder_file.cpp"
|
||||||
|
#include "4ed_api_definition.cpp"
|
||||||
|
#include "4ed_api_parser.cpp"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
function void
|
||||||
|
print_usage(void){
|
||||||
|
printf("usage: <script> <source-1> {<source-1>} : <source-2> {<source-2>}\n"
|
||||||
|
" source-1 : the authoritative/master api source file(s)\n"
|
||||||
|
" source-2 : the 'remote' api source file(s) to check against the master\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv){
|
||||||
|
Arena arena = make_arena_malloc();
|
||||||
|
|
||||||
|
if (argc < 4){
|
||||||
|
print_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_Definition_List master_list = {};
|
||||||
|
API_Definition_List remote_list = {};
|
||||||
|
|
||||||
|
{
|
||||||
|
i32 i = 1;
|
||||||
|
for (;i < argc; i += 1){
|
||||||
|
char *file_name = argv[i];
|
||||||
|
if (string_match(SCu8(file_name), string_u8_litexpr(":"))){
|
||||||
|
i += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FILE *file = fopen(file_name, "rb");
|
||||||
|
if (file == 0){
|
||||||
|
printf("error: could not open input file: '%s'\n", file_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String_Const_u8 text = file_load_all(&arena, file);
|
||||||
|
fclose(file);
|
||||||
|
if (text.size > 0){
|
||||||
|
api_parse_source_add_to_list(&arena, SCu8(file_name), text, &master_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (;i < argc; i += 1){
|
||||||
|
char *file_name = argv[i];
|
||||||
|
FILE *file = fopen(file_name, "rb");
|
||||||
|
if (file == 0){
|
||||||
|
printf("error: could not open input file: '%s'\n", file_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String_Const_u8 text = file_load_all(&arena, file);
|
||||||
|
fclose(file);
|
||||||
|
if (text.size > 0){
|
||||||
|
api_parse_source_add_to_list(&arena, SCu8(file_name), text, &remote_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (master_list.count == 0){
|
||||||
|
printf("error: no apis in master list\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remote_list.count == 0){
|
||||||
|
printf("error: no apis in remote list\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
List_String_Const_u8 errors = {};
|
||||||
|
api_list_check(&arena, &master_list, &remote_list, APICheck_ReportAll, &errors);
|
||||||
|
String_Const_u8 string = string_list_flatten(&arena, errors, StringFill_NullTerminate);
|
||||||
|
printf("%.*s", string_expand(string));
|
||||||
|
if (string.size > 0){
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOTTOM
|
|
@ -17,20 +17,25 @@ begin_api(Arena *arena, char *name){
|
||||||
}
|
}
|
||||||
|
|
||||||
function API_Call*
|
function API_Call*
|
||||||
api_call(Arena *arena, API_Definition *api, String_Const_u8 name, String_Const_u8 return_type){
|
api_call_with_location(Arena *arena, API_Definition *api, String_Const_u8 name, String_Const_u8 type,
|
||||||
|
String_Const_u8 location){
|
||||||
API_Call *call = push_array_zero(arena, API_Call, 1);
|
API_Call *call = push_array_zero(arena, API_Call, 1);
|
||||||
sll_queue_push(api->first, api->last, call);
|
sll_queue_push(api->first, api->last, call);
|
||||||
api->count += 1;
|
api->count += 1;
|
||||||
call->name = name;
|
call->name = name;
|
||||||
call->return_type = return_type;
|
call->return_type = type;
|
||||||
|
call->location_string = location;
|
||||||
return(call);
|
return(call);
|
||||||
}
|
}
|
||||||
|
|
||||||
function API_Call*
|
function API_Call*
|
||||||
api_call(Arena *arena, API_Definition *api, char *name, char *return_type){
|
api_call_with_location(Arena *arena, API_Definition *api, char *name, char *type, char *location){
|
||||||
return(api_call(arena, api, SCu8(name), SCu8(return_type)));
|
return(api_call_with_location(arena, api, SCu8(name), SCu8(type), SCu8(location)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define api_call(arena, api, name, type) \
|
||||||
|
api_call_with_location((arena), (api), (name), (type), file_name_line_number)
|
||||||
|
|
||||||
function API_Param*
|
function API_Param*
|
||||||
api_param(Arena *arena, API_Call *call, char *type_name, char *name){
|
api_param(Arena *arena, API_Call *call, char *type_name, char *name){
|
||||||
API_Param *param = push_array_zero(arena, API_Param, 1);
|
API_Param *param = push_array_zero(arena, API_Param, 1);
|
||||||
|
@ -47,7 +52,7 @@ api_set_param_list(API_Call *call, API_Param_List list){
|
||||||
}
|
}
|
||||||
|
|
||||||
function API_Definition*
|
function API_Definition*
|
||||||
api_get_api(Arena *arena, API_Definition_List *list, String_Const_u8 name){
|
api_get_api(API_Definition_List *list, String_Const_u8 name){
|
||||||
API_Definition *result = 0;
|
API_Definition *result = 0;
|
||||||
for (API_Definition *node = list->first;
|
for (API_Definition *node = list->first;
|
||||||
node != 0;
|
node != 0;
|
||||||
|
@ -57,6 +62,12 @@ api_get_api(Arena *arena, API_Definition_List *list, String_Const_u8 name){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
function API_Definition*
|
||||||
|
api_get_api(Arena *arena, API_Definition_List *list, String_Const_u8 name){
|
||||||
|
API_Definition *result = api_get_api(list, name);
|
||||||
if (result == 0){
|
if (result == 0){
|
||||||
result = push_array_zero(arena, API_Definition, 1);
|
result = push_array_zero(arena, API_Definition, 1);
|
||||||
sll_queue_push(list->first, list->last, result);
|
sll_queue_push(list->first, list->last, result);
|
||||||
|
@ -66,6 +77,39 @@ api_get_api(Arena *arena, API_Definition_List *list, String_Const_u8 name){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function API_Call*
|
||||||
|
api_get_call(API_Definition *api, String_Const_u8 name){
|
||||||
|
API_Call *result = 0;
|
||||||
|
for (API_Call *call = api->first;
|
||||||
|
call != 0;
|
||||||
|
call = call->next){
|
||||||
|
if (string_match(name, call->name)){
|
||||||
|
result = call;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
function b32
|
||||||
|
api_call_match_sigs(API_Call *a, API_Call *b){
|
||||||
|
b32 result = false;
|
||||||
|
if (a->params.count == b->params.count &&
|
||||||
|
string_match(a->return_type, b->return_type)){
|
||||||
|
result = true;
|
||||||
|
for (API_Param *a_param = a->params.first, *b_param = b->params.first;
|
||||||
|
a_param != 0 && b_param != 0;
|
||||||
|
a_param = a_param->next, b_param = b_param->next){
|
||||||
|
if (!string_match(a_param->name, b_param->name) ||
|
||||||
|
!string_match(a_param->type_name, b_param->type_name)){
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
#if !defined(SKIP_STDIO)
|
#if !defined(SKIP_STDIO)
|
||||||
|
@ -335,6 +379,142 @@ api_definition_generate_api_includes(Arena *arena, API_Definition *api, Generate
|
||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
function void
|
||||||
|
api_definition_error(Arena *arena, List_String_Const_u8 *list,
|
||||||
|
char *e1, API_Call *c1, char *e2, API_Call *c2){
|
||||||
|
Assert(e1 != 0);
|
||||||
|
Assert(c1 != 0);
|
||||||
|
string_list_pushf(arena, list,
|
||||||
|
"%.*s error: %s '%.*s'",
|
||||||
|
string_expand(c1->location_string),
|
||||||
|
e1, string_expand(c1->name));
|
||||||
|
if (e2 != 0){
|
||||||
|
string_list_pushf(arena, list, " %s", e2);
|
||||||
|
if (c2 != 0){
|
||||||
|
string_list_pushf(arena, list, " '%.*s'", string_expand(c2->name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string_list_push(arena, list, string_u8_litexpr("\n"));
|
||||||
|
if (c2 != 0){
|
||||||
|
string_list_push(arena, list, c2->location_string);
|
||||||
|
string_list_pushf(arena, list, " note: see declaration of '%.*s'\n", string_expand(c2->name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
api_definition_error(Arena *arena, List_String_Const_u8 *list,
|
||||||
|
char *e1, API_Call *c1, char *e2){
|
||||||
|
api_definition_error(arena, list, e1, c1, e2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
api_definition_error(Arena *arena, List_String_Const_u8 *list,
|
||||||
|
char *e1, API_Call *c1){
|
||||||
|
api_definition_error(arena, list, e1, c1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
api_definition_error(Arena *arena, List_String_Const_u8 *list,
|
||||||
|
char *e1, API_Definition *api1, char *e2){
|
||||||
|
Assert(e1 != 0);
|
||||||
|
Assert(api1 != 0);
|
||||||
|
string_list_pushf(arena, list, "error: %s '%.*s'",
|
||||||
|
e1, string_expand(api1->name));
|
||||||
|
if (e2 != 0){
|
||||||
|
string_list_pushf(arena, list, " %s", e2);
|
||||||
|
}
|
||||||
|
string_list_push(arena, list, string_u8_litexpr("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
api_definition_error(Arena *arena, List_String_Const_u8 *list,
|
||||||
|
char *e1, API_Definition *api1){
|
||||||
|
api_definition_error(arena, list, e1, api1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
api_definition_check(Arena *arena, API_Definition *correct, API_Definition *remote, API_Check_Flag flags, List_String_Const_u8 *error_list){
|
||||||
|
b32 report_missing = HasFlag(flags, APICheck_ReportMissingAPI);
|
||||||
|
b32 report_extra = HasFlag(flags, APICheck_ReportExtraAPI);
|
||||||
|
b32 report_mismatch = HasFlag(flags, APICheck_ReportMismatchAPI);
|
||||||
|
|
||||||
|
b32 iterate_correct = (report_missing || report_mismatch);
|
||||||
|
if (iterate_correct){
|
||||||
|
for (API_Call *call = correct->first;
|
||||||
|
call != 0;
|
||||||
|
call = call->next){
|
||||||
|
API_Call *remote_call = api_get_call(remote, call->name);
|
||||||
|
if (remote_call == 0 && report_missing){
|
||||||
|
api_definition_error(arena, error_list,
|
||||||
|
"no remote call for", call);
|
||||||
|
}
|
||||||
|
if (remote_call != 0 && !api_call_match_sigs(call, remote_call) && report_mismatch){
|
||||||
|
api_definition_error(arena, error_list,
|
||||||
|
"remote call", remote_call,
|
||||||
|
"does not match signature for", call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b32 iterate_remote = (report_extra);
|
||||||
|
if (iterate_remote){
|
||||||
|
for (API_Call *call = remote->first;
|
||||||
|
call != 0;
|
||||||
|
call = call->next){
|
||||||
|
API_Call *correct_call = api_get_call(correct, call->name);
|
||||||
|
if (correct_call == 0 && report_extra){
|
||||||
|
api_definition_error(arena, error_list,
|
||||||
|
"remote call", call,
|
||||||
|
"does not exist in api master");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
api_list_check(Arena *arena, API_Definition_List *correct, API_Definition_List *remote, API_Check_Flag flags, List_String_Const_u8 *error_list){
|
||||||
|
b32 report_missing = HasFlag(flags, APICheck_ReportMissingAPI);
|
||||||
|
b32 report_extra = HasFlag(flags, APICheck_ReportExtraAPI);
|
||||||
|
|
||||||
|
b32 iterate_correct = (report_missing);
|
||||||
|
if (iterate_correct){
|
||||||
|
for (API_Definition *api = correct->first;
|
||||||
|
api != 0;
|
||||||
|
api = api->next){
|
||||||
|
API_Definition *remote_api = api_get_api(remote, api->name);
|
||||||
|
if (remote_api == 0 && report_missing){
|
||||||
|
api_definition_error(arena, error_list,
|
||||||
|
"no remote api for", api);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b32 iterate_remote = (report_extra);
|
||||||
|
if (iterate_remote){
|
||||||
|
for (API_Definition *api = remote->first;
|
||||||
|
api != 0;
|
||||||
|
api = api->next){
|
||||||
|
API_Definition *correct_api = api_get_api(correct, api->name);
|
||||||
|
if (correct_api == 0 && report_extra){
|
||||||
|
api_definition_error(arena, error_list,
|
||||||
|
"remote api", api,
|
||||||
|
"does not have a master");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (API_Definition *api = correct->first;
|
||||||
|
api != 0;
|
||||||
|
api = api->next){
|
||||||
|
API_Definition *remote_api = api_get_api(remote, api->name);
|
||||||
|
if (remote_api != 0){
|
||||||
|
api_definition_check(arena, api, remote_api, flags, error_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
|
@ -28,6 +28,7 @@ struct API_Call{
|
||||||
API_Call *next;
|
API_Call *next;
|
||||||
String_Const_u8 name;
|
String_Const_u8 name;
|
||||||
String_Const_u8 return_type;
|
String_Const_u8 return_type;
|
||||||
|
String_Const_u8 location_string;
|
||||||
API_Param_List params;
|
API_Param_List params;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -52,6 +53,16 @@ enum{
|
||||||
APIGeneration_NoAPINameOnCallables = 1,
|
APIGeneration_NoAPINameOnCallables = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef u32 API_Check_Flag;
|
||||||
|
enum{
|
||||||
|
APICheck_ReportMissingAPI = 1,
|
||||||
|
APICheck_ReportExtraAPI = 2,
|
||||||
|
APICheck_ReportMismatchAPI = 4,
|
||||||
|
};
|
||||||
|
enum{
|
||||||
|
APICheck_ReportAll = APICheck_ReportMissingAPI|APICheck_ReportExtraAPI|APICheck_ReportMismatchAPI,
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
|
@ -9,21 +9,6 @@
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
#include "4coder_base_types.h"
|
|
||||||
#include "4coder_token.h"
|
|
||||||
#include "generated/lexer_cpp.h"
|
|
||||||
#include "4ed_api_definition.h"
|
|
||||||
|
|
||||||
#include "4coder_base_types.cpp"
|
|
||||||
#include "4coder_stringf.cpp"
|
|
||||||
#include "4coder_malloc_allocator.cpp"
|
|
||||||
#include "4coder_token.cpp"
|
|
||||||
#include "generated/lexer_cpp.cpp"
|
|
||||||
#include "4coder_file.cpp"
|
|
||||||
#include "4ed_api_definition.cpp"
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
function:
|
function:
|
||||||
api ( <identifier> ) function <identifier> {*} <identifier> ( <param_list> )
|
api ( <identifier> ) function <identifier> {*} <identifier> ( <param_list> )
|
||||||
|
@ -103,15 +88,41 @@ api_parse_add_param(Arena *arena, API_Param_List *list, String_Const_u8 type, i3
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
api_parse_add_function(Arena *arena, API_Definition_List *list, String_Const_u8 api_name, String_Const_u8 func_name, String_Const_u8 type, i32 star_counter, API_Param_List param_list){
|
api_parse_add_function(Arena *arena, API_Definition_List *list,
|
||||||
|
String_Const_u8 api_name, String_Const_u8 func_name,
|
||||||
|
String_Const_u8 type, i32 star_counter, API_Param_List param_list,
|
||||||
|
String_Const_u8 location){
|
||||||
API_Definition *api = api_get_api(arena, list, api_name);
|
API_Definition *api = api_get_api(arena, list, api_name);
|
||||||
type = api_parse__type_name_with_stars(arena, type, star_counter);
|
type = api_parse__type_name_with_stars(arena, type, star_counter);
|
||||||
API_Call *call = api_call(arena, api, func_name, type);
|
API_Call *call = api_call_with_location(arena, api, func_name, type, location);
|
||||||
api_set_param_list(call, param_list);
|
api_set_param_list(call, param_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function String_Const_u8
|
||||||
|
api_parse_location(Arena *arena, String_Const_u8 source_name, String_Const_u8 source, u8 *pos){
|
||||||
|
i32 line_number = 1;
|
||||||
|
i32 col_number = 1;
|
||||||
|
if (source.str <= pos && pos < source.str + source.size){
|
||||||
|
for (u8 *ptr = source.str;;){
|
||||||
|
if (ptr == pos){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*ptr == '\n'){
|
||||||
|
line_number += 1;
|
||||||
|
col_number = 1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
col_number += 1;
|
||||||
|
}
|
||||||
|
ptr += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(push_u8_stringf(arena, "%.*s:%d:%d:", string_expand(source_name), line_number, col_number));
|
||||||
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
api_parse_source_add_to_list(Arena *arena, String_Const_u8 source, API_Definition_List *list){
|
api_parse_source_add_to_list(Arena *arena, String_Const_u8 source_name, String_Const_u8 source,
|
||||||
|
API_Definition_List *list){
|
||||||
Token_List token_list = lex_full_input_cpp(arena, source);
|
Token_List token_list = lex_full_input_cpp(arena, source);
|
||||||
Token_Iterator token_it = token_iterator(token_iterator(0, &token_list));
|
Token_Iterator token_it = token_iterator(token_iterator(0, &token_list));
|
||||||
|
|
||||||
|
@ -187,7 +198,10 @@ api_parse_source_add_to_list(Arena *arena, String_Const_u8 source, API_Definitio
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success){
|
if (success){
|
||||||
api_parse_add_function(arena, list, api_name, func_name, ret_type, ret_type_star_counter, param_list);
|
String_Const_u8 location = api_parse_location(arena, source_name, source, func_name.str);
|
||||||
|
api_parse_add_function(arena, list, api_name, func_name,
|
||||||
|
ret_type, ret_type_star_counter, param_list,
|
||||||
|
location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
@ -196,50 +210,14 @@ api_parse_source_add_to_list(Arena *arena, String_Const_u8 source, API_Definitio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function API_Definition_List
|
function API_Definition_List
|
||||||
api_parse_source(Arena *arena, String_Const_u8 source){
|
api_parse_source(Arena *arena, String_Const_u8 source_name, String_Const_u8 source){
|
||||||
API_Definition_List list = {};
|
API_Definition_List list = {};
|
||||||
api_parse_source_add_to_list(arena, source, &list);
|
api_parse_source_add_to_list(arena, source_name, source, &list);
|
||||||
return(list);
|
return(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv){
|
|
||||||
Arena arena = make_arena_malloc();
|
|
||||||
|
|
||||||
if (argc < 2){
|
|
||||||
printf("usage: <script> <source> {<source>}\n"
|
|
||||||
" source : file to load and parse into the output list\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
API_Definition_List list = {};
|
|
||||||
for (i32 i = 1; i < argc; i += 1){
|
|
||||||
FILE *file = fopen(argv[i], "rb");
|
|
||||||
if (file == 0){
|
|
||||||
printf("error: could not open input file: '%s'\n", argv[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String_Const_u8 text = file_load_all(&arena, file);
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
if (text.size > 0){
|
|
||||||
api_parse_source_add_to_list(&arena, text, &list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (API_Definition *node = list.first;
|
|
||||||
node != 0;
|
|
||||||
node = node->next){
|
|
||||||
api_definition_generate_api_includes(&arena, node, GeneratedGroup_Custom, APIGeneration_NoAPINameOnCallables);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Mr. 4th Dimention - Allen Webster
|
||||||
|
*
|
||||||
|
* 06.10.2019
|
||||||
|
*
|
||||||
|
* Parser that extracts an API from C++ source code.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TOP
|
||||||
|
|
||||||
|
#include "4coder_base_types.h"
|
||||||
|
#include "4coder_token.h"
|
||||||
|
#include "generated/lexer_cpp.h"
|
||||||
|
#include "4ed_api_definition.h"
|
||||||
|
|
||||||
|
#include "4coder_base_types.cpp"
|
||||||
|
#include "4coder_stringf.cpp"
|
||||||
|
#include "4coder_malloc_allocator.cpp"
|
||||||
|
#include "4coder_token.cpp"
|
||||||
|
#include "generated/lexer_cpp.cpp"
|
||||||
|
#include "4coder_file.cpp"
|
||||||
|
#include "4ed_api_definition.cpp"
|
||||||
|
#include "4ed_api_parser.cpp"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv){
|
||||||
|
Arena arena = make_arena_malloc();
|
||||||
|
|
||||||
|
if (argc < 2){
|
||||||
|
printf("usage: <script> <source> {<source>}\n"
|
||||||
|
" source : file to load and parse into the output list\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_Definition_List list = {};
|
||||||
|
for (i32 i = 1; i < argc; i += 1){
|
||||||
|
char *file_name = argv[i];
|
||||||
|
FILE *file = fopen(file_name, "rb");
|
||||||
|
if (file == 0){
|
||||||
|
printf("error: could not open input file: '%s'\n", argv[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String_Const_u8 text = file_load_all(&arena, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
if (text.size > 0){
|
||||||
|
api_parse_source_add_to_list(&arena, SCu8(file_name), text, &list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (API_Definition *node = list.first;
|
||||||
|
node != 0;
|
||||||
|
node = node->next){
|
||||||
|
api_definition_generate_api_includes(&arena, node, GeneratedGroup_Custom, APIGeneration_NoAPINameOnCallables);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOTTOM
|
|
@ -301,8 +301,8 @@ global_const f32 epsilon_f32 = 5.96046448e-8f;
|
||||||
#define clamp_unsigned_to_u32(x) (u32)(clamp_top((u64)(x), (u64)u32_max))
|
#define clamp_unsigned_to_u32(x) (u32)(clamp_top((u64)(x), (u64)u32_max))
|
||||||
#define clamp_unsigned_to_u64(x) (u64)(clamp_top((u64)(x), (u64)u64_max))
|
#define clamp_unsigned_to_u64(x) (u64)(clamp_top((u64)(x), (u64)u64_max))
|
||||||
|
|
||||||
#define LINE_STR stringify(__LINE__)
|
#define LINE_STR__ stringify(__LINE__)
|
||||||
#define FNLN __FILE__ ":" LINE_STR ":"
|
#define file_name_line_number __FILE__ ":" LINE_STR__ ":"
|
||||||
|
|
||||||
#define require(c) Stmnt( if (!(c)){ return(0); } )
|
#define require(c) Stmnt( if (!(c)){ return(0); } )
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
api(system) function String_Const_u8 get_path(Arena* arena, System_Path_Code path_code);
|
||||||
|
api(system) function String_Const_u8 get_canonical(Arena* arena, String_Const_u8 name);
|
||||||
|
api(system) function File_List get_file_list(Arena* arena, String_Const_u8 directory);
|
||||||
|
api(system) function File_Attributes quick_file_attributes(Arena* scratch, String_Const_u8 file_name);
|
||||||
|
api(system) function b32 load_handle(Arena* scratch, char* file_name, Plat_Handle* out);
|
||||||
|
api(system) function File_Attributes load_attributes(Plat_Handle handle);
|
||||||
|
api(system) function b32 load_file(Plat_Handle handle, char* buffer, u32 size);
|
||||||
|
api(system) function b32 load_close(Plat_Handle handle);
|
||||||
|
api(system) function File_Attributes save_file(Arena* scratch, char* file_name, String_Const_u8 data);
|
||||||
|
api(system) function b32 load_library(Arena* scratch, String_Const_u8 file_name, System_Library* out);
|
||||||
|
api(system) function b32 release_library(System_Library handle);
|
||||||
|
api(system) function Void_Func* get_proc(System_Library handle, char* proc_name);
|
||||||
|
api(system) function u64 now_time(void);
|
||||||
|
api(system) function Plat_Handle wake_up_timer_create(void);
|
||||||
|
api(system) function void wake_up_timer_release(Plat_Handle handle);
|
||||||
|
api(system) function void wake_up_timer_set(Plat_Handle handle, u32 time_milliseconds);
|
||||||
|
api(system) function void signal_step(u32 code);
|
||||||
|
api(system) function void sleep(u64 microseconds);
|
||||||
|
api(system) function void post_clipboard(String_Const_u8 str);
|
||||||
|
api(system) function b32 cli_call(Arena* scratch, char* path, char* script, CLI_Handles* cli_out);
|
||||||
|
api(system) function void cli_begin_update(CLI_Handles* cli);
|
||||||
|
api(system) function b32 cli_update_step(CLI_Handles* cli, char* dest, u32 max, u32* amount);
|
||||||
|
api(system) function b32 cli_end_update(CLI_Handles* cli);
|
||||||
|
api(system) function void open_color_picker(Color_Picker* picker);
|
||||||
|
api(system) function f32 get_screen_scale_factor(void);
|
||||||
|
api(system) function System_Thread thread_launch(Thread_Function* proc, void* ptr);
|
||||||
|
api(system) function void thread_join(System_Thread thread);
|
||||||
|
api(system) function void thread_free(System_Thread thread);
|
||||||
|
api(system) function i32 thread_get_id(void);
|
||||||
|
api(system) function System_Mutex mutex_make(void);
|
||||||
|
api(system) function void mutex_acquire(System_Mutex mutex);
|
||||||
|
api(system) function void mutex_release(System_Mutex mutex);
|
||||||
|
api(system) function void mutex_free(System_Mutex mutex);
|
||||||
|
api(system) function System_Condition_Variable condition_variable_make(void);
|
||||||
|
api(system) function void condition_variable_wait(System_Condition_Variable cv, System_Mutex mutex);
|
||||||
|
api(system) function void condition_variable_signal(System_Condition_Variable cv);
|
||||||
|
api(system) function void condition_variable_free(System_Condition_Variable cv);
|
||||||
|
api(system) function void* memory_allocate(umem size);
|
||||||
|
api(system) function b32 memory_set_protection(void* ptr, umem size, u32 flags);
|
||||||
|
api(system) function void memory_free(void* ptr, umem size);
|
||||||
|
api(system) function void show_mouse_cursor(i32 show);
|
||||||
|
api(system) function b32 set_fullscreen(b32 full_screen);
|
||||||
|
api(system) function b32 is_fullscreen(void);
|
|
@ -678,7 +678,7 @@ internal void
|
||||||
win32_init_gl(HDC hdc){
|
win32_init_gl(HDC hdc){
|
||||||
//LOG("trying to load wgl extensions...\n");
|
//LOG("trying to load wgl extensions...\n");
|
||||||
|
|
||||||
#define GLInitFail(s) system_error_box(FNLN "\nOpenGL init fail - " s )
|
#define GLInitFail(s) system_error_box(file_name_line_number "\nOpenGL init fail - " s )
|
||||||
|
|
||||||
// Init First Context
|
// Init First Context
|
||||||
WNDCLASSA wglclass = {};
|
WNDCLASSA wglclass = {};
|
||||||
|
|
|
@ -59,7 +59,11 @@ command_list = {
|
||||||
|
|
||||||
{ .name = "build api parser",
|
{ .name = "build api parser",
|
||||||
.out = "*compilation*", .footer_panel = true, .save_dirty_files = true,
|
.out = "*compilation*", .footer_panel = true, .save_dirty_files = true,
|
||||||
.cmd = { { "custom\\bin\\build_one_time 4ed_api_parser.cpp ..\\build & copy /B ..\\build\\one_time.exe ..\\build\\api_parser.exe", .os = "win" }, }, },
|
.cmd = { { "custom\\bin\\build_one_time 4ed_api_parser_main.cpp ..\\build & copy /B ..\\build\\one_time.exe ..\\build\\api_parser.exe", .os = "win" }, }, },
|
||||||
|
|
||||||
|
{ .name = "build api checker",
|
||||||
|
.out = "*compilation*", .footer_panel = true, .save_dirty_files = true,
|
||||||
|
.cmd = { { "custom\\bin\\build_one_time 4ed_api_check.cpp ..\\build & copy /B ..\\build\\one_time.exe ..\\build\\api_checker.exe", .os = "win" }, }, },
|
||||||
|
|
||||||
{ .name = "generate custom api master list",
|
{ .name = "generate custom api master list",
|
||||||
.out = "*run*", .footer_panel = false, .save_dirty_files = false,
|
.out = "*run*", .footer_panel = false, .save_dirty_files = false,
|
||||||
|
@ -67,7 +71,7 @@ command_list = {
|
||||||
};
|
};
|
||||||
|
|
||||||
fkey_command[1] = "build x64";
|
fkey_command[1] = "build x64";
|
||||||
fkey_command[2] = "build api parser";
|
fkey_command[2] = "build api checker";
|
||||||
fkey_command[4] = "run one time";
|
fkey_command[4] = "run one time";
|
||||||
fkey_command[5] = "build C++ lexer generator";
|
fkey_command[5] = "build C++ lexer generator";
|
||||||
fkey_command[6] = "build token tester";
|
fkey_command[6] = "build token tester";
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
mouse_xy 20 20
|
||||||
|
key P MDFR_CTRL
|
||||||
|
basewait 1
|
||||||
|
key o MDFR_CTRL
|
||||||
|
type 1 gentokentest1.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key o MDFR_CTRL
|
||||||
|
key key_back MDFR_NONE
|
||||||
|
type 1 output/
|
||||||
|
key key_esc MDFR_NONE
|
||||||
|
key s MDFR_ALT
|
||||||
|
type 1 gentokentest1.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key key_down MDFR_CTRL
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key s MDFR_CTRL
|
||||||
|
exit
|
||||||
|
key Y MDFR_NONE
|
|
@ -0,0 +1,27 @@
|
||||||
|
mouse_xy 20 20
|
||||||
|
key P MDFR_CTRL
|
||||||
|
basewait 1
|
||||||
|
key o MDFR_CTRL
|
||||||
|
type 1 gentokentest2.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key o MDFR_CTRL
|
||||||
|
key key_back MDFR_NONE
|
||||||
|
type 1 output/
|
||||||
|
key key_esc MDFR_NONE
|
||||||
|
key s MDFR_ALT
|
||||||
|
type 1 gentokentest2.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key key_down MDFR_CTRL
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key s MDFR_CTRL
|
||||||
|
exit
|
||||||
|
key Y MDFR_NONE
|
|
@ -0,0 +1,27 @@
|
||||||
|
mouse_xy 20 20
|
||||||
|
key P MDFR_CTRL
|
||||||
|
basewait 1
|
||||||
|
key o MDFR_CTRL
|
||||||
|
type 1 gentokentest3.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key o MDFR_CTRL
|
||||||
|
key key_back MDFR_NONE
|
||||||
|
type 1 output/
|
||||||
|
key key_esc MDFR_NONE
|
||||||
|
key s MDFR_ALT
|
||||||
|
type 1 gentokentest3.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key key_down MDFR_CTRL
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key s MDFR_CTRL
|
||||||
|
exit
|
||||||
|
key Y MDFR_NONE
|
|
@ -0,0 +1,27 @@
|
||||||
|
mouse_xy 20 20
|
||||||
|
key P MDFR_CTRL
|
||||||
|
basewait 1
|
||||||
|
key o MDFR_CTRL
|
||||||
|
type 1 gentokentest4.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key o MDFR_CTRL
|
||||||
|
key key_back MDFR_NONE
|
||||||
|
type 1 output/
|
||||||
|
key key_esc MDFR_NONE
|
||||||
|
key s MDFR_ALT
|
||||||
|
type 1 gentokentest4.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key key_down MDFR_CTRL
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key s MDFR_CTRL
|
||||||
|
exit
|
||||||
|
key Y MDFR_NONE
|
|
@ -0,0 +1,27 @@
|
||||||
|
mouse_xy 20 20
|
||||||
|
key P MDFR_CTRL
|
||||||
|
basewait 1
|
||||||
|
key o MDFR_CTRL
|
||||||
|
type 1 gentokentest5.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key o MDFR_CTRL
|
||||||
|
key key_back MDFR_NONE
|
||||||
|
type 1 output/
|
||||||
|
key key_esc MDFR_NONE
|
||||||
|
key s MDFR_ALT
|
||||||
|
type 1 gentokentest5.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key key_down MDFR_CTRL
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
type 1 int x = 0;
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key s MDFR_CTRL
|
||||||
|
exit
|
||||||
|
key Y MDFR_NONE
|
|
@ -0,0 +1,16 @@
|
||||||
|
mouse_xy 20 20
|
||||||
|
key P MDFR_CTRL
|
||||||
|
basewait 1
|
||||||
|
key o MDFR_CTRL
|
||||||
|
type 1 genduplinetest0_0.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key o MDFR_CTRL
|
||||||
|
key key_back MDFR_NONE
|
||||||
|
type 1 output/
|
||||||
|
key key_esc MDFR_NONE
|
||||||
|
key s MDFR_ALT
|
||||||
|
type 1 genduplinetest0_0.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key L MDFR_CTRL
|
||||||
|
key s MDFR_CTRL
|
||||||
|
exit
|
|
@ -0,0 +1,16 @@
|
||||||
|
mouse_xy 20 20
|
||||||
|
key P MDFR_CTRL
|
||||||
|
basewait 1
|
||||||
|
key o MDFR_CTRL
|
||||||
|
type 1 genduplinetest0_1.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key o MDFR_CTRL
|
||||||
|
key key_back MDFR_NONE
|
||||||
|
type 1 output/
|
||||||
|
key key_esc MDFR_NONE
|
||||||
|
key s MDFR_ALT
|
||||||
|
type 1 genduplinetest0_1.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key L MDFR_CTRL
|
||||||
|
key s MDFR_CTRL
|
||||||
|
exit
|
|
@ -0,0 +1,16 @@
|
||||||
|
mouse_xy 20 20
|
||||||
|
key P MDFR_CTRL
|
||||||
|
basewait 1
|
||||||
|
key o MDFR_CTRL
|
||||||
|
type 1 genduplinetest1_0.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key o MDFR_CTRL
|
||||||
|
key key_back MDFR_NONE
|
||||||
|
type 1 output/
|
||||||
|
key key_esc MDFR_NONE
|
||||||
|
key s MDFR_ALT
|
||||||
|
type 1 genduplinetest1_0.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key L MDFR_CTRL
|
||||||
|
key s MDFR_CTRL
|
||||||
|
exit
|
|
@ -0,0 +1,16 @@
|
||||||
|
mouse_xy 20 20
|
||||||
|
key P MDFR_CTRL
|
||||||
|
basewait 1
|
||||||
|
key o MDFR_CTRL
|
||||||
|
type 1 genduplinetest1_1.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key o MDFR_CTRL
|
||||||
|
key key_back MDFR_NONE
|
||||||
|
type 1 output/
|
||||||
|
key key_esc MDFR_NONE
|
||||||
|
key s MDFR_ALT
|
||||||
|
type 1 genduplinetest1_1.cpp
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key L MDFR_CTRL
|
||||||
|
key s MDFR_CTRL
|
||||||
|
exit
|
|
@ -0,0 +1,9 @@
|
||||||
|
mouse_xy 20 20
|
||||||
|
key P MDFR_CTRL
|
||||||
|
basewait 1
|
||||||
|
key i MDFR_CTRL
|
||||||
|
type 1 *messages*
|
||||||
|
key key_newline MDFR_NONE
|
||||||
|
key L MDFR_CTRL
|
||||||
|
key s MDFR_CTRL
|
||||||
|
exit
|
Loading…
Reference in New Issue