mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-10 05:08:42 +00:00
Merge commit '3a6eda995ecfcebff3130d86ee3baeab12a41335' into haugesund
This commit is contained in:
commit
921344c3ba
48
lib/printf.c
48
lib/printf.c
@ -568,3 +568,51 @@ buffer_puts(buffer *buf, const char *str)
|
|||||||
|
|
||||||
buf->pos = (bp < be) ? bp : buf->end;
|
buf->pos = (bp < be) ? bp : buf->end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define POOL_PRINTF_MAXBUF 1024
|
||||||
|
|
||||||
|
char *mb_vsprintf(pool *p, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
char buf[POOL_PRINTF_MAXBUF];
|
||||||
|
int count = bvsnprintf(buf, POOL_PRINTF_MAXBUF, fmt, args);
|
||||||
|
|
||||||
|
if (count < 0)
|
||||||
|
bug("Attempted to mb_vsprintf() a too long string");
|
||||||
|
|
||||||
|
char *out = mb_alloc(p, count + 1);
|
||||||
|
memcpy(out, buf, count + 1);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *mb_sprintf(pool *p, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
char *out;
|
||||||
|
va_start(args, fmt);
|
||||||
|
out = mb_vsprintf(p, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *lp_vsprintf(linpool *p, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
char buf[POOL_PRINTF_MAXBUF];
|
||||||
|
int count = bvsnprintf(buf, POOL_PRINTF_MAXBUF, fmt, args);
|
||||||
|
|
||||||
|
if (count < 0)
|
||||||
|
bug("Attempted to mb_vsprintf() a too long string");
|
||||||
|
|
||||||
|
char *out = lp_alloc(p, count + 1);
|
||||||
|
memcpy(out, buf, count + 1);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *lp_sprintf(linpool *p, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
char *out;
|
||||||
|
va_start(args, fmt);
|
||||||
|
out = lp_vsprintf(p, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
@ -70,6 +70,20 @@ rp_new(pool *p, const char *name)
|
|||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pool *
|
||||||
|
rp_newf(pool *p, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
pool *z = rp_new(p, NULL);
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
z->name = mb_vsprintf(p, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pool_free(resource *P)
|
pool_free(resource *P)
|
||||||
{
|
{
|
||||||
@ -410,21 +424,6 @@ mb_realloc(void *m, unsigned size)
|
|||||||
return b->data;
|
return b->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* mb_move - move a memory block
|
|
||||||
* @m: memory block
|
|
||||||
* @p: target pool
|
|
||||||
*
|
|
||||||
* mb_move() moves the given memory block to another pool in the same way
|
|
||||||
* as rmove() moves a plain resource.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mb_move(void *m, pool *p)
|
|
||||||
{
|
|
||||||
struct mblock *b = SKIP_BACK(struct mblock, data, m);
|
|
||||||
rmove(b, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mb_free - free a memory block
|
* mb_free - free a memory block
|
||||||
|
@ -44,6 +44,7 @@ typedef struct pool pool;
|
|||||||
|
|
||||||
void resource_init(void);
|
void resource_init(void);
|
||||||
pool *rp_new(pool *, const char *); /* Create new pool */
|
pool *rp_new(pool *, const char *); /* Create new pool */
|
||||||
|
pool *rp_newf(pool *, const char *, ...); /* Create a new pool with a formatted string as its name */
|
||||||
void rfree(void *); /* Free single resource */
|
void rfree(void *); /* Free single resource */
|
||||||
void rdump(void *); /* Dump to debug output */
|
void rdump(void *); /* Dump to debug output */
|
||||||
struct resmem rmemsize(void *res); /* Return size of memory used by the resource */
|
struct resmem rmemsize(void *res); /* Return size of memory used by the resource */
|
||||||
@ -59,7 +60,6 @@ extern pool root_pool;
|
|||||||
void *mb_alloc(pool *, unsigned size);
|
void *mb_alloc(pool *, unsigned size);
|
||||||
void *mb_allocz(pool *, unsigned size);
|
void *mb_allocz(pool *, unsigned size);
|
||||||
void *mb_realloc(void *m, unsigned size);
|
void *mb_realloc(void *m, unsigned size);
|
||||||
void mb_move(void *, pool *);
|
|
||||||
void mb_free(void *);
|
void mb_free(void *);
|
||||||
|
|
||||||
/* Memory pools with linear allocation */
|
/* Memory pools with linear allocation */
|
||||||
|
@ -20,6 +20,11 @@ int bvsprintf(char *str, const char *fmt, va_list args);
|
|||||||
int bsnprintf(char *str, int size, const char *fmt, ...);
|
int bsnprintf(char *str, int size, const char *fmt, ...);
|
||||||
int bvsnprintf(char *str, int size, const char *fmt, va_list args);
|
int bvsnprintf(char *str, int size, const char *fmt, va_list args);
|
||||||
|
|
||||||
|
char *mb_sprintf(pool *p, const char *fmt, ...);
|
||||||
|
char *mb_vsprintf(pool *p, const char *fmt, va_list args);
|
||||||
|
char *lp_sprintf(linpool *p, const char *fmt, ...);
|
||||||
|
char *lp_vsprintf(linpool *p, const char *fmt, va_list args);
|
||||||
|
|
||||||
int buffer_vprint(buffer *buf, const char *fmt, va_list args);
|
int buffer_vprint(buffer *buf, const char *fmt, va_list args);
|
||||||
int buffer_print(buffer *buf, const char *fmt, ...);
|
int buffer_print(buffer *buf, const char *fmt, ...);
|
||||||
void buffer_puts(buffer *buf, const char *str);
|
void buffer_puts(buffer *buf, const char *str);
|
||||||
|
172
lib/tlists.h
Normal file
172
lib/tlists.h
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* BIRD Library -- Typed Linked Lists
|
||||||
|
*
|
||||||
|
* (c) 2022 Maria Matejka <mq@jmq.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This implementation of linked lists forces its members to be
|
||||||
|
* typed. On the other hand, it needs to be implemented as ugly macros to
|
||||||
|
* keep the needed genericity.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* 1. Include this file
|
||||||
|
* 2. Define the node structure
|
||||||
|
* 3. For every list type you need to define:
|
||||||
|
* A. #define TLIST_PREFIX and other macros
|
||||||
|
* B. Include this file once again
|
||||||
|
*
|
||||||
|
* Macros to define:
|
||||||
|
* TLIST_PREFIX: prefix to prepend to everything generated
|
||||||
|
* TLIST_TYPE: the actual node type
|
||||||
|
* TLIST_ITEM: where the tlist structure is
|
||||||
|
* TLIST_WANT_WALK: if defined, generates a helper functions for list walking macros
|
||||||
|
* TLIST_WANT_ADD_HEAD: if defined, TLIST_PREFIX_add_head() is generated to
|
||||||
|
* add an item to the beginning of the list
|
||||||
|
* TLIST_WANT_ADD_TAIL: if defined, TLIST_PREFIX_add_tail() is generated to
|
||||||
|
* add an item to the end of the list
|
||||||
|
*
|
||||||
|
* TLIST_PREFIX_rem_node() is generated always.
|
||||||
|
*
|
||||||
|
* All these macros are #undef-ed by including this file.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* #include "lib/tlists.h"
|
||||||
|
*
|
||||||
|
* struct foo {
|
||||||
|
* ...
|
||||||
|
* TLIST_NODE(bar, struct foo) baz;
|
||||||
|
* ...
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* #define TLIST_PREFIX bar
|
||||||
|
* #define TLIST_TYPE struct foo
|
||||||
|
* #define TLIST_ITEM baz
|
||||||
|
*
|
||||||
|
* #define TLIST_WANT_WALK
|
||||||
|
* #define TLIST_WANT_ADD_HEAD
|
||||||
|
*
|
||||||
|
* #include "lib/tlists.h"
|
||||||
|
*
|
||||||
|
* ...
|
||||||
|
* (end of example)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _BIRD_LIB_TLISTS_H_
|
||||||
|
# ifdef TLIST_PREFIX
|
||||||
|
|
||||||
|
/* Check for mandatory arguments */
|
||||||
|
#ifndef TLIST_TYPE
|
||||||
|
#error "TLIST_TYPE must be defined"
|
||||||
|
#endif
|
||||||
|
#ifndef TLIST_ITEM
|
||||||
|
#error "TLIST_ITEM must be defined"
|
||||||
|
#endif
|
||||||
|
#ifndef TLIST_PREFIX
|
||||||
|
#error "TLIST_PREFIX must be defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TLIST_NAME(x) MACRO_CONCAT_AFTER(TLIST_PREFIX,_##x)
|
||||||
|
#ifndef TLIST_LIST_STRUCT
|
||||||
|
#define TLIST_LIST_STRUCT TLIST_NAME(list)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct TLIST_LIST_STRUCT {
|
||||||
|
TLIST_TYPE *first;
|
||||||
|
TLIST_TYPE *last;
|
||||||
|
} TLIST_LIST_STRUCT;
|
||||||
|
|
||||||
|
#ifdef TLIST_WANT_WALK
|
||||||
|
static inline struct TLIST_NAME(node) * TLIST_NAME(node_get)(TLIST_TYPE *node)
|
||||||
|
{ return &(node->TLIST_ITEM); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TLIST_WANT_ADD_HEAD
|
||||||
|
static inline void TLIST_NAME(add_head)(TLIST_LIST_STRUCT *list, TLIST_TYPE *node)
|
||||||
|
{
|
||||||
|
ASSERT_DIE(!node->TLIST_ITEM.prev && !node->TLIST_ITEM.next);
|
||||||
|
if (node->TLIST_ITEM.next = list->first)
|
||||||
|
list->first->TLIST_ITEM.prev = node;
|
||||||
|
else
|
||||||
|
list->last = node;
|
||||||
|
list->first = node;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TLIST_WANT_ADD_TAIL
|
||||||
|
static inline void TLIST_NAME(add_tail)(TLIST_LIST_STRUCT *list, TLIST_TYPE *node)
|
||||||
|
{
|
||||||
|
ASSERT_DIE(!node->TLIST_ITEM.prev && !node->TLIST_ITEM.next);
|
||||||
|
if (node->TLIST_ITEM.prev = list->last)
|
||||||
|
list->last->TLIST_ITEM.next = node;
|
||||||
|
else
|
||||||
|
list->first = node;
|
||||||
|
list->last = node;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void TLIST_NAME(rem_node)(TLIST_LIST_STRUCT *list, TLIST_TYPE *node)
|
||||||
|
{
|
||||||
|
if (node->TLIST_ITEM.prev)
|
||||||
|
node->TLIST_ITEM.prev->TLIST_ITEM.next = node->TLIST_ITEM.next;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT_DIE(list->first == node);
|
||||||
|
list->first = node->TLIST_ITEM.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->TLIST_ITEM.next)
|
||||||
|
node->TLIST_ITEM.next->TLIST_ITEM.prev = node->TLIST_ITEM.prev;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT_DIE(list->last == node);
|
||||||
|
list->last = node->TLIST_ITEM.prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->TLIST_ITEM.next = node->TLIST_ITEM.prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef TLIST_PREFIX
|
||||||
|
#undef TLIST_NAME
|
||||||
|
#undef TLIST_LIST_STRUCT
|
||||||
|
#undef TLIST_TYPE
|
||||||
|
#undef TLIST_ITEM
|
||||||
|
#undef TLIST_WANT_ADD_HEAD
|
||||||
|
#undef TLIST_WANT_ADD_TAIL
|
||||||
|
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
#define _BIRD_LIB_TLISTS_H_
|
||||||
|
|
||||||
|
#include "lib/macro.h"
|
||||||
|
|
||||||
|
#if defined(TLIST_NAME) || defined(TLIST_PREFIX)
|
||||||
|
#error "You should first include lib/tlists.h without requesting a TLIST"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TLIST_NODE(_name, _type) struct _name##_node { _type *next; _type *prev; }
|
||||||
|
#define TLIST_LIST(_name) struct _name##_list
|
||||||
|
|
||||||
|
/* Use ->first and ->last to access HEAD and TAIL */
|
||||||
|
#define THEAD(_name, _list) (_list)->first
|
||||||
|
#define TTAIL(_name, _list) (_list)->last
|
||||||
|
|
||||||
|
/* Walkaround macros: simple and resilient to node removal */
|
||||||
|
#define WALK_TLIST(_name, _node, _list) \
|
||||||
|
for (typeof((_list)->first) _node = (_list)->first; \
|
||||||
|
_node; _node = _name##_node_get((_node))->next)
|
||||||
|
|
||||||
|
#define WALK_TLIST_DELSAFE(_name, _node, _list) \
|
||||||
|
for (typeof((_list)->first) _node = (_list)->first, \
|
||||||
|
_helper = _node ? _name##_node_get((_list)->first)->next : NULL; \
|
||||||
|
_node; \
|
||||||
|
(_node = _helper) ? (_helper = _name##_node_get(_helper)->next) : 0)
|
||||||
|
|
||||||
|
/* Empty check */
|
||||||
|
#define EMPTY_TLIST(_name, _list) (!(_list)->first)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -2212,12 +2212,7 @@ static struct resclass rt_class = {
|
|||||||
rtable *
|
rtable *
|
||||||
rt_setup(pool *pp, struct rtable_config *cf)
|
rt_setup(pool *pp, struct rtable_config *cf)
|
||||||
{
|
{
|
||||||
int ns = strlen("Routing table ") + strlen(cf->name) + 1;
|
pool *p = rp_newf(pp, "Routing table %s", cf->name);
|
||||||
void *nb = mb_alloc(pp, ns);
|
|
||||||
ASSERT_DIE(ns - 1 == bsnprintf(nb, ns, "Routing table %s", cf->name));
|
|
||||||
|
|
||||||
pool *p = rp_new(pp, nb);
|
|
||||||
mb_move(nb, p);
|
|
||||||
|
|
||||||
rtable *t = ralloc(p, &rt_class);
|
rtable *t = ralloc(p, &rt_class);
|
||||||
t->rp = p;
|
t->rp = p;
|
||||||
|
Loading…
Reference in New Issue
Block a user