From 87003907a703ab5cafa280eda1695d3c7107c590 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Mon, 28 Nov 2016 14:13:53 -0500 Subject: [PATCH] built out the entire site --- build.cpp | 8 +- site/abstract_document.cpp | 1671 +++++++++++++------------ site/out_context.cpp | 46 + site/sitegen.cpp | 104 +- site/source_material/feature_list.txt | 6 +- site/source_material/home.txt | 4 +- site/source_material/introduction.txt | 2 +- site/source_material/roadmap.txt | 4 +- 8 files changed, 1011 insertions(+), 834 deletions(-) diff --git a/build.cpp b/build.cpp index 6ae7d8ae..1ea16a21 100644 --- a/build.cpp +++ b/build.cpp @@ -525,7 +525,7 @@ init_build_line(Build_Line *line){ #define CL_INCLUDES "/I..\\foreign /I..\\foreign\\freetype2" -#define CL_SITE_INCLUDES "/I..\\..\\code" +#define CL_SITE_INCLUDES "/I..\\..\\foreign /I..\\..\\code" #define CL_LIBS \ "user32.lib winmm.lib gdi32.lib opengl32.lib " \ @@ -609,7 +609,7 @@ build_cl(uint32_t flags, char *code_path, char *code_file, char *out_path, char #define GCC_INCLUDES "-I../foreign -I../code" -#define GCC_SITE_INCLUDES "-I../../code" +#define GCC_SITE_INCLUDES "-I../../foreign -I../../code" #define GCC_LIBS \ "-L/usr/local/lib -lX11 -lpthread -lm -lrt " \ @@ -931,9 +931,9 @@ site_build(char *cdir, uint32_t flags){ BEGIN_TIME_SECTION(); #if defined(IS_WINDOWS) - systemf("..\\build\\site\\sitegen . site\\source_material ..\\site"); + systemf("..\\build\\site\\sitegen . ..\\foreign\\site-resources site\\source_material ..\\site"); #else - systemf("../build/site/sitegen . site/source_material ../site"); + systemf("../build/site/sitegen . ../foreign/site-resources site/source_material ../site"); #endif END_TIME_SECTION("run sitegen"); diff --git a/site/abstract_document.cpp b/site/abstract_document.cpp index f6855f37..738b5827 100644 --- a/site/abstract_document.cpp +++ b/site/abstract_document.cpp @@ -17,7 +17,7 @@ // Enriched Text struct Enriched_Text{ - String source; + String source; }; static Enriched_Text @@ -31,9 +31,9 @@ load_enriched_text(Partition *part, char *directory, char *filename){ append_sc(&fname, filename); terminate_with_null(&fname); - result.source = file_dump(fname.str); + result.source = file_dump(fname.str); return(result); - } +} // Document Declaration @@ -70,44 +70,66 @@ struct Document_Item{ struct{ Document_Item *first_child; Document_Item *last_child; - String name; + String name; String id; - } section; - - struct{ - Meta_Unit *unit; - Alternate_Names_Array *alt_names; - int32_t alt_name_type; - } unit_elements; - - struct{ - Enriched_Text *text; - } text; -}; + int32_t show_title; + } section; + + struct{ + Meta_Unit *unit; + Alternate_Names_Array *alt_names; + int32_t alt_name_type; + } unit_elements; + + struct{ + Enriched_Text *text; + } text; + }; }; static Document_Item null_document_item = {0}; -struct Abstract_Document{ - // Document value members - Document_Item *root_item; +enum{ + ItemType_Document, + ItemType_Image, + // never below this + ItemType_COUNT, +}; + +struct Abstract_Item{ + int32_t item_type; char *name; + // Document value members + Document_Item *root_item; + + // TODO(allen): make these external // Document building members Partition *part; Document_Item *section_stack[16]; - int32_t section_top; + int32_t section_top; + + // Image value members + char *source_file; + char *out_file; + float w_h_ratio; + float h_w_ratio; }; -static Abstract_Document null_abstract_document = {0}; +static Abstract_Item null_abstract_item = {0}; -struct Document_Node{ - Abstract_Document doc; - Document_Node *next; +struct Basic_Node{ + Basic_Node *next; +}; + +#define NodeGetData(node, T) ((T*) ((node)+1)) + +struct Basic_List{ + Basic_Node *head; + Basic_Node *tail; }; struct Document_System{ - Document_Node *head; - Document_Node *tail; - + Basic_List doc_list; + Basic_List img_list; Partition *part; }; @@ -118,48 +140,37 @@ create_document_system(Partition *part){ return(system); } -static Abstract_Document* -create_document(Document_System *system, char *name){ - int32_t is_new_name = 1; +static void* +push_item_on_list(Partition *part, Basic_List *list, int32_t item_size){ + int32_t mem_size = item_size + sizeof(Basic_Node); + void *mem = push_block(part, mem_size); + assert(mem != 0); + memset(mem, 0, mem_size); - for (Document_Node *node = system->head; - node != 0; - node = node->next){ - if (match_cc(node->doc.name, name)){ - is_new_name = 0; - } - } - - Abstract_Document *result = 0; - if (is_new_name){ - Document_Node *node = push_struct(system->part, Document_Node); - memset(node, 0, sizeof(*node)); - assert(node != 0); - - result = &node->doc; - node->next = 0; - if (system->head == 0){ - system->head = node; - system->tail = node; - } - else{ - system->tail->next = node; - system->tail = node; - } + Basic_Node *node = (Basic_Node*)mem; + if (list->head == 0){ + list->head = node; + list->tail = node; + } + else{ + list->tail->next = node; + list->tail = node; } + void *result = (node+1); return(result); } -static Abstract_Document* -get_document_by_name(Document_System *system, String name){ - Abstract_Document *result = 0; +static Abstract_Item* +get_item_by_name(Basic_List list, String name){ + Abstract_Item *result = 0; - for (Document_Node *node = system->head; + for (Basic_Node *node = list.head; node != 0; node = node->next){ - if (match_cs(node->doc.name, name)){ - result = &node->doc; + Abstract_Item *item = NodeGetData(node, Abstract_Item); + if (match(item->name, name)){ + result = item; break; } } @@ -167,12 +178,44 @@ get_document_by_name(Document_System *system, String name){ return(result); } +static Abstract_Item* +get_item_by_name(Basic_List list, char *name){ + Abstract_Item *result = 0; + + for (Basic_Node *node = list.head; + node != 0; + node = node->next){ + Abstract_Item *item = NodeGetData(node, Abstract_Item); + if (match(item->name, name)){ + result = item; + break; + } + } + + return(result); +} + +static Abstract_Item* +create_item(Partition *part, Basic_List *list, char *name){ + int32_t is_new_name = 1; + + Abstract_Item *lookup = get_item_by_name(*list, name); + + Abstract_Item *result = 0; + if (is_new_name){ + result = (Abstract_Item*)push_item_on_list(part, list, sizeof(Abstract_Item)); + } + + return(result); +} + static void -set_section_name(Partition *part, Document_Item *item, char *name){ +set_section_name(Partition *part, Document_Item *item, char *name, int32_t show_title){ int32_t name_len = str_size(name); item->section.name = make_string_cap(push_array(part, char, name_len+1), 0, name_len+1); partition_align(part, 8); append_sc(&item->section.name, name); + item->section.show_title = show_title; } static void @@ -184,8 +227,9 @@ set_section_id(Partition *part, Document_Item *item, char *id){ } static void -begin_document_description(Abstract_Document *doc, Partition *part, char *title){ - *doc = null_abstract_document; +begin_document_description(Abstract_Item *doc, Partition *part, char *title, int32_t show_title){ + *doc = null_abstract_item; + doc->item_type = ItemType_Document; doc->part = part; doc->root_item = push_struct(doc->part, Document_Item); @@ -193,27 +237,47 @@ begin_document_description(Abstract_Document *doc, Partition *part, char *title) doc->section_stack[doc->section_top] = doc->root_item; doc->root_item->type = Doc_Root; - set_section_name(doc->part, doc->root_item, title); + set_section_name(doc->part, doc->root_item, title, show_title); } -static void -set_document_name(Abstract_Document *doc, char *name){ - doc->name = name; -} - -static Abstract_Document* -begin_document_description(Document_System *system, char *title, char *name){ - Abstract_Document *doc = create_document(system, name); - if (doc){ - begin_document_description(doc, system->part, title); +static Abstract_Item* +add_image_description(Document_System *system, char *asset_directory, char *source_file, char *out_file, char *name){ + Abstract_Item *item = create_item(system->part, &system->img_list, name); + if (item){ + item->item_type = ItemType_Image; + item->source_file = source_file; + item->out_file = out_file; + item->name = name; + + char str[256]; + String s = make_fixed_width_string(str); + append_sc(&s, asset_directory); + append_sc(&s, "/"); + append_sc(&s, source_file); + terminate_with_null(&s); + + int32_t w = 0, h = 0, comp = 0; + int32_t stbi_r = stbi_info(str, &w, &h, &comp); + assert(stbi_r); + item->w_h_ratio = ((float)w/(float)h); + item->h_w_ratio = ((float)h/(float)w); } - set_document_name(doc, name); - return(doc); + return(item); +} + +static Abstract_Item* +begin_document_description(Document_System *system, char *title, char *name, int32_t show_title){ + Abstract_Item *item = create_item(system->part, &system->doc_list, name); + if (item){ + begin_document_description(item, system->part, title, show_title); + item->name = name; + } + return(item); } static void -end_document_description(Abstract_Document *doc){ - Assert(doc->section_top == 0); +end_document_description(Abstract_Item *item){ + Assert(item->section_top == 0); } static void @@ -230,32 +294,32 @@ append_child(Document_Item *parent, Document_Item *item){ } static void -begin_section(Abstract_Document *doc, char *title, char *id){ - Assert(doc->section_top+1 < ArrayCount(doc->section_stack)); +begin_section(Abstract_Item *item, char *title, char *id){ + Assert(item->section_top+1 < ArrayCount(item->section_stack)); - Document_Item *parent = doc->section_stack[doc->section_top]; - Document_Item *section = push_struct(doc->part, Document_Item); + Document_Item *parent = item->section_stack[item->section_top]; + Document_Item *section = push_struct(item->part, Document_Item); *section = null_document_item; - doc->section_stack[++doc->section_top] = section; + item->section_stack[++item->section_top] = section; section->type = Doc_Section; - set_section_name(doc->part, section, title); + set_section_name(item->part, section, title, 1); if (id){ - set_section_id(doc->part, section, id); + set_section_id(item->part, section, id); } append_child(parent, section); - } +} static void -end_section(Abstract_Document *doc){ +end_section(Abstract_Item *doc){ Assert(doc->section_top > 0); --doc->section_top; } static void -add_todo(Abstract_Document *doc){ +add_todo(Abstract_Item *doc){ Document_Item *parent = doc->section_stack[doc->section_top]; Document_Item *item = push_struct(doc->part, Document_Item); *item = null_document_item; @@ -265,7 +329,7 @@ add_todo(Abstract_Document *doc){ } static void -add_element_list(Abstract_Document *doc, Meta_Unit *unit){ +add_element_list(Abstract_Item *doc, Meta_Unit *unit){ Document_Item *parent = doc->section_stack[doc->section_top]; Document_Item *item = push_struct(doc->part, Document_Item); *item = null_document_item; @@ -276,7 +340,7 @@ add_element_list(Abstract_Document *doc, Meta_Unit *unit){ } static void -add_element_list(Abstract_Document *doc, Meta_Unit *unit, Alternate_Names_Array *alt_names, int32_t alt_name_type){ +add_element_list(Abstract_Item *doc, Meta_Unit *unit, Alternate_Names_Array *alt_names, int32_t alt_name_type){ Document_Item *parent = doc->section_stack[doc->section_top]; Document_Item *item = push_struct(doc->part, Document_Item); *item = null_document_item; @@ -289,7 +353,7 @@ add_element_list(Abstract_Document *doc, Meta_Unit *unit, Alternate_Names_Array } static void -add_full_elements(Abstract_Document *doc, Meta_Unit *unit){ +add_full_elements(Abstract_Item *doc, Meta_Unit *unit){ Document_Item *parent = doc->section_stack[doc->section_top]; Document_Item *item = push_struct(doc->part, Document_Item); *item = null_document_item; @@ -300,7 +364,7 @@ add_full_elements(Abstract_Document *doc, Meta_Unit *unit){ } static void -add_full_elements(Abstract_Document *doc, Meta_Unit *unit, Alternate_Names_Array *alt_names, int32_t alt_name_type){ +add_full_elements(Abstract_Item *doc, Meta_Unit *unit, Alternate_Names_Array *alt_names, int32_t alt_name_type){ Document_Item *parent = doc->section_stack[doc->section_top]; Document_Item *item = push_struct(doc->part, Document_Item); *item = null_document_item; @@ -313,7 +377,7 @@ add_full_elements(Abstract_Document *doc, Meta_Unit *unit, Alternate_Names_Array } static void -add_table_of_contents(Abstract_Document *doc){ +add_table_of_contents(Abstract_Item *doc){ Document_Item *parent = doc->section_stack[doc->section_top]; Document_Item *item = push_struct(doc->part, Document_Item); *item = null_document_item; @@ -323,7 +387,7 @@ add_table_of_contents(Abstract_Document *doc){ } static void -add_enriched_text(Abstract_Document *doc, Enriched_Text *text){ +add_enriched_text(Abstract_Item *doc, Enriched_Text *text){ Assert(doc->section_top+1 < ArrayCount(doc->section_stack)); Document_Item *parent = doc->section_stack[doc->section_top]; @@ -380,7 +444,7 @@ struct Section_Counter{ }; static int32_t -doc_get_link_string(Abstract_Document *doc, char *space, int32_t capacity){ +doc_get_link_string(Abstract_Item *doc, char *space, int32_t capacity){ String str = make_string_cap(space, 0, capacity); append_sc(&str, doc->name); append_sc(&str, ".html"); @@ -388,6 +452,14 @@ doc_get_link_string(Abstract_Document *doc, char *space, int32_t capacity){ return(result); } +static int32_t +img_get_link_string(Abstract_Item *img, char *space, int32_t capacity){ + String str = make_string_cap(space, 0, capacity); + append_sc(&str, img->out_file); + int32_t result = terminate_with_null(&str); + return(result); +} + static void append_section_number_reduced(String *out, Section_Counter *section_counter, int32_t reduce){ int32_t level = section_counter->nest_level-reduce; @@ -410,45 +482,45 @@ extract_command_body(String *out, String l, int32_t *i_in_out, int32_t *body_sta int32_t i = *i_in_out; - for (; i < l.size; ++i){ - if (!char_is_whitespace(l.str[i])){ + for (; i < l.size; ++i){ + if (!char_is_whitespace(l.str[i])){ + break; + } + } + + int32_t found_command_body = 0; + int32_t body_start = 0, body_end = 0; + if (l.str[i] == '{'){ + body_start = i+1; + + for (++i; i < l.size; ++i){ + if (l.str[i] == '}'){ + found_command_body = 1; + body_end = i; + ++i; break; } } - - int32_t found_command_body = 0; - int32_t body_start = 0, body_end = 0; - if (l.str[i] == '{'){ - body_start = i+1; - - for (++i; i < l.size; ++i){ - if (l.str[i] == '}'){ - found_command_body = 1; - body_end = i; - ++i; - break; - } - } - } + } - if (found_command_body){ - result = 1; - } - else{ + if (found_command_body){ + result = 1; + } + else{ #define STR_START "! Doc generator error: missing body for " - #define STR_SLOW " !" - append_sc(out, STR_START); - append_ss(out, command_name); - append_sc(out, STR_SLOW); +#define STR_SLOW " !" + append_sc(out, STR_START); + append_ss(out, command_name); + append_sc(out, STR_SLOW); #undef STR - - fprintf(stderr, "error: missing body for %.*s\n", command_name.size, command_name.str); - } - - *i_in_out = i; - *body_start_out = body_start; - *body_end_out = body_end; + fprintf(stderr, "error: missing body for %.*s\n", command_name.size, command_name.str); + } + + *i_in_out = i; + *body_start_out = body_start; + *body_end_out = body_end; + return(result); } @@ -484,6 +556,8 @@ html_render_section_header(String *out, String section_name, String section_id, } } +#define HTML_WIDTH 800 + static void write_enriched_text_html(String *out, Enriched_Text *text, Document_System *doc_system, Section_Counter *section_counter){ String source = text->source; @@ -523,7 +597,8 @@ write_enriched_text_html(String *out, Enriched_Text *text, Document_System *doc_ enum Command_Types{ Cmd_BackSlash, Cmd_Version, - Cmd_CodeStyle, + Cmd_BeginStyle, + Cmd_EndStyle, Cmd_DocLink, Cmd_BeginList, Cmd_EndList, @@ -533,24 +608,27 @@ write_enriched_text_html(String *out, Enriched_Text *text, Document_System *doc_ Cmd_Section, Cmd_BeginLink, Cmd_EndLink, + Cmd_Image, // never below this Cmd_COUNT, }; static String enriched_commands[Cmd_COUNT]; - enriched_commands[Cmd_BackSlash] = make_lit_string("\\"); - enriched_commands[Cmd_Version] = make_lit_string("VERSION"); - enriched_commands[Cmd_CodeStyle] = make_lit_string("CODE_STYLE"); - enriched_commands[Cmd_DocLink] = make_lit_string("DOC_LINK"); - enriched_commands[Cmd_BeginList] = make_lit_string("BEGIN_LIST"); - enriched_commands[Cmd_EndList] = make_lit_string("END_LIST"); - enriched_commands[Cmd_BeginItem] = make_lit_string("BEGIN_ITEM"); - enriched_commands[Cmd_EndItem] = make_lit_string("END_ITEM"); - enriched_commands[Cmd_BoldFace] = make_lit_string("BOLD_FACE"); - enriched_commands[Cmd_Section] = make_lit_string("SECTION"); - enriched_commands[Cmd_BeginLink] = make_lit_string("BEGIN_LINK"); - enriched_commands[Cmd_EndLink] = make_lit_string("END_LINK"); + enriched_commands[Cmd_BackSlash] = make_lit_string("\\"); + enriched_commands[Cmd_Version] = make_lit_string("VERSION"); + enriched_commands[Cmd_BeginStyle] = make_lit_string("BEGIN_STYLE"); + enriched_commands[Cmd_EndStyle] = make_lit_string("END_STYLE"); + enriched_commands[Cmd_DocLink] = make_lit_string("DOC_LINK"); + enriched_commands[Cmd_BeginList] = make_lit_string("BEGIN_LIST"); + enriched_commands[Cmd_EndList] = make_lit_string("END_LIST"); + enriched_commands[Cmd_BeginItem] = make_lit_string("BEGIN_ITEM"); + enriched_commands[Cmd_EndItem] = make_lit_string("END_ITEM"); + enriched_commands[Cmd_BoldFace] = make_lit_string("BOLD_FACE"); + enriched_commands[Cmd_Section] = make_lit_string("SECTION"); + enriched_commands[Cmd_BeginLink] = make_lit_string("BEGIN_LINK"); + enriched_commands[Cmd_EndLink] = make_lit_string("END_LINK"); + enriched_commands[Cmd_Image] = make_lit_string("IMAGE"); i = command_end; @@ -559,24 +637,33 @@ write_enriched_text_html(String *out, Enriched_Text *text, Document_System *doc_ switch (match_index){ case Cmd_BackSlash: append_sc(out, "\\"); break; case Cmd_Version: append_sc(out, VERSION); break; - case Cmd_CodeStyle: + + case Cmd_BeginStyle: { int32_t body_start = 0, body_end = 0; int32_t has_body = extract_command_body(out, l, &i, &body_start, &body_end, command_string); if (has_body){ String body_text = substr(l, body_start, body_end - body_start); - append_sc(out, ""); - append_ss(out, body_text); - append_sc(out, ""); + body_text = skip_chop_whitespace(body_text); + if (match_sc(body_text, "code")){ + append_sc(out, ""); + } } }break; + case Cmd_EndStyle: + { + append_sc(out, ""); + }break; + + // TODO(allen): upgrade this bs case Cmd_DocLink: { int32_t body_start = 0, body_end = 0; int32_t has_body = extract_command_body(out, l, &i, &body_start, &body_end, command_string); if (has_body){ String body_text = substr(l, body_start, body_end - body_start); + body_text = skip_chop_whitespace(body_text); append_sc(out, ""); @@ -619,6 +706,7 @@ write_enriched_text_html(String *out, Enriched_Text *text, Document_System *doc_ int32_t has_body = extract_command_body(out, l, &i, &body_start, &body_end, command_string); if (has_body){ String body_text = substr(l, body_start, body_end - body_start); + body_text = skip_chop_whitespace(body_text); html_render_section_header(out, body_text, null_string, section_counter); ++section_counter->counter[section_counter->nest_level]; @@ -632,12 +720,18 @@ write_enriched_text_html(String *out, Enriched_Text *text, Document_System *doc_ int32_t has_body = extract_command_body(out, l, &i, &body_start, &body_end, command_string); if (has_body){ String body_text = substr(l, body_start, body_end - body_start); + body_text = skip_chop_whitespace(body_text); - append_sc(out, ""); + } }break; @@ -659,6 +754,45 @@ write_enriched_text_html(String *out, Enriched_Text *text, Document_System *doc_ { append_sc(out, ""); }break; + + case Cmd_Image: + { + int32_t body_start = 0, body_end = 0; + int32_t has_body = extract_command_body(out, l, &i, &body_start, &body_end, command_string); + if (has_body){ + String body_text = substr(l, body_start, body_end - body_start); + body_text = skip_chop_whitespace(body_text); + + int32_t pixel_height = 10; + int32_t pixel_width = HTML_WIDTH / 4; + + Abstract_Item *img_lookup = 0; + if (match_part_sc(body_text, "image:")){ + String img_name = substr_tail(body_text, sizeof("image:")-1); + img_lookup = get_item_by_name(doc_system->img_list, img_name); + + if (img_lookup){ + pixel_height = CEIL32(pixel_width*img_lookup->h_w_ratio); + + append_sc(out, ""); + } + } + } + }break; } } else{ @@ -678,616 +812,616 @@ write_enriched_text_html(String *out, Enriched_Text *text, Document_System *doc_ } append_sc(out, ""); +} + +static void +print_item_in_list(String *out, String name, char *id_postfix){ + append_sc(out, "
  • "); + append_ss(out, name); + append_sc(out, "
  • "); +} + +static void +init_used_links(Partition *part, Used_Links *used, int32_t count){ + used->strs = push_array(part, String, count); + used->count = 0; + used->max = count; +} + +static int32_t +try_to_use(Used_Links *used, String str){ + int32_t result = 1; + int32_t index = 0; + + if (string_set_match(used->strs, used->count, str, &index)){ + result = 0; + } + else{ + used->strs[used->count++] = str; } - static void - print_item_in_list(String *out, String name, char *id_postfix){ - append_sc(out, "
  • "); - append_ss(out, name); - append_sc(out, "
  • "); - } + return(result); +} + +static void +print_struct_html(String *out, Item_Node *member, int32_t hide_children){ + String name = member->name; + String type = member->type; + String type_postfix = member->type_postfix; - static void - init_used_links(Partition *part, Used_Links *used, int32_t count){ - used->strs = push_array(part, String, count); - used->count = 0; - used->max = count; - } + append_ss (out, type); + append_s_char (out, ' '); + append_ss (out, name); + append_ss (out, type_postfix); - static int32_t - try_to_use(Used_Links *used, String str){ - int32_t result = 1; - int32_t index = 0; + if (match_ss(type, make_lit_string("struct")) || + match_ss(type, make_lit_string("union"))){ - if (string_set_match(used->strs, used->count, str, &index)){ - result = 0; + if (hide_children){ + append_sc(out, " { /* non-public internals */ } ;"); } else{ - used->strs[used->count++] = str; + append_sc(out, " {
    "); + + for (Item_Node *member_iter = member->first_child; + member_iter != 0; + member_iter = member_iter->next_sibling){ + print_struct_html(out, member_iter, hide_children); + } + + append_sc(out, "
    };
    "); + } + } + else{ + append_sc(out, ";
    "); + } +} + +static void +print_function_html(String *out, Used_Links *used, String cpp_name, String ret, char *function_call_head, String name, Argument_Breakdown breakdown){ + + append_ss (out, ret); + append_s_char (out, ' '); + append_sc (out, function_call_head); + append_ss (out, name); + + if (breakdown.count == 0){ + append_sc(out, "()"); + } + else if (breakdown.count == 1){ + append_sc(out, "("); + append_ss(out, breakdown.args[0].param_string); + append_sc(out, ")"); + } + else{ + append_sc(out, "(
    "); + + for (int32_t j = 0; j < breakdown.count; ++j){ + append_ss(out, breakdown.args[j].param_string); + if (j < breakdown.count - 1){ + append_s_char(out, ','); + } + append_sc(out, "
    "); } - return(result); + append_sc(out, "
    )"); + } +} + +static void +print_macro_html(String *out, String name, Argument_Breakdown breakdown){ + + append_sc (out, "#define "); + append_ss (out, name); + + if (breakdown.count == 0){ + append_sc(out, "()"); + } + else if (breakdown.count == 1){ + append_s_char (out, '('); + append_ss (out, breakdown.args[0].param_string); + append_s_char (out, ')'); + } + else{ + append_sc (out, "(
    "); + + for (int32_t j = 0; j < breakdown.count; ++j){ + append_ss(out, breakdown.args[j].param_string); + if (j < breakdown.count - 1){ + append_s_char(out, ','); + } + append_sc(out, "
    "); + } + + append_sc(out, ")
    )"); + } +} + +enum Doc_Chunk_Type{ + DocChunk_PlainText, + DocChunk_CodeExample, + + DocChunk_Count +}; + +static String doc_chunk_headers[] = { + make_lit_string(""), + make_lit_string("CODE_EXAMPLE"), +}; + +static String +get_next_doc_chunk(String source, String prev_chunk, Doc_Chunk_Type *type){ + String chunk = {0}; + String word = {0}; + int32_t pos = source.size; + int32_t word_index = 0; + Doc_Chunk_Type t = DocChunk_PlainText; + + int32_t start_pos = (int32_t)(prev_chunk.str - source.str) + prev_chunk.size; + String source_tail = substr_tail(source, start_pos); + + Assert(DocChunk_Count == ArrayCount(doc_chunk_headers)); + + for (word = get_first_word(source_tail); + word.str; + word = get_next_word(source_tail, word), ++word_index){ + + for (int32_t i = 1; i < DocChunk_Count; ++i){ + if (match_ss(word, doc_chunk_headers[i])){ + pos = (int32_t)(word.str - source.str); + t = (Doc_Chunk_Type)i; + goto doublebreak; + } + } + } + doublebreak:; + + *type = DocChunk_PlainText; + if (word_index == 0){ + *type = t; + + int32_t nest_level = 1; + int32_t i = find_s_char(source, pos, '('); + for (++i; i < source.size; ++i){ + if (source.str[i] == '('){ + ++nest_level; + } + else if (source.str[i] == ')'){ + --nest_level; + if (nest_level == 0){ + break; + } + } + } + + pos = i+1; } - static void - print_struct_html(String *out, Item_Node *member, int32_t hide_children){ - String name = member->name; - String type = member->type; - String type_postfix = member->type_postfix; - - append_ss (out, type); - append_s_char (out, ' '); - append_ss (out, name); - append_ss (out, type_postfix); + chunk = substr(source, start_pos, pos - start_pos); + + int32_t is_all_white = 1; + for (int32_t i = 0; i < chunk.size; ++i){ + if (!char_is_whitespace(chunk.str[i])){ + is_all_white = 0; + break; + } + } + + if (is_all_white){ + chunk = null_string; + } + + return(chunk); +} + +static String +get_first_doc_chunk(String source, Doc_Chunk_Type *type){ + String start_str = make_string(source.str, 0); + String chunk = get_next_doc_chunk(source, start_str, type); + return(chunk); +} + +static void +print_doc_description(String *out, Partition *part, String src){ + Doc_Chunk_Type type; + + for (String chunk = get_first_doc_chunk(src, &type); + chunk.str; + chunk = get_next_doc_chunk(src, chunk, &type)){ + switch (type){ + case DocChunk_PlainText: + { + for (String line = get_first_double_line(chunk); + line.str; + line = get_next_double_line(chunk, line)){ + append_ss(out, line); + append_sc(out, "

    "); + } + }break; + + case DocChunk_CodeExample: + { + int32_t start = 0; + int32_t end = chunk.size-1; + while (start < end && chunk.str[start] != '(') ++start; + start += 1; + while (end > start && chunk.str[end] != ')') --end; + + + append_sc(out, HTML_EXAMPLE_CODE_OPEN); + + if (start < end){ + String code_example = substr(chunk, start, end - start); + int32_t first_line = 1; + + for (String line = get_first_line(code_example); + line.str; + line = get_next_line(code_example, line)){ + + if (!(first_line && line.size == 0)){ + int32_t space_i = 0; + for (; space_i < line.size; ++space_i){ + if (line.str[space_i] == ' '){ + append_sc(out, " "); + } + else{ + break; + } + } + + String line_tail = substr_tail(line, space_i); + append_ss(out, line_tail); + append_sc(out, "
    "); + } + first_line = 0; + } + } + + append_sc(out, HTML_EXAMPLE_CODE_CLOSE); + }break; + } + } +} + +static void +print_struct_docs(String *out, Partition *part, Item_Node *member){ + for (Item_Node *member_iter = member->first_child; + member_iter != 0; + member_iter = member_iter->next_sibling){ + String type = member_iter->type; if (match_ss(type, make_lit_string("struct")) || match_ss(type, make_lit_string("union"))){ + print_struct_docs(out, part, member_iter); + } + else{ + Documentation doc = {0}; + perform_doc_parse(part, member_iter->doc_string, &doc); - if (hide_children){ - append_sc(out, " { /* non-public internals */ } ;"); + append_sc(out, "
    "); + + append_sc(out, "
    "HTML_DOC_ITEM_HEAD_INL_OPEN); + append_ss(out, member_iter->name); + append_sc(out, HTML_DOC_ITEM_HEAD_INL_CLOSE"
    "); + + append_sc(out, "
    "HTML_DOC_ITEM_OPEN); + print_doc_description(out, part, doc.main_doc); + append_sc(out, HTML_DOC_ITEM_CLOSE"
    "); + + append_sc(out, "
    "); + } + } +} + +static void +print_see_also(String *out, Documentation *doc){ + int32_t doc_see_count = doc->see_also_count; + if (doc_see_count > 0){ + append_sc(out, HTML_DOC_HEAD_OPEN"See Also"HTML_DOC_HEAD_CLOSE); + + for (int32_t j = 0; j < doc_see_count; ++j){ + String see_also = doc->see_also[j]; + append_sc(out, HTML_DOC_ITEM_OPEN""); + append_ss(out, see_also); + append_sc(out, ""HTML_DOC_ITEM_CLOSE); + } + } +} + +static void +print_function_docs(String *out, Partition *part, String name, String doc_string){ + if (doc_string.size == 0){ + append_sc(out, "No documentation generated for this function."); + fprintf(stderr, "warning: no documentation string for %.*s\n", name.size, name.str); + } + + Temp_Memory temp = begin_temp_memory(part); + + Documentation doc = {0}; + + perform_doc_parse(part, doc_string, &doc); + + int32_t doc_param_count = doc.param_count; + if (doc_param_count > 0){ + append_sc(out, HTML_DOC_HEAD_OPEN"Parameters"HTML_DOC_HEAD_CLOSE); + + for (int32_t j = 0; j < doc_param_count; ++j){ + String param_name = doc.param_name[j]; + String param_docs = doc.param_docs[j]; + + // TODO(allen): check that param_name is actually + // a parameter to this function! + + append_sc(out, "
    "HTML_DOC_ITEM_HEAD_OPEN); + append_ss(out, param_name); + append_sc(out, HTML_DOC_ITEM_HEAD_CLOSE"
    "HTML_DOC_ITEM_OPEN); + append_ss(out, param_docs); + append_sc(out, HTML_DOC_ITEM_CLOSE"
    "); + } + } + + String ret_doc = doc.return_doc; + if (ret_doc.size != 0){ + append_sc(out, HTML_DOC_HEAD_OPEN"Return"HTML_DOC_HEAD_CLOSE HTML_DOC_ITEM_OPEN); + append_ss(out, ret_doc); + append_sc(out, HTML_DOC_ITEM_CLOSE); + } + + String main_doc = doc.main_doc; + if (main_doc.size != 0){ + append_sc(out, HTML_DOC_HEAD_OPEN"Description"HTML_DOC_HEAD_CLOSE HTML_DOC_ITEM_OPEN); + print_doc_description(out, part, main_doc); + append_sc(out, HTML_DOC_ITEM_CLOSE); + } + + print_see_also(out, &doc); + + end_temp_memory(temp); +} + +static void +print_item_html(String *out, Partition *part, Used_Links *used, Item_Node *item, char *id_postfix, char *section, int32_t I, Alternate_Name *alt_name, int32_t alt_name_type){ + Temp_Memory temp = begin_temp_memory(part); + + String name = item->name; + + switch (alt_name_type){ + case AltName_Macro: + { + name = alt_name->macro; + }break; + + case AltName_Public_Name: + { + name = alt_name->public_name; + }break; + } + + /* NOTE(allen): + Open a div for the whole item. + Put a heading in it with the name and section. + Open a "descriptive" box for the display of the code interface. + */ + append_sc(out, "
    "); + + int32_t has_cpp_name = 0; + if (item->cpp_name.str != 0){ + if (try_to_use(used, item->cpp_name)){ + append_sc(out, "
    "); + has_cpp_name = 1; + } + } + + append_sc (out, "

    §"); + append_sc (out, section); + append_s_char (out, '.'); + append_int_to_str (out, I); + append_sc (out, ": "); + append_ss (out, name); + append_sc (out, "

    "); + + append_sc(out, "
    "); + + switch (item->t){ + case Item_Function: + { + // NOTE(allen): Code box + print_function_html(out, used, item->cpp_name, item->ret, "", name, item->breakdown); + + // NOTE(allen): Close the code box + append_sc(out, "
    "); + + // NOTE(allen): Descriptive section + print_function_docs(out, part, name, item->doc_string); + }break; + + case Item_Macro: + { + // NOTE(allen): Code box + print_macro_html(out, name, item->breakdown); + + // NOTE(allen): Close the code box + append_sc(out, "
    "); + + // NOTE(allen): Descriptive section + print_function_docs(out, part, name, item->doc_string); + }break; + + case Item_Typedef: + { + String type = item->type; + + // NOTE(allen): Code box + append_sc (out, "typedef "); + append_ss (out, type); + append_s_char (out, ' '); + append_ss (out, name); + append_s_char (out, ';'); + + // NOTE(allen): Close the code box + append_sc(out, "
    "); + + // NOTE(allen): Descriptive section + String doc_string = item->doc_string; + Documentation doc = {0}; + perform_doc_parse(part, doc_string, &doc); + + String main_doc = doc.main_doc; + if (main_doc.size != 0){ + append_sc(out, HTML_DOC_HEAD_OPEN"Description"HTML_DOC_HEAD_CLOSE); + + append_sc(out, HTML_DOC_ITEM_OPEN); + print_doc_description(out, part, main_doc); + append_sc(out, HTML_DOC_ITEM_CLOSE); } else{ - append_sc(out, " {
    "); + fprintf(stderr, "warning: no documentation string for %.*s\n", name.size, name.str); + } + + print_see_also(out, &doc); + + }break; + + case Item_Enum: + { + // NOTE(allen): Code box + append_sc (out, "enum "); + append_ss (out, name); + append_s_char (out, ';'); + + // NOTE(allen): Close the code box + append_sc(out, "
    "); + + // NOTE(allen): Descriptive section + String doc_string = item->doc_string; + Documentation doc = {0}; + perform_doc_parse(part, doc_string, &doc); + + String main_doc = doc.main_doc; + if (main_doc.size != 0){ + append_sc(out, HTML_DOC_HEAD_OPEN"Description"HTML_DOC_HEAD_CLOSE); - for (Item_Node *member_iter = member->first_child; - member_iter != 0; - member_iter = member_iter->next_sibling){ - print_struct_html(out, member_iter, hide_children); - } + append_sc(out, HTML_DOC_ITEM_OPEN); + print_doc_description(out, part, main_doc); + append_sc(out, HTML_DOC_ITEM_CLOSE); + } + else{ + fprintf(stderr, "warning: no documentation string for %.*s\n", name.size, name.str); + } + + if (item->first_child){ + append_sc(out, HTML_DOC_HEAD_OPEN"Values"HTML_DOC_HEAD_CLOSE); - append_sc(out, "};
    "); - } - } - else{ - append_sc(out, ";
    "); - } - } - - static void - print_function_html(String *out, Used_Links *used, String cpp_name, String ret, char *function_call_head, String name, Argument_Breakdown breakdown){ - - append_ss (out, ret); - append_s_char (out, ' '); - append_sc (out, function_call_head); - append_ss (out, name); - - if (breakdown.count == 0){ - append_sc(out, "()"); - } - else if (breakdown.count == 1){ - append_sc(out, "("); - append_ss(out, breakdown.args[0].param_string); - append_sc(out, ")"); - } - else{ - append_sc(out, "(
    "); - - for (int32_t j = 0; j < breakdown.count; ++j){ - append_ss(out, breakdown.args[j].param_string); - if (j < breakdown.count - 1){ - append_s_char(out, ','); - } - append_sc(out, "
    "); - } - - append_sc(out, "
    )"); - } - } - - static void - print_macro_html(String *out, String name, Argument_Breakdown breakdown){ - - append_sc (out, "#define "); - append_ss (out, name); - - if (breakdown.count == 0){ - append_sc(out, "()"); - } - else if (breakdown.count == 1){ - append_s_char (out, '('); - append_ss (out, breakdown.args[0].param_string); - append_s_char (out, ')'); - } - else{ - append_sc (out, "(
    "); - - for (int32_t j = 0; j < breakdown.count; ++j){ - append_ss(out, breakdown.args[j].param_string); - if (j < breakdown.count - 1){ - append_s_char(out, ','); - } - append_sc(out, "
    "); - } - - append_sc(out, ")
    )"); - } - } - - enum Doc_Chunk_Type{ - DocChunk_PlainText, - DocChunk_CodeExample, - - DocChunk_Count - }; - - static String doc_chunk_headers[] = { - make_lit_string(""), - make_lit_string("CODE_EXAMPLE"), - }; - - static String - get_next_doc_chunk(String source, String prev_chunk, Doc_Chunk_Type *type){ - String chunk = {0}; - String word = {0}; - int32_t pos = source.size; - int32_t word_index = 0; - Doc_Chunk_Type t = DocChunk_PlainText; - - int32_t start_pos = (int32_t)(prev_chunk.str - source.str) + prev_chunk.size; - String source_tail = substr_tail(source, start_pos); - - Assert(DocChunk_Count == ArrayCount(doc_chunk_headers)); - - for (word = get_first_word(source_tail); - word.str; - word = get_next_word(source_tail, word), ++word_index){ - - for (int32_t i = 1; i < DocChunk_Count; ++i){ - if (match_ss(word, doc_chunk_headers[i])){ - pos = (int32_t)(word.str - source.str); - t = (Doc_Chunk_Type)i; - goto doublebreak; + for (Item_Node *member = item->first_child; + member; + member = member->next_sibling){ + Documentation doc = {0}; + perform_doc_parse(part, member->doc_string, &doc); + + append_sc(out, "
    "); + + // NOTE(allen): Dafuq is this all? + append_sc(out, "
    "HTML_DOC_ITEM_HEAD_INL_OPEN); + append_ss(out, member->name); + append_sc(out, HTML_DOC_ITEM_HEAD_INL_CLOSE); + + if (member->value.str){ + append_sc(out, " = "); + append_ss(out, member->value); + } + + append_sc(out, "
    "); + + append_sc(out, "
    "HTML_DOC_ITEM_OPEN); + print_doc_description(out, part, doc.main_doc); + append_sc(out, HTML_DOC_ITEM_CLOSE"
    "); + + append_sc(out, "
    "); } } - } - doublebreak:; - - *type = DocChunk_PlainText; - if (word_index == 0){ - *type = t; - int32_t nest_level = 1; - int32_t i = find_s_char(source, pos, '('); - for (++i; i < source.size; ++i){ - if (source.str[i] == '('){ - ++nest_level; - } - else if (source.str[i] == ')'){ - --nest_level; - if (nest_level == 0){ + print_see_also(out, &doc); + + }break; + + case Item_Struct: case Item_Union: + { + String doc_string = item->doc_string; + + int32_t hide_members = 0; + + if (doc_string.size == 0){ + hide_members = 1; + } + else{ + for (String word = get_first_word(doc_string); + word.str; + word = get_next_word(doc_string, word)){ + if (match_ss(word, make_lit_string("HIDE_MEMBERS"))){ + hide_members = 1; break; } } } - pos = i+1; - } - - chunk = substr(source, start_pos, pos - start_pos); - - int32_t is_all_white = 1; - for (int32_t i = 0; i < chunk.size; ++i){ - if (!char_is_whitespace(chunk.str[i])){ - is_all_white = 0; - break; - } - } - - if (is_all_white){ - chunk = null_string; - } - - return(chunk); - } - - static String - get_first_doc_chunk(String source, Doc_Chunk_Type *type){ - String start_str = make_string(source.str, 0); - String chunk = get_next_doc_chunk(source, start_str, type); - return(chunk); - } - - static void - print_doc_description(String *out, Partition *part, String src){ - Doc_Chunk_Type type; - - for (String chunk = get_first_doc_chunk(src, &type); - chunk.str; - chunk = get_next_doc_chunk(src, chunk, &type)){ + // NOTE(allen): Code box + print_struct_html(out, item, hide_members); - switch (type){ - case DocChunk_PlainText: - { - for (String line = get_first_double_line(chunk); - line.str; - line = get_next_double_line(chunk, line)){ - append_ss(out, line); - append_sc(out, "

    "); - } - }break; - - case DocChunk_CodeExample: - { - int32_t start = 0; - int32_t end = chunk.size-1; - while (start < end && chunk.str[start] != '(') ++start; - start += 1; - while (end > start && chunk.str[end] != ')') --end; - - - append_sc(out, HTML_EXAMPLE_CODE_OPEN); - - if (start < end){ - String code_example = substr(chunk, start, end - start); - int32_t first_line = 1; - - for (String line = get_first_line(code_example); - line.str; - line = get_next_line(code_example, line)){ - - if (!(first_line && line.size == 0)){ - int32_t space_i = 0; - for (; space_i < line.size; ++space_i){ - if (line.str[space_i] == ' '){ - append_sc(out, " "); - } - else{ - break; - } - } - - String line_tail = substr_tail(line, space_i); - append_ss(out, line_tail); - append_sc(out, "
    "); - } - first_line = 0; - } - } - - append_sc(out, HTML_EXAMPLE_CODE_CLOSE); - }break; - } - } - } - - static void - print_struct_docs(String *out, Partition *part, Item_Node *member){ - for (Item_Node *member_iter = member->first_child; - member_iter != 0; - member_iter = member_iter->next_sibling){ - String type = member_iter->type; - if (match_ss(type, make_lit_string("struct")) || - match_ss(type, make_lit_string("union"))){ - print_struct_docs(out, part, member_iter); - } - else{ - Documentation doc = {0}; - perform_doc_parse(part, member_iter->doc_string, &doc); - - append_sc(out, "
    "); - - append_sc(out, "
    "HTML_DOC_ITEM_HEAD_INL_OPEN); - append_ss(out, member_iter->name); - append_sc(out, HTML_DOC_ITEM_HEAD_INL_CLOSE"
    "); - - append_sc(out, "
    "HTML_DOC_ITEM_OPEN); - print_doc_description(out, part, doc.main_doc); - append_sc(out, HTML_DOC_ITEM_CLOSE"
    "); - - append_sc(out, "
    "); - } - } - } - - static void - print_see_also(String *out, Documentation *doc){ - int32_t doc_see_count = doc->see_also_count; - if (doc_see_count > 0){ - append_sc(out, HTML_DOC_HEAD_OPEN"See Also"HTML_DOC_HEAD_CLOSE); - - for (int32_t j = 0; j < doc_see_count; ++j){ - String see_also = doc->see_also[j]; - append_sc(out, HTML_DOC_ITEM_OPEN""); - append_ss(out, see_also); - append_sc(out, ""HTML_DOC_ITEM_CLOSE); - } - } - } - - static void - print_function_docs(String *out, Partition *part, String name, String doc_string){ - if (doc_string.size == 0){ - append_sc(out, "No documentation generated for this function."); - fprintf(stderr, "warning: no documentation string for %.*s\n", name.size, name.str); - } - - Temp_Memory temp = begin_temp_memory(part); - - Documentation doc = {0}; - - perform_doc_parse(part, doc_string, &doc); - - int32_t doc_param_count = doc.param_count; - if (doc_param_count > 0){ - append_sc(out, HTML_DOC_HEAD_OPEN"Parameters"HTML_DOC_HEAD_CLOSE); - - for (int32_t j = 0; j < doc_param_count; ++j){ - String param_name = doc.param_name[j]; - String param_docs = doc.param_docs[j]; - - // TODO(allen): check that param_name is actually - // a parameter to this function! - - append_sc(out, "
    "HTML_DOC_ITEM_HEAD_OPEN); - append_ss(out, param_name); - append_sc(out, HTML_DOC_ITEM_HEAD_CLOSE"
    "HTML_DOC_ITEM_OPEN); - append_ss(out, param_docs); - append_sc(out, HTML_DOC_ITEM_CLOSE"
    "); - } - } - - String ret_doc = doc.return_doc; - if (ret_doc.size != 0){ - append_sc(out, HTML_DOC_HEAD_OPEN"Return"HTML_DOC_HEAD_CLOSE HTML_DOC_ITEM_OPEN); - append_ss(out, ret_doc); - append_sc(out, HTML_DOC_ITEM_CLOSE); - } - - String main_doc = doc.main_doc; - if (main_doc.size != 0){ - append_sc(out, HTML_DOC_HEAD_OPEN"Description"HTML_DOC_HEAD_CLOSE HTML_DOC_ITEM_OPEN); - print_doc_description(out, part, main_doc); - append_sc(out, HTML_DOC_ITEM_CLOSE); - } - - print_see_also(out, &doc); - - end_temp_memory(temp); - } - - static void - print_item_html(String *out, Partition *part, Used_Links *used, Item_Node *item, char *id_postfix, char *section, int32_t I, Alternate_Name *alt_name, int32_t alt_name_type){ - Temp_Memory temp = begin_temp_memory(part); - - String name = item->name; - - switch (alt_name_type){ - case AltName_Macro: - { - name = alt_name->macro; - }break; - - case AltName_Public_Name: - { - name = alt_name->public_name; - }break; - } - - /* NOTE(allen): - Open a div for the whole item. - Put a heading in it with the name and section. - Open a "descriptive" box for the display of the code interface. - */ - append_sc(out, "
    "); - - int32_t has_cpp_name = 0; - if (item->cpp_name.str != 0){ - if (try_to_use(used, item->cpp_name)){ - append_sc(out, "
    "); - has_cpp_name = 1; - } - } - - append_sc (out, "

    §"); - append_sc (out, section); - append_s_char (out, '.'); - append_int_to_str (out, I); - append_sc (out, ": "); - append_ss (out, name); - append_sc (out, "

    "); - - append_sc(out, "
    "); - - switch (item->t){ - case Item_Function: - { - // NOTE(allen): Code box - print_function_html(out, used, item->cpp_name, item->ret, "", name, item->breakdown); - - // NOTE(allen): Close the code box - append_sc(out, "
    "); - - // NOTE(allen): Descriptive section - print_function_docs(out, part, name, item->doc_string); - }break; - - case Item_Macro: - { - // NOTE(allen): Code box - print_macro_html(out, name, item->breakdown); - - // NOTE(allen): Close the code box - append_sc(out, "
    "); - - // NOTE(allen): Descriptive section - print_function_docs(out, part, name, item->doc_string); - }break; - - case Item_Typedef: - { - String type = item->type; - - // NOTE(allen): Code box - append_sc (out, "typedef "); - append_ss (out, type); - append_s_char (out, ' '); - append_ss (out, name); - append_s_char (out, ';'); - - // NOTE(allen): Close the code box - append_sc(out, "
    "); - - // NOTE(allen): Descriptive section - String doc_string = item->doc_string; - Documentation doc = {0}; - perform_doc_parse(part, doc_string, &doc); - - String main_doc = doc.main_doc; - if (main_doc.size != 0){ - append_sc(out, HTML_DOC_HEAD_OPEN"Description"HTML_DOC_HEAD_CLOSE); - - append_sc(out, HTML_DOC_ITEM_OPEN); - print_doc_description(out, part, main_doc); - append_sc(out, HTML_DOC_ITEM_CLOSE); - } - else{ - fprintf(stderr, "warning: no documentation string for %.*s\n", name.size, name.str); - } - - print_see_also(out, &doc); - - }break; - - case Item_Enum: - { - // NOTE(allen): Code box - append_sc (out, "enum "); - append_ss (out, name); - append_s_char (out, ';'); - - // NOTE(allen): Close the code box - append_sc(out, ""); - - // NOTE(allen): Descriptive section - String doc_string = item->doc_string; - Documentation doc = {0}; - perform_doc_parse(part, doc_string, &doc); - - String main_doc = doc.main_doc; - if (main_doc.size != 0){ - append_sc(out, HTML_DOC_HEAD_OPEN"Description"HTML_DOC_HEAD_CLOSE); - - append_sc(out, HTML_DOC_ITEM_OPEN); - print_doc_description(out, part, main_doc); - append_sc(out, HTML_DOC_ITEM_CLOSE); - } - else{ - fprintf(stderr, "warning: no documentation string for %.*s\n", name.size, name.str); - } - - if (item->first_child){ - append_sc(out, HTML_DOC_HEAD_OPEN"Values"HTML_DOC_HEAD_CLOSE); - - for (Item_Node *member = item->first_child; - member; - member = member->next_sibling){ - Documentation doc = {0}; - perform_doc_parse(part, member->doc_string, &doc); - - append_sc(out, "
    "); - - // NOTE(allen): Dafuq is this all? - append_sc(out, "
    "HTML_DOC_ITEM_HEAD_INL_OPEN); - append_ss(out, member->name); - append_sc(out, HTML_DOC_ITEM_HEAD_INL_CLOSE); - - if (member->value.str){ - append_sc(out, " = "); - append_ss(out, member->value); - } - - append_sc(out, "
    "); - - append_sc(out, "
    "HTML_DOC_ITEM_OPEN); - print_doc_description(out, part, doc.main_doc); - append_sc(out, HTML_DOC_ITEM_CLOSE"
    "); - - append_sc(out, "
    "); - } - } - - print_see_also(out, &doc); - - }break; - - case Item_Struct: case Item_Union: - { - String doc_string = item->doc_string; - - int32_t hide_members = 0; - - if (doc_string.size == 0){ - hide_members = 1; - } - else{ - for (String word = get_first_word(doc_string); - word.str; - word = get_next_word(doc_string, word)){ - if (match_ss(word, make_lit_string("HIDE_MEMBERS"))){ - hide_members = 1; - break; - } - } - } - - // NOTE(allen): Code box - print_struct_html(out, item, hide_members); - - // NOTE(allen): Close the code box - append_sc(out, ""); - - // NOTE(allen): Descriptive section - { - Documentation doc = {0}; - perform_doc_parse(part, doc_string, &doc); - - String main_doc = doc.main_doc; - if (main_doc.size != 0){ - append_sc(out, HTML_DOC_HEAD_OPEN"Description"HTML_DOC_HEAD_CLOSE); - - append_sc(out, HTML_DOC_ITEM_OPEN); - print_doc_description(out, part, main_doc); - append_sc(out, HTML_DOC_ITEM_CLOSE); - } - else{ - fprintf(stderr, "warning: no documentation string for %.*s\n", name.size, name.str); - } - - if (!hide_members){ - if (item->first_child){ - append_sc(out, HTML_DOC_HEAD_OPEN"Fields"HTML_DOC_HEAD_CLOSE); - print_struct_docs(out, part, item); - } - } - - print_see_also(out, &doc); - } - }break; - } - - if (has_cpp_name){ + // NOTE(allen): Close the code box append_sc(out, ""); - } - - // NOTE(allen): Close the item box - append_sc(out, "
    "); - - end_temp_memory(temp); + + // NOTE(allen): Descriptive section + { + Documentation doc = {0}; + perform_doc_parse(part, doc_string, &doc); + + String main_doc = doc.main_doc; + if (main_doc.size != 0){ + append_sc(out, HTML_DOC_HEAD_OPEN"Description"HTML_DOC_HEAD_CLOSE); + + append_sc(out, HTML_DOC_ITEM_OPEN); + print_doc_description(out, part, main_doc); + append_sc(out, HTML_DOC_ITEM_CLOSE); + } + else{ + fprintf(stderr, "warning: no documentation string for %.*s\n", name.size, name.str); + } + + if (!hide_members){ + if (item->first_child){ + append_sc(out, HTML_DOC_HEAD_OPEN"Fields"HTML_DOC_HEAD_CLOSE); + print_struct_docs(out, part, item); + } + } + + print_see_also(out, &doc); + } + }break; } + if (has_cpp_name){ + append_sc(out, ""); + } + + // NOTE(allen): Close the item box + append_sc(out, "
    "); + + end_temp_memory(temp); +} + static void - doc_item_head_html(String *out, Partition *part, Document_System *doc_system, Used_Links *used_links, Document_Item *item, Section_Counter *section_counter){ +doc_item_head_html(String *out, Partition *part, Document_System *doc_system, Used_Links *used_links, Document_Item *item, Section_Counter *section_counter){ switch (item->type){ case Doc_Root: { @@ -1348,12 +1482,15 @@ static void "\n" "" "
    "); + "width: "); + append_int_to_str(out, HTML_WIDTH); + append_sc(out, "px; text-align: justify; line-height: 1.25;'>"); - - append_sc(out, "

    "); - append_ss(out, item->section.name); - append_sc(out, "

    "); + if (item->section.show_title){ + append_sc(out, "

    "); + append_ss(out, item->section.name); + append_sc(out, "

    "); + } }break; case Doc_Section: @@ -1379,28 +1516,28 @@ static void Alternate_Names_Array *alt_names = item->unit_elements.alt_names; int32_t count = unit->set.count; - switch (item->unit_elements.alt_name_type){ - case AltName_Standard: - { - for (int32_t i = 0; i < count; ++i){ - print_item_in_list(out, unit->set.items[i].name, "_doc"); + switch (item->unit_elements.alt_name_type){ + case AltName_Standard: + { + for (int32_t i = 0; i < count; ++i){ + print_item_in_list(out, unit->set.items[i].name, "_doc"); + } + }break; + + case AltName_Macro: + { + for (int32_t i = 0; i < count; ++i){ + print_item_in_list(out, alt_names->names[i].macro, "_doc"); + } + }break; + + case AltName_Public_Name: + { + for (int32_t i = 0; i < count; ++i){ + print_item_in_list(out, alt_names->names[i].public_name, "_doc"); + } + }break; } - }break; - - case AltName_Macro: - { - for (int32_t i = 0; i < count; ++i){ - print_item_in_list(out, alt_names->names[i].macro, "_doc"); - } - }break; - - case AltName_Public_Name: - { - for (int32_t i = 0; i < count; ++i){ - print_item_in_list(out, alt_names->names[i].public_name, "_doc"); - } - }break; - } append_sc(out, ""); }break; @@ -1417,17 +1554,17 @@ static void terminate_with_null(§ion_str); if (alt_names){ - int32_t I = 1; - for (int32_t i = 0; i < count; ++i, ++I){ - print_item_html(out, part, used_links, &unit->set.items[i], "_doc", section_str.str, I, &alt_names->names[i], item->unit_elements.alt_name_type); + int32_t I = 1; + for (int32_t i = 0; i < count; ++i, ++I){ + print_item_html(out, part, used_links, &unit->set.items[i], "_doc", section_str.str, I, &alt_names->names[i], item->unit_elements.alt_name_type); + } } - } - else{ - int32_t I = 1; - for (int32_t i = 0; i < count; ++i, ++I){ - print_item_html(out, part, used_links, &unit->set.items[i], "_doc", section_str.str, I, 0, 0); + else{ + int32_t I = 1; + for (int32_t i = 0; i < count; ++i, ++I){ + print_item_html(out, part, used_links, &unit->set.items[i], "_doc", section_str.str, I, 0, 0); + } } - } }break; case Doc_Table_Of_Contents: @@ -1440,15 +1577,15 @@ static void toc_item = toc_item->next){ if (toc_item->type == Doc_Section){ if (toc_item->section.id.size > 0){ - append_sc(out, "
  • §"); + append_sc(out, "
  • §"); } else{ append_sc(out, "
  • §"); } - append_int_to_str (out, i); - append_s_char (out, ' '); + append_int_to_str (out, i); + append_s_char (out, ' '); append_ss (out, toc_item->section.name); append_sc (out, "
  • "); ++i; @@ -1494,7 +1631,9 @@ generate_item_html(String *out, Partition *part, Document_System *doc_system, Us } static void -generate_document_html(String *out, Partition *part, Document_System *doc_system, Abstract_Document *doc){ +generate_document_html(String *out, Partition *part, Document_System *doc_system, Abstract_Item *doc){ + assert(doc->root_item != 0); + Used_Links used_links = {0}; init_used_links(part, &used_links, 4000); diff --git a/site/out_context.cpp b/site/out_context.cpp index 7d0831b5..d0d25def 100644 --- a/site/out_context.cpp +++ b/site/out_context.cpp @@ -68,6 +68,52 @@ make_out_string(int32_t x){ return(str); } +static void +do_file_copy(Partition *part, char *src_dir, char *src_file, char *dst_dir, char *dst_file){ + char src[256]; + char dst[256]; + String str = {0}; + int32_t success = 0; + + str = make_fixed_width_string(src); + append_sc(&str, src_dir); + append_sc(&str, "/"); + append_sc(&str, src_file); + terminate_with_null(&str); + + str = make_fixed_width_string(dst); + append_sc(&str, dst_dir); + append_sc(&str, "/"); + append_sc(&str, dst_file); + terminate_with_null(&str); + + Temp_Memory temp = begin_temp_memory(part); + int32_t mem_size = partition_remaining(part); + void *mem = push_block(part, mem_size); + FILE *in = fopen(src, "rb"); + if (in){ + fseek(in, 0, SEEK_END); + int32_t file_size = ftell(in); + + if (mem_size >= file_size){ + fseek(in, 0, SEEK_SET); + fread(mem, 1, file_size, in); + + FILE *out = fopen(dst, "wb"); + if (out){ + fwrite(mem, 1, file_size, out); + fclose(out); + success = 1; + } + } + + fclose(in); + } + end_temp_memory(temp); + + assert(success); +} + #endif // BOTTOM diff --git a/site/sitegen.cpp b/site/sitegen.cpp index 6a2a438e..076962ef 100644 --- a/site/sitegen.cpp +++ b/site/sitegen.cpp @@ -9,8 +9,12 @@ // TOP +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + #include "4coder_version.h" -#include "internal_4coder_string.cpp" +#define FSTRING_IMPLEMENTATION +#include "4coder_string.h" #include "4cpp_lexer.h" #include @@ -19,6 +23,10 @@ #include #include "4coder_mem.h" + +#define CEIL32(x) ((int32_t) ( (x>0)?(x+1.f):(x) )) +#define FLOOR32(x) ((int32_t) ( (x>0)?(x):(x-1.f) )) + #include "meta_parser.cpp" #include "out_context.cpp" #include "abstract_document.cpp" @@ -31,43 +39,6 @@ // Meta Parse Rules // -#define BACK_COLOR "#FAFAFA" -#define TEXT_COLOR "#0D0D0D" -#define CODE_BACK "#DFDFDF" -#define EXAMPLE_BACK "#EFEFDF" - -#define POP_COLOR_1 "#309030" -#define POP_BACK_1 "#E0FFD0" -#define VISITED_LINK "#A0C050" - -#define POP_COLOR_2 "#005000" - -#define CODE_STYLE "font-family: \"Courier New\", Courier, monospace; text-align: left;" - -#define CODE_BLOCK_STYLE(back) \ -"margin-top: 3mm; margin-bottom: 3mm; font-size: .95em; " \ -"background: "back"; padding: 0.25em;" - -#define DESCRIPT_SECTION_STYLE CODE_BLOCK_STYLE(CODE_BACK) -#define EXAMPLE_CODE_STYLE CODE_BLOCK_STYLE(EXAMPLE_BACK) - -#define DOC_HEAD_OPEN "
    " -#define DOC_HEAD_CLOSE "
    " - -#define DOC_ITEM_HEAD_STYLE "font-weight: 600;" - -#define DOC_ITEM_HEAD_INL_OPEN "" -#define DOC_ITEM_HEAD_INL_CLOSE "" - -#define DOC_ITEM_HEAD_OPEN "
    " -#define DOC_ITEM_HEAD_CLOSE "
    " - -#define DOC_ITEM_OPEN "
    " -#define DOC_ITEM_CLOSE "
    " - -#define EXAMPLE_CODE_OPEN "
    " -#define EXAMPLE_CODE_CLOSE "
    " - static void print_function_body_code(String *out, Parse_Context *context, int32_t start){ String pstr = {0}, lexeme = {0}; @@ -152,40 +123,44 @@ assert_files_are_equal(char *directory, char *filename1, char *filename2){ } static void - do_html_output(Document_System *doc_system, Partition *part, char *dst_directory, Abstract_Document *doc){ + do_html_output(Document_System *doc_system, Partition *part, char *dst_directory, Abstract_Item *doc){ // NOTE(allen): Output Temp_Memory temp = begin_temp_memory(part); + String out = str_alloc(part, 10 << 20); + assert(out.str); Out_Context context = {0}; set_context_directory(&context, dst_directory); // Output Docs char space[256]; if (doc_get_link_string(doc, space, sizeof(space))){ - if (begin_file_out(&context, space, &out)){ - generate_document_html(&out, part, doc_system, doc); - end_file_out(context); + if (begin_file_out(&context, space, &out)){ + generate_document_html(&out, part, doc_system, doc); + end_file_out(context); + } + else{ + fprintf(stderr, "Failed to open %s\n", space); + } } - else{ - fprintf(stderr, "Failed to open %s", space); - } - } + end_temp_memory(temp); } - static Abstract_Document* + static Abstract_Item* generate_homepage(Document_System *doc_system, Partition *part, char *src_directory){ Enriched_Text *home = push_struct(part, Enriched_Text); *home = load_enriched_text(part, src_directory, "home.txt"); - Abstract_Document *doc = begin_document_description(doc_system, "4coder Home", "home"); + Abstract_Item *doc = begin_document_description(doc_system, "4coder Home", "home", 0); add_enriched_text(doc, home); end_document_description(doc); return(doc); } - static Abstract_Document* + // TODO(allen): replace the documentation declaration system with a straight up enriched text system + static Abstract_Item* generate_4coder_docs(Document_System *doc_system, Partition *part, char *code_directory, char *src_directory){ static Meta_Keywords meta_keywords[] = { {make_lit_string("API_EXPORT") , Item_Function } , @@ -252,7 +227,7 @@ assert_files_are_equal(char *directory, char *filename1, char *filename2){ *lexer_introduction = load_enriched_text(part, src_directory, "lexer_introduction.txt"); // NOTE(allen): Put together the abstract document - Abstract_Document *doc = begin_document_description(doc_system, "4coder API Docs", "custom_docs"); + Abstract_Item *doc = begin_document_description(doc_system, "4coder API Docs", "custom_docs", 1); add_table_of_contents(doc); @@ -320,24 +295,24 @@ assert_files_are_equal(char *directory, char *filename1, char *filename2){ return(doc); } - static Abstract_Document* + static Abstract_Item* generate_feature_list(Document_System *doc_system, Partition *part, char *src_directory){ Enriched_Text *feature_list = push_struct(part, Enriched_Text); *feature_list = load_enriched_text(part, src_directory, "feature_list.txt"); - Abstract_Document *doc = begin_document_description(doc_system, "4coder Feature List", "features"); + Abstract_Item *doc = begin_document_description(doc_system, "4coder Feature List", "features", 0); add_enriched_text(doc, feature_list); end_document_description(doc); return(doc); } - static Abstract_Document* + static Abstract_Item* generate_roadmap(Document_System *doc_system, Partition *part, char *src_directory){ Enriched_Text *roadmap = push_struct(part, Enriched_Text); *roadmap = load_enriched_text(part, src_directory, "roadmap.txt"); - Abstract_Document *doc = begin_document_description(doc_system, "4coder Roadmap", "roadmap"); + Abstract_Item *doc = begin_document_description(doc_system, "4coder Roadmap", "roadmap", 0); add_enriched_text(doc, roadmap); end_document_description(doc); @@ -345,7 +320,7 @@ assert_files_are_equal(char *directory, char *filename1, char *filename2){ } static void -generate_site(char *code_directory, char *src_directory, char *dst_directory){ +generate_site(char *code_directory, char *asset_directory, char *src_directory, char *dst_directory){ int32_t size = (512 << 20); void *mem = malloc(size); memset(mem, 0, size); @@ -354,22 +329,33 @@ generate_site(char *code_directory, char *src_directory, char *dst_directory){ Partition *part = &part_; Document_System doc_system = create_document_system(part); + add_image_description(&doc_system, asset_directory, "4coder_green.png", "4coder_logo.png", "4coder_logo"); generate_homepage(&doc_system, part, src_directory); generate_4coder_docs(&doc_system, part, code_directory, src_directory); generate_feature_list(&doc_system, part, src_directory); generate_roadmap(&doc_system, part, src_directory); - for (Document_Node *node = doc_system.head; + for (Basic_Node *node = doc_system.img_list.head; node != 0; node = node->next){ - do_html_output(&doc_system, part, dst_directory, &node->doc); + Abstract_Item *img = NodeGetData(node, Abstract_Item); + assert(img->item_type == ItemType_Image); + do_file_copy(part, asset_directory, img->source_file, dst_directory, img->out_file); + } + + for (Basic_Node *node = doc_system.doc_list.head; + node != 0; + node = node->next){ + Abstract_Item *doc = NodeGetData(node, Abstract_Item); + assert(doc->item_type == ItemType_Document); + do_html_output(&doc_system, part, dst_directory, doc); } } int main(int argc, char **argv){ - if (argc == 4){ - generate_site(argv[1], argv[2], argv[3]); + if (argc == 5){ + generate_site(argv[1], argv[2], argv[3], argv[4]); } } diff --git a/site/source_material/feature_list.txt b/site/source_material/feature_list.txt index 2c54fbbd..0de28e84 100644 --- a/site/source_material/feature_list.txt +++ b/site/source_material/feature_list.txt @@ -1,5 +1,7 @@ -This page provides a list of 4coder features for anyone trying to determine whether 4coder is the right editor for them. If a feature is missing here you should check out the \BEGIN_LINK{document:roadmap} roadmap \END_LINK page to see what is coming in the future. If the feature you want is on neither, you should contact \CODE_STYLE{editor@4coder.net}. Some features that are already in 4coder might be missing from this list, if you want to be sure you should contact \CODE_STYLE{editor@4coder.net}. +\IMAGE{image:4coder_logo} + +This page provides a list of 4coder features for anyone trying to determine whether 4coder is the right editor for them. If a feature is missing here you should check out the \BEGIN_LINK{document:roadmap} roadmap \END_LINK page to see what is coming in the future. If the feature you want is on neither, you should contact \BEGIN_STYLE{code} editor@4coder.net \END_STYLE. Some features that are already in 4coder might be missing from this list, if you want to be sure you should contact \BEGIN_STYLE{code} editor@4coder.net \END_STYLE. \SECTION{Text Editing} \BEGIN_LIST @@ -46,7 +48,7 @@ This page provides a list of 4coder features for anyone trying to determine whet 4coder's current setup and editing paradigm is modeled after emacs, so it is very natural to transition to 4coder from emacs for many users. 4coder customization is quite different from emacs though, so anyone who wants to keep their current keybinds will have to take the time to rewrite the keybinding code. Once the initial transition is done, any user who prefers C++ to Lisp will have a much better time in their 4coder configuration code. \SECTION{Transition From Vim} -For vim users the built-in editing paradigm will not line up with editing habits. Thanks to the open customization model, a vim paradigm and default vim key bindings can be used in 4coder. The vim customization \BEGIN_LINK{https://github.com/Chronister/4vim} here \END_LINK is an early example of this with many basic vim systems up and running. +For vim users the built-in editing paradigm will not line up with editing habits. Thanks to the open customization model, a vim paradigm and default vim key bindings can be used in 4coder. The vim customization \BEGIN_LINK{!https://github.com/Chronister/4vim} here \END_LINK is an early example of this with many basic vim systems up and running. Right now 4coder is admittedly not great for vim users, but the transition path exists so keep your eyes on 4coder as better vim emulation is still on the way. diff --git a/site/source_material/home.txt b/site/source_material/home.txt index 184a4003..412bc86c 100644 --- a/site/source_material/home.txt +++ b/site/source_material/home.txt @@ -1,7 +1,9 @@ +\IMAGE{image:4coder_logo} + 4coder is a code editor that first and foremost targets the needs C/C++ developers so that developers in that space can be as efficient as possible. Here you can learn about the features of 4coder, how to get started with 4coder, and how to get the absolute most out of 4cocer. -If you cannot find what you are looking for please contact \CODE_STYLE{editor@4coder.net} with questions. +If you cannot find what you are looking for please contact \BEGIN_STYLE{code} editor@4coder.net \END_STYLE with questions. \BEGIN_LINK{document:features} The official 4coder feature list \END_LINK diff --git a/site/source_material/introduction.txt b/site/source_material/introduction.txt index 2ca71b15..ac62ebd0 100644 --- a/site/source_material/introduction.txt +++ b/site/source_material/introduction.txt @@ -1,4 +1,4 @@ This is the documentation for \VERSION. The documentation is still under construction so some of the links are linking to sections that have not been written yet. What is here should be correct and I suspect useful even without some of the other sections. -If you have questions or discover errors please contact \CODE_STYLE{editor@4coder.net} or to get help from members of the 4coder and handmade network community you can post on the 4coder forums hosted at \CODE_STYLE{4coder.handmade.network}. +If you have questions or discover errors please contact \BEGIN_STYLE{code} editor@4coder.net \END_STYLE or to get help from members of the 4coder and handmade network community you can post on the 4coder forums hosted at \BEGIN_STYLE{code} 4coder.handmade.network \END_STYLE. diff --git a/site/source_material/roadmap.txt b/site/source_material/roadmap.txt index a2aae791..fcec4150 100644 --- a/site/source_material/roadmap.txt +++ b/site/source_material/roadmap.txt @@ -1,5 +1,7 @@ -This page provides an outline of planned 4coder features roughly sorted by priority. If a feature is missing here it may be on the \BEGIN_LINK{document:features} features \END_LINK page which means it is already in 4coder. If a feature is missing from both lists and you would like to recommend it for consideration, send your recommendation to \CODE_STYLE{editor@4coder.net}. If you believe the priority sorting of the items should be tweaked because certain items are more important than others, that recommendation can also be sent to the same 4coder email as any other recommendation. +\IMAGE{image:4coder_logo} + +This page provides an outline of planned 4coder features roughly sorted by priority. If a feature is missing here it may be on the \BEGIN_LINK{document:features} features \END_LINK page which means it is already in 4coder. If a feature is missing from both lists and you would like to recommend it for consideration, send your recommendation to \BEGIN_STYLE{code} editor@4coder.net \END_STYLE. If you believe the priority sorting of the items should be tweaked because certain items are more important than others, that recommendation can also be sent to the same 4coder email as any other recommendation. Each section represents one major type of todo item, within each section the items are roughly sorted by priority with respect to other items in that section. The sections are also sorted by a rough priority, but more than one section might receive attention at a time.