use b_plain use cz/vars cz_resolve_deps() vec *to_include = resolve_deps_init_uses() for_vec(i, includes, cstr) resolve_include(to_include, *i) vec_free(includes) includes = to_include vec *resolve_deps_init_uses() vec *headerfiles = resolve_deps_init() vec *uses = headerfiles for_vec(i, uses, cstr) *i = fformat("use %s", *i) return uses vec *resolve_deps_init() vec_set_size(b_include_path, b_include_path_base_len) # TODO can I move this into setup() ? vec *files cz_new_parse_vos(files) for_vec(use, cz_use, cstr) resolve_dep(files, *use) vec_squeeze(files) return files resolve_dep(vec *out, cstr header) if header[0] == '/' && is_dir(header) vec_push(b_include_path, header) return if among(header[0], '"', '<', '/') vec_push_cstr(out, header) return # TODO optimize, use static vecs here...? new(c_names, vec, cstr, 4) new(b_names, vec, cstr, 4) new(dir_names, vec, cstr, 4) cstr name = tofree(Strdup(header)) cstr suffix = strrchr(name, '.') if suffix *suffix++ = '\0' if cz_lang != LANG_CXX && among(suffix[0], 'b', 'c') && suffix[1] == suffix[0] error("can't include bb/C++ code `%s' from b/C code", header) if suffix[0] == 'b' cstr b_dot_name = fformat(".%s", header) vec_push(b_names, header) vec_push(b_names, b_dot_name) else vec_push(c_names, header) if cz_lang == LANG_CXX && suffix[0] == 'h' && suffix[1] == 'h' vec_push(c_names, name) # a bit bogus ;) so "use rope.hh" -> #include else vec_push(dir_names, name) if cz_lang == LANG_CXX vec_push(c_names, name) cstr b_dot_name = fformat(".%s.bbh", name) vec_push(b_names, b_dot_name+1) vec_push(b_names, b_dot_name) # remove? just put C++ / C only libs as foo.b # in a separate dir under BRACE_LIB?? cstr b_dot_name = fformat(".%s.bh", name) vec_push(b_names, b_dot_name+1) vec_push(b_names, b_dot_name) # if veclen(b_names) && veclen(c_names) # error("internal error - confused between brace and C headers!") # # this can't be right? new(b, buffer, 256) if veclen(b_names) # it's a brace header, include dirs and ALL from B_INCLUDE_PATH in order new(matches, vec, cstr, 16) for_vec(dir, b_include_path, cstr) for_vec(name, b_names, cstr) buffer_clear(b) Sprintf(b, "%s" path__sep_cstr "%s", *dir, *name) cstr path = buffer_add_nul(b) if is_file(path) vec_push(matches, tofree(Strdup(path))) else char *end = path + strlen(path) char *dot = strrchr(path, '.') if end != path && dot && dot[1] == 'b' && end[-1] == 'h' end[-1] = '\0' if is_file(path) end[-1] = 'h' vec_push(matches, tofree(Strdup(path))) new(dir_matches, vec, cstr, 16) for_vec(dir, b_include_path, cstr) for_vec(name, dir_names, cstr) buffer_clear(b) Sprintf(b, "%s" path__sep_cstr "%s", *dir, *name) cstr path = buffer_add_nul(b) if is_dir(path) vec_push(dir_matches, tofree(Strdup(path))) if veclen(dir_matches) vec_append(b_include_path, dir_matches) # XXX b_include_path changes here, therefore need to reset it for each file XXX vec_free(dir_matches) if veclen(matches) vec_append(out, matches) if veclen(dir_matches) || veclen(matches) buffer_free(b) return if veclen(c_names) # its a C header - include the first found vec *c_include_path_ = LANG_CXX ? cxx_include_path : c_include_path for_vec(dir, c_include_path_, cstr) for_vec(name, c_names, cstr) buffer_clear(b) Sprintf(b, "%s" path__sep_cstr "%s", *dir, *name) cstr path = buffer_add_nul(b) if is_file(path) cstr inc if (*dir)[0] == '.' && (*dir)[1] == '\0' inc = Format("\"%s\"", *name) eif cz_resolve_includes inc = Format("\"%s\"", path) else inc = Format("<%s>", *name) vec_push(out, tofree(inc)) buffer_free(b) return buffer_free(b) # return
for cpp to presumably barf on it. # warn("could not resolve include file %s", header) vec_push(out, fformat("<%s>", header)) return resolve_include(vec *includes, cstr include) cstr command = include cstr file while *command == '\t' ++command file = cstr_begins_with(command, "use ") if !file file = cstr_begins_with(command, "export ") if !file || file[strcspn(file, " \t")] error("bad use statement: %s", include) int start = veclen(includes) resolve_dep(includes, file) new(b, buffer, 256) char tmp = file[-1] file[-1] = '\0' cstr *i = v(includes, start) cstr *e = vecend(includes) for ; i!=e; ++i cstr f = *i bufclr(b) if !among(*f, '<', '"') sh_quote(f, b) f = buffer_nul_terminate(b) *i = fformat("%s %s", command, f) # the perl version included the indent - not needed I think file[-1] = tmp buffer_free(b)