#include #include #include static int switch_file_stack(scc_pproc_t *pp, scc_cstring_t *fname, scc_pos_t *pos, int is_system) { scc_cstring_t fpath = scc_cstring_create(); int ret = 0; const char *org_fname = pos->name; if (!is_system) { const char parent[] = "/../"; // FIXME maybe it can eazy scc_cstring_append_cstr(&fpath, org_fname, scc_strlen(org_fname)); scc_cstring_append_cstr(&fpath, parent, scc_strlen(parent)); scc_cstring_append(&fpath, fname); ret = scc_fexists(scc_cstring_as_cstr(&fpath)); if (ret == true) { goto FOPEN; } } /* system default path and -I includes path */ scc_vec_foreach(pp->include_paths, i) { scc_cstring_free(&fpath); scc_cstring_t *syspath = &scc_vec_at(pp->include_paths, i); scc_cstring_append(&fpath, syspath); scc_cstring_append_ch(&fpath, '/'); scc_cstring_append(&fpath, fname); ret = scc_fexists(scc_cstring_as_cstr(&fpath)); if (ret == true) { goto FOPEN; } } SCC_ERROR(*pos, "include file '%s' not found", scc_cstring_as_cstr(fname)); return -1; FOPEN: if ((int)scc_vec_size(pp->file_stack) >= pp->config.max_include_depth) { SCC_FATAL(*pos, "include depth exceeds maximum (%d)", pp->config.max_include_depth); LOG_FATAL("Include depth is too deep..."); } scc_pproc_file_t *file = scc_malloc(sizeof(scc_pproc_file_t)); Assert(file != null); if (scc_sstream_init(&(file->sstream), scc_cstring_as_cstr(&fpath), 1024)) { return -1; } scc_lexer_init(&(file->lexer), scc_sstream_to_ring(&(file->sstream))); file->ring = scc_lexer_to_ring(&(file->lexer), 8, true); pp->cur_ring = file->ring; scc_vec_push(pp->file_stack, file); return 0; } void scc_pproc_parse_include(scc_pproc_t *pp, scc_lexer_tok_t *include_tok, scc_lexer_tok_ring_t *tok_ring) { int ok; scc_lexer_tok_t tok; scc_pos_t pos = include_tok->loc; scc_lexer_tok_drop(include_tok); scc_cstring_t line = scc_cstring_create(); while (1) { scc_ring_next_consume(*tok_ring, tok, ok); if (!ok) break; if (scc_get_tok_subtype(tok.type) != SCC_TOK_SUBTYPE_EMPTYSPACE && scc_get_tok_subtype(tok.type) != SCC_TOK_SUBTYPE_COMMENT) { scc_cstring_append(&line, &tok.lexeme); } scc_lexer_tok_drop(&tok); } scc_ring_free(*tok_ring); const char *includename = scc_cstring_as_cstr(&line); int len = scc_cstring_len(&line); if (len < 2) { goto ERROR; } else if (len == 2) { goto ERROR; } else { if (includename[0] == '\"') { if (includename[len - 1] != '\"') { goto ERROR; } } else if (includename[0] == '<') { if (includename[len - 1] != '>') { goto ERROR; } } else { goto ERROR; } } scc_cstring_t fname = scc_cstring_create(); for (int i = 1; i < len - 1; i++) { scc_cstring_append_ch(&fname, includename[i]); } scc_cstring_free(&line); int is_system = includename[0] == '<'; if (switch_file_stack(pp, &fname, &pos, is_system)) { // LOG_ERROR() } scc_cstring_free(&fname); return; ERROR: SCC_ERROR(pos, "invalid include filename, expected \"FILENAME\" or "); scc_cstring_free(&line); }