Commit bc86794f authored by Havoc Pennington's avatar Havoc Pennington

2003-03-30 Havoc Pennington <hp@pobox.com>

	* bus/config-parser.c: hacking

	* dbus/dbus-memory.c: don't use DBusList for the list of stuff
	to shut down, since it could cause weirdness with the DBusList
	lock

	* dbus/dbus-list.c (_dbus_list_test): add tests for the
	link-oriented stack routines
	(alloc_link): free the mempool if the first alloc from it fails

	* dbus/dbus-mempool.c (struct DBusMemBlock): fix alignment issue

	* dbus/dbus-string.c (UNICODE_VALID): sync new version of this
	from GLib
	(_dbus_string_skip_white): new

	* doc/config-file.txt (Elements): add <includedir>
parent d361874e
2003-03-30 Havoc Pennington <hp@pobox.com>
* bus/config-parser.c: hacking
* dbus/dbus-memory.c: don't use DBusList for the list of stuff
to shut down, since it could cause weirdness with the DBusList
lock
* dbus/dbus-list.c (_dbus_list_test): add tests for the
link-oriented stack routines
(alloc_link): free the mempool if the first alloc from it fails
* dbus/dbus-mempool.c (struct DBusMemBlock): fix alignment issue
* dbus/dbus-string.c (UNICODE_VALID): sync new version of this
from GLib
(_dbus_string_skip_white): new
* doc/config-file.txt (Elements): add <includedir>
2003-03-28 Havoc Pennington <hp@pobox.com>
* dbus/dbus-string.c (_dbus_string_copy_data_len)
(_dbus_string_copy_data): new functions
2003-03-28 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-bus.c: (bus_data_free), (dbus_bus_get):
......
......@@ -4,7 +4,7 @@
* Copyright (C) 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
......@@ -14,7 +14,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
......@@ -41,6 +41,27 @@ typedef struct
dbus_bool_t failed;
} ExpatParseContext;
static dbus_bool_t
process_content (ExpatParseContext *context)
{
if (context->failed)
return FALSE;
if (_dbus_string_get_length (&context->content) > 0)
{
if (!bus_config_parser_content (context->parser,
&context->content,
context->error))
{
context->failed = TRUE;
return FALSE;
}
_dbus_string_set_length (&context->content, 0);
}
return TRUE;
}
static void
expat_StartElementHandler (void *userData,
const XML_Char *name,
......@@ -50,13 +71,16 @@ expat_StartElementHandler (void *userData,
int i;
char **names;
char **values;
/* Expat seems to suck and can't abort the parse if we
* throw an error. Expat 2.0 is supposed to fix this.
*/
if (context->failed)
return;
if (!process_content (context))
return;
/* "atts" is key, value, key, value, NULL */
for (i = 0; atts[i] != NULL; ++i)
; /* nothing */
......@@ -73,17 +97,17 @@ expat_StartElementHandler (void *userData,
dbus_free (values);
return;
}
i = 0;
while (atts[i] != NULL)
{
_dbus_assert (i % 2 == 0);
names [i / 2] = (char*) atts[i];
values[i / 2 + 1] = (char*) atts[i+1];
names [i / 2] = (char*) atts[i];
values[i / 2] = (char*) atts[i+1];
i += 2;
}
if (!bus_config_parser_start_element (context->parser,
name,
(const char **) names,
......@@ -105,20 +129,9 @@ expat_EndElementHandler (void *userData,
const XML_Char *name)
{
ExpatParseContext *context = userData;
if (context->failed)
return;
if (_dbus_string_get_length (&context->content) > 0)
{
if (!bus_config_parser_content (context->parser,
&context->content,
context->error))
{
context->failed = TRUE;
return;
}
_dbus_string_set_length (&context->content, 0);
}
if (!process_content (context))
return;
if (!bus_config_parser_end_element (context->parser,
name,
......@@ -157,22 +170,22 @@ bus_config_load (const DBusString *file,
const char *filename;
BusConfigParser *parser;
ExpatParseContext context;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
parser = NULL;
expat = NULL;
context.error = error;
context.failed = FALSE;
_dbus_string_get_const_data (file, &filename);
if (!_dbus_string_init (&context.content, _DBUS_INT_MAX))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return NULL;
}
expat = XML_ParserCreate_MM ("UTF-8", &memsuite, NULL);
if (expat == NULL)
{
......@@ -186,6 +199,7 @@ bus_config_load (const DBusString *file,
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto failed;
}
context.parser = parser;
XML_SetUserData (expat, &context);
XML_SetElementHandler (expat,
......@@ -197,28 +211,28 @@ bus_config_load (const DBusString *file,
{
DBusString data;
const char *data_str;
if (!_dbus_string_init (&data, _DBUS_INT_MAX))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto failed;
}
if (!_dbus_file_get_contents (&data, file, error))
{
_dbus_string_free (&data);
goto failed;
}
_dbus_string_get_const_data (&data, &data_str);
if (!XML_Parse (expat, data_str, _dbus_string_get_length (&data), TRUE))
{
if (context.error != NULL &&
!dbus_error_is_set (context.error))
{
enum XML_Error e;
e = XML_GetErrorCode (expat);
if (e == XML_ERROR_NO_MEMORY)
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
......@@ -230,7 +244,7 @@ bus_config_load (const DBusString *file,
XML_GetCurrentColumnNumber (expat),
XML_ErrorString (e));
}
_dbus_string_free (&data);
goto failed;
}
......@@ -240,7 +254,7 @@ bus_config_load (const DBusString *file,
if (context.failed)
goto failed;
}
if (!bus_config_parser_finished (parser, error))
goto failed;
......@@ -249,10 +263,10 @@ bus_config_load (const DBusString *file,
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
return parser;
failed:
_DBUS_ASSERT_ERROR_IS_SET (error);
_dbus_string_free (&context.content);
if (expat)
XML_ParserFree (expat);
......
This diff is collapsed.
......@@ -69,8 +69,8 @@ main (int argc, char **argv)
printf ("%s: Running config file parser test\n", argv[0]);
if (!bus_config_parser_test (&test_data_dir))
die ("parser");
check_memleaks (argv[0]);
check_memleaks (argv[0]);
printf ("%s: Running policy test\n", argv[0]);
if (!bus_policy_test (&test_data_dir))
......
......@@ -345,7 +345,7 @@ _dbus_test_oom_handling (const char *description,
if (!(* func) (data))
return FALSE;
approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
_dbus_verbose ("=================\n%s: about %d mallocs total\n=================\n",
......
......@@ -212,7 +212,8 @@ _DBUS_DECLARE_GLOBAL_LOCK (atomic);
_DBUS_DECLARE_GLOBAL_LOCK (message_handler);
_DBUS_DECLARE_GLOBAL_LOCK (user_info);
_DBUS_DECLARE_GLOBAL_LOCK (bus);
#define _DBUS_N_GLOBAL_LOCKS (7)
_DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);
#define _DBUS_N_GLOBAL_LOCKS (8)
DBUS_END_DECLS;
......
......@@ -57,8 +57,8 @@ alloc_link (void *data)
if (!_DBUS_LOCK (list))
return NULL;
if (!list_pool)
if (list_pool == NULL)
{
list_pool = _dbus_mem_pool_new (sizeof (DBusList), TRUE);
......@@ -67,9 +67,21 @@ alloc_link (void *data)
_DBUS_UNLOCK (list);
return NULL;
}
link = _dbus_mem_pool_alloc (list_pool);
if (link == NULL)
{
_dbus_mem_pool_free (list_pool);
list_pool = NULL;
_DBUS_UNLOCK (list);
return NULL;
}
}
link = _dbus_mem_pool_alloc (list_pool);
else
{
link = _dbus_mem_pool_alloc (list_pool);
}
if (link)
link->data = data;
......@@ -80,13 +92,14 @@ alloc_link (void *data)
static void
free_link (DBusList *link)
{
{
_DBUS_LOCK (list);
if (_dbus_mem_pool_dealloc (list_pool, link))
{
_dbus_mem_pool_free (list_pool);
list_pool = NULL;
}
_DBUS_UNLOCK (list);
}
......@@ -607,6 +620,27 @@ _dbus_list_pop_last (DBusList **list)
return data;
}
/**
* Removes the last link in the list and returns it. This is a
* constant-time operation.
*
* @param list address of the list head.
* @returns the last link in the list, or #NULL for an empty list.
*/
DBusList*
_dbus_list_pop_last_link (DBusList **list)
{
DBusList *link;
link = _dbus_list_get_last_link (list);
if (link == NULL)
return NULL;
_dbus_list_unlink (list, link);
return link;
}
/**
* Copies a list. This is a linear-time operation. If there isn't
* enough memory to copy the entire list, the destination list will be
......@@ -952,6 +986,58 @@ _dbus_list_test (void)
_dbus_assert (list1 == NULL);
_dbus_assert (list2 == NULL);
/* Test get_first_link, get_last_link, pop_first_link, pop_last_link */
i = 0;
while (i < 10)
{
_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
++i;
}
--i;
while (i >= 0)
{
DBusList *got_link1;
DBusList *got_link2;
DBusList *link1;
DBusList *link2;
void *data1;
void *data2;
got_link1 = _dbus_list_get_last_link (&list1);
got_link2 = _dbus_list_get_first_link (&list2);
link1 = _dbus_list_pop_last_link (&list1);
link2 = _dbus_list_pop_first_link (&list2);
_dbus_assert (got_link1 == link1);
_dbus_assert (got_link2 == link2);
data1 = link1->data;
data2 = link2->data;
_dbus_list_free_link (link1);
_dbus_list_free_link (link2);
_dbus_assert (_DBUS_POINTER_TO_INT (data1) == i);
_dbus_assert (_DBUS_POINTER_TO_INT (data2) == i);
verify_list (&list1);
verify_list (&list2);
_dbus_assert (is_ascending_sequence (&list1));
_dbus_assert (is_descending_sequence (&list2));
--i;
}
_dbus_assert (list1 == NULL);
_dbus_assert (list2 == NULL);
/* Test iteration */
i = 0;
......
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-list.h Generic linked list utility (internal to D-BUS implementation)
*
* Copyright (C) 2002 Red Hat, Inc.
* Copyright (C) 2002, 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
......@@ -63,6 +63,7 @@ void* _dbus_list_get_first (DBusList **list);
void* _dbus_list_pop_first (DBusList **list);
void* _dbus_list_pop_last (DBusList **list);
DBusList* _dbus_list_pop_first_link (DBusList **list);
DBusList* _dbus_list_pop_last_link (DBusList **list);
dbus_bool_t _dbus_list_copy (DBusList **list,
DBusList **dest);
int _dbus_list_get_length (DBusList **list);
......
......@@ -633,13 +633,17 @@ dbus_free_string_array (char **str_array)
*/
int _dbus_current_generation = 1;
static DBusList *registered_globals = NULL;
typedef struct ShutdownClosure ShutdownClosure;
typedef struct
struct ShutdownClosure
{
ShutdownClosure *next;
DBusShutdownFunction func;
void *data;
} ShutdownClosure;
};
_DBUS_DEFINE_GLOBAL_LOCK (shutdown_funcs);
static ShutdownClosure *registered_globals = NULL;
/**
* The D-BUS library keeps some internal global variables, for example
......@@ -656,22 +660,18 @@ typedef struct
void
dbus_shutdown (void)
{
DBusList *link;
link = _dbus_list_get_first_link (&registered_globals);
while (link != NULL)
while (registered_globals != NULL)
{
ShutdownClosure *c = link->data;
ShutdownClosure *c;
c = registered_globals;
registered_globals = c->next;
(* c->func) (c->data);
dbus_free (c);
link = _dbus_list_get_next_link (&registered_globals, link);
dbus_free (c);
}
_dbus_list_clear (&registered_globals);
_dbus_current_generation += 1;
}
......@@ -693,20 +693,17 @@ _dbus_register_shutdown_func (DBusShutdownFunction func,
if (c == NULL)
return FALSE;
c->func = func;
c->data = data;
/* We prepend, then shutdown the list in order, so
* we shutdown last-registered stuff first which
* is right.
*/
if (!_dbus_list_prepend (&registered_globals, c))
{
dbus_free (c);
return FALSE;
}
_DBUS_LOCK (shutdown_funcs);
c->next = registered_globals;
registered_globals = c;
_DBUS_UNLOCK (shutdown_funcs);
return TRUE;
}
......
......@@ -84,7 +84,8 @@ struct DBusMemBlock
* when we free the mem pool.
*/
int used_so_far; /**< bytes of this block already allocated as elements. */
/* this is a long so that "elements" is aligned */
long used_so_far; /**< bytes of this block already allocated as elements. */
unsigned char elements[ELEMENT_PADDING]; /**< the block data, actually allocated to required size */
};
......@@ -254,7 +255,7 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
memset (element, '\0', pool->element_size);
pool->allocated_elements += 1;
return element;
}
else
......@@ -311,11 +312,11 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
}
element = &pool->blocks->elements[pool->blocks->used_so_far];
pool->blocks->used_so_far += pool->element_size;
pool->allocated_elements += 1;
return element;
}
}
......
......@@ -633,7 +633,74 @@ _dbus_string_steal_data_len (DBusString *str,
return FALSE;
}
_dbus_warn ("Broken code in _dbus_string_steal_data_len(), FIXME\n");
_dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
if (!_dbus_string_steal_data (&dest, data_return))
{
_dbus_string_free (&dest);
return FALSE;
}
_dbus_string_free (&dest);
return TRUE;
}
/**
* Copies the data from the string into a char*
*
* @param str the string
* @param data_return place to return the data
* @returns #TRUE on success, #FALSE on no memory
*/
dbus_bool_t
_dbus_string_copy_data (const DBusString *str,
char **data_return)
{
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (data_return != NULL);
*data_return = dbus_malloc (real->len + 1);
if (*data_return == NULL)
return FALSE;
memcpy (*data_return, real->str, real->len + 1);
return TRUE;
}
/**
* Copies a segment of the string into a char*
*
* @param str the string
* @param data_return place to return the data
* @param start start index
* @param len length to copy
* @returns #FALSE if no memory
*/
dbus_bool_t
_dbus_string_copy_data_len (const DBusString *str,
char **data_return,
int start,
int len)
{
DBusString dest;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (data_return != NULL);
_dbus_assert (start >= 0);
_dbus_assert (len >= 0);
_dbus_assert (start <= real->len);
_dbus_assert (len <= real->len - start);
if (!_dbus_string_init (&dest, real->max_length))
return FALSE;
if (!_dbus_string_copy_len (str, start, len, &dest, 0))
{
_dbus_string_free (&dest);
return FALSE;
}
if (!_dbus_string_steal_data (&dest, data_return))
{
_dbus_string_free (&dest);
......@@ -1235,8 +1302,9 @@ _dbus_string_replace_len (const DBusString *source,
*/
#define UNICODE_VALID(Char) \
((Char) < 0x110000 && \
((Char) < 0xD800 || (Char) >= 0xE000) && \
(Char) != 0xFFFE && (Char) != 0xFFFF)
(((Char) & 0xFFFFF800) != 0xD800) && \
((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
((Char) & 0xFFFF) != 0xFFFF)
/**
* Gets a unicode character from a UTF-8 string. Does no validation;
......@@ -1426,6 +1494,7 @@ _dbus_string_find_blank (const DBusString *str,
/**
* Skips blanks from start, storing the first non-blank in *end
* (blank is space or tab).
*
* @param str the string
* @param start where to start
......@@ -1458,6 +1527,43 @@ _dbus_string_skip_blank (const DBusString *str,
*end = i;
}
/**
* Skips whitespace from start, storing the first non-whitespace in *end.
* (whitespace is space, tab, newline, CR).
*
* @param str the string
* @param start where to start
* @param end where to store the first non-whitespace byte index
*/
void
_dbus_string_skip_white (const DBusString *str,
int start,