/* Search for a compose file. According to Compose(5) man page the compose file searched in the following locations: - XCOMPOSEFILE variable. - .XCompose at $HOME. - System wide compose file for the current locale. */ static char * get_compose_file_for_locale() { struct matcher_context context = { NULL }; char *xcomposefile; char *to_be_freed; char *home; int err; xcomposefile = getenv ("XCOMPOSEFILE"); if (xcomposefile != NULL) return strdup (xcomposefile); home = getenv ("HOME"); if (home != NULL) { err = asprintf (&xcomposefile, "%s/.XCompose", home); if (err != -1) { if (faccessat(AT_FDCWD, xcomposefile, R_OK, AT_EACCESS) == 0) return xcomposefile; else { free (xcomposefile); /* TODO: check and report whether the compose file doesn't exist or read permission was not granted to us. */ } } } context.value = setlocale (LC_ALL, NULL); map_iterate (X11_PREFIX "/share/X11/locale/locale.alias", match_left_set_right, &context); to_be_freed = context.result; if (context.result != NULL) { /* Current locale is an alias. Use the real name to index the database. */ context.value = context.result; } context.result = NULL; map_iterate (X11_PREFIX "/share/X11/locale/compose.dir", match_right_set_left, &context); free (to_be_freed); /* compose.dir contains relative paths to compose files. */ to_be_freed = context.result; err = asprintf (&context.result, X11_PREFIX "/share/X11/locale/%s", context.result); if (err == -1) context.result = NULL; free (to_be_freed); return context.result; }
/* a function that prints out the contents of the map */ void print_map(map *m) { /* an iterator for iterating through all map entries */ map_iterator i; /* the method `int map_size(map *) returns the current number of entries */ printf("map (size: %d) {", map_size(m)); /* just like lists, map is iterated with _iterate and _next */ for (i=map_iterate(m); map_next(m, &i); ) { /* map_key_at and map_value_at return the key and value, respectively */ printf(" %s:%d,", map_key_at(m, i), map_value_at(m, i)); } printf("\b }\n"); }
int main(int argc, char *argv[]) { const char *key = "404"; const int values[3] = { 0, 1, 2 }; plan_no_plan(); Map *map = map_new(); ok(map && map_empty(map), "Creation"); ok(map_first(map, &key) == NULL && strcmp(key, "404") == 0, "First on empty map"); ok(map_empty(map_prefix(map, "404")), "Empty prefix map"); ok(!map_get(map, "404"), "Get non-existing key"); ok(!map_contains(map, "404"), "Contains non-existing key"); ok(!map_closest(map, "404") && errno == ENOENT, "Closest non-existing key"); ok(!map_put(map, "a", NULL) && errno == EINVAL && map_empty(map) && !map_get(map, "a"), "Put NULL value"); ok(map_put(map, "a", &values[0]) && !map_empty(map) && get(map, "a", &values[0]), "Put 1"); ok(map_first(map, &key) == &values[0] && strcmp(key, "a") == 0, "First on map with 1 value"); key = NULL; ok(map_first(map_prefix(map, "a"), &key) == &values[0] && strcmp(key, "a") == 0, "First on prefix map"); ok(map_contains(map, "a"), "Contains existing key"); ok(map_closest(map, "a") == &values[0], "Closest match existing key"); ok(!map_put(map, "a", &values[1]) && errno == EEXIST && get(map, "a", &values[0]), "Put duplicate"); ok(map_put(map, "cafebabe", &values[2]) && get(map, "cafebabe", &values[2]), "Put 2"); ok(map_put(map, "cafe", &values[1]) && get(map, "cafe", &values[1]), "Put 3"); key = NULL; ok(map_first(map_prefix(map, "cafe"), &key) == &values[1] && strcmp(key, "cafe") == 0, "First on prefix map with multiple suffixes"); Map *copy = map_new(); ok(map_copy(copy, map), "Copy"); ok(!map_empty(copy), "Not empty after copying"); map_iterate(copy, compare, map); map_iterate(map, compare, copy); int counter = 0; map_iterate(copy, once, &counter); ok(counter == 1, "Iterate stop condition"); ok(!map_get(map, "ca") && !map_closest(map, "ca") && errno == 0, "Closest ambigious"); int visited[] = { 0, 0, 0 }; map_iterate(map, visit, &visited); ok(visited[0] == 1 && visited[1] == 1 && visited[2] == 1, "Iterate map"); memset(visited, 0, sizeof visited); order_counter = 0; map_iterate(map, order, &visited); ok(visited[0] == 1 && visited[1] == 2 && visited[2] == 3, "Ordered iteration"); memset(visited, 0, sizeof visited); map_iterate(map_prefix(map, "ca"), visit, &visited); ok(visited[0] == 0 && visited[1] == 1 && visited[2] == 1, "Iterate sub map"); memset(visited, 0, sizeof visited); order_counter = 0; map_iterate(map_prefix(map, "ca"), order, &visited); ok(visited[0] == 0 && visited[1] == 1 && visited[2] == 2, "Ordered sub map iteration"); ok(map_empty(map_prefix(map, "404")), "Empty map for non-existing prefix"); ok(!map_delete(map, "404"), "Delete non-existing key"); ok(map_delete(map, "cafe") == &values[1] && !map_get(map, "cafe"), "Delete existing key"); ok(map_closest(map, "cafe") == &values[2], "Closest unambigious"); ok(map_put(map, "cafe", &values[1]) && get(map, "cafe", &values[1]), "Put 3 again"); map_clear(map); ok(map_empty(map), "Empty after clean"); map_free(map); map_free(copy); return exit_status(); }