1 // Logic for converting user's Tomo names into valid C identifiers
6 #include "environment.h"
7 #include "stdlib/paths.h"
8 #include "stdlib/text.h"
10 static const char *c_keywords[] = {
11 // Maintain sorted order:
73 static CONSTFUNC bool is_keyword(const char *word, size_t len) {
74 int64_t lo = 0, hi = sizeof(c_keywords) / sizeof(c_keywords[0]) - 1;
76 int64_t mid = (lo + hi) / 2;
77 int32_t cmp = strncmp(word, c_keywords[mid], len + 1);
78 if (cmp == 0) return true;
79 else if (cmp > 0) lo = mid + 1;
80 else if (cmp < 0) hi = mid - 1;
86 Text_t valid_c_name(const char *name) {
87 size_t len = strlen(name);
88 size_t trailing_underscores = 0;
89 while (trailing_underscores < len && name[len - 1 - trailing_underscores] == '_')
90 trailing_underscores += 1;
91 if (is_keyword(name, len - trailing_underscores)) {
92 return Texts(Text$from_str(name), Text("_"));
94 return Text$from_str(name);
98 Text_t CONSTFUNC namespace_name(env_t *env, namespace_t *ns, Text_t name) {
99 for (; ns; ns = ns->parent) {
100 name = Texts(ns->name, "$", name);
102 if (env->id_suffix.length > 0) name = Texts(name, env->id_suffix);
107 Text_t get_id_suffix(const char *filename) {
109 Path_t path = Path$from_str(filename);
110 Path_t build_dir = Path$sibling(path, Text(".build"));
111 if (mkdir(Path$as_c_string(build_dir), 0755) != 0) {
112 if (!Path$is_directory(build_dir, true)) err(1, "Could not make .build directory");
114 Path_t id_file = Path$child(build_dir, Texts(Path$base_name(path), Text$from_str(".id")));
115 OptionalText_t id = Path$read(id_file);
116 if (id.tag == TEXT_NONE) err(1, "Could not read ID file: %s", Path$as_c_string(id_file));
117 id = Text$trim(id, Text(" \r\n"), true, true);
118 return Texts("$", id);