/* * Copyright 2008-2009 Katholieke Universiteit Leuven * * Use of this software is governed by the MIT license * * Written by Sven Verdoolaege, K.U.Leuven, Departement * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium */ #include #include #include #undef EL_BASE #define EL_BASE id #include /* A special, static isl_id to use as domains (and ranges) * of sets and parameters domains. * The user should never get a hold on this isl_id. */ isl_id isl_id_none = { .ref = -1, .ctx = NULL, .name = "#none", .user = NULL }; isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id) { return id ? id->ctx : NULL; } void *isl_id_get_user(__isl_keep isl_id *id) { return id ? id->user : NULL; } const char *isl_id_get_name(__isl_keep isl_id *id) { return id ? id->name : NULL; } static __isl_give isl_id *id_alloc(isl_ctx *ctx, const char *name, void *user) { const char *copy = name ? strdup(name) : NULL; isl_id *id; if (name && !copy) return NULL; id = isl_calloc_type(ctx, struct isl_id); if (!id) goto error; id->ctx = ctx; isl_ctx_ref(id->ctx); id->ref = 1; id->name = copy; id->user = user; id->hash = isl_hash_init(); if (name) id->hash = isl_hash_string(id->hash, name); else id->hash = isl_hash_builtin(id->hash, user); return id; error: free((char *)copy); return NULL; } uint32_t isl_id_get_hash(__isl_keep isl_id *id) { return id ? id->hash : 0; } struct isl_name_and_user { const char *name; void *user; }; static isl_bool isl_id_has_name_and_user(const void *entry, const void *val) { isl_id *id = (isl_id *)entry; struct isl_name_and_user *nu = (struct isl_name_and_user *) val; if (id->user != nu->user) return isl_bool_false; if (id->name == nu->name) return isl_bool_true; if (!id->name || !nu->name) return isl_bool_false; return isl_bool_ok(!strcmp(id->name, nu->name)); } __isl_give isl_id *isl_id_alloc(isl_ctx *ctx, const char *name, void *user) { struct isl_hash_table_entry *entry; uint32_t id_hash; struct isl_name_and_user nu = { name, user }; if (!ctx) return NULL; id_hash = isl_hash_init(); if (name) id_hash = isl_hash_string(id_hash, name); else id_hash = isl_hash_builtin(id_hash, user); entry = isl_hash_table_find(ctx, &ctx->id_table, id_hash, isl_id_has_name_and_user, &nu, 1); if (!entry) return NULL; if (entry->data) return isl_id_copy(entry->data); entry->data = id_alloc(ctx, name, user); if (!entry->data) ctx->id_table.n--; return entry->data; } /* If the id has a negative refcount, then it is a static isl_id * which should not be changed. */ __isl_give isl_id *isl_id_copy(isl_id *id) { if (!id) return NULL; if (id->ref < 0) return id; id->ref++; return id; } /* Compare two isl_ids. * * The order is fairly arbitrary. We do keep the comparison of * the user pointers as a last resort since these pointer values * may not be stable across different systems or even different runs. */ int isl_id_cmp(__isl_keep isl_id *id1, __isl_keep isl_id *id2) { if (id1 == id2) return 0; if (!id1) return -1; if (!id2) return 1; if (!id1->name != !id2->name) return !id1->name - !id2->name; if (id1->name) { int cmp = strcmp(id1->name, id2->name); if (cmp != 0) return cmp; } if (id1->user < id2->user) return -1; else return 1; } static isl_bool isl_id_eq(const void *entry, const void *name) { return isl_bool_ok(entry == name); } uint32_t isl_hash_id(uint32_t hash, __isl_keep isl_id *id) { if (id) isl_hash_hash(hash, id->hash); return hash; } /* Replace the free_user callback by "free_user". */ __isl_give isl_id *isl_id_set_free_user(__isl_take isl_id *id, void (*free_user)(void *user)) { if (!id) return NULL; id->free_user = free_user; return id; } /* If the id has a negative refcount, then it is a static isl_id * and should not be freed. */ __isl_null isl_id *isl_id_free(__isl_take isl_id *id) { struct isl_hash_table_entry *entry; if (!id) return NULL; if (id->ref < 0) return NULL; if (--id->ref > 0) return NULL; entry = isl_hash_table_find(id->ctx, &id->ctx->id_table, id->hash, isl_id_eq, id, 0); if (!entry) return NULL; if (entry == isl_hash_table_entry_none) isl_die(id->ctx, isl_error_unknown, "unable to find id", (void)0); else isl_hash_table_remove(id->ctx, &id->ctx->id_table, entry); if (id->free_user) id->free_user(id->user); free((char *)id->name); isl_ctx_deref(id->ctx); free(id); return NULL; } __isl_give isl_printer *isl_printer_print_id(__isl_take isl_printer *p, __isl_keep isl_id *id) { if (!id) goto error; if (id->name) p = isl_printer_print_str(p, id->name); if (id->user) { char buffer[50]; snprintf(buffer, sizeof(buffer), "@%p", id->user); p = isl_printer_print_str(p, buffer); } return p; error: isl_printer_free(p); return NULL; } /* Read an isl_id from "s" based on its name. */ __isl_give isl_id *isl_stream_read_id(__isl_keep isl_stream *s) { struct isl_token *tok; char *str; isl_ctx *ctx; isl_id *id; if (!s) return NULL; tok = isl_stream_next_token(s); if (!tok) { isl_stream_error(s, NULL, "unexpected EOF"); return NULL; } ctx = isl_stream_get_ctx(s); str = isl_token_get_str(ctx, tok); isl_token_free(tok); if (!str) return NULL; id = isl_id_alloc(ctx, str, NULL); free(str); return id; } /* Read an isl_id object from the string "str". */ __isl_give isl_id *isl_id_read_from_str(isl_ctx *ctx, const char *str) { isl_id *id; isl_stream *s = isl_stream_new_str(ctx, str); if (!s) return NULL; id = isl_stream_read_id(s); isl_stream_free(s); return id; } /* Is "id1" (obviously) equal to "id2"? * * isl_id objects can be compared by pointer value, but * isl_multi_*_plain_is_equal needs an isl_*_plain_is_equal. */ static isl_bool isl_id_plain_is_equal(__isl_keep isl_id *id1, __isl_keep isl_id *id2) { if (!id1 || !id2) return isl_bool_error; return id1 == id2; } #undef BASE #define BASE id #include #include #include