blob: 89e14c09bfadbd314a2dc79446007a08c126cb9e [file] [log] [blame]
/*
* 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 <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *duplicate_str(const char *s)
{
char *dup;
if (!s)
return NULL;
dup = malloc(strlen(s)+1);
if (!dup)
return NULL;
return strcpy(dup, s);
}
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;
if (bug_on(!l))
return -err_internal;
if (bug_on(!name))
return -err_internal;
/* 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. */
l->next->name = duplicate_str(name);
if (!l->next->name) {
errcode = -err_no_mem;
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;
}