a2cdc6c2a0
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
318 lines
7.9 KiB
C
318 lines
7.9 KiB
C
#ifndef _DUTIL_H_
|
|
#define _DUTIL_H_ 1
|
|
/*
|
|
* Copyright (C) 2007..2009 Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* Some functions came from the Linux Kernel sources, copyrighted by a
|
|
* cast of dozens, please see the Linux Kernel git history for details.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <elf.h>
|
|
#include <gelf.h>
|
|
#include <asm/bitsperlong.h>
|
|
#include "rbtree.h"
|
|
|
|
#define BITS_PER_LONG __BITS_PER_LONG
|
|
|
|
#ifndef __unused
|
|
#define __unused __attribute__ ((unused))
|
|
#endif
|
|
|
|
#ifndef __pure
|
|
#define __pure __attribute__ ((pure))
|
|
#endif
|
|
|
|
#define roundup(x,y) ((((x) + ((y) - 1)) / (y)) * (y))
|
|
|
|
static inline __attribute__((const)) bool is_power_of_2(unsigned long n)
|
|
{
|
|
return (n != 0 && ((n & (n - 1)) == 0));
|
|
}
|
|
|
|
/**
|
|
* fls - find last (most-significant) bit set
|
|
* @x: the word to search
|
|
*
|
|
* This is defined the same way as ffs.
|
|
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
|
|
*/
|
|
static __always_inline int fls(int x)
|
|
{
|
|
return x ? sizeof(x) * 8 - __builtin_clz(x) : 0;
|
|
}
|
|
|
|
/**
|
|
* fls64 - find last set bit in a 64-bit word
|
|
* @x: the word to search
|
|
*
|
|
* This is defined in a similar way as the libc and compiler builtin
|
|
* ffsll, but returns the position of the most significant set bit.
|
|
*
|
|
* fls64(value) returns 0 if value is 0 or the position of the last
|
|
* set bit if value is nonzero. The last (most significant) bit is
|
|
* at position 64.
|
|
*/
|
|
#if BITS_PER_LONG == 32
|
|
static __always_inline int fls64(uint64_t x)
|
|
{
|
|
uint32_t h = x >> 32;
|
|
if (h)
|
|
return fls(h) + 32;
|
|
return fls(x);
|
|
}
|
|
#elif BITS_PER_LONG == 64
|
|
/**
|
|
* __fls - find last (most-significant) set bit in a long word
|
|
* @word: the word to search
|
|
*
|
|
* Undefined if no set bit exists, so code should check against 0 first.
|
|
*/
|
|
static __always_inline unsigned long __fls(unsigned long word)
|
|
{
|
|
int num = BITS_PER_LONG - 1;
|
|
|
|
#if BITS_PER_LONG == 64
|
|
if (!(word & (~0ul << 32))) {
|
|
num -= 32;
|
|
word <<= 32;
|
|
}
|
|
#endif
|
|
if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
|
|
num -= 16;
|
|
word <<= 16;
|
|
}
|
|
if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
|
|
num -= 8;
|
|
word <<= 8;
|
|
}
|
|
if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
|
|
num -= 4;
|
|
word <<= 4;
|
|
}
|
|
if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
|
|
num -= 2;
|
|
word <<= 2;
|
|
}
|
|
if (!(word & (~0ul << (BITS_PER_LONG-1))))
|
|
num -= 1;
|
|
return num;
|
|
}
|
|
|
|
static __always_inline int fls64(uint64_t x)
|
|
{
|
|
if (x == 0)
|
|
return 0;
|
|
return __fls(x) + 1;
|
|
}
|
|
#else
|
|
#error BITS_PER_LONG not 32 or 64
|
|
#endif
|
|
|
|
static inline unsigned fls_long(unsigned long l)
|
|
{
|
|
if (sizeof(l) == 4)
|
|
return fls(l);
|
|
return fls64(l);
|
|
}
|
|
|
|
/*
|
|
* round up to nearest power of two
|
|
*/
|
|
static inline __attribute__((const))
|
|
unsigned long __roundup_pow_of_two(unsigned long n)
|
|
{
|
|
return 1UL << fls_long(n - 1);
|
|
}
|
|
|
|
/*
|
|
* non-constant log of base 2 calculators
|
|
* - the arch may override these in asm/bitops.h if they can be implemented
|
|
* more efficiently than using fls() and fls64()
|
|
* - the arch is not required to handle n==0 if implementing the fallback
|
|
*/
|
|
static inline __attribute__((const))
|
|
int __ilog2_u32(uint32_t n)
|
|
{
|
|
return fls(n) - 1;
|
|
}
|
|
|
|
static inline __attribute__((const))
|
|
int __ilog2_u64(uint64_t n)
|
|
{
|
|
return fls64(n) - 1;
|
|
}
|
|
|
|
/*
|
|
* deal with unrepresentable constant logarithms
|
|
*/
|
|
extern __attribute__((const, noreturn))
|
|
int ____ilog2_NaN(void);
|
|
|
|
/**
|
|
* ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
|
|
* @n - parameter
|
|
*
|
|
* constant-capable log of base 2 calculation
|
|
* - this can be used to initialise global variables from constant data, hence
|
|
* the massive ternary operator construction
|
|
*
|
|
* selects the appropriately-sized optimised version depending on sizeof(n)
|
|
*/
|
|
#define ilog2(n) \
|
|
( \
|
|
__builtin_constant_p(n) ? ( \
|
|
(n) < 1 ? ____ilog2_NaN() : \
|
|
(n) & (1ULL << 63) ? 63 : \
|
|
(n) & (1ULL << 62) ? 62 : \
|
|
(n) & (1ULL << 61) ? 61 : \
|
|
(n) & (1ULL << 60) ? 60 : \
|
|
(n) & (1ULL << 59) ? 59 : \
|
|
(n) & (1ULL << 58) ? 58 : \
|
|
(n) & (1ULL << 57) ? 57 : \
|
|
(n) & (1ULL << 56) ? 56 : \
|
|
(n) & (1ULL << 55) ? 55 : \
|
|
(n) & (1ULL << 54) ? 54 : \
|
|
(n) & (1ULL << 53) ? 53 : \
|
|
(n) & (1ULL << 52) ? 52 : \
|
|
(n) & (1ULL << 51) ? 51 : \
|
|
(n) & (1ULL << 50) ? 50 : \
|
|
(n) & (1ULL << 49) ? 49 : \
|
|
(n) & (1ULL << 48) ? 48 : \
|
|
(n) & (1ULL << 47) ? 47 : \
|
|
(n) & (1ULL << 46) ? 46 : \
|
|
(n) & (1ULL << 45) ? 45 : \
|
|
(n) & (1ULL << 44) ? 44 : \
|
|
(n) & (1ULL << 43) ? 43 : \
|
|
(n) & (1ULL << 42) ? 42 : \
|
|
(n) & (1ULL << 41) ? 41 : \
|
|
(n) & (1ULL << 40) ? 40 : \
|
|
(n) & (1ULL << 39) ? 39 : \
|
|
(n) & (1ULL << 38) ? 38 : \
|
|
(n) & (1ULL << 37) ? 37 : \
|
|
(n) & (1ULL << 36) ? 36 : \
|
|
(n) & (1ULL << 35) ? 35 : \
|
|
(n) & (1ULL << 34) ? 34 : \
|
|
(n) & (1ULL << 33) ? 33 : \
|
|
(n) & (1ULL << 32) ? 32 : \
|
|
(n) & (1ULL << 31) ? 31 : \
|
|
(n) & (1ULL << 30) ? 30 : \
|
|
(n) & (1ULL << 29) ? 29 : \
|
|
(n) & (1ULL << 28) ? 28 : \
|
|
(n) & (1ULL << 27) ? 27 : \
|
|
(n) & (1ULL << 26) ? 26 : \
|
|
(n) & (1ULL << 25) ? 25 : \
|
|
(n) & (1ULL << 24) ? 24 : \
|
|
(n) & (1ULL << 23) ? 23 : \
|
|
(n) & (1ULL << 22) ? 22 : \
|
|
(n) & (1ULL << 21) ? 21 : \
|
|
(n) & (1ULL << 20) ? 20 : \
|
|
(n) & (1ULL << 19) ? 19 : \
|
|
(n) & (1ULL << 18) ? 18 : \
|
|
(n) & (1ULL << 17) ? 17 : \
|
|
(n) & (1ULL << 16) ? 16 : \
|
|
(n) & (1ULL << 15) ? 15 : \
|
|
(n) & (1ULL << 14) ? 14 : \
|
|
(n) & (1ULL << 13) ? 13 : \
|
|
(n) & (1ULL << 12) ? 12 : \
|
|
(n) & (1ULL << 11) ? 11 : \
|
|
(n) & (1ULL << 10) ? 10 : \
|
|
(n) & (1ULL << 9) ? 9 : \
|
|
(n) & (1ULL << 8) ? 8 : \
|
|
(n) & (1ULL << 7) ? 7 : \
|
|
(n) & (1ULL << 6) ? 6 : \
|
|
(n) & (1ULL << 5) ? 5 : \
|
|
(n) & (1ULL << 4) ? 4 : \
|
|
(n) & (1ULL << 3) ? 3 : \
|
|
(n) & (1ULL << 2) ? 2 : \
|
|
(n) & (1ULL << 1) ? 1 : \
|
|
(n) & (1ULL << 0) ? 0 : \
|
|
____ilog2_NaN() \
|
|
) : \
|
|
(sizeof(n) <= 4) ? \
|
|
__ilog2_u32(n) : \
|
|
__ilog2_u64(n) \
|
|
)
|
|
|
|
/**
|
|
* roundup_pow_of_two - round the given value up to nearest power of two
|
|
* @n - parameter
|
|
*
|
|
* round the given value up to the nearest power of two
|
|
* - the result is undefined when n == 0
|
|
* - this can be used to initialise global variables from constant data
|
|
*/
|
|
#define roundup_pow_of_two(n) \
|
|
( \
|
|
__builtin_constant_p(n) ? ( \
|
|
(n == 1) ? 1 : \
|
|
(1UL << (ilog2((n) - 1) + 1)) \
|
|
) : \
|
|
__roundup_pow_of_two(n) \
|
|
)
|
|
|
|
/* We need define two variables, argp_program_version_hook and
|
|
argp_program_bug_address, in all programs. argp.h declares these
|
|
variables as non-const (which is correct in general). But we can
|
|
do better, it is not going to change. So we want to move them into
|
|
the .rodata section. Define macros to do the trick. */
|
|
#define ARGP_PROGRAM_VERSION_HOOK_DEF \
|
|
void (*const apvh) (FILE *, struct argp_state *) \
|
|
__asm ("argp_program_version_hook")
|
|
#define ARGP_PROGRAM_BUG_ADDRESS_DEF \
|
|
const char *const apba__ __asm ("argp_program_bug_address")
|
|
|
|
struct str_node {
|
|
struct rb_node rb_node;
|
|
const char *s;
|
|
};
|
|
|
|
struct strlist {
|
|
struct rb_root entries;
|
|
bool dupstr;
|
|
};
|
|
|
|
struct strlist *strlist__new(bool dupstr);
|
|
void strlist__delete(struct strlist *slist);
|
|
|
|
void strlist__remove(struct strlist *slist, struct str_node *sn);
|
|
int strlist__load(struct strlist *slist, const char *filename);
|
|
int strlist__add(struct strlist *slist, const char *str);
|
|
|
|
bool strlist__has_entry(struct strlist *slist, const char *entry);
|
|
|
|
static inline bool strlist__empty(const struct strlist *slist)
|
|
{
|
|
return rb_first(&slist->entries) == NULL;
|
|
}
|
|
|
|
/**
|
|
* strstarts - does @str start with @prefix?
|
|
* @str: string to examine
|
|
* @prefix: prefix to look for.
|
|
*/
|
|
static inline bool strstarts(const char *str, const char *prefix)
|
|
{
|
|
return strncmp(str, prefix, strlen(prefix)) == 0;
|
|
}
|
|
|
|
void *zalloc(const size_t size);
|
|
|
|
Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
|
|
GElf_Shdr *shp, const char *name, size_t *index);
|
|
|
|
#ifndef SHT_GNU_ATTRIBUTES
|
|
/* Just a way to check if we're using an old elfutils version */
|
|
static inline int elf_getshdrstrndx(Elf *elf, size_t *dst)
|
|
{
|
|
return elf_getshstrndx(elf, dst);
|
|
}
|
|
#endif
|
|
|
|
#endif /* _DUTIL_H_ */
|