fstr_bool string_set_match(
String *str_set,
int32_t count,
String str,
int32_t *match_index
)
diff --git a/4coder_string.h b/4coder_string.h
index 12f3a481..7ebcb04f 100644
--- a/4coder_string.h
+++ b/4coder_string.h
@@ -166,6 +166,7 @@ FSTRING_LINK fstr_bool set_last_folder_ss(String *dir, String folder_name
FSTRING_LINK String file_extension(String str);
FSTRING_LINK fstr_bool remove_extension(String *str);
FSTRING_LINK fstr_bool remove_last_folder(String *str);
+FSTRING_LINK fstr_bool string_set_match_table(void *str_set, int32_t item_size, int32_t count, String str, int32_t *match_index);
FSTRING_LINK fstr_bool string_set_match(String *str_set, int32_t count, String str, int32_t *match_index);
#if !defined(FSTRING_C)
@@ -241,6 +242,7 @@ FSTRING_INLINE int32_t str_to_int(String str);
FSTRING_INLINE int32_t reverse_seek_slash(String str, int32_t pos);
FSTRING_INLINE fstr_bool set_last_folder(String *dir, char *folder_name, char slash);
FSTRING_INLINE fstr_bool set_last_folder(String *dir, String folder_name, char slash);
+FSTRING_INLINE fstr_bool string_set_match(void *str_set, int32_t item_size, int32_t count, String str, int32_t *match_index);
#endif
@@ -384,6 +386,8 @@ FSTRING_INLINE fstr_bool
set_last_folder(String *dir, char *folder_name, char slash){return(set_last_folder_sc(dir,folder_name,slash));}
FSTRING_INLINE fstr_bool
set_last_folder(String *dir, String folder_name, char slash){return(set_last_folder_ss(dir,folder_name,slash));}
+FSTRING_INLINE fstr_bool
+string_set_match(void *str_set, int32_t item_size, int32_t count, String str, int32_t *match_index){return(string_set_match_table(str_set,item_size,count,str,match_index));}
#endif
@@ -2021,13 +2025,15 @@ remove_last_folder(String *str){
#endif
// TODO(allen): Add hash-table extension to string sets.
+
#if defined(FSTRING_IMPLEMENTATION)
FSTRING_LINK fstr_bool
-string_set_match(String *str_set, int32_t count, String str, int32_t *match_index){
+string_set_match_table(void *str_set, int32_t item_size, int32_t count, String str, int32_t *match_index){
fstr_bool result = 0;
int32_t i = 0;
- for (; i < count; ++i, ++str_set){
- if (match_ss(*str_set, str)){
+ uint8_t *ptr = (uint8_t*)str_set;
+ for (; i < count; ++i, ptr += item_size){
+ if (match_ss(*(String*)ptr, str)){
*match_index = i;
result = 1;
break;
@@ -2037,6 +2043,15 @@ string_set_match(String *str_set, int32_t count, String str, int32_t *match_inde
}
#endif
+#if defined(FSTRING_IMPLEMENTATION)
+FSTRING_LINK fstr_bool
+string_set_match(String *str_set, int32_t count, String str, int32_t *match_index){
+ fstr_bool result = string_set_match_table(str_set, sizeof(String), count, str, match_index);
+ return(result);
+}
+#endif
+
+
#ifndef FSTRING_EXPERIMENTAL
#define FSTRING_EXPERIMENTAL
diff --git a/4ed_metagen.cpp b/4ed_metagen.cpp
index 6265777e..4fd0d69d 100644
--- a/4ed_metagen.cpp
+++ b/4ed_metagen.cpp
@@ -333,6 +333,14 @@ generate_style(){
}
//////////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef struct Parse_Context{
+ Cpp_Token *token_s;
+ Cpp_Token *token_e;
+ Cpp_Token *token;
+ char *data;
+} Parse_Context;
+
typedef struct Argument{
String param_string;
String param_name;
@@ -387,6 +395,7 @@ typedef struct Item_Node{
typedef struct Item_Set{
Item_Node *items;
+ int32_t count;
} Item_Set;
typedef struct Parse{
@@ -394,8 +403,97 @@ typedef struct Parse{
Cpp_Token_Stack tokens;
} Parse;
+typedef struct Meta_Unit{
+ Item_Set set;
+
+ Parse *parse;
+ int32_t count;
+} Meta_Unit;
+
+typedef struct Meta_Keywords{
+ String key;
+ Item_Type type;
+} Meta_Keywords;
+
static Item_Node null_item_node = {0};
+static String
+get_lexeme(Cpp_Token token, char *code){
+ String str = make_string(code + token.start, token.size);
+ return(str);
+}
+
+static Parse_Context
+setup_parse_context(char *data, Cpp_Token_Stack stack){
+ Parse_Context context;
+ context.token_s = stack.tokens;
+ context.token_e = stack.tokens + stack.count;
+ context.token = context.token_s;
+ context.data = data;
+ return(context);
+}
+
+static Parse_Context
+setup_parse_context(Parse parse){
+ Parse_Context context;
+ context.token_s = parse.tokens.tokens;
+ context.token_e = parse.tokens.tokens + parse.tokens.count;
+ context.token = context.token_s;
+ context.data = parse.code.str;
+ return(context);
+}
+
+static Cpp_Token*
+get_token(Parse_Context *context){
+ Cpp_Token *result = context->token;
+ if (result >= context->token_e){
+ result = 0;
+ }
+ return(result);
+}
+
+static Cpp_Token*
+get_next_token(Parse_Context *context){
+ Cpp_Token *result = context->token+1;
+ context->token = result;
+ if (result >= context->token_e){
+ result = 0;
+ context->token = context->token_e;
+ }
+ return(result);
+}
+
+static Cpp_Token*
+get_prev_token(Parse_Context *context){
+ Cpp_Token *result = context->token-1;
+ if (result < context->token_s){
+ result = 0;
+ }
+ else{
+ context->token = result;
+ }
+ return(result);
+}
+
+static Cpp_Token*
+can_back_step(Parse_Context *context){
+ Cpp_Token *result = context->token-1;
+ if (result < context->token_s){
+ result = 0;
+ }
+ return(result);
+}
+
+static Cpp_Token*
+set_token(Parse_Context *context, Cpp_Token *token){
+ Cpp_Token *result = 0;
+ if (token >= context->token_s && token < context->token_e){
+ context->token = token;
+ result = token;
+ }
+ return(result);
+}
+
static String
file_dump(char *filename){
String result = {0};
@@ -419,7 +517,7 @@ file_dump(char *filename){
}
static Parse
-meta_parse(char *filename){
+meta_lex(char *filename){
Parse result = {0};
result.code = file_dump(filename);
result.tokens = cpp_make_token_stack(1024);
@@ -427,6 +525,52 @@ meta_parse(char *filename){
return(result);
}
+static Meta_Unit
+compile_meta_unit(Partition *part, char **files, int32_t file_count,
+ Meta_Keywords *keywords, int32_t key_count){
+ Meta_Unit unit = {0};
+ int32_t i = 0;
+
+ unit.count = file_count;
+ unit.parse = push_array(part, Parse, file_count);
+
+ for (i = 0; i < file_count; ++i){
+ unit.parse[i] = meta_lex(files[i]);
+ }
+
+#if 0
+ // TODO(allen): This stage counts nested structs
+ // and unions which is not correct. Luckily it only
+ // means we over allocate by a few items, but fixing it
+ // to be exactly correct would be nice.
+ for (int32_t J = 0; J < unit.count; ++J){
+ Cpp_Token *token = 0;
+ Parse_Context context_ = setup_parse_context(unit.parse[J]);
+ Parse_Context *context = &context_;
+
+ for (; (token = get_token(context)) != 0; get_next_token(context)){
+ if (!(token->flags & CPP_TFLAG_PP_BODY) &&
+ ((token->flags & CPP_TFLAG_IS_KEYWORD) ||
+ token->type == CPP_TOKEN_IDENTIFIER)){
+
+ String lexeme = get_lexeme(*token, context->data);
+ int32_t match_index = 0;
+ if (string_set_match_table(keywords, sizeof(*keywords), key_count, lexeme, &match_index)){
+ switch (match_index){
+ case 0: //typedef
+ case 1: case 2: //struct/union
+ case 3: //ENUM
+ ++unit.set.count; break;
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ return(unit);
+}
+
static String
get_first_line(String source){
String line = {0};
@@ -474,17 +618,17 @@ typedef enum Doc_Note_Type{
} Doc_Note_Type;
static int32_t
-check_and_fix_docs(String *lexeme){
+check_and_fix_docs(String *doc_string){
int32_t result = false;
- if (lexeme->size > 4){
- if (lexeme->str[0] == '/'){
- if (lexeme->str[1] == '*'){
- if (lexeme->str[lexeme->size - 2] == '*'){
- if (lexeme->str[lexeme->size - 1] == '/'){
+ if (doc_string->size > 4){
+ if (doc_string->str[0] == '/'){
+ if (doc_string->str[1] == '*'){
+ if (doc_string->str[doc_string->size - 2] == '*'){
+ if (doc_string->str[doc_string->size - 1] == '/'){
result = true;
- lexeme->str += 2;
- lexeme->size -= 4;
+ doc_string->str += 2;
+ doc_string->size -= 4;
}
}
}
@@ -494,6 +638,23 @@ check_and_fix_docs(String *lexeme){
return(result);
}
+static int32_t
+get_doc_string_from_prev(Parse_Context *context, String *doc_string){
+ int32_t result = false;
+
+ if (can_back_step(context)){
+ Cpp_Token *prev_token = get_token(context) - 1;
+ if (prev_token->type == CPP_TOKEN_COMMENT){
+ *doc_string = get_lexeme(*prev_token, context->data);
+ if (check_and_fix_docs(doc_string)){
+ result = true;
+ }
+ }
+ }
+
+ return(result);
+}
+
static String
doc_note_string[] = {
make_lit_string("DOC_PARAM"),
@@ -688,107 +849,17 @@ perform_doc_parse(Partition *part, String doc_string, Documentation *doc){
}while(keep_parsing);
}
-static String
-get_lexeme(Cpp_Token token, char *code){
- String str = make_string(code + token.start, token.size);
- return(str);
-}
-
static Item_Set
allocate_item_set(Partition *part, int32_t count){
Item_Set item_set = {0};
if (count > 0){
item_set.items = push_array(part, Item_Node, count);
+ item_set.count = count;
memset(item_set.items, 0, sizeof(Item_Node)*count);
}
return(item_set);
}
-typedef struct Parse_Context{
- Cpp_Token *token_s;
- Cpp_Token *token_e;
- Cpp_Token *token;
- char *data;
-} Parse_Context;
-
-static Parse_Context
-setup_parse_context(char *data, Cpp_Token_Stack stack){
- Parse_Context context;
- context.token_s = stack.tokens;
- context.token_e = stack.tokens + stack.count;
- context.token = context.token_s;
- context.data = data;
- return(context);
-}
-
-static Cpp_Token*
-get_token(Parse_Context *context){
- Cpp_Token *result = context->token;
- if (result >= context->token_e){
- result = 0;
- }
- return(result);
-}
-
-static Cpp_Token*
-get_next_token(Parse_Context *context){
- Cpp_Token *result = context->token+1;
- context->token = result;
- if (result >= context->token_e){
- result = 0;
- context->token = context->token_e;
- }
- return(result);
-}
-
-static Cpp_Token*
-get_prev_token(Parse_Context *context){
- Cpp_Token *result = context->token-1;
- if (result < context->token_s){
- result = 0;
- }
- else{
- context->token = result;
- }
- return(result);
-}
-
-static Cpp_Token*
-can_back_step(Parse_Context *context){
- Cpp_Token *result = context->token-1;
- if (result < context->token_s){
- result = 0;
- }
- return(result);
-}
-
-static Cpp_Token*
-set_token(Parse_Context *context, Cpp_Token *token){
- Cpp_Token *result = 0;
- if (token >= context->token_s && token < context->token_e){
- context->token = token;
- result = token;
- }
- return(result);
-}
-
-static int32_t
-get_doc_string_from_prev(Parse_Context *context, String *doc_string){
- int32_t result = false;
-
- if (can_back_step(context)){
- Cpp_Token *prev_token = get_token(context) - 1;
- if (prev_token->type == CPP_TOKEN_COMMENT){
- *doc_string = get_lexeme(*prev_token, context->data);
- if (check_and_fix_docs(doc_string)){
- result = true;
- }
- }
- }
-
- return(result);
-}
-
//
// Meta Parse Rules
@@ -1993,7 +2064,7 @@ generate_custom_headers(){
Partition part_ = make_part(mem, size);
Partition *part = &part_;
- Parse string_parse = meta_parse("internal_4coder_string.cpp");
+ Parse string_parse = meta_lex("internal_4coder_string.cpp");
int32_t string_function_count = 0;
@@ -2083,8 +2154,8 @@ generate_custom_headers(){
//
Parse parses[2];
- parses[0] = meta_parse("4ed_api_implementation.cpp");
- parses[1] = meta_parse("win32_api_impl.cpp");
+ parses[0] = meta_lex("4ed_api_implementation.cpp");
+ parses[1] = meta_lex("win32_api_impl.cpp");
int32_t line_count = 0;
@@ -2258,128 +2329,126 @@ generate_custom_headers(){
// NOTE(allen): Documentation
{
- Item_Set typedef_set = {0};
- Item_Set struct_set = {0};
- Item_Set enum_set = {0};
-
- Parse type_parse[1];
- type_parse[0] = meta_parse("4coder_types.h");
-
- int32_t file_count = ArrayCount(type_parse);
-
- int32_t typedef_count = 0;
- int32_t struct_count = 0;
- int32_t enum_count = 0;
-
- static String type_spec_keys[] = {
- make_lit_string("typedef"),
- make_lit_string("struct"),
- make_lit_string("union"),
- make_lit_string("ENUM")
+ static char *type_files[] = {
+ "4coder_types.h"
};
- for (int32_t J = 0; J < file_count; ++J){
- char *data = type_parse[J].code.str;
-
- int32_t count = type_parse[J].tokens.count;
- Cpp_Token *tokens = type_parse[J].tokens.tokens;
- Cpp_Token *token = tokens;
-
- for (int32_t i = 0; i < count; ++i, ++token){
- if (!(token->flags & CPP_TFLAG_PP_BODY) &&
- (token->type == CPP_TOKEN_KEY_TYPE_DECLARATION ||
- token->type == CPP_TOKEN_IDENTIFIER)){
-
- String lexeme = make_string(data + token->start, token->size);
- int32_t match_index = 0;
- if (string_set_match(type_spec_keys, ArrayCount(type_spec_keys),
- lexeme, &match_index)){
- switch (match_index){
- case 0: //typedef
- ++typedef_count; break;
-
- case 1: case 2: //struct/union
- ++struct_count; break;
-
- case 3: //ENUM
- ++enum_count; break;
- }
- }
- }
- }
- }
+#if 0
+ static Meta_Keywords type_spec_keys[] = {
+ {make_lit_string("typedef") , Item_Typedef } ,
+ {make_lit_string("struct") , Item_Struct } ,
+ {make_lit_string("union") , Item_Union } ,
+ {make_lit_string("ENUM") , Item_Enum } ,
+ };
+#endif
- if (typedef_count > 0){
- typedef_set = allocate_item_set(part, typedef_count);
- }
+ static String type_spec_keys[] = {
+ make_lit_string("typedef") ,
+ make_lit_string("struct") ,
+ make_lit_string("union") ,
+ make_lit_string("ENUM") ,
+ };
- if (struct_count > 0){
- struct_set = allocate_item_set(part, struct_count);
- }
+ Meta_Unit unit = compile_meta_unit(part, type_files, ArrayCount(type_files),
+ 0,0);
+ //type_spec_keys, ArrayCount(type_spec_keys));
- if (enum_count > 0){
- enum_set = allocate_item_set(part, enum_count);
- }
-
- int32_t typedef_index = 0;
- int32_t struct_index = 0;
- int32_t enum_index = 0;
-
- for (int32_t J = 0; J < file_count; ++J){
- char *data = type_parse[J].code.str;
- Cpp_Token_Stack types_tokens = type_parse[J].tokens;
-
- Cpp_Token *token = types_tokens.tokens;
-
- Parse_Context context_ = setup_parse_context(data, types_tokens);
+ // TODO(allen): This stage counts nested structs
+ // and unions which is not correct. Luckily it only
+ // means we over allocate by a few items, but fixing it
+ // to be exactly correct would be nice.
+ for (int32_t J = 0; J < unit.count; ++J){
+ Cpp_Token *token = 0;
+ Parse_Context context_ = setup_parse_context(unit.parse[J]);
Parse_Context *context = &context_;
for (; (token = get_token(context)) != 0; get_next_token(context)){
if (!(token->flags & CPP_TFLAG_PP_BODY) &&
- (token->type == CPP_TOKEN_KEY_TYPE_DECLARATION ||
+ ((token->flags & CPP_TFLAG_IS_KEYWORD) ||
token->type == CPP_TOKEN_IDENTIFIER)){
- String lexeme = get_lexeme(*token, data);
+ String lexeme = get_lexeme(*token, context->data);
+ int32_t match_index = 0;
+ if (string_set_match(type_spec_keys, ArrayCount(type_spec_keys),
+ lexeme, &match_index)){
+ switch (match_index){
+ case 0: //typedef
+ case 1: case 2: //struct/union
+ case 3: //ENUM
+ ++unit.set.count; break;
+ }
+ }
+ }
+ }
+ }
+
+ if (unit.set.count > 0){
+ unit.set = allocate_item_set(part, unit.set.count);
+ }
+
+ int32_t index = 0;
+
+ for (int32_t J = 0; J < unit.count; ++J){
+ Cpp_Token *token = 0;
+ Parse_Context context_ = setup_parse_context(unit.parse[J]);
+ Parse_Context *context = &context_;
+
+ for (; (token = get_token(context)) != 0; get_next_token(context)){
+ if (!(token->flags & CPP_TFLAG_PP_BODY) &&
+ ((token->flags & CPP_TFLAG_IS_KEYWORD) ||
+ token->type == CPP_TOKEN_IDENTIFIER)){
+
+#define InvalidPath Assert(!"Invalid path of execution")
+
+ String lexeme = get_lexeme(*token, context->data);
int32_t match_index = 0;
if (string_set_match(type_spec_keys, ArrayCount(type_spec_keys),
lexeme, &match_index)){
switch (match_index){
case 0: //typedef
{
- set_token(context, token);
- if (typedef_parse(context, typedef_set.items + typedef_index)){
- Assert(typedef_set.items[typedef_index].t == Item_Typedef);
- ++typedef_index;
+ if (typedef_parse(context, unit.set.items + index)){
+ Assert(unit.set.items[index].t == Item_Typedef);
+ ++index;
+ }
+ else{
+ InvalidPath;
}
}break;
case 1: case 2: //struct/union
{
- set_token(context, token);
if (struct_parse(part, (match_index == 1),
- context, struct_set.items + struct_index)){
- Assert(struct_set.items[struct_index].t == Item_Struct ||
- struct_set.items[struct_index].t == Item_Union);
- ++struct_index;
+ context, unit.set.items + index)){
+ Assert(unit.set.items[index].t == Item_Struct ||
+ unit.set.items[index].t == Item_Union);
+ ++index;
+ }
+ else{
+ InvalidPath;
}
}break;
case 3: //ENUM
{
- set_token(context, token);
- if (enum_parse(part, context, enum_set.items + enum_index)){
- Assert(enum_set.items[enum_index].t == Item_Enum);
- ++enum_index;
+ if (enum_parse(part, context, unit.set.items + index)){
+ Assert(unit.set.items[index].t == Item_Enum);
+ ++index;
+ }
+ else{
+ InvalidPath;
}
}break;
+
}
}
}
}
- typedef_count = typedef_index;
- struct_count = struct_index;
- enum_count = enum_index;
+ // NOTE(allen): This is necessary for now because
+ // the original count is slightly overestimated thanks
+ // to nested structs and unions.
+ unit.set.count = index;
}
//
@@ -2818,30 +2887,8 @@ generate_custom_headers(){
"
\n"
);
- for (int32_t i = 0; i < typedef_count; ++i){
- String name = typedef_set.items[i].name;
- fprintf(file,
- "- "
- "%.*s"
- "
\n",
- name.size, name.str,
- name.size, name.str
- );
- }
-
- for (int32_t i = 0; i < enum_count; ++i){
- String name = enum_set.items[i].name;
- fprintf(file,
- "- "
- "%.*s"
- "
\n",
- name.size, name.str,
- name.size, name.str
- );
- }
-
- for (int32_t i = 0; i < struct_count; ++i){
- String name = struct_set.items[i].name;
+ for (int32_t i = 0; i < unit.set.count; ++i){
+ String name = unit.set.items[i].name;
fprintf(file,
"- "
"%.*s"
@@ -2881,16 +2928,8 @@ generate_custom_headers(){
fprintf(file, "
§"SECTION" Type Descriptions
\n");
int32_t I = 1;
- for (int32_t i = 0; i < typedef_count; ++i, ++I){
- print_item(part, file, typedef_set.items + i, SECTION, I);
- }
-
- for (int32_t i = 0; i < enum_count; ++i, ++I){
- print_item(part, file, enum_set.items + i, SECTION, I);
- }
-
- for (int32_t i = 0; i < struct_count; ++i, ++I){
- print_item(part, file, struct_set.items + i, SECTION, I);
+ for (int32_t i = 0; i < unit.set.count; ++i, ++I){
+ print_item(part, file, unit.set.items + i, SECTION, I);
}
}
diff --git a/internal_4coder_string.cpp b/internal_4coder_string.cpp
index dee76470..60dbe677 100644
--- a/internal_4coder_string.cpp
+++ b/internal_4coder_string.cpp
@@ -1742,8 +1742,9 @@ This call returns non-zero on success.) */{
}
// TODO(allen): Add hash-table extension to string sets.
+CPP_NAME(string_set_match)
FSTRING_LINK fstr_bool
-string_set_match(String *str_set, int32_t count, String str, int32_t *match_index)/*
+string_set_match_table(void *str_set, int32_t item_size, int32_t count, String str, int32_t *match_index)/*
DOC_PARAM(str_set, The str_set parameter is an array of String structs specifying matchable strings.)
DOC_PARAM(count, The count parameter specifies the number of String structs in the str_set array.)
DOC_PARAM(str, The str parameter specifies the string to match against the str_set.)
@@ -1753,8 +1754,9 @@ succeeds and returns non-zero. The matching rule is equivalent to the matching
DOC_SEE(match) */{
fstr_bool result = 0;
int32_t i = 0;
- for (; i < count; ++i, ++str_set){
- if (match_ss(*str_set, str)){
+ uint8_t *ptr = (uint8_t*)str_set;
+ for (; i < count; ++i, ptr += item_size){
+ if (match_ss(*(String*)ptr, str)){
*match_index = i;
result = 1;
break;
@@ -1763,6 +1765,20 @@ DOC_SEE(match) */{
return(result);
}
+FSTRING_LINK fstr_bool
+string_set_match(String *str_set, int32_t count, String str, int32_t *match_index)/*
+DOC_PARAM(str_set, The str_set parameter is an array of String structs specifying matchable strings.)
+DOC_PARAM(count, The count parameter specifies the number of String structs in the str_set array.)
+DOC_PARAM(str, The str parameter specifies the string to match against the str_set.)
+DOC_PARAM(match_index, If this call succeeds match_index is filled with the index into str_set where the match occurred.)
+DOC(This call tries to see if str matches any of the strings in str_set. If there is a match the call
+succeeds and returns non-zero. The matching rule is equivalent to the matching rule for match.)
+DOC_SEE(match) */{
+ fstr_bool result = string_set_match_table(str_set, sizeof(String), count, str, match_index);
+ return(result);
+}
+
+
#ifndef FSTRING_EXPERIMENTAL
#define FSTRING_EXPERIMENTAL