static int config_parse(struct darray *sections, const char *file, bool always_open) { char *file_data; struct lexer lex; struct base_token token; struct strref section_name; FILE *f; f = os_fopen(file, "rb"); if (always_open && !f) f = os_fopen(file, "w+"); if (!f) return CONFIG_FILENOTFOUND; os_fread_utf8(f, &file_data); fclose(f); if (!file_data) return CONFIG_SUCCESS; lexer_init(&lex); lexer_start_move(&lex, file_data); base_token_clear(&token); while (lexer_getbasetoken(&lex, &token, PARSE_WHITESPACE)) { struct config_section *section; while (token.type == BASETOKEN_WHITESPACE) { if (!lexer_getbasetoken(&lex, &token, PARSE_WHITESPACE)) goto complete; } if (*token.text.array != '[') { while (!is_newline(*token.text.array)) { if (!lexer_getbasetoken(&lex, &token, PARSE_WHITESPACE)) goto complete; } continue; } strref_clear(§ion_name); config_parse_string(&lex, §ion_name, ']'); if (!section_name.len) break; section = darray_push_back_new(sizeof(struct config_section), sections); section->name = bstrdup_n(section_name.array, section_name.len); config_parse_section(section, &lex); } complete: lexer_free(&lex); return CONFIG_SUCCESS; }
static bool config_parse_string(struct lexer *lex, struct strref *ref, char end) { bool success = end != 0; struct base_token token; base_token_clear(&token); while (lexer_getbasetoken(lex, &token, false)) { if (end) { if (*token.text.array == end) { success = true; break; } else if (is_newline(*token.text.array)) { success = false; break; } } else { if (is_newline(*token.text.array)) { success = true; break; } } strref_add(ref, &token.text); } remove_ref_whitespace(ref); return success; }
static bool cf_lexer_nexttoken(struct cf_lexer *lex, struct cf_token *out_token) { struct base_token token, start_token; bool wrote_data = false; base_token_clear(&token); base_token_clear(&start_token); cf_token_clear(out_token); while (lexer_getbasetoken(&lex->base_lexer, &token, false)) { /* reclassify underscore as alpha for alnum tokens */ if (*token.text.array == '_') token.type = BASETOKEN_ALPHA; /* ignore escaped newlines to merge spliced lines */ if (cf_is_splice(token.text.array)) { lex->base_lexer.offset += newline_size(token.text.array+1); continue; } if (!wrote_data) { out_token->unmerged_str.array = token.text.array; out_token->str.array = lex->write_offset; /* if comment then output a space */ if (cf_lexer_process_comment(lex, out_token)) return true; /* process string tokens if any */ if (cf_lexer_process_string(lex, out_token)) return true; base_token_copy(&start_token, &token); wrote_data = true; } else if (cf_is_token_break(&start_token, &token)) { lex->base_lexer.offset -= token.text.len; break; } /* write token to CF lexer to account for splicing/comments */ cf_lexer_write_strref(lex, &token.text); out_token->str.len += token.text.len; } if (wrote_data) { out_token->unmerged_str.len = (size_t)(lex->base_lexer.offset - out_token->unmerged_str.array); out_token->type = cf_get_token_type(out_token, &start_token); } return wrote_data; }
static void config_parse_section(struct config_section *section, struct lexer *lex) { struct base_token token; while (lexer_getbasetoken(lex, &token, false)) { struct strref name, value; while (token.type == BASETOKEN_WHITESPACE) { if (!lexer_getbasetoken(lex, &token, false)) return; } if (token.type == BASETOKEN_OTHER) { if (*token.text.array == '#') { do { if (!lexer_getbasetoken(lex, &token, false)) return; } while (!is_newline(*token.text.array)); continue; } else if (*token.text.array == '[') { lex->offset--; return; } } strref_copy(&name, &token.text); if (!config_parse_string(lex, &name, '=')) continue; strref_clear(&value); config_parse_string(lex, &value, 0); config_add_item(§ion->items, &name, &value); } }
static void parse_config_data(struct darray *sections, struct lexer *lex) { struct strref section_name; struct base_token token; base_token_clear(&token); while (lexer_getbasetoken(lex, &token, PARSE_WHITESPACE)) { struct config_section *section; while (token.type == BASETOKEN_WHITESPACE) { if (!lexer_getbasetoken(lex, &token, PARSE_WHITESPACE)) return; } if (*token.text.array != '[') { while (!is_newline(*token.text.array)) { if (!lexer_getbasetoken(lex, &token, PARSE_WHITESPACE)) return; } continue; } strref_clear(§ion_name); config_parse_string(lex, §ion_name, ']'); if (!section_name.len) return; section = darray_push_back_new(sizeof(struct config_section), sections); section->name = bstrdup_n(section_name.array, section_name.len); config_parse_section(section, lex); } }