Newer
Older
}
}
/*!
\brief Strip leading/trailing whitespace from a string.
\param s The string to be stripped (will be modified).
\return The stripped string.
This functions strips all leading and trailing whitespace
characters from the input string, and returns a pointer to
the resulting string. The string is modified in place.
*/
AST_INLINE_API(
char *ast_strip(char *s),
{
s = ast_skip_blanks(s);
if (s)
ast_trim_blanks(s);
return s;
struct ast_variable {
char *name;
char *value;
char *file;
int lineno;
int object; /*!< 0 for variable, 1 for object */
int blanklines; /*!< Number of blanklines following entry */
struct ast_comment *precomments;
struct ast_comment *sameline;
struct ast_variable *next;
char stuff[0];
};
static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable);
static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, int withcomments, const char *suggested_include_file);
struct ast_config *localized_config_load_with_comments(const char *filename);
static char *ast_category_browse(struct ast_config *config, const char *prev);
static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category);
static void ast_variables_destroy(struct ast_variable *v);
static void ast_config_destroy(struct ast_config *cfg);
static struct ast_config_include *ast_include_new(struct ast_config *conf, const char *from_file, const char *included_file, int is_exec, const char *exec_file, int from_lineno, char *real_included_file_name, int real_included_file_name_size);
static struct ast_config_include *ast_include_find(struct ast_config *conf, const char *included_file);
void localized_ast_include_rename(struct ast_config *conf, const char *from_file, const char *to_file);
static struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename);
static struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename)
{
int name_len = strlen(name) + 1;
size_t value_len = strlen(value) + 1;
size_t filename_len = strlen(filename) + 1;
if ((variable = ast_calloc(1, name_len + value_len + filename_len + sizeof(*variable)))) {
variable->value = variable->stuff + name_len;
variable->file = variable->value + value_len;
ast_copy_string(variable->value, value, value_len);
ast_copy_string(variable->file, filename, filename_len);
}
static struct ast_config_include *ast_include_new(struct ast_config *conf, const char *from_file, const char *included_file, int is_exec, const char *exec_file, int from_lineno, char *real_included_file_name, int real_included_file_name_size)
{
/* a file should be included ONCE. Otherwise, if one of the instances is changed,
then all be changed. -- how do we know to include it? -- Handling modified
instances is possible, I'd have
to create a new master for each instance. */
struct ast_config_include *inc;
inc = ast_include_find(conf, included_file);
if (inc)
{
inc->inclusion_count++;
snprintf(real_included_file_name, real_included_file_name_size, "%s~~%d", included_file, inc->inclusion_count);
ast_log(LOG_WARNING,"'%s', line %d: Same File included more than once! This data will be saved in %s if saved back to disk.\n", from_file, from_lineno, real_included_file_name);
} else
*real_included_file_name = 0;
inc = ast_calloc(1,sizeof(struct ast_config_include));
inc->include_location_file = ast_strdup(from_file);
inc->include_location_lineno = from_lineno;
if (!ast_strlen_zero(real_included_file_name))
inc->included_file = ast_strdup(real_included_file_name);
else
inc->included_file = ast_strdup(included_file);
inc->exec = is_exec;
if (is_exec)
inc->exec_file = ast_strdup(exec_file);
/* attach this new struct to the conf struct */
inc->next = conf->includes;
conf->includes = inc;
}
void localized_ast_include_rename(struct ast_config *conf, const char *from_file, const char *to_file)
{
struct ast_config_include *incl;
struct ast_category *cat;
struct ast_variable *v;
int from_len = strlen(from_file);
int to_len = strlen(to_file);
if (strcmp(from_file, to_file) == 0) /* no use wasting time if the name is the same */
return;
/* the manager code allows you to read in one config file, then
write it back out under a different name. But, the new arrangement
ties output lines to the file name. So, before you try to write
the config file to disk, better riffle thru the data and make sure
the file names are changed.
*/
/* file names are on categories, includes (of course), and on variables. So,
traverse all this and swap names */
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
for (incl = conf->includes; incl; incl=incl->next) {
if (strcmp(incl->include_location_file,from_file) == 0) {
if (from_len >= to_len)
strcpy(incl->include_location_file, to_file);
else {
free(incl->include_location_file);
incl->include_location_file = strdup(to_file);
}
}
}
for (cat = conf->root; cat; cat = cat->next) {
if (strcmp(cat->file,from_file) == 0) {
if (from_len >= to_len)
strcpy(cat->file, to_file);
else {
free(cat->file);
cat->file = strdup(to_file);
}
}
for (v = cat->root; v; v = v->next) {
if (strcmp(v->file,from_file) == 0) {
if (from_len >= to_len)
strcpy(v->file, to_file);
else {
free(v->file);
v->file = strdup(to_file);
}
}
}
}
}
static struct ast_config_include *ast_include_find(struct ast_config *conf, const char *included_file)
{
struct ast_config_include *x;
for (x=conf->includes;x;x=x->next)
{
if (strcmp(x->included_file,included_file) == 0)
return x;
}
return 0;
}
static void ast_variable_append(struct ast_category *category, struct ast_variable *variable);
static void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
{
if (!variable)
return;
if (category->last)
category->last->next = variable;
else
category->root = variable;
category->last = variable;
while (category->last->next)
category->last = category->last->next;
}
static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored);
static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored)
{
/* try exact match first, then case-insensitive match */
for (cat = config->root; cat; cat = cat->next) {
if (cat->name == category_name && (ignored || !cat->ignored))
return cat;
}
for (cat = config->root; cat; cat = cat->next) {
if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
return cat;
}
return NULL;
}
static struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name)
{
}
static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category)
{
if (category && config->last_browse && (config->last_browse->name == category))
cat = config->last_browse;
else
cat = ast_category_get(config, category);
}
static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
{
if (category) {
for (v = ast_variable_browse(config, category); v; v = v->next) {
if (!strcasecmp(variable, v->name))
return v->value;
}
} else {
struct ast_category *cat;
for (cat = config->root; cat; cat = cat->next)
for (v = cat->root; v; v = v->next)
if (!strcasecmp(variable, v->name))
return v->value;
}
}
static struct ast_variable *variable_clone(const struct ast_variable *old)
{
struct ast_variable *new = ast_variable_new(old->name, old->value, old->file);
if (new) {
new->lineno = old->lineno;
new->object = old->object;
new->blanklines = old->blanklines;
/* TODO: clone comments? */
}
}
static void ast_variables_destroy(struct ast_variable *v)
{
while (v) {
vn = v;
v = v->next;
free(vn);
}
}
static void ast_includes_destroy(struct ast_config_include *incls)
{
for (incl=incls; incl; incl = inclnext) {
inclnext = incl->next;
if (incl->include_location_file)
free(incl->include_location_file);
if (incl->exec_file)
free(incl->exec_file);
if (incl->included_file)
free(incl->included_file);
free(incl);
}
}
static void ast_config_destroy(struct ast_config *cfg)
{
cat = cfg->root;
while (cat) {
ast_variables_destroy(cat->root);
catn = cat;
cat = cat->next;
free(catn);
}
free(cfg);
}
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
enum ast_option_flags {
/*! Allow \#exec in config files */
AST_OPT_FLAG_EXEC_INCLUDES = (1 << 0),
/*! Do not fork() */
AST_OPT_FLAG_NO_FORK = (1 << 1),
/*! Keep quiet */
AST_OPT_FLAG_QUIET = (1 << 2),
/*! Console mode */
AST_OPT_FLAG_CONSOLE = (1 << 3),
/*! Run in realtime Linux priority */
AST_OPT_FLAG_HIGH_PRIORITY = (1 << 4),
/*! Initialize keys for RSA authentication */
AST_OPT_FLAG_INIT_KEYS = (1 << 5),
/*! Remote console */
AST_OPT_FLAG_REMOTE = (1 << 6),
/*! Execute an asterisk CLI command upon startup */
AST_OPT_FLAG_EXEC = (1 << 7),
/*! Don't use termcap colors */
AST_OPT_FLAG_NO_COLOR = (1 << 8),
/*! Are we fully started yet? */
AST_OPT_FLAG_FULLY_BOOTED = (1 << 9),
/*! Trascode via signed linear */
AST_OPT_FLAG_TRANSCODE_VIA_SLIN = (1 << 10),
/*! Dump core on a seg fault */
AST_OPT_FLAG_DUMP_CORE = (1 << 12),
/*! Cache sound files */
AST_OPT_FLAG_CACHE_RECORD_FILES = (1 << 13),
/*! Display timestamp in CLI verbose output */
AST_OPT_FLAG_TIMESTAMP = (1 << 14),
/*! Override config */
AST_OPT_FLAG_OVERRIDE_CONFIG = (1 << 15),
/*! Reconnect */
AST_OPT_FLAG_RECONNECT = (1 << 16),
/*! Transmit Silence during Record() and DTMF Generation */
AST_OPT_FLAG_TRANSMIT_SILENCE = (1 << 17),
/*! Suppress some warnings */
AST_OPT_FLAG_DONT_WARN = (1 << 18),
/*! Always fork, even if verbose or debug settings are non-zero */
AST_OPT_FLAG_ALWAYS_FORK = (1 << 21),
/*! Disable log/verbose output to remote consoles */
AST_OPT_FLAG_MUTE = (1 << 22),
/*! There is a per-file debug setting */
AST_OPT_FLAG_DEBUG_FILE = (1 << 23),
/*! Terminal colors should be adjusted for a light-colored background */
AST_OPT_FLAG_LIGHT_BACKGROUND = (1 << 25),
/*! Force black background */
AST_OPT_FLAG_FORCE_BLACK_BACKGROUND = (1 << 27),
};
/* options.h declares ast_options extern; I need it static? */
#define AST_CACHE_DIR_LEN 512
#define AST_FILENAME_MAX 80
/*! These are the options that set by default when Asterisk starts */
#define AST_DEFAULT_OPTIONS AST_OPT_FLAG_TRANSCODE_VIA_SLIN
struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
#define ast_opt_exec_includes ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES)
#define ast_opt_no_fork ast_test_flag(&ast_options, AST_OPT_FLAG_NO_FORK)
#define ast_opt_quiet ast_test_flag(&ast_options, AST_OPT_FLAG_QUIET)
#define ast_opt_console ast_test_flag(&ast_options, AST_OPT_FLAG_CONSOLE)
#define ast_opt_high_priority ast_test_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY)
#define ast_opt_init_keys ast_test_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS)
#define ast_opt_remote ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)
#define ast_opt_exec ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC)
#define ast_opt_no_color ast_test_flag(&ast_options, AST_OPT_FLAG_NO_COLOR)
#define ast_fully_booted ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)
#define ast_opt_transcode_via_slin ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN)
#define ast_opt_priority_jumping ast_test_flag(&ast_options, AST_OPT_FLAG_PRIORITY_JUMPING)
#define ast_opt_dump_core ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE)
#define ast_opt_cache_record_files ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES)
#define ast_opt_timestamp ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP)
#define ast_opt_override_config ast_test_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG)
#define ast_opt_reconnect ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT)
#define ast_opt_transmit_silence ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE)
#define ast_opt_dont_warn ast_test_flag(&ast_options, AST_OPT_FLAG_DONT_WARN)
#define ast_opt_always_fork ast_test_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK)
#define ast_opt_mute ast_test_flag(&ast_options, AST_OPT_FLAG_MUTE)
extern int option_verbose;
extern int option_debug; /*!< Debugging */
extern int ast_option_maxcalls; /*!< Maximum number of simultaneous channels */
extern double ast_option_maxload;
extern char ast_defaultlanguage[];
extern char record_cache_dir[AST_CACHE_DIR_LEN];
extern char debug_filename[AST_FILENAME_MAX];
extern int ast_language_is_prefix;
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
/* linkedlists.h */
/*!
\brief Write locks a list.
\param head This is a pointer to the list head structure
This macro attempts to place an exclusive write lock in the
list head structure pointed to by head.
Returns non-zero on success, 0 on failure
*/
#define AST_RWLIST_WRLOCK(head) \
ast_rwlock_wrlock(&(head)->lock)
/*!
\brief Read locks a list.
\param head This is a pointer to the list head structure
This macro attempts to place a read lock in the
list head structure pointed to by head.
Returns non-zero on success, 0 on failure
*/
#define AST_RWLIST_RDLOCK(head) \
ast_rwlock_rdlock(&(head)->lock)
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
/*!
\brief Attempts to unlock a read/write based list.
\param head This is a pointer to the list head structure
This macro attempts to remove a read or write lock from the
list head structure pointed to by head. If the list
was not locked by this thread, this macro has no effect.
*/
#define AST_RWLIST_UNLOCK(head) \
ast_rwlock_unlock(&(head)->lock)
/*!
\brief Defines a structure to be used to hold a list of specified type.
\param name This will be the name of the defined structure.
\param type This is the type of each list entry.
This macro creates a structure definition that can be used
to hold a list of the entries of type \a type. It does not actually
declare (allocate) a structure; to do that, either follow this
macro with the desired name of the instance you wish to declare,
or use the specified \a name to declare instances elsewhere.
Example usage:
\code
static AST_LIST_HEAD(entry_list, entry) entries;
\endcode
This would define \c struct \c entry_list, and declare an instance of it named
\a entries, all intended to hold a list of type \c struct \c entry.
*/
#define AST_LIST_HEAD(name, type) \
struct name { \
struct type *first; \
struct type *last; \
ast_mutex_t lock; \
}
/*!
\brief Defines a structure to be used to hold a read/write list of specified type.
\param name This will be the name of the defined structure.
\param type This is the type of each list entry.
This macro creates a structure definition that can be used
to hold a list of the entries of type \a type. It does not actually
declare (allocate) a structure; to do that, either follow this
macro with the desired name of the instance you wish to declare,
or use the specified \a name to declare instances elsewhere.
Example usage:
\code
static AST_RWLIST_HEAD(entry_list, entry) entries;
\endcode
This would define \c struct \c entry_list, and declare an instance of it named
\a entries, all intended to hold a list of type \c struct \c entry.
*/
#define AST_RWLIST_HEAD(name, type) \
struct name { \
struct type *first; \
struct type *last; \
ast_rwlock_t lock; \
}
/*!
\brief Defines a structure to be used to hold a list of specified type (with no lock).
\param name This will be the name of the defined structure.
\param type This is the type of each list entry.
This macro creates a structure definition that can be used
to hold a list of the entries of type \a type. It does not actually
declare (allocate) a structure; to do that, either follow this
macro with the desired name of the instance you wish to declare,
or use the specified \a name to declare instances elsewhere.
Example usage:
\code
static AST_LIST_HEAD_NOLOCK(entry_list, entry) entries;
\endcode
This would define \c struct \c entry_list, and declare an instance of it named
\a entries, all intended to hold a list of type \c struct \c entry.
*/
#define AST_LIST_HEAD_NOLOCK(name, type) \
struct name { \
struct type *first; \
struct type *last; \
}
/*!
\brief Defines initial values for a declaration of AST_LIST_HEAD
*/
#define AST_LIST_HEAD_INIT_VALUE { \
.first = NULL, \
.last = NULL, \
.lock = AST_MUTEX_INIT_VALUE, \
}
/*!
\brief Defines initial values for a declaration of AST_RWLIST_HEAD
*/
#define AST_RWLIST_HEAD_INIT_VALUE { \
.first = NULL, \
.last = NULL, \
.lock = AST_RWLOCK_INIT_VALUE, \
}
/*!
\brief Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK
*/
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE { \
.first = NULL, \
.last = NULL, \
}
/*!
\brief Defines a structure to be used to hold a list of specified type, statically initialized.
\param name This will be the name of the defined structure.
\param type This is the type of each list entry.
This macro creates a structure definition that can be used
to hold a list of the entries of type \a type, and allocates an instance
of it, initialized to be empty.
Example usage:
\code
static AST_LIST_HEAD_STATIC(entry_list, entry);
\endcode
This would define \c struct \c entry_list, intended to hold a list of
type \c struct \c entry.
*/
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
#define AST_LIST_HEAD_STATIC(name, type) \
struct name { \
struct type *first; \
struct type *last; \
ast_mutex_t lock; \
} name; \
static void __attribute__((constructor)) init_##name(void) \
{ \
AST_LIST_HEAD_INIT(&name); \
} \
static void __attribute__((destructor)) fini_##name(void) \
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
{ \
AST_LIST_HEAD_DESTROY(&name); \
} \
struct __dummy_##name
#else
#define AST_LIST_HEAD_STATIC(name, type) \
struct name { \
struct type *first; \
struct type *last; \
ast_mutex_t lock; \
} name = AST_LIST_HEAD_INIT_VALUE
#endif
/*!
\brief Defines a structure to be used to hold a read/write list of specified type, statically initialized.
\param name This will be the name of the defined structure.
\param type This is the type of each list entry.
This macro creates a structure definition that can be used
to hold a list of the entries of type \a type, and allocates an instance
of it, initialized to be empty.
Example usage:
\code
static AST_RWLIST_HEAD_STATIC(entry_list, entry);
\endcode
This would define \c struct \c entry_list, intended to hold a list of
type \c struct \c entry.
*/
#ifndef AST_RWLOCK_INIT_VALUE
#define AST_RWLIST_HEAD_STATIC(name, type) \
struct name { \
struct type *first; \
struct type *last; \
ast_rwlock_t lock; \
} name; \
static void __attribute__((constructor)) init_##name(void) \
{ \
AST_RWLIST_HEAD_INIT(&name); \
} \
static void __attribute__((destructor)) fini_##name(void) \
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
{ \
AST_RWLIST_HEAD_DESTROY(&name); \
} \
struct __dummy_##name
#else
#define AST_RWLIST_HEAD_STATIC(name, type) \
struct name { \
struct type *first; \
struct type *last; \
ast_rwlock_t lock; \
} name = AST_RWLIST_HEAD_INIT_VALUE
#endif
/*!
\brief Defines a structure to be used to hold a list of specified type, statically initialized.
This is the same as AST_LIST_HEAD_STATIC, except without the lock included.
*/
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type) \
struct name { \
struct type *first; \
struct type *last; \
} name = AST_LIST_HEAD_NOLOCK_INIT_VALUE
/*!
\brief Initializes a list head structure with a specified first entry.
\param head This is a pointer to the list head structure
\param entry pointer to the list entry that will become the head of the list
This macro initializes a list head structure by setting the head
entry to the supplied value and recreating the embedded lock.
*/
#define AST_LIST_HEAD_SET(head, entry) do { \
(head)->first = (entry); \
(head)->last = (entry); \
ast_mutex_init(&(head)->lock); \
} while (0)
/*!
\brief Initializes an rwlist head structure with a specified first entry.
\param head This is a pointer to the list head structure
\param entry pointer to the list entry that will become the head of the list
This macro initializes a list head structure by setting the head
entry to the supplied value and recreating the embedded lock.
*/
#define AST_RWLIST_HEAD_SET(head, entry) do { \
(head)->first = (entry); \
(head)->last = (entry); \
ast_rwlock_init(&(head)->lock); \
} while (0)
/*!
\brief Initializes a list head structure with a specified first entry.
\param head This is a pointer to the list head structure
\param entry pointer to the list entry that will become the head of the list
This macro initializes a list head structure by setting the head
entry to the supplied value.
*/
#define AST_LIST_HEAD_SET_NOLOCK(head, entry) do { \
(head)->first = (entry); \
(head)->last = (entry); \
} while (0)
/*!
\brief Declare a forward link structure inside a list entry.
\param type This is the type of each list entry.
This macro declares a structure to be used to link list entries together.
It must be used inside the definition of the structure named in
\a type, as follows:
\code
struct list_entry {
...
AST_LIST_ENTRY(list_entry) list;
}
\endcode
The field name \a list here is arbitrary, and can be anything you wish.
*/
#define AST_LIST_ENTRY(type) \
struct { \
struct type *next; \
}
#define AST_RWLIST_ENTRY AST_LIST_ENTRY
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
/*!
\brief Returns the first entry contained in a list.
\param head This is a pointer to the list head structure
*/
#define AST_LIST_FIRST(head) ((head)->first)
#define AST_RWLIST_FIRST AST_LIST_FIRST
/*!
\brief Returns the last entry contained in a list.
\param head This is a pointer to the list head structure
*/
#define AST_LIST_LAST(head) ((head)->last)
#define AST_RWLIST_LAST AST_LIST_LAST
/*!
\brief Returns the next entry in the list after the given entry.
\param elm This is a pointer to the current entry.
\param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together.
*/
#define AST_LIST_NEXT(elm, field) ((elm)->field.next)
#define AST_RWLIST_NEXT AST_LIST_NEXT
/*!
\brief Checks whether the specified list contains any entries.
\param head This is a pointer to the list head structure
Returns non-zero if the list has entries, zero if not.
*/
#define AST_LIST_EMPTY(head) (AST_LIST_FIRST(head) == NULL)
#define AST_RWLIST_EMPTY AST_LIST_EMPTY
/*!
\brief Loops over (traverses) the entries in a list.
\param head This is a pointer to the list head structure
\param var This is the name of the variable that will hold a pointer to the
current list entry on each iteration. It must be declared before calling
this macro.
\param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together.
This macro is use to loop over (traverse) the entries in a list. It uses a
\a for loop, and supplies the enclosed code with a pointer to each list
entry as it loops. It is typically used as follows:
\code
static AST_LIST_HEAD(entry_list, list_entry) entries;
...
struct list_entry {
...
AST_LIST_ENTRY(list_entry) list;
}
...
struct list_entry *current;
...
AST_LIST_TRAVERSE(&entries, current, list) {
(do something with current here)
}
\endcode
\warning If you modify the forward-link pointer contained in the \a current entry while
inside the loop, the behavior will be unpredictable. At a minimum, the following
macros will modify the forward-link pointer, and should not be used inside
AST_LIST_TRAVERSE() against the entry pointed to by the \a current pointer without
careful consideration of their consequences:
\li AST_LIST_NEXT() (when used as an lvalue)
\li AST_LIST_INSERT_AFTER()
\li AST_LIST_INSERT_HEAD()
\li AST_LIST_INSERT_TAIL()
*/
#define AST_LIST_TRAVERSE(head,var,field) \
for((var) = (head)->first; (var); (var) = (var)->field.next)
#define AST_RWLIST_TRAVERSE AST_LIST_TRAVERSE
/*!
\brief Loops safely over (traverses) the entries in a list.
\param head This is a pointer to the list head structure
\param var This is the name of the variable that will hold a pointer to the
current list entry on each iteration. It must be declared before calling
this macro.
\param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together.
This macro is used to safely loop over (traverse) the entries in a list. It
uses a \a for loop, and supplies the enclosed code with a pointer to each list
entry as it loops. It is typically used as follows:
\code
static AST_LIST_HEAD(entry_list, list_entry) entries;
...
struct list_entry {
...
AST_LIST_ENTRY(list_entry) list;
}
...
struct list_entry *current;
...
AST_LIST_TRAVERSE_SAFE_BEGIN(&entries, current, list) {
(do something with current here)
}
AST_LIST_TRAVERSE_SAFE_END;
\endcode
It differs from AST_LIST_TRAVERSE() in that the code inside the loop can modify
(or even free, after calling AST_LIST_REMOVE_CURRENT()) the entry pointed to by
the \a current pointer without affecting the loop traversal.
*/
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field) { \
typeof((head)->first) __list_next; \
typeof((head)->first) __list_prev = NULL; \
typeof((head)->first) __new_prev = NULL; \
for ((var) = (head)->first, __new_prev = (var), \
__list_next = (var) ? (var)->field.next : NULL; \
(var); \
__list_prev = __new_prev, (var) = __list_next, \
__new_prev = (var), \
__list_next = (var) ? (var)->field.next : NULL \
)
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN AST_LIST_TRAVERSE_SAFE_BEGIN
/*!
\brief Removes the \a current entry from a list during a traversal.
\param head This is a pointer to the list head structure
\param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together.
\note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
block; it is used to unlink the current entry from the list without affecting
the list traversal (and without having to re-traverse the list to modify the
previous entry, if any).
*/
#define AST_LIST_REMOVE_CURRENT(head, field) \
__new_prev->field.next = NULL; \
__new_prev = __list_prev; \
if (__list_prev) \
__list_prev->field.next = __list_next; \
else \
(head)->first = __list_next; \
if (!__list_next) \
(head)->last = __list_prev;
#define AST_RWLIST_REMOVE_CURRENT AST_LIST_REMOVE_CURRENT
/*!
\brief Inserts a list entry before the current entry during a traversal.
\param head This is a pointer to the list head structure
\param elm This is a pointer to the entry to be inserted.
\param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together.
\note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
block.
*/
#define AST_LIST_INSERT_BEFORE_CURRENT(head, elm, field) do { \
if (__list_prev) { \
(elm)->field.next = __list_prev->field.next; \
__list_prev->field.next = elm; \
} else { \
(elm)->field.next = (head)->first; \
(head)->first = (elm); \
} \
__new_prev = (elm); \
} while (0)
#define AST_RWLIST_INSERT_BEFORE_CURRENT AST_LIST_INSERT_BEFORE_CURRENT
/*!
\brief Closes a safe loop traversal block.
*/
#define AST_LIST_TRAVERSE_SAFE_END }
#define AST_RWLIST_TRAVERSE_SAFE_END AST_LIST_TRAVERSE_SAFE_END
/*!
\brief Initializes a list head structure.
\param head This is a pointer to the list head structure
This macro initializes a list head structure by setting the head
entry to \a NULL (empty list) and recreating the embedded lock.
*/
#define AST_LIST_HEAD_INIT(head) { \
(head)->first = NULL; \
(head)->last = NULL; \
ast_mutex_init(&(head)->lock); \
}
/*!
\brief Initializes an rwlist head structure.
\param head This is a pointer to the list head structure
This macro initializes a list head structure by setting the head
entry to \a NULL (empty list) and recreating the embedded lock.
*/
#define AST_RWLIST_HEAD_INIT(head) { \
(head)->first = NULL; \
(head)->last = NULL; \
ast_rwlock_init(&(head)->lock); \
}
/*!
\brief Destroys an rwlist head structure.
\param head This is a pointer to the list head structure
This macro destroys a list head structure by setting the head
entry to \a NULL (empty list) and destroying the embedded lock.
It does not free the structure from memory.
*/
#define AST_RWLIST_HEAD_DESTROY(head) { \
(head)->first = NULL; \
(head)->last = NULL; \
ast_rwlock_destroy(&(head)->lock); \
}
/*!
\brief Initializes a list head structure.
\param head This is a pointer to the list head structure
This macro initializes a list head structure by setting the head
entry to \a NULL (empty list). There is no embedded lock handling
with this macro.
*/
#define AST_LIST_HEAD_INIT_NOLOCK(head) { \
(head)->first = NULL; \
(head)->last = NULL; \
}
/*!
\brief Inserts a list entry after a given entry.
\param head This is a pointer to the list head structure
\param listelm This is a pointer to the entry after which the new entry should
be inserted.
\param elm This is a pointer to the entry to be inserted.
\param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together.
*/
#define AST_LIST_INSERT_AFTER(head, listelm, elm, field) do { \
(elm)->field.next = (listelm)->field.next; \
(listelm)->field.next = (elm); \
if ((head)->last == (listelm)) \
(head)->last = (elm); \
} while (0)
#define AST_RWLIST_INSERT_AFTER AST_LIST_INSERT_AFTER
/*!
\brief Inserts a list entry at the head of a list.
\param head This is a pointer to the list head structure
\param elm This is a pointer to the entry to be inserted.
\param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together.
*/
#define AST_LIST_INSERT_HEAD(head, elm, field) do { \
(elm)->field.next = (head)->first; \
(head)->first = (elm); \
if (!(head)->last) \
(head)->last = (elm); \
} while (0)
#define AST_RWLIST_INSERT_HEAD AST_LIST_INSERT_HEAD
/*!
\brief Appends a list entry to the tail of a list.
\param head This is a pointer to the list head structure
\param elm This is a pointer to the entry to be appended.
\param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together.
Note: The link field in the appended entry is \b not modified, so if it is
actually the head of a list itself, the entire list will be appended
temporarily (until the next AST_LIST_INSERT_TAIL is performed).
*/
#define AST_LIST_INSERT_TAIL(head, elm, field) do { \
if (!(head)->first) { \
(head)->first = (elm); \
(head)->last = (elm); \
} else { \
(head)->last->field.next = (elm); \
(head)->last = (elm); \
} \
} while (0)
#define AST_RWLIST_INSERT_TAIL AST_LIST_INSERT_TAIL
/*!
\brief Appends a whole list to the tail of a list.
\param head This is a pointer to the list head structure
\param list This is a pointer to the list to be appended.
\param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together.
*/
#define AST_LIST_APPEND_LIST(head, list, field) do { \
if (!(head)->first) { \
(head)->first = (list)->first; \
(head)->last = (list)->last; \
} else { \
(head)->last->field.next = (list)->first; \