#include #include #include #include static int pproc_next_one_file(scc_pproc_t *pp, scc_lexer_tok_t *out) { scc_lexer_tok_ring_t *stream = null; scc_lexer_tok_t tok = {0}; int ok = 0; CONTINUE: stream = pp->cur_ring; if (pp->expanded_ring.cap) { scc_ring_next_consume(pp->expanded_ring, *out, ok); if (ok == false) { scc_ring_free(pp->expanded_ring); goto CONTINUE; } else { return true; } } scc_ring_peek(*stream, tok, ok); if (ok == false) { return false; } if (pp->at_line_start) { if (tok.type == SCC_TOK_SHARP) { // parse to # scc_pproc_handle_directive(pp); pp->at_line_start = true; goto CONTINUE; } else if (tok.type == SCC_TOK_BLANK) { scc_ring_next(*stream, *out, ok); scc_ring_peek(*stream, tok, ok); if (ok && tok.type == SCC_TOK_SHARP) { scc_lexer_tok_drop(out); scc_pproc_handle_directive(pp); pp->at_line_start = true; goto CONTINUE; } scc_ring_back(*stream, ok); Assert(ok == true); scc_ring_peek(*stream, tok, ok); } } if (pp->enable == false) { scc_lexer_skip_until_newline(stream); pp->at_line_start = true; goto CONTINUE; } if (tok.type == SCC_TOK_ENDLINE) { scc_ring_next_consume(*stream, *out, ok); pp->at_line_start = true; return true; } else if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_IDENTIFIER) { // maybe expanded scc_pproc_macro_t *macro = scc_pproc_macro_table_get(&pp->macro_table, &tok.lexeme); if (macro == null) { scc_ring_next_consume(*stream, *out, ok); return ok; } scc_pproc_expand_by_src(&pp->macro_table, pp->cur_ring, &pp->expanded_ring, macro, pp->config.keep_original_pos); goto CONTINUE; } else { // continue scc_ring_next_consume(*stream, *out, ok); return ok; } return false; } static int pproc_next(scc_pproc_t *pp, scc_lexer_tok_t *tok) { int ret = 0; CONTINUE: ret = pproc_next_one_file(pp, tok); if (ret != 0) { return true; } if (scc_vec_size(pp->file_stack) == 0) { return false; } scc_pproc_file_t *file = scc_vec_pop(pp->file_stack); Assert(file->ring == pp->cur_ring); scc_lexer_drop_ring(file->ring); scc_lexer_drop(&(file->lexer)); scc_sstream_drop(&(file->sstream)); scc_free(file); if (scc_vec_size(pp->file_stack) == 0) { pp->cur_ring = pp->org_ring; } else { pp->cur_ring = scc_vec_at(pp->file_stack, scc_vec_size(pp->file_stack) - 1)->ring; } goto CONTINUE; } void scc_pproc_init(scc_pproc_t *pp, scc_lexer_tok_ring_t *input) { Assert(pp != null && input != null); pp->org_ring = input; pp->cur_ring = pp->org_ring; scc_ring_init(pp->expanded_ring, 0, 0, 0); scc_pproc_marco_table_init(&pp->macro_table); scc_vec_init(pp->include_paths); scc_vec_init(pp->if_stack); scc_vec_init(pp->file_stack); pp->at_line_start = true; pp->enable = true; pp->config.max_include_depth = 32; pp->config.keep_original_pos = true; } void scc_pproc_add_builtin_macros() { // TODO } static cbool fill_token(scc_lexer_tok_t *tok, void *userdata) { scc_pproc_t *pp = userdata; cbool ret = false; CONTINUE: ret = pproc_next(pp, tok); // FIXME Hack the token if (ret && tok->type >= SCC_TOK_DISABLED) { tok->type -= SCC_TOK_DISABLED; } if (ret && scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_INVALID) { PanicFmt("Invalid token: %s", scc_cstring_as_cstr(&tok->lexeme)); } if (ret && !pp->ring_need_comment && scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_COMMENT) { scc_lexer_tok_drop(tok); goto CONTINUE; } if (ret && !pp->ring_need_empty && scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_EMPTYSPACE) { scc_lexer_tok_drop(tok); goto CONTINUE; } return ret; } scc_lexer_tok_ring_t *scc_pproc_to_ring(scc_pproc_t *pp, int ring_size, cbool need_empty, cbool need_comment) { scc_ring_init(pp->ring, ring_size, fill_token, pp); pp->ring_need_comment = need_comment; pp->ring_need_empty = need_empty; pp->ring_ref_count++; return &pp->ring; } // 销毁预处理器 void scc_pproc_drop(scc_pproc_t *pp) { if (pp == null) return; Assert(pp->cur_ring == pp->org_ring); scc_lexer_drop_ring(pp->org_ring); scc_pproc_macro_table_drop(&pp->macro_table); scc_ring_free(pp->expanded_ring); scc_vec_foreach(pp->include_paths, i) { scc_cstring_free(&scc_vec_at(pp->include_paths, i)); } scc_vec_free(pp->include_paths); Assert(scc_vec_size(pp->if_stack) == 0); scc_vec_free(pp->if_stack); Assert(scc_vec_size(pp->file_stack) == 0); scc_vec_free(pp->file_stack); }