diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..456a702 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/gjs-1.56.2.tar.xz diff --git a/.gjs.metadata b/.gjs.metadata new file mode 100644 index 0000000..ed23f03 --- /dev/null +++ b/.gjs.metadata @@ -0,0 +1 @@ +cf4f885d2d41a5c9fb85bd90df46bb67a93f4f07 SOURCES/gjs-1.56.2.tar.xz diff --git a/SOURCES/0001-gi-Include-missing-glib-bits.patch b/SOURCES/0001-gi-Include-missing-glib-bits.patch new file mode 100644 index 0000000..4fd11ed --- /dev/null +++ b/SOURCES/0001-gi-Include-missing-glib-bits.patch @@ -0,0 +1,1581 @@ +From 9d7d64617c59e99bd2aced57009213c8a99e676e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 29 May 2019 19:44:55 +0200 +Subject: [PATCH] gi: Include missing glib bits + +--- + gi/garcbox.c | 387 ++++++++++++++++++++++++++++++++++ + gi/grcbox.c | 506 +++++++++++++++++++++++++++++++++++++++++++++ + gi/grcbox.h | 96 +++++++++ + gi/grcboxprivate.h | 78 +++++++ + gi/grefcount.c | 289 ++++++++++++++++++++++++++ + gi/grefcount.h | 134 ++++++++++++ + gi/wrapperutils.h | 2 + + gjs-srcs.mk | 6 + + 8 files changed, 1498 insertions(+) + create mode 100644 gi/garcbox.c + create mode 100644 gi/grcbox.c + create mode 100644 gi/grcbox.h + create mode 100644 gi/grcboxprivate.h + create mode 100644 gi/grefcount.c + create mode 100644 gi/grefcount.h + +diff --git a/gi/garcbox.c b/gi/garcbox.c +new file mode 100644 +index 00000000..bee75073 +--- /dev/null ++++ b/gi/garcbox.c +@@ -0,0 +1,387 @@ ++/* garcbox.c: Atomically reference counted data ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#include "config.h" ++ ++#include "grcboxprivate.h" ++ ++#if 0 ++#include "gmessages.h" ++#endif ++#include "grefcount.h" ++ ++#ifdef ENABLE_VALGRIND ++#include "valgrind.h" ++#endif ++ ++#if 0 ++#include "glib_trace.h" ++#else ++#include "gjs_gi_trace.h" ++#endif ++ ++#include ++ ++#define G_ARC_BOX(p) (GArcBox *) (((char *) (p)) - G_ARC_BOX_SIZE) ++ ++/** ++ * SECTION:arcbox ++ * @Title: Atomically reference counted data ++ * @Short_description: Allocated memory with atomic reference counting semantics ++ * ++ * An "atomically reference counted box", or "ArcBox", is an opaque wrapper ++ * data type that is guaranteed to be as big as the size of a given data type, ++ * and which augments the given data type with thread safe reference counting ++ * semantics for its memory management. ++ * ++ * ArcBox is useful if you have a plain old data type, like a structure ++ * typically placed on the stack, and you wish to provide additional API ++ * to use it on the heap; or if you want to implement a new type to be ++ * passed around by reference without necessarily implementing copy/free ++ * semantics or your own reference counting. ++ * ++ * The typical use is: ++ * ++ * |[ ++ * typedef struct { ++ * char *name; ++ * char *address; ++ * char *city; ++ * char *state; ++ * int age; ++ * } Person; ++ * ++ * Person * ++ * person_new (void) ++ * { ++ * return g_atomic_rc_box_new0 (Person); ++ * } ++ * ]| ++ * ++ * Every time you wish to acquire a reference on the memory, you should ++ * call g_atomic_rc_box_acquire(); similarly, when you wish to release a reference ++ * you should call g_atomic_rc_box_release(): ++ * ++ * |[ ++ * // Add a Person to the Database; the Database acquires ownership ++ * // of the Person instance ++ * void ++ * add_person_to_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_prepend (db->persons, g_atomic_rc_box_acquire (p)); ++ * } ++ * ++ * // Removes a Person from the Database; the reference acquired by ++ * // add_person_to_database() is released here ++ * void ++ * remove_person_from_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_remove (db->persons, p); ++ * g_atomic_rc_box_release (p); ++ * } ++ * ]| ++ * ++ * If you have additional memory allocated inside the structure, you can ++ * use g_atomic_rc_box_release_full(), which takes a function pointer, which ++ * will be called if the reference released was the last: ++ * ++ * |[ ++ * void ++ * person_clear (Person *p) ++ * { ++ * g_free (p->name); ++ * g_free (p->address); ++ * g_free (p->city); ++ * g_free (p->state); ++ * } ++ * ++ * void ++ * remove_person_from_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_remove (db->persons, p); ++ * g_atomic_rc_box_release_full (p, (GDestroyNotify) person_clear); ++ * } ++ * ]| ++ * ++ * If you wish to transfer the ownership of a reference counted data ++ * type without increasing the reference count, you can use g_steal_pointer(): ++ * ++ * |[ ++ * Person *p = g_atomic_rc_box_new (Person); ++ * ++ * fill_person_details (p); ++ * ++ * add_person_to_database (db, g_steal_pointer (&p)); ++ * ]| ++ * ++ * ## Thread safety ++ * ++ * The reference counting operations on data allocated using g_atomic_rc_box_alloc(), ++ * g_atomic_rc_box_new(), and g_atomic_rc_box_dup() are guaranteed to be atomic, and thus ++ * can be safely be performed by different threads. It is important to note that ++ * only the reference acquisition and release are atomic; changes to the content ++ * of the data are your responsibility. ++ * ++ * ## Automatic pointer clean up ++ * ++ * If you want to add g_autoptr() support to your plain old data type through ++ * reference counting, you can use the G_DEFINE_AUTOPTR_CLEANUP_FUNC() and ++ * g_atomic_rc_box_release(): ++ * ++ * |[ ++ * G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, g_atomic_rc_box_release) ++ * ]| ++ * ++ * If you need to clear the contents of the data, you will need to use an ++ * ancillary function that calls g_rc_box_release_full(): ++ * ++ * |[ ++ * static void ++ * my_data_struct_release (MyDataStruct *data) ++ * { ++ * // my_data_struct_clear() is defined elsewhere ++ * g_atomic_rc_box_release_full (data, (GDestroyNotify) my_data_struct_clear); ++ * } ++ * ++ * G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, my_data_struct_release) ++ * ]| ++ * ++ * Since: 2.58. ++ */ ++ ++/** ++ * g_atomic_rc_box_alloc: ++ * @block_size: the size of the allocation, must be greater than 0 ++ * ++ * Allocates @block_size bytes of memory, and adds atomic ++ * reference counting semantics to it. ++ * ++ * The data will be freed when its reference count drops to ++ * zero. ++ * ++ * The allocated data is guaranteed to be suitably aligned for any ++ * built-in type. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++g_atomic_rc_box_alloc (gsize block_size) ++{ ++ g_return_val_if_fail (block_size > 0, NULL); ++ ++ return g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, TRUE, FALSE); ++} ++ ++/** ++ * g_atomic_rc_box_alloc0: ++ * @block_size: the size of the allocation, must be greater than 0 ++ * ++ * Allocates @block_size bytes of memory, and adds atomic ++ * referenc counting semantics to it. ++ * ++ * The contents of the returned data is set to zero. ++ * ++ * The data will be freed when its reference count drops to ++ * zero. ++ * ++ * The allocated data is guaranteed to be suitably aligned for any ++ * built-in type. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++g_atomic_rc_box_alloc0 (gsize block_size) ++{ ++ g_return_val_if_fail (block_size > 0, NULL); ++ ++ return g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, TRUE, TRUE); ++} ++ ++/** ++ * g_atomic_rc_box_new: ++ * @type: the type to allocate, typically a structure name ++ * ++ * A convenience macro to allocate atomically reference counted ++ * data with the size of the given @type. ++ * ++ * This macro calls g_atomic_rc_box_alloc() with `sizeof (@type)` and ++ * casts the returned pointer to a pointer of the given @type, ++ * avoiding a type cast in the source code. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated ++ * memory, cast to a pointer for the given @type ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * g_atomic_rc_box_new0: ++ * @type: the type to allocate, typically a structure name ++ * ++ * A convenience macro to allocate atomically reference counted ++ * data with the size of the given @type, and set its contents ++ * to zero. ++ * ++ * This macro calls g_atomic_rc_box_alloc0() with `sizeof (@type)` and ++ * casts the returned pointer to a pointer of the given @type, ++ * avoiding a type cast in the source code. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated ++ * memory, cast to a pointer for the given @type ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * g_atomic_rc_box_dup: ++ * @block_size: the number of bytes to copy, must be greater than 0 ++ * @mem_block: (not nullable): the memory to copy ++ * ++ * Allocates a new block of data with atomit reference counting ++ * semantics, and copies @block_size bytes of @mem_block ++ * into it. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated ++ * memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++(g_atomic_rc_box_dup) (gsize block_size, ++ gconstpointer mem_block) ++{ ++ gpointer res; ++ ++ g_return_val_if_fail (block_size > 0, NULL); ++ g_return_val_if_fail (mem_block != NULL, NULL); ++ ++ res = g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, TRUE, FALSE); ++ memcpy (res, mem_block, block_size); ++ ++ return res; ++} ++ ++/** ++ * g_atomic_rc_box_acquire: ++ * @mem_block: (not nullable): a pointer to reference counted data ++ * ++ * Atomically acquires a reference on the data pointed by @mem_block. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the data, ++ * with its reference count increased ++ * ++ * Since: 2.58 ++ */ ++gpointer ++(g_atomic_rc_box_acquire) (gpointer mem_block) ++{ ++ GArcBox *real_box = G_ARC_BOX (mem_block); ++ ++ g_return_val_if_fail (mem_block != NULL, NULL); ++#ifndef G_DISABLE_ASSERT ++ g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, NULL); ++#endif ++ ++ g_atomic_ref_count_inc (&real_box->ref_count); ++ ++ TRACE (GLIB_RCBOX_ACQUIRE (mem_block, 1)); ++ ++ return mem_block; ++} ++ ++/** ++ * g_atomic_rc_box_release: ++ * @mem_block: (transfer full) (not nullable): a pointer to reference counted data ++ * ++ * Atomically releases a reference on the data pointed by @mem_block. ++ * ++ * If the reference was the last one, it will free the ++ * resources allocated for @mem_block. ++ * ++ * Since: 2.58 ++ */ ++void ++g_atomic_rc_box_release (gpointer mem_block) ++{ ++ g_atomic_rc_box_release_full (mem_block, NULL); ++} ++ ++/** ++ * g_atomic_rc_box_release_full: ++ * @mem_block: (transfer full) (not nullable): a pointer to reference counted data ++ * @clear_func: (not nullable): a function to call when clearing the data ++ * ++ * Atomically releases a reference on the data pointed by @mem_block. ++ * ++ * If the reference was the last one, it will call @clear_func ++ * to clear the contents of @mem_block, and then will free the ++ * resources allocated for @mem_block. ++ * ++ * Since: 2.58 ++ */ ++void ++g_atomic_rc_box_release_full (gpointer mem_block, ++ GDestroyNotify clear_func) ++{ ++ GArcBox *real_box = G_ARC_BOX (mem_block); ++ ++ g_return_if_fail (mem_block != NULL); ++#ifndef G_DISABLE_ASSERT ++ g_return_if_fail (real_box->magic == G_BOX_MAGIC); ++#endif ++ ++ if (g_atomic_ref_count_dec (&real_box->ref_count)) ++ { ++ char *real_mem = (char *) real_box - real_box->private_offset; ++ ++ TRACE (GLIB_RCBOX_RELEASE (mem_block, 1)); ++ ++ if (clear_func != NULL) ++ clear_func (mem_block); ++ ++ TRACE (GLIB_RCBOX_FREE (mem_block)); ++ g_free (real_mem); ++ } ++} ++ ++/** ++ * g_atomic_rc_box_get_size: ++ * @mem_block: (not nullable): a pointer to reference counted data ++ * ++ * Retrieves the size of the reference counted data pointed by @mem_block. ++ * ++ * Returns: the size of the data, in bytes ++ * ++ * Since: 2.58 ++ */ ++gsize ++g_atomic_rc_box_get_size (gpointer mem_block) ++{ ++ GArcBox *real_box = G_ARC_BOX (mem_block); ++ ++ g_return_val_if_fail (mem_block != NULL, 0); ++#ifndef G_DISABLE_ASSERT ++ g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, 0); ++#endif ++ ++ return real_box->mem_size; ++} +diff --git a/gi/grcbox.c b/gi/grcbox.c +new file mode 100644 +index 00000000..4f76a2b5 +--- /dev/null ++++ b/gi/grcbox.c +@@ -0,0 +1,506 @@ ++/* grcbox.c: Reference counted data ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#include "config.h" ++ ++#include "grcboxprivate.h" ++ ++#include "grefcount.h" ++#if 0 ++#include "gmessages.h" ++#include "gtestutils.h" ++ ++#include "glib_trace.h" ++#else ++#include "gjs_gi_trace.h" ++#endif ++ ++#ifdef ENABLE_VALGRIND ++#include "valgrind.h" ++#endif ++ ++#include ++ ++/** ++ * SECTION:rcbox ++ * @Title: Reference counted data ++ * @Short_description: Allocated memory with reference counting semantics ++ * ++ * A "reference counted box", or "RcBox", is an opaque wrapper data type ++ * that is guaranteed to be as big as the size of a given data type, and ++ * which augments the given data type with reference counting semantics ++ * for its memory management. ++ * ++ * RcBox is useful if you have a plain old data type, like a structure ++ * typically placed on the stack, and you wish to provide additional API ++ * to use it on the heap; or if you want to implement a new type to be ++ * passed around by reference without necessarily implementing copy/free ++ * semantics or your own reference counting. ++ * ++ * The typical use is: ++ * ++ * |[ ++ * typedef struct { ++ * char *name; ++ * char *address; ++ * char *city; ++ * char *state; ++ * int age; ++ * } Person; ++ * ++ * Person * ++ * person_new (void) ++ * { ++ * return g_rc_box_new0 (Person); ++ * } ++ * ]| ++ * ++ * Every time you wish to acquire a reference on the memory, you should ++ * call g_rc_box_acquire(); similarly, when you wish to release a reference ++ * you should call g_rc_box_release(): ++ * ++ * |[ ++ * // Add a Person to the Database; the Database acquires ownership ++ * // of the Person instance ++ * void ++ * add_person_to_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_prepend (db->persons, g_rc_box_acquire (p)); ++ * } ++ * ++ * // Removes a Person from the Database; the reference acquired by ++ * // add_person_to_database() is released here ++ * void ++ * remove_person_from_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_remove (db->persons, p); ++ * g_rc_box_release (p); ++ * } ++ * ]| ++ * ++ * If you have additional memory allocated inside the structure, you can ++ * use g_rc_box_release_full(), which takes a function pointer, which ++ * will be called if the reference released was the last: ++ * ++ * |[ ++ * void ++ * person_clear (Person *p) ++ * { ++ * g_free (p->name); ++ * g_free (p->address); ++ * g_free (p->city); ++ * g_free (p->state); ++ * } ++ * ++ * void ++ * remove_person_from_database (Database *db, Person *p) ++ * { ++ * db->persons = g_list_remove (db->persons, p); ++ * g_rc_box_release_full (p, (GDestroyNotify) person_clear); ++ * } ++ * ]| ++ * ++ * If you wish to transfer the ownership of a reference counted data ++ * type without increasing the reference count, you can use g_steal_pointer(): ++ * ++ * |[ ++ * Person *p = g_rc_box_new (Person); ++ * ++ * // fill_person_details() is defined elsewhere ++ * fill_person_details (p); ++ * ++ * // add_person_to_database_no_ref() is defined elsewhere; it adds ++ * // a Person to the Database without taking a reference ++ * add_person_to_database_no_ref (db, g_steal_pointer (&p)); ++ * ]| ++ * ++ * ## Thread safety ++ * ++ * The reference counting operations on data allocated using g_rc_box_alloc(), ++ * g_rc_box_new(), and g_rc_box_dup() are not thread safe; it is your code's ++ * responsibility to ensure that references are acquired are released on the ++ * same thread. ++ * ++ * If you need thread safe reference counting, see the [atomic reference counted ++ * data][arcbox] API. ++ * ++ * ## Automatic pointer clean up ++ * ++ * If you want to add g_autoptr() support to your plain old data type through ++ * reference counting, you can use the G_DEFINE_AUTOPTR_CLEANUP_FUNC() and ++ * g_rc_box_release(): ++ * ++ * |[ ++ * G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, g_rc_box_release) ++ * ]| ++ * ++ * If you need to clear the contents of the data, you will need to use an ++ * ancillary function that calls g_rc_box_release_full(): ++ * ++ * |[ ++ * static void ++ * my_data_struct_release (MyDataStruct *data) ++ * { ++ * // my_data_struct_clear() is defined elsewhere ++ * g_rc_box_release_full (data, (GDestroyNotify) my_data_struct_clear); ++ * } ++ * ++ * G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, my_data_struct_release) ++ * ]| ++ * ++ * Since: 2.58. ++ */ ++ ++/* We use the same alignment as GTypeInstance and GNU libc's malloc */ ++#define ALIGN_STRUCT(offset) ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT) ++ ++#define G_RC_BOX(p) (GRcBox *) (((char *) (p)) - G_RC_BOX_SIZE) ++ ++gpointer ++g_rc_box_alloc_full (gsize block_size, ++ gsize alignment, ++ gboolean atomic, ++ gboolean clear) ++{ ++ /* We don't do an (atomic ? G_ARC_BOX_SIZE : G_RC_BOX_SIZE) check, here ++ * because we have a static assertion that sizeof(GArcBox) == sizeof(GRcBox) ++ * inside grcboxprivate.h, and we don't want the compiler to unnecessarily ++ * warn about both branches of the conditional yielding identical results ++ */ ++ gsize private_size = G_ARC_BOX_SIZE; ++ gsize private_offset = 0; ++ gsize real_size; ++ char *allocated; ++ ++ g_assert (alignment != 0); ++ ++ /* We need to ensure that the private data is aligned */ ++ if (private_size % alignment != 0) ++ { ++ private_offset = private_size % alignment; ++ private_size += (alignment - private_offset); ++ } ++ ++ g_assert (block_size < (G_MAXSIZE - private_size)); ++ real_size = private_size + block_size; ++ ++ /* The real allocated size must be a multiple of @alignment, to ++ * maintain the alignment of block_size ++ */ ++ if (real_size % alignment != 0) ++ { ++ gsize offset = real_size % alignment; ++ g_assert (real_size < (G_MAXSIZE - (alignment - offset))); ++ real_size += (alignment - offset); ++ } ++ ++#ifdef ENABLE_VALGRIND ++ if (RUNNING_ON_VALGRIND) ++ { ++ /* When running under Valgrind we massage the memory allocation ++ * to include a pointer at the tail end of the block; the pointer ++ * is then set to the start of the block. This trick allows ++ * Valgrind to keep track of the over-allocation and not be ++ * confused when passing the pointer around ++ */ ++ g_assert (private_size < (G_MAXSIZE - ALIGN_STRUCT (1))); ++ private_size += ALIGN_STRUCT (1); ++ ++ if (clear) ++ allocated = g_malloc0 (real_size + sizeof (gpointer)); ++ else ++ allocated = g_malloc (real_size + sizeof (gpointer)); ++ ++ *(gpointer *) (allocated + private_size + block_size) = allocated + ALIGN_STRUCT (1); ++ ++ VALGRIND_MALLOCLIKE_BLOCK (allocated + private_size, block_size + sizeof (gpointer), 0, TRUE); ++ VALGRIND_MALLOCLIKE_BLOCK (allocated + ALIGN_STRUCT (1), private_size - ALIGN_STRUCT (1), 0, TRUE); ++ } ++ else ++#endif /* ENABLE_VALGRIND */ ++ { ++ if (clear) ++ allocated = g_malloc0 (real_size); ++ else ++ allocated = g_malloc (real_size); ++ } ++ ++ if (atomic) ++ { ++ /* We leave the alignment padding at the top of the allocation, ++ * so we have an in memory layout of: ++ * ++ * |[ offset ][ sizeof(GArcBox) ]||[ block_size ]| ++ */ ++ GArcBox *real_box = (GArcBox *) (allocated + private_offset); ++ /* Store the real size */ ++ real_box->mem_size = block_size; ++ /* Store the alignment offset, to be used when freeing the ++ * allocated block ++ */ ++ real_box->private_offset = private_offset; ++#ifndef G_DISABLE_ASSERT ++ real_box->magic = G_BOX_MAGIC; ++#endif ++ g_atomic_ref_count_init (&real_box->ref_count); ++ } ++ else ++ { ++ /* We leave the alignment padding at the top of the allocation, ++ * so we have an in memory layout of: ++ * ++ * |[ offset ][ sizeof(GRcBox) ]||[ block_size ]| ++ */ ++ GRcBox *real_box = (GRcBox *) (allocated + private_offset); ++ /* Store the real size */ ++ real_box->mem_size = block_size; ++ /* Store the alignment offset, to be used when freeing the ++ * allocated block ++ */ ++ real_box->private_offset = private_offset; ++#ifndef G_DISABLE_ASSERT ++ real_box->magic = G_BOX_MAGIC; ++#endif ++ g_ref_count_init (&real_box->ref_count); ++ } ++ ++ TRACE (GLIB_RCBOX_ALLOC (allocated, block_size, atomic, clear)); ++ ++ return allocated + private_size; ++} ++ ++/** ++ * g_rc_box_alloc: ++ * @block_size: the size of the allocation, must be greater than 0 ++ * ++ * Allocates @block_size bytes of memory, and adds reference ++ * counting semantics to it. ++ * ++ * The data will be freed when its reference count drops to ++ * zero. ++ * ++ * The allocated data is guaranteed to be suitably aligned for any ++ * built-in type. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++g_rc_box_alloc (gsize block_size) ++{ ++ g_return_val_if_fail (block_size > 0, NULL); ++ ++ return g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, FALSE, FALSE); ++} ++ ++/** ++ * g_rc_box_alloc0: ++ * @block_size: the size of the allocation, must be greater than 0 ++ * ++ * Allocates @block_size bytes of memory, and adds reference ++ * counting semantics to it. ++ * ++ * The contents of the returned data is set to zero. ++ * ++ * The data will be freed when its reference count drops to ++ * zero. ++ * ++ * The allocated data is guaranteed to be suitably aligned for any ++ * built-in type. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++g_rc_box_alloc0 (gsize block_size) ++{ ++ g_return_val_if_fail (block_size > 0, NULL); ++ ++ return g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, FALSE, TRUE); ++} ++ ++/** ++ * g_rc_box_new: ++ * @type: the type to allocate, typically a structure name ++ * ++ * A convenience macro to allocate reference counted data with ++ * the size of the given @type. ++ * ++ * This macro calls g_rc_box_alloc() with `sizeof (@type)` and ++ * casts the returned pointer to a pointer of the given @type, ++ * avoiding a type cast in the source code. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the ++ * allocated memory, cast to a pointer for the given @type ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * g_rc_box_new0: ++ * @type: the type to allocate, typically a structure name ++ * ++ * A convenience macro to allocate reference counted data with ++ * the size of the given @type, and set its contents to zero. ++ * ++ * This macro calls g_rc_box_alloc0() with `sizeof (@type)` and ++ * casts the returned pointer to a pointer of the given @type, ++ * avoiding a type cast in the source code. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the ++ * allocated memory, cast to a pointer for the given @type ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * g_rc_box_dup: ++ * @block_size: the number of bytes to copy, must be greater than 0 ++ * @mem_block: (not nullable): the memory to copy ++ * ++ * Allocates a new block of data with reference counting ++ * semantics, and copies @block_size bytes of @mem_block ++ * into it. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the allocated ++ * memory ++ * ++ * Since: 2.58 ++ */ ++gpointer ++(g_rc_box_dup) (gsize block_size, ++ gconstpointer mem_block) ++{ ++ gpointer res; ++ ++ g_return_val_if_fail (block_size > 0, NULL); ++ g_return_val_if_fail (mem_block != NULL, NULL); ++ ++ res = g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, FALSE, FALSE); ++ memcpy (res, mem_block, block_size); ++ ++ return res; ++} ++ ++/** ++ * g_rc_box_acquire: ++ * @mem_block: (not nullable): a pointer to reference counted data ++ * ++ * Acquires a reference on the data pointed by @mem_block. ++ * ++ * Returns: (transfer full) (not nullable): a pointer to the data, ++ * with its reference count increased ++ * ++ * Since: 2.58 ++ */ ++gpointer ++(g_rc_box_acquire) (gpointer mem_block) ++{ ++ GRcBox *real_box = G_RC_BOX (mem_block); ++ ++ g_return_val_if_fail (mem_block != NULL, NULL); ++#ifndef G_DISABLE_ASSERT ++ g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, NULL); ++#endif ++ ++ g_ref_count_inc (&real_box->ref_count); ++ ++ TRACE (GLIB_RCBOX_ACQUIRE (mem_block, 0)); ++ ++ return mem_block; ++} ++ ++/** ++ * g_rc_box_release: ++ * @mem_block: (transfer full) (not nullable): a pointer to reference counted data ++ * ++ * Releases a reference on the data pointed by @mem_block. ++ * ++ * If the reference was the last one, it will free the ++ * resources allocated for @mem_block. ++ * ++ * Since: 2.58 ++ */ ++void ++g_rc_box_release (gpointer mem_block) ++{ ++ g_rc_box_release_full (mem_block, NULL); ++} ++ ++/** ++ * g_rc_box_release_full: ++ * @mem_block: (transfer full) (not nullable): a pointer to reference counted data ++ * @clear_func: (not nullable): a function to call when clearing the data ++ * ++ * Releases a reference on the data pointed by @mem_block. ++ * ++ * If the reference was the last one, it will call @clear_func ++ * to clear the contents of @mem_block, and then will free the ++ * resources allocated for @mem_block. ++ * ++ * Since: 2.58 ++ */ ++void ++g_rc_box_release_full (gpointer mem_block, ++ GDestroyNotify clear_func) ++{ ++ GRcBox *real_box = G_RC_BOX (mem_block); ++ ++ g_return_if_fail (mem_block != NULL); ++#ifndef G_DISABLE_ASSERT ++ g_return_if_fail (real_box->magic == G_BOX_MAGIC); ++#endif ++ ++ if (g_ref_count_dec (&real_box->ref_count)) ++ { ++ char *real_mem = (char *) real_box - real_box->private_offset; ++ ++ TRACE (GLIB_RCBOX_RELEASE (mem_block, 0)); ++ ++ if (clear_func != NULL) ++ clear_func (mem_block); ++ ++ TRACE (GLIB_RCBOX_FREE (mem_block)); ++ g_free (real_mem); ++ } ++} ++ ++/** ++ * g_rc_box_get_size: ++ * @mem_block: (not nullable): a pointer to reference counted data ++ * ++ * Retrieves the size of the reference counted data pointed by @mem_block. ++ * ++ * Returns: the size of the data, in bytes ++ * ++ * Since: 2.58 ++ */ ++gsize ++g_rc_box_get_size (gpointer mem_block) ++{ ++ GRcBox *real_box = G_RC_BOX (mem_block); ++ ++ g_return_val_if_fail (mem_block != NULL, 0); ++#ifndef G_DISABLE_ASSERT ++ g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, 0); ++#endif ++ ++ return real_box->mem_size; ++} +diff --git a/gi/grcbox.h b/gi/grcbox.h +new file mode 100644 +index 00000000..7c2f89f5 +--- /dev/null ++++ b/gi/grcbox.h +@@ -0,0 +1,96 @@ ++/* grcbox.h: Reference counted data ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#pragma once ++ ++#if 0 ++#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) ++#error "Only can be included directly." ++#endif ++ ++#include ++#else ++#include ++ ++#ifndef GLIB_AVAILABLE_IN_2_58 ++#define GLIB_AVAILABLE_IN_2_58 ++#endif ++#endif ++ ++G_BEGIN_DECLS ++ ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_rc_box_alloc (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_rc_box_alloc0 (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_rc_box_dup (gsize block_size, ++ gconstpointer mem_block) G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_rc_box_acquire (gpointer mem_block); ++GLIB_AVAILABLE_IN_2_58 ++void g_rc_box_release (gpointer mem_block); ++GLIB_AVAILABLE_IN_2_58 ++void g_rc_box_release_full (gpointer mem_block, ++ GDestroyNotify clear_func); ++ ++GLIB_AVAILABLE_IN_2_58 ++gsize g_rc_box_get_size (gpointer mem_block); ++ ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_atomic_rc_box_alloc (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_atomic_rc_box_alloc0 (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_atomic_rc_box_dup (gsize block_size, ++ gconstpointer mem_block) G_GNUC_ALLOC_SIZE(1); ++GLIB_AVAILABLE_IN_2_58 ++gpointer g_atomic_rc_box_acquire (gpointer mem_block); ++GLIB_AVAILABLE_IN_2_58 ++void g_atomic_rc_box_release (gpointer mem_block); ++GLIB_AVAILABLE_IN_2_58 ++void g_atomic_rc_box_release_full (gpointer mem_block, ++ GDestroyNotify clear_func); ++ ++GLIB_AVAILABLE_IN_2_58 ++gsize g_atomic_rc_box_get_size (gpointer mem_block); ++ ++#define g_rc_box_new(type) \ ++ ((type *) g_rc_box_alloc (sizeof (type))) ++#define g_rc_box_new0(type) \ ++ ((type *) g_rc_box_alloc0 (sizeof (type))) ++#define g_atomic_rc_box_new(type) \ ++ ((type *) g_atomic_rc_box_alloc (sizeof (type))) ++#define g_atomic_rc_box_new0(type) \ ++ ((type *) g_atomic_rc_box_alloc0 (sizeof (type))) ++ ++#ifdef g_has_typeof ++/* Type check to avoid assigning references to different types */ ++# define g_rc_box_acquire(mem_block) \ ++ ((__typeof__(mem_block)) (g_rc_box_acquire) (mem_block)) ++# define g_atomic_rc_box_acquire(mem_block) \ ++ ((__typeof__(mem_block)) (g_atomic_rc_box_acquire) (mem_block)) ++ ++/* Type check to avoid duplicating data to different types */ ++# define g_rc_box_dup(block_size,mem_block) \ ++ ((__typeof__(mem_block)) (g_rc_box_dup) (block_size,mem_block)) ++# define g_atomic_rc_box_dup(block_size,mem_block) \ ++ ((__typeof__(mem_block)) (g_atomic_rc_box_dup) (block_size,mem_block)) ++#endif ++ ++G_END_DECLS +diff --git a/gi/grcboxprivate.h b/gi/grcboxprivate.h +new file mode 100644 +index 00000000..7ed94ab8 +--- /dev/null ++++ b/gi/grcboxprivate.h +@@ -0,0 +1,78 @@ ++/* grcboxprivate.h: Reference counted data ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#pragma once ++ ++#if 0 ++#include "gtypes.h" ++#else ++#include ++ ++typedef gint grefcount; ++typedef volatile gint gatomicrefcount; ++#endif ++#include "grcbox.h" ++ ++G_BEGIN_DECLS ++ ++typedef struct { ++ grefcount ref_count; ++ ++ gsize mem_size; ++ gsize private_offset; ++ ++#ifndef G_DISABLE_ASSERT ++ /* A "magic" number, used to perform additional integrity ++ * checks on the allocated data ++ */ ++ guint32 magic; ++#endif ++} GRcBox; ++ ++typedef struct { ++ gatomicrefcount ref_count; ++ ++ gsize mem_size; ++ gsize private_offset; ++ ++#ifndef G_DISABLE_ASSERT ++ guint32 magic; ++#endif ++} GArcBox; ++ ++#define G_BOX_MAGIC 0x44ae2bf0 ++ ++/* Keep the two refcounted boxes identical in size */ ++G_STATIC_ASSERT (sizeof (GRcBox) == sizeof (GArcBox)); ++ ++/* This is the default alignment we use when allocating the ++ * refcounted memory blocks; it's similar to the alignment ++ * guaranteed by the malloc() in GNU's libc and by the GSlice ++ * allocator ++ */ ++#define STRUCT_ALIGNMENT (2 * sizeof (gsize)) ++ ++#define G_RC_BOX_SIZE sizeof (GRcBox) ++#define G_ARC_BOX_SIZE sizeof (GArcBox) ++ ++gpointer g_rc_box_alloc_full (gsize block_size, ++ gsize alignment, ++ gboolean atomic, ++ gboolean clear); ++ ++G_END_DECLS +diff --git a/gi/grefcount.c b/gi/grefcount.c +new file mode 100644 +index 00000000..2bc7e9d7 +--- /dev/null ++++ b/gi/grefcount.c +@@ -0,0 +1,289 @@ ++/* grefcount.c: Reference counting ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++/** ++ * SECTION:refcount ++ * @Title: Reference counting ++ * @Short_description: Reference counting types and functions ++ * ++ * Reference counting is a garbage collection mechanism that is based on ++ * assigning a counter to a data type, or any memory area; the counter is ++ * increased whenever a new reference to that data type is acquired, and ++ * decreased whenever the reference is released. Once the last reference ++ * is released, the resources associated to that data type are freed. ++ * ++ * GLib uses reference counting in many of its data types, and provides ++ * the #grefcount and #gatomicrefcount types to implement safe and atomic ++ * reference counting semantics in new data types. ++ * ++ * It is important to note that #grefcount and #gatomicrefcount should be ++ * considered completely opaque types; you should always use the provided ++ * API to increase and decrease the counters, and you should never check ++ * their content directly, or compare their content with other values. ++ * ++ * Since: 2.58 ++ */ ++ ++#include "config.h" ++ ++#include "grefcount.h" ++ ++#if 0 ++#include "gatomic.h" ++#include "gmessages.h" ++#else ++#include ++#endif ++ ++/** ++ * grefcount: ++ * ++ * A type for implementing non-atomic reference count semantics. ++ * ++ * Use g_ref_count_init() to initialize it; g_ref_count_inc() to ++ * increase the counter, and g_ref_count_dec() to decrease it. ++ * ++ * It is safe to use #grefcount only if you're expecting to operate ++ * on the reference counter from a single thread. It is entirely up ++ * to you to ensure that all reference count changes happen in the ++ * same thread. ++ * ++ * See also: #gatomicrefcount ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * gatomicrefcount: ++ * ++ * A type for implementing atomic reference count semantics. ++ * ++ * Use g_atomic_ref_count_init() to initialize it; g_atomic_ref_count_inc() ++ * to increase the counter, and g_atomic_ref_count_dec() to decrease it. ++ * ++ * It is safe to use #gatomicrefcount if you're expecting to operate on the ++ * reference counter from multiple threads. ++ * ++ * See also: #grefcount ++ * ++ * Since: 2.58 ++ */ ++ ++/** ++ * g_ref_count_init: ++ * @rc: the address of a reference count variable ++ * ++ * Initializes a reference count variable. ++ * ++ * Since: 2.58 ++ */ ++void ++(g_ref_count_init) (grefcount *rc) ++{ ++ g_return_if_fail (rc != NULL); ++ ++ /* Non-atomic refcounting is implemented using the negative range ++ * of signed integers: ++ * ++ * G_MININT Z¯< 0 > Z⁺ G_MAXINT ++ * |----------------------------|----------------------------| ++ * ++ * Acquiring a reference moves us towards MININT, and releasing a ++ * reference moves us towards 0. ++ */ ++ *rc = -1; ++} ++ ++/** ++ * g_ref_count_inc: ++ * @rc: the address of a reference count variable ++ * ++ * Increases the reference count. ++ * ++ * Since: 2.58 ++ */ ++void ++(g_ref_count_inc) (grefcount *rc) ++{ ++ grefcount rrc; ++ ++ g_return_if_fail (rc != NULL); ++ ++ rrc = *rc; ++ ++ g_return_if_fail (rrc < 0); ++ ++ /* Check for saturation */ ++ if (rrc == G_MININT) ++ { ++ g_critical ("Reference count %p has reached saturation", rc); ++ return; ++ } ++ ++ rrc -= 1; ++ ++ *rc = rrc; ++} ++ ++/** ++ * g_ref_count_dec: ++ * @rc: the address of a reference count variable ++ * ++ * Decreases the reference count. ++ * ++ * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise ++ * ++ * Since: 2.58 ++ */ ++gboolean ++(g_ref_count_dec) (grefcount *rc) ++{ ++ grefcount rrc; ++ ++ g_return_val_if_fail (rc != NULL, FALSE); ++ ++ rrc = *rc; ++ ++ g_return_val_if_fail (rrc < 0, FALSE); ++ ++ rrc += 1; ++ if (rrc == 0) ++ return TRUE; ++ ++ *rc = rrc; ++ ++ return FALSE; ++} ++ ++/** ++ * g_ref_count_compare: ++ * @rc: the address of a reference count variable ++ * @val: the value to compare ++ * ++ * Compares the current value of @rc with @val. ++ * ++ * Returns: %TRUE if the reference count is the same ++ * as the given value ++ * ++ * Since: 2.58 ++ */ ++gboolean ++(g_ref_count_compare) (grefcount *rc, ++ gint val) ++{ ++ grefcount rrc; ++ ++ g_return_val_if_fail (rc != NULL, FALSE); ++ g_return_val_if_fail (val >= 0, FALSE); ++ ++ rrc = *rc; ++ ++ if (val == G_MAXINT) ++ return rrc == G_MININT; ++ ++ return rrc == -val; ++} ++ ++/** ++ * g_atomic_ref_count_init: ++ * @arc: the address of an atomic reference count variable ++ * ++ * Initializes a reference count variable. ++ * ++ * Since: 2.58 ++ */ ++void ++(g_atomic_ref_count_init) (gatomicrefcount *arc) ++{ ++ g_return_if_fail (arc != NULL); ++ ++ /* Atomic refcounting is implemented using the positive range ++ * of signed integers: ++ * ++ * G_MININT Z¯< 0 > Z⁺ G_MAXINT ++ * |----------------------------|----------------------------| ++ * ++ * Acquiring a reference moves us towards MAXINT, and releasing a ++ * reference moves us towards 0. ++ */ ++ *arc = 1; ++} ++ ++/** ++ * g_atomic_ref_count_inc: ++ * @arc: the address of an atomic reference count variable ++ * ++ * Atomically increases the reference count. ++ * ++ * Since: 2.58 ++ */ ++void ++(g_atomic_ref_count_inc) (gatomicrefcount *arc) ++{ ++ g_return_if_fail (arc != NULL); ++ g_return_if_fail (g_atomic_int_get (arc) > 0); ++ ++ if (g_atomic_int_get (arc) == G_MAXINT) ++ { ++ g_critical ("Reference count has reached saturation"); ++ return; ++ } ++ ++ g_atomic_int_inc (arc); ++} ++ ++/** ++ * g_atomic_ref_count_dec: ++ * @arc: the address of an atomic reference count variable ++ * ++ * Atomically decreases the reference count. ++ * ++ * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise ++ * ++ * Since: 2.58 ++ */ ++gboolean ++(g_atomic_ref_count_dec) (gatomicrefcount *arc) ++{ ++ g_return_val_if_fail (arc != NULL, FALSE); ++ g_return_val_if_fail (g_atomic_int_get (arc) > 0, FALSE); ++ ++ return g_atomic_int_dec_and_test (arc); ++} ++ ++/** ++ * g_atomic_ref_count_compare: ++ * @arc: the address of an atomic reference count variable ++ * @val: the value to compare ++ * ++ * Atomically compares the current value of @arc with @val. ++ * ++ * Returns: %TRUE if the reference count is the same ++ * as the given value ++ * ++ * Since: 2.58 ++ */ ++gboolean ++(g_atomic_ref_count_compare) (gatomicrefcount *arc, ++ gint val) ++{ ++ g_return_val_if_fail (arc != NULL, FALSE); ++ g_return_val_if_fail (val >= 0, FALSE); ++ ++ return g_atomic_int_get (arc) == val; ++} +diff --git a/gi/grefcount.h b/gi/grefcount.h +new file mode 100644 +index 00000000..d2f78037 +--- /dev/null ++++ b/gi/grefcount.h +@@ -0,0 +1,134 @@ ++/* grefcount.h: Reference counting ++ * ++ * Copyright 2018 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#ifndef __GREFCOUNT_H__ ++#define __GREFCOUNT_H__ ++ ++#if 0 ++#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) ++#error "Only can be included directly." ++#endif ++ ++#include ++#include ++#else ++#include ++ ++#ifndef GLIB_AVAILABLE_IN_2_58 ++#define GLIB_AVAILABLE_IN_2_58 ++#endif ++ ++typedef gint grefcount; ++typedef volatile gint gatomicrefcount; ++#endif ++ ++G_BEGIN_DECLS ++ ++GLIB_AVAILABLE_IN_2_58 ++void g_ref_count_init (grefcount *rc); ++GLIB_AVAILABLE_IN_2_58 ++void g_ref_count_inc (grefcount *rc); ++GLIB_AVAILABLE_IN_2_58 ++gboolean g_ref_count_dec (grefcount *rc); ++GLIB_AVAILABLE_IN_2_58 ++gboolean g_ref_count_compare (grefcount *rc, ++ gint val); ++ ++GLIB_AVAILABLE_IN_2_58 ++void g_atomic_ref_count_init (gatomicrefcount *arc); ++GLIB_AVAILABLE_IN_2_58 ++void g_atomic_ref_count_inc (gatomicrefcount *arc); ++GLIB_AVAILABLE_IN_2_58 ++gboolean g_atomic_ref_count_dec (gatomicrefcount *arc); ++GLIB_AVAILABLE_IN_2_58 ++gboolean g_atomic_ref_count_compare (gatomicrefcount *arc, ++ gint val); ++ ++/* On GCC we can use __extension__ to inline the API without using ++ * ancillary functions; we only do this when disabling checks, as ++ * it disables warnings when saturating the reference counters ++ */ ++#if defined(__GNUC__) && defined(G_DISABLE_CHECKS) ++ ++# define g_ref_count_init(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \ ++ (void) (0 ? *(rc) ^ *(rc) : 1); \ ++ *(rc) = -1; \ ++ })) ++ ++# define g_ref_count_inc(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \ ++ (void) (0 ? *(rc) ^ *(rc) : 1); \ ++ if (*(rc) == G_MININT) ; else { \ ++ *(rc) -= 1; \ ++ } \ ++ })) ++ ++# define g_ref_count_dec(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \ ++ grefcount __rc = *(rc); \ ++ __rc += 1; \ ++ if (__rc == 0) ; else { \ ++ *(rc) = __rc; \ ++ } \ ++ (gboolean) (__rc == 0); \ ++ })) ++ ++# define g_ref_count_compare(rc,val) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \ ++ (void) (0 ? *(rc) ^ (val) : 1); \ ++ (gboolean) (*(rc) == -(val)); \ ++ })) ++ ++# define g_atomic_ref_count_init(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \ ++ (void) (0 ? *(rc) ^ *(rc) : 1); \ ++ *(rc) = 1; \ ++ })) ++ ++# define g_atomic_ref_count_inc(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \ ++ (void) (0 ? *(rc) ^ *(rc) : 1); \ ++ (void) (g_atomic_int_get (rc) == G_MAXINT ? 0 : g_atomic_int_inc ((rc))); \ ++ })) ++ ++# define g_atomic_ref_count_dec(rc) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \ ++ (void) (0 ? *(rc) ^ *(rc) : 1); \ ++ g_atomic_int_dec_and_test ((rc)); \ ++ })) ++ ++# define g_atomic_ref_count_compare(rc,val) \ ++ (G_GNUC_EXTENSION ({ \ ++ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \ ++ (void) (0 ? *(rc) ^ (val) : 1); \ ++ (gboolean) (g_atomic_int_get (rc) == (val)); \ ++ })) ++ ++#endif /* __GNUC__ && G_DISABLE_CHECKS */ ++ ++G_END_DECLS ++ ++#endif /* __GREFCOUNT_H__ */ +diff --git a/gi/wrapperutils.h b/gi/wrapperutils.h +index 5fa4ae2f..4a67ea87 100644 +--- a/gi/wrapperutils.h ++++ b/gi/wrapperutils.h +@@ -31,6 +31,8 @@ + #include "gjs/macros.h" + #include "util/log.h" + ++#include "gi/grcbox.h" ++ + G_BEGIN_DECLS + + GJS_JSAPI_RETURN_CONVENTION +diff --git a/gjs-srcs.mk b/gjs-srcs.mk +index dcdc4387..a66f4788 100644 +--- a/gjs-srcs.mk ++++ b/gjs-srcs.mk +@@ -13,6 +13,12 @@ gjs_public_headers = \ + # public + + gjs_srcs = \ ++ gi/garcbox.c \ ++ gi/grcbox.c \ ++ gi/grcbox.h \ ++ gi/grcboxprivate.h \ ++ gi/grefcount.c \ ++ gi/grefcount.h \ + gi/arg.cpp \ + gi/arg.h \ + gi/boxed.cpp \ +-- +2.21.0 + diff --git a/SPECS/gjs.spec b/SPECS/gjs.spec new file mode 100644 index 0000000..1511da9 --- /dev/null +++ b/SPECS/gjs.spec @@ -0,0 +1,530 @@ +%global glib2_version 2.54.0 +%global gobject_introspection_version 1.41.4 +%global gtk3_version 3.20 +%global mozjs60_version 60.9.0-4 + +Name: gjs +Version: 1.56.2 +Release: 4%{?dist} +Summary: Javascript Bindings for GNOME + +# The following files contain code from Mozilla which +# is triple licensed under MPL1.1/LGPLv2+/GPLv2+: +# The console module (modules/console.c) +# Stack printer (gjs/stack.c) +License: MIT and (MPLv1.1 or GPLv2+ or LGPLv2+) +URL: https://wiki.gnome.org/Projects/Gjs +Source0: https://download.gnome.org/sources/%{name}/1.56/%{name}-%{version}.tar.xz + +Patch0: 0001-gi-Include-missing-glib-bits.patch + +BuildRequires: cairo-gobject-devel +BuildRequires: chrpath +BuildRequires: dbus-daemon +BuildRequires: dbus-glib-devel +BuildRequires: gcc-c++ +BuildRequires: gettext +BuildRequires: glib2-devel >= %{glib2_version} +BuildRequires: gobject-introspection-devel >= %{gobject_introspection_version} +BuildRequires: gtk3-devel >= %{gtk3_version} +BuildRequires: mozjs60-devel >= %{mozjs60_version} +BuildRequires: pkgconfig +BuildRequires: readline-devel + +Requires: glib2%{?_isa} >= %{glib2_version} +Requires: gobject-introspection%{?_isa} >= %{gobject_introspection_version} +Requires: gtk3%{?_isa} >= %{gtk3_version} +Requires: mozjs60%{?_isa} >= %{mozjs60_version} + +# Filter provides for private libraries +%global __provides_exclude_from ^%{_libdir}/gjs/ + +%description +Gjs allows using GNOME libraries from Javascript. It's based on the +Spidermonkey Javascript engine from Mozilla and the GObject introspection +framework. + +%package devel +Summary: Development package for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +Files for development with %{name}. + +%package tests +Summary: Tests for the gjs package +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description tests +The gjs-tests package contains tests that can be used to verify +the functionality of the installed gjs package. + +%prep +%autosetup -p1 + +%build +%configure --disable-static --enable-installed-tests + +make %{?_smp_mflags} V=1 + +%install +%make_install + +# Remove lib64 rpaths +chrpath --delete %{buildroot}%{_bindir}/gjs-console +chrpath --delete %{buildroot}%{_libexecdir}/gjs/installed-tests/minijasmine + +find %{buildroot} -name '*.la' -exec rm -f {} ';' + +%check +#make check + +%files +%license COPYING +%doc NEWS README +%{_bindir}/gjs +%{_bindir}/gjs-console +%{_libdir}/*.so.* +%{_libdir}/gjs + +%files devel +%doc examples/* +%{_includedir}/gjs-1.0 +%{_libdir}/pkgconfig/gjs-1.0.pc +%{_libdir}/*.so +%dir %{_datadir}/gjs-1.0 +%{_datadir}/gjs-1.0/lsan/ +%{_datadir}/gjs-1.0/valgrind/ + +%files tests +%{_libexecdir}/gjs/installed-tests +%{_datadir}/installed-tests + +%changelog +* Tue Feb 18 2020 Kalev Lember - 1.56.2-4 +- Rebuild for mozjs60 s390x fixes +- Related: #1803824 + +* Tue Sep 10 2019 Kalev Lember - 1.56.2-3 +- Rebuild for mozjs60 s390x fixes +- Related: #1746889 + +* Thu May 23 2019 Florian Müllner - 1.56.2-1 +- Update to 1.56.2 + Resolves: #1698923 + +* Fri Feb 22 2019 Florian Müllner - 1.52.5-2 +- Fix crash in cairo support module + Resolves: #1678869 + +* Mon Jan 21 2019 Ray Strode - 1.52.5-1 +- Update to 1.52.5 +- Fixes delayed garbage collection problem + Resolves: #1666809 + +* Wed Dec 12 2018 Ray Strode - 1.52.4-2 +- rebuild + +* Tue Oct 16 2018 Kalev Lember - 1.52.4-1 +- Update to 1.52.4 + +* Tue May 08 2018 Kalev Lember - 1.52.3-1 +- Update to 1.52.3 + +* Wed Apr 18 2018 Kalev Lember - 1.52.2-1 +- Update to 1.52.2 + +* Tue Apr 10 2018 Kalev Lember - 1.52.1-1 +- Update to 1.52.1 + +* Tue Mar 13 2018 Kalev Lember - 1.52.0-1 +- Update to 1.52.0 + +* Sun Mar 11 2018 Kalev Lember - 1.51.92-1 +- Update to 1.51.92 + +* Wed Feb 21 2018 Kalev Lember - 1.51.91-1 +- Update to 1.51.91 + +* Wed Feb 07 2018 Fedora Release Engineering - 1.51.90-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Mon Feb 05 2018 Kalev Lember - 1.51.90-1 +- Update to 1.51.90 +- Drop ldconfig scriptlets +- Filter provides for private libraries + +* Sat Feb 03 2018 Igor Gnatenko - 1.50.4-2 +- Switch to %%ldconfig_scriptlets + +* Sun Jan 28 2018 Kalev Lember - 1.50.4-1 +- Update to 1.50.4 + +* Thu Jan 18 2018 Kalev Lember - 1.50.3-1 +- Update to 1.50.3 + +* Wed Nov 01 2017 Kalev Lember - 1.50.2-1 +- Update to 1.50.2 + +* Mon Oct 09 2017 Kalev Lember - 1.50.1-1 +- Update to 1.50.1 + +* Wed Sep 20 2017 Kalev Lember - 1.50.0-1 +- Update to 1.50.0 + +* Wed Aug 02 2017 Fedora Release Engineering - 1.49.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 1.49.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Sun Jun 25 2017 Kalev Lember - 1.49.3-1 +- Update to 1.49.3 + +* Tue Jun 13 2017 Bastien Nocera - 1.49.2-2 ++ gjs-1.49.2-2 +- Add fix for possible use-after-free crasher (bgo #781799) + +* Mon Jun 12 2017 Kalev Lember - 1.49.2-1 +- Update to 1.49.2 + +* Mon May 15 2017 Fedora Release Engineering - 1.48.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_27_Mass_Rebuild + +* Tue May 09 2017 Kalev Lember - 1.48.3-1 +- Update to 1.48.3 + +* Fri Apr 21 2017 Kalev Lember - 1.48.2-1 +- Update to 1.48.2 + +* Tue Apr 11 2017 Kalev Lember - 1.48.1-1 +- Update to 1.48.1 + +* Tue Mar 21 2017 Kalev Lember - 1.48.0-1 +- Update to 1.48.0 + +* Thu Mar 16 2017 Kalev Lember - 1.47.92-1 +- Update to 1.47.92 + +* Wed Mar 01 2017 Kalev Lember - 1.47.91-1 +- Update to 1.47.91 + +* Wed Feb 15 2017 Kalev Lember - 1.47.90-1 +- Update to 1.47.90 +- Switch to building with mozjs38 +- Set minimum required glib2 and gtk3 versions + +* Fri Feb 10 2017 Fedora Release Engineering - 1.47.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Sun Jan 15 2017 Kalev Lember - 1.47.4-1 +- Update to 1.47.4 +- Remove lib64 rpaths + +* Thu Jan 12 2017 Igor Gnatenko - 1.47.0-2 +- Rebuild for readline 7.x + +* Thu Nov 10 2016 Florian Müllner - 3.47.0-1 +- Update to 1.47.0 + +* Wed Sep 21 2016 Kalev Lember - 1.46.0-1 +- Update to 1.46.0 +- Don't set group tags +- Use make_install macro + +* Tue Jul 19 2016 Florian Müllner - 3.1.45.4-1 +- Update to 1.45.4 + +* Wed Feb 03 2016 Fedora Release Engineering - 1.45.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Fri Dec 18 2015 Kalev Lember - 1.45.3-1 +- Update to 1.45.3 +- Update project URL + +* Wed Oct 28 2015 Kalev Lember - 1.44.0-1 +- Update to 1.44.0 +- Use license macro for COPYING + +* Wed Jun 17 2015 Fedora Release Engineering - 1.43.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Sat May 02 2015 Kalev Lember - 1.43.3-2 +- Rebuilt for GCC 5 C++11 ABI change + +* Mon Dec 29 2014 Richard Hughes - 1.43.3-1 +- Update to 1.43.3 + +* Mon Sep 29 2014 Kalev Lember - 1.42.0-1 +- Update to 1.42.0 + +* Fri Sep 5 2014 Vadim Rutkovsky - 1.41.91-2 +- Build installed tests + +* Mon Sep 01 2014 Kalev Lember - 1.41.91-1 +- Update to 1.41.91 + +* Sat Aug 16 2014 Fedora Release Engineering - 1.41.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Tue Jul 22 2014 Kalev Lember - 1.41.4-1 +- Update to 1.41.4 + +* Thu Jun 26 2014 Richard Hughes - 1.41.3-1 +- Update to 1.41.3 + +* Sat Jun 07 2014 Fedora Release Engineering - 1.40.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue Apr 15 2014 Kalev Lember - 1.40.1-1 +- Update to 1.40.1 + +* Sat Apr 05 2014 Kalev Lember - 1.40.0-2 +- Tighten -devel deps +- Set minimum gobject-introspection version + +* Tue Mar 25 2014 Richard Hughes - 1.40.0-1 +- Update to 1.40.0 + +* Tue Mar 04 2014 Richard Hughes - 1.39.91-1 +- Update to 1.39.91 + +* Wed Feb 19 2014 Richard Hughes - 1.39.90-1 +- Update to 1.39.90 + +* Wed Feb 05 2014 Adam Williamson - 1.39.3-2 +- build against mozjs24 + +* Wed Jan 29 2014 Richard Hughes - 1.39.3-1 +- Update to 1.39.3 + +* Wed Nov 20 2013 Jasper St. Pierre - 1.39.0-1 +- Update to 1.39.0 + +* Wed Sep 25 2013 Kalev Lember - 1.38.1-1 +- Update to 1.38.1 + +* Wed Sep 25 2013 Kalev Lember - 1.38.0-1 +- Update to 1.38.0 + +* Thu Aug 22 2013 Kalev Lember - 1.37.6-1 +- Update to 1.37.6 + +* Sat Aug 03 2013 Fedora Release Engineering - 1.37.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Tue Jul 16 2013 Richard Hughes - 1.37.4-1 +- Update to 1.37.4 + +* Tue May 28 2013 Colin Walters - 1.37.1-1 +- Update to 1.37.1, and switch to mozjs17 + +* Mon Apr 29 2013 Kalev Lember - 1.36.1-1 +- Update to 1.36.1 + +* Tue Mar 26 2013 Kalev Lember - 1.36.0-1 +- Update to 1.36.0 + +* Thu Mar 21 2013 Kalev Lember - 1.35.9-1 +- Update to 1.35.9 + +* Wed Feb 20 2013 Richard Hughes - 1.35.8-1 +- Update to 1.35.8 + +* Wed Feb 13 2013 Fedora Release Engineering - 1.35.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Tue Jan 15 2013 Matthias Clasen - 1.35.4-1 +- Update to 1.35.4 + +* Thu Dec 20 2012 Kalev Lember - 1.35.3-1 +- Update to 1.35.3 + +* Tue Nov 20 2012 Richard Hughes - 1.35.2-1 +- Update to 1.35.2 + +* Tue Sep 25 2012 Kalev Lember - 1.34.0-1 +- Update to 1.34.0 + +* Wed Sep 19 2012 Richard Hughes - 1.33.14-1 +- Update to 1.33.14 + +* Thu Sep 06 2012 Richard Hughes - 1.33.10-1 +- Update to 1.33.10 + +* Tue Aug 21 2012 Richard Hughes - 1.33.9-1 +- Update to 1.33.9 + +* Thu Jul 19 2012 Fedora Release Engineering - 1.33.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Jul 17 2012 Richard Hughes - 1.33.4-1 +- Update to 1.33.4 + +* Thu Jul 5 2012 Peter Robinson - 1.33.3-2 +- Enable verbose build + +* Tue Jun 26 2012 Richard Hughes - 1.33.3-1 +- Update to 1.33.3 + +* Sat Jun 9 2012 Matthias Clasen - 1.33.2-2 +- Fix the build + +* Thu Jun 07 2012 Richard Hughes - 1.33.2-1 +- Update to 1.33.2 + +* Wed Mar 28 2012 Richard Hughes - 1.32.0-1 +- Update to 1.32.0 + +* Wed Mar 21 2012 Matthias Clasen - 1.31.22-1 +- Update to 1.31.22 + +* Mon Mar 5 2012 Matthias Clasen - 1.31.20-1 +- Update to 1.31.20 + +* Tue Feb 7 2012 Colin Walters - 1.31.10-2 +- Drop custom .gir/.typelib directories; see upstream commit + ea4d639eab307737870479b6573d5dab9fb2915a + +* Thu Jan 19 2012 Matthias Clasen - 1.31.10-1 +- 1.31.10 + +* Fri Jan 13 2012 Fedora Release Engineering - 1.31.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Dec 20 2011 Matthias Clasen 1.31.6-1 +- 1.31.6 + +* Fri Dec 02 2011 Karsten Hopp 1.31.0-2 +- fix crash on PPC, bugzilla 749604 + +* Wed Nov 2 2011 Matthias Clasen - 1.31.0-1 +- Update to 1.31.0 + +* Tue Sep 27 2011 Ray - 1.30.0-1 +- Update to 1.30.0 + +* Wed Sep 21 2011 Matthias Clasen 1.29.18-1 +- Update to 1.29.18 + +* Mon Sep 05 2011 Luis Bazan 1.29.17-2 +- mass rebuild + +* Tue Aug 30 2011 Matthias Clasen 1.29.17-1 +- Update to 1.29.17 + +* Thu Aug 18 2011 Matthias Clasen 1.29.16-1 +- Update to 1.29.16 + +* Thu Jul 28 2011 Colin Walters - 1.29.0-3 +- BR latest g-i to fix build issue + +* Mon Jun 27 2011 Adam Williamson - 1.29.0-2 +- build against js, not gecko (from f15 branch, but patch not needed) +- BR cairo-devel (also from f15) + +* Fri Jun 17 2011 Tomas Bzatek - 1.29.0-1 +- Update to 1.29.0 + +* Thu Apr 28 2011 Christopher Aillon - 0.7.14-3 +- Rebuild against newer gecko + +* Thu Apr 14 2011 Colin Walters - 0.7.14-2 +- BR readline; closes #696254 + +* Mon Apr 4 2011 Colin Walters - 0.7.14-1 +- Update to 0.7.14; fixes notification race condition on login + +* Tue Mar 22 2011 Christopher Aillon - 0.7.13-3 +- Rebuild against newer gecko + +* Fri Mar 18 2011 Christopher Aillon - 0.7.13-2 +- Rebuild against newer gecko + +* Thu Mar 10 2011 Colin Walters - 0.7.13-1 +- Update to 0.7.13 + +* Wed Mar 9 2011 Christopher Aillon - 0.7.11-3 +- Rebuild against newer gecko + +* Fri Feb 25 2011 Christopher Aillon - 0.7.11-2 +- Rebuild against newer gecko + +* Tue Feb 22 2011 Owen Taylor - 0.7.11-1 +- Update to 0.7.11 + +* Thu Feb 10 2011 Christopher Aillon - 0.7.10-4 +- Require gecko-libs instead of xulrunner + +* Wed Feb 9 2011 Colin Walters - 0.7.10-3 +- Add a hardcoded Requires on xulrunner; see comment + +* Tue Feb 08 2011 Fedora Release Engineering - 0.7.10-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Tue Jan 25 2011 Colin Walters - 0.7.10-1 +- New upstream release + +* Tue Jan 25 2011 Christopher Aillon - 0.7.9-3 +- Rebuild for new xulrunner + +* Fri Jan 14 2011 Christopher Aillon - 0.7.9-2 +- Rebuild for new xulrunner + +* Fri Jan 14 2011 Colin Walters - 0.7.9-1 +- 0.7.9 + +* Wed Jan 12 2011 Colin Walters - 0.7.8-1 +- Update to 0.7.8 +- Drop upstreamed patches +- BR latest g-i for GI_TYPE_TAG_UNICHAR + +* Wed Dec 29 2010 Dan Williams - 0.7.7-3 +- Work around Mozilla JS API changes + +* Wed Dec 22 2010 Colin Walters - 0.7.7-2 +- Remove rpath removal; we need an rpath on libmozjs, since + it's in a nonstandard directory. + +* Mon Nov 15 2010 Owen Taylor - 0.7.7-1 +- Update to 0.7.7 + +* Tue Nov 9 2010 Owen Taylor - 0.7.6-1 +- Update to 0.7.6 + +* Fri Oct 29 2010 Owen Taylor - 0.7.5-1 +- Update to 0.7.5 + +* Mon Oct 4 2010 Owen Taylor - 0.7.4-1 +- Update to 0.7.4 + +* Wed Jul 14 2010 Colin Walters - 0.7.1-3 +- Rebuild for new gobject-introspection + +* Mon Jul 12 2010 Colin Walters - 0.7.1-2 +- New upstream version +- Changes to allow builds from snapshots + +* Fri May 28 2010 Matthias Clasen 0.7-1 +- Update to 0.7 + +* Wed Mar 24 2010 Peter Robinson 0.6-1 +- New upstream 0.6 stable release + +* Sat Feb 20 2010 Peter Robinson 0.5-1 +- New upstream 0.5 release + +* Thu Jan 14 2010 Peter Robinson 0.5-0.1 +- Move to git snapshot to fix compile against xulrunner 1.9.2.1 + +* Thu Aug 27 2009 Peter Robinson 0.4-1 +- New upstream 0.4 release + +* Fri Aug 7 2009 Peter Robinson 0.3-2 +- Updates from the review request + +* Wed Jul 8 2009 Peter Robinson 0.3-1 +- New upstream release. Clarify licensing for review + +* Sat Jun 27 2009 Peter Robinson 0.2-1 +- Initial packaging