diff options
Diffstat (limited to 'pttc/src/util.c')
| -rw-r--r-- | pttc/src/util.c | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/pttc/src/util.c b/pttc/src/util.c new file mode 100644 index 0000000000000..9528dafa52fbf --- /dev/null +++ b/pttc/src/util.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2013-2019, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "errcode.h" +#include "util.h" +#include "parse.h" + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int duplicate_name(char **d, const char *s, size_t n) +{ + char *dup; + size_t len; + + if (!d || !s) + return -err_internal; + + len = strnlen(s, n); + if (n <= len) + return -err_name_too_long; + + dup = malloc(len + 1); + if (!dup) + return -err_no_mem; + + *d = memcpy(dup, s, len); + dup[len] = 0; + + return 0; +} + +int str_to_uint64(const char *str, uint64_t *val, int base) +{ + char *endptr; + uint64_t x; + + if (!str || !val) + return -err_internal; + + errno = 0; + x = strtoull(str, &endptr, base); + + if (errno == EINVAL) + return -err_parse_int; + + if (errno == ERANGE) + return -err_parse_int_too_big; + + if (str == endptr || *endptr != '\0') + return -err_parse_int; + + *val = x; + + return 0; +} + +int str_to_uint32(const char *str, uint32_t *val, int base) +{ + uint64_t x; + int errcode; + + if (!str || !val) + return -err_internal; + + errcode = str_to_uint64(str, &x, base); + if (errcode < 0) + return errcode; + + if (UINT32_MAX < x) + return -err_parse_int_too_big; + + *val = (uint32_t) x; + return 0; +} + +int str_to_uint16(const char *str, uint16_t *val, int base) +{ + uint64_t x; + int errcode; + + if (!str || !val) + return -err_internal; + + errcode = str_to_uint64(str, &x, base); + if (errcode < 0) + return errcode; + + if (UINT16_MAX < x) + return -err_parse_int_too_big; + + *val = (uint16_t) x; + return 0; +} + +int str_to_uint8(const char *str, uint8_t *val, int base) +{ + uint64_t x; + int errcode; + + if (!str || !val) + return -err_internal; + + errcode = str_to_uint64(str, &x, base); + if (errcode < 0) + return errcode; + + if (UINT8_MAX < x) + return -err_parse_int_too_big; + + *val = (uint8_t) x; + return 0; +} + +int do_bug_on(int cond, const char *condstr, const char *file, int line) +{ + if (cond) + fprintf(stderr, "%s:%d: internal error: %s\n", file, line, + condstr); + return cond; +} +struct label *l_alloc(void) +{ + return calloc(1, sizeof(struct label)); +} + +void l_free(struct label *l) +{ + if (!l) + return; + + l_free(l->next); + free(l->name); + free(l); +} + +int l_append(struct label *l, const char *name, uint64_t addr) +{ + int errcode; + size_t nlen; + + if (bug_on(!l)) + return -err_internal; + + if (bug_on(!name)) + return -err_internal; + + nlen = strnlen(name, (size_t) l_max); + if ((size_t) l_max <= nlen) + return -err_label_name; + + /* skip to the last label. */ + while (l->next) { + l = l->next; + + /* ignore the first label, which has no name. */ + if (strcmp(l->name, name) == 0) + return -err_label_not_unique; + } + + /* append a new label. */ + l->next = l_alloc(); + if (!l->next) + return -err_no_mem; + + /* save the name. */ + errcode = duplicate_name(&l->next->name, name, nlen+1); + if (errcode < 0) + goto error; + + /* save the address. */ + l->next->addr = addr; + + return 0; +error: + free(l->next->name); + free(l->next); + l->next = NULL; + return errcode; +} + +int l_lookup(const struct label *l, uint64_t *addr, + const char *name) +{ + if (bug_on(!l)) + return -err_internal; + + if (bug_on(!addr)) + return -err_internal; + + if (bug_on(!name)) + return -err_internal; + + + *addr = 0; + while (l->next) { + l = l->next; + if (strcmp(l->name, name) == 0) { + *addr = l->addr; + return 0; + } + } + return -err_no_label; +} + +struct label *l_find(struct label *l, const char *name) +{ + if (bug_on(!l)) + return NULL; + + if (bug_on(!name)) + return NULL; + + + while (l->next) { + l = l->next; + + if (bug_on(!l->name)) + continue; + + if (strcmp(l->name, name) == 0) + return l; + } + return NULL; +} |
