summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaikumar Ganesh <jaikumar@google.com>2009-06-04 16:14:32 -0700
committerJaikumar Ganesh <jaikumar@google.com>2009-06-04 16:47:29 -0700
commitbb28d819383d1cbebb355153d2f53c858288835f (patch)
tree20e23fdc7346b18789e28927cda9c366b8b2e432
parent3c3776dce32610185914957072ca66cfff34d7bb (diff)
downloadglib-bb28d819383d1cbebb355153d2f53c858288835f.tar.gz
Android specific changes.
Added Android.mk fies, delete files.
-rwxr-xr-xAndroid.mk20
-rw-r--r--glib.h (renamed from glib/glib.h)0
-rwxr-xr-xglib/Android.mk45
-rwxr-xr-xglib/abicheck.sh13
-rw-r--r--glib/gasyncqueue.c666
-rw-r--r--glib/gbacktrace.c308
-rw-r--r--glib/gbase64.c423
-rw-r--r--glib/gbookmarkfile.c3709
-rw-r--r--glib/gcache.c197
-rw-r--r--glib/gchecksum.c1439
-rw-r--r--glib/gcompletion.c350
-rw-r--r--glib/gconvert.c24
-rw-r--r--glib/gdate.c1905
-rwxr-xr-xglib/gen-script-table.pl119
-rwxr-xr-xglib/gen-unicode-tables.pl1303
-rw-r--r--glib/ghook.c638
-rw-r--r--glib/giowin32.c2191
-rw-r--r--glib/glib-mirroring-tab/Makefile11
-rw-r--r--glib/glib-mirroring-tab/gen-mirroring-tab.c232
-rw-r--r--glib/glib-mirroring-tab/packtab.c424
-rw-r--r--glib/glib-mirroring-tab/packtab.h50
-rw-r--r--glib/glib.rc.in30
-rw-r--r--glib/glib.symbols1655
-rw-r--r--glib/glibintl.h2
-rw-r--r--glib/gmain.c4
-rw-r--r--glib/gmappedfile.c278
-rw-r--r--glib/gmarkup.c2996
-rw-r--r--glib/gnode.c1165
-rw-r--r--glib/gprimes.c90
-rw-r--r--glib/gqueue.c1013
-rw-r--r--glib/gregex.c2762
-rw-r--r--glib/grel.c484
-rw-r--r--glib/gscanner.c1767
-rw-r--r--glib/gsequence.c1750
-rw-r--r--glib/gshell.c673
-rw-r--r--glib/gspawn-win32-helper.c333
-rw-r--r--glib/gspawn-win32.c1494
-rw-r--r--glib/gspawn.c1671
-rw-r--r--glib/gstrfuncs.c6
-rwxr-xr-xglib/gtester-report358
-rw-r--r--glib/gtester.c711
-rw-r--r--glib/gthreadpool.c945
-rw-r--r--glib/gtree.c1290
-rw-r--r--glib/gunibreak.c66
-rw-r--r--glib/gunicollate.c679
-rw-r--r--glib/gurifuncs.c245
-rw-r--r--glib/gutf8.c11
-rw-r--r--glib/gutils.c7
-rw-r--r--glib/gwin32.c600
-rw-r--r--glib/libcharset/.gitignore3
-rw-r--r--glib/libcharset/Makefile.am64
-rw-r--r--glib/libcharset/README46
-rw-r--r--glib/libcharset/codeset.m421
-rwxr-xr-xglib/libcharset/config.charset640
-rw-r--r--glib/libcharset/glibc21.m430
-rw-r--r--glib/libcharset/libcharset-glib.patch77
-rw-r--r--glib/libcharset/libcharset.h46
-rw-r--r--glib/libcharset/localcharset.c465
-rw-r--r--glib/libcharset/localcharset.h43
-rwxr-xr-xglib/libcharset/make-patch.sh28
-rw-r--r--glib/libcharset/ref-add.sin31
-rw-r--r--glib/libcharset/ref-del.sin26
-rwxr-xr-xglib/libcharset/update.sh33
-rw-r--r--glib/makefile.msc.in141
-rwxr-xr-xglib/makegalias.pl136
-rw-r--r--glib/pcre/COPYING5
-rw-r--r--glib/pcre/Makefile.am66
-rw-r--r--glib/pcre/makefile.msc30
-rw-r--r--glib/pcre/pcre.h293
-rw-r--r--glib/pcre/pcre_chartables.c198
-rw-r--r--glib/pcre/pcre_compile.c6258
-rw-r--r--glib/pcre/pcre_config.c128
-rw-r--r--glib/pcre/pcre_dfa_exec.c2920
-rw-r--r--glib/pcre/pcre_exec.c4998
-rw-r--r--glib/pcre/pcre_fullinfo.c165
-rw-r--r--glib/pcre/pcre_get.c465
-rw-r--r--glib/pcre/pcre_globals.c57
-rw-r--r--glib/pcre/pcre_info.c93
-rw-r--r--glib/pcre/pcre_internal.h1157
-rw-r--r--glib/pcre/pcre_maketables.c143
-rw-r--r--glib/pcre/pcre_newline.c164
-rw-r--r--glib/pcre/pcre_ord2utf8.c87
-rw-r--r--glib/pcre/pcre_refcount.c82
-rw-r--r--glib/pcre/pcre_study.c588
-rw-r--r--glib/pcre/pcre_tables.c356
-rw-r--r--glib/pcre/pcre_try_flipped.c137
-rw-r--r--glib/pcre/pcre_ucp_searchfuncs.c81
-rw-r--r--glib/pcre/pcre_valid_utf8.c13
-rw-r--r--glib/pcre/pcre_version.c90
-rw-r--r--glib/pcre/pcre_xclass.c146
-rw-r--r--glib/pcre/ucp.h144
-rw-r--r--glib/pcre/ucpinternal.h92
-rwxr-xr-xglib/pltcheck.sh25
-rw-r--r--glib/tests/.gitignore11
-rw-r--r--glib/tests/4096-random-bytes45
-rw-r--r--glib/tests/Makefile.am62
-rw-r--r--glib/tests/array-test.c133
-rw-r--r--glib/tests/fileutils.c508
-rw-r--r--glib/tests/keyfile.c1262
-rw-r--r--glib/tests/markup-subparser.c377
-rw-r--r--glib/tests/option-context.c1794
-rw-r--r--glib/tests/printf.c711
-rw-r--r--glib/tests/rand.c160
-rw-r--r--glib/tests/strfuncs.c1241
-rw-r--r--glib/tests/string.c394
-rw-r--r--glib/tests/testing.c214
-rw-r--r--glib/update-pcre/Makefile.am10
-rw-r--r--glib/update-pcre/Makefile.am-130
-rw-r--r--glib/update-pcre/Makefile.am-210
-rw-r--r--glib/update-pcre/digitab.patch133
-rw-r--r--glib/update-pcre/make_utt.py57
-rw-r--r--glib/update-pcre/memory.patch87
-rw-r--r--glib/update-pcre/pcre_ucp_searchfuncs.c126
-rw-r--r--glib/update-pcre/pcre_valid_utf8.c13
-rw-r--r--glib/update-pcre/table-reduction.patch269
-rw-r--r--glib/update-pcre/ucp.patch141
-rw-r--r--glib/update-pcre/update.sh159
-rw-r--r--glib/update-pcre/utt.patch30
-rw-r--r--glib/win_iconv.c1956
119 files changed, 115 insertions, 67781 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100755
index 000000000..456efddcd
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+ifneq ($(TARGET_SIMULATOR),true)
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+ include $(all-subdir-makefiles)
+endif
+endif
diff --git a/glib/glib.h b/glib.h
index 000d41768..000d41768 100644
--- a/glib/glib.h
+++ b/glib.h
diff --git a/glib/Android.mk b/glib/Android.mk
new file mode 100755
index 000000000..975fe1e2b
--- /dev/null
+++ b/glib/Android.mk
@@ -0,0 +1,45 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ gdir.c \
+ gerror.c \
+ giochannel.c \
+ gkeyfile.c \
+ gmain.c \
+ gmem.c \
+ goption.c \
+ gslice.c \
+ gslist.c \
+ gstring.c \
+ gstrfuncs.c \
+ gtimer.c \
+ giounix.c \
+ gmessages.c \
+ gutf8.c \
+ gfileutils.c \
+ gconvert.c \
+ gdataset.c \
+ gtestutils.c \
+ ghash.c \
+ glist.c \
+ gthread.c \
+ garray.c \
+ gutils.c \
+ gatomic.c \
+ gprintf.c \
+ gpattern.c \
+ guniprop.c \
+ gpoll.c \
+ grand.c \
+ gunidecomp.c \
+ gqsort.c \
+ gstdio.c
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/../ \
+ $(LOCAL_PATH)
+
+LOCAL_MODULE:=libglib_static
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/glib/abicheck.sh b/glib/abicheck.sh
deleted file mode 100755
index ce9a96672..000000000
--- a/glib/abicheck.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#! /bin/sh
-
-egrep '^#([^i]|if).*[^\]$' "${top_builddir:-..}/glibconfig.h" > glibconfig.cpp
-
-INCLUDES="-include ${top_builddir:-..}/config.h"
-INCLUDES="$INCLUDES -include glibconfig.cpp $GLIB_DEBUG_FLAGS"
-
-cpp -P -DINCLUDE_INTERNAL_SYMBOLS -DINCLUDE_VARIABLES -DG_STDIO_NO_WRAP_ON_UNIX -DALL_FILES $INCLUDES "${srcdir:-.}/glib.symbols" | sed -e '/^$/d' -e 's/ G_GNUC.*$//' -e 's/ PRIVATE$//' | sort > expected-abi
-rm -f glibconfig.cpp
-
-nm -D -g --defined-only .libs/libglib-2.0.so | cut -d ' ' -f 3 | sort > actual-abi
-
-diff -u expected-abi actual-abi && rm -f expected-abi actual-abi
diff --git a/glib/gasyncqueue.c b/glib/gasyncqueue.c
deleted file mode 100644
index 65e95a8de..000000000
--- a/glib/gasyncqueue.c
+++ /dev/null
@@ -1,666 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * GAsyncQueue: asynchronous queue implementation, based on Gqueue.
- * Copyright (C) 2000 Sebastian Wilhelmi; University of Karlsruhe
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#include "glib.h"
-#include "galias.h"
-
-
-struct _GAsyncQueue
-{
- GMutex *mutex;
- GCond *cond;
- GQueue *queue;
- GDestroyNotify item_free_func;
- guint waiting_threads;
- gint32 ref_count;
-};
-
-typedef struct {
- GCompareDataFunc func;
- gpointer user_data;
-} SortData;
-
-/**
- * g_async_queue_new:
- *
- * Creates a new asynchronous queue with the initial reference count of 1.
- *
- * Return value: the new #GAsyncQueue.
- **/
-GAsyncQueue*
-g_async_queue_new (void)
-{
- GAsyncQueue* retval = g_new (GAsyncQueue, 1);
- retval->mutex = g_mutex_new ();
- retval->cond = NULL;
- retval->queue = g_queue_new ();
- retval->waiting_threads = 0;
- retval->ref_count = 1;
- retval->item_free_func = NULL;
- return retval;
-}
-
-/**
- * g_async_queue_new_full:
- * @item_free_func: function to free queue elements
- *
- * Creates a new asynchronous queue with an initial reference count of 1 and
- * sets up a destroy notify function that is used to free any remaining
- * queue items when the queue is destroyed after the final unref.
- *
- * Return value: the new #GAsyncQueue.
- *
- * Since: 2.16
- **/
-GAsyncQueue*
-g_async_queue_new_full (GDestroyNotify item_free_func)
-{
- GAsyncQueue *async_queue = g_async_queue_new ();
- async_queue->item_free_func = item_free_func;
- return async_queue;
-}
-
-/**
- * g_async_queue_ref:
- * @queue: a #GAsyncQueue.
- *
- * Increases the reference count of the asynchronous @queue by 1. You
- * do not need to hold the lock to call this function.
- *
- * Returns: the @queue that was passed in (since 2.6)
- **/
-GAsyncQueue *
-g_async_queue_ref (GAsyncQueue *queue)
-{
- g_return_val_if_fail (queue, NULL);
- g_return_val_if_fail (g_atomic_int_get (&queue->ref_count) > 0, NULL);
-
- g_atomic_int_inc (&queue->ref_count);
-
- return queue;
-}
-
-/**
- * g_async_queue_ref_unlocked:
- * @queue: a #GAsyncQueue.
- *
- * Increases the reference count of the asynchronous @queue by 1.
- *
- * @Deprecated: Since 2.8, reference counting is done atomically
- * so g_async_queue_ref() can be used regardless of the @queue's
- * lock.
- **/
-void
-g_async_queue_ref_unlocked (GAsyncQueue *queue)
-{
- g_return_if_fail (queue);
- g_return_if_fail (g_atomic_int_get (&queue->ref_count) > 0);
-
- g_atomic_int_inc (&queue->ref_count);
-}
-
-/**
- * g_async_queue_unref_and_unlock:
- * @queue: a #GAsyncQueue.
- *
- * Decreases the reference count of the asynchronous @queue by 1 and
- * releases the lock. This function must be called while holding the
- * @queue's lock. If the reference count went to 0, the @queue will be
- * destroyed and the memory allocated will be freed.
- *
- * @Deprecated: Since 2.8, reference counting is done atomically
- * so g_async_queue_unref() can be used regardless of the @queue's
- * lock.
- **/
-void
-g_async_queue_unref_and_unlock (GAsyncQueue *queue)
-{
- g_return_if_fail (queue);
- g_return_if_fail (g_atomic_int_get (&queue->ref_count) > 0);
-
- g_mutex_unlock (queue->mutex);
- g_async_queue_unref (queue);
-}
-
-/**
- * g_async_queue_unref:
- * @queue: a #GAsyncQueue.
- *
- * Decreases the reference count of the asynchronous @queue by 1. If
- * the reference count went to 0, the @queue will be destroyed and the
- * memory allocated will be freed. So you are not allowed to use the
- * @queue afterwards, as it might have disappeared. You do not need to
- * hold the lock to call this function.
- **/
-void
-g_async_queue_unref (GAsyncQueue *queue)
-{
- g_return_if_fail (queue);
- g_return_if_fail (g_atomic_int_get (&queue->ref_count) > 0);
-
- if (g_atomic_int_dec_and_test (&queue->ref_count))
- {
- g_return_if_fail (queue->waiting_threads == 0);
- g_mutex_free (queue->mutex);
- if (queue->cond)
- g_cond_free (queue->cond);
- if (queue->item_free_func)
- g_queue_foreach (queue->queue, (GFunc) queue->item_free_func, NULL);
- g_queue_free (queue->queue);
- g_free (queue);
- }
-}
-
-/**
- * g_async_queue_lock:
- * @queue: a #GAsyncQueue.
- *
- * Acquires the @queue's lock. After that you can only call the
- * <function>g_async_queue_*_unlocked()</function> function variants on that
- * @queue. Otherwise it will deadlock.
- **/
-void
-g_async_queue_lock (GAsyncQueue *queue)
-{
- g_return_if_fail (queue);
- g_return_if_fail (g_atomic_int_get (&queue->ref_count) > 0);
-
- g_mutex_lock (queue->mutex);
-}
-
-/**
- * g_async_queue_unlock:
- * @queue: a #GAsyncQueue.
- *
- * Releases the queue's lock.
- **/
-void
-g_async_queue_unlock (GAsyncQueue *queue)
-{
- g_return_if_fail (queue);
- g_return_if_fail (g_atomic_int_get (&queue->ref_count) > 0);
-
- g_mutex_unlock (queue->mutex);
-}
-
-/**
- * g_async_queue_push:
- * @queue: a #GAsyncQueue.
- * @data: @data to push into the @queue.
- *
- * Pushes the @data into the @queue. @data must not be %NULL.
- **/
-void
-g_async_queue_push (GAsyncQueue* queue, gpointer data)
-{
- g_return_if_fail (queue);
- g_return_if_fail (g_atomic_int_get (&queue->ref_count) > 0);
- g_return_if_fail (data);
-
- g_mutex_lock (queue->mutex);
- g_async_queue_push_unlocked (queue, data);
- g_mutex_unlock (queue->mutex);
-}
-
-/**
- * g_async_queue_push_unlocked:
- * @queue: a #GAsyncQueue.
- * @data: @data to push into the @queue.
- *
- * Pushes the @data into the @queue. @data must not be %NULL. This
- * function must be called while holding the @queue's lock.
- **/
-void
-g_async_queue_push_unlocked (GAsyncQueue* queue, gpointer data)
-{
- g_return_if_fail (queue);
- g_return_if_fail (g_atomic_int_get (&queue->ref_count) > 0);
- g_return_if_fail (data);
-
- g_queue_push_head (queue->queue, data);
- if (queue->waiting_threads > 0)
- g_cond_signal (queue->cond);
-}
-
-/**
- * g_async_queue_push_sorted:
- * @queue: a #GAsyncQueue
- * @data: the @data to push into the @queue
- * @func: the #GCompareDataFunc is used to sort @queue. This function
- * is passed two elements of the @queue. The function should return
- * 0 if they are equal, a negative value if the first element
- * should be higher in the @queue or a positive value if the first
- * element should be lower in the @queue than the second element.
- * @user_data: user data passed to @func.
- *
- * Inserts @data into @queue using @func to determine the new
- * position.
- *
- * This function requires that the @queue is sorted before pushing on
- * new elements.
- *
- * This function will lock @queue before it sorts the queue and unlock
- * it when it is finished.
- *
- * For an example of @func see g_async_queue_sort().
- *
- * Since: 2.10
- **/
-void
-g_async_queue_push_sorted (GAsyncQueue *queue,
- gpointer data,
- GCompareDataFunc func,
- gpointer user_data)
-{
- g_return_if_fail (queue != NULL);
-
- g_mutex_lock (queue->mutex);
- g_async_queue_push_sorted_unlocked (queue, data, func, user_data);
- g_mutex_unlock (queue->mutex);
-}
-
-static gint
-g_async_queue_invert_compare (gpointer v1,
- gpointer v2,
- SortData *sd)
-{
- return -sd->func (v1, v2, sd->user_data);
-}
-
-/**
- * g_async_queue_push_sorted_unlocked:
- * @queue: a #GAsyncQueue
- * @data: the @data to push into the @queue
- * @func: the #GCompareDataFunc is used to sort @queue. This function
- * is passed two elements of the @queue. The function should return
- * 0 if they are equal, a negative value if the first element
- * should be higher in the @queue or a positive value if the first
- * element should be lower in the @queue than the second element.
- * @user_data: user data passed to @func.
- *
- * Inserts @data into @queue using @func to determine the new
- * position.
- *
- * This function requires that the @queue is sorted before pushing on
- * new elements.
- *
- * This function is called while holding the @queue's lock.
- *
- * For an example of @func see g_async_queue_sort().
- *
- * Since: 2.10
- **/
-void
-g_async_queue_push_sorted_unlocked (GAsyncQueue *queue,
- gpointer data,
- GCompareDataFunc func,
- gpointer user_data)
-{
- SortData sd;
-
- g_return_if_fail (queue != NULL);
-
- sd.func = func;
- sd.user_data = user_data;
-
- g_queue_insert_sorted (queue->queue,
- data,
- (GCompareDataFunc)g_async_queue_invert_compare,
- &sd);
- if (queue->waiting_threads > 0)
- g_cond_signal (queue->cond);
-}
-
-static gpointer
-g_async_queue_pop_intern_unlocked (GAsyncQueue *queue,
- gboolean try,
- GTimeVal *end_time)
-{
- gpointer retval;
-
- if (!g_queue_peek_tail_link (queue->queue))
- {
- if (try)
- return NULL;
-
- if (!queue->cond)
- queue->cond = g_cond_new ();
-
- if (!end_time)
- {
- queue->waiting_threads++;
- while (!g_queue_peek_tail_link (queue->queue))
- g_cond_wait (queue->cond, queue->mutex);
- queue->waiting_threads--;
- }
- else
- {
- queue->waiting_threads++;
- while (!g_queue_peek_tail_link (queue->queue))
- if (!g_cond_timed_wait (queue->cond, queue->mutex, end_time))
- break;
- queue->waiting_threads--;
- if (!g_queue_peek_tail_link (queue->queue))
- return NULL;
- }
- }
-
- retval = g_queue_pop_tail (queue->queue);
-
- g_assert (retval);
-
- return retval;
-}
-
-/**
- * g_async_queue_pop:
- * @queue: a #GAsyncQueue.
- *
- * Pops data from the @queue. This function blocks until data become
- * available.
- *
- * Return value: data from the queue.
- **/
-gpointer
-g_async_queue_pop (GAsyncQueue* queue)
-{
- gpointer retval;
-
- g_return_val_if_fail (queue, NULL);
- g_return_val_if_fail (g_atomic_int_get (&queue->ref_count) > 0, NULL);
-
- g_mutex_lock (queue->mutex);
- retval = g_async_queue_pop_intern_unlocked (queue, FALSE, NULL);
- g_mutex_unlock (queue->mutex);
-
- return retval;
-}
-
-/**
- * g_async_queue_pop_unlocked:
- * @queue: a #GAsyncQueue.
- *
- * Pops data from the @queue. This function blocks until data become
- * available. This function must be called while holding the @queue's
- * lock.
- *
- * Return value: data from the queue.
- **/
-gpointer
-g_async_queue_pop_unlocked (GAsyncQueue* queue)
-{
- g_return_val_if_fail (queue, NULL);
- g_return_val_if_fail (g_atomic_int_get (&queue->ref_count) > 0, NULL);
-
- return g_async_queue_pop_intern_unlocked (queue, FALSE, NULL);
-}
-
-/**
- * g_async_queue_try_pop:
- * @queue: a #GAsyncQueue.
- *
- * Tries to pop data from the @queue. If no data is available, %NULL is
- * returned.
- *
- * Return value: data from the queue or %NULL, when no data is
- * available immediately.
- **/
-gpointer
-g_async_queue_try_pop (GAsyncQueue* queue)
-{
- gpointer retval;
-
- g_return_val_if_fail (queue, NULL);
- g_return_val_if_fail (g_atomic_int_get (&queue->ref_count) > 0, NULL);
-
- g_mutex_lock (queue->mutex);
- retval = g_async_queue_pop_intern_unlocked (queue, TRUE, NULL);
- g_mutex_unlock (queue->mutex);
-
- return retval;
-}
-
-/**
- * g_async_queue_try_pop_unlocked:
- * @queue: a #GAsyncQueue.
- *
- * Tries to pop data from the @queue. If no data is available, %NULL is
- * returned. This function must be called while holding the @queue's
- * lock.
- *
- * Return value: data from the queue or %NULL, when no data is
- * available immediately.
- **/
-gpointer
-g_async_queue_try_pop_unlocked (GAsyncQueue* queue)
-{
- g_return_val_if_fail (queue, NULL);
- g_return_val_if_fail (g_atomic_int_get (&queue->ref_count) > 0, NULL);
-
- return g_async_queue_pop_intern_unlocked (queue, TRUE, NULL);
-}
-
-/**
- * g_async_queue_timed_pop:
- * @queue: a #GAsyncQueue.
- * @end_time: a #GTimeVal, determining the final time.
- *
- * Pops data from the @queue. If no data is received before @end_time,
- * %NULL is returned.
- *
- * To easily calculate @end_time a combination of g_get_current_time()
- * and g_time_val_add() can be used.
- *
- * Return value: data from the queue or %NULL, when no data is
- * received before @end_time.
- **/
-gpointer
-g_async_queue_timed_pop (GAsyncQueue* queue, GTimeVal *end_time)
-{
- gpointer retval;
-
- g_return_val_if_fail (queue, NULL);
- g_return_val_if_fail (g_atomic_int_get (&queue->ref_count) > 0, NULL);
-
- g_mutex_lock (queue->mutex);
- retval = g_async_queue_pop_intern_unlocked (queue, FALSE, end_time);
- g_mutex_unlock (queue->mutex);
-
- return retval;
-}
-
-/**
- * g_async_queue_timed_pop_unlocked:
- * @queue: a #GAsyncQueue.
- * @end_time: a #GTimeVal, determining the final time.
- *
- * Pops data from the @queue. If no data is received before @end_time,
- * %NULL is returned. This function must be called while holding the
- * @queue's lock.
- *
- * To easily calculate @end_time a combination of g_get_current_time()
- * and g_time_val_add() can be used.
- *
- * Return value: data from the queue or %NULL, when no data is
- * received before @end_time.
- **/
-gpointer
-g_async_queue_timed_pop_unlocked (GAsyncQueue* queue, GTimeVal *end_time)
-{
- g_return_val_if_fail (queue, NULL);
- g_return_val_if_fail (g_atomic_int_get (&queue->ref_count) > 0, NULL);
-
- return g_async_queue_pop_intern_unlocked (queue, FALSE, end_time);
-}
-
-/**
- * g_async_queue_length:
- * @queue: a #GAsyncQueue.
- *
- * Returns the length of the queue, negative values mean waiting
- * threads, positive values mean available entries in the
- * @queue. Actually this function returns the number of data items in
- * the queue minus the number of waiting threads. Thus a return value
- * of 0 could mean 'n' entries in the queue and 'n' thread waiting.
- * That can happen due to locking of the queue or due to
- * scheduling.
- *
- * Return value: the length of the @queue.
- **/
-gint
-g_async_queue_length (GAsyncQueue* queue)
-{
- gint retval;
-
- g_return_val_if_fail (queue, 0);
- g_return_val_if_fail (g_atomic_int_get (&queue->ref_count) > 0, 0);
-
- g_mutex_lock (queue->mutex);
- retval = queue->queue->length - queue->waiting_threads;
- g_mutex_unlock (queue->mutex);
-
- return retval;
-}
-
-/**
- * g_async_queue_length_unlocked:
- * @queue: a #GAsyncQueue.
- *
- * Returns the length of the queue, negative values mean waiting
- * threads, positive values mean available entries in the
- * @queue. Actually this function returns the number of data items in
- * the queue minus the number of waiting threads. Thus a return value
- * of 0 could mean 'n' entries in the queue and 'n' thread waiting.
- * That can happen due to locking of the queue or due to
- * scheduling. This function must be called while holding the @queue's
- * lock.
- *
- * Return value: the length of the @queue.
- **/
-gint
-g_async_queue_length_unlocked (GAsyncQueue* queue)
-{
- g_return_val_if_fail (queue, 0);
- g_return_val_if_fail (g_atomic_int_get (&queue->ref_count) > 0, 0);
-
- return queue->queue->length - queue->waiting_threads;
-}
-
-/**
- * g_async_queue_sort:
- * @queue: a #GAsyncQueue
- * @func: the #GCompareDataFunc is used to sort @queue. This
- * function is passed two elements of the @queue. The function
- * should return 0 if they are equal, a negative value if the
- * first element should be higher in the @queue or a positive
- * value if the first element should be lower in the @queue than
- * the second element.
- * @user_data: user data passed to @func
- *
- * Sorts @queue using @func.
- *
- * This function will lock @queue before it sorts the queue and unlock
- * it when it is finished.
- *
- * If you were sorting a list of priority numbers to make sure the
- * lowest priority would be at the top of the queue, you could use:
- * |[
- * gint32 id1;
- * gint32 id2;
- *
- * id1 = GPOINTER_TO_INT (element1);
- * id2 = GPOINTER_TO_INT (element2);
- *
- * return (id1 > id2 ? +1 : id1 == id2 ? 0 : -1);
- * ]|
- *
- * Since: 2.10
- **/
-void
-g_async_queue_sort (GAsyncQueue *queue,
- GCompareDataFunc func,
- gpointer user_data)
-{
- g_return_if_fail (queue != NULL);
- g_return_if_fail (func != NULL);
-
- g_mutex_lock (queue->mutex);
- g_async_queue_sort_unlocked (queue, func, user_data);
- g_mutex_unlock (queue->mutex);
-}
-
-/**
- * g_async_queue_sort_unlocked:
- * @queue: a #GAsyncQueue
- * @func: the #GCompareDataFunc is used to sort @queue. This
- * function is passed two elements of the @queue. The function
- * should return 0 if they are equal, a negative value if the
- * first element should be higher in the @queue or a positive
- * value if the first element should be lower in the @queue than
- * the second element.
- * @user_data: user data passed to @func
- *
- * Sorts @queue using @func.
- *
- * This function is called while holding the @queue's lock.
- *
- * Since: 2.10
- **/
-void
-g_async_queue_sort_unlocked (GAsyncQueue *queue,
- GCompareDataFunc func,
- gpointer user_data)
-{
- SortData sd;
-
- g_return_if_fail (queue != NULL);
- g_return_if_fail (func != NULL);
-
- sd.func = func;
- sd.user_data = user_data;
-
- g_queue_sort (queue->queue,
- (GCompareDataFunc)g_async_queue_invert_compare,
- &sd);
-}
-
-/*
- * Private API
- */
-
-GMutex*
-_g_async_queue_get_mutex (GAsyncQueue* queue)
-{
- g_return_val_if_fail (queue, NULL);
- g_return_val_if_fail (g_atomic_int_get (&queue->ref_count) > 0, NULL);
-
- return queue->mutex;
-}
-
-#define __G_ASYNCQUEUE_C__
-#include "galiasdef.c"
diff --git a/glib/gbacktrace.c b/glib/gbacktrace.c
deleted file mode 100644
index 238d9cf97..000000000
--- a/glib/gbacktrace.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * MT safe ; except for g_on_error_stack_trace, but who wants thread safety
- * then
- */
-
-#include "config.h"
-
-#include <signal.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "glib.h"
-#include "gprintfint.h"
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_TIMES_H
-#include <sys/times.h>
-#endif
-#include <sys/types.h>
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif /* HAVE_SYS_SELECT_H */
-
-#include <string.h> /* for bzero on BSD systems */
-
-#ifdef G_OS_WIN32
-# define STRICT /* Strict typing, please */
-# define _WIN32_WINDOWS 0x0401 /* to get IsDebuggerPresent */
-# include <windows.h>
-# undef STRICT
-#endif
-
-#ifndef NO_FD_SET
-# define SELECT_MASK fd_set
-#else
-# if defined(_IBMR2)
-# define SELECT_MASK void
-# else
-# define SELECT_MASK int
-# endif
-#endif
-
-#include "galias.h"
-
-#ifndef G_OS_WIN32
-static void stack_trace (char **args);
-#endif
-
-extern volatile gboolean glib_on_error_halt;
-volatile gboolean glib_on_error_halt = TRUE;
-
-void
-g_on_error_query (const gchar *prg_name)
-{
-#ifndef G_OS_WIN32
- static const gchar * const query1 = "[E]xit, [H]alt";
- static const gchar * const query2 = ", show [S]tack trace";
- static const gchar * const query3 = " or [P]roceed";
- gchar buf[16];
-
- if (!prg_name)
- prg_name = g_get_prgname ();
-
- retry:
-
- if (prg_name)
- _g_fprintf (stdout,
- "%s (pid:%u): %s%s%s: ",
- prg_name,
- (guint) getpid (),
- query1,
- query2,
- query3);
- else
- _g_fprintf (stdout,
- "(process:%u): %s%s: ",
- (guint) getpid (),
- query1,
- query3);
- fflush (stdout);
-
- if (isatty(0) && isatty(1))
- fgets (buf, 8, stdin);
- else
- strcpy (buf, "E\n");
-
- if ((buf[0] == 'E' || buf[0] == 'e')
- && buf[1] == '\n')
- _exit (0);
- else if ((buf[0] == 'P' || buf[0] == 'p')
- && buf[1] == '\n')
- return;
- else if (prg_name
- && (buf[0] == 'S' || buf[0] == 's')
- && buf[1] == '\n')
- {
- g_on_error_stack_trace (prg_name);
- goto retry;
- }
- else if ((buf[0] == 'H' || buf[0] == 'h')
- && buf[1] == '\n')
- {
- while (glib_on_error_halt)
- ;
- glib_on_error_halt = TRUE;
- return;
- }
- else
- goto retry;
-#else
- if (!prg_name)
- prg_name = g_get_prgname ();
-
- MessageBox (NULL, "g_on_error_query called, program terminating",
- (prg_name && *prg_name) ? prg_name : NULL,
- MB_OK|MB_ICONERROR);
- _exit(0);
-#endif
-}
-
-void
-g_on_error_stack_trace (const gchar *prg_name)
-{
-#if defined(G_OS_UNIX) || defined(G_OS_BEOS)
- pid_t pid;
- gchar buf[16];
- gchar *args[4] = { "gdb", NULL, NULL, NULL };
- int status;
-
- if (!prg_name)
- return;
-
- _g_sprintf (buf, "%u", (guint) getpid ());
-
- args[1] = (gchar*) prg_name;
- args[2] = buf;
-
- pid = fork ();
- if (pid == 0)
- {
- stack_trace (args);
- _exit (0);
- }
- else if (pid == (pid_t) -1)
- {
- perror ("unable to fork gdb");
- return;
- }
-
- waitpid (pid, &status, 0);
-#else
- if (IsDebuggerPresent ())
- G_BREAKPOINT ();
- else
- abort ();
-#endif
-}
-
-#ifndef G_OS_WIN32
-
-static gboolean stack_trace_done = FALSE;
-
-static void
-stack_trace_sigchld (int signum)
-{
- stack_trace_done = TRUE;
-}
-
-static void
-stack_trace (char **args)
-{
- pid_t pid;
- int in_fd[2];
- int out_fd[2];
- SELECT_MASK fdset;
- SELECT_MASK readset;
- struct timeval tv;
- int sel, idx, state;
- char buffer[256];
- char c;
-
- stack_trace_done = FALSE;
- signal (SIGCHLD, stack_trace_sigchld);
-
- if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
- {
- perror ("unable to open pipe");
- _exit (0);
- }
-
- pid = fork ();
- if (pid == 0)
- {
- close (0); dup (in_fd[0]); /* set the stdin to the in pipe */
- close (1); dup (out_fd[1]); /* set the stdout to the out pipe */
- close (2); dup (out_fd[1]); /* set the stderr to the out pipe */
-
- execvp (args[0], args); /* exec gdb */
- perror ("exec failed");
- _exit (0);
- }
- else if (pid == (pid_t) -1)
- {
- perror ("unable to fork");
- _exit (0);
- }
-
- FD_ZERO (&fdset);
- FD_SET (out_fd[0], &fdset);
-
- write (in_fd[1], "backtrace\n", 10);
- write (in_fd[1], "p x = 0\n", 8);
- write (in_fd[1], "quit\n", 5);
-
- idx = 0;
- state = 0;
-
- while (1)
- {
- readset = fdset;
- tv.tv_sec = 1;
- tv.tv_usec = 0;
-
- sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
- if (sel == -1)
- break;
-
- if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
- {
- if (read (out_fd[0], &c, 1))
- {
- switch (state)
- {
- case 0:
- if (c == '#')
- {
- state = 1;
- idx = 0;
- buffer[idx++] = c;
- }
- break;
- case 1:
- buffer[idx++] = c;
- if ((c == '\n') || (c == '\r'))
- {
- buffer[idx] = 0;
- _g_fprintf (stdout, "%s", buffer);
- state = 0;
- idx = 0;
- }
- break;
- default:
- break;
- }
- }
- }
- else if (stack_trace_done)
- break;
- }
-
- close (in_fd[0]);
- close (in_fd[1]);
- close (out_fd[0]);
- close (out_fd[1]);
- _exit (0);
-}
-
-#endif /* !G_OS_WIN32 */
-
-#define __G_BACKTRACE_C__
-#include "galiasdef.c"
diff --git a/glib/gbase64.c b/glib/gbase64.c
deleted file mode 100644
index bfdc76aa5..000000000
--- a/glib/gbase64.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/* gbase64.c - Base64 encoding/decoding
- *
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
- * Copyright (C) 2000-2003 Ximian Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * This is based on code in camel, written by:
- * Michael Zucchi <notzed@ximian.com>
- * Jeffrey Stedfast <fejj@ximian.com>
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include "gbase64.h"
-#include "glib.h"
-#include "glibintl.h"
-
-#include "galias.h"
-
-static const char base64_alphabet[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-/**
- * g_base64_encode_step:
- * @in: the binary data to encode
- * @len: the length of @in
- * @break_lines: whether to break long lines
- * @out: pointer to destination buffer
- * @state: Saved state between steps, initialize to 0
- * @save: Saved state between steps, initialize to 0
- *
- * Incrementally encode a sequence of binary data into its Base-64 stringified
- * representation. By calling this function multiple times you can convert
- * data in chunks to avoid having to have the full encoded data in memory.
- *
- * When all of the data has been converted you must call
- * g_base64_encode_close() to flush the saved state.
- *
- * The output buffer must be large enough to fit all the data that will
- * be written to it. Due to the way base64 encodes you will need
- * at least: (@len / 3 + 1) * 4 + 4 bytes (+ 4 may be needed in case of
- * non-zero state). If you enable line-breaking you will need at least:
- * ((@len / 3 + 1) * 4 + 4) / 72 + 1 bytes of extra space.
- *
- * @break_lines is typically used when putting base64-encoded data in emails.
- * It breaks the lines at 72 columns instead of putting all of the text on
- * the same line. This avoids problems with long lines in the email system.
- *
- * Return value: The number of bytes of output that was written
- *
- * Since: 2.12
- */
-gsize
-g_base64_encode_step (const guchar *in,
- gsize len,
- gboolean break_lines,
- gchar *out,
- gint *state,
- gint *save)
-{
- char *outptr;
- const guchar *inptr;
-
- g_return_val_if_fail (in != NULL, 0);
- g_return_val_if_fail (out != NULL, 0);
- g_return_val_if_fail (state != NULL, 0);
- g_return_val_if_fail (save != NULL, 0);
-
- if (len <= 0)
- return 0;
-
- inptr = in;
- outptr = out;
-
- if (len + ((char *) save) [0] > 2)
- {
- const guchar *inend = in+len-2;
- int c1, c2, c3;
- int already;
-
- already = *state;
-
- switch (((char *) save) [0])
- {
- case 1:
- c1 = ((unsigned char *) save) [1];
- goto skip1;
- case 2:
- c1 = ((unsigned char *) save) [1];
- c2 = ((unsigned char *) save) [2];
- goto skip2;
- }
-
- /*
- * yes, we jump into the loop, no i'm not going to change it,
- * it's beautiful!
- */
- while (inptr < inend)
- {
- c1 = *inptr++;
- skip1:
- c2 = *inptr++;
- skip2:
- c3 = *inptr++;
- *outptr++ = base64_alphabet [ c1 >> 2 ];
- *outptr++ = base64_alphabet [ c2 >> 4 |
- ((c1&0x3) << 4) ];
- *outptr++ = base64_alphabet [ ((c2 &0x0f) << 2) |
- (c3 >> 6) ];
- *outptr++ = base64_alphabet [ c3 & 0x3f ];
- /* this is a bit ugly ... */
- if (break_lines && (++already) >= 19)
- {
- *outptr++ = '\n';
- already = 0;
- }
- }
-
- ((char *)save)[0] = 0;
- len = 2 - (inptr - inend);
- *state = already;
- }
-
- if (len>0)
- {
- char *saveout;
-
- /* points to the slot for the next char to save */
- saveout = & (((char *)save)[1]) + ((char *)save)[0];
-
- /* len can only be 0 1 or 2 */
- switch(len)
- {
- case 2: *saveout++ = *inptr++;
- case 1: *saveout++ = *inptr++;
- }
- ((char *)save)[0] += len;
- }
-
- return outptr - out;
-}
-
-/**
- * g_base64_encode_close:
- * @break_lines: whether to break long lines
- * @out: pointer to destination buffer
- * @state: Saved state from g_base64_encode_step()
- * @save: Saved state from g_base64_encode_step()
- *
- * Flush the status from a sequence of calls to g_base64_encode_step().
- *
- * Return value: The number of bytes of output that was written
- *
- * Since: 2.12
- */
-gsize
-g_base64_encode_close (gboolean break_lines,
- gchar *out,
- gint *state,
- gint *save)
-{
- int c1, c2;
- char *outptr = out;
-
- g_return_val_if_fail (out != NULL, 0);
- g_return_val_if_fail (state != NULL, 0);
- g_return_val_if_fail (save != NULL, 0);
-
- c1 = ((unsigned char *) save) [1];
- c2 = ((unsigned char *) save) [2];
-
- switch (((char *) save) [0])
- {
- case 2:
- outptr [2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
- g_assert (outptr [2] != 0);
- goto skip;
- case 1:
- outptr[2] = '=';
- skip:
- outptr [0] = base64_alphabet [ c1 >> 2 ];
- outptr [1] = base64_alphabet [ c2 >> 4 | ( (c1&0x3) << 4 )];
- outptr [3] = '=';
- outptr += 4;
- break;
- }
- if (break_lines)
- *outptr++ = '\n';
-
- *save = 0;
- *state = 0;
-
- return outptr - out;
-}
-
-/**
- * g_base64_encode:
- * @data: the binary data to encode
- * @len: the length of @data
- *
- * Encode a sequence of binary data into its Base-64 stringified
- * representation.
- *
- * Return value: a newly allocated, zero-terminated Base-64 encoded
- * string representing @data. The returned string must
- * be freed with g_free().
- *
- * Since: 2.12
- */
-gchar *
-g_base64_encode (const guchar *data,
- gsize len)
-{
- gchar *out;
- gint state = 0, outlen;
- gint save = 0;
-
- g_return_val_if_fail (data != NULL, NULL);
- g_return_val_if_fail (len > 0, NULL);
-
- /* We can use a smaller limit here, since we know the saved state is 0,
- +1 is needed for trailing \0, also check for unlikely integer overflow */
- if (len >= ((G_MAXSIZE - 1) / 4 - 1) * 3)
- g_error("%s: input too large for Base64 encoding (%"G_GSIZE_FORMAT" chars)",
- G_STRLOC, len);
-
- out = g_malloc ((len / 3 + 1) * 4 + 1);
-
- outlen = g_base64_encode_step (data, len, FALSE, out, &state, &save);
- outlen += g_base64_encode_close (FALSE, out + outlen, &state, &save);
- out[outlen] = '\0';
-
- return (gchar *) out;
-}
-
-static const unsigned char mime_base64_rank[256] = {
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
- 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
- 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-};
-
-/**
- * g_base64_decode_step:
- * @in: binary input data
- * @len: max length of @in data to decode
- * @out: output buffer
- * @state: Saved state between steps, initialize to 0
- * @save: Saved state between steps, initialize to 0
- *
- * Incrementally decode a sequence of binary data from its Base-64 stringified
- * representation. By calling this function multiple times you can convert
- * data in chunks to avoid having to have the full encoded data in memory.
- *
- * The output buffer must be large enough to fit all the data that will
- * be written to it. Since base64 encodes 3 bytes in 4 chars you need
- * at least: (@len / 4) * 3 + 3 bytes (+ 3 may be needed in case of non-zero
- * state).
- *
- * Return value: The number of bytes of output that was written
- *
- * Since: 2.12
- **/
-gsize
-g_base64_decode_step (const gchar *in,
- gsize len,
- guchar *out,
- gint *state,
- guint *save)
-{
- const guchar *inptr;
- guchar *outptr;
- const guchar *inend;
- guchar c, rank;
- guchar last[2];
- unsigned int v;
- int i;
-
- g_return_val_if_fail (in != NULL, 0);
- g_return_val_if_fail (out != NULL, 0);
- g_return_val_if_fail (state != NULL, 0);
- g_return_val_if_fail (save != NULL, 0);
-
- if (len <= 0)
- return 0;
-
- inend = (const guchar *)in+len;
- outptr = out;
-
- /* convert 4 base64 bytes to 3 normal bytes */
- v=*save;
- i=*state;
- inptr = (const guchar *)in;
- last[0] = last[1] = 0;
- while (inptr < inend)
- {
- c = *inptr++;
- rank = mime_base64_rank [c];
- if (rank != 0xff)
- {
- last[1] = last[0];
- last[0] = c;
- v = (v<<6) | rank;
- i++;
- if (i==4)
- {
- *outptr++ = v>>16;
- if (last[1] != '=')
- *outptr++ = v>>8;
- if (last[0] != '=')
- *outptr++ = v;
- i=0;
- }
- }
- }
-
- *save = v;
- *state = i;
-
- return outptr - out;
-}
-
-/**
- * g_base64_decode:
- * @text: zero-terminated string with base64 text to decode
- * @out_len: The length of the decoded data is written here
- *
- * Decode a sequence of Base-64 encoded text into binary data
- *
- * Return value: a newly allocated buffer containing the binary data
- * that @text represents. The returned buffer must
- * be freed with g_free().
- *
- * Since: 2.12
- */
-guchar *
-g_base64_decode (const gchar *text,
- gsize *out_len)
-{
- guchar *ret;
- gsize input_length;
- gint state = 0;
- guint save = 0;
-
- g_return_val_if_fail (text != NULL, NULL);
- g_return_val_if_fail (out_len != NULL, NULL);
-
- input_length = strlen (text);
-
- g_return_val_if_fail (input_length > 1, NULL);
-
- /* We can use a smaller limit here, since we know the saved state is 0,
- +1 used to avoid calling g_malloc0(0), and hence retruning NULL */
- ret = g_malloc0 ((input_length / 4) * 3 + 1);
-
- *out_len = g_base64_decode_step (text, input_length, ret, &state, &save);
-
- return ret;
-}
-
-/**
- * g_base64_decode_inplace:
- * @text: zero-terminated string with base64 text to decode
- * @out_len: The length of the decoded data is written here
- *
- * Decode a sequence of Base-64 encoded text into binary data
- * by overwriting the input data.
- *
- * Return value: The binary data that @text responds. This pointer
- * is the same as the input @text.
- *
- * Since: 2.20
- */
-guchar *
-g_base64_decode_inplace (gchar *text,
- gsize *out_len)
-{
- gint input_length, state = 0;
- guint save = 0;
-
- g_return_val_if_fail (text != NULL, NULL);
- g_return_val_if_fail (out_len != NULL, NULL);
-
- input_length = strlen (text);
-
- g_return_val_if_fail (input_length > 1, NULL);
-
- *out_len = g_base64_decode_step (text, input_length, (guchar *) text, &state, &save);
-
- return text;
-}
-
-
-#define __G_BASE64_C__
-#include "galiasdef.c"
diff --git a/glib/gbookmarkfile.c b/glib/gbookmarkfile.c
deleted file mode 100644
index 01c7e639e..000000000
--- a/glib/gbookmarkfile.c
+++ /dev/null
@@ -1,3709 +0,0 @@
-/* gbookmarkfile.c: parsing and building desktop bookmarks
- *
- * Copyright (C) 2005-2006 Emmanuele Bassi
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- */
-
-#include "config.h"
-
-#include "gbookmarkfile.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <locale.h>
-#include <time.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "gconvert.h"
-#include "gdataset.h"
-#include "gerror.h"
-#include "gfileutils.h"
-#include "ghash.h"
-#include "glibintl.h"
-#include "glist.h"
-#include "gslist.h"
-#include "gmain.h"
-#include "gmarkup.h"
-#include "gmem.h"
-#include "gmessages.h"
-#include "gshell.h"
-#include "gslice.h"
-#include "gstdio.h"
-#include "gstring.h"
-#include "gstrfuncs.h"
-#include "gtimer.h"
-#include "gutils.h"
-
-#include "galias.h"
-
-/* XBEL 1.0 standard entities */
-#define XBEL_VERSION "1.0"
-#define XBEL_DTD_NICK "xbel"
-#define XBEL_DTD_SYSTEM "+//IDN python.org//DTD XML Bookmark " \
- "Exchange Language 1.0//EN//XML"
-
-#define XBEL_DTD_URI "http://www.python.org/topics/xml/dtds/xbel-1.0.dtd"
-
-#define XBEL_ROOT_ELEMENT "xbel"
-#define XBEL_FOLDER_ELEMENT "folder" /* unused */
-#define XBEL_BOOKMARK_ELEMENT "bookmark"
-#define XBEL_ALIAS_ELEMENT "alias" /* unused */
-#define XBEL_SEPARATOR_ELEMENT "separator" /* unused */
-#define XBEL_TITLE_ELEMENT "title"
-#define XBEL_DESC_ELEMENT "desc"
-#define XBEL_INFO_ELEMENT "info"
-#define XBEL_METADATA_ELEMENT "metadata"
-
-#define XBEL_VERSION_ATTRIBUTE "version"
-#define XBEL_FOLDED_ATTRIBUTE "folded" /* unused */
-#define XBEL_OWNER_ATTRIBUTE "owner"
-#define XBEL_ADDED_ATTRIBUTE "added"
-#define XBEL_VISITED_ATTRIBUTE "visited"
-#define XBEL_MODIFIED_ATTRIBUTE "modified"
-#define XBEL_ID_ATTRIBUTE "id"
-#define XBEL_HREF_ATTRIBUTE "href"
-#define XBEL_REF_ATTRIBUTE "ref" /* unused */
-
-#define XBEL_YES_VALUE "yes"
-#define XBEL_NO_VALUE "no"
-
-/* Desktop bookmark spec entities */
-#define BOOKMARK_METADATA_OWNER "http://freedesktop.org"
-
-#define BOOKMARK_NAMESPACE_NAME "bookmark"
-#define BOOKMARK_NAMESPACE_URI "http://www.freedesktop.org/standards/desktop-bookmarks"
-
-#define BOOKMARK_GROUPS_ELEMENT "groups"
-#define BOOKMARK_GROUP_ELEMENT "group"
-#define BOOKMARK_APPLICATIONS_ELEMENT "applications"
-#define BOOKMARK_APPLICATION_ELEMENT "application"
-#define BOOKMARK_ICON_ELEMENT "icon"
-#define BOOKMARK_PRIVATE_ELEMENT "private"
-
-#define BOOKMARK_NAME_ATTRIBUTE "name"
-#define BOOKMARK_EXEC_ATTRIBUTE "exec"
-#define BOOKMARK_COUNT_ATTRIBUTE "count"
-#define BOOKMARK_TIMESTAMP_ATTRIBUTE "timestamp" /* deprecated by "modified" */
-#define BOOKMARK_MODIFIED_ATTRIBUTE "modified"
-#define BOOKMARK_HREF_ATTRIBUTE "href"
-#define BOOKMARK_TYPE_ATTRIBUTE "type"
-
-/* Shared MIME Info entities */
-#define MIME_NAMESPACE_NAME "mime"
-#define MIME_NAMESPACE_URI "http://www.freedesktop.org/standards/shared-mime-info"
-#define MIME_TYPE_ELEMENT "mime-type"
-#define MIME_TYPE_ATTRIBUTE "type"
-
-
-typedef struct _BookmarkAppInfo BookmarkAppInfo;
-typedef struct _BookmarkMetadata BookmarkMetadata;
-typedef struct _BookmarkItem BookmarkItem;
-typedef struct _ParseData ParseData;
-
-struct _BookmarkAppInfo
-{
- gchar *name;
- gchar *exec;
-
- guint count;
-
- time_t stamp;
-};
-
-struct _BookmarkMetadata
-{
- gchar *mime_type;
-
- GList *groups;
-
- GList *applications;
- GHashTable *apps_by_name;
-
- gchar *icon_href;
- gchar *icon_mime;
-
- guint is_private : 1;
-};
-
-struct _BookmarkItem
-{
- gchar *uri;
-
- gchar *title;
- gchar *description;
-
- time_t added;
- time_t modified;
- time_t visited;
-
- BookmarkMetadata *metadata;
-};
-
-struct _GBookmarkFile
-{
- gchar *title;
- gchar *description;
-
- /* we store our items in a list and keep a copy inside
- * an hash table for faster lookup performances
- */
- GList *items;
- GHashTable *items_by_uri;
-};
-
-/* parser state machine */
-enum
-{
- STATE_STARTED = 0,
-
- STATE_ROOT,
- STATE_BOOKMARK,
- STATE_TITLE,
- STATE_DESC,
- STATE_INFO,
- STATE_METADATA,
- STATE_APPLICATIONS,
- STATE_APPLICATION,
- STATE_GROUPS,
- STATE_GROUP,
- STATE_MIME,
- STATE_ICON,
-
- STATE_FINISHED
-};
-
-static void g_bookmark_file_init (GBookmarkFile *bookmark);
-static void g_bookmark_file_clear (GBookmarkFile *bookmark);
-static gboolean g_bookmark_file_parse (GBookmarkFile *bookmark,
- const gchar *buffer,
- gsize length,
- GError **error);
-static gchar * g_bookmark_file_dump (GBookmarkFile *bookmark,
- gsize *length,
- GError **error);
-static BookmarkItem *g_bookmark_file_lookup_item (GBookmarkFile *bookmark,
- const gchar *uri);
-static void g_bookmark_file_add_item (GBookmarkFile *bookmark,
- BookmarkItem *item,
- GError **error);
-
-static time_t timestamp_from_iso8601 (const gchar *iso_date);
-static gchar * timestamp_to_iso8601 (time_t timestamp);
-
-/********************************
- * BookmarkAppInfo *
- * *
- * Application metadata storage *
- ********************************/
-static BookmarkAppInfo *
-bookmark_app_info_new (const gchar *name)
-{
- BookmarkAppInfo *retval;
-
- g_warn_if_fail (name != NULL);
-
- retval = g_slice_new (BookmarkAppInfo);
-
- retval->name = g_strdup (name);
- retval->exec = NULL;
- retval->count = 0;
- retval->stamp = 0;
-
- return retval;
-}
-
-static void
-bookmark_app_info_free (BookmarkAppInfo *app_info)
-{
- if (!app_info)
- return;
-
- g_free (app_info->name);
- g_free (app_info->exec);
-
- g_slice_free (BookmarkAppInfo, app_info);
-}
-
-static gchar *
-bookmark_app_info_dump (BookmarkAppInfo *app_info)
-{
- gchar *retval;
- gchar *name, *exec, *modified, *count;
-
- g_warn_if_fail (app_info != NULL);
-
- if (app_info->count == 0)
- return NULL;
-
- name = g_markup_escape_text (app_info->name, -1);
- exec = g_markup_escape_text (app_info->exec, -1);
- modified = timestamp_to_iso8601 (app_info->stamp);
- count = g_strdup_printf ("%u", app_info->count);
-
- retval = g_strconcat (" "
- "<" BOOKMARK_NAMESPACE_NAME ":" BOOKMARK_APPLICATION_ELEMENT
- " " BOOKMARK_NAME_ATTRIBUTE "=\"", name, "\""
- " " BOOKMARK_EXEC_ATTRIBUTE "=\"", exec, "\""
- " " BOOKMARK_MODIFIED_ATTRIBUTE "=\"", modified, "\""
- " " BOOKMARK_COUNT_ATTRIBUTE "=\"", count, "\"/>\n",
- NULL);
-
- g_free (name);
- g_free (exec);
- g_free (modified);
- g_free (count);
-
- return retval;
-}
-
-
-/***********************
- * BookmarkMetadata *
- * *
- * Metadata storage *
- ***********************/
-static BookmarkMetadata *
-bookmark_metadata_new (void)
-{
- BookmarkMetadata *retval;
-
- retval = g_slice_new (BookmarkMetadata);
-
- retval->mime_type = NULL;
-
- retval->groups = NULL;
-
- retval->applications = NULL;
- retval->apps_by_name = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- NULL,
- NULL);
-
- retval->is_private = FALSE;
-
- retval->icon_href = NULL;
- retval->icon_mime = NULL;
-
- return retval;
-}
-
-static void
-bookmark_metadata_free (BookmarkMetadata *metadata)
-{
- if (!metadata)
- return;
-
- g_free (metadata->mime_type);
-
- if (metadata->groups)
- {
- g_list_foreach (metadata->groups,
- (GFunc) g_free,
- NULL);
- g_list_free (metadata->groups);
- }
-
- if (metadata->applications)
- {
- g_list_foreach (metadata->applications,
- (GFunc) bookmark_app_info_free,
- NULL);
- g_list_free (metadata->applications);
- }
-
- g_hash_table_destroy (metadata->apps_by_name);
-
- g_free (metadata->icon_href);
- g_free (metadata->icon_mime);
-
- g_slice_free (BookmarkMetadata, metadata);
-}
-
-static gchar *
-bookmark_metadata_dump (BookmarkMetadata *metadata)
-{
- GString *retval;
- gchar *buffer;
-
- if (!metadata->applications)
- return NULL;
-
- retval = g_string_sized_new (1024);
-
- /* metadata container */
- g_string_append (retval,
- " "
- "<" XBEL_METADATA_ELEMENT
- " " XBEL_OWNER_ATTRIBUTE "=\"" BOOKMARK_METADATA_OWNER
- "\">\n");
-
- /* mime type */
- if (metadata->mime_type) {
- buffer = g_strconcat (" "
- "<" MIME_NAMESPACE_NAME ":" MIME_TYPE_ELEMENT " "
- MIME_TYPE_ATTRIBUTE "=\"", metadata->mime_type, "\"/>\n",
- NULL);
- g_string_append (retval, buffer);
- g_free (buffer);
- }
-
- if (metadata->groups)
- {
- GList *l;
-
- /* open groups container */
- g_string_append (retval,
- " "
- "<" BOOKMARK_NAMESPACE_NAME
- ":" BOOKMARK_GROUPS_ELEMENT ">\n");
-
- for (l = g_list_last (metadata->groups); l != NULL; l = l->prev)
- {
- gchar *group_name;
-
- group_name = g_markup_escape_text ((gchar *) l->data, -1);
- buffer = g_strconcat (" "
- "<" BOOKMARK_NAMESPACE_NAME
- ":" BOOKMARK_GROUP_ELEMENT ">",
- group_name,
- "</" BOOKMARK_NAMESPACE_NAME
- ":" BOOKMARK_GROUP_ELEMENT ">\n", NULL);
- g_string_append (retval, buffer);
-
- g_free (buffer);
- g_free (group_name);
- }
-
- /* close groups container */
- g_string_append (retval,
- " "
- "</" BOOKMARK_NAMESPACE_NAME
- ":" BOOKMARK_GROUPS_ELEMENT ">\n");
- }
-
- if (metadata->applications)
- {
- GList *l;
-
- /* open applications container */
- g_string_append (retval,
- " "
- "<" BOOKMARK_NAMESPACE_NAME
- ":" BOOKMARK_APPLICATIONS_ELEMENT ">\n");
-
- for (l = g_list_last (metadata->applications); l != NULL; l = l->prev)
- {
- BookmarkAppInfo *app_info = (BookmarkAppInfo *) l->data;
- gchar *app_data;
-
- g_warn_if_fail (app_info != NULL);
-
- app_data = bookmark_app_info_dump (app_info);
-
- if (app_data)
- {
- retval = g_string_append (retval, app_data);
-
- g_free (app_data);
- }
- }
-
- /* close applications container */
- g_string_append (retval,
- " "
- "</" BOOKMARK_NAMESPACE_NAME
- ":" BOOKMARK_APPLICATIONS_ELEMENT ">\n");
- }
-
- /* icon */
- if (metadata->icon_href)
- {
- if (!metadata->icon_mime)
- metadata->icon_mime = g_strdup ("application/octet-stream");
-
- buffer = g_strconcat (" "
- "<" BOOKMARK_NAMESPACE_NAME
- ":" BOOKMARK_ICON_ELEMENT
- " " BOOKMARK_HREF_ATTRIBUTE "=\"", metadata->icon_href,
- "\" " BOOKMARK_TYPE_ATTRIBUTE "=\"", metadata->icon_mime, "\"/>\n", NULL);
- g_string_append (retval, buffer);
-
- g_free (buffer);
- }
-
- /* private hint */
- if (metadata->is_private)
- g_string_append (retval,
- " "
- "<" BOOKMARK_NAMESPACE_NAME
- ":" BOOKMARK_PRIVATE_ELEMENT "/>\n");
-
- /* close metadata container */
- g_string_append (retval,
- " "
- "</" XBEL_METADATA_ELEMENT ">\n");
-
- return g_string_free (retval, FALSE);
-}
-
-/******************************************************
- * BookmarkItem *
- * *
- * Storage for a single bookmark item inside the list *
- ******************************************************/
-static BookmarkItem *
-bookmark_item_new (const gchar *uri)
-{
- BookmarkItem *item;
-
- g_warn_if_fail (uri != NULL);
-
- item = g_slice_new (BookmarkItem);
- item->uri = g_strdup (uri);
-
- item->title = NULL;
- item->description = NULL;
-
- item->added = (time_t) -1;
- item->modified = (time_t) -1;
- item->visited = (time_t) -1;
-
- item->metadata = NULL;
-
- return item;
-}
-
-static void
-bookmark_item_free (BookmarkItem *item)
-{
- if (!item)
- return;
-
- g_free (item->uri);
- g_free (item->title);
- g_free (item->description);
-
- if (item->metadata)
- bookmark_metadata_free (item->metadata);
-
- g_slice_free (BookmarkItem, item);
-}
-
-static gchar *
-bookmark_item_dump (BookmarkItem *item)
-{
- GString *retval;
- gchar *added, *visited, *modified;
- gchar *escaped_uri;
- gchar *buffer;
-
- /* at this point, we must have at least a registered application; if we don't
- * we don't screw up the bookmark file, and just skip this item
- */
- if (!item->metadata || !item->metadata->applications)
- {
- g_warning ("Item for URI '%s' has no registered applications: skipping.\n", item->uri);
- return NULL;
- }
-
- retval = g_string_sized_new (4096);
-
- added = timestamp_to_iso8601 (item->added);
- modified = timestamp_to_iso8601 (item->modified);
- visited = timestamp_to_iso8601 (item->visited);
-
- escaped_uri = g_markup_escape_text (item->uri, -1);
-
- buffer = g_strconcat (" <"
- XBEL_BOOKMARK_ELEMENT
- " "
- XBEL_HREF_ATTRIBUTE "=\"", escaped_uri, "\" "
- XBEL_ADDED_ATTRIBUTE "=\"", added, "\" "
- XBEL_MODIFIED_ATTRIBUTE "=\"", modified, "\" "
- XBEL_VISITED_ATTRIBUTE "=\"", visited, "\">\n",
- NULL);
-
- g_string_append (retval, buffer);
-
- g_free (escaped_uri);
- g_free (visited);
- g_free (modified);
- g_free (added);
- g_free (buffer);
-
- if (item->title)
- {
- gchar *escaped_title;
-
- escaped_title = g_markup_escape_text (item->title, -1);
- buffer = g_strconcat (" "
- "<" XBEL_TITLE_ELEMENT ">",
- escaped_title,
- "</" XBEL_TITLE_ELEMENT ">\n",
- NULL);
- g_string_append (retval, buffer);
-
- g_free (escaped_title);
- g_free (buffer);
- }
-
- if (item->description)
- {
- gchar *escaped_desc;
-
- escaped_desc = g_markup_escape_text (item->description, -1);
- buffer = g_strconcat (" "
- "<" XBEL_DESC_ELEMENT ">",
- escaped_desc,
- "</" XBEL_DESC_ELEMENT ">\n",
- NULL);
- g_string_append (retval, buffer);
-
- g_free (escaped_desc);
- g_free (buffer);
- }
-
- if (item->metadata)
- {
- gchar *metadata;
-
- metadata = bookmark_metadata_dump (item->metadata);
- if (metadata)
- {
- buffer = g_strconcat (" "
- "<" XBEL_INFO_ELEMENT ">\n",
- metadata,
- " "
- "</" XBEL_INFO_ELEMENT ">\n",
- NULL);
- retval = g_string_append (retval, buffer);
-
- g_free (buffer);
- g_free (metadata);
- }
- }
-
- g_string_append (retval, " </" XBEL_BOOKMARK_ELEMENT ">\n");
-
- return g_string_free (retval, FALSE);
-}
-
-static BookmarkAppInfo *
-bookmark_item_lookup_app_info (BookmarkItem *item,
- const gchar *app_name)
-{
- g_warn_if_fail (item != NULL && app_name != NULL);
-
- if (!item->metadata)
- return NULL;
-
- return g_hash_table_lookup (item->metadata->apps_by_name, app_name);
-}
-
-/*************************
- * GBookmarkFile *
- *************************/
-
-static void
-g_bookmark_file_init (GBookmarkFile *bookmark)
-{
- bookmark->title = NULL;
- bookmark->description = NULL;
-
- bookmark->items = NULL;
- bookmark->items_by_uri = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- NULL,
- NULL);
-}
-
-static void
-g_bookmark_file_clear (GBookmarkFile *bookmark)
-{
- g_free (bookmark->title);
- g_free (bookmark->description);
-
- if (bookmark->items)
- {
- g_list_foreach (bookmark->items,
- (GFunc) bookmark_item_free,
- NULL);
- g_list_free (bookmark->items);
-
- bookmark->items = NULL;
- }
-
- if (bookmark->items_by_uri)
- {
- g_hash_table_destroy (bookmark->items_by_uri);
-
- bookmark->items_by_uri = NULL;
- }
-}
-
-struct _ParseData
-{
- gint state;
-
- GHashTable *namespaces;
-
- GBookmarkFile *bookmark_file;
- BookmarkItem *current_item;
-};
-
-static ParseData *
-parse_data_new (void)
-{
- ParseData *retval;
-
- retval = g_new (ParseData, 1);
-
- retval->state = STATE_STARTED;
- retval->namespaces = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_free);
- retval->bookmark_file = NULL;
- retval->current_item = NULL;
-
- return retval;
-}
-
-static void
-parse_data_free (ParseData *parse_data)
-{
- g_hash_table_destroy (parse_data->namespaces);
-
- g_free (parse_data);
-}
-
-#define IS_ATTRIBUTE(s,a) ((0 == strcmp ((s), (a))))
-
-static void
-parse_bookmark_element (GMarkupParseContext *context,
- ParseData *parse_data,
- const gchar **attribute_names,
- const gchar **attribute_values,
- GError **error)
-{
- const gchar *uri, *added, *modified, *visited;
- const gchar *attr;
- gint i;
- BookmarkItem *item;
- GError *add_error;
-
- g_warn_if_fail ((parse_data != NULL) && (parse_data->state == STATE_BOOKMARK));
-
- i = 0;
- uri = added = modified = visited = NULL;
- for (attr = attribute_names[i]; attr != NULL; attr = attribute_names[++i])
- {
- if (IS_ATTRIBUTE (attr, XBEL_HREF_ATTRIBUTE))
- uri = attribute_values[i];
- else if (IS_ATTRIBUTE (attr, XBEL_ADDED_ATTRIBUTE))
- added = attribute_values[i];
- else if (IS_ATTRIBUTE (attr, XBEL_MODIFIED_ATTRIBUTE))
- modified = attribute_values[i];
- else if (IS_ATTRIBUTE (attr, XBEL_VISITED_ATTRIBUTE))
- visited = attribute_values[i];
- else
- {
- /* bookmark is defined by the XBEL spec, so we need
- * to error out if the element has different or
- * missing attributes
- */
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
- _("Unexpected attribute '%s' for element '%s'"),
- attr,
- XBEL_BOOKMARK_ELEMENT);
- return;
- }
- }
-
- if (!uri)
- {
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Attribute '%s' of element '%s' not found"),
- XBEL_HREF_ATTRIBUTE,
- XBEL_BOOKMARK_ELEMENT);
- return;
- }
-
- g_warn_if_fail (parse_data->current_item == NULL);
-
- item = bookmark_item_new (uri);
-
- if (added)
- item->added = timestamp_from_iso8601 (added);
-
- if (modified)
- item->modified = timestamp_from_iso8601 (modified);
-
- if (visited)
- item->visited = timestamp_from_iso8601 (visited);
-
- add_error = NULL;
- g_bookmark_file_add_item (parse_data->bookmark_file,
- item,
- &add_error);
- if (add_error)
- {
- bookmark_item_free (item);
-
- g_propagate_error (error, add_error);
-
- return;
- }
-
- parse_data->current_item = item;
-}
-
-static void
-parse_application_element (GMarkupParseContext *context,
- ParseData *parse_data,
- const gchar **attribute_names,
- const gchar **attribute_values,
- GError **error)
-{
- const gchar *name, *exec, *count, *stamp, *modified;
- const gchar *attr;
- gint i;
- BookmarkItem *item;
- BookmarkAppInfo *ai;
-
- g_warn_if_fail ((parse_data != NULL) && (parse_data->state == STATE_APPLICATION));
-
- i = 0;
- name = exec = count = stamp = modified = NULL;
- for (attr = attribute_names[i]; attr != NULL; attr = attribute_names[++i])
- {
- if (IS_ATTRIBUTE (attr, BOOKMARK_NAME_ATTRIBUTE))
- name = attribute_values[i];
- else if (IS_ATTRIBUTE (attr, BOOKMARK_EXEC_ATTRIBUTE))
- exec = attribute_values[i];
- else if (IS_ATTRIBUTE (attr, BOOKMARK_COUNT_ATTRIBUTE))
- count = attribute_values[i];
- else if (IS_ATTRIBUTE (attr, BOOKMARK_TIMESTAMP_ATTRIBUTE))
- stamp = attribute_values[i];
- else if (IS_ATTRIBUTE (attr, BOOKMARK_MODIFIED_ATTRIBUTE))
- modified = attribute_values[i];
- }
-
- /* the "name" and "exec" attributes are mandatory */
- if (!name)
- {
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Attribute '%s' of element '%s' not found"),
- BOOKMARK_NAME_ATTRIBUTE,
- BOOKMARK_APPLICATION_ELEMENT);
- return;
- }
-
- if (!exec)
- {
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Attribute '%s' of element '%s' not found"),
- BOOKMARK_EXEC_ATTRIBUTE,
- BOOKMARK_APPLICATION_ELEMENT);
- return;
- }
-
- g_warn_if_fail (parse_data->current_item != NULL);
- item = parse_data->current_item;
-
- ai = bookmark_item_lookup_app_info (item, name);
- if (!ai)
- {
- ai = bookmark_app_info_new (name);
-
- if (!item->metadata)
- item->metadata = bookmark_metadata_new ();
-
- item->metadata->applications = g_list_prepend (item->metadata->applications, ai);
- g_hash_table_replace (item->metadata->apps_by_name, ai->name, ai);
- }
-
- ai->exec = g_strdup (exec);
-
- if (count)
- ai->count = atoi (count);
- else
- ai->count = 1;
-
- if (modified)
- ai->stamp = timestamp_from_iso8601 (modified);
- else
- {
- /* the timestamp attribute has been deprecated but we still parse
- * it for backward compatibility
- */
- if (stamp)
- ai->stamp = (time_t) atol (stamp);
- else
- ai->stamp = time (NULL);
- }
-}
-
-static void
-parse_mime_type_element (GMarkupParseContext *context,
- ParseData *parse_data,
- const gchar **attribute_names,
- const gchar **attribute_values,
- GError **error)
-{
- const gchar *type;
- const gchar *attr;
- gint i;
- BookmarkItem *item;
-
- g_warn_if_fail ((parse_data != NULL) && (parse_data->state == STATE_MIME));
-
- i = 0;
- type = NULL;
- for (attr = attribute_names[i]; attr != NULL; attr = attribute_names[++i])
- {
- if (IS_ATTRIBUTE (attr, MIME_TYPE_ATTRIBUTE))
- type = attribute_values[i];
- }
-
- if (!type)
- type = "application/octet-stream";
-
- g_warn_if_fail (parse_data->current_item != NULL);
- item = parse_data->current_item;
-
- if (!item->metadata)
- item->metadata = bookmark_metadata_new ();
-
- item->metadata->mime_type = g_strdup (type);
-}
-
-static void
-parse_icon_element (GMarkupParseContext *context,
- ParseData *parse_data,
- const gchar **attribute_names,
- const gchar **attribute_values,
- GError **error)
-{
- const gchar *href;
- const gchar *type;
- const gchar *attr;
- gint i;
- BookmarkItem *item;
-
- g_warn_if_fail ((parse_data != NULL) && (parse_data->state == STATE_ICON));
-
- i = 0;
- href = NULL;
- type = NULL;
- for (attr = attribute_names[i]; attr != NULL; attr = attribute_names[++i])
- {
- if (IS_ATTRIBUTE (attr, BOOKMARK_HREF_ATTRIBUTE))
- href = attribute_values[i];
- else if (IS_ATTRIBUTE (attr, BOOKMARK_TYPE_ATTRIBUTE))
- type = attribute_values[i];
- }
-
- /* the "href" attribute is mandatory */
- if (!href)
- {
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Attribute '%s' of element '%s' not found"),
- BOOKMARK_HREF_ATTRIBUTE,
- BOOKMARK_ICON_ELEMENT);
- return;
- }
-
- if (!type)
- type = "application/octet-stream";
-
- g_warn_if_fail (parse_data->current_item != NULL);
- item = parse_data->current_item;
-
- if (!item->metadata)
- item->metadata = bookmark_metadata_new ();
-
- item->metadata->icon_href = g_strdup (href);
- item->metadata->icon_mime = g_strdup (type);
-}
-
-/* scans through the attributes of an element for the "xmlns" pragma, and
- * adds any resulting namespace declaration to a per-parser hashtable, using
- * the namespace name as a key for the namespace URI; if no key was found,
- * the namespace is considered as default, and stored under the "default" key.
- *
- * FIXME: this works on the assumption that the generator of the XBEL file
- * is either this code or is smart enough to place the namespace declarations
- * inside the main root node or inside the metadata node and does not redefine
- * a namespace inside an inner node; this does *not* conform to the
- * XML-NS standard, although is a close approximation. In order to make this
- * conformant to the XML-NS specification we should use a per-element
- * namespace table inside GMarkup and ask it to resolve the namespaces for us.
- */
-static void
-map_namespace_to_name (ParseData *parse_data,
- const gchar **attribute_names,
- const gchar **attribute_values)
-{
- const gchar *attr;
- gint i;
-
- g_warn_if_fail (parse_data != NULL);
-
- if (!attribute_names || !attribute_names[0])
- return;
-
- i = 0;
- for (attr = attribute_names[i]; attr; attr = attribute_names[++i])
- {
- if (g_str_has_prefix (attr, "xmlns"))
- {
- gchar *namespace_name, *namespace_uri;
- gchar *p;
-
- p = g_utf8_strchr (attr, -1, ':');
- if (p)
- p = g_utf8_next_char (p);
- else
- p = "default";
-
- namespace_name = g_strdup (p);
- namespace_uri = g_strdup (attribute_values[i]);
-
- g_hash_table_replace (parse_data->namespaces,
- namespace_name,
- namespace_uri);
- }
- }
-}
-
-/* checks whether @element_full is equal to @element.
- *
- * if @namespace is set, it tries to resolve the namespace to a known URI,
- * and if found is prepended to the element name, from which is separated
- * using the character specified in the @sep parameter.
- */
-static gboolean
-is_element_full (ParseData *parse_data,
- const gchar *element_full,
- const gchar *namespace,
- const gchar *element,
- const gchar sep)
-{
- gchar *ns_uri, *ns_name;
- const gchar *p, *element_name;
- gboolean retval;
-
- g_warn_if_fail (parse_data != NULL);
- g_warn_if_fail (element_full != NULL);
-
- if (!element)
- return FALSE;
-
- /* no namespace requested: dumb element compare */
- if (!namespace)
- return (0 == strcmp (element_full, element));
-
- /* search for namespace separator; if none found, assume we are under the
- * default namespace, and set ns_name to our "default" marker; if no default
- * namespace has been set, just do a plain comparison between @full_element
- * and @element.
- */
- p = g_utf8_strchr (element_full, -1, ':');
- if (p)
- {
- ns_name = g_strndup (element_full, p - element_full);
- element_name = g_utf8_next_char (p);
- }
- else
- {
- ns_name = g_strdup ("default");
- element_name = element_full;
- }
-
- ns_uri = g_hash_table_lookup (parse_data->namespaces, ns_name);
- if (!ns_uri)
- {
- /* no default namespace found */
- g_free (ns_name);
-
- return (0 == strcmp (element_full, element));
- }
-
- retval = (0 == strcmp (ns_uri, namespace) &&
- 0 == strcmp (element_name, element));
-
- g_free (ns_name);
-
- return retval;
-}
-
-#define IS_ELEMENT(p,s,e) (is_element_full ((p), (s), NULL, (e), '\0'))
-#define IS_ELEMENT_NS(p,s,n,e) (is_element_full ((p), (s), (n), (e), '|'))
-
-static void
-start_element_raw_cb (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer user_data,
- GError **error)
-{
- ParseData *parse_data = (ParseData *) user_data;
-
- /* we must check for namespace declarations first
- *
- * XXX - we could speed up things by checking for namespace declarations
- * only on the root node, where they usually are; this would probably break
- * on streams not produced by us or by "smart" generators
- */
- map_namespace_to_name (parse_data, attribute_names, attribute_values);
-
- switch (parse_data->state)
- {
- case STATE_STARTED:
- if (IS_ELEMENT (parse_data, element_name, XBEL_ROOT_ELEMENT))
- {
- const gchar *attr;
- gint i;
-
- i = 0;
- for (attr = attribute_names[i]; attr; attr = attribute_names[++i])
- {
- if ((IS_ATTRIBUTE (attr, XBEL_VERSION_ATTRIBUTE)) &&
- (0 == strcmp (attribute_values[i], XBEL_VERSION)))
- parse_data->state = STATE_ROOT;
- }
- }
- else
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Unexpected tag '%s', tag '%s' expected"),
- element_name, XBEL_ROOT_ELEMENT);
- break;
- case STATE_ROOT:
- if (IS_ELEMENT (parse_data, element_name, XBEL_TITLE_ELEMENT))
- parse_data->state = STATE_TITLE;
- else if (IS_ELEMENT (parse_data, element_name, XBEL_DESC_ELEMENT))
- parse_data->state = STATE_DESC;
- else if (IS_ELEMENT (parse_data, element_name, XBEL_BOOKMARK_ELEMENT))
- {
- GError *inner_error = NULL;
-
- parse_data->state = STATE_BOOKMARK;
-
- parse_bookmark_element (context,
- parse_data,
- attribute_names,
- attribute_values,
- &inner_error);
- if (inner_error)
- g_propagate_error (error, inner_error);
- }
- else
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Unexpected tag '%s' inside '%s'"),
- element_name,
- XBEL_ROOT_ELEMENT);
- break;
- case STATE_BOOKMARK:
- if (IS_ELEMENT (parse_data, element_name, XBEL_TITLE_ELEMENT))
- parse_data->state = STATE_TITLE;
- else if (IS_ELEMENT (parse_data, element_name, XBEL_DESC_ELEMENT))
- parse_data->state = STATE_DESC;
- else if (IS_ELEMENT (parse_data, element_name, XBEL_INFO_ELEMENT))
- parse_data->state = STATE_INFO;
- else
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Unexpected tag '%s' inside '%s'"),
- element_name,
- XBEL_BOOKMARK_ELEMENT);
- break;
- case STATE_INFO:
- if (IS_ELEMENT (parse_data, element_name, XBEL_METADATA_ELEMENT))
- {
- const gchar *attr;
- gint i;
-
- i = 0;
- for (attr = attribute_names[i]; attr; attr = attribute_names[++i])
- {
- if ((IS_ATTRIBUTE (attr, XBEL_OWNER_ATTRIBUTE)) &&
- (0 == strcmp (attribute_values[i], BOOKMARK_METADATA_OWNER)))
- {
- parse_data->state = STATE_METADATA;
-
- if (!parse_data->current_item->metadata)
- parse_data->current_item->metadata = bookmark_metadata_new ();
- }
- }
- }
- else
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Unexpected tag '%s', tag '%s' expected"),
- element_name,
- XBEL_METADATA_ELEMENT);
- break;
- case STATE_METADATA:
- if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_APPLICATIONS_ELEMENT))
- parse_data->state = STATE_APPLICATIONS;
- else if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_GROUPS_ELEMENT))
- parse_data->state = STATE_GROUPS;
- else if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_PRIVATE_ELEMENT))
- parse_data->current_item->metadata->is_private = TRUE;
- else if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_ICON_ELEMENT))
- {
- GError *inner_error = NULL;
-
- parse_data->state = STATE_ICON;
-
- parse_icon_element (context,
- parse_data,
- attribute_names,
- attribute_values,
- &inner_error);
- if (inner_error)
- g_propagate_error (error, inner_error);
- }
- else if (IS_ELEMENT_NS (parse_data, element_name, MIME_NAMESPACE_URI, MIME_TYPE_ELEMENT))
- {
- GError *inner_error = NULL;
-
- parse_data->state = STATE_MIME;
-
- parse_mime_type_element (context,
- parse_data,
- attribute_names,
- attribute_values,
- &inner_error);
- if (inner_error)
- g_propagate_error (error, inner_error);
- }
- else
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_UNKNOWN_ELEMENT,
- _("Unexpected tag '%s' inside '%s'"),
- element_name,
- XBEL_METADATA_ELEMENT);
- break;
- case STATE_APPLICATIONS:
- if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_APPLICATION_ELEMENT))
- {
- GError *inner_error = NULL;
-
- parse_data->state = STATE_APPLICATION;
-
- parse_application_element (context,
- parse_data,
- attribute_names,
- attribute_values,
- &inner_error);
- if (inner_error)
- g_propagate_error (error, inner_error);
- }
- else
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Unexpected tag '%s', tag '%s' expected"),
- element_name,
- BOOKMARK_APPLICATION_ELEMENT);
- break;
- case STATE_GROUPS:
- if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_GROUP_ELEMENT))
- parse_data->state = STATE_GROUP;
- else
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- _("Unexpected tag '%s', tag '%s' expected"),
- element_name,
- BOOKMARK_GROUP_ELEMENT);
- break;
- case STATE_ICON:
- if (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_ICON_ELEMENT))
- {
- GError *inner_error = NULL;
-
- parse_icon_element (context,
- parse_data,
- attribute_names,
- attribute_values,
- &inner_error);
- if (inner_error)
- g_propagate_error (error, inner_error);
- }
- else
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_UNKNOWN_ELEMENT,
- _("Unexpected tag '%s' inside '%s'"),
- element_name,
- XBEL_METADATA_ELEMENT);
- break;
- default:
- g_warn_if_reached ();
- break;
- }
-}
-
-static void
-end_element_raw_cb (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer user_data,
- GError **error)
-{
- ParseData *parse_data = (ParseData *) user_data;
-
- if (IS_ELEMENT (parse_data, element_name, XBEL_ROOT_ELEMENT))
- parse_data->state = STATE_FINISHED;
- else if (IS_ELEMENT (parse_data, element_name, XBEL_BOOKMARK_ELEMENT))
- {
- parse_data->current_item = NULL;
-
- parse_data->state = STATE_ROOT;
- }
- else if ((IS_ELEMENT (parse_data, element_name, XBEL_INFO_ELEMENT)) ||
- (IS_ELEMENT (parse_data, element_name, XBEL_TITLE_ELEMENT)) ||
- (IS_ELEMENT (parse_data, element_name, XBEL_DESC_ELEMENT)))
- {
- if (parse_data->current_item)
- parse_data->state = STATE_BOOKMARK;
- else
- parse_data->state = STATE_ROOT;
- }
- else if (IS_ELEMENT (parse_data, element_name, XBEL_METADATA_ELEMENT))
- parse_data->state = STATE_INFO;
- else if (IS_ELEMENT_NS (parse_data, element_name,
- BOOKMARK_NAMESPACE_URI,
- BOOKMARK_APPLICATION_ELEMENT))
- parse_data->state = STATE_APPLICATIONS;
- else if (IS_ELEMENT_NS (parse_data, element_name,
- BOOKMARK_NAMESPACE_URI,
- BOOKMARK_GROUP_ELEMENT))
- parse_data->state = STATE_GROUPS;
- else if ((IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_APPLICATIONS_ELEMENT)) ||
- (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_GROUPS_ELEMENT)) ||
- (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_PRIVATE_ELEMENT)) ||
- (IS_ELEMENT_NS (parse_data, element_name, BOOKMARK_NAMESPACE_URI, BOOKMARK_ICON_ELEMENT)) ||
- (IS_ELEMENT_NS (parse_data, element_name, MIME_NAMESPACE_URI, MIME_TYPE_ELEMENT)))
- parse_data->state = STATE_METADATA;
-}
-
-static void
-text_raw_cb (GMarkupParseContext *context,
- const gchar *text,
- gsize length,
- gpointer user_data,
- GError **error)
-{
- ParseData *parse_data = (ParseData *) user_data;
- gchar *payload;
-
- payload = g_strndup (text, length);
-
- switch (parse_data->state)
- {
- case STATE_TITLE:
- if (parse_data->current_item)
- {
- g_free (parse_data->current_item->title);
- parse_data->current_item->title = g_strdup (payload);
- }
- else
- {
- g_free (parse_data->bookmark_file->title);
- parse_data->bookmark_file->title = g_strdup (payload);
- }
- break;
- case STATE_DESC:
- if (parse_data->current_item)
- {
- g_free (parse_data->current_item->description);
- parse_data->current_item->description = g_strdup (payload);
- }
- else
- {
- g_free (parse_data->bookmark_file->description);
- parse_data->bookmark_file->description = g_strdup (payload);
- }
- break;
- case STATE_GROUP:
- {
- GList *groups;
-
- g_warn_if_fail (parse_data->current_item != NULL);
-
- if (!parse_data->current_item->metadata)
- parse_data->current_item->metadata = bookmark_metadata_new ();
-
- groups = parse_data->current_item->metadata->groups;
- parse_data->current_item->metadata->groups = g_list_prepend (groups, g_strdup (payload));
- }
- break;
- case STATE_ROOT:
- case STATE_BOOKMARK:
- case STATE_INFO:
- case STATE_METADATA:
- case STATE_APPLICATIONS:
- case STATE_APPLICATION:
- case STATE_GROUPS:
- case STATE_MIME:
- case STATE_ICON:
- break;
- default:
- g_warn_if_reached ();
- break;
- }
-
- g_free (payload);
-}
-
-static const GMarkupParser markup_parser =
-{
- start_element_raw_cb, /* start_element */
- end_element_raw_cb, /* end_element */
- text_raw_cb, /* text */
- NULL, /* passthrough */
- NULL
-};
-
-static gboolean
-g_bookmark_file_parse (GBookmarkFile *bookmark,
- const gchar *buffer,
- gsize length,
- GError **error)
-{
- GMarkupParseContext *context;
- ParseData *parse_data;
- GError *parse_error, *end_error;
- gboolean retval;
-
- g_warn_if_fail (bookmark != NULL);
-
- if (!buffer)
- return FALSE;
-
- if (length == (gsize) -1)
- length = strlen (buffer);
-
- parse_data = parse_data_new ();
- parse_data->bookmark_file = bookmark;
-
- context = g_markup_parse_context_new (&markup_parser,
- 0,
- parse_data,
- (GDestroyNotify) parse_data_free);
-
- parse_error = NULL;
- retval = g_markup_parse_context_parse (context,
- buffer,
- length,
- &parse_error);
- if (!retval)
- {
- g_propagate_error (error, parse_error);
-
- return FALSE;
- }
-
- end_error = NULL;
- retval = g_markup_parse_context_end_parse (context, &end_error);
- if (!retval)
- {
- g_propagate_error (error, end_error);
-
- return FALSE;
- }
-
- g_markup_parse_context_free (context);
-
- return TRUE;
-}
-
-static gchar *
-g_bookmark_file_dump (GBookmarkFile *bookmark,
- gsize *length,
- GError **error)
-{
- GString *retval;
- gchar *buffer;
- GList *l;
-
- retval = g_string_sized_new (4096);
-
- g_string_append (retval,
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-#if 0
- /* XXX - do we really need the doctype? */
- "<!DOCTYPE " XBEL_DTD_NICK "\n"
- " PUBLIC \"" XBEL_DTD_SYSTEM "\"\n"
- " \"" XBEL_DTD_URI "\">\n"
-#endif
- "<" XBEL_ROOT_ELEMENT " " XBEL_VERSION_ATTRIBUTE "=\"" XBEL_VERSION "\"\n"
- " xmlns:" BOOKMARK_NAMESPACE_NAME "=\"" BOOKMARK_NAMESPACE_URI "\"\n"
- " xmlns:" MIME_NAMESPACE_NAME "=\"" MIME_NAMESPACE_URI "\"\n>");
-
- if (bookmark->title)
- {
- gchar *escaped_title;
-
- escaped_title = g_markup_escape_text (bookmark->title, -1);
-
- buffer = g_strconcat (" "
- "<" XBEL_TITLE_ELEMENT ">",
- escaped_title,
- "</" XBEL_TITLE_ELEMENT ">\n", NULL);
-
- g_string_append (retval, buffer);
-
- g_free (buffer);
- g_free (escaped_title);
- }
-
- if (bookmark->description)
- {
- gchar *escaped_desc;
-
- escaped_desc = g_markup_escape_text (bookmark->description, -1);
-
- buffer = g_strconcat (" "
- "<" XBEL_DESC_ELEMENT ">",
- escaped_desc,
- "</" XBEL_DESC_ELEMENT ">\n", NULL);
- g_string_append (retval, buffer);
-
- g_free (buffer);
- g_free (escaped_desc);
- }
-
- if (!bookmark->items)
- goto out;
- else
- retval = g_string_append (retval, "\n");
-
- /* the items are stored in reverse order */
- for (l = g_list_last (bookmark->items);
- l != NULL;
- l = l->prev)
- {
- BookmarkItem *item = (BookmarkItem *) l->data;
- gchar *item_dump;
-
- item_dump = bookmark_item_dump (item);
- if (!item_dump)
- continue;
-
- retval = g_string_append (retval, item_dump);
-
- g_free (item_dump);
- }
-
-out:
- g_string_append (retval, "</" XBEL_ROOT_ELEMENT ">");
-
- if (length)
- *length = retval->len;
-
- return g_string_free (retval, FALSE);
-}
-
-/**************
- * Misc *
- **************/
-
-/* converts a Unix timestamp in a ISO 8601 compliant string; you
- * should free the returned string.
- */
-static gchar *
-timestamp_to_iso8601 (time_t timestamp)
-{
- GTimeVal stamp;
-
- if (timestamp == (time_t) -1)
- g_get_current_time (&stamp);
- else
- {
- stamp.tv_sec = timestamp;
- stamp.tv_usec = 0;
- }
-
- return g_time_val_to_iso8601 (&stamp);
-}
-
-static time_t
-timestamp_from_iso8601 (const gchar *iso_date)
-{
- GTimeVal stamp;
-
- if (!g_time_val_from_iso8601 (iso_date, &stamp))
- return (time_t) -1;
-
- return (time_t) stamp.tv_sec;
-}
-
-
-
-GQuark
-g_bookmark_file_error_quark (void)
-{
- return g_quark_from_static_string ("g-bookmark-file-error-quark");
-}
-
-
-
-/********************
- * Public API *
- ********************/
-
-/**
- * g_bookmark_file_new:
- *
- * Creates a new empty #GBookmarkFile object.
- *
- * Use g_bookmark_file_load_from_file(), g_bookmark_file_load_from_data()
- * or g_bookmark_file_load_from_data_dirs() to read an existing bookmark
- * file.
- *
- * Return value: an empty #GBookmarkFile
- *
- * Since: 2.12
- */
-GBookmarkFile *
-g_bookmark_file_new (void)
-{
- GBookmarkFile *bookmark;
-
- bookmark = g_new (GBookmarkFile, 1);
-
- g_bookmark_file_init (bookmark);
-
- return bookmark;
-}
-
-/**
- * g_bookmark_file_free:
- * @bookmark: a #GBookmarkFile
- *
- * Frees a #GBookmarkFile.
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_free (GBookmarkFile *bookmark)
-{
- if (!bookmark)
- return;
-
- g_bookmark_file_clear (bookmark);
-
- g_free (bookmark);
-}
-
-/**
- * g_bookmark_file_load_from_data:
- * @bookmark: an empty #GBookmarkFile struct
- * @data: desktop bookmarks loaded in memory
- * @length: the length of @data in bytes
- * @error: return location for a #GError, or %NULL
- *
- * Loads a bookmark file from memory into an empty #GBookmarkFile
- * structure. If the object cannot be created then @error is set to a
- * #GBookmarkFileError.
- *
- * Return value: %TRUE if a desktop bookmark could be loaded.
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_load_from_data (GBookmarkFile *bookmark,
- const gchar *data,
- gsize length,
- GError **error)
-{
- GError *parse_error;
- gboolean retval;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (data != NULL, FALSE);
- g_return_val_if_fail (length != 0, FALSE);
-
- if (length == (gsize) -1)
- length = strlen (data);
-
- if (bookmark->items)
- {
- g_bookmark_file_clear (bookmark);
- g_bookmark_file_init (bookmark);
- }
-
- parse_error = NULL;
- retval = g_bookmark_file_parse (bookmark, data, length, &parse_error);
- if (!retval)
- {
- g_propagate_error (error, parse_error);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * g_bookmark_file_load_from_file:
- * @bookmark: an empty #GBookmarkFile struct
- * @filename: the path of a filename to load, in the GLib file name encoding
- * @error: return location for a #GError, or %NULL
- *
- * Loads a desktop bookmark file into an empty #GBookmarkFile structure.
- * If the file could not be loaded then @error is set to either a #GFileError
- * or #GBookmarkFileError.
- *
- * Return value: %TRUE if a desktop bookmark file could be loaded
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_load_from_file (GBookmarkFile *bookmark,
- const gchar *filename,
- GError **error)
-{
- gchar *buffer;
- gsize len;
- GError *read_error;
- gboolean retval;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (filename != NULL, FALSE);
-
- read_error = NULL;
- g_file_get_contents (filename, &buffer, &len, &read_error);
- if (read_error)
- {
- g_propagate_error (error, read_error);
-
- return FALSE;
- }
-
- read_error = NULL;
- retval = g_bookmark_file_load_from_data (bookmark,
- buffer,
- len,
- &read_error);
- if (read_error)
- {
- g_propagate_error (error, read_error);
-
- g_free (buffer);
-
- return FALSE;
- }
-
- g_free (buffer);
-
- return retval;
-}
-
-
-/* Iterates through all the directories in *dirs trying to
- * find file. When it successfully locates file, returns a
- * string its absolute path. It also leaves the unchecked
- * directories in *dirs. You should free the returned string
- *
- * Adapted from gkeyfile.c
- */
-static gchar *
-find_file_in_data_dirs (const gchar *file,
- gchar ***dirs,
- GError **error)
-{
- gchar **data_dirs, *data_dir, *path;
-
- path = NULL;
-
- if (dirs == NULL)
- return NULL;
-
- data_dirs = *dirs;
- path = NULL;
- while (data_dirs && (data_dir = *data_dirs) && !path)
- {
- gchar *candidate_file, *sub_dir;
-
- candidate_file = (gchar *) file;
- sub_dir = g_strdup ("");
- while (candidate_file != NULL && !path)
- {
- gchar *p;
-
- path = g_build_filename (data_dir, sub_dir,
- candidate_file, NULL);
-
- candidate_file = strchr (candidate_file, '-');
-
- if (candidate_file == NULL)
- break;
-
- candidate_file++;
-
- g_free (sub_dir);
- sub_dir = g_strndup (file, candidate_file - file - 1);
-
- for (p = sub_dir; *p != '\0'; p++)
- {
- if (*p == '-')
- *p = G_DIR_SEPARATOR;
- }
- }
- g_free (sub_dir);
- data_dirs++;
- }
-
- *dirs = data_dirs;
-
- if (!path)
- {
- g_set_error_literal (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_FILE_NOT_FOUND,
- _("No valid bookmark file found in data dirs"));
-
- return NULL;
- }
-
- return path;
-}
-
-
-/**
- * g_bookmark_file_load_from_data_dirs:
- * @bookmark: a #GBookmarkFile
- * @file: a relative path to a filename to open and parse
- * @full_path: return location for a string containing the full path
- * of the file, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * This function looks for a desktop bookmark file named @file in the
- * paths returned from g_get_user_data_dir() and g_get_system_data_dirs(),
- * loads the file into @bookmark and returns the file's full path in
- * @full_path. If the file could not be loaded then an %error is
- * set to either a #GFileError or #GBookmarkFileError.
- *
- * Return value: %TRUE if a key file could be loaded, %FALSE othewise
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_load_from_data_dirs (GBookmarkFile *bookmark,
- const gchar *file,
- gchar **full_path,
- GError **error)
-{
- GError *file_error = NULL;
- gchar **all_data_dirs, **data_dirs;
- const gchar *user_data_dir;
- const gchar * const * system_data_dirs;
- gsize i, j;
- gchar *output_path;
- gboolean found_file;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (!g_path_is_absolute (file), FALSE);
-
- user_data_dir = g_get_user_data_dir ();
- system_data_dirs = g_get_system_data_dirs ();
- all_data_dirs = g_new0 (gchar *, g_strv_length ((gchar **)system_data_dirs) + 2);
-
- i = 0;
- all_data_dirs[i++] = g_strdup (user_data_dir);
-
- j = 0;
- while (system_data_dirs[j] != NULL)
- all_data_dirs[i++] = g_strdup (system_data_dirs[j++]);
-
- found_file = FALSE;
- data_dirs = all_data_dirs;
- output_path = NULL;
- while (*data_dirs != NULL && !found_file)
- {
- g_free (output_path);
-
- output_path = find_file_in_data_dirs (file, &data_dirs, &file_error);
-
- if (file_error)
- {
- g_propagate_error (error, file_error);
- break;
- }
-
- found_file = g_bookmark_file_load_from_file (bookmark,
- output_path,
- &file_error);
- if (file_error)
- {
- g_propagate_error (error, file_error);
- break;
- }
- }
-
- if (found_file && full_path)
- *full_path = output_path;
- else
- g_free (output_path);
-
- g_strfreev (all_data_dirs);
-
- return found_file;
-}
-
-
-/**
- * g_bookmark_file_to_data:
- * @bookmark: a #GBookmarkFile
- * @length: return location for the length of the returned string, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * This function outputs @bookmark as a string.
- *
- * Return value: a newly allocated string holding
- * the contents of the #GBookmarkFile
- *
- * Since: 2.12
- */
-gchar *
-g_bookmark_file_to_data (GBookmarkFile *bookmark,
- gsize *length,
- GError **error)
-{
- GError *write_error = NULL;
- gchar *retval;
-
- g_return_val_if_fail (bookmark != NULL, NULL);
-
- retval = g_bookmark_file_dump (bookmark, length, &write_error);
- if (write_error)
- {
- g_propagate_error (error, write_error);
-
- return NULL;
- }
-
- return retval;
-}
-
-/**
- * g_bookmark_file_to_file:
- * @bookmark: a #GBookmarkFile
- * @filename: path of the output file
- * @error: return location for a #GError, or %NULL
- *
- * This function outputs @bookmark into a file. The write process is
- * guaranteed to be atomic by using g_file_set_contents() internally.
- *
- * Return value: %TRUE if the file was successfully written.
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_to_file (GBookmarkFile *bookmark,
- const gchar *filename,
- GError **error)
-{
- gchar *data;
- GError *data_error, *write_error;
- gsize len;
- gboolean retval;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (filename != NULL, FALSE);
-
- data_error = NULL;
- data = g_bookmark_file_to_data (bookmark, &len, &data_error);
- if (data_error)
- {
- g_propagate_error (error, data_error);
-
- return FALSE;
- }
-
- write_error = NULL;
- g_file_set_contents (filename, data, len, &write_error);
- if (write_error)
- {
- g_propagate_error (error, write_error);
-
- retval = FALSE;
- }
- else
- retval = TRUE;
-
- g_free (data);
-
- return retval;
-}
-
-static BookmarkItem *
-g_bookmark_file_lookup_item (GBookmarkFile *bookmark,
- const gchar *uri)
-{
- g_warn_if_fail (bookmark != NULL && uri != NULL);
-
- return g_hash_table_lookup (bookmark->items_by_uri, uri);
-}
-
-/* this function adds a new item to the list */
-static void
-g_bookmark_file_add_item (GBookmarkFile *bookmark,
- BookmarkItem *item,
- GError **error)
-{
- g_warn_if_fail (bookmark != NULL);
- g_warn_if_fail (item != NULL);
-
- /* this should never happen; and if it does, then we are
- * screwing up something big time.
- */
- if (G_UNLIKELY (g_bookmark_file_has_item (bookmark, item->uri)))
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_INVALID_URI,
- _("A bookmark for URI '%s' already exists"),
- item->uri);
- return;
- }
-
- bookmark->items = g_list_prepend (bookmark->items, item);
-
- g_hash_table_replace (bookmark->items_by_uri,
- item->uri,
- item);
-
- if (item->added == (time_t) -1)
- item->added = time (NULL);
-
- if (item->modified == (time_t) -1)
- item->modified = time (NULL);
-}
-
-/**
- * g_bookmark_file_remove_item:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @error: return location for a #GError, or %NULL
- *
- * Removes the bookmark for @uri from the bookmark file @bookmark.
- *
- * Return value: %TRUE if the bookmark was removed successfully.
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_remove_item (GBookmarkFile *bookmark,
- const gchar *uri,
- GError **error)
-{
- BookmarkItem *item;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
-
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return FALSE;
- }
-
- bookmark->items = g_list_remove (bookmark->items, item);
- g_hash_table_remove (bookmark->items_by_uri, item->uri);
-
- bookmark_item_free (item);
-
- return TRUE;
-}
-
-/**
- * g_bookmark_file_has_item:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- *
- * Looks whether the desktop bookmark has an item with its URI set to @uri.
- *
- * Return value: %TRUE if @uri is inside @bookmark, %FALSE otherwise
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_has_item (GBookmarkFile *bookmark,
- const gchar *uri)
-{
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
-
- return (NULL != g_hash_table_lookup (bookmark->items_by_uri, uri));
-}
-
-/**
- * g_bookmark_file_get_uris:
- * @bookmark: a #GBookmarkFile
- * @length: return location for the number of returned URIs, or %NULL
- *
- * Returns all URIs of the bookmarks in the bookmark file @bookmark.
- * The array of returned URIs will be %NULL-terminated, so @length may
- * optionally be %NULL.
- *
- * Return value: a newly allocated %NULL-terminated array of strings.
- * Use g_strfreev() to free it.
- *
- * Since: 2.12
- */
-gchar **
-g_bookmark_file_get_uris (GBookmarkFile *bookmark,
- gsize *length)
-{
- GList *l;
- gchar **uris;
- gsize i, n_items;
-
- g_return_val_if_fail (bookmark != NULL, NULL);
-
- n_items = g_list_length (bookmark->items);
- uris = g_new0 (gchar *, n_items + 1);
-
- /* the items are stored in reverse order, so we walk the list backward */
- for (l = g_list_last (bookmark->items), i = 0; l != NULL; l = l->prev)
- {
- BookmarkItem *item = (BookmarkItem *) l->data;
-
- g_warn_if_fail (item != NULL);
-
- uris[i++] = g_strdup (item->uri);
- }
- uris[i] = NULL;
-
- if (length)
- *length = i;
-
- return uris;
-}
-
-/**
- * g_bookmark_file_set_title:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI or %NULL
- * @title: a UTF-8 encoded string
- *
- * Sets @title as the title of the bookmark for @uri inside the
- * bookmark file @bookmark.
- *
- * If @uri is %NULL, the title of @bookmark is set.
- *
- * If a bookmark for @uri cannot be found then it is created.
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_set_title (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *title)
-{
- g_return_if_fail (bookmark != NULL);
-
- if (!uri)
- {
- g_free (bookmark->title);
- bookmark->title = g_strdup (title);
- }
- else
- {
- BookmarkItem *item;
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
-
- g_free (item->title);
- item->title = g_strdup (title);
-
- item->modified = time (NULL);
- }
-}
-
-/**
- * g_bookmark_file_get_title:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Returns the title of the bookmark for @uri.
- *
- * If @uri is %NULL, the title of @bookmark is returned.
- *
- * In the event the URI cannot be found, %NULL is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- *
- * Return value: a newly allocated string or %NULL if the specified
- * URI cannot be found.
- *
- * Since: 2.12
- */
-gchar *
-g_bookmark_file_get_title (GBookmarkFile *bookmark,
- const gchar *uri,
- GError **error)
-{
- BookmarkItem *item;
-
- g_return_val_if_fail (bookmark != NULL, NULL);
-
- if (!uri)
- return g_strdup (bookmark->title);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return NULL;
- }
-
- return g_strdup (item->title);
-}
-
-/**
- * g_bookmark_file_set_description:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI or %NULL
- * @description: a string
- *
- * Sets @description as the description of the bookmark for @uri.
- *
- * If @uri is %NULL, the description of @bookmark is set.
- *
- * If a bookmark for @uri cannot be found then it is created.
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_set_description (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *description)
-{
- g_return_if_fail (bookmark != NULL);
-
- if (!uri)
- {
- g_free (bookmark->description);
- bookmark->description = g_strdup (description);
- }
- else
- {
- BookmarkItem *item;
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
-
- g_free (item->description);
- item->description = g_strdup (description);
-
- item->modified = time (NULL);
- }
-}
-
-/**
- * g_bookmark_file_get_description:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @error: return location for a #GError, or %NULL
- *
- * Retrieves the description of the bookmark for @uri.
- *
- * In the event the URI cannot be found, %NULL is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- *
- * Return value: a newly allocated string or %NULL if the specified
- * URI cannot be found.
- *
- * Since: 2.12
- */
-gchar *
-g_bookmark_file_get_description (GBookmarkFile *bookmark,
- const gchar *uri,
- GError **error)
-{
- BookmarkItem *item;
-
- g_return_val_if_fail (bookmark != NULL, NULL);
-
- if (!uri)
- return g_strdup (bookmark->description);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return NULL;
- }
-
- return g_strdup (item->description);
-}
-
-/**
- * g_bookmark_file_set_mime_type:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @mime_type: a MIME type
- *
- * Sets @mime_type as the MIME type of the bookmark for @uri.
- *
- * If a bookmark for @uri cannot be found then it is created.
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_set_mime_type (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *mime_type)
-{
- BookmarkItem *item;
-
- g_return_if_fail (bookmark != NULL);
- g_return_if_fail (uri != NULL);
- g_return_if_fail (mime_type != NULL);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
-
- if (!item->metadata)
- item->metadata = bookmark_metadata_new ();
-
- g_free (item->metadata->mime_type);
-
- item->metadata->mime_type = g_strdup (mime_type);
- item->modified = time (NULL);
-}
-
-/**
- * g_bookmark_file_get_mime_type:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @error: return location for a #GError, or %NULL
- *
- * Retrieves the MIME type of the resource pointed by @uri.
- *
- * In the event the URI cannot be found, %NULL is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. In the
- * event that the MIME type cannot be found, %NULL is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_INVALID_VALUE.
- *
- * Return value: a newly allocated string or %NULL if the specified
- * URI cannot be found.
- *
- * Since: 2.12
- */
-gchar *
-g_bookmark_file_get_mime_type (GBookmarkFile *bookmark,
- const gchar *uri,
- GError **error)
-{
- BookmarkItem *item;
-
- g_return_val_if_fail (bookmark != NULL, NULL);
- g_return_val_if_fail (uri != NULL, NULL);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return NULL;
- }
-
- if (!item->metadata)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_INVALID_VALUE,
- _("No MIME type defined in the bookmark for URI '%s'"),
- uri);
- return NULL;
- }
-
- return g_strdup (item->metadata->mime_type);
-}
-
-/**
- * g_bookmark_file_set_is_private:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @is_private: %TRUE if the bookmark should be marked as private
- *
- * Sets the private flag of the bookmark for @uri.
- *
- * If a bookmark for @uri cannot be found then it is created.
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_set_is_private (GBookmarkFile *bookmark,
- const gchar *uri,
- gboolean is_private)
-{
- BookmarkItem *item;
-
- g_return_if_fail (bookmark != NULL);
- g_return_if_fail (uri != NULL);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
-
- if (!item->metadata)
- item->metadata = bookmark_metadata_new ();
-
- item->metadata->is_private = (is_private == TRUE);
- item->modified = time (NULL);
-}
-
-/**
- * g_bookmark_file_get_is_private:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @error: return location for a #GError, or %NULL
- *
- * Gets whether the private flag of the bookmark for @uri is set.
- *
- * In the event the URI cannot be found, %FALSE is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. In the
- * event that the private flag cannot be found, %FALSE is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_INVALID_VALUE.
- *
- * Return value: %TRUE if the private flag is set, %FALSE otherwise.
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_get_is_private (GBookmarkFile *bookmark,
- const gchar *uri,
- GError **error)
-{
- BookmarkItem *item;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return FALSE;
- }
-
- if (!item->metadata)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_INVALID_VALUE,
- _("No private flag has been defined in bookmark for URI '%s'"),
- uri);
- return FALSE;
- }
-
- return item->metadata->is_private;
-}
-
-/**
- * g_bookmark_file_set_added:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @added: a timestamp or -1 to use the current time
- *
- * Sets the time the bookmark for @uri was added into @bookmark.
- *
- * If no bookmark for @uri is found then it is created.
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_set_added (GBookmarkFile *bookmark,
- const gchar *uri,
- time_t added)
-{
- BookmarkItem *item;
-
- g_return_if_fail (bookmark != NULL);
- g_return_if_fail (uri != NULL);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
-
- if (added == (time_t) -1)
- time (&added);
-
- item->added = added;
- item->modified = added;
-}
-
-/**
- * g_bookmark_file_get_added:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @error: return location for a #GError, or %NULL
- *
- * Gets the time the bookmark for @uri was added to @bookmark
- *
- * In the event the URI cannot be found, -1 is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- *
- * Return value: a timestamp
- *
- * Since: 2.12
- */
-time_t
-g_bookmark_file_get_added (GBookmarkFile *bookmark,
- const gchar *uri,
- GError **error)
-{
- BookmarkItem *item;
-
- g_return_val_if_fail (bookmark != NULL, (time_t) -1);
- g_return_val_if_fail (uri != NULL, (time_t) -1);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return (time_t) -1;
- }
-
- return item->added;
-}
-
-/**
- * g_bookmark_file_set_modified:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @modified: a timestamp or -1 to use the current time
- *
- * Sets the last time the bookmark for @uri was last modified.
- *
- * If no bookmark for @uri is found then it is created.
- *
- * The "modified" time should only be set when the bookmark's meta-data
- * was actually changed. Every function of #GBookmarkFile that
- * modifies a bookmark also changes the modification time, except for
- * g_bookmark_file_set_visited().
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_set_modified (GBookmarkFile *bookmark,
- const gchar *uri,
- time_t modified)
-{
- BookmarkItem *item;
-
- g_return_if_fail (bookmark != NULL);
- g_return_if_fail (uri != NULL);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
-
- if (modified == (time_t) -1)
- time (&modified);
-
- item->modified = modified;
-}
-
-/**
- * g_bookmark_file_get_modified:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @error: return location for a #GError, or %NULL
- *
- * Gets the time when the bookmark for @uri was last modified.
- *
- * In the event the URI cannot be found, -1 is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- *
- * Return value: a timestamp
- *
- * Since: 2.12
- */
-time_t
-g_bookmark_file_get_modified (GBookmarkFile *bookmark,
- const gchar *uri,
- GError **error)
-{
- BookmarkItem *item;
-
- g_return_val_if_fail (bookmark != NULL, (time_t) -1);
- g_return_val_if_fail (uri != NULL, (time_t) -1);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return (time_t) -1;
- }
-
- return item->modified;
-}
-
-/**
- * g_bookmark_file_set_visited:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @visited: a timestamp or -1 to use the current time
- *
- * Sets the time the bookmark for @uri was last visited.
- *
- * If no bookmark for @uri is found then it is created.
- *
- * The "visited" time should only be set if the bookmark was launched,
- * either using the command line retrieved by g_bookmark_file_get_app_info()
- * or by the default application for the bookmark's MIME type, retrieved
- * using g_bookmark_file_get_mime_type(). Changing the "visited" time
- * does not affect the "modified" time.
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_set_visited (GBookmarkFile *bookmark,
- const gchar *uri,
- time_t visited)
-{
- BookmarkItem *item;
-
- g_return_if_fail (bookmark != NULL);
- g_return_if_fail (uri != NULL);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
-
- if (visited == (time_t) -1)
- time (&visited);
-
- item->visited = visited;
-}
-
-/**
- * g_bookmark_file_get_visited:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @error: return location for a #GError, or %NULL
- *
- * Gets the time the bookmark for @uri was last visited.
- *
- * In the event the URI cannot be found, -1 is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- *
- * Return value: a timestamp.
- *
- * Since: 2.12
- */
-time_t
-g_bookmark_file_get_visited (GBookmarkFile *bookmark,
- const gchar *uri,
- GError **error)
-{
- BookmarkItem *item;
-
- g_return_val_if_fail (bookmark != NULL, (time_t) -1);
- g_return_val_if_fail (uri != NULL, (time_t) -1);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return (time_t) -1;
- }
-
- return item->visited;
-}
-
-/**
- * g_bookmark_file_has_group:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @group: the group name to be searched
- * @error: return location for a #GError, or %NULL
- *
- * Checks whether @group appears in the list of groups to which
- * the bookmark for @uri belongs to.
- *
- * In the event the URI cannot be found, %FALSE is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- *
- * Return value: %TRUE if @group was found.
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_has_group (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *group,
- GError **error)
-{
- BookmarkItem *item;
- GList *l;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return FALSE;
- }
-
- if (!item->metadata)
- return FALSE;
-
- for (l = item->metadata->groups; l != NULL; l = l->next)
- {
- if (strcmp (l->data, group) == 0)
- return TRUE;
- }
-
- return FALSE;
-
-}
-
-/**
- * g_bookmark_file_add_group:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @group: the group name to be added
- *
- * Adds @group to the list of groups to which the bookmark for @uri
- * belongs to.
- *
- * If no bookmark for @uri is found then it is created.
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_add_group (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *group)
-{
- BookmarkItem *item;
-
- g_return_if_fail (bookmark != NULL);
- g_return_if_fail (uri != NULL);
- g_return_if_fail (group != NULL && group[0] != '\0');
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
-
- if (!item->metadata)
- item->metadata = bookmark_metadata_new ();
-
- if (!g_bookmark_file_has_group (bookmark, uri, group, NULL))
- {
- item->metadata->groups = g_list_prepend (item->metadata->groups,
- g_strdup (group));
-
- item->modified = time (NULL);
- }
-}
-
-/**
- * g_bookmark_file_remove_group:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @group: the group name to be removed
- * @error: return location for a #GError, or %NULL
- *
- * Removes @group from the list of groups to which the bookmark
- * for @uri belongs to.
- *
- * In the event the URI cannot be found, %FALSE is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- * In the event no group was defined, %FALSE is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_INVALID_VALUE.
- *
- * Return value: %TRUE if @group was successfully removed.
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_remove_group (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *group,
- GError **error)
-{
- BookmarkItem *item;
- GList *l;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return FALSE;
- }
-
- if (!item->metadata)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_INVALID_VALUE,
- _("No groups set in bookmark for URI '%s'"),
- uri);
- return FALSE;
- }
-
- for (l = item->metadata->groups; l != NULL; l = l->next)
- {
- if (strcmp (l->data, group) == 0)
- {
- item->metadata->groups = g_list_remove_link (item->metadata->groups, l);
- g_free (l->data);
- g_list_free_1 (l);
-
- item->modified = time (NULL);
-
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/**
- * g_bookmark_file_set_groups:
- * @bookmark: a #GBookmarkFile
- * @uri: an item's URI
- * @groups: an array of group names, or %NULL to remove all groups
- * @length: number of group name values in @groups
- *
- * Sets a list of group names for the item with URI @uri. Each previously
- * set group name list is removed.
- *
- * If @uri cannot be found then an item for it is created.
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_set_groups (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar **groups,
- gsize length)
-{
- BookmarkItem *item;
- gsize i;
-
- g_return_if_fail (bookmark != NULL);
- g_return_if_fail (uri != NULL);
- g_return_if_fail (groups != NULL);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
-
- if (!item->metadata)
- item->metadata = bookmark_metadata_new ();
-
- if (item->metadata->groups != NULL)
- {
- g_list_foreach (item->metadata->groups,
- (GFunc) g_free,
- NULL);
- g_list_free (item->metadata->groups);
- item->metadata->groups = NULL;
- }
-
- if (groups)
- {
- for (i = 0; groups[i] != NULL && i < length; i++)
- item->metadata->groups = g_list_append (item->metadata->groups,
- g_strdup (groups[i]));
- }
-
- item->modified = time (NULL);
-}
-
-/**
- * g_bookmark_file_get_groups:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @length: return location for the length of the returned string, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Retrieves the list of group names of the bookmark for @uri.
- *
- * In the event the URI cannot be found, %NULL is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- *
- * The returned array is %NULL terminated, so @length may optionally
- * be %NULL.
- *
- * Return value: a newly allocated %NULL-terminated array of group names.
- * Use g_strfreev() to free it.
- *
- * Since: 2.12
- */
-gchar **
-g_bookmark_file_get_groups (GBookmarkFile *bookmark,
- const gchar *uri,
- gsize *length,
- GError **error)
-{
- BookmarkItem *item;
- GList *l;
- gsize len, i;
- gchar **retval;
-
- g_return_val_if_fail (bookmark != NULL, NULL);
- g_return_val_if_fail (uri != NULL, NULL);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return NULL;
- }
-
- if (!item->metadata)
- {
- if (length)
- *length = 0;
-
- return NULL;
- }
-
- len = g_list_length (item->metadata->groups);
- retval = g_new0 (gchar *, len + 1);
- for (l = g_list_last (item->metadata->groups), i = 0;
- l != NULL;
- l = l->prev)
- {
- gchar *group_name = (gchar *) l->data;
-
- g_warn_if_fail (group_name != NULL);
-
- retval[i++] = g_strdup (group_name);
- }
- retval[i] = NULL;
-
- if (length)
- *length = len;
-
- return retval;
-}
-
-/**
- * g_bookmark_file_add_application:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @name: the name of the application registering the bookmark
- * or %NULL
- * @exec: command line to be used to launch the bookmark or %NULL
- *
- * Adds the application with @name and @exec to the list of
- * applications that have registered a bookmark for @uri into
- * @bookmark.
- *
- * Every bookmark inside a #GBookmarkFile must have at least an
- * application registered. Each application must provide a name, a
- * command line useful for launching the bookmark, the number of times
- * the bookmark has been registered by the application and the last
- * time the application registered this bookmark.
- *
- * If @name is %NULL, the name of the application will be the
- * same returned by g_get_application_name(); if @exec is %NULL, the
- * command line will be a composition of the program name as
- * returned by g_get_prgname() and the "%u" modifier, which will be
- * expanded to the bookmark's URI.
- *
- * This function will automatically take care of updating the
- * registrations count and timestamping in case an application
- * with the same @name had already registered a bookmark for
- * @uri inside @bookmark.
- *
- * If no bookmark for @uri is found, one is created.
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_add_application (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *name,
- const gchar *exec)
-{
- BookmarkItem *item;
- gchar *app_name, *app_exec;
-
- g_return_if_fail (bookmark != NULL);
- g_return_if_fail (uri != NULL);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
-
- if (name && name[0] != '\0')
- app_name = g_strdup (name);
- else
- app_name = g_strdup (g_get_application_name ());
-
- if (exec && exec[0] != '\0')
- app_exec = g_strdup (exec);
- else
- app_exec = g_strjoin (" ", g_get_prgname(), "%u", NULL);
-
- g_bookmark_file_set_app_info (bookmark, uri,
- app_name,
- app_exec,
- -1,
- (time_t) -1,
- NULL);
-
- g_free (app_exec);
- g_free (app_name);
-}
-
-/**
- * g_bookmark_file_remove_application:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @name: the name of the application
- * @error: return location for a #GError or %NULL
- *
- * Removes application registered with @name from the list of applications
- * that have registered a bookmark for @uri inside @bookmark.
- *
- * In the event the URI cannot be found, %FALSE is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- * In the event that no application with name @app_name has registered
- * a bookmark for @uri, %FALSE is returned and error is set to
- * #G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED.
- *
- * Return value: %TRUE if the application was successfully removed.
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_remove_application (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *name,
- GError **error)
-{
- GError *set_error;
- gboolean retval;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
-
- set_error = NULL;
- retval = g_bookmark_file_set_app_info (bookmark, uri,
- name,
- "",
- 0,
- (time_t) -1,
- &set_error);
- if (set_error)
- {
- g_propagate_error (error, set_error);
-
- return FALSE;
- }
-
- return retval;
-}
-
-/**
- * g_bookmark_file_has_application:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @name: the name of the application
- * @error: return location for a #GError or %NULL
- *
- * Checks whether the bookmark for @uri inside @bookmark has been
- * registered by application @name.
- *
- * In the event the URI cannot be found, %FALSE is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- *
- * Return value: %TRUE if the application @name was found
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_has_application (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *name,
- GError **error)
-{
- BookmarkItem *item;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return FALSE;
- }
-
- return (NULL != bookmark_item_lookup_app_info (item, name));
-}
-
-/**
- * g_bookmark_file_set_app_info:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @name: an application's name
- * @exec: an application's command line
- * @count: the number of registrations done for this application
- * @stamp: the time of the last registration for this application
- * @error: return location for a #GError or %NULL
- *
- * Sets the meta-data of application @name inside the list of
- * applications that have registered a bookmark for @uri inside
- * @bookmark.
- *
- * You should rarely use this function; use g_bookmark_file_add_application()
- * and g_bookmark_file_remove_application() instead.
- *
- * @name can be any UTF-8 encoded string used to identify an
- * application.
- * @exec can have one of these two modifiers: "%f", which will
- * be expanded as the local file name retrieved from the bookmark's
- * URI; "%u", which will be expanded as the bookmark's URI.
- * The expansion is done automatically when retrieving the stored
- * command line using the g_bookmark_file_get_app_info() function.
- * @count is the number of times the application has registered the
- * bookmark; if is < 0, the current registration count will be increased
- * by one, if is 0, the application with @name will be removed from
- * the list of registered applications.
- * @stamp is the Unix time of the last registration; if it is -1, the
- * current time will be used.
- *
- * If you try to remove an application by setting its registration count to
- * zero, and no bookmark for @uri is found, %FALSE is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND; similarly,
- * in the event that no application @name has registered a bookmark
- * for @uri, %FALSE is returned and error is set to
- * #G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED. Otherwise, if no bookmark
- * for @uri is found, one is created.
- *
- * Return value: %TRUE if the application's meta-data was successfully
- * changed.
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_set_app_info (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *name,
- const gchar *exec,
- gint count,
- time_t stamp,
- GError **error)
-{
- BookmarkItem *item;
- BookmarkAppInfo *ai;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
- g_return_val_if_fail (exec != NULL, FALSE);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- if (count == 0)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return FALSE;
- }
- else
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
- }
-
- ai = bookmark_item_lookup_app_info (item, name);
- if (!ai)
- {
- if (count == 0)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED,
- _("No application with name '%s' registered a bookmark for '%s'"),
- name,
- uri);
- return FALSE;
- }
- else
- {
- ai = bookmark_app_info_new (name);
-
- item->metadata->applications = g_list_prepend (item->metadata->applications, ai);
- g_hash_table_replace (item->metadata->apps_by_name, ai->name, ai);
- }
- }
-
- if (count == 0)
- {
- item->metadata->applications = g_list_remove (item->metadata->applications, ai);
- g_hash_table_remove (item->metadata->apps_by_name, ai->name);
- bookmark_app_info_free (ai);
-
- item->modified = time (NULL);
-
- return TRUE;
- }
- else if (count > 0)
- ai->count = count;
- else
- ai->count += 1;
-
- if (stamp != (time_t) -1)
- ai->stamp = stamp;
- else
- ai->stamp = time (NULL);
-
- if (exec && exec[0] != '\0')
- {
- g_free (ai->exec);
- ai->exec = g_shell_quote (exec);
- }
-
- item->modified = time (NULL);
-
- return TRUE;
-}
-
-/* expands the application's command line */
-static gchar *
-expand_exec_line (const gchar *exec_fmt,
- const gchar *uri)
-{
- GString *exec;
- gchar ch;
-
- exec = g_string_sized_new (512);
- while ((ch = *exec_fmt++) != '\0')
- {
- if (ch != '%')
- {
- exec = g_string_append_c (exec, ch);
- continue;
- }
-
- ch = *exec_fmt++;
- switch (ch)
- {
- case '\0':
- goto out;
- case 'U':
- case 'u':
- g_string_append (exec, uri);
- break;
- case 'F':
- case 'f':
- {
- gchar *file = g_filename_from_uri (uri, NULL, NULL);
- if (file)
- {
- g_string_append (exec, file);
- g_free (file);
- }
- else
- {
- g_string_free (exec, TRUE);
- return NULL;
- }
- }
- break;
- case '%':
- default:
- exec = g_string_append_c (exec, ch);
- break;
- }
- }
-
- out:
- return g_string_free (exec, FALSE);
-}
-
-/**
- * g_bookmark_file_get_app_info:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @name: an application's name
- * @exec: location for the command line of the application, or %NULL
- * @count: return location for the registration count, or %NULL
- * @stamp: return location for the last registration time, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Gets the registration informations of @app_name for the bookmark for
- * @uri. See g_bookmark_file_set_app_info() for more informations about
- * the returned data.
- *
- * The string returned in @app_exec must be freed.
- *
- * In the event the URI cannot be found, %FALSE is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND. In the
- * event that no application with name @app_name has registered a bookmark
- * for @uri, %FALSE is returned and error is set to
- * #G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED. In the event that unquoting
- * the command line fails, an error of the #G_SHELL_ERROR domain is
- * set and %FALSE is returned.
- *
- * Return value: %TRUE on success.
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_get_app_info (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *name,
- gchar **exec,
- guint *count,
- time_t *stamp,
- GError **error)
-{
- BookmarkItem *item;
- BookmarkAppInfo *ai;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return FALSE;
- }
-
- ai = bookmark_item_lookup_app_info (item, name);
- if (!ai)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_APP_NOT_REGISTERED,
- _("No application with name '%s' registered a bookmark for '%s'"),
- name,
- uri);
- return FALSE;
- }
-
- if (exec)
- {
- GError *unquote_error = NULL;
- gchar *command_line;
-
- command_line = g_shell_unquote (ai->exec, &unquote_error);
- if (unquote_error)
- {
- g_propagate_error (error, unquote_error);
- return FALSE;
- }
-
- *exec = expand_exec_line (command_line, uri);
- if (!*exec)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_INVALID_URI,
- _("Failed to expand exec line '%s' with URI '%s'"),
- ai->exec, uri);
- g_free (command_line);
-
- return FALSE;
- }
- else
- g_free (command_line);
- }
-
- if (count)
- *count = ai->count;
-
- if (stamp)
- *stamp = ai->stamp;
-
- return TRUE;
-}
-
-/**
- * g_bookmark_file_get_applications:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @length: return location of the length of the returned list, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Retrieves the names of the applications that have registered the
- * bookmark for @uri.
- *
- * In the event the URI cannot be found, %NULL is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- *
- * Return value: a newly allocated %NULL-terminated array of strings.
- * Use g_strfreev() to free it.
- *
- * Since: 2.12
- */
-gchar **
-g_bookmark_file_get_applications (GBookmarkFile *bookmark,
- const gchar *uri,
- gsize *length,
- GError **error)
-{
- BookmarkItem *item;
- GList *l;
- gchar **apps;
- gsize i, n_apps;
-
- g_return_val_if_fail (bookmark != NULL, NULL);
- g_return_val_if_fail (uri != NULL, NULL);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return NULL;
- }
-
- if (!item->metadata)
- {
- if (length)
- *length = 0;
-
- return NULL;
- }
-
- n_apps = g_list_length (item->metadata->applications);
- apps = g_new0 (gchar *, n_apps + 1);
-
- for (l = g_list_last (item->metadata->applications), i = 0;
- l != NULL;
- l = l->prev)
- {
- BookmarkAppInfo *ai;
-
- ai = (BookmarkAppInfo *) l->data;
-
- g_warn_if_fail (ai != NULL);
- g_warn_if_fail (ai->name != NULL);
-
- apps[i++] = g_strdup (ai->name);
- }
- apps[i] = NULL;
-
- if (length)
- *length = i;
-
- return apps;
-}
-
-/**
- * g_bookmark_file_get_size:
- * @bookmark: a #GBookmarkFile
- *
- * Gets the number of bookmarks inside @bookmark.
- *
- * Return value: the number of bookmarks
- *
- * Since: 2.12
- */
-gint
-g_bookmark_file_get_size (GBookmarkFile *bookmark)
-{
- g_return_val_if_fail (bookmark != NULL, 0);
-
- return g_list_length (bookmark->items);
-}
-
-/**
- * g_bookmark_file_move_item:
- * @bookmark: a #GBookmarkFile
- * @old_uri: a valid URI
- * @new_uri: a valid URI, or %NULL
- * @error: return location for a #GError or %NULL
- *
- * Changes the URI of a bookmark item from @old_uri to @new_uri. Any
- * existing bookmark for @new_uri will be overwritten. If @new_uri is
- * %NULL, then the bookmark is removed.
- *
- * In the event the URI cannot be found, %FALSE is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- *
- * Return value: %TRUE if the URI was successfully changed
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_move_item (GBookmarkFile *bookmark,
- const gchar *old_uri,
- const gchar *new_uri,
- GError **error)
-{
- BookmarkItem *item;
- GError *remove_error;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (old_uri != NULL, FALSE);
-
- item = g_bookmark_file_lookup_item (bookmark, old_uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- old_uri);
- return FALSE;
- }
-
- if (new_uri && new_uri[0] != '\0')
- {
- if (g_bookmark_file_has_item (bookmark, new_uri))
- {
- remove_error = NULL;
- g_bookmark_file_remove_item (bookmark, new_uri, &remove_error);
- if (remove_error)
- {
- g_propagate_error (error, remove_error);
-
- return FALSE;
- }
- }
-
- g_hash_table_steal (bookmark->items_by_uri, item->uri);
-
- g_free (item->uri);
- item->uri = g_strdup (new_uri);
- item->modified = time (NULL);
-
- g_hash_table_replace (bookmark->items_by_uri, item->uri, item);
-
- return TRUE;
- }
- else
- {
- remove_error = NULL;
- g_bookmark_file_remove_item (bookmark, old_uri, &remove_error);
- if (remove_error)
- {
- g_propagate_error (error, remove_error);
-
- return FALSE;
- }
-
- return TRUE;
- }
-}
-
-/**
- * g_bookmark_file_set_icon:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @href: the URI of the icon for the bookmark, or %NULL
- * @mime_type: the MIME type of the icon for the bookmark
- *
- * Sets the icon for the bookmark for @uri. If @href is %NULL, unsets
- * the currently set icon. @href can either be a full URL for the icon
- * file or the icon name following the Icon Naming specification.
- *
- * If no bookmark for @uri is found one is created.
- *
- * Since: 2.12
- */
-void
-g_bookmark_file_set_icon (GBookmarkFile *bookmark,
- const gchar *uri,
- const gchar *href,
- const gchar *mime_type)
-{
- BookmarkItem *item;
-
- g_return_if_fail (bookmark != NULL);
- g_return_if_fail (uri != NULL);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- item = bookmark_item_new (uri);
- g_bookmark_file_add_item (bookmark, item, NULL);
- }
-
- if (!item->metadata)
- item->metadata = bookmark_metadata_new ();
-
- g_free (item->metadata->icon_href);
- g_free (item->metadata->icon_mime);
-
- item->metadata->icon_href = g_strdup (href);
-
- if (mime_type && mime_type[0] != '\0')
- item->metadata->icon_mime = g_strdup (mime_type);
- else
- item->metadata->icon_mime = g_strdup ("application/octet-stream");
-
- item->modified = time (NULL);
-}
-
-/**
- * g_bookmark_file_get_icon:
- * @bookmark: a #GBookmarkFile
- * @uri: a valid URI
- * @href: return location for the icon's location or %NULL
- * @mime_type: return location for the icon's MIME type or %NULL
- * @error: return location for a #GError or %NULL
- *
- * Gets the icon of the bookmark for @uri.
- *
- * In the event the URI cannot be found, %FALSE is returned and
- * @error is set to #G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND.
- *
- * Return value: %TRUE if the icon for the bookmark for the URI was found.
- * You should free the returned strings.
- *
- * Since: 2.12
- */
-gboolean
-g_bookmark_file_get_icon (GBookmarkFile *bookmark,
- const gchar *uri,
- gchar **href,
- gchar **mime_type,
- GError **error)
-{
- BookmarkItem *item;
-
- g_return_val_if_fail (bookmark != NULL, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
-
- item = g_bookmark_file_lookup_item (bookmark, uri);
- if (!item)
- {
- g_set_error (error, G_BOOKMARK_FILE_ERROR,
- G_BOOKMARK_FILE_ERROR_URI_NOT_FOUND,
- _("No bookmark found for URI '%s'"),
- uri);
- return FALSE;
- }
-
- if ((!item->metadata) || (!item->metadata->icon_href))
- return FALSE;
-
- if (href)
- *href = g_strdup (item->metadata->icon_href);
-
- if (mime_type)
- *mime_type = g_strdup (item->metadata->icon_mime);
-
- return TRUE;
-}
-
-#define __G_BOOKMARK_FILE_C__
-#include "galiasdef.c"
diff --git a/glib/gcache.c b/glib/gcache.c
deleted file mode 100644
index a5b02974c..000000000
--- a/glib/gcache.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#include "glib.h"
-#include "galias.h"
-
-
-typedef struct _GCacheNode GCacheNode;
-
-struct _GCacheNode
-{
- /* A reference counted node */
- gpointer value;
- gint ref_count;
-};
-
-struct _GCache
-{
- /* Called to create a value from a key */
- GCacheNewFunc value_new_func;
-
- /* Called to destroy a value */
- GCacheDestroyFunc value_destroy_func;
-
- /* Called to duplicate a key */
- GCacheDupFunc key_dup_func;
-
- /* Called to destroy a key */
- GCacheDestroyFunc key_destroy_func;
-
- /* Associates keys with nodes */
- GHashTable *key_table;
-
- /* Associates nodes with keys */
- GHashTable *value_table;
-};
-
-static inline GCacheNode*
-g_cache_node_new (gpointer value)
-{
- GCacheNode *node = g_slice_new (GCacheNode);
- node->value = value;
- node->ref_count = 1;
- return node;
-}
-
-static inline void
-g_cache_node_destroy (GCacheNode *node)
-{
- g_slice_free (GCacheNode, node);
-}
-
-GCache*
-g_cache_new (GCacheNewFunc value_new_func,
- GCacheDestroyFunc value_destroy_func,
- GCacheDupFunc key_dup_func,
- GCacheDestroyFunc key_destroy_func,
- GHashFunc hash_key_func,
- GHashFunc hash_value_func,
- GEqualFunc key_equal_func)
-{
- GCache *cache;
-
- g_return_val_if_fail (value_new_func != NULL, NULL);
- g_return_val_if_fail (value_destroy_func != NULL, NULL);
- g_return_val_if_fail (key_dup_func != NULL, NULL);
- g_return_val_if_fail (key_destroy_func != NULL, NULL);
- g_return_val_if_fail (hash_key_func != NULL, NULL);
- g_return_val_if_fail (hash_value_func != NULL, NULL);
- g_return_val_if_fail (key_equal_func != NULL, NULL);
-
- cache = g_slice_new (GCache);
- cache->value_new_func = value_new_func;
- cache->value_destroy_func = value_destroy_func;
- cache->key_dup_func = key_dup_func;
- cache->key_destroy_func = key_destroy_func;
- cache->key_table = g_hash_table_new (hash_key_func, key_equal_func);
- cache->value_table = g_hash_table_new (hash_value_func, NULL);
-
- return cache;
-}
-
-void
-g_cache_destroy (GCache *cache)
-{
- g_return_if_fail (cache != NULL);
-
- g_hash_table_destroy (cache->key_table);
- g_hash_table_destroy (cache->value_table);
- g_slice_free (GCache, cache);
-}
-
-gpointer
-g_cache_insert (GCache *cache,
- gpointer key)
-{
- GCacheNode *node;
- gpointer value;
-
- g_return_val_if_fail (cache != NULL, NULL);
-
- node = g_hash_table_lookup (cache->key_table, key);
- if (node)
- {
- node->ref_count += 1;
- return node->value;
- }
-
- key = (* cache->key_dup_func) (key);
- value = (* cache->value_new_func) (key);
- node = g_cache_node_new (value);
-
- g_hash_table_insert (cache->key_table, key, node);
- g_hash_table_insert (cache->value_table, value, key);
-
- return node->value;
-}
-
-void
-g_cache_remove (GCache *cache,
- gconstpointer value)
-{
- GCacheNode *node;
- gpointer key;
-
- g_return_if_fail (cache != NULL);
-
- key = g_hash_table_lookup (cache->value_table, value);
- node = g_hash_table_lookup (cache->key_table, key);
-
- g_return_if_fail (node != NULL);
-
- node->ref_count -= 1;
- if (node->ref_count == 0)
- {
- g_hash_table_remove (cache->value_table, value);
- g_hash_table_remove (cache->key_table, key);
-
- (* cache->key_destroy_func) (key);
- (* cache->value_destroy_func) (node->value);
- g_cache_node_destroy (node);
- }
-}
-
-void
-g_cache_key_foreach (GCache *cache,
- GHFunc func,
- gpointer user_data)
-{
- g_return_if_fail (cache != NULL);
- g_return_if_fail (func != NULL);
-
- g_hash_table_foreach (cache->value_table, func, user_data);
-}
-
-void
-g_cache_value_foreach (GCache *cache,
- GHFunc func,
- gpointer user_data)
-{
- g_return_if_fail (cache != NULL);
- g_return_if_fail (func != NULL);
-
- g_hash_table_foreach (cache->key_table, func, user_data);
-}
-
-#define __G_CACHE_C__
-#include "galiasdef.c"
diff --git a/glib/gchecksum.c b/glib/gchecksum.c
deleted file mode 100644
index 1611193d4..000000000
--- a/glib/gchecksum.c
+++ /dev/null
@@ -1,1439 +0,0 @@
-/* gchecksum.h - data hashing functions
- *
- * Copyright (C) 2007 Emmanuele Bassi <ebassi@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include "glibconfig.h"
-#include "gchecksum.h"
-#include "glib.h"
-#include "glibintl.h"
-
-#include "galias.h"
-
-#define IS_VALID_TYPE(type) ((type) >= G_CHECKSUM_MD5 && (type) <= G_CHECKSUM_SHA256)
-
-/* The fact that these are lower case characters is part of the ABI */
-static const gchar hex_digits[] = "0123456789abcdef";
-
-#define MD5_DATASIZE 64
-#define MD5_DIGEST_LEN 16
-
-typedef struct
-{
- guint32 buf[4];
- guint32 bits[2];
-
- guchar data[MD5_DATASIZE];
-
- guchar digest[MD5_DIGEST_LEN];
-} Md5sum;
-
-#define SHA1_DATASIZE 64
-#define SHA1_DIGEST_LEN 20
-
-typedef struct
-{
- guint32 buf[5];
- guint32 bits[2];
-
- /* we pack 64 unsigned chars into 16 32-bit unsigned integers */
- guint32 data[16];
-
- guchar digest[SHA1_DIGEST_LEN];
-} Sha1sum;
-
-#define SHA256_DATASIZE 64
-#define SHA256_DIGEST_LEN 32
-
-typedef struct
-{
- guint32 buf[8];
- guint32 bits[2];
-
- guint8 data[SHA256_DATASIZE];
-
- guchar digest[SHA256_DIGEST_LEN];
-} Sha256sum;
-
-struct _GChecksum
-{
- GChecksumType type;
-
- gchar *digest_str;
-
- union {
- Md5sum md5;
- Sha1sum sha1;
- Sha256sum sha256;
- } sum;
-};
-
-/* we need different byte swapping functions because MD5 expects buffers
- * to be little-endian, while SHA1 and SHA256 expect them in big-endian
- * form.
- */
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-#define md5_byte_reverse(buffer,length)
-#else
-/* assume that the passed buffer is integer aligned */
-static inline void
-md5_byte_reverse (guchar *buffer,
- gulong length)
-{
- guint32 bit;
-
- do
- {
- bit = (guint32) ((unsigned) buffer[3] << 8 | buffer[2]) << 16 |
- ((unsigned) buffer[1] << 8 | buffer[0]);
- * (guint32 *) buffer = bit;
- buffer += 4;
- }
- while (--length);
-}
-#endif /* G_BYTE_ORDER == G_LITTLE_ENDIAN */
-
-#if G_BYTE_ORDER == G_BIG_ENDIAN
-#define sha_byte_reverse(buffer,length)
-#else
-static inline void
-sha_byte_reverse (guint32 *buffer,
- gint length)
-{
- length /= sizeof (guint32);
- while (length--)
- {
- *buffer = GUINT32_SWAP_LE_BE (*buffer);
- ++buffer;
- }
-}
-#endif /* G_BYTE_ORDER == G_BIG_ENDIAN */
-
-static gchar *
-digest_to_string (guint8 *digest,
- gsize digest_len)
-{
- gint len = digest_len * 2;
- gint i;
- gchar *retval;
-
- retval = g_new (gchar, len + 1);
-
- for (i = 0; i < digest_len; i++)
- {
- guint8 byte = digest[i];
-
- retval[2 * i] = hex_digits[byte >> 4];
- retval[2 * i + 1] = hex_digits[byte & 0xf];
- }
-
- retval[len] = 0;
-
- return retval;
-}
-
-/*
- * MD5 Checksum
- */
-
-/* This MD5 digest computation is based on the equivalent code
- * written by Colin Plumb. It came with this notice:
- *
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest. This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- */
-
-static void
-md5_sum_init (Md5sum *md5)
-{
- /* arbitrary constants */
- md5->buf[0] = 0x67452301;
- md5->buf[1] = 0xefcdab89;
- md5->buf[2] = 0x98badcfe;
- md5->buf[3] = 0x10325476;
-
- md5->bits[0] = md5->bits[1] = 0;
-}
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. md5_sum_update()
- * blocks the data and converts bytes into longwords for this routine.
- */
-static void
-md5_transform (guint32 buf[4],
- guint32 const in[16])
-{
- register guint32 a, b, c, d;
-
-/* The four core functions - F1 is optimized somewhat */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1 (z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define md5_step(f, w, x, y, z, data, s) \
- ( w += f (x, y, z) + data, w = w << s | w >> (32 - s), w += x )
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- md5_step (F1, a, b, c, d, in[0] + 0xd76aa478, 7);
- md5_step (F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
- md5_step (F1, c, d, a, b, in[2] + 0x242070db, 17);
- md5_step (F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
- md5_step (F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
- md5_step (F1, d, a, b, c, in[5] + 0x4787c62a, 12);
- md5_step (F1, c, d, a, b, in[6] + 0xa8304613, 17);
- md5_step (F1, b, c, d, a, in[7] + 0xfd469501, 22);
- md5_step (F1, a, b, c, d, in[8] + 0x698098d8, 7);
- md5_step (F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
- md5_step (F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
- md5_step (F1, b, c, d, a, in[11] + 0x895cd7be, 22);
- md5_step (F1, a, b, c, d, in[12] + 0x6b901122, 7);
- md5_step (F1, d, a, b, c, in[13] + 0xfd987193, 12);
- md5_step (F1, c, d, a, b, in[14] + 0xa679438e, 17);
- md5_step (F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
- md5_step (F2, a, b, c, d, in[1] + 0xf61e2562, 5);
- md5_step (F2, d, a, b, c, in[6] + 0xc040b340, 9);
- md5_step (F2, c, d, a, b, in[11] + 0x265e5a51, 14);
- md5_step (F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
- md5_step (F2, a, b, c, d, in[5] + 0xd62f105d, 5);
- md5_step (F2, d, a, b, c, in[10] + 0x02441453, 9);
- md5_step (F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
- md5_step (F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
- md5_step (F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
- md5_step (F2, d, a, b, c, in[14] + 0xc33707d6, 9);
- md5_step (F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
- md5_step (F2, b, c, d, a, in[8] + 0x455a14ed, 20);
- md5_step (F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
- md5_step (F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
- md5_step (F2, c, d, a, b, in[7] + 0x676f02d9, 14);
- md5_step (F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
- md5_step (F3, a, b, c, d, in[5] + 0xfffa3942, 4);
- md5_step (F3, d, a, b, c, in[8] + 0x8771f681, 11);
- md5_step (F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
- md5_step (F3, b, c, d, a, in[14] + 0xfde5380c, 23);
- md5_step (F3, a, b, c, d, in[1] + 0xa4beea44, 4);
- md5_step (F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
- md5_step (F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
- md5_step (F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
- md5_step (F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
- md5_step (F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
- md5_step (F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
- md5_step (F3, b, c, d, a, in[6] + 0x04881d05, 23);
- md5_step (F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
- md5_step (F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
- md5_step (F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
- md5_step (F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
- md5_step (F4, a, b, c, d, in[0] + 0xf4292244, 6);
- md5_step (F4, d, a, b, c, in[7] + 0x432aff97, 10);
- md5_step (F4, c, d, a, b, in[14] + 0xab9423a7, 15);
- md5_step (F4, b, c, d, a, in[5] + 0xfc93a039, 21);
- md5_step (F4, a, b, c, d, in[12] + 0x655b59c3, 6);
- md5_step (F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
- md5_step (F4, c, d, a, b, in[10] + 0xffeff47d, 15);
- md5_step (F4, b, c, d, a, in[1] + 0x85845dd1, 21);
- md5_step (F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
- md5_step (F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
- md5_step (F4, c, d, a, b, in[6] + 0xa3014314, 15);
- md5_step (F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
- md5_step (F4, a, b, c, d, in[4] + 0xf7537e82, 6);
- md5_step (F4, d, a, b, c, in[11] + 0xbd3af235, 10);
- md5_step (F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
- md5_step (F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-
-#undef F1
-#undef F2
-#undef F3
-#undef F4
-#undef md5_step
-}
-
-static void
-md5_sum_update (Md5sum *md5,
- const guchar *data,
- gsize length)
-{
- guint32 bit;
-
- bit = md5->bits[0];
- md5->bits[0] = bit + ((guint32) length << 3);
-
- /* carry from low to high */
- if (md5->bits[0] < bit)
- md5->bits[1] += 1;
-
- md5->bits[1] += length >> 29;
-
- /* bytes already in Md5sum->data */
- bit = (bit >> 3) & 0x3f;
-
- /* handle any leading odd-sized chunks */
- if (bit)
- {
- guchar *p = (guchar *) md5->data + bit;
-
- bit = MD5_DATASIZE - bit;
- if (length < bit)
- {
- memcpy (p, data, length);
- return;
- }
-
- memcpy (p, data, bit);
-
- md5_byte_reverse (md5->data, 16);
- md5_transform (md5->buf, (guint32 *) md5->data);
-
- data += bit;
- length -= bit;
- }
-
- /* process data in 64-byte chunks */
- while (length >= MD5_DATASIZE)
- {
- memcpy (md5->data, data, MD5_DATASIZE);
-
- md5_byte_reverse (md5->data, 16);
- md5_transform (md5->buf, (guint32 *) md5->data);
-
- data += MD5_DATASIZE;
- length -= MD5_DATASIZE;
- }
-
- /* handle any remaining bytes of data */
- memcpy (md5->data, data, length);
-}
-
-/* closes a checksum */
-static void
-md5_sum_close (Md5sum *md5)
-{
- guint count;
- guchar *p;
-
- /* Compute number of bytes mod 64 */
- count = (md5->bits[0] >> 3) & 0x3F;
-
- /* Set the first char of padding to 0x80.
- * This is safe since there is always at least one byte free
- */
- p = md5->data + count;
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = MD5_DATASIZE - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8)
- {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset (p, 0, count);
-
- md5_byte_reverse (md5->data, 16);
- md5_transform (md5->buf, (guint32 *) md5->data);
-
- /* Now fill the next block with 56 bytes */
- memset (md5->data, 0, MD5_DATASIZE - 8);
- }
- else
- {
- /* Pad block to 56 bytes */
- memset (p, 0, count - 8);
- }
-
- md5_byte_reverse (md5->data, 14);
-
- /* Append length in bits and transform */
- ((guint32 *) md5->data)[14] = md5->bits[0];
- ((guint32 *) md5->data)[15] = md5->bits[1];
-
- md5_transform (md5->buf, (guint32 *) md5->data);
- md5_byte_reverse ((guchar *) md5->buf, 4);
-
- memcpy (md5->digest, md5->buf, 16);
-
- /* Reset buffers in case they contain sensitive data */
- memset (md5->buf, 0, sizeof (md5->buf));
- memset (md5->data, 0, sizeof (md5->data));
-}
-
-static gchar *
-md5_sum_to_string (Md5sum *md5)
-{
- return digest_to_string (md5->digest, MD5_DIGEST_LEN);
-}
-
-static void
-md5_sum_digest (Md5sum *md5,
- guint8 *digest)
-{
- gint i;
-
- for (i = 0; i < MD5_DIGEST_LEN; i++)
- digest[i] = md5->digest[i];
-}
-
-/*
- * SHA-1 Checksum
- */
-
-/* The following implementation comes from D-Bus dbus-sha.c. I've changed
- * it to use GLib types and to work more like the MD5 implementation above.
- * I left the comments to have an history of this code.
- * -- Emmanuele Bassi, ebassi@gnome.org
- */
-
-/* The following comments have the history of where this code
- * comes from. I actually copied it from GNet in GNOME CVS.
- * - hp@redhat.com
- */
-
-/*
- * sha.h : Implementation of the Secure Hash Algorithm
- *
- * Part of the Python Cryptography Toolkit, version 1.0.0
- *
- * Copyright (C) 1995, A.M. Kuchling
- *
- * Distribute and use freely; there are no restrictions on further
- * dissemination and usage except those imposed by the laws of your
- * country of residence.
- *
- */
-
-/* SHA: NIST's Secure Hash Algorithm */
-
-/* Based on SHA code originally posted to sci.crypt by Peter Gutmann
- in message <30ajo5$oe8@ccu2.auckland.ac.nz>.
- Modified to test for endianness on creation of SHA objects by AMK.
- Also, the original specification of SHA was found to have a weakness
- by NSA/NIST. This code implements the fixed version of SHA.
-*/
-
-/* Here's the first paragraph of Peter Gutmann's posting:
-
-The following is my SHA (FIPS 180) code updated to allow use of the "fixed"
-SHA, thanks to Jim Gillogly and an anonymous contributor for the information on
-what's changed in the new version. The fix is a simple change which involves
-adding a single rotate in the initial expansion function. It is unknown
-whether this is an optimal solution to the problem which was discovered in the
-SHA or whether it's simply a bandaid which fixes the problem with a minimum of
-effort (for example the reengineering of a great many Capstone chips).
-*/
-
-static void
-sha1_sum_init (Sha1sum *sha1)
-{
- /* initialize constants */
- sha1->buf[0] = 0x67452301L;
- sha1->buf[1] = 0xEFCDAB89L;
- sha1->buf[2] = 0x98BADCFEL;
- sha1->buf[3] = 0x10325476L;
- sha1->buf[4] = 0xC3D2E1F0L;
-
- /* initialize bits */
- sha1->bits[0] = sha1->bits[1] = 0;
-}
-
-/* The SHA f()-functions. */
-
-#define f1(x,y,z) (z ^ (x & (y ^ z))) /* Rounds 0-19 */
-#define f2(x,y,z) (x ^ y ^ z) /* Rounds 20-39 */
-#define f3(x,y,z) (( x & y) | (z & (x | y))) /* Rounds 40-59 */
-#define f4(x,y,z) (x ^ y ^ z) /* Rounds 60-79 */
-
-/* The SHA Mysterious Constants */
-#define K1 0x5A827999L /* Rounds 0-19 */
-#define K2 0x6ED9EBA1L /* Rounds 20-39 */
-#define K3 0x8F1BBCDCL /* Rounds 40-59 */
-#define K4 0xCA62C1D6L /* Rounds 60-79 */
-
-/* 32-bit rotate left - kludged with shifts */
-#define ROTL(n,X) (((X) << n ) | ((X) >> (32 - n)))
-
-/* The initial expanding function. The hash function is defined over an
- 80-word expanded input array W, where the first 16 are copies of the input
- data, and the remaining 64 are defined by
-
- W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ]
-
- This implementation generates these values on the fly in a circular
- buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this
- optimization.
-
- The updated SHA changes the expanding function by adding a rotate of 1
- bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor
- for this information */
-
-#define expand(W,i) (W[ i & 15 ] = ROTL (1, (W[ i & 15] ^ \
- W[(i - 14) & 15] ^ \
- W[(i - 8) & 15] ^ \
- W[(i - 3) & 15])))
-
-
-/* The prototype SHA sub-round. The fundamental sub-round is:
-
- a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data;
- b' = a;
- c' = ROTL( 30, b );
- d' = c;
- e' = d;
-
- but this is implemented by unrolling the loop 5 times and renaming the
- variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration.
- This code is then replicated 20 times for each of the 4 functions, using
- the next 20 values from the W[] array each time */
-
-#define subRound(a, b, c, d, e, f, k, data) \
- (e += ROTL (5, a) + f(b, c, d) + k + data, b = ROTL (30, b))
-
-static void
-sha1_transform (guint32 buf[5],
- guint32 in[16])
-{
- guint32 A, B, C, D, E;
-
- A = buf[0];
- B = buf[1];
- C = buf[2];
- D = buf[3];
- E = buf[4];
-
- /* Heavy mangling, in 4 sub-rounds of 20 interations each. */
- subRound (A, B, C, D, E, f1, K1, in[0]);
- subRound (E, A, B, C, D, f1, K1, in[1]);
- subRound (D, E, A, B, C, f1, K1, in[2]);
- subRound (C, D, E, A, B, f1, K1, in[3]);
- subRound (B, C, D, E, A, f1, K1, in[4]);
- subRound (A, B, C, D, E, f1, K1, in[5]);
- subRound (E, A, B, C, D, f1, K1, in[6]);
- subRound (D, E, A, B, C, f1, K1, in[7]);
- subRound (C, D, E, A, B, f1, K1, in[8]);
- subRound (B, C, D, E, A, f1, K1, in[9]);
- subRound (A, B, C, D, E, f1, K1, in[10]);
- subRound (E, A, B, C, D, f1, K1, in[11]);
- subRound (D, E, A, B, C, f1, K1, in[12]);
- subRound (C, D, E, A, B, f1, K1, in[13]);
- subRound (B, C, D, E, A, f1, K1, in[14]);
- subRound (A, B, C, D, E, f1, K1, in[15]);
- subRound (E, A, B, C, D, f1, K1, expand (in, 16));
- subRound (D, E, A, B, C, f1, K1, expand (in, 17));
- subRound (C, D, E, A, B, f1, K1, expand (in, 18));
- subRound (B, C, D, E, A, f1, K1, expand (in, 19));
-
- subRound (A, B, C, D, E, f2, K2, expand (in, 20));
- subRound (E, A, B, C, D, f2, K2, expand (in, 21));
- subRound (D, E, A, B, C, f2, K2, expand (in, 22));
- subRound (C, D, E, A, B, f2, K2, expand (in, 23));
- subRound (B, C, D, E, A, f2, K2, expand (in, 24));
- subRound (A, B, C, D, E, f2, K2, expand (in, 25));
- subRound (E, A, B, C, D, f2, K2, expand (in, 26));
- subRound (D, E, A, B, C, f2, K2, expand (in, 27));
- subRound (C, D, E, A, B, f2, K2, expand (in, 28));
- subRound (B, C, D, E, A, f2, K2, expand (in, 29));
- subRound (A, B, C, D, E, f2, K2, expand (in, 30));
- subRound (E, A, B, C, D, f2, K2, expand (in, 31));
- subRound (D, E, A, B, C, f2, K2, expand (in, 32));
- subRound (C, D, E, A, B, f2, K2, expand (in, 33));
- subRound (B, C, D, E, A, f2, K2, expand (in, 34));
- subRound (A, B, C, D, E, f2, K2, expand (in, 35));
- subRound (E, A, B, C, D, f2, K2, expand (in, 36));
- subRound (D, E, A, B, C, f2, K2, expand (in, 37));
- subRound (C, D, E, A, B, f2, K2, expand (in, 38));
- subRound (B, C, D, E, A, f2, K2, expand (in, 39));
-
- subRound (A, B, C, D, E, f3, K3, expand (in, 40));
- subRound (E, A, B, C, D, f3, K3, expand (in, 41));
- subRound (D, E, A, B, C, f3, K3, expand (in, 42));
- subRound (C, D, E, A, B, f3, K3, expand (in, 43));
- subRound (B, C, D, E, A, f3, K3, expand (in, 44));
- subRound (A, B, C, D, E, f3, K3, expand (in, 45));
- subRound (E, A, B, C, D, f3, K3, expand (in, 46));
- subRound (D, E, A, B, C, f3, K3, expand (in, 47));
- subRound (C, D, E, A, B, f3, K3, expand (in, 48));
- subRound (B, C, D, E, A, f3, K3, expand (in, 49));
- subRound (A, B, C, D, E, f3, K3, expand (in, 50));
- subRound (E, A, B, C, D, f3, K3, expand (in, 51));
- subRound (D, E, A, B, C, f3, K3, expand (in, 52));
- subRound (C, D, E, A, B, f3, K3, expand (in, 53));
- subRound (B, C, D, E, A, f3, K3, expand (in, 54));
- subRound (A, B, C, D, E, f3, K3, expand (in, 55));
- subRound (E, A, B, C, D, f3, K3, expand (in, 56));
- subRound (D, E, A, B, C, f3, K3, expand (in, 57));
- subRound (C, D, E, A, B, f3, K3, expand (in, 58));
- subRound (B, C, D, E, A, f3, K3, expand (in, 59));
-
- subRound (A, B, C, D, E, f4, K4, expand (in, 60));
- subRound (E, A, B, C, D, f4, K4, expand (in, 61));
- subRound (D, E, A, B, C, f4, K4, expand (in, 62));
- subRound (C, D, E, A, B, f4, K4, expand (in, 63));
- subRound (B, C, D, E, A, f4, K4, expand (in, 64));
- subRound (A, B, C, D, E, f4, K4, expand (in, 65));
- subRound (E, A, B, C, D, f4, K4, expand (in, 66));
- subRound (D, E, A, B, C, f4, K4, expand (in, 67));
- subRound (C, D, E, A, B, f4, K4, expand (in, 68));
- subRound (B, C, D, E, A, f4, K4, expand (in, 69));
- subRound (A, B, C, D, E, f4, K4, expand (in, 70));
- subRound (E, A, B, C, D, f4, K4, expand (in, 71));
- subRound (D, E, A, B, C, f4, K4, expand (in, 72));
- subRound (C, D, E, A, B, f4, K4, expand (in, 73));
- subRound (B, C, D, E, A, f4, K4, expand (in, 74));
- subRound (A, B, C, D, E, f4, K4, expand (in, 75));
- subRound (E, A, B, C, D, f4, K4, expand (in, 76));
- subRound (D, E, A, B, C, f4, K4, expand (in, 77));
- subRound (C, D, E, A, B, f4, K4, expand (in, 78));
- subRound (B, C, D, E, A, f4, K4, expand (in, 79));
-
- /* Build message digest */
- buf[0] += A;
- buf[1] += B;
- buf[2] += C;
- buf[3] += D;
- buf[4] += E;
-}
-
-#undef K1
-#undef K2
-#undef K3
-#undef K4
-#undef f1
-#undef f2
-#undef f3
-#undef f4
-#undef ROTL
-#undef expand
-#undef subRound
-
-static void
-sha1_sum_update (Sha1sum *sha1,
- const guchar *buffer,
- gsize count)
-{
- guint32 tmp;
- guint dataCount;
-
- /* Update bitcount */
- tmp = sha1->bits[0];
- if ((sha1->bits[0] = tmp + ((guint32) count << 3) ) < tmp)
- sha1->bits[1] += 1; /* Carry from low to high */
- sha1->bits[1] += count >> 29;
-
- /* Get count of bytes already in data */
- dataCount = (guint) (tmp >> 3) & 0x3F;
-
- /* Handle any leading odd-sized chunks */
- if (dataCount)
- {
- guchar *p = (guchar *) sha1->data + dataCount;
-
- dataCount = SHA1_DATASIZE - dataCount;
- if (count < dataCount)
- {
- memcpy (p, buffer, count);
- return;
- }
-
- memcpy (p, buffer, dataCount);
-
- sha_byte_reverse (sha1->data, SHA1_DATASIZE);
- sha1_transform (sha1->buf, sha1->data);
-
- buffer += dataCount;
- count -= dataCount;
- }
-
- /* Process data in SHA1_DATASIZE chunks */
- while (count >= SHA1_DATASIZE)
- {
- memcpy (sha1->data, buffer, SHA1_DATASIZE);
-
- sha_byte_reverse (sha1->data, SHA1_DATASIZE);
- sha1_transform (sha1->buf, sha1->data);
-
- buffer += SHA1_DATASIZE;
- count -= SHA1_DATASIZE;
- }
-
- /* Handle any remaining bytes of data. */
- memcpy (sha1->data, buffer, count);
-}
-
-/* Final wrapup - pad to SHA_DATASIZE-byte boundary with the bit pattern
- 1 0* (64-bit count of bits processed, MSB-first) */
-static void
-sha1_sum_close (Sha1sum *sha1)
-{
- gint count;
- guchar *data_p;
-
- /* Compute number of bytes mod 64 */
- count = (gint) ((sha1->bits[0] >> 3) & 0x3f);
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- data_p = (guchar *) sha1->data + count;
- *data_p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = SHA1_DATASIZE - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8)
- {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset (data_p, 0, count);
-
- sha_byte_reverse (sha1->data, SHA1_DATASIZE);
- sha1_transform (sha1->buf, sha1->data);
-
- /* Now fill the next block with 56 bytes */
- memset (sha1->data, 0, SHA1_DATASIZE - 8);
- }
- else
- {
- /* Pad block to 56 bytes */
- memset (data_p, 0, count - 8);
- }
-
- /* Append length in bits and transform */
- sha1->data[14] = sha1->bits[1];
- sha1->data[15] = sha1->bits[0];
-
- sha_byte_reverse (sha1->data, SHA1_DATASIZE - 8);
- sha1_transform (sha1->buf, sha1->data);
- sha_byte_reverse (sha1->buf, SHA1_DIGEST_LEN);
-
- memcpy (sha1->digest, sha1->buf, SHA1_DIGEST_LEN);
-
- /* Reset buffers in case they contain sensitive data */
- memset (sha1->buf, 0, sizeof (sha1->buf));
- memset (sha1->data, 0, sizeof (sha1->data));
-}
-
-static gchar *
-sha1_sum_to_string (Sha1sum *sha1)
-{
- return digest_to_string (sha1->digest, SHA1_DIGEST_LEN);
-}
-
-static void
-sha1_sum_digest (Sha1sum *sha1,
- guint8 *digest)
-{
- gint i;
-
- for (i = 0; i < SHA1_DIGEST_LEN; i++)
- digest[i] = sha1->digest[i];
-}
-
-/*
- * SHA-256 Checksum
- */
-
-/* adapted from the SHA256 implementation in gsk/src/hash/gskhash.c.
- *
- * Copyright (C) 2006 Dave Benson
- * Released under the terms of the GNU Lesser General Public License
- */
-
-static void
-sha256_sum_init (Sha256sum *sha256)
-{
- sha256->buf[0] = 0x6a09e667;
- sha256->buf[1] = 0xbb67ae85;
- sha256->buf[2] = 0x3c6ef372;
- sha256->buf[3] = 0xa54ff53a;
- sha256->buf[4] = 0x510e527f;
- sha256->buf[5] = 0x9b05688c;
- sha256->buf[6] = 0x1f83d9ab;
- sha256->buf[7] = 0x5be0cd19;
-
- sha256->bits[0] = sha256->bits[1] = 0;
-}
-
-#define GET_UINT32(n,b,i) G_STMT_START{ \
- (n) = ((guint32) (b)[(i) ] << 24) \
- | ((guint32) (b)[(i) + 1] << 16) \
- | ((guint32) (b)[(i) + 2] << 8) \
- | ((guint32) (b)[(i) + 3] ); } G_STMT_END
-
-#define PUT_UINT32(n,b,i) G_STMT_START{ \
- (b)[(i) ] = (guint8) ((n) >> 24); \
- (b)[(i) + 1] = (guint8) ((n) >> 16); \
- (b)[(i) + 2] = (guint8) ((n) >> 8); \
- (b)[(i) + 3] = (guint8) ((n) ); } G_STMT_END
-
-static void
-sha256_transform (guint32 buf[8],
- guint8 const data[64])
-{
- guint32 temp1, temp2, W[64];
- guint32 A, B, C, D, E, F, G, H;
-
- GET_UINT32 (W[0], data, 0);
- GET_UINT32 (W[1], data, 4);
- GET_UINT32 (W[2], data, 8);
- GET_UINT32 (W[3], data, 12);
- GET_UINT32 (W[4], data, 16);
- GET_UINT32 (W[5], data, 20);
- GET_UINT32 (W[6], data, 24);
- GET_UINT32 (W[7], data, 28);
- GET_UINT32 (W[8], data, 32);
- GET_UINT32 (W[9], data, 36);
- GET_UINT32 (W[10], data, 40);
- GET_UINT32 (W[11], data, 44);
- GET_UINT32 (W[12], data, 48);
- GET_UINT32 (W[13], data, 52);
- GET_UINT32 (W[14], data, 56);
- GET_UINT32 (W[15], data, 60);
-
-#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
-#define ROTR(x,n) (SHR (x,n) | (x << (32 - n)))
-
-#define S0(x) (ROTR (x, 7) ^ ROTR (x,18) ^ SHR (x, 3))
-#define S1(x) (ROTR (x,17) ^ ROTR (x,19) ^ SHR (x,10))
-#define S2(x) (ROTR (x, 2) ^ ROTR (x,13) ^ ROTR (x,22))
-#define S3(x) (ROTR (x, 6) ^ ROTR (x,11) ^ ROTR (x,25))
-
-#define F0(x,y,z) ((x & y) | (z & (x | y)))
-#define F1(x,y,z) (z ^ (x & (y ^ z)))
-
-#define R(t) (W[t] = S1(W[t - 2]) + W[t - 7] + \
- S0(W[t - 15]) + W[t - 16])
-
-#define P(a,b,c,d,e,f,g,h,x,K) G_STMT_START { \
- temp1 = h + S3(e) + F1(e,f,g) + K + x; \
- temp2 = S2(a) + F0(a,b,c); \
- d += temp1; h = temp1 + temp2; } G_STMT_END
-
- A = buf[0];
- B = buf[1];
- C = buf[2];
- D = buf[3];
- E = buf[4];
- F = buf[5];
- G = buf[6];
- H = buf[7];
-
- P (A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98);
- P (H, A, B, C, D, E, F, G, W[ 1], 0x71374491);
- P (G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF);
- P (F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5);
- P (E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B);
- P (D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1);
- P (C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4);
- P (B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5);
- P (A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98);
- P (H, A, B, C, D, E, F, G, W[ 9], 0x12835B01);
- P (G, H, A, B, C, D, E, F, W[10], 0x243185BE);
- P (F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
- P (E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
- P (D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
- P (C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
- P (B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
- P (A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
- P (H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
- P (G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
- P (F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
- P (E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
- P (D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
- P (C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
- P (B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
- P (A, B, C, D, E, F, G, H, R(24), 0x983E5152);
- P (H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
- P (G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
- P (F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
- P (E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
- P (D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
- P (C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
- P (B, C, D, E, F, G, H, A, R(31), 0x14292967);
- P (A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
- P (H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
- P (G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
- P (F, G, H, A, B, C, D, E, R(35), 0x53380D13);
- P (E, F, G, H, A, B, C, D, R(36), 0x650A7354);
- P (D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
- P (C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
- P (B, C, D, E, F, G, H, A, R(39), 0x92722C85);
- P (A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
- P (H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
- P (G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
- P (F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
- P (E, F, G, H, A, B, C, D, R(44), 0xD192E819);
- P (D, E, F, G, H, A, B, C, R(45), 0xD6990624);
- P (C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
- P (B, C, D, E, F, G, H, A, R(47), 0x106AA070);
- P (A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
- P (H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
- P (G, H, A, B, C, D, E, F, R(50), 0x2748774C);
- P (F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
- P (E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
- P (D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
- P (C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
- P (B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
- P (A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
- P (H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
- P (G, H, A, B, C, D, E, F, R(58), 0x84C87814);
- P (F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
- P (E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
- P (D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
- P (C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
- P (B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
-
-#undef SHR
-#undef ROTR
-#undef S0
-#undef S1
-#undef S2
-#undef S3
-#undef F0
-#undef F1
-#undef R
-#undef P
-
- buf[0] += A;
- buf[1] += B;
- buf[2] += C;
- buf[3] += D;
- buf[4] += E;
- buf[5] += F;
- buf[6] += G;
- buf[7] += H;
-}
-
-static void
-sha256_sum_update (Sha256sum *sha256,
- const guchar *buffer,
- gsize length)
-{
- guint32 left, fill;
- const guint8 *input = buffer;
-
- if (length == 0)
- return;
-
- left = sha256->bits[0] & 0x3F;
- fill = 64 - left;
-
- sha256->bits[0] += length;
- sha256->bits[0] &= 0xFFFFFFFF;
-
- if (sha256->bits[0] < length)
- sha256->bits[1]++;
-
- if (left > 0 && length >= fill)
- {
- memcpy ((sha256->data + left), input, fill);
-
- sha256_transform (sha256->buf, sha256->data);
- length -= fill;
- input += fill;
-
- left = 0;
- }
-
- while (length >= SHA256_DATASIZE)
- {
- sha256_transform (sha256->buf, input);
-
- length -= 64;
- input += 64;
- }
-
- if (length)
- memcpy (sha256->data + left, input, length);
-}
-
-static guint8 sha256_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static void
-sha256_sum_close (Sha256sum *sha256)
-{
- guint32 last, padn;
- guint32 high, low;
- guint8 msglen[8];
-
- high = (sha256->bits[0] >> 29)
- | (sha256->bits[1] << 3);
- low = (sha256->bits[0] << 3);
-
- PUT_UINT32 (high, msglen, 0);
- PUT_UINT32 (low, msglen, 4);
-
- last = sha256->bits[0] & 0x3F;
- padn = (last < 56) ? (56 - last) : (120 - last);
-
- sha256_sum_update (sha256, sha256_padding, padn);
- sha256_sum_update (sha256, msglen, 8);
-
- PUT_UINT32 (sha256->buf[0], sha256->digest, 0);
- PUT_UINT32 (sha256->buf[1], sha256->digest, 4);
- PUT_UINT32 (sha256->buf[2], sha256->digest, 8);
- PUT_UINT32 (sha256->buf[3], sha256->digest, 12);
- PUT_UINT32 (sha256->buf[4], sha256->digest, 16);
- PUT_UINT32 (sha256->buf[5], sha256->digest, 20);
- PUT_UINT32 (sha256->buf[6], sha256->digest, 24);
- PUT_UINT32 (sha256->buf[7], sha256->digest, 28);
-}
-
-#undef PUT_UINT32
-#undef GET_UINT32
-
-static gchar *
-sha256_sum_to_string (Sha256sum *sha256)
-{
- return digest_to_string (sha256->digest, SHA256_DIGEST_LEN);
-}
-
-static void
-sha256_sum_digest (Sha256sum *sha256,
- guint8 *digest)
-{
- gint i;
-
- for (i = 0; i < SHA256_DIGEST_LEN; i++)
- digest[i] = sha256->digest[i];
-}
-
-
-/*
- * Public API
- */
-
-/**
- * g_checksum_type_get_length:
- * @checksum_type: a #GChecksumType
- *
- * Gets the length in bytes of digests of type @checksum_type
- *
- * Return value: the checksum length, or -1 if @checksum_type is
- * not supported.
- *
- * Since: 2.16
- */
-gssize
-g_checksum_type_get_length (GChecksumType checksum_type)
-{
- gssize len = -1;
-
- switch (checksum_type)
- {
- case G_CHECKSUM_MD5:
- len = MD5_DIGEST_LEN;
- break;
- case G_CHECKSUM_SHA1:
- len = SHA1_DIGEST_LEN;
- break;
- case G_CHECKSUM_SHA256:
- len = SHA256_DIGEST_LEN;
- break;
- default:
- len = -1;
- break;
- }
-
- return len;
-}
-
-/**
- * g_checksum_new:
- * @checksum_type: the desired type of checksum
- *
- * Creates a new #GChecksum, using the checksum algorithm @checksum_type.
- * If the @checksum_type is not known, %NULL is returned.
- * A #GChecksum can be used to compute the checksum, or digest, of an
- * arbitrary binary blob, using different hashing algorithms.
- *
- * A #GChecksum works by feeding a binary blob through g_checksum_update()
- * until there is data to be checked; the digest can then be extracted
- * using g_checksum_get_string(), which will return the checksum as a
- * hexadecimal string; or g_checksum_get_digest(), which will return a
- * vector of raw bytes. Once either g_checksum_get_string() or
- * g_checksum_get_digest() have been called on a #GChecksum, the checksum
- * will be closed and it won't be possible to call g_checksum_update()
- * on it anymore.
- *
- * Return value: the newly created #GChecksum, or %NULL.
- * Use g_checksum_free() to free the memory allocated by it.
- *
- * Since: 2.16
- */
-GChecksum *
-g_checksum_new (GChecksumType checksum_type)
-{
- GChecksum *checksum;
-
- if (! IS_VALID_TYPE (checksum_type))
- return NULL;
-
- checksum = g_slice_new0 (GChecksum);
- checksum->type = checksum_type;
-
- g_checksum_reset (checksum);
-
- return checksum;
-}
-
-/**
- * g_checksum_reset:
- * @checksum: the #GChecksum to reset
- *
- * Resets the state of the @checksum back to its initial state.
- *
- * Since: 2.18
- **/
-void
-g_checksum_reset (GChecksum *checksum)
-{
- g_return_if_fail (checksum != NULL);
-
- g_free (checksum->digest_str);
- checksum->digest_str = NULL;
-
- switch (checksum->type)
- {
- case G_CHECKSUM_MD5:
- md5_sum_init (&(checksum->sum.md5));
- break;
- case G_CHECKSUM_SHA1:
- sha1_sum_init (&(checksum->sum.sha1));
- break;
- case G_CHECKSUM_SHA256:
- sha256_sum_init (&(checksum->sum.sha256));
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-}
-
-/**
- * g_checksum_copy:
- * @checksum: the #GChecksum to copy
- *
- * Copies a #GChecksum. If @checksum has been closed, by calling
- * g_checksum_get_string() or g_checksum_get_digest(), the copied
- * checksum will be closed as well.
- *
- * Return value: the copy of the passed #GChecksum. Use g_checksum_free()
- * when finished using it.
- *
- * Since: 2.16
- */
-GChecksum *
-g_checksum_copy (const GChecksum *checksum)
-{
- GChecksum *copy;
-
- g_return_val_if_fail (checksum != NULL, NULL);
-
- copy = g_slice_new (GChecksum);
- *copy = *checksum;
-
- copy->digest_str = g_strdup (checksum->digest_str);
-
- return copy;
-}
-
-/**
- * g_checksum_free:
- * @checksum: a #GChecksum
- *
- * Frees the memory allocated for @checksum.
- *
- * Since: 2.16
- */
-void
-g_checksum_free (GChecksum *checksum)
-{
- if (G_LIKELY (checksum))
- {
- g_free (checksum->digest_str);
-
- g_slice_free (GChecksum, checksum);
- }
-}
-
-/**
- * g_checksum_update:
- * @checksum: a #GChecksum
- * @data: buffer used to compute the checksum
- * @length: size of the buffer, or -1 if it is a null-terminated string.
- *
- * Feeds @data into an existing #GChecksum. The checksum must still be
- * open, that is g_checksum_get_string() or g_checksum_get_digest() must
- * not have been called on @checksum.
- *
- * Since: 2.16
- */
-void
-g_checksum_update (GChecksum *checksum,
- const guchar *data,
- gssize length)
-{
- g_return_if_fail (checksum != NULL);
- g_return_if_fail (data != NULL);
-
- if (length < 0)
- length = strlen ((const gchar *) data);
-
- if (checksum->digest_str)
- {
- g_warning ("The checksum `%s' has been closed and cannot be updated "
- "anymore.",
- checksum->digest_str);
- return;
- }
-
- switch (checksum->type)
- {
- case G_CHECKSUM_MD5:
- md5_sum_update (&(checksum->sum.md5), data, length);
- break;
- case G_CHECKSUM_SHA1:
- sha1_sum_update (&(checksum->sum.sha1), data, length);
- break;
- case G_CHECKSUM_SHA256:
- sha256_sum_update (&(checksum->sum.sha256), data, length);
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-}
-
-/**
- * g_checksum_get_string:
- * @checksum: a #GChecksum
- *
- * Gets the digest as an hexadecimal string.
- *
- * Once this function has been called the #GChecksum can no longer be
- * updated with g_checksum_update().
- *
- * The hexadecimal characters will be lower case.
- *
- * Return value: the hexadecimal representation of the checksum. The
- * returned string is owned by the checksum and should not be modified
- * or freed.
- *
- * Since: 2.16
- */
-G_CONST_RETURN gchar *
-g_checksum_get_string (GChecksum *checksum)
-{
- gchar *str = NULL;
-
- g_return_val_if_fail (checksum != NULL, NULL);
-
- if (checksum->digest_str)
- return checksum->digest_str;
-
- switch (checksum->type)
- {
- case G_CHECKSUM_MD5:
- md5_sum_close (&(checksum->sum.md5));
- str = md5_sum_to_string (&(checksum->sum.md5));
- break;
- case G_CHECKSUM_SHA1:
- sha1_sum_close (&(checksum->sum.sha1));
- str = sha1_sum_to_string (&(checksum->sum.sha1));
- break;
- case G_CHECKSUM_SHA256:
- sha256_sum_close (&(checksum->sum.sha256));
- str = sha256_sum_to_string (&(checksum->sum.sha256));
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- checksum->digest_str = str;
-
- return checksum->digest_str;
-}
-
-/**
- * g_checksum_get_digest:
- * @checksum: a #GChecksum
- * @buffer: output buffer
- * @digest_len: an inout parameter. The caller initializes it to the size of @buffer.
- * After the call it contains the length of the digest.
- *
- * Gets the digest from @checksum as a raw binary vector and places it
- * into @buffer. The size of the digest depends on the type of checksum.
- *
- * Once this function has been called, the #GChecksum is closed and can
- * no longer be updated with g_checksum_update().
- *
- * Since: 2.16
- */
-void
-g_checksum_get_digest (GChecksum *checksum,
- guint8 *buffer,
- gsize *digest_len)
-{
- gboolean checksum_open = FALSE;
- gchar *str = NULL;
- gsize len;
-
- g_return_if_fail (checksum != NULL);
-
- len = g_checksum_type_get_length (checksum->type);
- g_return_if_fail (*digest_len >= len);
-
- checksum_open = !!(checksum->digest_str == NULL);
-
- switch (checksum->type)
- {
- case G_CHECKSUM_MD5:
- if (checksum_open)
- {
- md5_sum_close (&(checksum->sum.md5));
- str = md5_sum_to_string (&(checksum->sum.md5));
- }
- md5_sum_digest (&(checksum->sum.md5), buffer);
- break;
- case G_CHECKSUM_SHA1:
- if (checksum_open)
- {
- sha1_sum_close (&(checksum->sum.sha1));
- str = sha1_sum_to_string (&(checksum->sum.sha1));
- }
- sha1_sum_digest (&(checksum->sum.sha1), buffer);
- break;
- case G_CHECKSUM_SHA256:
- if (checksum_open)
- {
- sha256_sum_close (&(checksum->sum.sha256));
- str = sha256_sum_to_string (&(checksum->sum.sha256));
- }
- sha256_sum_digest (&(checksum->sum.sha256), buffer);
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- if (str)
- checksum->digest_str = str;
-
- *digest_len = len;
-}
-
-/**
- * g_compute_checksum_for_data:
- * @checksum_type: a #GChecksumType
- * @data: binary blob to compute the digest of
- * @length: length of @data
- *
- * Computes the checksum for a binary @data of @length. This is a
- * convenience wrapper for g_checksum_new(), g_checksum_get_string()
- * and g_checksum_free().
- *
- * The hexadecimal string returned will be in lower case.
- *
- * Return value: the digest of the binary data as a string in hexadecimal.
- * The returned string should be freed with g_free() when done using it.
- *
- * Since: 2.16
- */
-gchar *
-g_compute_checksum_for_data (GChecksumType checksum_type,
- const guchar *data,
- gsize length)
-{
- GChecksum *checksum;
- gchar *retval;
-
- g_return_val_if_fail (IS_VALID_TYPE (checksum_type), NULL);
- g_return_val_if_fail (data != NULL, NULL);
-
- checksum = g_checksum_new (checksum_type);
- if (!checksum)
- return NULL;
-
- g_checksum_update (checksum, data, length);
- retval = g_strdup (g_checksum_get_string (checksum));
- g_checksum_free (checksum);
-
- return retval;
-}
-
-/**
- * g_compute_checksum_for_string:
- * @checksum_type: a #GChecksumType
- * @str: the string to compute the checksum of
- * @length: the length of the string, or -1 if the string is null-terminated.
- *
- * Computes the checksum of a string.
- *
- * The hexadecimal string returned will be in lower case.
- *
- * Return value: the checksum as a hexadecimal string. The returned string
- * should be freed with g_free() when done using it.
- *
- * Since: 2.16
- */
-gchar *
-g_compute_checksum_for_string (GChecksumType checksum_type,
- const gchar *str,
- gssize length)
-{
- g_return_val_if_fail (IS_VALID_TYPE (checksum_type), NULL);
- g_return_val_if_fail (str != NULL, NULL);
-
- if (length < 0)
- length = strlen (str);
-
- return g_compute_checksum_for_data (checksum_type, (const guchar *) str, length);
-}
-
-#define __G_CHECKSUM_C__
-#include "galiasdef.c"
diff --git a/glib/gcompletion.c b/glib/gcompletion.c
deleted file mode 100644
index 5d2607846..000000000
--- a/glib/gcompletion.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include "glib.h"
-#include "galias.h"
-
-static void completion_check_cache (GCompletion* cmp,
- gchar** new_prefix);
-
-GCompletion*
-g_completion_new (GCompletionFunc func)
-{
- GCompletion* gcomp;
-
- gcomp = g_new (GCompletion, 1);
- gcomp->items = NULL;
- gcomp->cache = NULL;
- gcomp->prefix = NULL;
- gcomp->func = func;
- gcomp->strncmp_func = strncmp;
-
- return gcomp;
-}
-
-void
-g_completion_add_items (GCompletion* cmp,
- GList* items)
-{
- GList* it;
-
- g_return_if_fail (cmp != NULL);
-
- /* optimize adding to cache? */
- if (cmp->cache)
- {
- g_list_free (cmp->cache);
- cmp->cache = NULL;
- }
-
- if (cmp->prefix)
- {
- g_free (cmp->prefix);
- cmp->prefix = NULL;
- }
-
- it = items;
- while (it)
- {
- cmp->items = g_list_prepend (cmp->items, it->data);
- it = it->next;
- }
-}
-
-void
-g_completion_remove_items (GCompletion* cmp,
- GList* items)
-{
- GList* it;
-
- g_return_if_fail (cmp != NULL);
-
- it = items;
- while (cmp->items && it)
- {
- cmp->items = g_list_remove (cmp->items, it->data);
- it = it->next;
- }
-
- it = items;
- while (cmp->cache && it)
- {
- cmp->cache = g_list_remove(cmp->cache, it->data);
- it = it->next;
- }
-}
-
-void
-g_completion_clear_items (GCompletion* cmp)
-{
- g_return_if_fail (cmp != NULL);
-
- g_list_free (cmp->items);
- cmp->items = NULL;
- g_list_free (cmp->cache);
- cmp->cache = NULL;
- g_free (cmp->prefix);
- cmp->prefix = NULL;
-}
-
-static void
-completion_check_cache (GCompletion* cmp,
- gchar** new_prefix)
-{
- register GList* list;
- register gsize len;
- register gsize i;
- register gsize plen;
- gchar* postfix;
- gchar* s;
-
- if (!new_prefix)
- return;
- if (!cmp->cache)
- {
- *new_prefix = NULL;
- return;
- }
-
- len = strlen(cmp->prefix);
- list = cmp->cache;
- s = cmp->func ? cmp->func (list->data) : (gchar*) list->data;
- postfix = s + len;
- plen = strlen (postfix);
- list = list->next;
-
- while (list && plen)
- {
- s = cmp->func ? cmp->func (list->data) : (gchar*) list->data;
- s += len;
- for (i = 0; i < plen; ++i)
- {
- if (postfix[i] != s[i])
- break;
- }
- plen = i;
- list = list->next;
- }
-
- *new_prefix = g_new0 (gchar, len + plen + 1);
- strncpy (*new_prefix, cmp->prefix, len);
- strncpy (*new_prefix + len, postfix, plen);
-}
-
-/**
- * g_completion_complete_utf8:
- * @cmp: the #GCompletion
- * @prefix: the prefix string, typically used by the user, which is compared
- * with each of the items
- * @new_prefix: if non-%NULL, returns the longest prefix which is common to all
- * items that matched @prefix, or %NULL if no items matched @prefix.
- * This string should be freed when no longer needed.
- *
- * Attempts to complete the string @prefix using the #GCompletion target items.
- * In contrast to g_completion_complete(), this function returns the largest common
- * prefix that is a valid UTF-8 string, omitting a possible common partial
- * character.
- *
- * You should use this function instead of g_completion_complete() if your
- * items are UTF-8 strings.
- *
- * Return value: the list of items whose strings begin with @prefix. This should
- * not be changed.
- *
- * Since: 2.4
- **/
-GList*
-g_completion_complete_utf8 (GCompletion *cmp,
- const gchar *prefix,
- gchar **new_prefix)
-{
- GList *list;
- gchar *p, *q;
-
- list = g_completion_complete (cmp, prefix, new_prefix);
-
- if (new_prefix && *new_prefix)
- {
- p = *new_prefix + strlen (*new_prefix);
- q = g_utf8_find_prev_char (*new_prefix, p);
-
- switch (g_utf8_get_char_validated (q, p - q))
- {
- case (gunichar)-2:
- case (gunichar)-1:
- *q = 0;
- break;
- default: ;
- }
-
- }
-
- return list;
-}
-
-GList*
-g_completion_complete (GCompletion* cmp,
- const gchar* prefix,
- gchar** new_prefix)
-{
- gsize plen, len;
- gboolean done = FALSE;
- GList* list;
-
- g_return_val_if_fail (cmp != NULL, NULL);
- g_return_val_if_fail (prefix != NULL, NULL);
-
- len = strlen (prefix);
- if (cmp->prefix && cmp->cache)
- {
- plen = strlen (cmp->prefix);
- if (plen <= len && ! cmp->strncmp_func (prefix, cmp->prefix, plen))
- {
- /* use the cache */
- list = cmp->cache;
- while (list)
- {
- GList *next = list->next;
-
- if (cmp->strncmp_func (prefix,
- cmp->func ? cmp->func (list->data) : (gchar*) list->data,
- len))
- cmp->cache = g_list_delete_link (cmp->cache, list);
-
- list = next;
- }
- done = TRUE;
- }
- }
-
- if (!done)
- {
- /* normal code */
- g_list_free (cmp->cache);
- cmp->cache = NULL;
- list = cmp->items;
- while (*prefix && list)
- {
- if (!cmp->strncmp_func (prefix,
- cmp->func ? cmp->func (list->data) : (gchar*) list->data,
- len))
- cmp->cache = g_list_prepend (cmp->cache, list->data);
- list = list->next;
- }
- }
- if (cmp->prefix)
- {
- g_free (cmp->prefix);
- cmp->prefix = NULL;
- }
- if (cmp->cache)
- cmp->prefix = g_strdup (prefix);
- completion_check_cache (cmp, new_prefix);
-
- return *prefix ? cmp->cache : cmp->items;
-}
-
-void
-g_completion_free (GCompletion* cmp)
-{
- g_return_if_fail (cmp != NULL);
-
- g_completion_clear_items (cmp);
- g_free (cmp);
-}
-
-void
-g_completion_set_compare(GCompletion *cmp,
- GCompletionStrncmpFunc strncmp_func)
-{
- cmp->strncmp_func = strncmp_func;
-}
-
-#ifdef TEST_COMPLETION
-#include <stdio.h>
-int
-main (int argc,
- char* argv[])
-{
- FILE *file;
- gchar buf[1024];
- GList *list;
- GList *result;
- GList *tmp;
- GCompletion *cmp;
- gint i;
- gchar *longp = NULL;
-
- if (argc < 3)
- {
- g_warning ("Usage: %s filename prefix1 [prefix2 ...]\n", argv[0]);
- return 1;
- }
-
- file = fopen (argv[1], "r");
- if (!file)
- {
- g_warning ("Cannot open %s\n", argv[1]);
- return 1;
- }
-
- cmp = g_completion_new (NULL);
- list = g_list_alloc ();
- while (fgets (buf, 1024, file))
- {
- list->data = g_strdup (buf);
- g_completion_add_items (cmp, list);
- }
- fclose (file);
-
- for (i = 2; i < argc; ++i)
- {
- printf ("COMPLETING: %s\n", argv[i]);
- result = g_completion_complete (cmp, argv[i], &longp);
- g_list_foreach (result, (GFunc) printf, NULL);
- printf ("LONG MATCH: %s\n", longp);
- g_free (longp);
- longp = NULL;
- }
-
- g_list_foreach (cmp->items, (GFunc) g_free, NULL);
- g_completion_free (cmp);
- g_list_free (list);
-
- return 0;
-}
-#endif
-
-#define __G_COMPLETION_C__
-#include "galiasdef.c"
diff --git a/glib/gconvert.c b/glib/gconvert.c
index 7aefe24f3..c0952da59 100644
--- a/glib/gconvert.c
+++ b/glib/gconvert.c
@@ -24,9 +24,13 @@
#include "glib.h"
+
+#ifdef ANDROID_STUB
#ifndef G_OS_WIN32
#include <iconv.h>
#endif
+#endif
+
#include <errno.h>
#include <stdio.h>
#include <string.h>
@@ -57,6 +61,8 @@
#include "galias.h"
+typedef void iconv_t;
+
GQuark
g_convert_error_quark (void)
{
@@ -68,12 +74,16 @@ try_conversion (const char *to_codeset,
const char *from_codeset,
iconv_t *cd)
{
+#ifdef ANDROID_STUB
*cd = iconv_open (to_codeset, from_codeset);
if (*cd == (iconv_t)-1 && errno == EINVAL)
return FALSE;
else
return TRUE;
+#else
+ return FALSE;
+#endif
}
static gboolean
@@ -96,8 +106,10 @@ try_to_aliases (const char **to_aliases,
return FALSE;
}
+#ifdef ANDROID_STUB
G_GNUC_INTERNAL extern const char **
_g_charset_get_aliases (const char *canonical_name);
+#endif
/**
* g_iconv_open:
@@ -118,6 +130,7 @@ GIConv
g_iconv_open (const gchar *to_codeset,
const gchar *from_codeset)
{
+#ifdef ANDROID_STUB
iconv_t cd;
if (!try_conversion (to_codeset, from_codeset, &cd))
@@ -146,6 +159,9 @@ g_iconv_open (const gchar *to_codeset,
out:
return (cd == (iconv_t)-1) ? (GIConv)-1 : (GIConv)cd;
+#else
+ return (GIConv) -1;
+#endif
}
/**
@@ -172,9 +188,13 @@ g_iconv (GIConv converter,
gchar **outbuf,
gsize *outbytes_left)
{
+#ifdef ANDROID_STUB
iconv_t cd = (iconv_t)converter;
return iconv (cd, inbuf, inbytes_left, outbuf, outbytes_left);
+#else
+ return -1;
+#endif
}
/**
@@ -195,9 +215,13 @@ g_iconv (GIConv converter,
gint
g_iconv_close (GIConv converter)
{
+#ifdef ANDROID_STUB
iconv_t cd = (iconv_t)converter;
return iconv_close (cd);
+#else
+ return -1;
+#endif
}
diff --git a/glib/gdate.c b/glib/gdate.c
deleted file mode 100644
index cb25f3c56..000000000
--- a/glib/gdate.c
+++ /dev/null
@@ -1,1905 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#define DEBUG_MSG(x) /* */
-#ifdef G_ENABLE_DEBUG
-/* #define DEBUG_MSG(args) g_message args ; */
-#endif
-
-#include "glib.h"
-
-#include <time.h>
-#include <string.h>
-#include <stdlib.h>
-#include <locale.h>
-
-#ifdef G_OS_WIN32
-#include <windows.h>
-#endif
-
-#include "galias.h"
-
-GDate*
-g_date_new (void)
-{
- GDate *d = g_new0 (GDate, 1); /* happily, 0 is the invalid flag for everything. */
-
- return d;
-}
-
-GDate*
-g_date_new_dmy (GDateDay day,
- GDateMonth m,
- GDateYear y)
-{
- GDate *d;
- g_return_val_if_fail (g_date_valid_dmy (day, m, y), NULL);
-
- d = g_new (GDate, 1);
-
- d->julian = FALSE;
- d->dmy = TRUE;
-
- d->month = m;
- d->day = day;
- d->year = y;
-
- g_assert (g_date_valid (d));
-
- return d;
-}
-
-GDate*
-g_date_new_julian (guint32 j)
-{
- GDate *d;
- g_return_val_if_fail (g_date_valid_julian (j), NULL);
-
- d = g_new (GDate, 1);
-
- d->julian = TRUE;
- d->dmy = FALSE;
-
- d->julian_days = j;
-
- g_assert (g_date_valid (d));
-
- return d;
-}
-
-void
-g_date_free (GDate *d)
-{
- g_return_if_fail (d != NULL);
-
- g_free (d);
-}
-
-gboolean
-g_date_valid (const GDate *d)
-{
- g_return_val_if_fail (d != NULL, FALSE);
-
- return (d->julian || d->dmy);
-}
-
-static const guint8 days_in_months[2][13] =
-{ /* error, jan feb mar apr may jun jul aug sep oct nov dec */
- { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } /* leap year */
-};
-
-static const guint16 days_in_year[2][14] =
-{ /* 0, jan feb mar apr may jun jul aug sep oct nov dec */
- { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
- { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
-};
-
-gboolean
-g_date_valid_month (GDateMonth m)
-{
- return ( (m > G_DATE_BAD_MONTH) && (m < 13) );
-}
-
-gboolean
-g_date_valid_year (GDateYear y)
-{
- return ( y > G_DATE_BAD_YEAR );
-}
-
-gboolean
-g_date_valid_day (GDateDay d)
-{
- return ( (d > G_DATE_BAD_DAY) && (d < 32) );
-}
-
-gboolean
-g_date_valid_weekday (GDateWeekday w)
-{
- return ( (w > G_DATE_BAD_WEEKDAY) && (w < 8) );
-}
-
-gboolean
-g_date_valid_julian (guint32 j)
-{
- return (j > G_DATE_BAD_JULIAN);
-}
-
-gboolean
-g_date_valid_dmy (GDateDay d,
- GDateMonth m,
- GDateYear y)
-{
- return ( (m > G_DATE_BAD_MONTH) &&
- (m < 13) &&
- (d > G_DATE_BAD_DAY) &&
- (y > G_DATE_BAD_YEAR) && /* must check before using g_date_is_leap_year */
- (d <= (g_date_is_leap_year (y) ?
- days_in_months[1][m] : days_in_months[0][m])) );
-}
-
-
-/* "Julian days" just means an absolute number of days, where Day 1 ==
- * Jan 1, Year 1
- */
-static void
-g_date_update_julian (const GDate *const_d)
-{
- GDate *d = (GDate *) const_d;
- GDateYear year;
- gint idx;
-
- g_return_if_fail (d != NULL);
- g_return_if_fail (d->dmy);
- g_return_if_fail (!d->julian);
- g_return_if_fail (g_date_valid_dmy (d->day, d->month, d->year));
-
- /* What we actually do is: multiply years * 365 days in the year,
- * add the number of years divided by 4, subtract the number of
- * years divided by 100 and add the number of years divided by 400,
- * which accounts for leap year stuff. Code from Steffen Beyer's
- * DateCalc.
- */
-
- year = d->year - 1; /* we know d->year > 0 since it's valid */
-
- d->julian_days = year * 365U;
- d->julian_days += (year >>= 2); /* divide by 4 and add */
- d->julian_days -= (year /= 25); /* divides original # years by 100 */
- d->julian_days += year >> 2; /* divides by 4, which divides original by 400 */
-
- idx = g_date_is_leap_year (d->year) ? 1 : 0;
-
- d->julian_days += days_in_year[idx][d->month] + d->day;
-
- g_return_if_fail (g_date_valid_julian (d->julian_days));
-
- d->julian = TRUE;
-}
-
-static void
-g_date_update_dmy (const GDate *const_d)
-{
- GDate *d = (GDate *) const_d;
- GDateYear y;
- GDateMonth m;
- GDateDay day;
-
- guint32 A, B, C, D, E, M;
-
- g_return_if_fail (d != NULL);
- g_return_if_fail (d->julian);
- g_return_if_fail (!d->dmy);
- g_return_if_fail (g_date_valid_julian (d->julian_days));
-
- /* Formula taken from the Calendar FAQ; the formula was for the
- * Julian Period which starts on 1 January 4713 BC, so we add
- * 1,721,425 to the number of days before doing the formula.
- *
- * I'm sure this can be simplified for our 1 January 1 AD period
- * start, but I can't figure out how to unpack the formula.
- */
-
- A = d->julian_days + 1721425 + 32045;
- B = ( 4 *(A + 36524) )/ 146097 - 1;
- C = A - (146097 * B)/4;
- D = ( 4 * (C + 365) ) / 1461 - 1;
- E = C - ((1461*D) / 4);
- M = (5 * (E - 1) + 2)/153;
-
- m = M + 3 - (12*(M/10));
- day = E - (153*M + 2)/5;
- y = 100 * B + D - 4800 + (M/10);
-
-#ifdef G_ENABLE_DEBUG
- if (!g_date_valid_dmy (day, m, y))
- g_warning ("\nOOPS julian: %u computed dmy: %u %u %u\n",
- d->julian_days, day, m, y);
-#endif
-
- d->month = m;
- d->day = day;
- d->year = y;
-
- d->dmy = TRUE;
-}
-
-GDateWeekday
-g_date_get_weekday (const GDate *d)
-{
- g_return_val_if_fail (g_date_valid (d), G_DATE_BAD_WEEKDAY);
-
- if (!d->julian)
- g_date_update_julian (d);
-
- g_return_val_if_fail (d->julian, G_DATE_BAD_WEEKDAY);
-
- return ((d->julian_days - 1) % 7) + 1;
-}
-
-GDateMonth
-g_date_get_month (const GDate *d)
-{
- g_return_val_if_fail (g_date_valid (d), G_DATE_BAD_MONTH);
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_val_if_fail (d->dmy, G_DATE_BAD_MONTH);
-
- return d->month;
-}
-
-GDateYear
-g_date_get_year (const GDate *d)
-{
- g_return_val_if_fail (g_date_valid (d), G_DATE_BAD_YEAR);
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_val_if_fail (d->dmy, G_DATE_BAD_YEAR);
-
- return d->year;
-}
-
-GDateDay
-g_date_get_day (const GDate *d)
-{
- g_return_val_if_fail (g_date_valid (d), G_DATE_BAD_DAY);
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_val_if_fail (d->dmy, G_DATE_BAD_DAY);
-
- return d->day;
-}
-
-guint32
-g_date_get_julian (const GDate *d)
-{
- g_return_val_if_fail (g_date_valid (d), G_DATE_BAD_JULIAN);
-
- if (!d->julian)
- g_date_update_julian (d);
-
- g_return_val_if_fail (d->julian, G_DATE_BAD_JULIAN);
-
- return d->julian_days;
-}
-
-guint
-g_date_get_day_of_year (const GDate *d)
-{
- gint idx;
-
- g_return_val_if_fail (g_date_valid (d), 0);
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_val_if_fail (d->dmy, 0);
-
- idx = g_date_is_leap_year (d->year) ? 1 : 0;
-
- return (days_in_year[idx][d->month] + d->day);
-}
-
-guint
-g_date_get_monday_week_of_year (const GDate *d)
-{
- GDateWeekday wd;
- guint day;
- GDate first;
-
- g_return_val_if_fail (g_date_valid (d), 0);
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_val_if_fail (d->dmy, 0);
-
- g_date_clear (&first, 1);
-
- g_date_set_dmy (&first, 1, 1, d->year);
-
- wd = g_date_get_weekday (&first) - 1; /* make Monday day 0 */
- day = g_date_get_day_of_year (d) - 1;
-
- return ((day + wd)/7U + (wd == 0 ? 1 : 0));
-}
-
-guint
-g_date_get_sunday_week_of_year (const GDate *d)
-{
- GDateWeekday wd;
- guint day;
- GDate first;
-
- g_return_val_if_fail (g_date_valid (d), 0);
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_val_if_fail (d->dmy, 0);
-
- g_date_clear (&first, 1);
-
- g_date_set_dmy (&first, 1, 1, d->year);
-
- wd = g_date_get_weekday (&first);
- if (wd == 7) wd = 0; /* make Sunday day 0 */
- day = g_date_get_day_of_year (d) - 1;
-
- return ((day + wd)/7U + (wd == 0 ? 1 : 0));
-}
-
-/**
- * g_date_get_iso8601_week_of_year:
- * @date: a valid #GDate
- *
- * Returns the week of the year, where weeks are interpreted according
- * to ISO 8601.
- *
- * Returns: ISO 8601 week number of the year.
- *
- * Since: 2.6
- **/
-guint
-g_date_get_iso8601_week_of_year (const GDate *d)
-{
- guint j, d4, L, d1, w;
-
- g_return_val_if_fail (g_date_valid (d), 0);
-
- if (!d->julian)
- g_date_update_julian (d);
-
- g_return_val_if_fail (d->julian, 0);
-
- /* Formula taken from the Calendar FAQ; the formula was for the
- * Julian Period which starts on 1 January 4713 BC, so we add
- * 1,721,425 to the number of days before doing the formula.
- */
- j = d->julian_days + 1721425;
- d4 = (j + 31741 - (j % 7)) % 146097 % 36524 % 1461;
- L = d4 / 1460;
- d1 = ((d4 - L) % 365) + L;
- w = d1 / 7 + 1;
-
- return w;
-}
-
-gint
-g_date_days_between (const GDate *d1,
- const GDate *d2)
-{
- g_return_val_if_fail (g_date_valid (d1), 0);
- g_return_val_if_fail (g_date_valid (d2), 0);
-
- return (gint)g_date_get_julian (d2) - (gint)g_date_get_julian (d1);
-}
-
-void
-g_date_clear (GDate *d, guint ndates)
-{
- g_return_if_fail (d != NULL);
- g_return_if_fail (ndates != 0);
-
- memset (d, 0x0, ndates*sizeof (GDate));
-}
-
-G_LOCK_DEFINE_STATIC (g_date_global);
-
-/* These are for the parser, output to the user should use *
- * g_date_strftime () - this creates more never-freed memory to annoy
- * all those memory debugger users. :-)
- */
-
-static gchar *long_month_names[13] =
-{
- NULL,
-};
-
-static gchar *short_month_names[13] =
-{
- NULL,
-};
-
-/* This tells us if we need to update the parse info */
-static gchar *current_locale = NULL;
-
-/* order of these in the current locale */
-static GDateDMY dmy_order[3] =
-{
- G_DATE_DAY, G_DATE_MONTH, G_DATE_YEAR
-};
-
-/* Where to chop two-digit years: i.e., for the 1930 default, numbers
- * 29 and below are counted as in the year 2000, numbers 30 and above
- * are counted as in the year 1900.
- */
-
-static const GDateYear twodigit_start_year = 1930;
-
-/* It is impossible to enter a year between 1 AD and 99 AD with this
- * in effect.
- */
-static gboolean using_twodigit_years = FALSE;
-
-/* Adjustment of locale era to AD, non-zero means using locale era
- */
-static gint locale_era_adjust = 0;
-
-struct _GDateParseTokens {
- gint num_ints;
- gint n[3];
- guint month;
-};
-
-typedef struct _GDateParseTokens GDateParseTokens;
-
-#define NUM_LEN 10
-
-/* HOLDS: g_date_global_lock */
-static void
-g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
-{
- gchar num[4][NUM_LEN+1];
- gint i;
- const guchar *s;
-
- /* We count 4, but store 3; so we can give an error
- * if there are 4.
- */
- num[0][0] = num[1][0] = num[2][0] = num[3][0] = '\0';
-
- s = (const guchar *) str;
- pt->num_ints = 0;
- while (*s && pt->num_ints < 4)
- {
-
- i = 0;
- while (*s && g_ascii_isdigit (*s) && i < NUM_LEN)
- {
- num[pt->num_ints][i] = *s;
- ++s;
- ++i;
- }
-
- if (i > 0)
- {
- num[pt->num_ints][i] = '\0';
- ++(pt->num_ints);
- }
-
- if (*s == '\0') break;
-
- ++s;
- }
-
- pt->n[0] = pt->num_ints > 0 ? atoi (num[0]) : 0;
- pt->n[1] = pt->num_ints > 1 ? atoi (num[1]) : 0;
- pt->n[2] = pt->num_ints > 2 ? atoi (num[2]) : 0;
-
- pt->month = G_DATE_BAD_MONTH;
-
- if (pt->num_ints < 3)
- {
- gchar *casefold;
- gchar *normalized;
-
- casefold = g_utf8_casefold (str, -1);
- normalized = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
- g_free (casefold);
-
- i = 1;
- while (i < 13)
- {
- if (long_month_names[i] != NULL)
- {
- const gchar *found = strstr (normalized, long_month_names[i]);
-
- if (found != NULL)
- {
- pt->month = i;
- break;
- }
- }
-
- if (short_month_names[i] != NULL)
- {
- const gchar *found = strstr (normalized, short_month_names[i]);
-
- if (found != NULL)
- {
- pt->month = i;
- break;
- }
- }
-
- ++i;
- }
-
- g_free (normalized);
- }
-}
-
-/* HOLDS: g_date_global_lock */
-static void
-g_date_prepare_to_parse (const gchar *str,
- GDateParseTokens *pt)
-{
- const gchar *locale = setlocale (LC_TIME, NULL);
- gboolean recompute_localeinfo = FALSE;
- GDate d;
-
- g_return_if_fail (locale != NULL); /* should not happen */
-
- g_date_clear (&d, 1); /* clear for scratch use */
-
- if ( (current_locale == NULL) || (strcmp (locale, current_locale) != 0) )
- recompute_localeinfo = TRUE; /* Uh, there used to be a reason for the temporary */
-
- if (recompute_localeinfo)
- {
- int i = 1;
- GDateParseTokens testpt;
- gchar buf[128];
-
- g_free (current_locale); /* still works if current_locale == NULL */
-
- current_locale = g_strdup (locale);
-
- short_month_names[0] = "Error";
- long_month_names[0] = "Error";
-
- while (i < 13)
- {
- gchar *casefold;
-
- g_date_set_dmy (&d, 1, i, 1);
-
- g_return_if_fail (g_date_valid (&d));
-
- g_date_strftime (buf, 127, "%b", &d);
-
- casefold = g_utf8_casefold (buf, -1);
- g_free (short_month_names[i]);
- short_month_names[i] = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
- g_free (casefold);
-
- g_date_strftime (buf, 127, "%B", &d);
- casefold = g_utf8_casefold (buf, -1);
- g_free (long_month_names[i]);
- long_month_names[i] = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
- g_free (casefold);
-
- ++i;
- }
-
- /* Determine DMY order */
-
- /* had to pick a random day - don't change this, some strftimes
- * are broken on some days, and this one is good so far. */
- g_date_set_dmy (&d, 4, 7, 1976);
-
- g_date_strftime (buf, 127, "%x", &d);
-
- g_date_fill_parse_tokens (buf, &testpt);
-
- i = 0;
- while (i < testpt.num_ints)
- {
- switch (testpt.n[i])
- {
- case 7:
- dmy_order[i] = G_DATE_MONTH;
- break;
- case 4:
- dmy_order[i] = G_DATE_DAY;
- break;
- case 76:
- using_twodigit_years = TRUE; /* FALL THRU */
- case 1976:
- dmy_order[i] = G_DATE_YEAR;
- break;
- default:
- /* assume locale era */
- locale_era_adjust = 1976 - testpt.n[i];
- dmy_order[i] = G_DATE_YEAR;
- break;
- }
- ++i;
- }
-
-#ifdef G_ENABLE_DEBUG
- DEBUG_MSG (("**GDate prepared a new set of locale-specific parse rules."));
- i = 1;
- while (i < 13)
- {
- DEBUG_MSG ((" %s %s", long_month_names[i], short_month_names[i]));
- ++i;
- }
- if (using_twodigit_years)
- {
- DEBUG_MSG (("**Using twodigit years with cutoff year: %u", twodigit_start_year));
- }
- {
- gchar *strings[3];
- i = 0;
- while (i < 3)
- {
- switch (dmy_order[i])
- {
- case G_DATE_MONTH:
- strings[i] = "Month";
- break;
- case G_DATE_YEAR:
- strings[i] = "Year";
- break;
- case G_DATE_DAY:
- strings[i] = "Day";
- break;
- default:
- strings[i] = NULL;
- break;
- }
- ++i;
- }
- DEBUG_MSG (("**Order: %s, %s, %s", strings[0], strings[1], strings[2]));
- DEBUG_MSG (("**Sample date in this locale: `%s'", buf));
- }
-#endif
- }
-
- g_date_fill_parse_tokens (str, pt);
-}
-
-void
-g_date_set_parse (GDate *d,
- const gchar *str)
-{
- GDateParseTokens pt;
- guint m = G_DATE_BAD_MONTH, day = G_DATE_BAD_DAY, y = G_DATE_BAD_YEAR;
-
- g_return_if_fail (d != NULL);
-
- /* set invalid */
- g_date_clear (d, 1);
-
- G_LOCK (g_date_global);
-
- g_date_prepare_to_parse (str, &pt);
-
- DEBUG_MSG (("Found %d ints, `%d' `%d' `%d' and written out month %d",
- pt.num_ints, pt.n[0], pt.n[1], pt.n[2], pt.month));
-
-
- if (pt.num_ints == 4)
- {
- G_UNLOCK (g_date_global);
- return; /* presumably a typo; bail out. */
- }
-
- if (pt.num_ints > 1)
- {
- int i = 0;
- int j = 0;
-
- g_assert (pt.num_ints < 4); /* i.e., it is 2 or 3 */
-
- while (i < pt.num_ints && j < 3)
- {
- switch (dmy_order[j])
- {
- case G_DATE_MONTH:
- {
- if (pt.num_ints == 2 && pt.month != G_DATE_BAD_MONTH)
- {
- m = pt.month;
- ++j; /* skip months, but don't skip this number */
- continue;
- }
- else
- m = pt.n[i];
- }
- break;
- case G_DATE_DAY:
- {
- if (pt.num_ints == 2 && pt.month == G_DATE_BAD_MONTH)
- {
- day = 1;
- ++j; /* skip days, since we may have month/year */
- continue;
- }
- day = pt.n[i];
- }
- break;
- case G_DATE_YEAR:
- {
- y = pt.n[i];
-
- if (locale_era_adjust != 0)
- {
- y += locale_era_adjust;
- }
- else if (using_twodigit_years && y < 100)
- {
- guint two = twodigit_start_year % 100;
- guint century = (twodigit_start_year / 100) * 100;
-
- if (y < two)
- century += 100;
-
- y += century;
- }
- }
- break;
- default:
- break;
- }
-
- ++i;
- ++j;
- }
-
-
- if (pt.num_ints == 3 && !g_date_valid_dmy (day, m, y))
- {
- /* Try YYYY MM DD */
- y = pt.n[0];
- m = pt.n[1];
- day = pt.n[2];
-
- if (using_twodigit_years && y < 100)
- y = G_DATE_BAD_YEAR; /* avoids ambiguity */
- }
- else if (pt.num_ints == 2)
- {
- if (m == G_DATE_BAD_MONTH && pt.month != G_DATE_BAD_MONTH)
- m = pt.month;
- }
- }
- else if (pt.num_ints == 1)
- {
- if (pt.month != G_DATE_BAD_MONTH)
- {
- /* Month name and year? */
- m = pt.month;
- day = 1;
- y = pt.n[0];
- }
- else
- {
- /* Try yyyymmdd and yymmdd */
-
- m = (pt.n[0]/100) % 100;
- day = pt.n[0] % 100;
- y = pt.n[0]/10000;
-
- /* FIXME move this into a separate function */
- if (using_twodigit_years && y < 100)
- {
- guint two = twodigit_start_year % 100;
- guint century = (twodigit_start_year / 100) * 100;
-
- if (y < two)
- century += 100;
-
- y += century;
- }
- }
- }
-
- /* See if we got anything valid out of all this. */
- /* y < 8000 is to catch 19998 style typos; the library is OK up to 65535 or so */
- if (y < 8000 && g_date_valid_dmy (day, m, y))
- {
- d->month = m;
- d->day = day;
- d->year = y;
- d->dmy = TRUE;
- }
-#ifdef G_ENABLE_DEBUG
- else
- {
- DEBUG_MSG (("Rejected DMY %u %u %u", day, m, y));
- }
-#endif
- G_UNLOCK (g_date_global);
-}
-
-/**
- * g_date_set_time_t:
- * @date: a #GDate
- * @timet: <type>time_t</type> value to set
- *
- * Sets the value of a date to the date corresponding to a time
- * specified as a time_t. The time to date conversion is done using
- * the user's current timezone.
- *
- * To set the value of a date to the current day, you could write:
- * |[
- * g_date_set_time_t (date, time (NULL));
- * ]|
- *
- * Since: 2.10
- */
-void
-g_date_set_time_t (GDate *date,
- time_t timet)
-{
- struct tm tm;
-
- g_return_if_fail (date != NULL);
-
-#ifdef HAVE_LOCALTIME_R
- localtime_r (&timet, &tm);
-#else
- {
- struct tm *ptm = localtime (&timet);
-
- if (ptm == NULL)
- {
- /* Happens at least in Microsoft's C library if you pass a
- * negative time_t. Use 2000-01-01 as default date.
- */
-#ifndef G_DISABLE_CHECKS
- g_return_if_fail_warning (G_LOG_DOMAIN, "g_date_set_time", "ptm != NULL");
-#endif
-
- tm.tm_mon = 0;
- tm.tm_mday = 1;
- tm.tm_year = 100;
- }
- else
- memcpy ((void *) &tm, (void *) ptm, sizeof(struct tm));
- }
-#endif
-
- date->julian = FALSE;
-
- date->month = tm.tm_mon + 1;
- date->day = tm.tm_mday;
- date->year = tm.tm_year + 1900;
-
- g_return_if_fail (g_date_valid_dmy (date->day, date->month, date->year));
-
- date->dmy = TRUE;
-}
-
-
-/**
- * g_date_set_time:
- * @date: a #GDate.
- * @time_: #GTime value to set.
- *
- * Sets the value of a date from a #GTime value.
- * The time to date conversion is done using the user's current timezone.
- *
- * @Deprecated:2.10: Use g_date_set_time_t() instead.
- */
-void
-g_date_set_time (GDate *date,
- GTime time_)
-{
- g_date_set_time_t (date, (time_t) time_);
-}
-
-/**
- * g_date_set_time_val:
- * @date: a #GDate
- * @timeval: #GTimeVal value to set
- *
- * Sets the value of a date from a #GTimeVal value. Note that the
- * @tv_usec member is ignored, because #GDate can't make use of the
- * additional precision.
- *
- * Since: 2.10
- */
-void
-g_date_set_time_val (GDate *date,
- GTimeVal *timeval)
-{
- g_date_set_time_t (date, (time_t) timeval->tv_sec);
-}
-
-void
-g_date_set_month (GDate *d,
- GDateMonth m)
-{
- g_return_if_fail (d != NULL);
- g_return_if_fail (g_date_valid_month (m));
-
- if (d->julian && !d->dmy) g_date_update_dmy(d);
- d->julian = FALSE;
-
- d->month = m;
-
- if (g_date_valid_dmy (d->day, d->month, d->year))
- d->dmy = TRUE;
- else
- d->dmy = FALSE;
-}
-
-void
-g_date_set_day (GDate *d,
- GDateDay day)
-{
- g_return_if_fail (d != NULL);
- g_return_if_fail (g_date_valid_day (day));
-
- if (d->julian && !d->dmy) g_date_update_dmy(d);
- d->julian = FALSE;
-
- d->day = day;
-
- if (g_date_valid_dmy (d->day, d->month, d->year))
- d->dmy = TRUE;
- else
- d->dmy = FALSE;
-}
-
-void
-g_date_set_year (GDate *d,
- GDateYear y)
-{
- g_return_if_fail (d != NULL);
- g_return_if_fail (g_date_valid_year (y));
-
- if (d->julian && !d->dmy) g_date_update_dmy(d);
- d->julian = FALSE;
-
- d->year = y;
-
- if (g_date_valid_dmy (d->day, d->month, d->year))
- d->dmy = TRUE;
- else
- d->dmy = FALSE;
-}
-
-void
-g_date_set_dmy (GDate *d,
- GDateDay day,
- GDateMonth m,
- GDateYear y)
-{
- g_return_if_fail (d != NULL);
- g_return_if_fail (g_date_valid_dmy (day, m, y));
-
- d->julian = FALSE;
-
- d->month = m;
- d->day = day;
- d->year = y;
-
- d->dmy = TRUE;
-}
-
-void
-g_date_set_julian (GDate *d,
- guint32 j)
-{
- g_return_if_fail (d != NULL);
- g_return_if_fail (g_date_valid_julian (j));
-
- d->julian_days = j;
- d->julian = TRUE;
- d->dmy = FALSE;
-}
-
-
-gboolean
-g_date_is_first_of_month (const GDate *d)
-{
- g_return_val_if_fail (g_date_valid (d), FALSE);
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_val_if_fail (d->dmy, FALSE);
-
- if (d->day == 1) return TRUE;
- else return FALSE;
-}
-
-gboolean
-g_date_is_last_of_month (const GDate *d)
-{
- gint idx;
-
- g_return_val_if_fail (g_date_valid (d), FALSE);
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_val_if_fail (d->dmy, FALSE);
-
- idx = g_date_is_leap_year (d->year) ? 1 : 0;
-
- if (d->day == days_in_months[idx][d->month]) return TRUE;
- else return FALSE;
-}
-
-void
-g_date_add_days (GDate *d,
- guint ndays)
-{
- g_return_if_fail (g_date_valid (d));
-
- if (!d->julian)
- g_date_update_julian (d);
-
- g_return_if_fail (d->julian);
-
- d->julian_days += ndays;
- d->dmy = FALSE;
-}
-
-void
-g_date_subtract_days (GDate *d,
- guint ndays)
-{
- g_return_if_fail (g_date_valid (d));
-
- if (!d->julian)
- g_date_update_julian (d);
-
- g_return_if_fail (d->julian);
- g_return_if_fail (d->julian_days > ndays);
-
- d->julian_days -= ndays;
- d->dmy = FALSE;
-}
-
-void
-g_date_add_months (GDate *d,
- guint nmonths)
-{
- guint years, months;
- gint idx;
-
- g_return_if_fail (g_date_valid (d));
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_if_fail (d->dmy);
-
- nmonths += d->month - 1;
-
- years = nmonths/12;
- months = nmonths%12;
-
- d->month = months + 1;
- d->year += years;
-
- idx = g_date_is_leap_year (d->year) ? 1 : 0;
-
- if (d->day > days_in_months[idx][d->month])
- d->day = days_in_months[idx][d->month];
-
- d->julian = FALSE;
-
- g_return_if_fail (g_date_valid (d));
-}
-
-void
-g_date_subtract_months (GDate *d,
- guint nmonths)
-{
- guint years, months;
- gint idx;
-
- g_return_if_fail (g_date_valid (d));
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_if_fail (d->dmy);
-
- years = nmonths/12;
- months = nmonths%12;
-
- g_return_if_fail (d->year > years);
-
- d->year -= years;
-
- if (d->month > months) d->month -= months;
- else
- {
- months -= d->month;
- d->month = 12 - months;
- d->year -= 1;
- }
-
- idx = g_date_is_leap_year (d->year) ? 1 : 0;
-
- if (d->day > days_in_months[idx][d->month])
- d->day = days_in_months[idx][d->month];
-
- d->julian = FALSE;
-
- g_return_if_fail (g_date_valid (d));
-}
-
-void
-g_date_add_years (GDate *d,
- guint nyears)
-{
- g_return_if_fail (g_date_valid (d));
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_if_fail (d->dmy);
-
- d->year += nyears;
-
- if (d->month == 2 && d->day == 29)
- {
- if (!g_date_is_leap_year (d->year))
- d->day = 28;
- }
-
- d->julian = FALSE;
-}
-
-void
-g_date_subtract_years (GDate *d,
- guint nyears)
-{
- g_return_if_fail (g_date_valid (d));
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_if_fail (d->dmy);
- g_return_if_fail (d->year > nyears);
-
- d->year -= nyears;
-
- if (d->month == 2 && d->day == 29)
- {
- if (!g_date_is_leap_year (d->year))
- d->day = 28;
- }
-
- d->julian = FALSE;
-}
-
-gboolean
-g_date_is_leap_year (GDateYear year)
-{
- g_return_val_if_fail (g_date_valid_year (year), FALSE);
-
- return ( (((year % 4) == 0) && ((year % 100) != 0)) ||
- (year % 400) == 0 );
-}
-
-guint8
-g_date_get_days_in_month (GDateMonth month,
- GDateYear year)
-{
- gint idx;
-
- g_return_val_if_fail (g_date_valid_year (year), 0);
- g_return_val_if_fail (g_date_valid_month (month), 0);
-
- idx = g_date_is_leap_year (year) ? 1 : 0;
-
- return days_in_months[idx][month];
-}
-
-guint8
-g_date_get_monday_weeks_in_year (GDateYear year)
-{
- GDate d;
-
- g_return_val_if_fail (g_date_valid_year (year), 0);
-
- g_date_clear (&d, 1);
- g_date_set_dmy (&d, 1, 1, year);
- if (g_date_get_weekday (&d) == G_DATE_MONDAY) return 53;
- g_date_set_dmy (&d, 31, 12, year);
- if (g_date_get_weekday (&d) == G_DATE_MONDAY) return 53;
- if (g_date_is_leap_year (year))
- {
- g_date_set_dmy (&d, 2, 1, year);
- if (g_date_get_weekday (&d) == G_DATE_MONDAY) return 53;
- g_date_set_dmy (&d, 30, 12, year);
- if (g_date_get_weekday (&d) == G_DATE_MONDAY) return 53;
- }
- return 52;
-}
-
-guint8
-g_date_get_sunday_weeks_in_year (GDateYear year)
-{
- GDate d;
-
- g_return_val_if_fail (g_date_valid_year (year), 0);
-
- g_date_clear (&d, 1);
- g_date_set_dmy (&d, 1, 1, year);
- if (g_date_get_weekday (&d) == G_DATE_SUNDAY) return 53;
- g_date_set_dmy (&d, 31, 12, year);
- if (g_date_get_weekday (&d) == G_DATE_SUNDAY) return 53;
- if (g_date_is_leap_year (year))
- {
- g_date_set_dmy (&d, 2, 1, year);
- if (g_date_get_weekday (&d) == G_DATE_SUNDAY) return 53;
- g_date_set_dmy (&d, 30, 12, year);
- if (g_date_get_weekday (&d) == G_DATE_SUNDAY) return 53;
- }
- return 52;
-}
-
-gint
-g_date_compare (const GDate *lhs,
- const GDate *rhs)
-{
- g_return_val_if_fail (lhs != NULL, 0);
- g_return_val_if_fail (rhs != NULL, 0);
- g_return_val_if_fail (g_date_valid (lhs), 0);
- g_return_val_if_fail (g_date_valid (rhs), 0);
-
- /* Remember the self-comparison case! I think it works right now. */
-
- while (TRUE)
- {
- if (lhs->julian && rhs->julian)
- {
- if (lhs->julian_days < rhs->julian_days) return -1;
- else if (lhs->julian_days > rhs->julian_days) return 1;
- else return 0;
- }
- else if (lhs->dmy && rhs->dmy)
- {
- if (lhs->year < rhs->year) return -1;
- else if (lhs->year > rhs->year) return 1;
- else
- {
- if (lhs->month < rhs->month) return -1;
- else if (lhs->month > rhs->month) return 1;
- else
- {
- if (lhs->day < rhs->day) return -1;
- else if (lhs->day > rhs->day) return 1;
- else return 0;
- }
-
- }
-
- }
- else
- {
- if (!lhs->julian) g_date_update_julian (lhs);
- if (!rhs->julian) g_date_update_julian (rhs);
- g_return_val_if_fail (lhs->julian, 0);
- g_return_val_if_fail (rhs->julian, 0);
- }
-
- }
- return 0; /* warnings */
-}
-
-
-void
-g_date_to_struct_tm (const GDate *d,
- struct tm *tm)
-{
- GDateWeekday day;
-
- g_return_if_fail (g_date_valid (d));
- g_return_if_fail (tm != NULL);
-
- if (!d->dmy)
- g_date_update_dmy (d);
-
- g_return_if_fail (d->dmy);
-
- /* zero all the irrelevant fields to be sure they're valid */
-
- /* On Linux and maybe other systems, there are weird non-POSIX
- * fields on the end of struct tm that choke strftime if they
- * contain garbage. So we need to 0 the entire struct, not just the
- * fields we know to exist.
- */
-
- memset (tm, 0x0, sizeof (struct tm));
-
- tm->tm_mday = d->day;
- tm->tm_mon = d->month - 1; /* 0-11 goes in tm */
- tm->tm_year = ((int)d->year) - 1900; /* X/Open says tm_year can be negative */
-
- day = g_date_get_weekday (d);
- if (day == 7) day = 0; /* struct tm wants days since Sunday, so Sunday is 0 */
-
- tm->tm_wday = (int)day;
-
- tm->tm_yday = g_date_get_day_of_year (d) - 1; /* 0 to 365 */
- tm->tm_isdst = -1; /* -1 means "information not available" */
-}
-
-void
-g_date_clamp (GDate *date,
- const GDate *min_date,
- const GDate *max_date)
-{
- g_return_if_fail (g_date_valid (date));
-
- if (min_date != NULL)
- g_return_if_fail (g_date_valid (min_date));
-
- if (max_date != NULL)
- g_return_if_fail (g_date_valid (max_date));
-
- if (min_date != NULL && max_date != NULL)
- g_return_if_fail (g_date_compare (min_date, max_date) <= 0);
-
- if (min_date && g_date_compare (date, min_date) < 0)
- *date = *min_date;
-
- if (max_date && g_date_compare (max_date, date) < 0)
- *date = *max_date;
-}
-
-void
-g_date_order (GDate *date1,
- GDate *date2)
-{
- g_return_if_fail (g_date_valid (date1));
- g_return_if_fail (g_date_valid (date2));
-
- if (g_date_compare (date1, date2) > 0)
- {
- GDate tmp = *date1;
- *date1 = *date2;
- *date2 = tmp;
- }
-}
-
-#ifdef G_OS_WIN32
-static gsize
-win32_strftime_helper (const GDate *d,
- const gchar *format,
- const struct tm *tm,
- gchar *s,
- gsize slen)
-{
- SYSTEMTIME systemtime;
- TIME_ZONE_INFORMATION tzinfo;
- LCID lcid;
- int n, k;
- GArray *result;
- const gchar *p;
- gunichar c;
- const wchar_t digits[] = L"0123456789";
- gchar *convbuf;
- glong convlen = 0;
- gsize retval;
-
- systemtime.wYear = tm->tm_year + 1900;
- systemtime.wMonth = tm->tm_mon + 1;
- systemtime.wDayOfWeek = tm->tm_wday;
- systemtime.wDay = tm->tm_mday;
- systemtime.wHour = tm->tm_hour;
- systemtime.wMinute = tm->tm_min;
- systemtime.wSecond = tm->tm_sec;
- systemtime.wMilliseconds = 0;
-
- lcid = GetThreadLocale ();
- result = g_array_sized_new (FALSE, FALSE, sizeof (wchar_t), MAX (128, strlen (format) * 2));
-
- p = format;
- while (*p)
- {
- c = g_utf8_get_char (p);
- if (c == '%')
- {
- p = g_utf8_next_char (p);
- if (!*p)
- {
- s[0] = '\0';
- g_array_free (result, TRUE);
-
- return 0;
- }
-
- c = g_utf8_get_char (p);
- if (c == 'E' || c == 'O')
- {
- /* Ignore modified conversion specifiers for now. */
- p = g_utf8_next_char (p);
- if (!*p)
- {
- s[0] = '\0';
- g_array_free (result, TRUE);
-
- return 0;
- }
-
- c = g_utf8_get_char (p);
- }
-
- switch (c)
- {
- case 'a':
- if (systemtime.wDayOfWeek == 0)
- k = 6;
- else
- k = systemtime.wDayOfWeek - 1;
- n = GetLocaleInfoW (lcid, LOCALE_SABBREVDAYNAME1+k, NULL, 0);
- g_array_set_size (result, result->len + n);
- GetLocaleInfoW (lcid, LOCALE_SABBREVDAYNAME1+k, ((wchar_t *) result->data) + result->len - n, n);
- g_array_set_size (result, result->len - 1);
- break;
- case 'A':
- if (systemtime.wDayOfWeek == 0)
- k = 6;
- else
- k = systemtime.wDayOfWeek - 1;
- n = GetLocaleInfoW (lcid, LOCALE_SDAYNAME1+k, NULL, 0);
- g_array_set_size (result, result->len + n);
- GetLocaleInfoW (lcid, LOCALE_SDAYNAME1+k, ((wchar_t *) result->data) + result->len - n, n);
- g_array_set_size (result, result->len - 1);
- break;
- case 'b':
- case 'h':
- n = GetLocaleInfoW (lcid, LOCALE_SABBREVMONTHNAME1+systemtime.wMonth-1, NULL, 0);
- g_array_set_size (result, result->len + n);
- GetLocaleInfoW (lcid, LOCALE_SABBREVMONTHNAME1+systemtime.wMonth-1, ((wchar_t *) result->data) + result->len - n, n);
- g_array_set_size (result, result->len - 1);
- break;
- case 'B':
- n = GetLocaleInfoW (lcid, LOCALE_SMONTHNAME1+systemtime.wMonth-1, NULL, 0);
- g_array_set_size (result, result->len + n);
- GetLocaleInfoW (lcid, LOCALE_SMONTHNAME1+systemtime.wMonth-1, ((wchar_t *) result->data) + result->len - n, n);
- g_array_set_size (result, result->len - 1);
- break;
- case 'c':
- n = GetDateFormatW (lcid, 0, &systemtime, NULL, NULL, 0);
- if (n > 0)
- {
- g_array_set_size (result, result->len + n);
- GetDateFormatW (lcid, 0, &systemtime, NULL, ((wchar_t *) result->data) + result->len - n, n);
- g_array_set_size (result, result->len - 1);
- }
- g_array_append_vals (result, L" ", 1);
- n = GetTimeFormatW (lcid, 0, &systemtime, NULL, NULL, 0);
- if (n > 0)
- {
- g_array_set_size (result, result->len + n);
- GetTimeFormatW (lcid, 0, &systemtime, NULL, ((wchar_t *) result->data) + result->len - n, n);
- g_array_set_size (result, result->len - 1);
- }
- break;
- case 'C':
- g_array_append_vals (result, digits + systemtime.wYear/1000, 1);
- g_array_append_vals (result, digits + (systemtime.wYear/1000)%10, 1);
- break;
- case 'd':
- g_array_append_vals (result, digits + systemtime.wDay/10, 1);
- g_array_append_vals (result, digits + systemtime.wDay%10, 1);
- break;
- case 'D':
- g_array_append_vals (result, digits + systemtime.wMonth/10, 1);
- g_array_append_vals (result, digits + systemtime.wMonth%10, 1);
- g_array_append_vals (result, L"/", 1);
- g_array_append_vals (result, digits + systemtime.wDay/10, 1);
- g_array_append_vals (result, digits + systemtime.wDay%10, 1);
- g_array_append_vals (result, L"/", 1);
- g_array_append_vals (result, digits + (systemtime.wYear/10)%10, 1);
- g_array_append_vals (result, digits + systemtime.wYear%10, 1);
- break;
- case 'e':
- if (systemtime.wDay >= 10)
- g_array_append_vals (result, digits + systemtime.wDay/10, 1);
- else
- g_array_append_vals (result, L" ", 1);
- g_array_append_vals (result, digits + systemtime.wDay%10, 1);
- break;
-
- /* A GDate has no time fields, so for now we can
- * hardcode all time conversions into zeros (or 12 for
- * %I). The alternative code snippets in the #else
- * branches are here ready to be taken into use when
- * needed by a g_strftime() or g_date_and_time_format()
- * or whatever.
- */
- case 'H':
-#if 1
- g_array_append_vals (result, L"00", 2);
-#else
- g_array_append_vals (result, digits + systemtime.wHour/10, 1);
- g_array_append_vals (result, digits + systemtime.wHour%10, 1);
-#endif
- break;
- case 'I':
-#if 1
- g_array_append_vals (result, L"12", 2);
-#else
- if (systemtime.wHour == 0)
- g_array_append_vals (result, L"12", 2);
- else
- {
- g_array_append_vals (result, digits + (systemtime.wHour%12)/10, 1);
- g_array_append_vals (result, digits + (systemtime.wHour%12)%10, 1);
- }
-#endif
- break;
- case 'j':
- g_array_append_vals (result, digits + (tm->tm_yday+1)/100, 1);
- g_array_append_vals (result, digits + ((tm->tm_yday+1)/10)%10, 1);
- g_array_append_vals (result, digits + (tm->tm_yday+1)%10, 1);
- break;
- case 'm':
- g_array_append_vals (result, digits + systemtime.wMonth/10, 1);
- g_array_append_vals (result, digits + systemtime.wMonth%10, 1);
- break;
- case 'M':
-#if 1
- g_array_append_vals (result, L"00", 2);
-#else
- g_array_append_vals (result, digits + systemtime.wMinute/10, 1);
- g_array_append_vals (result, digits + systemtime.wMinute%10, 1);
-#endif
- break;
- case 'n':
- g_array_append_vals (result, L"\n", 1);
- break;
- case 'p':
- n = GetTimeFormatW (lcid, 0, &systemtime, L"tt", NULL, 0);
- if (n > 0)
- {
- g_array_set_size (result, result->len + n);
- GetTimeFormatW (lcid, 0, &systemtime, L"tt", ((wchar_t *) result->data) + result->len - n, n);
- g_array_set_size (result, result->len - 1);
- }
- break;
- case 'r':
- /* This is a rather odd format. Hard to say what to do.
- * Let's always use the POSIX %I:%M:%S %p
- */
-#if 1
- g_array_append_vals (result, L"12:00:00", 8);
-#else
- if (systemtime.wHour == 0)
- g_array_append_vals (result, L"12", 2);
- else
- {
- g_array_append_vals (result, digits + (systemtime.wHour%12)/10, 1);
- g_array_append_vals (result, digits + (systemtime.wHour%12)%10, 1);
- }
- g_array_append_vals (result, L":", 1);
- g_array_append_vals (result, digits + systemtime.wMinute/10, 1);
- g_array_append_vals (result, digits + systemtime.wMinute%10, 1);
- g_array_append_vals (result, L":", 1);
- g_array_append_vals (result, digits + systemtime.wSecond/10, 1);
- g_array_append_vals (result, digits + systemtime.wSecond%10, 1);
- g_array_append_vals (result, L" ", 1);
-#endif
- n = GetTimeFormatW (lcid, 0, &systemtime, L"tt", NULL, 0);
- if (n > 0)
- {
- g_array_set_size (result, result->len + n);
- GetTimeFormatW (lcid, 0, &systemtime, L"tt", ((wchar_t *) result->data) + result->len - n, n);
- g_array_set_size (result, result->len - 1);
- }
- break;
- case 'R':
-#if 1
- g_array_append_vals (result, L"00:00", 5);
-#else
- g_array_append_vals (result, digits + systemtime.wHour/10, 1);
- g_array_append_vals (result, digits + systemtime.wHour%10, 1);
- g_array_append_vals (result, L":", 1);
- g_array_append_vals (result, digits + systemtime.wMinute/10, 1);
- g_array_append_vals (result, digits + systemtime.wMinute%10, 1);
-#endif
- break;
- case 'S':
-#if 1
- g_array_append_vals (result, L"00", 2);
-#else
- g_array_append_vals (result, digits + systemtime.wSecond/10, 1);
- g_array_append_vals (result, digits + systemtime.wSecond%10, 1);
-#endif
- break;
- case 't':
- g_array_append_vals (result, L"\t", 1);
- break;
- case 'T':
-#if 1
- g_array_append_vals (result, L"00:00:00", 8);
-#else
- g_array_append_vals (result, digits + systemtime.wHour/10, 1);
- g_array_append_vals (result, digits + systemtime.wHour%10, 1);
- g_array_append_vals (result, L":", 1);
- g_array_append_vals (result, digits + systemtime.wMinute/10, 1);
- g_array_append_vals (result, digits + systemtime.wMinute%10, 1);
- g_array_append_vals (result, L":", 1);
- g_array_append_vals (result, digits + systemtime.wSecond/10, 1);
- g_array_append_vals (result, digits + systemtime.wSecond%10, 1);
-#endif
- break;
- case 'u':
- if (systemtime.wDayOfWeek == 0)
- g_array_append_vals (result, L"7", 1);
- else
- g_array_append_vals (result, digits + systemtime.wDayOfWeek, 1);
- break;
- case 'U':
- n = g_date_get_sunday_week_of_year (d);
- g_array_append_vals (result, digits + n/10, 1);
- g_array_append_vals (result, digits + n%10, 1);
- break;
- case 'V':
- n = g_date_get_iso8601_week_of_year (d);
- g_array_append_vals (result, digits + n/10, 1);
- g_array_append_vals (result, digits + n%10, 1);
- break;
- case 'w':
- g_array_append_vals (result, digits + systemtime.wDayOfWeek, 1);
- break;
- case 'W':
- n = g_date_get_monday_week_of_year (d);
- g_array_append_vals (result, digits + n/10, 1);
- g_array_append_vals (result, digits + n%10, 1);
- break;
- case 'x':
- n = GetDateFormatW (lcid, 0, &systemtime, NULL, NULL, 0);
- if (n > 0)
- {
- g_array_set_size (result, result->len + n);
- GetDateFormatW (lcid, 0, &systemtime, NULL, ((wchar_t *) result->data) + result->len - n, n);
- g_array_set_size (result, result->len - 1);
- }
- break;
- case 'X':
- n = GetTimeFormatW (lcid, 0, &systemtime, NULL, NULL, 0);
- if (n > 0)
- {
- g_array_set_size (result, result->len + n);
- GetTimeFormatW (lcid, 0, &systemtime, NULL, ((wchar_t *) result->data) + result->len - n, n);
- g_array_set_size (result, result->len - 1);
- }
- break;
- case 'y':
- g_array_append_vals (result, digits + (systemtime.wYear/10)%10, 1);
- g_array_append_vals (result, digits + systemtime.wYear%10, 1);
- break;
- case 'Y':
- g_array_append_vals (result, digits + systemtime.wYear/1000, 1);
- g_array_append_vals (result, digits + (systemtime.wYear/100)%10, 1);
- g_array_append_vals (result, digits + (systemtime.wYear/10)%10, 1);
- g_array_append_vals (result, digits + systemtime.wYear%10, 1);
- break;
- case 'Z':
- n = GetTimeZoneInformation (&tzinfo);
- if (n == TIME_ZONE_ID_UNKNOWN)
- ;
- else if (n == TIME_ZONE_ID_STANDARD)
- g_array_append_vals (result, tzinfo.StandardName, wcslen (tzinfo.StandardName));
- else if (n == TIME_ZONE_ID_DAYLIGHT)
- g_array_append_vals (result, tzinfo.DaylightName, wcslen (tzinfo.DaylightName));
- break;
- case '%':
- g_array_append_vals (result, L"%", 1);
- break;
- }
- }
- else if (c <= 0xFFFF)
- {
- wchar_t wc = c;
- g_array_append_vals (result, &wc, 1);
- }
- else
- {
- glong nwc;
- wchar_t *ws;
-
- ws = g_ucs4_to_utf16 (&c, 1, NULL, &nwc, NULL);
- g_array_append_vals (result, ws, nwc);
- g_free (ws);
- }
- p = g_utf8_next_char (p);
- }
-
- convbuf = g_utf16_to_utf8 ((wchar_t *) result->data, result->len, NULL, &convlen, NULL);
- g_array_free (result, TRUE);
-
- if (!convbuf)
- {
- s[0] = '\0';
- return 0;
- }
-
- if (slen <= convlen)
- {
- /* Ensure only whole characters are copied into the buffer. */
- gchar *end = g_utf8_find_prev_char (convbuf, convbuf + slen);
- g_assert (end != NULL);
- convlen = end - convbuf;
-
- /* Return 0 because the buffer isn't large enough. */
- retval = 0;
- }
- else
- retval = convlen;
-
- memcpy (s, convbuf, convlen);
- s[convlen] = '\0';
- g_free (convbuf);
-
- return retval;
-}
-
-#endif
-
-gsize
-g_date_strftime (gchar *s,
- gsize slen,
- const gchar *format,
- const GDate *d)
-{
- struct tm tm;
-#ifndef G_OS_WIN32
- gsize locale_format_len = 0;
- gchar *locale_format;
- gsize tmplen;
- gchar *tmpbuf;
- gsize tmpbufsize;
- gsize convlen = 0;
- gchar *convbuf;
- GError *error = NULL;
- gsize retval;
-#endif
-
- g_return_val_if_fail (g_date_valid (d), 0);
- g_return_val_if_fail (slen > 0, 0);
- g_return_val_if_fail (format != NULL, 0);
- g_return_val_if_fail (s != NULL, 0);
-
- g_date_to_struct_tm (d, &tm);
-
-#ifdef G_OS_WIN32
- if (!g_utf8_validate (format, -1, NULL))
- {
- s[0] = '\0';
- return 0;
- }
- return win32_strftime_helper (d, format, &tm, s, slen);
-#else
-
- locale_format = g_locale_from_utf8 (format, -1, NULL, &locale_format_len, &error);
-
- if (error)
- {
- g_warning (G_STRLOC "Error converting format to locale encoding: %s\n", error->message);
- g_error_free (error);
-
- s[0] = '\0';
- return 0;
- }
-
- tmpbufsize = MAX (128, locale_format_len * 2);
- while (TRUE)
- {
- tmpbuf = g_malloc (tmpbufsize);
-
- /* Set the first byte to something other than '\0', to be able to
- * recognize whether strftime actually failed or just returned "".
- */
- tmpbuf[0] = '\1';
- tmplen = strftime (tmpbuf, tmpbufsize, locale_format, &tm);
-
- if (tmplen == 0 && tmpbuf[0] != '\0')
- {
- g_free (tmpbuf);
- tmpbufsize *= 2;
-
- if (tmpbufsize > 65536)
- {
- g_warning (G_STRLOC "Maximum buffer size for g_date_strftime exceeded: giving up\n");
- g_free (locale_format);
-
- s[0] = '\0';
- return 0;
- }
- }
- else
- break;
- }
- g_free (locale_format);
-
- convbuf = g_locale_to_utf8 (tmpbuf, tmplen, NULL, &convlen, &error);
- g_free (tmpbuf);
-
- if (error)
- {
- g_warning (G_STRLOC "Error converting results of strftime to UTF-8: %s\n", error->message);
- g_error_free (error);
-
- s[0] = '\0';
- return 0;
- }
-
- if (slen <= convlen)
- {
- /* Ensure only whole characters are copied into the buffer.
- */
- gchar *end = g_utf8_find_prev_char (convbuf, convbuf + slen);
- g_assert (end != NULL);
- convlen = end - convbuf;
-
- /* Return 0 because the buffer isn't large enough.
- */
- retval = 0;
- }
- else
- retval = convlen;
-
- memcpy (s, convbuf, convlen);
- s[convlen] = '\0';
- g_free (convbuf);
-
- return retval;
-#endif
-}
-
-#define __G_DATE_C__
-#include "galiasdef.c"
-
diff --git a/glib/gen-script-table.pl b/glib/gen-script-table.pl
deleted file mode 100755
index 27268ab84..000000000
--- a/glib/gen-script-table.pl
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/perl -w
-#
-# Script to convert http://www.unicode.org/Public/UNIDATA/Scripts.txt
-# into a machine-readable table.
-#
-######################################################################
-
-if (@ARGV != 1) {
- die "Usage: gen-script-table.pl Scripts.txt > gscripttable.h\n";
-}
-
-open IN, $ARGV[0] || die "Cannot open $ARGV[0]: $!\n";
-
-my @ranges;
-my $file;
-my $easy_range;
-my $i;
-my $start;
-my $end;
-my $script;
-
-
-while (<IN>) {
- if (/^\#\s+(Scripts-.*.txt)/) {
- $file = $1;
- }
-
- s/#.*//;
- next if /^\s*$/;
- if (!/^([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s*;\s*([A-Za-z_]+)\s*$/) {
- die "Cannot parse line: '$_'\n";
- }
-
- if (defined $2) {
- push @ranges, [ hex $1, hex $2, uc $3 ];
- } else {
- push @ranges, [ hex $1, hex $1, uc $3 ];
- }
-}
-
-@ranges = sort { $a->[0] <=> $b->[0] } @ranges;
-$date = gmtime;
-
-print <<"EOT";
-/* gscripttable.h: Generated by gen-script-table.pl
- *
- * Date: $date
- * Source: $file
- *
- * Do not edit.
- */
-
-EOT
-
-$easy_range = 0x2000;
-
-print <<"EOT";
-#define G_EASY_SCRIPTS_RANGE $easy_range
-
-static const guchar g_script_easy_table[$easy_range] = {
-EOT
-
-$i = 0;
-$end = -1;
-
-for (my $c = 0; $c < $easy_range; $c++) {
-
- if ($c % 3 == 0) {
- printf "\n ";
- }
-
- if ($c > $end) {
- $start = $ranges[$i]->[0];
- $end = $ranges[$i]->[1];
- $script = $ranges[$i]->[2];
- $i++;
- }
-
- if ($c < $start) {
- printf " G_UNICODE_SCRIPT_UNKNOWN,";
- } else {
- printf " G_UNICODE_SCRIPT_%s,", $script;
- }
-}
-
-if ($end >= $easy_range) {
- $i--;
- $ranges[$i]->[0] = $easy_range;
-}
-
-
-print <<"EOT";
-
-};
-
-static const struct {
- gunichar start;
- guint16 chars;
- guint16 script;
-} g_script_table[] = {
-EOT
-
-for (; $i <= $#ranges; $i++) {
- $start = $ranges[$i]->[0];
- $end = $ranges[$i]->[1];
- $script = $ranges[$i]->[2];
-
- while ($i <= $#ranges - 1 &&
- $ranges[$i + 1]->[0] == $end + 1 &&
- $ranges[$i + 1]->[2] eq $script) {
- $i++;
- $end = $ranges[$i]->[1];
- }
-
- printf " { %#06x, %5d, G_UNICODE_SCRIPT_%s },\n", $start, $end - $start + 1, $script;
-}
-
-printf "};\n";
-
diff --git a/glib/gen-unicode-tables.pl b/glib/gen-unicode-tables.pl
deleted file mode 100755
index 5368adfc6..000000000
--- a/glib/gen-unicode-tables.pl
+++ /dev/null
@@ -1,1303 +0,0 @@
-#! /usr/bin/perl -w
-
-# Copyright (C) 1998, 1999 Tom Tromey
-# Copyright (C) 2001 Red Hat Software
-
-# 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, or (at your option)
-# any later version.
-
-# This program 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 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.
-
-# Contributer(s):
-# Andrew Taylor <andrew.taylor@montage.ca>
-
-# gen-unicode-tables.pl - Generate tables for libunicode from Unicode data.
-# See http://www.unicode.org/Public/UNIDATA/UnicodeCharacterDatabase.html
-# I consider the output of this program to be unrestricted. Use it as
-# you will.
-
-# FIXME:
-# * For decomp table it might make sense to use a shift count other
-# than 8. We could easily compute the perfect shift count.
-
-# we use some perl unicode features
-require 5.006;
-
-use vars qw($CODE $NAME $CATEGORY $COMBINING_CLASSES $BIDI_CATEGORY $DECOMPOSITION $DECIMAL_VALUE $DIGIT_VALUE $NUMERIC_VALUE $MIRRORED $OLD_NAME $COMMENT $UPPER $LOWER $TITLE $BREAK_CODE $BREAK_CATEGORY $BREAK_NAME $CASE_CODE $CASE_LOWER $CASE_TITLE $CASE_UPPER $CASE_CONDITION);
-
-
-# Names of fields in Unicode data table.
-$CODE = 0;
-$NAME = 1;
-$CATEGORY = 2;
-$COMBINING_CLASSES = 3;
-$BIDI_CATEGORY = 4;
-$DECOMPOSITION = 5;
-$DECIMAL_VALUE = 6;
-$DIGIT_VALUE = 7;
-$NUMERIC_VALUE = 8;
-$MIRRORED = 9;
-$OLD_NAME = 10;
-$COMMENT = 11;
-$UPPER = 12;
-$LOWER = 13;
-$TITLE = 14;
-
-# Names of fields in the line break table
-$BREAK_CODE = 0;
-$BREAK_PROPERTY = 1;
-
-# Names of fields in the SpecialCasing table
-$CASE_CODE = 0;
-$CASE_LOWER = 1;
-$CASE_TITLE = 2;
-$CASE_UPPER = 3;
-$CASE_CONDITION = 4;
-
-# Names of fields in the CaseFolding table
-$FOLDING_CODE = 0;
-$FOLDING_STATUS = 1;
-$FOLDING_MAPPING = 2;
-
-# Map general category code onto symbolic name.
-%mappings =
- (
- # Normative.
- 'Lu' => "G_UNICODE_UPPERCASE_LETTER",
- 'Ll' => "G_UNICODE_LOWERCASE_LETTER",
- 'Lt' => "G_UNICODE_TITLECASE_LETTER",
- 'Mn' => "G_UNICODE_NON_SPACING_MARK",
- 'Mc' => "G_UNICODE_COMBINING_MARK",
- 'Me' => "G_UNICODE_ENCLOSING_MARK",
- 'Nd' => "G_UNICODE_DECIMAL_NUMBER",
- 'Nl' => "G_UNICODE_LETTER_NUMBER",
- 'No' => "G_UNICODE_OTHER_NUMBER",
- 'Zs' => "G_UNICODE_SPACE_SEPARATOR",
- 'Zl' => "G_UNICODE_LINE_SEPARATOR",
- 'Zp' => "G_UNICODE_PARAGRAPH_SEPARATOR",
- 'Cc' => "G_UNICODE_CONTROL",
- 'Cf' => "G_UNICODE_FORMAT",
- 'Cs' => "G_UNICODE_SURROGATE",
- 'Co' => "G_UNICODE_PRIVATE_USE",
- 'Cn' => "G_UNICODE_UNASSIGNED",
-
- # Informative.
- 'Lm' => "G_UNICODE_MODIFIER_LETTER",
- 'Lo' => "G_UNICODE_OTHER_LETTER",
- 'Pc' => "G_UNICODE_CONNECT_PUNCTUATION",
- 'Pd' => "G_UNICODE_DASH_PUNCTUATION",
- 'Ps' => "G_UNICODE_OPEN_PUNCTUATION",
- 'Pe' => "G_UNICODE_CLOSE_PUNCTUATION",
- 'Pi' => "G_UNICODE_INITIAL_PUNCTUATION",
- 'Pf' => "G_UNICODE_FINAL_PUNCTUATION",
- 'Po' => "G_UNICODE_OTHER_PUNCTUATION",
- 'Sm' => "G_UNICODE_MATH_SYMBOL",
- 'Sc' => "G_UNICODE_CURRENCY_SYMBOL",
- 'Sk' => "G_UNICODE_MODIFIER_SYMBOL",
- 'So' => "G_UNICODE_OTHER_SYMBOL"
- );
-
-%break_mappings =
- (
- 'BK' => "G_UNICODE_BREAK_MANDATORY",
- 'CR' => "G_UNICODE_BREAK_CARRIAGE_RETURN",
- 'LF' => "G_UNICODE_BREAK_LINE_FEED",
- 'CM' => "G_UNICODE_BREAK_COMBINING_MARK",
- 'SG' => "G_UNICODE_BREAK_SURROGATE",
- 'ZW' => "G_UNICODE_BREAK_ZERO_WIDTH_SPACE",
- 'IN' => "G_UNICODE_BREAK_INSEPARABLE",
- 'GL' => "G_UNICODE_BREAK_NON_BREAKING_GLUE",
- 'CB' => "G_UNICODE_BREAK_CONTINGENT",
- 'SP' => "G_UNICODE_BREAK_SPACE",
- 'BA' => "G_UNICODE_BREAK_AFTER",
- 'BB' => "G_UNICODE_BREAK_BEFORE",
- 'B2' => "G_UNICODE_BREAK_BEFORE_AND_AFTER",
- 'HY' => "G_UNICODE_BREAK_HYPHEN",
- 'NS' => "G_UNICODE_BREAK_NON_STARTER",
- 'OP' => "G_UNICODE_BREAK_OPEN_PUNCTUATION",
- 'CL' => "G_UNICODE_BREAK_CLOSE_PUNCTUATION",
- 'QU' => "G_UNICODE_BREAK_QUOTATION",
- 'EX' => "G_UNICODE_BREAK_EXCLAMATION",
- 'ID' => "G_UNICODE_BREAK_IDEOGRAPHIC",
- 'NU' => "G_UNICODE_BREAK_NUMERIC",
- 'IS' => "G_UNICODE_BREAK_INFIX_SEPARATOR",
- 'SY' => "G_UNICODE_BREAK_SYMBOL",
- 'AL' => "G_UNICODE_BREAK_ALPHABETIC",
- 'PR' => "G_UNICODE_BREAK_PREFIX",
- 'PO' => "G_UNICODE_BREAK_POSTFIX",
- 'SA' => "G_UNICODE_BREAK_COMPLEX_CONTEXT",
- 'AI' => "G_UNICODE_BREAK_AMBIGUOUS",
- 'NL' => "G_UNICODE_BREAK_NEXT_LINE",
- 'WJ' => "G_UNICODE_BREAK_WORD_JOINER",
- 'XX' => "G_UNICODE_BREAK_UNKNOWN",
- 'JL' => "G_UNICODE_BREAK_HANGUL_L_JAMO",
- 'JV' => "G_UNICODE_BREAK_HANGUL_V_JAMO",
- 'JT' => "G_UNICODE_BREAK_HANGUL_T_JAMO",
- 'H2' => "G_UNICODE_BREAK_HANGUL_LV_SYLLABLE",
- 'H3' => "G_UNICODE_BREAK_HANGUL_LVT_SYLLABLE"
- );
-
-# Title case mappings.
-%title_to_lower = ();
-%title_to_upper = ();
-
-# Maximum length of special-case strings
-
-my @special_cases;
-my @special_case_offsets;
-my $special_case_offset = 0;
-
-$do_decomp = 0;
-$do_props = 1;
-if (@ARGV && $ARGV[0] eq '-decomp')
-{
- $do_decomp = 1;
- $do_props = 0;
- shift @ARGV;
-}
-elsif (@ARGV && $ARGV[0] eq '-both')
-{
- $do_decomp = 1;
- shift @ARGV;
-}
-
-if (@ARGV != 2) {
- $0 =~ s@.*/@@;
- die "\nUsage: $0 [-decomp | -both] UNICODE-VERSION DIRECTORY\n\n DIRECTORY should contain the following Unicode data files:\n UnicodeData.txt, LineBreak.txt, SpecialCasing.txt, CaseFolding.txt,\n CompositionExclusions.txt, BidiMirroring.txt\n\n";
-}
-
-my ($unicodedatatxt, $linebreaktxt, $specialcasingtxt, $casefoldingtxt, $compositionexclusionstxt);
-
-my $d = $ARGV[1];
-opendir (my $dir, $d) or die "Cannot open Unicode data dir $d: $!\n";
-for my $f (readdir ($dir))
-{
- $unicodedatatxt = "$d/$f" if ($f =~ /UnicodeData.*\.txt/);
- $linebreaktxt = "$d/$f" if ($f =~ /LineBreak.*\.txt/);
- $specialcasingtxt = "$d/$f" if ($f =~ /SpecialCasing.*\.txt/);
- $casefoldingtxt = "$d/$f" if ($f =~ /CaseFolding.*\.txt/);
- $compositionexclusionstxt = "$d/$f" if ($f =~ /CompositionExclusions.*\.txt/);
-}
-
-defined $unicodedatatxt or die "Did not find UnicodeData file";
-defined $linebreaktxt or die "Did not find LineBreak file";
-defined $specialcasingtxt or die "Did not find SpecialCasing file";
-defined $casefoldingtxt or die "Did not find CaseFolding file";
-defined $compositionexclusionstxt or die "Did not find CompositionExclusions file";
-
-print "Creating decomp table\n" if ($do_decomp);
-print "Creating property table\n" if ($do_props);
-
-print "Composition exlusions from $compositionexclusionstxt\n";
-
-open (INPUT, "< $compositionexclusionstxt") || exit 1;
-
-while (<INPUT>) {
-
- chop;
-
- next if /^#/;
- next if /^\s*$/;
-
- s/\s*#.*//;
-
- s/^\s*//;
- s/\s*$//;
-
- $composition_exclusions{hex($_)} = 1;
-}
-
-close INPUT;
-
-print "Unicode data from $unicodedatatxt\n";
-
-open (INPUT, "< $unicodedatatxt") || exit 1;
-
-# we save memory by skipping the huge empty area before U+E0000
-my $pages_before_e0000;
-
-$last_code = -1;
-while (<INPUT>)
-{
- chop;
- @fields = split (';', $_, 30);
- if ($#fields != 14)
- {
- printf STDERR ("Entry for $fields[$CODE] has wrong number of fields (%d)\n", $#fields);
- }
-
- $code = hex ($fields[$CODE]);
-
- if ($code >= 0xE0000 and $last_code < 0xE0000)
- {
- $pages_before_e0000 = ($last_code >> 8) + 1;
- }
-
- if ($code > $last_code + 1)
- {
- # Found a gap.
- if ($fields[$NAME] =~ /Last>/)
- {
- # Fill the gap with the last character read,
- # since this was a range specified in the char database
- @gfields = @fields;
- }
- else
- {
- # The gap represents undefined characters. Only the type
- # matters.
- @gfields = ('', '', 'Cn', '0', '', '', '', '', '', '', '',
- '', '', '', '');
- }
- for (++$last_code; $last_code < $code; ++$last_code)
- {
- $gfields{$CODE} = sprintf ("%04x", $last_code);
- &process_one ($last_code, @gfields);
- }
- }
- &process_one ($code, @fields);
- $last_code = $code;
-}
-
-close INPUT;
-
-@gfields = ('', '', 'Cn', '0', '', '', '', '', '', '', '',
- '', '', '', '');
-for (++$last_code; $last_code <= 0x10FFFF; ++$last_code)
-{
- $gfields{$CODE} = sprintf ("%04x", $last_code);
- &process_one ($last_code, @gfields);
-}
---$last_code; # Want last to be 0x10FFFF.
-
-print "Creating line break table\n";
-
-print "Line break data from $linebreaktxt\n";
-
-open (INPUT, "< $linebreaktxt") || exit 1;
-
-$last_code = -1;
-while (<INPUT>)
-{
- my ($start_code, $end_code);
-
- chop;
-
- next if /^#/;
-
- s/\s*#.*//;
-
- @fields = split (';', $_, 30);
- if ($#fields != 1)
- {
- printf STDERR ("Entry for $fields[$CODE] has wrong number of fields (%d)\n", $#fields);
- next;
- }
-
- if ($fields[$CODE] =~ /([A-F0-9]{4,6})\.\.([A-F0-9]{4,6})/)
- {
- $start_code = hex ($1);
- $end_code = hex ($2);
- } else {
- $start_code = $end_code = hex ($fields[$CODE]);
-
- }
-
- if ($start_code > $last_code + 1)
- {
- # The gap represents undefined characters. If assigned,
- # they are AL, if not assigned, XX
- for (++$last_code; $last_code < $start_code; ++$last_code)
- {
- if ($type[$last_code] eq 'Cn')
- {
- $break_props[$last_code] = 'XX';
- }
- else
- {
- $break_props[$last_code] = 'AL';
- }
- }
- }
-
- for ($last_code = $start_code; $last_code <= $end_code; $last_code++)
- {
- $break_props[$last_code] = $fields[$BREAK_PROPERTY];
- }
-
- $last_code = $end_code;
-}
-
-close INPUT;
-
-for (++$last_code; $last_code <= 0x10FFFF; ++$last_code)
-{
- if ($type[$last_code] eq 'Cn')
- {
- $break_props[$last_code] = 'XX';
- }
- else
- {
- $break_props[$last_code] = 'AL';
- }
-}
---$last_code; # Want last to be 0x10FFFF.
-
-print STDERR "Last code is not 0x10FFFF" if ($last_code != 0x10FFFF);
-
-print "Reading special-casing table for case conversion\n";
-
-open (INPUT, "< $specialcasingtxt") || exit 1;
-
-while (<INPUT>)
-{
- my $code;
-
- chop;
-
- next if /^#/;
- next if /^\s*$/;
-
- s/\s*#.*//;
-
- @fields = split ('\s*;\s*', $_, 30);
-
- $raw_code = $fields[$CASE_CODE];
- $code = hex ($raw_code);
-
- if ($#fields != 4 && $#fields != 5)
- {
- printf STDERR ("Entry for $raw_code has wrong number of fields (%d)\n", $#fields);
- next;
- }
-
- if (!defined $type[$code])
- {
- printf STDERR "Special case for code point: $code, which has no defined type\n";
- next;
- }
-
- if (defined $fields[5]) {
- # Ignore conditional special cases - we'll handle them in code
- next;
- }
-
- if ($type[$code] eq 'Lu')
- {
- (hex $fields[$CASE_UPPER] == $code) || die "$raw_code is Lu and UCD_Upper($raw_code) != $raw_code";
-
- &add_special_case ($code, $value[$code], $fields[$CASE_LOWER], $fields[$CASE_TITLE]);
-
- } elsif ($type[$code] eq 'Lt')
- {
- (hex $fields[$CASE_TITLE] == $code) || die "$raw_code is Lt and UCD_Title($raw_code) != $raw_code";
-
- &add_special_case ($code, undef, $fields[$CASE_LOWER], $fields[$CASE_UPPER]);
- } elsif ($type[$code] eq 'Ll')
- {
- (hex $fields[$CASE_LOWER] == $code) || die "$raw_code is Ll and UCD_Lower($raw_code) != $raw_code";
-
- &add_special_case ($code, $value[$code], $fields[$CASE_UPPER], $fields[$CASE_TITLE]);
- } else {
- printf STDERR "Special case for non-alphabetic code point: $raw_code\n";
- next;
- }
-}
-
-close INPUT;
-
-open (INPUT, "< $casefoldingtxt") || exit 1;
-
-my $casefoldlen = 0;
-my @casefold;
-
-while (<INPUT>)
-{
- my $code;
-
- chop;
-
- next if /^#/;
- next if /^\s*$/;
-
- s/\s*#.*//;
-
- @fields = split ('\s*;\s*', $_, 30);
-
- $raw_code = $fields[$FOLDING_CODE];
- $code = hex ($raw_code);
-
- if ($#fields != 3)
- {
- printf STDERR ("Entry for $raw_code has wrong number of fields (%d)\n", $#fields);
- next;
- }
-
- # we don't use Simple or Turkic rules here
- next if ($fields[$FOLDING_STATUS] =~ /^[ST]$/);
-
- @values = map { hex ($_) } split /\s+/, $fields[$FOLDING_MAPPING];
-
- # Check simple case
-
- if (@values == 1 &&
- !(defined $value[$code] && $value[$code] >= 0x1000000) &&
- defined $type[$code]) {
-
- my $lower;
- if ($type[$code] eq 'Ll')
- {
- $lower = $code;
- } elsif ($type[$code] eq 'Lt')
- {
- $lower = $title_to_lower{$code};
- } elsif ($type[$code] eq 'Lu')
- {
- $lower = $value[$code];
- } else {
- $lower = $code;
- }
-
- if ($lower == $values[0]) {
- next;
- }
- }
-
- my $string = pack ("U*", @values);
-
- if (1 + &length_in_bytes ($string) > $casefoldlen) {
- $casefoldlen = 1 + &length_in_bytes ($string);
- }
-
- push @casefold, [ $code, &escape ($string) ];
-}
-
-close INPUT;
-
-if ($do_props) {
- &print_tables ($last_code)
-}
-if ($do_decomp) {
- &print_decomp ($last_code);
- &output_composition_table;
-}
-
-&print_line_break ($last_code);
-
-exit 0;
-
-
-# perl "length" returns the length in characters
-sub length_in_bytes
-{
- my ($string) = @_;
-
- use bytes;
- return length $string;
-}
-
-# Process a single character.
-sub process_one
-{
- my ($code, @fields) = @_;
-
- $type[$code] = $fields[$CATEGORY];
- if ($type[$code] eq 'Nd')
- {
- $value[$code] = int ($fields[$DECIMAL_VALUE]);
- }
- elsif ($type[$code] eq 'Ll')
- {
- $value[$code] = hex ($fields[$UPPER]);
- }
- elsif ($type[$code] eq 'Lu')
- {
- $value[$code] = hex ($fields[$LOWER]);
- }
-
- if ($type[$code] eq 'Lt')
- {
- $title_to_lower{$code} = hex ($fields[$LOWER]);
- $title_to_upper{$code} = hex ($fields[$UPPER]);
- }
-
- $cclass[$code] = $fields[$COMBINING_CLASSES];
-
- # Handle decompositions.
- if ($fields[$DECOMPOSITION] ne '')
- {
- if ($fields[$DECOMPOSITION] =~ s/\<.*\>\s*//) {
- $decompose_compat[$code] = 1;
- } else {
- $decompose_compat[$code] = 0;
-
- if (!exists $composition_exclusions{$code}) {
- $compositions{$code} = $fields[$DECOMPOSITION];
- }
- }
- $decompositions[$code] = $fields[$DECOMPOSITION];
- }
-}
-
-sub print_tables
-{
- my ($last) = @_;
- my ($outfile) = "gunichartables.h";
-
- local ($bytes_out) = 0;
-
- print "Writing $outfile...\n";
-
- open (OUT, "> $outfile");
-
- print OUT "/* This file is automatically generated. DO NOT EDIT!\n";
- print OUT " Instead, edit gen-unicode-tables.pl and re-run. */\n\n";
-
- print OUT "#ifndef CHARTABLES_H\n";
- print OUT "#define CHARTABLES_H\n\n";
-
- print OUT "#define G_UNICODE_DATA_VERSION \"$ARGV[0]\"\n\n";
-
- printf OUT "#define G_UNICODE_LAST_CHAR 0x%04x\n\n", $last;
-
- printf OUT "#define G_UNICODE_MAX_TABLE_INDEX 10000\n\n";
-
- my $last_part1 = ($pages_before_e0000 * 256) - 1;
- printf OUT "#define G_UNICODE_LAST_CHAR_PART1 0x%04X\n\n", $last_part1;
- printf OUT "#define G_UNICODE_LAST_PAGE_PART1 %d\n\n", $pages_before_e0000 - 1;
-
- $table_index = 0;
- printf OUT "static const char type_data[][256] = {\n";
- for ($count = 0; $count <= $last; $count += 256)
- {
- $row[$count / 256] = &print_row ($count, 1, \&fetch_type);
- }
- printf OUT "\n};\n\n";
-
- printf OUT "/* U+0000 through U+%04X */\n", $last_part1;
- print OUT "static const gint16 type_table_part1[$pages_before_e0000] = {\n";
- for ($count = 0; $count <= $last_part1; $count += 256)
- {
- print OUT ",\n" if $count > 0;
- print OUT " ", $row[$count / 256];
- $bytes_out += 2;
- }
- print OUT "\n};\n\n";
-
- printf OUT "/* U+E0000 through U+%04X */\n", $last;
- print OUT "static const gint16 type_table_part2[768] = {\n";
- for ($count = 0xE0000; $count <= $last; $count += 256)
- {
- print OUT ",\n" if $count > 0xE0000;
- print OUT " ", $row[$count / 256];
- $bytes_out += 2;
- }
- print OUT "\n};\n\n";
-
-
- #
- # Now print attribute table.
- #
-
- $table_index = 0;
- printf OUT "static const gunichar attr_data[][256] = {\n";
- for ($count = 0; $count <= $last; $count += 256)
- {
- $row[$count / 256] = &print_row ($count, 4, \&fetch_attr);
- }
- printf OUT "\n};\n\n";
-
- printf OUT "/* U+0000 through U+%04X */\n", $last_part1;
- print OUT "static const gint16 attr_table_part1[$pages_before_e0000] = {\n";
- for ($count = 0; $count <= $last_part1; $count += 256)
- {
- print OUT ",\n" if $count > 0;
- print OUT " ", $row[$count / 256];
- $bytes_out += 2;
- }
- print OUT "\n};\n\n";
-
- printf OUT "/* U+E0000 through U+%04X */\n", $last;
- print OUT "static const gint16 attr_table_part2[768] = {\n";
- for ($count = 0xE0000; $count <= $last; $count += 256)
- {
- print OUT ",\n" if $count > 0xE0000;
- print OUT " ", $row[$count / 256];
- $bytes_out += 2;
- }
- print OUT "\n};\n\n";
-
- #
- # print title case table
- #
-
- print OUT "static const gunichar title_table[][3] = {\n";
- my ($item);
- my ($first) = 1;
- foreach $item (sort keys %title_to_lower)
- {
- print OUT ",\n"
- unless $first;
- $first = 0;
- printf OUT " { 0x%04x, 0x%04x, 0x%04x }", $item, $title_to_upper{$item}, $title_to_lower{$item};
- $bytes_out += 12;
- }
- print OUT "\n};\n\n";
-
- #
- # And special case conversion table -- conversions that change length
- #
- &output_special_case_table (\*OUT);
- &output_casefold_table (\*OUT);
-
- print OUT "#endif /* CHARTABLES_H */\n";
-
- close (OUT);
-
- printf STDERR "Generated %d bytes in tables\n", $bytes_out;
-}
-
-# A fetch function for the type table.
-sub fetch_type
-{
- my ($index) = @_;
- return $mappings{$type[$index]};
-}
-
-# A fetch function for the attribute table.
-sub fetch_attr
-{
- my ($index) = @_;
- if (defined $value[$index])
- {
- return sprintf ("0x%04x", $value[$index]);
- }
- else
- {
- return "0x0000";
- }
-}
-
-sub print_row
-{
- my ($start, $typsize, $fetcher) = @_;
-
- my ($i);
- my (@values);
- my ($flag) = 1;
- my ($off);
-
- for ($off = 0; $off < 256; ++$off)
- {
- $values[$off] = $fetcher->($off + $start);
- if ($values[$off] ne $values[0])
- {
- $flag = 0;
- }
- }
- if ($flag)
- {
- return $values[0] . " + G_UNICODE_MAX_TABLE_INDEX";
- }
-
- printf OUT ",\n" if ($table_index != 0);
- printf OUT " { /* page %d, index %d */\n ", $start / 256, $table_index;
- my ($column) = 4;
- for ($i = $start; $i < $start + 256; ++$i)
- {
- print OUT ", "
- if $i > $start;
- my ($text) = $values[$i - $start];
- if (length ($text) + $column + 2 > 78)
- {
- print OUT "\n ";
- $column = 4;
- }
- print OUT $text;
- $column += length ($text) + 2;
- }
- print OUT "\n }";
-
- $bytes_out += 256 * $typsize;
-
- return sprintf "%d /* page %d */", $table_index++, $start / 256;
-}
-
-sub escape
-{
- my ($string) = @_;
-
- my $escaped = unpack("H*", $string);
- $escaped =~ s/(.{2})/\\x$1/g;
-
- return $escaped;
-}
-
-# Returns the offset of $decomp in the offset string. Updates the
-# referenced variables as appropriate.
-sub handle_decomp ($$$$)
-{
- my ($decomp, $decomp_offsets_ref, $decomp_string_ref, $decomp_string_offset_ref) = @_;
- my $offset = "G_UNICODE_NOT_PRESENT_OFFSET";
-
- if (defined $decomp)
- {
- if (defined $decomp_offsets_ref->{$decomp})
- {
- $offset = $decomp_offsets_ref->{$decomp};
- }
- else
- {
- $offset = ${$decomp_string_offset_ref};
- $decomp_offsets_ref->{$decomp} = $offset;
- ${$decomp_string_ref} .= "\n \"" . &escape ($decomp) . "\\0\" /* offset ${$decomp_string_offset_ref} */";
- ${$decomp_string_offset_ref} += &length_in_bytes ($decomp) + 1;
- }
- }
-
- return $offset;
-}
-
-# Generate the character decomposition header.
-sub print_decomp
-{
- my ($last) = @_;
- my ($outfile) = "gunidecomp.h";
-
- local ($bytes_out) = 0;
-
- print "Writing $outfile...\n";
-
- open (OUT, "> $outfile") || exit 1;
-
- print OUT "/* This file is automatically generated. DO NOT EDIT! */\n\n";
- print OUT "#ifndef DECOMP_H\n";
- print OUT "#define DECOMP_H\n\n";
-
- printf OUT "#define G_UNICODE_LAST_CHAR 0x%04x\n\n", $last;
-
- printf OUT "#define G_UNICODE_MAX_TABLE_INDEX (0x110000 / 256)\n\n";
-
- my $last_part1 = ($pages_before_e0000 * 256) - 1;
- printf OUT "#define G_UNICODE_LAST_CHAR_PART1 0x%04X\n\n", $last_part1;
- printf OUT "#define G_UNICODE_LAST_PAGE_PART1 %d\n\n", $pages_before_e0000 - 1;
-
- $NOT_PRESENT_OFFSET = 65535;
- print OUT "#define G_UNICODE_NOT_PRESENT_OFFSET $NOT_PRESENT_OFFSET\n\n";
-
- my ($count, @row);
- $table_index = 0;
- printf OUT "static const guchar cclass_data[][256] = {\n";
- for ($count = 0; $count <= $last; $count += 256)
- {
- $row[$count / 256] = &print_row ($count, 1, \&fetch_cclass);
- }
- printf OUT "\n};\n\n";
-
- print OUT "static const gint16 combining_class_table_part1[$pages_before_e0000] = {\n";
- for ($count = 0; $count <= $last_part1; $count += 256)
- {
- print OUT ",\n" if $count > 0;
- print OUT " ", $row[$count / 256];
- $bytes_out += 2;
- }
- print OUT "\n};\n\n";
-
- print OUT "static const gint16 combining_class_table_part2[768] = {\n";
- for ($count = 0xE0000; $count <= $last; $count += 256)
- {
- print OUT ",\n" if $count > 0xE0000;
- print OUT " ", $row[$count / 256];
- $bytes_out += 2;
- }
- print OUT "\n};\n\n";
-
- print OUT "typedef struct\n{\n";
- print OUT " gunichar ch;\n";
- print OUT " guint16 canon_offset;\n";
- print OUT " guint16 compat_offset;\n";
- print OUT "} decomposition;\n\n";
-
- print OUT "static const decomposition decomp_table[] =\n{\n";
- my ($iter);
- my ($first) = 1;
- my ($decomp_string) = "";
- my ($decomp_string_offset) = 0;
- for ($count = 0; $count <= $last; ++$count)
- {
- if (defined $decompositions[$count])
- {
- print OUT ",\n"
- if ! $first;
- $first = 0;
-
- my $canon_decomp;
- my $compat_decomp;
-
- if (!$decompose_compat[$count]) {
- $canon_decomp = make_decomp ($count, 0);
- }
- $compat_decomp = make_decomp ($count, 1);
-
- if (defined $canon_decomp && $compat_decomp eq $canon_decomp) {
- undef $compat_decomp;
- }
-
- my $canon_offset = handle_decomp ($canon_decomp, \%decomp_offsets, \$decomp_string, \$decomp_string_offset);
- my $compat_offset = handle_decomp ($compat_decomp, \%decomp_offsets, \$decomp_string, \$decomp_string_offset);
-
- die if $decomp_string_offset > $NOT_PRESENT_OFFSET;
-
- printf OUT qq( { 0x%04x, $canon_offset, $compat_offset }), $count;
- $bytes_out += 8;
- }
- }
- print OUT "\n};\n\n";
- $bytes_out += $decomp_string_offset + 1;
-
- printf OUT "static const gchar decomp_expansion_string[] = %s;\n\n", $decomp_string;
-
- print OUT "#endif /* DECOMP_H */\n";
-
- printf STDERR "Generated %d bytes in decomp tables\n", $bytes_out;
-}
-
-sub print_line_break
-{
- my ($last) = @_;
- my ($outfile) = "gunibreak.h";
-
- local ($bytes_out) = 0;
-
- print "Writing $outfile...\n";
-
- open (OUT, "> $outfile");
-
- print OUT "/* This file is automatically generated. DO NOT EDIT!\n";
- print OUT " Instead, edit gen-unicode-tables.pl and re-run. */\n\n";
-
- print OUT "#ifndef BREAKTABLES_H\n";
- print OUT "#define BREAKTABLES_H\n\n";
-
- print OUT "#define G_UNICODE_DATA_VERSION \"$ARGV[0]\"\n\n";
-
- printf OUT "#define G_UNICODE_LAST_CHAR 0x%04X\n\n", $last;
-
- printf OUT "#define G_UNICODE_MAX_TABLE_INDEX 10000\n\n";
-
- my $last_part1 = ($pages_before_e0000 * 256) - 1;
- printf OUT "/* the last code point that should be looked up in break_property_table_part1 */\n";
- printf OUT "#define G_UNICODE_LAST_CHAR_PART1 0x%04X\n\n", $last_part1;
-
- $table_index = 0;
- printf OUT "static const gint8 break_property_data[][256] = {\n";
- for ($count = 0; $count <= $last; $count += 256)
- {
- $row[$count / 256] = &print_row ($count, 1, \&fetch_break_type);
- }
- printf OUT "\n};\n\n";
-
- printf OUT "/* U+0000 through U+%04X */\n", $last_part1;
- print OUT "static const gint16 break_property_table_part1[$pages_before_e0000] = {\n";
- for ($count = 0; $count <= $last_part1; $count += 256)
- {
- print OUT ",\n" if $count > 0;
- print OUT " ", $row[$count / 256];
- $bytes_out += 2;
- }
- print OUT "\n};\n\n";
-
- printf OUT "/* U+E0000 through U+%04X */\n", $last;
- print OUT "static const gint16 break_property_table_part2[768] = {\n";
- for ($count = 0xE0000; $count <= $last; $count += 256)
- {
- print OUT ",\n" if $count > 0xE0000;
- print OUT " ", $row[$count / 256];
- $bytes_out += 2;
- }
- print OUT "\n};\n\n";
-
-
- print OUT "#endif /* BREAKTABLES_H */\n";
-
- close (OUT);
-
- printf STDERR "Generated %d bytes in break tables\n", $bytes_out;
-}
-
-
-# A fetch function for the break properties table.
-sub fetch_break_type
-{
- my ($index) = @_;
- return $break_mappings{$break_props[$index]};
-}
-
-# Fetcher for combining class.
-sub fetch_cclass
-{
- my ($i) = @_;
- return $cclass[$i];
-}
-
-# Expand a character decomposition recursively.
-sub expand_decomp
-{
- my ($code, $compat) = @_;
-
- my ($iter, $val);
- my (@result) = ();
- foreach $iter (split (' ', $decompositions[$code]))
- {
- $val = hex ($iter);
- if (defined $decompositions[$val] &&
- ($compat || !$decompose_compat[$val]))
- {
- push (@result, &expand_decomp ($val, $compat));
- }
- else
- {
- push (@result, $val);
- }
- }
-
- return @result;
-}
-
-sub make_decomp
-{
- my ($code, $compat) = @_;
-
- my $result = "";
- foreach $iter (&expand_decomp ($code, $compat))
- {
- $result .= pack ("U", $iter); # to utf-8
- }
-
- $result;
-}
-# Generate special case data string from two fields
-sub add_special_case
-{
- my ($code, $single, $field1, $field2) = @_;
-
- @values = (defined $single ? $single : (),
- (map { hex ($_) } split /\s+/, $field1),
- 0,
- (map { hex ($_) } split /\s+/, $field2));
- $result = "";
-
-
- for $value (@values) {
- $result .= pack ("U", $value); # to utf-8
- }
-
- push @special_case_offsets, $special_case_offset;
-
- # We encode special cases up in the 0x1000000 space
- $value[$code] = 0x1000000 + $special_case_offset;
-
- $special_case_offset += 1 + &length_in_bytes ($result);
-
- push @special_cases, &escape ($result);
-}
-
-sub output_special_case_table
-{
- my $out = shift;
-
- print $out <<EOT;
-
-/* Table of special cases for case conversion; each record contains
- * First, the best single character mapping to lowercase if Lu,
- * and to uppercase if Ll, followed by the output mapping for the two cases
- * other than the case of the codepoint, in the order [Ll],[Lu],[Lt],
- * encoded in UTF-8, separated and terminated by a null character.
- */
-static const gchar special_case_table[] = {
-EOT
-
- my $i = 0;
- for $case (@special_cases) {
- print $out qq( "$case\\0" /* offset ${special_case_offsets[$i]} */\n);
- $i++;
- }
-
- print $out <<EOT;
-};
-
-EOT
-
- print STDERR "Generated " . ($special_case_offset + 1) . " bytes in special case table\n";
-}
-
-sub enumerate_ordered
-{
- my ($array) = @_;
-
- my $n = 0;
- for my $code (sort { $a <=> $b } keys %$array) {
- if ($array->{$code} == 1) {
- delete $array->{$code};
- next;
- }
- $array->{$code} = $n++;
- }
-
- return $n;
-}
-
-sub output_composition_table
-{
- print STDERR "Generating composition table\n";
-
- local ($bytes_out) = 0;
-
- my %first;
- my %second;
-
- # First we need to go through and remove decompositions
- # starting with a non-starter, and single-character
- # decompositions. At the same time, record
- # the first and second character of each decomposition
-
- for $code (keys %compositions)
- {
- @values = map { hex ($_) } split /\s+/, $compositions{$code};
-
- # non-starters
- if ($cclass[$values[0]]) {
- delete $compositions{$code};
- next;
- }
-
- # single-character decompositions
- if (@values == 1) {
- delete $compositions{$code};
- next;
- }
-
- if (@values != 2) {
- die "$code has more than two elements in its decomposition!\n";
- }
-
- if (exists $first{$values[0]}) {
- $first{$values[0]}++;
- } else {
- $first{$values[0]} = 1;
- }
- }
-
- # Assign integer indices, removing singletons
- my $n_first = enumerate_ordered (\%first);
-
- # Now record the second character of each (non-singleton) decomposition
- for $code (keys %compositions) {
- @values = map { hex ($_) } split /\s+/, $compositions{$code};
-
- if (exists $first{$values[0]}) {
- if (exists $second{$values[1]}) {
- $second{$values[1]}++;
- } else {
- $second{$values[1]} = 1;
- }
- }
- }
-
- # Assign integer indices, removing duplicate
- my $n_second = enumerate_ordered (\%second);
-
- # Build reverse table
-
- my @first_singletons;
- my @second_singletons;
- my %reverse;
- for $code (keys %compositions) {
- @values = map { hex ($_) } split /\s+/, $compositions{$code};
-
- my $first = $first{$values[0]};
- my $second = $second{$values[1]};
-
- if (defined $first && defined $second) {
- $reverse{"$first|$second"} = $code;
- } elsif (!defined $first) {
- push @first_singletons, [ $values[0], $values[1], $code ];
- } else {
- push @second_singletons, [ $values[1], $values[0], $code ];
- }
- }
-
- @first_singletons = sort { $a->[0] <=> $b->[0] } @first_singletons;
- @second_singletons = sort { $a->[0] <=> $b->[0] } @second_singletons;
-
- my %vals;
-
- open OUT, ">gunicomp.h" or die "Cannot open gunicomp.h: $!\n";
-
- # Assign values in lookup table for all code points involved
-
- my $total = 1;
- my $last = 0;
- printf OUT "#define COMPOSE_FIRST_START %d\n", $total;
- for $code (keys %first) {
- $vals{$code} = $first{$code} + $total;
- $last = $code if $code > $last;
- }
- $total += $n_first;
- $i = 0;
- printf OUT "#define COMPOSE_FIRST_SINGLE_START %d\n", $total;
- for $record (@first_singletons) {
- my $code = $record->[0];
- $vals{$code} = $i++ + $total;
- $last = $code if $code > $last;
- }
- $total += @first_singletons;
- printf OUT "#define COMPOSE_SECOND_START %d\n", $total;
- for $code (keys %second) {
- $vals{$code} = $second{$code} + $total;
- $last = $code if $code > $last;
- }
- $total += $n_second;
- $i = 0;
- printf OUT "#define COMPOSE_SECOND_SINGLE_START %d\n\n", $total;
- for $record (@second_singletons) {
- my $code = $record->[0];
- $vals{$code} = $i++ + $total;
- $last = $code if $code > $last;
- }
-
- printf OUT "#define COMPOSE_TABLE_LAST %d\n\n", $last / 256;
-
- # Output lookup table
-
- my @row;
- $table_index = 0;
- printf OUT "static const guint16 compose_data[][256] = {\n";
- for (my $count = 0; $count <= $last; $count += 256)
- {
- $row[$count / 256] = &print_row ($count, 2, sub { exists $vals{$_[0]} ? $vals{$_[0]} : 0; });
- }
- printf OUT "\n};\n\n";
-
- print OUT "static const gint16 compose_table[COMPOSE_TABLE_LAST + 1] = {\n";
- for (my $count = 0; $count <= $last; $count += 256)
- {
- print OUT ",\n" if $count > 0;
- print OUT " ", $row[$count / 256];
- $bytes_out += 2;
- }
- print OUT "\n};\n\n";
-
- # Output first singletons
-
- print OUT "static const guint16 compose_first_single[][2] = {\n";
- $i = 0;
- for $record (@first_singletons) {
- if ($record->[1] > 0xFFFF or $record->[2] > 0xFFFF) {
- die "time to switch compose_first_single to gunichar" ;
- }
- print OUT ",\n" if $i++ > 0;
- printf OUT " { %#06x, %#06x }", $record->[1], $record->[2];
- }
- print OUT "\n};\n";
-
- $bytes_out += @first_singletons * 4;
-
- # Output second singletons
-
- print OUT "static const guint16 compose_second_single[][2] = {\n";
- $i = 0;
- for $record (@second_singletons) {
- if ($record->[1] > 0xFFFF or $record->[2] > 0xFFFF) {
- die "time to switch compose_second_single to gunichar";
- }
- print OUT ",\n" if $i++ > 0;
- printf OUT " { %#06x, %#06x }", $record->[1], $record->[2];
- }
- print OUT "\n};\n";
-
- $bytes_out += @second_singletons * 4;
-
- # Output array of composition pairs
-
- print OUT <<EOT;
-static const guint16 compose_array[$n_first][$n_second] = {
-EOT
-
- for (my $i = 0; $i < $n_first; $i++) {
- print OUT ",\n" if $i;
- print OUT " { ";
- for (my $j = 0; $j < $n_second; $j++) {
- print OUT ", " if $j;
- if (exists $reverse{"$i|$j"}) {
- if ($reverse{"$i|$j"} > 0xFFFF) {
- die "time to switch compose_array to gunichar" ;
- }
- printf OUT "0x%04x", $reverse{"$i|$j"};
- } else {
- print OUT " 0";
- }
- }
- print OUT " }";
- }
- print OUT "\n";
-
- print OUT <<EOT;
-};
-EOT
-
- $bytes_out += $n_first * $n_second * 2;
-
- printf STDERR "Generated %d bytes in compose tables\n", $bytes_out;
-}
-
-sub output_casefold_table
-{
- my $out = shift;
-
- print $out <<EOT;
-
-/* Table of casefolding cases that can't be derived by lowercasing
- */
-static const struct {
- guint16 ch;
- gchar data[$casefoldlen];
-} casefold_table[] = {
-EOT
-
- @casefold = sort { $a->[0] <=> $b->[0] } @casefold;
-
- for $case (@casefold)
- {
- $code = $case->[0];
- $string = $case->[1];
-
- if ($code > 0xFFFF) {
- die "time to switch casefold_table to gunichar" ;
- }
-
- print $out sprintf(qq( { 0x%04x, "$string" },\n), $code);
-
- }
-
- print $out <<EOT;
-};
-
-EOT
-
- my $recordlen = (2+$casefoldlen+1) & ~1;
- printf "Generated %d bytes for casefold table\n", $recordlen * @casefold;
-}
-
-
-
diff --git a/glib/ghook.c b/glib/ghook.c
deleted file mode 100644
index d038ee2c2..000000000
--- a/glib/ghook.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * GHook: Callback maintenance functions
- * Copyright (C) 1998 Tim Janik
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#include "glib.h"
-#include "galias.h"
-
-
-/* --- functions --- */
-static void
-default_finalize_hook (GHookList *hook_list,
- GHook *hook)
-{
- GDestroyNotify destroy = hook->destroy;
-
- if (destroy)
- {
- hook->destroy = NULL;
- destroy (hook->data);
- }
-}
-
-void
-g_hook_list_init (GHookList *hook_list,
- guint hook_size)
-{
- g_return_if_fail (hook_list != NULL);
- g_return_if_fail (hook_size >= sizeof (GHook));
-
- hook_list->seq_id = 1;
- hook_list->hook_size = hook_size;
- hook_list->is_setup = TRUE;
- hook_list->hooks = NULL;
- hook_list->dummy3 = NULL;
- hook_list->finalize_hook = default_finalize_hook;
- hook_list->dummy[0] = NULL;
- hook_list->dummy[1] = NULL;
-}
-
-void
-g_hook_list_clear (GHookList *hook_list)
-{
- g_return_if_fail (hook_list != NULL);
-
- if (hook_list->is_setup)
- {
- GHook *hook;
-
- hook_list->is_setup = FALSE;
-
- hook = hook_list->hooks;
- if (!hook)
- {
- /* destroy hook_list->hook_memchunk */
- }
- else
- do
- {
- GHook *tmp;
-
- g_hook_ref (hook_list, hook);
- g_hook_destroy_link (hook_list, hook);
- tmp = hook->next;
- g_hook_unref (hook_list, hook);
- hook = tmp;
- }
- while (hook);
- }
-}
-
-GHook*
-g_hook_alloc (GHookList *hook_list)
-{
- GHook *hook;
-
- g_return_val_if_fail (hook_list != NULL, NULL);
- g_return_val_if_fail (hook_list->is_setup, NULL);
-
- hook = g_slice_alloc0 (hook_list->hook_size);
- hook->data = NULL;
- hook->next = NULL;
- hook->prev = NULL;
- hook->flags = G_HOOK_FLAG_ACTIVE;
- hook->ref_count = 0;
- hook->hook_id = 0;
- hook->func = NULL;
- hook->destroy = NULL;
-
- return hook;
-}
-
-void
-g_hook_free (GHookList *hook_list,
- GHook *hook)
-{
- g_return_if_fail (hook_list != NULL);
- g_return_if_fail (hook_list->is_setup);
- g_return_if_fail (hook != NULL);
- g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
- g_return_if_fail (!G_HOOK_IN_CALL (hook));
-
- if(hook_list->finalize_hook != NULL)
- hook_list->finalize_hook (hook_list, hook);
- g_slice_free1 (hook_list->hook_size, hook);
-}
-
-void
-g_hook_destroy_link (GHookList *hook_list,
- GHook *hook)
-{
- g_return_if_fail (hook_list != NULL);
- g_return_if_fail (hook != NULL);
-
- hook->flags &= ~G_HOOK_FLAG_ACTIVE;
- if (hook->hook_id)
- {
- hook->hook_id = 0;
- g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
- }
-}
-
-gboolean
-g_hook_destroy (GHookList *hook_list,
- gulong hook_id)
-{
- GHook *hook;
-
- g_return_val_if_fail (hook_list != NULL, FALSE);
- g_return_val_if_fail (hook_id > 0, FALSE);
-
- hook = g_hook_get (hook_list, hook_id);
- if (hook)
- {
- g_hook_destroy_link (hook_list, hook);
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-g_hook_unref (GHookList *hook_list,
- GHook *hook)
-{
- g_return_if_fail (hook_list != NULL);
- g_return_if_fail (hook != NULL);
- g_return_if_fail (hook->ref_count > 0);
-
- hook->ref_count--;
- if (!hook->ref_count)
- {
- g_return_if_fail (hook->hook_id == 0);
- g_return_if_fail (!G_HOOK_IN_CALL (hook));
-
- if (hook->prev)
- hook->prev->next = hook->next;
- else
- hook_list->hooks = hook->next;
- if (hook->next)
- {
- hook->next->prev = hook->prev;
- hook->next = NULL;
- }
- hook->prev = NULL;
-
- if (!hook_list->is_setup)
- {
- hook_list->is_setup = TRUE;
- g_hook_free (hook_list, hook);
- hook_list->is_setup = FALSE;
-
- if (!hook_list->hooks)
- {
- /* destroy hook_list->hook_memchunk */
- }
- }
- else
- g_hook_free (hook_list, hook);
- }
-}
-
-GHook *
-g_hook_ref (GHookList *hook_list,
- GHook *hook)
-{
- g_return_val_if_fail (hook_list != NULL, NULL);
- g_return_val_if_fail (hook != NULL, NULL);
- g_return_val_if_fail (hook->ref_count > 0, NULL);
-
- hook->ref_count++;
-
- return hook;
-}
-
-void
-g_hook_prepend (GHookList *hook_list,
- GHook *hook)
-{
- g_return_if_fail (hook_list != NULL);
-
- g_hook_insert_before (hook_list, hook_list->hooks, hook);
-}
-
-void
-g_hook_insert_before (GHookList *hook_list,
- GHook *sibling,
- GHook *hook)
-{
- g_return_if_fail (hook_list != NULL);
- g_return_if_fail (hook_list->is_setup);
- g_return_if_fail (hook != NULL);
- g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
- g_return_if_fail (hook->ref_count == 0);
-
- hook->hook_id = hook_list->seq_id++;
- hook->ref_count = 1; /* counterpart to g_hook_destroy_link */
-
- if (sibling)
- {
- if (sibling->prev)
- {
- hook->prev = sibling->prev;
- hook->prev->next = hook;
- hook->next = sibling;
- sibling->prev = hook;
- }
- else
- {
- hook_list->hooks = hook;
- hook->next = sibling;
- sibling->prev = hook;
- }
- }
- else
- {
- if (hook_list->hooks)
- {
- sibling = hook_list->hooks;
- while (sibling->next)
- sibling = sibling->next;
- hook->prev = sibling;
- sibling->next = hook;
- }
- else
- hook_list->hooks = hook;
- }
-}
-
-void
-g_hook_list_invoke (GHookList *hook_list,
- gboolean may_recurse)
-{
- GHook *hook;
-
- g_return_if_fail (hook_list != NULL);
- g_return_if_fail (hook_list->is_setup);
-
- hook = g_hook_first_valid (hook_list, may_recurse);
- while (hook)
- {
- GHookFunc func;
- gboolean was_in_call;
-
- func = (GHookFunc) hook->func;
-
- was_in_call = G_HOOK_IN_CALL (hook);
- hook->flags |= G_HOOK_FLAG_IN_CALL;
- func (hook->data);
- if (!was_in_call)
- hook->flags &= ~G_HOOK_FLAG_IN_CALL;
-
- hook = g_hook_next_valid (hook_list, hook, may_recurse);
- }
-}
-
-void
-g_hook_list_invoke_check (GHookList *hook_list,
- gboolean may_recurse)
-{
- GHook *hook;
-
- g_return_if_fail (hook_list != NULL);
- g_return_if_fail (hook_list->is_setup);
-
- hook = g_hook_first_valid (hook_list, may_recurse);
- while (hook)
- {
- GHookCheckFunc func;
- gboolean was_in_call;
- gboolean need_destroy;
-
- func = (GHookCheckFunc) hook->func;
-
- was_in_call = G_HOOK_IN_CALL (hook);
- hook->flags |= G_HOOK_FLAG_IN_CALL;
- need_destroy = !func (hook->data);
- if (!was_in_call)
- hook->flags &= ~G_HOOK_FLAG_IN_CALL;
- if (need_destroy)
- g_hook_destroy_link (hook_list, hook);
-
- hook = g_hook_next_valid (hook_list, hook, may_recurse);
- }
-}
-
-void
-g_hook_list_marshal_check (GHookList *hook_list,
- gboolean may_recurse,
- GHookCheckMarshaller marshaller,
- gpointer data)
-{
- GHook *hook;
-
- g_return_if_fail (hook_list != NULL);
- g_return_if_fail (hook_list->is_setup);
- g_return_if_fail (marshaller != NULL);
-
- hook = g_hook_first_valid (hook_list, may_recurse);
- while (hook)
- {
- gboolean was_in_call;
- gboolean need_destroy;
-
- was_in_call = G_HOOK_IN_CALL (hook);
- hook->flags |= G_HOOK_FLAG_IN_CALL;
- need_destroy = !marshaller (hook, data);
- if (!was_in_call)
- hook->flags &= ~G_HOOK_FLAG_IN_CALL;
- if (need_destroy)
- g_hook_destroy_link (hook_list, hook);
-
- hook = g_hook_next_valid (hook_list, hook, may_recurse);
- }
-}
-
-void
-g_hook_list_marshal (GHookList *hook_list,
- gboolean may_recurse,
- GHookMarshaller marshaller,
- gpointer data)
-{
- GHook *hook;
-
- g_return_if_fail (hook_list != NULL);
- g_return_if_fail (hook_list->is_setup);
- g_return_if_fail (marshaller != NULL);
-
- hook = g_hook_first_valid (hook_list, may_recurse);
- while (hook)
- {
- gboolean was_in_call;
-
- was_in_call = G_HOOK_IN_CALL (hook);
- hook->flags |= G_HOOK_FLAG_IN_CALL;
- marshaller (hook, data);
- if (!was_in_call)
- hook->flags &= ~G_HOOK_FLAG_IN_CALL;
-
- hook = g_hook_next_valid (hook_list, hook, may_recurse);
- }
-}
-
-GHook*
-g_hook_first_valid (GHookList *hook_list,
- gboolean may_be_in_call)
-{
- g_return_val_if_fail (hook_list != NULL, NULL);
-
- if (hook_list->is_setup)
- {
- GHook *hook;
-
- hook = hook_list->hooks;
- if (hook)
- {
- g_hook_ref (hook_list, hook);
- if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
- return hook;
- else
- return g_hook_next_valid (hook_list, hook, may_be_in_call);
- }
- }
-
- return NULL;
-}
-
-GHook*
-g_hook_next_valid (GHookList *hook_list,
- GHook *hook,
- gboolean may_be_in_call)
-{
- GHook *ohook = hook;
-
- g_return_val_if_fail (hook_list != NULL, NULL);
-
- if (!hook)
- return NULL;
-
- hook = hook->next;
- while (hook)
- {
- if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
- {
- g_hook_ref (hook_list, hook);
- g_hook_unref (hook_list, ohook);
-
- return hook;
- }
- hook = hook->next;
- }
- g_hook_unref (hook_list, ohook);
-
- return NULL;
-}
-
-GHook*
-g_hook_get (GHookList *hook_list,
- gulong hook_id)
-{
- GHook *hook;
-
- g_return_val_if_fail (hook_list != NULL, NULL);
- g_return_val_if_fail (hook_id > 0, NULL);
-
- hook = hook_list->hooks;
- while (hook)
- {
- if (hook->hook_id == hook_id)
- return hook;
- hook = hook->next;
- }
-
- return NULL;
-}
-
-GHook*
-g_hook_find (GHookList *hook_list,
- gboolean need_valids,
- GHookFindFunc func,
- gpointer data)
-{
- GHook *hook;
-
- g_return_val_if_fail (hook_list != NULL, NULL);
- g_return_val_if_fail (func != NULL, NULL);
-
- hook = hook_list->hooks;
- while (hook)
- {
- GHook *tmp;
-
- /* test only non-destroyed hooks */
- if (!hook->hook_id)
- {
- hook = hook->next;
- continue;
- }
-
- g_hook_ref (hook_list, hook);
-
- if (func (hook, data) && hook->hook_id && (!need_valids || G_HOOK_ACTIVE (hook)))
- {
- g_hook_unref (hook_list, hook);
-
- return hook;
- }
-
- tmp = hook->next;
- g_hook_unref (hook_list, hook);
- hook = tmp;
- }
-
- return NULL;
-}
-
-GHook*
-g_hook_find_data (GHookList *hook_list,
- gboolean need_valids,
- gpointer data)
-{
- GHook *hook;
-
- g_return_val_if_fail (hook_list != NULL, NULL);
-
- hook = hook_list->hooks;
- while (hook)
- {
- /* test only non-destroyed hooks */
- if (hook->data == data &&
- hook->hook_id &&
- (!need_valids || G_HOOK_ACTIVE (hook)))
- return hook;
-
- hook = hook->next;
- }
-
- return NULL;
-}
-
-GHook*
-g_hook_find_func (GHookList *hook_list,
- gboolean need_valids,
- gpointer func)
-{
- GHook *hook;
-
- g_return_val_if_fail (hook_list != NULL, NULL);
- g_return_val_if_fail (func != NULL, NULL);
-
- hook = hook_list->hooks;
- while (hook)
- {
- /* test only non-destroyed hooks */
- if (hook->func == func &&
- hook->hook_id &&
- (!need_valids || G_HOOK_ACTIVE (hook)))
- return hook;
-
- hook = hook->next;
- }
-
- return NULL;
-}
-
-GHook*
-g_hook_find_func_data (GHookList *hook_list,
- gboolean need_valids,
- gpointer func,
- gpointer data)
-{
- GHook *hook;
-
- g_return_val_if_fail (hook_list != NULL, NULL);
- g_return_val_if_fail (func != NULL, NULL);
-
- hook = hook_list->hooks;
- while (hook)
- {
- /* test only non-destroyed hooks */
- if (hook->data == data &&
- hook->func == func &&
- hook->hook_id &&
- (!need_valids || G_HOOK_ACTIVE (hook)))
- return hook;
-
- hook = hook->next;
- }
-
- return NULL;
-}
-
-void
-g_hook_insert_sorted (GHookList *hook_list,
- GHook *hook,
- GHookCompareFunc func)
-{
- GHook *sibling;
-
- g_return_if_fail (hook_list != NULL);
- g_return_if_fail (hook_list->is_setup);
- g_return_if_fail (hook != NULL);
- g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
- g_return_if_fail (hook->func != NULL);
- g_return_if_fail (func != NULL);
-
- /* first non-destroyed hook */
- sibling = hook_list->hooks;
- while (sibling && !sibling->hook_id)
- sibling = sibling->next;
-
- while (sibling)
- {
- GHook *tmp;
-
- g_hook_ref (hook_list, sibling);
- if (func (hook, sibling) <= 0 && sibling->hook_id)
- {
- g_hook_unref (hook_list, sibling);
- break;
- }
-
- /* next non-destroyed hook */
- tmp = sibling->next;
- while (tmp && !tmp->hook_id)
- tmp = tmp->next;
-
- g_hook_unref (hook_list, sibling);
- sibling = tmp;
- }
-
- g_hook_insert_before (hook_list, sibling, hook);
-}
-
-gint
-g_hook_compare_ids (GHook *new_hook,
- GHook *sibling)
-{
- if (new_hook->hook_id < sibling->hook_id)
- return -1;
- else if (new_hook->hook_id > sibling->hook_id)
- return 1;
-
- return 0;
-}
-
-#define __G_HOOK_C__
-#include "galiasdef.c"
diff --git a/glib/giowin32.c b/glib/giowin32.c
deleted file mode 100644
index 7f395473d..000000000
--- a/glib/giowin32.c
+++ /dev/null
@@ -1,2191 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * giowin32.c: IO Channels for Win32.
- * Copyright 1998 Owen Taylor and Tor Lillqvist
- * Copyright 1999-2000 Tor Lillqvist and Craig Setera
- * Copyright 2001-2003 Andrew Lanoix
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * Bugs that are related to the code in this file:
- *
- * Bug 137968 - Sometimes a GIOFunc on Win32 is called with zero condition
- * http://bugzilla.gnome.org/show_bug.cgi?id=137968
- *
- * Bug 324234 - Using g_io_add_watch_full() to wait for connect() to return on a non-blocking socket returns prematurely
- * http://bugzilla.gnome.org/show_bug.cgi?id=324234
- *
- * Bug 331214 - g_io_channel async socket io stalls
- * http://bugzilla.gnome.org/show_bug.cgi?id=331214
- *
- * Bug 338943 - Multiple watches on the same socket
- * http://bugzilla.gnome.org/show_bug.cgi?id=338943
- *
- * Bug 357674 - 2 serious bugs in giowin32.c making glib iochannels useless
- * http://bugzilla.gnome.org/show_bug.cgi?id=357674
- *
- * Bug 425156 - GIOChannel deadlocks on a win32 socket
- * http://bugzilla.gnome.org/show_bug.cgi?id=425156
- *
- * Bug 468910 - giofunc condition=0
- * http://bugzilla.gnome.org/show_bug.cgi?id=468910
- *
- * Bug 500246 - Bug fixes for giowin32
- * http://bugzilla.gnome.org/show_bug.cgi?id=500246
- *
- * Bug 548278 - Async GETs connections are always terminated unexpectedly on windows
- * http://bugzilla.gnome.org/show_bug.cgi?id=548278
- *
- * Bug 548536 - giowin32 problem when adding and removing watches
- * http://bugzilla.gnome.org/show_bug.cgi?id=548536
- *
- * When fixing bugs related to the code in this file, either the above
- * bugs or others, make sure that the test programs attached to the
- * above bugs continue to work.
- */
-
-#include "config.h"
-
-#include "glib.h"
-
-#include <stdlib.h>
-#include <winsock2.h>
-#include <windows.h>
-#include <conio.h>
-#include <fcntl.h>
-#include <io.h>
-#include <process.h>
-#include <errno.h>
-#include <sys/stat.h>
-
-#include "gstdio.h"
-#include "glibintl.h"
-
-#include "galias.h"
-
-typedef struct _GIOWin32Channel GIOWin32Channel;
-typedef struct _GIOWin32Watch GIOWin32Watch;
-
-#define BUFFER_SIZE 4096
-
-typedef enum {
- G_IO_WIN32_WINDOWS_MESSAGES, /* Windows messages */
-
- G_IO_WIN32_FILE_DESC, /* Unix-like file descriptors from
- * _open() or _pipe(), except for
- * console IO. Separate thread to read
- * or write.
- */
-
- G_IO_WIN32_CONSOLE, /* Console IO (usually stdin, stdout, stderr) */
-
- G_IO_WIN32_SOCKET /* Sockets. No separate thread. */
-} GIOWin32ChannelType;
-
-struct _GIOWin32Channel {
- GIOChannel channel;
- gint fd; /* Either a Unix-like file handle as provided
- * by the Microsoft C runtime, or a SOCKET
- * as provided by WinSock.
- */
- GIOWin32ChannelType type;
-
- gboolean debug;
-
- /* Field used by G_IO_WIN32_WINDOWS_MESSAGES channels */
- HWND hwnd; /* Handle of window, or NULL */
-
- /* Fields used by G_IO_WIN32_FILE_DESC channels. */
- CRITICAL_SECTION mutex;
-
- int direction; /* 0 means we read from it,
- * 1 means we write to it.
- */
-
- gboolean running; /* Is reader or writer thread
- * running. FALSE if EOF has been
- * reached by the reader thread.
- */
-
- gboolean needs_close; /* If the channel has been closed while
- * the reader thread was still running.
- */
-
- guint thread_id; /* If non-NULL the channel has or has
- * had a reader or writer thread.
- */
- HANDLE data_avail_event;
-
- gushort revents;
-
- /* Data is kept in a circular buffer. To be able to distinguish between
- * empty and full buffers, we cannot fill it completely, but have to
- * leave a one character gap.
- *
- * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
- *
- * Empty: wrp == rdp
- * Full: (wrp + 1) % BUFFER_SIZE == rdp
- * Partial: otherwise
- */
- guchar *buffer; /* (Circular) buffer */
- gint wrp, rdp; /* Buffer indices for writing and reading */
- HANDLE space_avail_event;
-
- /* Fields used by G_IO_WIN32_SOCKET channels */
- int event_mask;
- int last_events;
- HANDLE event;
- gboolean write_would_have_blocked;
- gboolean ever_writable;
-};
-
-struct _GIOWin32Watch {
- GSource source;
- GPollFD pollfd;
- GIOChannel *channel;
- GIOCondition condition;
-};
-
-static void
-g_win32_print_access_mode (int flags)
-{
- g_print ("%s%s%s%s%s%s%s%s%s%s",
- ((flags & 0x3) == _O_RDWR ? "O_RDWR" :
- ((flags & 0x3) == _O_RDONLY ? "O_RDONLY" :
- ((flags & 0x3) == _O_WRONLY ? "O_WRONLY" : "0"))),
- (flags & _O_APPEND ? "|O_APPEND" : ""),
- (flags & _O_RANDOM ? "|O_RANDOM" : ""),
- (flags & _O_SEQUENTIAL ? "|O_SEQUENTIAL" : ""),
- (flags & _O_TEMPORARY ? "|O_TEMPORARY" : ""),
- (flags & _O_CREAT ? "|O_CREAT" : ""),
- (flags & _O_TRUNC ? "|O_TRUNC" : ""),
- (flags & _O_EXCL ? "|O_EXCL" : ""),
- (flags & _O_TEXT ? "|O_TEXT" : ""),
- (flags & _O_BINARY ? "|O_BINARY" : ""));
-}
-
-static void
-g_win32_print_gioflags (GIOFlags flags)
-{
- char *bar = "";
-
- if (flags & G_IO_FLAG_APPEND)
- bar = "|", g_print ("APPEND");
- if (flags & G_IO_FLAG_NONBLOCK)
- g_print ("%sNONBLOCK", bar), bar = "|";
- if (flags & G_IO_FLAG_IS_READABLE)
- g_print ("%sREADABLE", bar), bar = "|";
- if (flags & G_IO_FLAG_IS_WRITEABLE)
- g_print ("%sWRITEABLE", bar), bar = "|";
- if (flags & G_IO_FLAG_IS_SEEKABLE)
- g_print ("%sSEEKABLE", bar), bar = "|";
-}
-
-static const char *
-event_mask_to_string (int mask)
-{
- char buf[100];
- int checked_bits = 0;
- char *bufp = buf;
-
- if (mask == 0)
- return "";
-
-#define BIT(n) checked_bits |= FD_##n; if (mask & FD_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
-
- BIT (READ);
- BIT (WRITE);
- BIT (OOB);
- BIT (ACCEPT);
- BIT (CONNECT);
- BIT (CLOSE);
- BIT (QOS);
- BIT (GROUP_QOS);
- BIT (ROUTING_INTERFACE_CHANGE);
- BIT (ADDRESS_LIST_CHANGE);
-
-#undef BIT
-
- if ((mask & ~checked_bits) != 0)
- bufp += sprintf (bufp, "|%#x", mask & ~checked_bits);
-
- return g_quark_to_string (g_quark_from_string (buf));
-}
-
-static const char *
-condition_to_string (GIOCondition condition)
-{
- char buf[100];
- int checked_bits = 0;
- char *bufp = buf;
-
- if (condition == 0)
- return "";
-
-#define BIT(n) checked_bits |= G_IO_##n; if (condition & G_IO_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
-
- BIT (IN);
- BIT (OUT);
- BIT (PRI);
- BIT (ERR);
- BIT (HUP);
- BIT (NVAL);
-
-#undef BIT
-
- if ((condition & ~checked_bits) != 0)
- bufp += sprintf (bufp, "|%#x", condition & ~checked_bits);
-
- return g_quark_to_string (g_quark_from_string (buf));
-}
-
-static gboolean
-g_io_win32_get_debug_flag (void)
-{
- return (getenv ("G_IO_WIN32_DEBUG") != NULL);
-}
-
-static void
-g_io_channel_win32_init (GIOWin32Channel *channel)
-{
- channel->debug = g_io_win32_get_debug_flag ();
-
- InitializeCriticalSection (&channel->mutex);
- channel->running = FALSE;
- channel->needs_close = FALSE;
- channel->thread_id = 0;
- channel->data_avail_event = NULL;
- channel->revents = 0;
- channel->buffer = NULL;
- channel->space_avail_event = NULL;
-
- channel->event_mask = 0;
- channel->last_events = 0;
- channel->event = NULL;
- channel->write_would_have_blocked = FALSE;
- channel->ever_writable = FALSE;
-}
-
-static void
-create_events (GIOWin32Channel *channel)
-{
- SECURITY_ATTRIBUTES sec_attrs;
-
- sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
- sec_attrs.lpSecurityDescriptor = NULL;
- sec_attrs.bInheritHandle = FALSE;
-
- /* The data available event is manual reset, the space available event
- * is automatic reset.
- */
- if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
- || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
- {
- gchar *emsg = g_win32_error_message (GetLastError ());
-
- g_error ("Error creating event: %s", emsg);
- g_free (emsg);
- }
-}
-
-static unsigned __stdcall
-read_thread (void *parameter)
-{
- GIOWin32Channel *channel = parameter;
- guchar *buffer;
- gint nbytes;
-
- g_io_channel_ref ((GIOChannel *)channel);
-
- if (channel->debug)
- g_print ("read_thread %#x: start fd=%d, data_avail=%p space_avail=%p\n",
- channel->thread_id,
- channel->fd,
- channel->data_avail_event,
- channel->space_avail_event);
-
- channel->direction = 0;
- channel->buffer = g_malloc (BUFFER_SIZE);
- channel->rdp = channel->wrp = 0;
- channel->running = TRUE;
-
- SetEvent (channel->space_avail_event);
-
- EnterCriticalSection (&channel->mutex);
- while (channel->running)
- {
- if (channel->debug)
- g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
- channel->thread_id, channel->rdp, channel->wrp);
- if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
- {
- /* Buffer is full */
- if (channel->debug)
- g_print ("read_thread %#x: resetting space_avail\n",
- channel->thread_id);
- ResetEvent (channel->space_avail_event);
- if (channel->debug)
- g_print ("read_thread %#x: waiting for space\n",
- channel->thread_id);
- LeaveCriticalSection (&channel->mutex);
- WaitForSingleObject (channel->space_avail_event, INFINITE);
- EnterCriticalSection (&channel->mutex);
- if (channel->debug)
- g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
- channel->thread_id, channel->rdp, channel->wrp);
- }
-
- buffer = channel->buffer + channel->wrp;
-
- /* Always leave at least one byte unused gap to be able to
- * distinguish between the full and empty condition...
- */
- nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
- BUFFER_SIZE - channel->wrp);
-
- if (channel->debug)
- g_print ("read_thread %#x: calling read() for %d bytes\n",
- channel->thread_id, nbytes);
-
- LeaveCriticalSection (&channel->mutex);
-
- nbytes = read (channel->fd, buffer, nbytes);
-
- EnterCriticalSection (&channel->mutex);
-
- channel->revents = G_IO_IN;
- if (nbytes == 0)
- channel->revents |= G_IO_HUP;
- else if (nbytes < 0)
- channel->revents |= G_IO_ERR;
-
- if (channel->debug)
- g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
- channel->thread_id, nbytes, channel->rdp, channel->wrp);
-
- if (nbytes <= 0)
- break;
-
- channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
- if (channel->debug)
- g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
- channel->thread_id, channel->rdp, channel->wrp);
- SetEvent (channel->data_avail_event);
- }
-
- channel->running = FALSE;
- if (channel->needs_close)
- {
- if (channel->debug)
- g_print ("read_thread %#x: channel fd %d needs closing\n",
- channel->thread_id, channel->fd);
- close (channel->fd);
- channel->fd = -1;
- }
-
- if (channel->debug)
- g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
- channel->thread_id, channel->rdp, channel->wrp);
- SetEvent (channel->data_avail_event);
- LeaveCriticalSection (&channel->mutex);
-
- g_io_channel_unref ((GIOChannel *)channel);
-
- /* No need to call _endthreadex(), the actual thread starter routine
- * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
- * _endthreadex() for us.
- */
-
- return 0;
-}
-
-static unsigned __stdcall
-write_thread (void *parameter)
-{
- GIOWin32Channel *channel = parameter;
- guchar *buffer;
- gint nbytes;
-
- g_io_channel_ref ((GIOChannel *)channel);
-
- if (channel->debug)
- g_print ("write_thread %#x: start fd=%d, data_avail=%p space_avail=%p\n",
- channel->thread_id,
- channel->fd,
- channel->data_avail_event,
- channel->space_avail_event);
-
- channel->direction = 1;
- channel->buffer = g_malloc (BUFFER_SIZE);
- channel->rdp = channel->wrp = 0;
- channel->running = TRUE;
-
- SetEvent (channel->space_avail_event);
-
- /* We use the same event objects as for a reader thread, but with
- * reversed meaning. So, space_avail is used if data is available
- * for writing, and data_avail is used if space is available in the
- * write buffer.
- */
-
- EnterCriticalSection (&channel->mutex);
- while (channel->running || channel->rdp != channel->wrp)
- {
- if (channel->debug)
- g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
- channel->thread_id, channel->rdp, channel->wrp);
- if (channel->wrp == channel->rdp)
- {
- /* Buffer is empty. */
- if (channel->debug)
- g_print ("write_thread %#x: resetting space_avail\n",
- channel->thread_id);
- ResetEvent (channel->space_avail_event);
- if (channel->debug)
- g_print ("write_thread %#x: waiting for data\n",
- channel->thread_id);
- channel->revents = G_IO_OUT;
- SetEvent (channel->data_avail_event);
- LeaveCriticalSection (&channel->mutex);
- WaitForSingleObject (channel->space_avail_event, INFINITE);
-
- EnterCriticalSection (&channel->mutex);
- if (channel->rdp == channel->wrp)
- break;
-
- if (channel->debug)
- g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
- channel->thread_id, channel->rdp, channel->wrp);
- }
-
- buffer = channel->buffer + channel->rdp;
- if (channel->rdp < channel->wrp)
- nbytes = channel->wrp - channel->rdp;
- else
- nbytes = BUFFER_SIZE - channel->rdp;
-
- if (channel->debug)
- g_print ("write_thread %#x: calling write() for %d bytes\n",
- channel->thread_id, nbytes);
-
- LeaveCriticalSection (&channel->mutex);
- nbytes = write (channel->fd, buffer, nbytes);
- EnterCriticalSection (&channel->mutex);
-
- if (channel->debug)
- g_print ("write_thread %#x: write(%i) returned %d, rdp=%d, wrp=%d\n",
- channel->thread_id, channel->fd, nbytes, channel->rdp, channel->wrp);
-
- channel->revents = 0;
- if (nbytes > 0)
- channel->revents |= G_IO_OUT;
- else if (nbytes <= 0)
- channel->revents |= G_IO_ERR;
-
- channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
-
- if (nbytes <= 0)
- break;
-
- if (channel->debug)
- g_print ("write_thread: setting data_avail for thread %#x\n",
- channel->thread_id);
- SetEvent (channel->data_avail_event);
- }
-
- channel->running = FALSE;
- if (channel->needs_close)
- {
- if (channel->debug)
- g_print ("write_thread %#x: channel fd %d needs closing\n",
- channel->thread_id, channel->fd);
- close (channel->fd);
- channel->fd = -1;
- }
-
- LeaveCriticalSection (&channel->mutex);
-
- g_io_channel_unref ((GIOChannel *)channel);
-
- return 0;
-}
-
-static void
-create_thread (GIOWin32Channel *channel,
- GIOCondition condition,
- unsigned (__stdcall *thread) (void *parameter))
-{
- HANDLE thread_handle;
-
- thread_handle = (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
- &channel->thread_id);
- if (thread_handle == 0)
- g_warning ("Error creating thread: %s.",
- g_strerror (errno));
- else if (!CloseHandle (thread_handle))
- {
- gchar *emsg = g_win32_error_message (GetLastError ());
-
- g_warning ("Error closing thread handle: %s.", emsg);
- g_free (emsg);
- }
-
- WaitForSingleObject (channel->space_avail_event, INFINITE);
-}
-
-static GIOStatus
-buffer_read (GIOWin32Channel *channel,
- gchar *dest,
- gsize count,
- gsize *bytes_read,
- GError **err)
-{
- guint nbytes;
- guint left = count;
-
- EnterCriticalSection (&channel->mutex);
- if (channel->debug)
- g_print ("reading from thread %#x %" G_GSIZE_FORMAT " bytes, rdp=%d, wrp=%d\n",
- channel->thread_id, count, channel->rdp, channel->wrp);
-
- if (channel->wrp == channel->rdp)
- {
- LeaveCriticalSection (&channel->mutex);
- if (channel->debug)
- g_print ("waiting for data from thread %#x\n", channel->thread_id);
- WaitForSingleObject (channel->data_avail_event, INFINITE);
- if (channel->debug)
- g_print ("done waiting for data from thread %#x\n", channel->thread_id);
- EnterCriticalSection (&channel->mutex);
- if (channel->wrp == channel->rdp && !channel->running)
- {
- if (channel->debug)
- g_print ("wrp==rdp, !running\n");
- LeaveCriticalSection (&channel->mutex);
- *bytes_read = 0;
- return G_IO_STATUS_EOF;
- }
- }
-
- if (channel->rdp < channel->wrp)
- nbytes = channel->wrp - channel->rdp;
- else
- nbytes = BUFFER_SIZE - channel->rdp;
- LeaveCriticalSection (&channel->mutex);
- nbytes = MIN (left, nbytes);
- if (channel->debug)
- g_print ("moving %d bytes from thread %#x\n",
- nbytes, channel->thread_id);
- memcpy (dest, channel->buffer + channel->rdp, nbytes);
- dest += nbytes;
- left -= nbytes;
- EnterCriticalSection (&channel->mutex);
- channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
- if (channel->debug)
- g_print ("setting space_avail for thread %#x\n", channel->thread_id);
- SetEvent (channel->space_avail_event);
- if (channel->debug)
- g_print ("for thread %#x: rdp=%d, wrp=%d\n",
- channel->thread_id, channel->rdp, channel->wrp);
- if (channel->running && channel->wrp == channel->rdp)
- {
- if (channel->debug)
- g_print ("resetting data_avail of thread %#x\n",
- channel->thread_id);
- ResetEvent (channel->data_avail_event);
- };
- LeaveCriticalSection (&channel->mutex);
-
- /* We have no way to indicate any errors form the actual
- * read() or recv() call in the reader thread. Should we have?
- */
- *bytes_read = count - left;
- return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
-}
-
-
-static GIOStatus
-buffer_write (GIOWin32Channel *channel,
- const gchar *dest,
- gsize count,
- gsize *bytes_written,
- GError **err)
-{
- guint nbytes;
- guint left = count;
-
- EnterCriticalSection (&channel->mutex);
- if (channel->debug)
- g_print ("buffer_write: writing to thread %#x %" G_GSIZE_FORMAT " bytes, rdp=%d, wrp=%d\n",
- channel->thread_id, count, channel->rdp, channel->wrp);
-
- if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
- {
- /* Buffer is full */
- if (channel->debug)
- g_print ("buffer_write: tid %#x: resetting data_avail\n",
- channel->thread_id);
- ResetEvent (channel->data_avail_event);
- if (channel->debug)
- g_print ("buffer_write: tid %#x: waiting for space\n",
- channel->thread_id);
- LeaveCriticalSection (&channel->mutex);
- WaitForSingleObject (channel->data_avail_event, INFINITE);
- EnterCriticalSection (&channel->mutex);
- if (channel->debug)
- g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d\n",
- channel->thread_id, channel->rdp, channel->wrp);
- }
-
- nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
- BUFFER_SIZE - channel->wrp);
-
- LeaveCriticalSection (&channel->mutex);
- nbytes = MIN (left, nbytes);
- if (channel->debug)
- g_print ("buffer_write: tid %#x: writing %d bytes\n",
- channel->thread_id, nbytes);
- memcpy (channel->buffer + channel->wrp, dest, nbytes);
- dest += nbytes;
- left -= nbytes;
- EnterCriticalSection (&channel->mutex);
-
- channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
- if (channel->debug)
- g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d, setting space_avail\n",
- channel->thread_id, channel->rdp, channel->wrp);
- SetEvent (channel->space_avail_event);
-
- if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
- {
- /* Buffer is full */
- if (channel->debug)
- g_print ("buffer_write: tid %#x: resetting data_avail\n",
- channel->thread_id);
- ResetEvent (channel->data_avail_event);
- }
-
- LeaveCriticalSection (&channel->mutex);
-
- /* We have no way to indicate any errors form the actual
- * write() call in the writer thread. Should we have?
- */
- *bytes_written = count - left;
- return (*bytes_written > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
-}
-
-
-static gboolean
-g_io_win32_prepare (GSource *source,
- gint *timeout)
-{
- GIOWin32Watch *watch = (GIOWin32Watch *)source;
- GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
- GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
- int event_mask;
-
- *timeout = -1;
-
- if (channel->debug)
- g_print ("g_io_win32_prepare: source=%p channel=%p", source, channel);
-
- switch (channel->type)
- {
- case G_IO_WIN32_WINDOWS_MESSAGES:
- if (channel->debug)
- g_print (" MSG");
- break;
-
- case G_IO_WIN32_CONSOLE:
- if (channel->debug)
- g_print (" CON");
- break;
-
- case G_IO_WIN32_FILE_DESC:
- if (channel->debug)
- g_print (" FD thread=%#x buffer_condition:{%s}"
- "\n watch->pollfd.events:{%s} watch->pollfd.revents:{%s} channel->revents:{%s}",
- channel->thread_id, condition_to_string (buffer_condition),
- condition_to_string (watch->pollfd.events),
- condition_to_string (watch->pollfd.revents),
- condition_to_string (channel->revents));
-
- EnterCriticalSection (&channel->mutex);
- if (channel->running)
- {
- if (channel->direction == 0 && channel->wrp == channel->rdp)
- {
- if (channel->debug)
- g_print ("\n setting revents=0");
- channel->revents = 0;
- }
- }
- else
- {
- if (channel->direction == 1
- && (channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
- {
- if (channel->debug)
- g_print ("\n setting revents=0");
- channel->revents = 0;
- }
- }
- LeaveCriticalSection (&channel->mutex);
- break;
-
- case G_IO_WIN32_SOCKET:
- if (channel->debug)
- g_print (" SOCK");
- event_mask = 0;
- if (watch->condition & G_IO_IN)
- event_mask |= (FD_READ | FD_ACCEPT);
- if (watch->condition & G_IO_OUT)
- event_mask |= (FD_WRITE | FD_CONNECT);
- event_mask |= FD_CLOSE;
-
- if (channel->event_mask != event_mask)
- {
- if (channel->debug)
- g_print ("\n WSAEventSelect(%d,%p,{%s})",
- channel->fd, (HANDLE) watch->pollfd.fd,
- event_mask_to_string (event_mask));
- if (WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd,
- event_mask) == SOCKET_ERROR)
- if (channel->debug)
- {
- gchar *emsg = g_win32_error_message (WSAGetLastError ());
-
- g_print (" failed: %s", emsg);
- g_free (emsg);
- }
- channel->event_mask = event_mask;
-
- if (channel->debug)
- g_print ("\n setting last_events=0");
- channel->last_events = 0;
-
- if ((event_mask & FD_WRITE) &&
- channel->ever_writable &&
- !channel->write_would_have_blocked)
- {
- if (channel->debug)
- g_print (" WSASetEvent(%p)", (WSAEVENT) watch->pollfd.fd);
- WSASetEvent ((WSAEVENT) watch->pollfd.fd);
- }
- }
- break;
-
- default:
- g_assert_not_reached ();
- abort ();
- }
- if (channel->debug)
- g_print ("\n");
-
- return ((watch->condition & buffer_condition) == watch->condition);
-}
-
-static gboolean
-g_io_win32_check (GSource *source)
-{
- MSG msg;
- GIOWin32Watch *watch = (GIOWin32Watch *)source;
- GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
- GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
- WSANETWORKEVENTS events;
-
- if (channel->debug)
- g_print ("g_io_win32_check: source=%p channel=%p", source, channel);
-
- switch (channel->type)
- {
- case G_IO_WIN32_WINDOWS_MESSAGES:
- if (channel->debug)
- g_print (" MSG\n");
- return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
-
- case G_IO_WIN32_FILE_DESC:
- if (channel->debug)
- g_print (" FD thread=%#x buffer_condition=%s\n"
- " watch->pollfd.events={%s} watch->pollfd.revents={%s} channel->revents={%s}\n",
- channel->thread_id, condition_to_string (buffer_condition),
- condition_to_string (watch->pollfd.events),
- condition_to_string (watch->pollfd.revents),
- condition_to_string (channel->revents));
-
- watch->pollfd.revents = (watch->pollfd.events & channel->revents);
-
- return ((watch->pollfd.revents | buffer_condition) & watch->condition);
-
- case G_IO_WIN32_CONSOLE:
- if (channel->debug)
- g_print (" CON\n");
- if (watch->channel->is_writeable)
- return TRUE;
- else if (watch->channel->is_readable)
- {
- INPUT_RECORD buffer;
- DWORD n;
- if (PeekConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n) &&
- n == 1)
- {
- /* _kbhit() does quite complex processing to find out
- * whether at least one of the key events pending corresponds
- * to a "real" character that can be read.
- */
- if (_kbhit ())
- return TRUE;
-
- /* Discard all other kinds of events */
- ReadConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n);
- }
- }
- return FALSE;
-
- case G_IO_WIN32_SOCKET:
- if (channel->debug)
- g_print (" SOCK");
- if (channel->last_events & FD_WRITE)
- {
- if (channel->debug)
- g_print (" sock=%d event=%p last_events has FD_WRITE",
- channel->fd, (HANDLE) watch->pollfd.fd);
- }
- else
- {
- WSAEnumNetworkEvents (channel->fd, 0, &events);
-
- if (channel->debug)
- g_print ("\n revents={%s} condition={%s}"
- "\n WSAEnumNetworkEvents(%d,0) sets events={%s}",
- condition_to_string (watch->pollfd.revents),
- condition_to_string (watch->condition),
- channel->fd,
- event_mask_to_string (events.lNetworkEvents));
-
- if (watch->pollfd.revents != 0 &&
- events.lNetworkEvents == 0 &&
- !(channel->event_mask & FD_WRITE))
- {
- channel->event_mask = 0;
- if (channel->debug)
- g_print ("\n WSAEventSelect(%d,%p,{})",
- channel->fd, (HANDLE) watch->pollfd.fd);
- WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd, 0);
- if (channel->debug)
- g_print (" ResetEvent(%p)",
- (HANDLE) watch->pollfd.fd);
- ResetEvent ((HANDLE) watch->pollfd.fd);
- }
- else if (events.lNetworkEvents & FD_WRITE)
- channel->ever_writable = TRUE;
- channel->last_events = events.lNetworkEvents;
- }
-
- watch->pollfd.revents = 0;
- if (channel->last_events & (FD_READ | FD_ACCEPT))
- watch->pollfd.revents |= G_IO_IN;
-
- if (channel->last_events & FD_WRITE)
- watch->pollfd.revents |= G_IO_OUT;
- else
- {
- /* We have called WSAEnumNetworkEvents() above but it didn't
- * set FD_WRITE.
- */
- if (events.lNetworkEvents & FD_CONNECT)
- {
- if (events.iErrorCode[FD_CONNECT_BIT] == 0)
- watch->pollfd.revents |= G_IO_OUT;
- else
- watch->pollfd.revents |= (G_IO_HUP | G_IO_ERR);
- }
- if (watch->pollfd.revents == 0 && (channel->last_events & (FD_CLOSE)))
- watch->pollfd.revents |= G_IO_HUP;
- }
-
- /* Regardless of WSAEnumNetworkEvents() result, if watching for
- * writability, and if we have ever got a FD_WRITE event, and
- * unless last write would have blocked, set G_IO_OUT. But never
- * set both G_IO_OUT and G_IO_HUP.
- */
- if (!(watch->pollfd.revents & G_IO_HUP) &&
- channel->ever_writable &&
- !channel->write_would_have_blocked &&
- (channel->event_mask & FD_WRITE))
- watch->pollfd.revents |= G_IO_OUT;
-
- if (channel->debug)
- g_print ("\n revents={%s} retval={%s}\n",
- condition_to_string (watch->pollfd.revents),
- condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));
-
- return ((watch->pollfd.revents | buffer_condition) & watch->condition);
-
- default:
- g_assert_not_reached ();
- abort ();
- }
-}
-
-static gboolean
-g_io_win32_dispatch (GSource *source,
- GSourceFunc callback,
- gpointer user_data)
-{
- GIOFunc func = (GIOFunc)callback;
- GIOWin32Watch *watch = (GIOWin32Watch *)source;
- GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
- GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
-
- if (!func)
- {
- g_warning ("IO Watch dispatched without callback\n"
- "You must call g_source_connect().");
- return FALSE;
- }
-
- if (channel->debug)
- g_print ("g_io_win32_dispatch: pollfd.revents=%s condition=%s result=%s\n",
- condition_to_string (watch->pollfd.revents),
- condition_to_string (watch->condition),
- condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));
-
- return (*func) (watch->channel,
- (watch->pollfd.revents | buffer_condition) & watch->condition,
- user_data);
-}
-
-static void
-g_io_win32_finalize (GSource *source)
-{
- GIOWin32Watch *watch = (GIOWin32Watch *)source;
- GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
-
- if (channel->debug)
- g_print ("g_io_win32_finalize: source=%p channel=%p", source, channel);
-
- switch (channel->type)
- {
- case G_IO_WIN32_WINDOWS_MESSAGES:
- if (channel->debug)
- g_print (" MSG");
- break;
-
- case G_IO_WIN32_CONSOLE:
- if (channel->debug)
- g_print (" CON");
- break;
-
- case G_IO_WIN32_FILE_DESC:
- if (channel->debug)
- g_print (" FD thread=%#x", channel->thread_id);
- break;
-
- case G_IO_WIN32_SOCKET:
- if (channel->debug)
- g_print (" SOCK sock=%d", channel->fd);
- break;
-
- default:
- g_assert_not_reached ();
- abort ();
- }
- if (channel->debug)
- g_print ("\n");
- g_io_channel_unref (watch->channel);
-}
-
-GSourceFuncs g_io_watch_funcs = {
- g_io_win32_prepare,
- g_io_win32_check,
- g_io_win32_dispatch,
- g_io_win32_finalize
-};
-
-static GIOStatus
-g_io_win32_msg_read (GIOChannel *channel,
- gchar *buf,
- gsize count,
- gsize *bytes_read,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
- MSG msg; /* In case of alignment problems */
-
- if (count < sizeof (MSG))
- {
- g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
- "Incorrect message size"); /* Informative enough error message? */
- return G_IO_STATUS_ERROR;
- }
-
- if (win32_channel->debug)
- g_print ("g_io_win32_msg_read: channel=%p hwnd=%p\n",
- channel, win32_channel->hwnd);
- if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
- return G_IO_STATUS_AGAIN;
-
- memmove (buf, &msg, sizeof (MSG));
- *bytes_read = sizeof (MSG);
-
- return G_IO_STATUS_NORMAL;
-}
-
-static GIOStatus
-g_io_win32_msg_write (GIOChannel *channel,
- const gchar *buf,
- gsize count,
- gsize *bytes_written,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
- MSG msg;
-
- if (count != sizeof (MSG))
- {
- g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
- "Incorrect message size"); /* Informative enough error message? */
- return G_IO_STATUS_ERROR;
- }
-
- /* In case of alignment problems */
- memmove (&msg, buf, sizeof (MSG));
- if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
- {
- gchar *emsg = g_win32_error_message (GetLastError ());
-
- g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, emsg);
- g_free (emsg);
-
- return G_IO_STATUS_ERROR;
- }
-
- *bytes_written = sizeof (MSG);
-
- return G_IO_STATUS_NORMAL;
-}
-
-static GIOStatus
-g_io_win32_msg_close (GIOChannel *channel,
- GError **err)
-{
- /* Nothing to be done. Or should we set hwnd to some invalid value? */
-
- return G_IO_STATUS_NORMAL;
-}
-
-static void
-g_io_win32_free (GIOChannel *channel)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-
- if (win32_channel->debug)
- g_print ("g_io_win32_free channel=%p fd=%d\n", channel, win32_channel->fd);
-
- DeleteCriticalSection (&win32_channel->mutex);
-
- if (win32_channel->data_avail_event)
- if (!CloseHandle (win32_channel->data_avail_event))
- if (win32_channel->debug)
- {
- gchar *emsg = g_win32_error_message (GetLastError ());
-
- g_print (" CloseHandle(%p) failed: %s\n",
- win32_channel->data_avail_event, emsg);
- g_free (emsg);
- }
-
- g_free (win32_channel->buffer);
-
- if (win32_channel->space_avail_event)
- if (!CloseHandle (win32_channel->space_avail_event))
- if (win32_channel->debug)
- {
- gchar *emsg = g_win32_error_message (GetLastError ());
-
- g_print (" CloseHandle(%p) failed: %s\n",
- win32_channel->space_avail_event, emsg);
- g_free (emsg);
- }
-
- if (win32_channel->type == G_IO_WIN32_SOCKET)
- if (WSAEventSelect (win32_channel->fd, NULL, 0) == SOCKET_ERROR)
- if (win32_channel->debug)
- {
- gchar *emsg = g_win32_error_message (WSAGetLastError ());
-
- g_print (" WSAEventSelect(%d,NULL,{}) failed: %s\n",
- win32_channel->fd, emsg);
- g_free (emsg);
- }
-
- if (win32_channel->event)
- if (!WSACloseEvent (win32_channel->event))
- if (win32_channel->debug)
- {
- gchar *emsg = g_win32_error_message (WSAGetLastError ());
-
- g_print (" WSACloseEvent(%p) failed: %s\n",
- win32_channel->event, emsg);
- g_free (emsg);
- }
-
- g_free (win32_channel);
-}
-
-static GSource *
-g_io_win32_msg_create_watch (GIOChannel *channel,
- GIOCondition condition)
-{
- GIOWin32Watch *watch;
- GSource *source;
-
- source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
- watch = (GIOWin32Watch *)source;
-
- watch->channel = channel;
- g_io_channel_ref (channel);
-
- watch->condition = condition;
-
- watch->pollfd.fd = (gintptr) G_WIN32_MSG_HANDLE;
- watch->pollfd.events = condition;
-
- g_source_add_poll (source, &watch->pollfd);
-
- return source;
-}
-
-static GIOStatus
-g_io_win32_fd_and_console_read (GIOChannel *channel,
- gchar *buf,
- gsize count,
- gsize *bytes_read,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
- gint result;
-
- if (win32_channel->debug)
- g_print ("g_io_win32_fd_read: fd=%d count=%" G_GSIZE_FORMAT "\n",
- win32_channel->fd, count);
-
- if (win32_channel->thread_id)
- {
- return buffer_read (win32_channel, buf, count, bytes_read, err);
- }
-
- result = read (win32_channel->fd, buf, count);
-
- if (win32_channel->debug)
- g_print ("g_io_win32_fd_read: read() => %d\n", result);
-
- if (result < 0)
- {
- *bytes_read = 0;
-
- switch (errno)
- {
-#ifdef EAGAIN
- case EAGAIN:
- return G_IO_STATUS_AGAIN;
-#endif
- default:
- g_set_error_literal (err, G_IO_CHANNEL_ERROR,
- g_io_channel_error_from_errno (errno),
- g_strerror (errno));
- return G_IO_STATUS_ERROR;
- }
- }
-
- *bytes_read = result;
-
- return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
-}
-
-static GIOStatus
-g_io_win32_fd_and_console_write (GIOChannel *channel,
- const gchar *buf,
- gsize count,
- gsize *bytes_written,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
- gint result;
-
- if (win32_channel->thread_id)
- {
- return buffer_write (win32_channel, buf, count, bytes_written, err);
- }
-
- result = write (win32_channel->fd, buf, count);
- if (win32_channel->debug)
- g_print ("g_io_win32_fd_write: fd=%d count=%" G_GSIZE_FORMAT " => %d\n",
- win32_channel->fd, count, result);
-
- if (result < 0)
- {
- *bytes_written = 0;
-
- switch (errno)
- {
-#ifdef EAGAIN
- case EAGAIN:
- return G_IO_STATUS_AGAIN;
-#endif
- default:
- g_set_error_literal (err, G_IO_CHANNEL_ERROR,
- g_io_channel_error_from_errno (errno),
- g_strerror (errno));
- return G_IO_STATUS_ERROR;
- }
- }
-
- *bytes_written = result;
-
- return G_IO_STATUS_NORMAL;
-}
-
-static GIOStatus
-g_io_win32_fd_seek (GIOChannel *channel,
- gint64 offset,
- GSeekType type,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
- int whence;
- off_t tmp_offset;
- off_t result;
-
- switch (type)
- {
- case G_SEEK_SET:
- whence = SEEK_SET;
- break;
- case G_SEEK_CUR:
- whence = SEEK_CUR;
- break;
- case G_SEEK_END:
- whence = SEEK_END;
- break;
- default:
- whence = -1; /* Keep the compiler quiet */
- g_assert_not_reached ();
- abort ();
- }
-
- tmp_offset = offset;
- if (tmp_offset != offset)
- {
- g_set_error_literal (err, G_IO_CHANNEL_ERROR,
- g_io_channel_error_from_errno (EINVAL),
- g_strerror (EINVAL));
- return G_IO_STATUS_ERROR;
- }
-
- result = lseek (win32_channel->fd, tmp_offset, whence);
-
- if (result < 0)
- {
- g_set_error_literal (err, G_IO_CHANNEL_ERROR,
- g_io_channel_error_from_errno (errno),
- g_strerror (errno));
- return G_IO_STATUS_ERROR;
- }
-
- return G_IO_STATUS_NORMAL;
-}
-
-static GIOStatus
-g_io_win32_fd_close (GIOChannel *channel,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-
- if (win32_channel->debug)
- g_print ("g_io_win32_fd_close: thread=%#x: fd=%d\n",
- win32_channel->thread_id,
- win32_channel->fd);
- EnterCriticalSection (&win32_channel->mutex);
- if (win32_channel->running)
- {
- if (win32_channel->debug)
- g_print ("thread %#x: running, marking fd %d for later close\n",
- win32_channel->thread_id, win32_channel->fd);
- win32_channel->running = FALSE;
- win32_channel->needs_close = TRUE;
- if (win32_channel->direction == 0)
- SetEvent (win32_channel->data_avail_event);
- else
- SetEvent (win32_channel->space_avail_event);
- }
- else
- {
- if (win32_channel->debug)
- g_print ("closing fd %d\n", win32_channel->fd);
- close (win32_channel->fd);
- if (win32_channel->debug)
- g_print ("closed fd %d, setting to -1\n",
- win32_channel->fd);
- win32_channel->fd = -1;
- }
- LeaveCriticalSection (&win32_channel->mutex);
-
- /* FIXME error detection? */
-
- return G_IO_STATUS_NORMAL;
-}
-
-static GSource *
-g_io_win32_fd_create_watch (GIOChannel *channel,
- GIOCondition condition)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
- GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
- GIOWin32Watch *watch = (GIOWin32Watch *)source;
-
- watch->channel = channel;
- g_io_channel_ref (channel);
-
- watch->condition = condition;
-
- if (win32_channel->data_avail_event == NULL)
- create_events (win32_channel);
-
- watch->pollfd.fd = (gintptr) win32_channel->data_avail_event;
- watch->pollfd.events = condition;
-
- if (win32_channel->debug)
- g_print ("g_io_win32_fd_create_watch: channel=%p fd=%d condition={%s} event=%p\n",
- channel, win32_channel->fd,
- condition_to_string (condition), (HANDLE) watch->pollfd.fd);
-
- EnterCriticalSection (&win32_channel->mutex);
- if (win32_channel->thread_id == 0)
- {
- if (condition & G_IO_IN)
- create_thread (win32_channel, condition, read_thread);
- else if (condition & G_IO_OUT)
- create_thread (win32_channel, condition, write_thread);
- }
-
- g_source_add_poll (source, &watch->pollfd);
- LeaveCriticalSection (&win32_channel->mutex);
-
- return source;
-}
-
-static GIOStatus
-g_io_win32_console_close (GIOChannel *channel,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-
- if (close (win32_channel->fd) < 0)
- {
- g_set_error_literal (err, G_IO_CHANNEL_ERROR,
- g_io_channel_error_from_errno (errno),
- g_strerror (errno));
- return G_IO_STATUS_ERROR;
- }
-
- return G_IO_STATUS_NORMAL;
-}
-
-static GSource *
-g_io_win32_console_create_watch (GIOChannel *channel,
- GIOCondition condition)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
- GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
- GIOWin32Watch *watch = (GIOWin32Watch *)source;
-
- watch->channel = channel;
- g_io_channel_ref (channel);
-
- watch->condition = condition;
-
- watch->pollfd.fd = _get_osfhandle (win32_channel->fd);
- watch->pollfd.events = condition;
-
- g_source_add_poll (source, &watch->pollfd);
-
- return source;
-}
-
-static GIOStatus
-g_io_win32_sock_read (GIOChannel *channel,
- gchar *buf,
- gsize count,
- gsize *bytes_read,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
- gint result;
- GIOChannelError error;
- int winsock_error;
-
- if (win32_channel->debug)
- g_print ("g_io_win32_sock_read: channel=%p sock=%d count=%" G_GSIZE_FORMAT,
- channel, win32_channel->fd, count);
-
- result = recv (win32_channel->fd, buf, count, 0);
- if (result == SOCKET_ERROR)
- winsock_error = WSAGetLastError ();
-
- if (win32_channel->debug)
- g_print (" recv=%d", result);
-
- if (result == SOCKET_ERROR)
- {
- gchar *emsg = g_win32_error_message (winsock_error);
-
- if (win32_channel->debug)
- g_print (" %s\n", emsg);
-
- *bytes_read = 0;
-
- switch (winsock_error)
- {
- case WSAEINVAL:
- error = G_IO_CHANNEL_ERROR_INVAL;
- break;
- case WSAEWOULDBLOCK:
- g_free (emsg);
- return G_IO_STATUS_AGAIN;
- default:
- error = G_IO_CHANNEL_ERROR_FAILED;
- break;
- }
- g_set_error_literal (err, G_IO_CHANNEL_ERROR, error, emsg);
- g_free (emsg);
-
- return G_IO_STATUS_ERROR;
- }
- else
- {
- if (win32_channel->debug)
- g_print ("\n");
- *bytes_read = result;
- if (result == 0)
- return G_IO_STATUS_EOF;
- else
- return G_IO_STATUS_NORMAL;
- }
-}
-
-static GIOStatus
-g_io_win32_sock_write (GIOChannel *channel,
- const gchar *buf,
- gsize count,
- gsize *bytes_written,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
- gint result;
- GIOChannelError error;
- int winsock_error;
-
- if (win32_channel->debug)
- g_print ("g_io_win32_sock_write: channel=%p sock=%d count=%" G_GSIZE_FORMAT,
- channel, win32_channel->fd, count);
-
- result = send (win32_channel->fd, buf, count, 0);
- if (result == SOCKET_ERROR)
- winsock_error = WSAGetLastError ();
-
- if (win32_channel->debug)
- g_print (" send=%d", result);
-
- if (result == SOCKET_ERROR)
- {
- gchar *emsg = g_win32_error_message (winsock_error);
-
- if (win32_channel->debug)
- g_print (" %s\n", emsg);
-
- *bytes_written = 0;
-
- switch (winsock_error)
- {
- case WSAEINVAL:
- error = G_IO_CHANNEL_ERROR_INVAL;
- break;
- case WSAEWOULDBLOCK:
- win32_channel->write_would_have_blocked = TRUE;
- win32_channel->last_events = 0;
- g_free (emsg);
- return G_IO_STATUS_AGAIN;
- default:
- error = G_IO_CHANNEL_ERROR_FAILED;
- break;
- }
- g_set_error_literal (err, G_IO_CHANNEL_ERROR, error, emsg);
- g_free (emsg);
-
- return G_IO_STATUS_ERROR;
- }
- else
- {
- if (win32_channel->debug)
- g_print ("\n");
- *bytes_written = result;
- win32_channel->write_would_have_blocked = FALSE;
-
- return G_IO_STATUS_NORMAL;
- }
-}
-
-static GIOStatus
-g_io_win32_sock_close (GIOChannel *channel,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-
- if (win32_channel->fd != -1)
- {
- if (win32_channel->debug)
- g_print ("g_io_win32_sock_close: channel=%p sock=%d\n",
- channel, win32_channel->fd);
-
- closesocket (win32_channel->fd);
- win32_channel->fd = -1;
- }
-
- /* FIXME error detection? */
-
- return G_IO_STATUS_NORMAL;
-}
-
-static GSource *
-g_io_win32_sock_create_watch (GIOChannel *channel,
- GIOCondition condition)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
- GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
- GIOWin32Watch *watch = (GIOWin32Watch *)source;
-
- watch->channel = channel;
- g_io_channel_ref (channel);
-
- watch->condition = condition;
-
- if (win32_channel->event == 0)
- win32_channel->event = WSACreateEvent ();
-
- watch->pollfd.fd = (gintptr) win32_channel->event;
- watch->pollfd.events = condition;
-
- if (win32_channel->debug)
- g_print ("g_io_win32_sock_create_watch: channel=%p sock=%d event=%p condition={%s}\n",
- channel, win32_channel->fd, (HANDLE) watch->pollfd.fd,
- condition_to_string (watch->condition));
-
- g_source_add_poll (source, &watch->pollfd);
-
- return source;
-}
-
-GIOChannel *
-g_io_channel_new_file (const gchar *filename,
- const gchar *mode,
- GError **error)
-{
- int fid, flags, pmode;
- GIOChannel *channel;
-
- enum { /* Cheesy hack */
- MODE_R = 1 << 0,
- MODE_W = 1 << 1,
- MODE_A = 1 << 2,
- MODE_PLUS = 1 << 3,
- } mode_num;
-
- g_return_val_if_fail (filename != NULL, NULL);
- g_return_val_if_fail (mode != NULL, NULL);
- g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
-
- switch (mode[0])
- {
- case 'r':
- mode_num = MODE_R;
- break;
- case 'w':
- mode_num = MODE_W;
- break;
- case 'a':
- mode_num = MODE_A;
- break;
- default:
- g_warning ("Invalid GIOFileMode %s.", mode);
- return NULL;
- }
-
- switch (mode[1])
- {
- case '\0':
- break;
- case '+':
- if (mode[2] == '\0')
- {
- mode_num |= MODE_PLUS;
- break;
- }
- /* Fall through */
- default:
- g_warning ("Invalid GIOFileMode %s.", mode);
- return NULL;
- }
-
- switch (mode_num)
- {
- case MODE_R:
- flags = O_RDONLY;
- pmode = _S_IREAD;
- break;
- case MODE_W:
- flags = O_WRONLY | O_TRUNC | O_CREAT;
- pmode = _S_IWRITE;
- break;
- case MODE_A:
- flags = O_WRONLY | O_APPEND | O_CREAT;
- pmode = _S_IWRITE;
- break;
- case MODE_R | MODE_PLUS:
- flags = O_RDWR;
- pmode = _S_IREAD | _S_IWRITE;
- break;
- case MODE_W | MODE_PLUS:
- flags = O_RDWR | O_TRUNC | O_CREAT;
- pmode = _S_IREAD | _S_IWRITE;
- break;
- case MODE_A | MODE_PLUS:
- flags = O_RDWR | O_APPEND | O_CREAT;
- pmode = _S_IREAD | _S_IWRITE;
- break;
- default:
- g_assert_not_reached ();
- abort ();
- }
-
- /* always open 'untranslated' */
- fid = g_open (filename, flags | _O_BINARY, pmode);
-
- if (g_io_win32_get_debug_flag ())
- {
- g_print ("g_io_channel_win32_new_file: open(\"%s\",", filename);
- g_win32_print_access_mode (flags|_O_BINARY);
- g_print (",%#o)=%d\n", pmode, fid);
- }
-
- if (fid < 0)
- {
- g_set_error_literal (error, G_FILE_ERROR,
- g_file_error_from_errno (errno),
- g_strerror (errno));
- return (GIOChannel *)NULL;
- }
-
- channel = g_io_channel_win32_new_fd (fid);
-
- /* XXX: move this to g_io_channel_win32_new_fd () */
- channel->close_on_unref = TRUE;
- channel->is_seekable = TRUE;
-
- /* g_io_channel_win32_new_fd sets is_readable and is_writeable to
- * correspond to actual readability/writeability. Set to FALSE those
- * that mode doesn't allow
- */
- switch (mode_num)
- {
- case MODE_R:
- channel->is_writeable = FALSE;
- break;
- case MODE_W:
- case MODE_A:
- channel->is_readable = FALSE;
- break;
- case MODE_R | MODE_PLUS:
- case MODE_W | MODE_PLUS:
- case MODE_A | MODE_PLUS:
- break;
- default:
- g_assert_not_reached ();
- abort ();
- }
-
- return channel;
-}
-
-#if !defined (_WIN64)
-
-#undef g_io_channel_new_file
-
-/* Binary compatibility version. Not for newly compiled code. */
-
-GIOChannel *
-g_io_channel_new_file (const gchar *filename,
- const gchar *mode,
- GError **error)
-{
- gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
- GIOChannel *retval;
-
- if (utf8_filename == NULL)
- return NULL;
-
- retval = g_io_channel_new_file_utf8 (utf8_filename, mode, error);
-
- g_free (utf8_filename);
-
- return retval;
-}
-
-#endif
-
-static GIOStatus
-g_io_win32_unimpl_set_flags (GIOChannel *channel,
- GIOFlags flags,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-
- if (win32_channel->debug)
- {
- g_print ("g_io_win32_unimpl_set_flags: ");
- g_win32_print_gioflags (flags);
- g_print ("\n");
- }
-
- g_set_error_literal (err, G_IO_CHANNEL_ERROR,
- G_IO_CHANNEL_ERROR_FAILED,
- "Not implemented on Win32");
-
- return G_IO_STATUS_ERROR;
-}
-
-static GIOFlags
-g_io_win32_fd_get_flags_internal (GIOChannel *channel,
- struct stat *st)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
- gchar c;
- DWORD count;
-
- if (st->st_mode & _S_IFIFO)
- {
- channel->is_readable =
- (PeekNamedPipe ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL, NULL) != 0) || GetLastError () == ERROR_BROKEN_PIPE;
- channel->is_writeable =
- (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
- channel->is_seekable = FALSE;
- }
- else
- {
- channel->is_readable =
- (ReadFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
- channel->is_writeable =
- (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
- channel->is_seekable = TRUE;
- }
-
- /* XXX: G_IO_FLAG_APPEND */
- /* XXX: G_IO_FLAG_NONBLOCK */
-
- return 0;
-}
-
-static GIOFlags
-g_io_win32_fd_get_flags (GIOChannel *channel)
-{
- struct stat st;
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-
- g_return_val_if_fail (win32_channel != NULL, 0);
- g_return_val_if_fail (win32_channel->type == G_IO_WIN32_FILE_DESC, 0);
-
- if (0 == fstat (win32_channel->fd, &st))
- return g_io_win32_fd_get_flags_internal (channel, &st);
- else
- return 0;
-}
-
-static GIOFlags
-g_io_win32_console_get_flags_internal (GIOChannel *channel)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
- HANDLE handle = (HANDLE) _get_osfhandle (win32_channel->fd);
- gchar c;
- DWORD count;
- INPUT_RECORD record;
-
- channel->is_readable = PeekConsoleInput (handle, &record, 1, &count);
- channel->is_writeable = WriteFile (handle, &c, 0, &count, NULL);
- channel->is_seekable = FALSE;
-
- return 0;
-}
-
-static GIOFlags
-g_io_win32_console_get_flags (GIOChannel *channel)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-
- g_return_val_if_fail (win32_channel != NULL, 0);
- g_return_val_if_fail (win32_channel->type == G_IO_WIN32_CONSOLE, 0);
-
- return g_io_win32_console_get_flags_internal (channel);
-}
-
-static GIOFlags
-g_io_win32_msg_get_flags (GIOChannel *channel)
-{
- return 0;
-}
-
-static GIOStatus
-g_io_win32_sock_set_flags (GIOChannel *channel,
- GIOFlags flags,
- GError **err)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
- u_long arg;
-
- if (win32_channel->debug)
- {
- g_print ("g_io_win32_sock_set_flags: ");
- g_win32_print_gioflags (flags);
- g_print ("\n");
- }
-
- if (flags & G_IO_FLAG_NONBLOCK)
- {
- arg = 1;
- if (ioctlsocket (win32_channel->fd, FIONBIO, &arg) == SOCKET_ERROR)
- {
- gchar *emsg = g_win32_error_message (WSAGetLastError ());
-
- g_set_error_literal (err, G_IO_CHANNEL_ERROR,
- G_IO_CHANNEL_ERROR_FAILED,
- emsg);
- g_free (emsg);
-
- return G_IO_STATUS_ERROR;
- }
- }
- else
- {
- arg = 0;
- if (ioctlsocket (win32_channel->fd, FIONBIO, &arg) == SOCKET_ERROR)
- {
- gchar *emsg = g_win32_error_message (WSAGetLastError ());
-
- g_set_error_literal (err, G_IO_CHANNEL_ERROR,
- G_IO_CHANNEL_ERROR_FAILED,
- emsg);
- g_free (emsg);
-
- return G_IO_STATUS_ERROR;
- }
- }
-
- return G_IO_STATUS_NORMAL;
-}
-
-static GIOFlags
-g_io_win32_sock_get_flags (GIOChannel *channel)
-{
- /* Could we do something here? */
- return 0;
-}
-
-static GIOFuncs win32_channel_msg_funcs = {
- g_io_win32_msg_read,
- g_io_win32_msg_write,
- NULL,
- g_io_win32_msg_close,
- g_io_win32_msg_create_watch,
- g_io_win32_free,
- g_io_win32_unimpl_set_flags,
- g_io_win32_msg_get_flags,
-};
-
-static GIOFuncs win32_channel_fd_funcs = {
- g_io_win32_fd_and_console_read,
- g_io_win32_fd_and_console_write,
- g_io_win32_fd_seek,
- g_io_win32_fd_close,
- g_io_win32_fd_create_watch,
- g_io_win32_free,
- g_io_win32_unimpl_set_flags,
- g_io_win32_fd_get_flags,
-};
-
-static GIOFuncs win32_channel_console_funcs = {
- g_io_win32_fd_and_console_read,
- g_io_win32_fd_and_console_write,
- NULL,
- g_io_win32_console_close,
- g_io_win32_console_create_watch,
- g_io_win32_free,
- g_io_win32_unimpl_set_flags,
- g_io_win32_console_get_flags,
-};
-
-static GIOFuncs win32_channel_sock_funcs = {
- g_io_win32_sock_read,
- g_io_win32_sock_write,
- NULL,
- g_io_win32_sock_close,
- g_io_win32_sock_create_watch,
- g_io_win32_free,
- g_io_win32_sock_set_flags,
- g_io_win32_sock_get_flags,
-};
-
-GIOChannel *
-#if GLIB_SIZEOF_VOID_P == 8
-g_io_channel_win32_new_messages (gsize hwnd)
-#else
-g_io_channel_win32_new_messages (guint hwnd)
-#endif
-{
- GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
- GIOChannel *channel = (GIOChannel *)win32_channel;
-
- g_io_channel_init (channel);
- g_io_channel_win32_init (win32_channel);
- if (win32_channel->debug)
- g_print ("g_io_channel_win32_new_messages: channel=%p hwnd=%p\n",
- channel, (HWND) hwnd);
- channel->funcs = &win32_channel_msg_funcs;
- win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
- win32_channel->hwnd = (HWND) hwnd;
-
- /* XXX: check this. */
- channel->is_readable = IsWindow (win32_channel->hwnd);
- channel->is_writeable = IsWindow (win32_channel->hwnd);
-
- channel->is_seekable = FALSE;
-
- return channel;
-}
-
-static GIOChannel *
-g_io_channel_win32_new_fd_internal (gint fd,
- struct stat *st)
-{
- GIOWin32Channel *win32_channel;
- GIOChannel *channel;
-
- win32_channel = g_new (GIOWin32Channel, 1);
- channel = (GIOChannel *)win32_channel;
-
- g_io_channel_init (channel);
- g_io_channel_win32_init (win32_channel);
-
- win32_channel->fd = fd;
-
- if (win32_channel->debug)
- g_print ("g_io_channel_win32_new_fd: channel=%p fd=%u\n",
- channel, fd);
-
- if (st->st_mode & _S_IFCHR) /* console */
- {
- channel->funcs = &win32_channel_console_funcs;
- win32_channel->type = G_IO_WIN32_CONSOLE;
- g_io_win32_console_get_flags_internal (channel);
- }
- else
- {
- channel->funcs = &win32_channel_fd_funcs;
- win32_channel->type = G_IO_WIN32_FILE_DESC;
- g_io_win32_fd_get_flags_internal (channel, st);
- }
-
- return channel;
-}
-
-GIOChannel *
-g_io_channel_win32_new_fd (gint fd)
-{
- struct stat st;
-
- if (fstat (fd, &st) == -1)
- {
- g_warning ("g_io_channel_win32_new_fd: %d isn't an open file descriptor in the C library GLib uses.", fd);
- return NULL;
- }
-
- return g_io_channel_win32_new_fd_internal (fd, &st);
-}
-
-gint
-g_io_channel_win32_get_fd (GIOChannel *channel)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-
- return win32_channel->fd;
-}
-
-GIOChannel *
-g_io_channel_win32_new_socket (int socket)
-{
- GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
- GIOChannel *channel = (GIOChannel *)win32_channel;
-
- g_io_channel_init (channel);
- g_io_channel_win32_init (win32_channel);
- if (win32_channel->debug)
- g_print ("g_io_channel_win32_new_socket: channel=%p sock=%d\n",
- channel, socket);
- channel->funcs = &win32_channel_sock_funcs;
- win32_channel->type = G_IO_WIN32_SOCKET;
- win32_channel->fd = socket;
-
- channel->is_readable = TRUE;
- channel->is_writeable = TRUE;
- channel->is_seekable = FALSE;
-
- return channel;
-}
-
-GIOChannel *
-g_io_channel_unix_new (gint fd)
-{
- gboolean is_fd, is_socket;
- struct stat st;
- int optval, optlen;
-
- is_fd = (fstat (fd, &st) == 0);
-
- optlen = sizeof (optval);
- is_socket = (getsockopt (fd, SOL_SOCKET, SO_TYPE, (char *) &optval, &optlen) != SOCKET_ERROR);
-
- if (is_fd && is_socket)
- g_warning ("g_io_channel_unix_new: %d is both a file descriptor and a socket. File descriptor interpretation assumed. To avoid ambiguity, call either g_io_channel_win32_new_fd() or g_io_channel_win32_new_socket() instead.", fd);
-
- if (is_fd)
- return g_io_channel_win32_new_fd_internal (fd, &st);
-
- if (is_socket)
- return g_io_channel_win32_new_socket(fd);
-
- g_warning ("g_io_channel_unix_new: %d is neither a file descriptor or a socket.", fd);
-
- return NULL;
-}
-
-gint
-g_io_channel_unix_get_fd (GIOChannel *channel)
-{
- return g_io_channel_win32_get_fd (channel);
-}
-
-void
-g_io_channel_win32_set_debug (GIOChannel *channel,
- gboolean flag)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-
- win32_channel->debug = flag;
-}
-
-gint
-g_io_channel_win32_poll (GPollFD *fds,
- gint n_fds,
- gint timeout)
-{
- g_return_val_if_fail (n_fds >= 0, 0);
-
- return g_poll (fds, n_fds, timeout);
-}
-
-void
-g_io_channel_win32_make_pollfd (GIOChannel *channel,
- GIOCondition condition,
- GPollFD *fd)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-
- switch (win32_channel->type)
- {
- case G_IO_WIN32_FILE_DESC:
- if (win32_channel->data_avail_event == NULL)
- create_events (win32_channel);
-
- fd->fd = (gintptr) win32_channel->data_avail_event;
-
- if (win32_channel->thread_id == 0)
- {
- /* Is it meaningful for a file descriptor to be polled for
- * both IN and OUT? For what kind of file descriptor would
- * that be? Doesn't seem to make sense, in practise the file
- * descriptors handled here are always read or write ends of
- * pipes surely, and thus unidirectional.
- */
- if (condition & G_IO_IN)
- create_thread (win32_channel, condition, read_thread);
- else if (condition & G_IO_OUT)
- create_thread (win32_channel, condition, write_thread);
- }
- break;
-
- case G_IO_WIN32_CONSOLE:
- fd->fd = _get_osfhandle (win32_channel->fd);
- break;
-
- case G_IO_WIN32_SOCKET:
- fd->fd = (gintptr) WSACreateEvent ();
- break;
-
- case G_IO_WIN32_WINDOWS_MESSAGES:
- fd->fd = G_WIN32_MSG_HANDLE;
- break;
-
- default:
- g_assert_not_reached ();
- abort ();
- }
-
- fd->events = condition;
-}
-
-#ifndef _WIN64
-
-/* Binary compatibility */
-GIOChannel *
-g_io_channel_win32_new_stream_socket (int socket)
-{
- return g_io_channel_win32_new_socket (socket);
-}
-
-#endif
-
-#define __G_IO_WIN32_C__
-#include "galiasdef.c"
diff --git a/glib/glib-mirroring-tab/Makefile b/glib/glib-mirroring-tab/Makefile
deleted file mode 100644
index 8ab193c17..000000000
--- a/glib/glib-mirroring-tab/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-
-CFLAGS = `pkg-config --cflags glib-2.0`
-LIBS = `pkg-config --libs glib-2.0`
-
-
-all: gen-mirroring-tab
-
-gen-mirroring-tab: gen-mirroring-tab.o packtab.o
-
-clean:
- $(RM) gen-mirroring-tab *.o
diff --git a/glib/glib-mirroring-tab/gen-mirroring-tab.c b/glib/glib-mirroring-tab/gen-mirroring-tab.c
deleted file mode 100644
index 6b1637657..000000000
--- a/glib/glib-mirroring-tab/gen-mirroring-tab.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/* gen-mirroring-tab.c - generate gmirroringtable.h for glib
- * copied from FriBidi.
- *
- * $Id$
- * $Author$
- * $Date$
- * $Revision$
- * $Source$
- *
- * Author:
- * Behdad Esfahbod, 2001, 2002, 2004
- *
- * Copyright (C) 2004 Sharif FarsiWeb, Inc
- * Copyright (C) 2001,2002,2004 Behdad Esfahbod
- *
- * 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, in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA
- *
- * For licensing issues, contact <license@farsiweb.info>.
- */
-
-#include <glib.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "packtab.h"
-
-#define appname "gen-mirroring-tab"
-#define outputname "gmirroringtable.h"
-
-static void
-die (
- const char *msg
-)
-{
- fprintf (stderr, appname ": %s\n", msg);
- exit (1);
-}
-
-static void
-die2 (
- const char *fmt,
- const char *p
-)
-{
- fprintf (stderr, appname ": ");
- fprintf (stderr, fmt, p);
- fprintf (stderr, "\n");
- exit (1);
-}
-
-static void
-die4 (
- const char *fmt,
- unsigned long l,
- unsigned long p,
- unsigned long q
-)
-{
- fprintf (stderr, appname ": ");
- fprintf (stderr, fmt, l, p, q);
- fprintf (stderr, "\n");
- exit (1);
-}
-
-#define table_name "Mir"
-#define macro_name "GLIB_GET_MIRRORING"
-
-#define UNICODE_CHARS 0x110000
-
-static signed int table[UNICODE_CHARS];
-static char buf[4000];
-static signed long max_dist;
-
-static void
-init (
- void
-)
-{
- max_dist = 0;
-}
-
-static void
-clear_tab (
- void
-)
-{
- register gunichar c;
-
- for (c = 0; c < UNICODE_CHARS; c++)
- table[c] = 0;
-}
-
-static void
-init_tab_mirroring_txt (
- void
-)
-{
- clear_tab ();
-}
-
-static void
-read_bidi_mirroring_txt (
- FILE *f
-)
-{
- unsigned long l;
-
- init_tab_mirroring_txt ();
-
- l = 0;
- while (fgets (buf, sizeof buf, f))
- {
- unsigned long i, j;
- signed long dist;
- int k;
- const char *s = buf;
-
- l++;
-
- while (*s == ' ')
- s++;
-
- if (s[0] == '#' || s[0] == '\0' || s[0] == '\n')
- continue;
-
- k = sscanf (s, "%lx; %lx", &i, &j);
- if (k != 2 || i >= UNICODE_CHARS || j >= UNICODE_CHARS)
- die4 ("invalid pair in input at line %ld: %04lX, %04lX", l, i, j);
- dist = ((signed long) j - (signed long) i);
- table[i] = dist;
- if (dist > max_dist)
- max_dist = dist;
- else if (-dist > max_dist)
- max_dist = -dist;
- }
-}
-
-static void
-read_data (
- const char *data_file_type,
- const char *data_file_name
-)
-{
- FILE *f;
-
- fprintf (stderr, "Reading `%s'\n", data_file_name);
- if (!(f = fopen (data_file_name, "rt")))
- die2 ("error: cannot open `%s' for reading", data_file_name);
-
- if (!strcmp (data_file_type, "BidiMirroring.txt"))
- read_bidi_mirroring_txt (f);
- else
- die2 ("error: unknown data-file-type %s", data_file_type);
-
- fclose (f);
-}
-
-static void
-gen_mirroring_tab (
- int max_depth,
- const char *data_file_type
-)
-{
- int key_bytes;
- const char *key_type;
-
- fprintf (stderr,
- "Generating `" outputname "', it may take up to a few minutes\n");
- printf ("/* " outputname "\n * generated by " appname " "
- "\n" " * from the file %s of */\n\n", data_file_type);
-
- printf ("#define PACKTAB_UINT8 guint8\n"
- "#define PACKTAB_UINT16 guint16\n"
- "#define PACKTAB_UINT32 guint32\n\n");
-
- key_bytes = max_dist <= 0x7f ? 1 : max_dist < 0x7fff ? 2 : 4;
- key_type = key_bytes == 1 ? "gint8" : key_bytes == 2 ?
- "gint16" : "gint32";
-
- if (!pack_table
- (table, UNICODE_CHARS, key_bytes, 0, max_depth, 1, NULL,
- key_type, table_name, macro_name "_DELTA", stdout))
- die ("error: insufficient memory, decrease max_depth");
-
- printf ("#undef PACKTAB_UINT8\n"
- "#undef PACKTAB_UINT16\n" "#undef PACKTAB_UINT32\n\n");
-
- printf ("#define " macro_name "(x) ((x) + " macro_name "_DELTA(x))\n\n");
-
- printf ("/* End of generated " outputname " */\n");
-}
-
-int
-main (
- int argc,
- const char **argv
-)
-{
- const char *data_file_type = "BidiMirroring.txt";
-
- if (argc < 3)
- die2 ("usage:\n " appname " max-lookups /path/to/%s [junk...]",
- data_file_type);
-
- {
- int max_depth = atoi (argv[1]);
- const char *data_file_name = argv[2];
-
- if (max_depth < 2)
- die ("invalid depth");
-
- init ();
- read_data (data_file_type, data_file_name);
- gen_mirroring_tab (max_depth, data_file_type);
- }
-
- return 0;
-}
diff --git a/glib/glib-mirroring-tab/packtab.c b/glib/glib-mirroring-tab/packtab.c
deleted file mode 100644
index 7c0ff5db4..000000000
--- a/glib/glib-mirroring-tab/packtab.c
+++ /dev/null
@@ -1,424 +0,0 @@
-/* PackTab - Pack a static table
- * Copyright (C) 2001 Behdad Esfahbod.
- *
- * 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, in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA
- *
- * For licensing issues, contact <fwpg@sharif.edu>.
- */
-
-/*
- 8 <= N <= 2^21
- int key
- 1 <= max_depth <= 21
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "packtab.h"
-
-typedef signed int uni_table[1024 * 1024 * 2];
-static int n, a, max_depth, digits, tab_width, per_row;
-static long N;
-signed int def_key;
-static uni_table temp, x, perm, *tab;
-static long pow[22], cluster, cmpcluster;
-static const char *const *name, *key_type_name, *table_name, *macro_name;
-static FILE *f;
-
-static long
-most_binary (
- long min,
- long max
-)
-{
- /* min should be less than max */
- register int i, ii;
-
- if (min == max)
- return max;
-
- for (i = 21; max < pow[i]; i--)
- ;
- ii = i;
- while (i && !((min ^ max) & pow[i]))
- i--;
-
- if (ii == i)
- {
- /* min is less than half of max */
- for (i = 21 - 1; min < pow[i]; i--)
- ;
- i++;
- return pow[i];
- }
-
- return max & (pow[i] - 1);
-}
-
-static void
-init (
- const signed int *table
-)
-{
- register int i;
-
- /* initialize powers of two */
- pow[0] = 1;
- for (i = 1; i <= 21; i++)
- pow[i] = pow[i - 1] << 1;
-
- /* reduce number of elements to get a more binary number */
- {
- long essen;
-
- /* find number of essential items */
- essen = N - 1;
- while (essen && table[essen] == def_key)
- essen--;
- essen++;
-
- N = most_binary (essen, N);
- }
-
- for (n = 21; N % pow[n]; n--)
- ;
- digits = (n + 3) / 4;
- for (i = 6; i; i--)
- if (pow[i] * (tab_width + 1) < 80)
- break;
- per_row = pow[i];
-}
-
-static int
-compare (
- const void *r,
- const void *s
-)
-{
- int i;
- for (i = 0; i < cmpcluster; i++)
- if (((int *) r)[i] != ((int *) s)[i])
- return ((int *) r)[i] - ((int *) s)[i];
- return 0;
-}
-
-static int lev, best_lev, p[22], best_p[22], nn;
-static long c[22], best_c[22], s, best_s;
-static long t[22], best_t[22], clusters[22], best_cluster[22];
-
-static void
-found (
- void
-)
-{
- int i;
-
- if (s < best_s)
- {
- best_s = s;
- best_lev = lev;
- for (i = 0; i <= lev; i++)
- {
- best_p[i] = p[i];
- best_c[i] = c[i];
- best_t[i] = t[i];
- best_cluster[i] = clusters[i];
- }
- }
-}
-
-static void
-bt (
- int node_size
-)
-{
- long i, j, k, y, sbak;
- long key_bytes;
-
- if (t[lev] == 1)
- {
- found ();
- return;
- }
- if (lev == max_depth)
- return;
-
- for (i = 1 - t[lev] % 2; i <= nn + (t[lev] >> nn) % 2; i++)
- {
- nn -= (p[lev] = i);
- clusters[lev] = cluster = (i && nn >= 0) ? pow[i] : t[lev];
- cmpcluster = cluster + 1;
-
- t[lev + 1] = (t[lev] - 1) / cluster + 1;
- for (j = 0; j < t[lev + 1]; j++)
- {
- memmove (temp + j * cmpcluster, tab[lev] + j * cluster,
- cluster * sizeof (tab[lev][0]));
- temp[j * cmpcluster + cluster] = j;
- }
- qsort (temp, t[lev + 1], cmpcluster * sizeof (temp[0]), compare);
- for (j = 0; j < t[lev + 1]; j++)
- {
- perm[j] = temp[j * cmpcluster + cluster];
- temp[j * cmpcluster + cluster] = 0;
- }
- k = 1;
- y = 0;
- tab[lev + 1][perm[0]] = perm[0];
- for (j = 1; j < t[lev + 1]; j++)
- {
- if (compare (temp + y, temp + y + cmpcluster))
- {
- k++;
- tab[lev + 1][perm[j]] = perm[j];
- }
- else
- tab[lev + 1][perm[j]] = tab[lev + 1][perm[j - 1]];
- y += cmpcluster;
- }
- sbak = s;
- s += k * node_size * cluster;
- c[lev] = k;
-
- if (s >= best_s)
- {
- s = sbak;
- nn += i;
- return;
- }
-
- key_bytes = k * cluster;
- key_bytes = key_bytes < 0xff ? 1 : key_bytes < 0xffff ? 2 : 4;
- lev++;
- bt (key_bytes);
- lev--;
-
- s = sbak;
- nn += i;
- }
-}
-
-static void
-solve (
- void
-)
-{
- best_lev = max_depth + 2;
- best_s = N * a * 2;
- lev = 0;
- s = 0;
- nn = n;
- t[0] = N;
- bt (a);
-}
-
-static void
-write_array (
- long max_key
-)
-{
- int i, j, k, y, ii, ofs;
- const char *key_type;
-
- if (best_t[lev] == 1)
- return;
-
- nn -= (i = best_p[lev]);
- cluster = best_cluster[lev];
- cmpcluster = cluster + 1;
-
- t[lev + 1] = best_t[lev + 1];
- for (j = 0; j < t[lev + 1]; j++)
- {
- memmove (temp + j * cmpcluster, tab[lev] + j * cluster,
- cluster * sizeof (tab[lev][0]));
- temp[j * cmpcluster + cluster] = j;
- }
- qsort (temp, t[lev + 1], cmpcluster * sizeof (temp[0]), compare);
- for (j = 0; j < t[lev + 1]; j++)
- {
- perm[j] = temp[j * cmpcluster + cluster];
- temp[j * cmpcluster + cluster] = 0;
- }
- k = 1;
- y = 0;
- tab[lev + 1][perm[0]] = x[0] = perm[0];
- for (j = 1; j < t[lev + 1]; j++)
- {
- if (compare (temp + y, temp + y + cmpcluster))
- {
- x[k] = perm[j];
- tab[lev + 1][perm[j]] = x[k];
- k++;
- }
- else
- tab[lev + 1][perm[j]] = tab[lev + 1][perm[j - 1]];
- y += cmpcluster;
- }
-
- i = 0;
- for (ii = 1; ii < k; ii++)
- if (x[ii] < x[i])
- i = ii;
-
- key_type = !lev ? key_type_name :
- max_key <= 0xff ? "PACKTAB_UINT8" :
- max_key <= 0xffff ? "PACKTAB_UINT16" : "PACKTAB_UINT32";
- fprintf (f, "static const %s %sLev%d[%ld*%d] = {", key_type, table_name,
- best_lev - lev - 1, cluster, k);
- ofs = 0;
- for (ii = 0; ii < k; ii++)
- {
- int kk, jj;
- fprintf (f, "\n#define %sLev%d_%0*lX 0x%0X", table_name,
- best_lev - lev - 1, digits, x[i] * pow[n - nn], ofs);
- kk = x[i] * cluster;
- if (!lev)
- if (name)
- for (j = 0; j < cluster; j++)
- {
- if (!(j % per_row) && j != cluster - 1)
- fprintf (f, "\n ");
- fprintf (f, "%*s,", tab_width, name[tab[lev][kk++]]);
- }
- else
- for (j = 0; j < cluster; j++)
- {
- if (!(j % per_row) && j != cluster - 1)
- fprintf (f, "\n ");
- fprintf (f, "%*d,", tab_width, tab[lev][kk++]);
- }
- else
- for (j = 0; j < cluster; j++, kk++)
- fprintf (f, "\n %sLev%d_%0*lX, /* %0*lX..%0*lX */", table_name,
- best_lev - lev, digits,
- tab[lev][kk] * pow[n - nn - best_p[lev]], digits,
- x[i] * pow[n - nn] + j * pow[n - nn - best_p[lev]], digits,
- x[i] * pow[n - nn] + (j + 1) * pow[n - nn - best_p[lev]] -
- 1);
- ofs += cluster;
- jj = i;
- for (j = 0; j < k; j++)
- if (x[j] > x[i] && (x[j] < x[jj] || jj == i))
- jj = j;
- i = jj;
- }
- fprintf (f, "\n};\n\n");
- lev++;
- write_array (cluster * k);
- lev--;
-}
-
-static void
-write_source (
- void
-)
-{
- int i, j;
-
- lev = 0;
- s = 0;
- nn = n;
- t[0] = N;
- fprintf (f, "\n" "/* *IND" "ENT-OFF* */\n\n");
- write_array (0);
- fprintf (f, "/* *IND" "ENT-ON* */\n\n");
-
- fprintf (f, "#define %s(x) \\\n", macro_name);
- fprintf (f, "\t((x) >= 0x%lx ? ", N);
- if (name)
- fprintf (f, "%s", name[def_key]);
- else
- fprintf (f, "%d", def_key);
- fprintf (f, " : ");
- j = 0;
- for (i = best_lev - 1; i >= 0; i--)
- {
- fprintf (f, " \\\n\t%sLev%d[((x)", table_name, i);
- if (j != 0)
- fprintf (f, " >> %d", j);
- if (i)
- fprintf (f, " & 0x%02lx) +", pow[best_p[best_lev - 1 - i]] - 1);
- j += best_p[best_lev - 1 - i];
- }
- fprintf (f, ")");
- for (i = 0; i < best_lev; i++)
- fprintf (f, "]");
- fprintf (f, ")\n\n");
-}
-
-static void
-write_out (
- void
-)
-{
- int i;
- fprintf (f, "/*\n"
- " generated by packtab.c version %d\n\n"
- " use %s(key) to access your table\n\n"
- " assumed sizeof(%s): %d\n"
- " required memory: %ld\n"
- " lookups: %d\n"
- " partition shape: %s",
- packtab_version, macro_name, key_type_name, a, best_s, best_lev,
- table_name);
- for (i = best_lev - 1; i >= 0; i--)
- fprintf (f, "[%ld]", best_cluster[i]);
- fprintf (f, "\n" " different table entries:");
- for (i = best_lev - 1; i >= 0; i--)
- fprintf (f, " %ld", best_c[i]);
- fprintf (f, "\n*/\n");
- write_source ();
-}
-
-int
-pack_table (
- const signed int *base,
- long key_num,
- int key_size,
- signed int default_key,
- int p_max_depth,
- int p_tab_width,
- const char *const *p_name,
- const char *p_key_type_name,
- const char *p_table_name,
- const char *p_macro_name,
- FILE *out
-)
-{
- N = key_num;
- a = key_size;
- def_key = default_key;
- max_depth = p_max_depth;
- tab_width = p_tab_width;
- name = p_name;
- key_type_name = p_key_type_name;
- table_name = p_table_name;
- macro_name = p_macro_name;
- f = out;
- init (base);
- if (!(tab = malloc ((n + 1) * sizeof (tab[0]))))
- return 0;
- memmove (tab[0], base, N * sizeof (base[0]));
- solve ();
- write_out ();
- free (tab);
- return 1;
-}
-
-/* End of packtab.c */
diff --git a/glib/glib-mirroring-tab/packtab.h b/glib/glib-mirroring-tab/packtab.h
deleted file mode 100644
index 7cab9be31..000000000
--- a/glib/glib-mirroring-tab/packtab.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* PackTab - Pack a static table
- * Copyright (C) 2001 Behdad Esfahbod.
- *
- * 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, in a file named COPYING; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA
- *
- * For licensing issues, contact <fwpg@sharif.edu>.
- */
-
-#ifndef PACKTAB_H
-#define PACKTAB_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#define packtab_version 3
-
- int pack_table (
- const signed int *base,
- long key_num,
- int key_size,
- signed int default_key,
- int max_depth,
- int tab_width,
- const char *const *name,
- const char *key_type_name,
- const char *table_name,
- const char *macro_name,
- FILE *out
- );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* PACKTAB_H */
diff --git a/glib/glib.rc.in b/glib/glib.rc.in
deleted file mode 100644
index 77596cc41..000000000
--- a/glib/glib.rc.in
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <winver.h>
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0
- PRODUCTVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0
- FILEFLAGSMASK 0
- FILEFLAGS 0
- FILEOS VOS__WINDOWS32
- FILETYPE VFT_DLL
- FILESUBTYPE VFT2_UNKNOWN
- BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904B0"
- BEGIN
- VALUE "CompanyName", "The GLib developer community"
- VALUE "FileDescription", "GLib"
- VALUE "FileVersion", "@GLIB_VERSION@.0"
- VALUE "InternalName", "libglib-2.0-@LT_CURRENT_MINUS_AGE@"
- VALUE "LegalCopyright", "Copyright © 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald. Modified by the GLib Team and others 1997-2004."
- VALUE "OriginalFilename", "libglib-2.0-@LT_CURRENT_MINUS_AGE@.dll"
- VALUE "ProductName", "GLib"
- VALUE "ProductVersion", "@GLIB_VERSION@"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
- END
diff --git a/glib/glib.symbols b/glib/glib.symbols
deleted file mode 100644
index a8b7b44f0..000000000
--- a/glib/glib.symbols
+++ /dev/null
@@ -1,1655 +0,0 @@
-/* This file lists all exported symbols. It is used to generate
- * the glib.def file used to control exports on Windows and the
- * galias.h/galiasdef.c files used to avoid PLT entries for
- * internal uses of exported functions (see makegalias.pl).
- *
- * Every symbol must be included in the right
- * #ifdef IN_HEADER(sym) #endif and
- * #ifdef IN_FILE(sym) #endif sections.
- */
-#ifdef ALL_FILES
-#define IN_FILE(x) 1
-#define IN_HEADER(x) 1
-#endif
-#if IN_HEADER(__G_ARRAY_H__)
-#if IN_FILE(__G_ARRAY_C__)
-g_array_append_vals
-g_array_free
-g_array_insert_vals
-g_array_new
-g_array_prepend_vals
-g_array_remove_index
-g_array_remove_index_fast
-g_array_remove_range
-g_array_set_size
-g_array_sized_new
-g_array_sort
-g_array_sort_with_data
-g_byte_array_append
-g_byte_array_free
-g_byte_array_new
-g_byte_array_prepend
-g_byte_array_remove_index
-g_byte_array_remove_index_fast
-g_byte_array_remove_range
-g_byte_array_set_size
-g_byte_array_sized_new
-g_byte_array_sort
-g_byte_array_sort_with_data
-g_ptr_array_add
-g_ptr_array_foreach
-g_ptr_array_free
-g_ptr_array_new
-g_ptr_array_remove
-g_ptr_array_remove_fast
-g_ptr_array_remove_index
-g_ptr_array_remove_index_fast
-g_ptr_array_remove_range
-g_ptr_array_set_size
-g_ptr_array_sized_new
-g_ptr_array_sort
-g_ptr_array_sort_with_data
-#endif
-#endif
-
-#if IN_HEADER(__G_ASYNCQUEUE_H__)
-#if IN_FILE(__G_ASYNCQUEUE_C__)
-g_async_queue_length
-g_async_queue_length_unlocked
-g_async_queue_lock
-g_async_queue_new
-g_async_queue_new_full
-g_async_queue_pop
-g_async_queue_pop_unlocked
-g_async_queue_push
-g_async_queue_push_unlocked
-g_async_queue_push_sorted
-g_async_queue_push_sorted_unlocked
-g_async_queue_ref
-g_async_queue_sort
-g_async_queue_sort_unlocked
-g_async_queue_timed_pop
-g_async_queue_timed_pop_unlocked
-g_async_queue_try_pop
-g_async_queue_try_pop_unlocked
-g_async_queue_unlock
-g_async_queue_unref
-#ifndef G_DISABLE_DEPRECATED
-g_async_queue_ref_unlocked
-g_async_queue_unref_and_unlock
-#endif
-#endif
-#endif
-
-#if IN_HEADER(__G_ATOMIC_H__)
-#if IN_FILE(__G_ATOMIC_C__)
-g_atomic_int_add
-g_atomic_int_compare_and_exchange
-g_atomic_int_exchange_and_add
-g_atomic_pointer_compare_and_exchange
-#ifdef INCLUDE_INTERNAL_SYMBOLS
- /* these are not internal, but we don't want to alias them */
-g_atomic_int_get
-g_atomic_pointer_get
-g_atomic_int_set
-g_atomic_pointer_set
-#endif
-#endif
-#endif
-
-#if IN_HEADER(__G_BACKTRACE_H__)
-#if IN_FILE(__G_BACKTRACE_C__)
-g_on_error_query
-g_on_error_stack_trace
-#endif
-#endif
-
-#if IN_HEADER(__G_BASE64_H__)
-#if IN_FILE(__G_BASE64_C__)
-g_base64_encode_step
-g_base64_encode_close
-g_base64_encode G_GNUC_MALLOC
-g_base64_decode_step
-g_base64_decode G_GNUC_MALLOC
-g_base64_decode_inplace
-#endif
-#endif
-
-#if IN_HEADER(__G_BOOKMARK_FILE_H__)
-#if IN_FILE(__G_BOOKMARK_FILE_C__)
-g_bookmark_file_error_quark
-g_bookmark_file_new
-g_bookmark_file_free
-g_bookmark_file_load_from_file
-g_bookmark_file_load_from_data
-g_bookmark_file_load_from_data_dirs
-g_bookmark_file_to_data
-g_bookmark_file_to_file
-g_bookmark_file_set_title
-g_bookmark_file_get_title G_GNUC_MALLOC
-g_bookmark_file_set_description
-g_bookmark_file_get_description G_GNUC_MALLOC
-g_bookmark_file_set_mime_type
-g_bookmark_file_get_mime_type G_GNUC_MALLOC
-g_bookmark_file_set_groups
-g_bookmark_file_add_group
-g_bookmark_file_has_group
-g_bookmark_file_get_groups G_GNUC_MALLOC
-g_bookmark_file_add_application
-g_bookmark_file_has_application
-g_bookmark_file_get_applications G_GNUC_MALLOC
-g_bookmark_file_set_app_info
-g_bookmark_file_get_app_info
-g_bookmark_file_set_is_private
-g_bookmark_file_get_is_private
-g_bookmark_file_set_icon
-g_bookmark_file_get_icon
-g_bookmark_file_set_added
-g_bookmark_file_get_added
-g_bookmark_file_set_modified
-g_bookmark_file_get_modified
-g_bookmark_file_set_visited
-g_bookmark_file_get_visited
-g_bookmark_file_has_item
-g_bookmark_file_get_size
-g_bookmark_file_get_uris G_GNUC_MALLOC
-g_bookmark_file_remove_group
-g_bookmark_file_remove_application
-g_bookmark_file_remove_item
-g_bookmark_file_move_item
-#endif
-#endif
-
-#if IN_HEADER(__G_CACHE_H__)
-#if IN_FILE(__G_CACHE_C__)
-g_cache_destroy
-g_cache_insert
-g_cache_key_foreach
-g_cache_new
-g_cache_remove
-#ifndef G_DISABLE_DEPRECATED
-g_cache_value_foreach
-#endif
-#endif
-#endif
-
-#if IN_HEADER(__G_CHECKSUM_H__)
-#if IN_FILE(__G_CHECKSUM_C__)
-g_checksum_type_get_length
-g_checksum_new
-g_checksum_copy
-g_checksum_free
-g_checksum_update
-g_checksum_reset
-g_checksum_get_string
-g_checksum_get_digest
-g_compute_checksum_for_data
-g_compute_checksum_for_string
-#endif
-#endif
-
-#if IN_HEADER(__G_COMPLETION_H__)
-#if IN_FILE(__G_COMPLETION_C__)
-g_completion_add_items
-g_completion_clear_items
-g_completion_complete
-g_completion_complete_utf8
-g_completion_free
-g_completion_new
-g_completion_remove_items
-g_completion_set_compare
-#endif
-#endif
-
-#if IN_HEADER(__G_CONVERT_H__)
-#if IN_FILE(__G_CONVERT_C__)
-g_get_filename_charsets
-g_convert G_GNUC_MALLOC
-g_convert_error_quark
-g_convert_with_fallback G_GNUC_MALLOC
-g_convert_with_iconv G_GNUC_MALLOC
-g_iconv
-g_iconv_close
-g_iconv_open
-g_locale_from_utf8 G_GNUC_MALLOC
-g_locale_to_utf8 G_GNUC_MALLOC
-g_filename_display_name G_GNUC_MALLOC
-g_filename_display_basename G_GNUC_MALLOC
-#ifndef _WIN64
-g_filename_from_uri PRIVATE G_GNUC_MALLOC
-g_filename_from_utf8 PRIVATE G_GNUC_MALLOC
-g_filename_to_uri PRIVATE G_GNUC_MALLOC
-g_filename_to_utf8 PRIVATE G_GNUC_MALLOC
-#endif
-#ifdef G_OS_WIN32
-g_filename_from_uri_utf8 G_GNUC_MALLOC
-g_filename_from_utf8_utf8
-g_filename_to_uri_utf8 G_GNUC_MALLOC
-g_filename_to_utf8_utf8
-#endif
-g_uri_list_extract_uris G_GNUC_MALLOC
-#endif
-#endif
-
-#if IN_HEADER(__G_DATASET_H__)
-#if IN_FILE(__G_DATASET_C__)
-g_datalist_clear
-g_datalist_foreach
-g_datalist_get_flags
-g_datalist_id_get_data
-g_datalist_id_remove_no_notify
-g_datalist_id_set_data_full
-g_datalist_set_flags
-g_datalist_unset_flags
-g_datalist_init
-g_dataset_destroy
-g_dataset_foreach
-g_dataset_id_get_data
-g_dataset_id_remove_no_notify
-g_dataset_id_set_data_full
-#endif
-#endif
-
-#if IN_HEADER(__G_QUARK_H__)
-#if IN_FILE(__G_DATASET_C__)
-g_quark_from_static_string
-g_quark_from_string
-g_quark_to_string G_GNUC_CONST
-g_quark_try_string
-g_intern_string
-g_intern_static_string
-#endif
-#endif
-
-#if IN_HEADER(__G_DATE_H__)
-#if IN_FILE(__G_DATE_C__)
-g_date_add_days
-g_date_add_months
-g_date_add_years
-g_date_clamp
-g_date_clear
-g_date_compare
-g_date_days_between
-g_date_free
-g_date_get_day
-g_date_get_day_of_year
-g_date_get_days_in_month
-g_date_get_iso8601_week_of_year
-g_date_get_julian
-g_date_get_monday_week_of_year
-g_date_get_monday_weeks_in_year G_GNUC_CONST
-g_date_get_month
-g_date_get_sunday_week_of_year
-g_date_get_sunday_weeks_in_year G_GNUC_CONST
-g_date_get_weekday
-g_date_get_year
-g_date_is_first_of_month
-g_date_is_last_of_month
-g_date_is_leap_year G_GNUC_CONST
-g_date_new
-g_date_new_dmy
-g_date_new_julian
-g_date_order
-g_date_set_day
-g_date_set_dmy
-g_date_set_julian
-g_date_set_month
-g_date_set_parse
-#ifndef G_DISABLE_DEPRECATED
-g_date_set_time
-#endif
-g_date_set_time_t
-g_date_set_time_val
-g_date_set_year
-g_date_strftime
-g_date_subtract_days
-g_date_subtract_months
-g_date_subtract_years
-g_date_to_struct_tm
-g_date_valid
-g_date_valid_day G_GNUC_CONST
-g_date_valid_dmy
-g_date_valid_julian G_GNUC_CONST
-g_date_valid_month G_GNUC_CONST
-g_date_valid_weekday G_GNUC_CONST
-g_date_valid_year G_GNUC_CONST
-#endif
-#endif
-
-#if IN_HEADER(__G_DIR_H__)
-#if IN_FILE(__G_DIR_C__)
-g_dir_close
-#ifndef _WIN64
-g_dir_open PRIVATE
-g_dir_read_name PRIVATE
-#endif
-#ifdef G_OS_WIN32
-g_dir_open_utf8
-g_dir_read_name_utf8
-#endif
-g_dir_rewind
-#endif
-#endif
-
-#if IN_HEADER(__G_ERROR_H__)
-#if IN_FILE(__G_ERROR_C__)
-g_clear_error
-g_error_copy
-g_error_free
-g_error_matches
-g_error_new G_GNUC_PRINTF(3,4)
-g_error_new_literal
-g_propagate_error
-g_set_error G_GNUC_PRINTF(4,5)
-g_set_error_literal
-g_prefix_error G_GNUC_PRINTF(2,3)
-g_propagate_prefixed_error G_GNUC_PRINTF(3,4)
-#endif
-#endif
-
-#if IN_HEADER(__G_FILEUTILS_H__)
-#if IN_FILE(__G_FILEUTILS_C__)
-g_build_filename G_GNUC_MALLOC G_GNUC_NULL_TERMINATED
-g_build_filenamev G_GNUC_MALLOC
-g_build_path G_GNUC_MALLOC G_GNUC_NULL_TERMINATED
-g_build_pathv G_GNUC_MALLOC
-g_file_error_from_errno
-g_file_error_quark
-#ifndef _WIN64
-g_file_get_contents PRIVATE
-#endif
-g_file_set_contents
-#ifndef _WIN64
-g_file_open_tmp PRIVATE
-g_file_test PRIVATE
-#endif
-g_file_read_link
-g_format_size_for_display
-#ifndef _WIN64
-g_mkstemp PRIVATE
-#endif
-g_mkdir_with_parents
-#ifdef G_OS_WIN32
-g_file_get_contents_utf8
-g_file_open_tmp_utf8
-g_file_test_utf8
-g_mkstemp_utf8
-#endif
-#endif
-#endif
-
-#if IN_HEADER(__G_HASH_H__)
-#if IN_FILE(__G_HASH_C__)
-g_hash_table_destroy
-g_hash_table_unref
-g_hash_table_ref
-g_hash_table_find
-g_hash_table_foreach
-g_hash_table_foreach_remove
-g_hash_table_foreach_steal
-g_hash_table_get_keys
-g_hash_table_get_values
-g_hash_table_insert
-g_hash_table_lookup
-g_hash_table_lookup_extended
-g_hash_table_new
-g_hash_table_new_full
-g_hash_table_remove
-g_hash_table_remove_all
-g_hash_table_replace
-g_hash_table_size
-g_hash_table_steal
-g_hash_table_steal_all
-g_hash_table_iter_init
-g_hash_table_iter_next
-g_hash_table_iter_get_hash_table
-g_hash_table_iter_remove
-g_hash_table_iter_steal
-#endif
-#endif
-
-#if IN_HEADER(__G_HOOK_H__)
-#if IN_FILE(__G_HOOK_C__)
-g_hook_alloc
-g_hook_compare_ids
-g_hook_destroy
-g_hook_destroy_link
-g_hook_find
-g_hook_find_data
-g_hook_find_func
-g_hook_find_func_data
-g_hook_first_valid
-g_hook_free
-g_hook_get
-g_hook_insert_before
-g_hook_insert_sorted
-g_hook_list_clear
-g_hook_list_init
-g_hook_list_invoke
-g_hook_list_invoke_check
-g_hook_list_marshal
-g_hook_list_marshal_check
-g_hook_next_valid
-g_hook_prepend
-g_hook_ref
-g_hook_unref
-#endif
-#endif
-
-#if IN_HEADER(__G_IOCHANNEL_H__)
-#if IN_FILE(__G_IOCHANNEL_C__)
-g_io_add_watch
-g_io_add_watch_full
-g_io_create_watch
-g_io_channel_error_from_errno
-g_io_channel_error_quark
-g_io_channel_flush
-g_io_channel_get_buffer_condition
-g_io_channel_get_buffered
-g_io_channel_get_buffer_size
-g_io_channel_get_close_on_unref
-g_io_channel_get_encoding
-g_io_channel_get_flags
-g_io_channel_get_line_term
-g_io_channel_init
-g_io_channel_read_chars
-g_io_channel_read_line
-g_io_channel_read_line_string
-g_io_channel_read_to_end
-g_io_channel_read_unichar
-g_io_channel_ref
-g_io_channel_seek_position
-g_io_channel_set_buffered
-g_io_channel_set_buffer_size
-g_io_channel_set_close_on_unref
-g_io_channel_set_encoding
-g_io_channel_set_flags
-g_io_channel_set_line_term
-g_io_channel_shutdown
-g_io_channel_unref
-#ifndef G_DISABLE_DEPRECATED
-g_io_channel_close
-g_io_channel_read
-g_io_channel_seek
-g_io_channel_write
-#endif
-g_io_channel_write_chars
-g_io_channel_write_unichar
-#endif
-#endif
-
-#if IN_HEADER(__G_IOCHANNEL_H__)
-#if IN_FILE(__G_IO_UNIX_C__)
-#ifdef G_OS_UNIX
-g_io_channel_unix_get_fd
-g_io_channel_unix_new
-g_io_channel_new_file PRIVATE
-#endif
-#endif
-#endif
-
-#if IN_HEADER(__G_IOCHANNEL_H__)
-#if IN_FILE(__G_IO_WIN32_C__)
-#ifdef G_OS_WIN32
-g_io_channel_unix_get_fd
-g_io_channel_unix_new
-#ifndef _WIN64
-g_io_channel_new_file PRIVATE
-#endif
-g_io_channel_new_file_utf8
-g_io_channel_win32_get_fd
-g_io_channel_win32_make_pollfd
-g_io_channel_win32_new_fd
-g_io_channel_win32_new_messages
-g_io_channel_win32_new_socket
-#ifndef _WIN64
-g_io_channel_win32_new_stream_socket PRIVATE
-#endif
-g_io_channel_win32_poll
-g_io_channel_win32_set_debug
-#endif
-#endif
-#endif
-
-#if IN_HEADER(__G_KEY_FILE_H__)
-#if IN_FILE(__G_KEY_FILE_C__)
-g_key_file_error_quark
-g_key_file_free
-g_key_file_get_boolean
-g_key_file_get_boolean_list G_GNUC_MALLOC
-g_key_file_get_comment G_GNUC_MALLOC
-g_key_file_get_groups G_GNUC_MALLOC
-g_key_file_get_double
-g_key_file_get_double_list G_GNUC_MALLOC
-g_key_file_get_integer
-g_key_file_get_integer_list G_GNUC_MALLOC
-g_key_file_get_keys G_GNUC_MALLOC
-g_key_file_get_locale_string G_GNUC_MALLOC
-g_key_file_get_locale_string_list G_GNUC_MALLOC
-g_key_file_get_start_group G_GNUC_MALLOC
-g_key_file_get_string G_GNUC_MALLOC
-g_key_file_get_string_list G_GNUC_MALLOC
-g_key_file_get_value G_GNUC_MALLOC
-g_key_file_has_group
-g_key_file_has_key
-g_key_file_load_from_dirs
-g_key_file_load_from_data
-g_key_file_load_from_data_dirs
-g_key_file_load_from_file
-g_key_file_new
-g_key_file_remove_comment
-g_key_file_remove_group
-g_key_file_remove_key
-g_key_file_set_boolean
-g_key_file_set_boolean_list
-g_key_file_set_comment
-g_key_file_set_double
-g_key_file_set_double_list
-g_key_file_set_integer
-g_key_file_set_integer_list
-g_key_file_set_list_separator
-g_key_file_set_locale_string
-g_key_file_set_locale_string_list
-g_key_file_set_string
-g_key_file_set_string_list
-g_key_file_set_value
-g_key_file_to_data G_GNUC_MALLOC
-#endif
-#endif
-
-#if IN_HEADER(__G_LIST_H__)
-#if IN_FILE(__G_LIST_C__)
-g_list_alloc
-g_list_append
-g_list_concat
-g_list_copy
-g_list_delete_link
-g_list_find
-g_list_find_custom
-g_list_first
-g_list_foreach
-g_list_free
-g_list_free_1
-g_list_index
-g_list_insert
-g_list_insert_before
-g_list_insert_sorted
-g_list_insert_sorted_with_data
-g_list_last
-g_list_length
-g_list_nth
-g_list_nth_data
-g_list_nth_prev
-#ifndef G_DISABLE_DEPRECATED
-g_list_pop_allocator
-#endif
-g_list_position
-g_list_prepend
-#ifndef G_DISABLE_DEPRECATED
-g_list_push_allocator
-#endif
-g_list_remove
-g_list_remove_all
-g_list_remove_link
-g_list_reverse
-g_list_sort
-g_list_sort_with_data
-#endif
-#endif
-
-#if IN_HEADER(__G_MAIN_H__)
-#if IN_FILE(__G_MAIN_C__)
-g_child_watch_add
-g_child_watch_add_full
-g_child_watch_source_new
-g_get_current_time
-g_main_context_acquire
-g_main_context_add_poll
-g_main_context_check
-g_main_context_default
-g_main_context_dispatch
-g_main_context_find_source_by_funcs_user_data
-g_main_context_find_source_by_id
-g_main_context_find_source_by_user_data
-g_main_context_get_poll_func
-g_main_context_is_owner
-g_main_context_iteration
-g_main_context_new
-g_main_context_pending
-g_main_context_prepare
-g_main_context_query
-g_main_context_ref
-g_main_context_release
-g_main_context_remove_poll
-g_main_context_set_poll_func
-g_main_context_unref
-g_main_context_wait
-g_main_context_wakeup
-g_main_depth
-g_main_current_source
-g_main_loop_get_context
-g_main_loop_is_running
-g_main_loop_new
-g_main_loop_quit
-g_main_loop_ref
-g_main_loop_run
-g_main_loop_unref
-g_source_add_poll
-g_source_attach
-g_source_destroy
-g_source_get_can_recurse
-g_source_get_context
-g_source_get_current_time
-g_source_get_id
-g_source_get_priority
-g_source_new
-g_source_ref
-g_source_remove
-g_source_remove_by_funcs_user_data
-g_source_remove_by_user_data
-g_source_remove_poll
-g_source_set_callback
-g_source_set_callback_indirect
-g_source_set_can_recurse
-g_source_set_funcs
-g_source_is_destroyed
-g_source_set_priority
-g_source_unref
-g_idle_add
-g_idle_add_full
-g_idle_remove_by_data
-g_idle_source_new
-g_timeout_add
-g_timeout_add_seconds
-g_timeout_add_full
-g_timeout_add_seconds_full
-g_timeout_source_new
-g_timeout_source_new_seconds
-#endif
-#endif
-
-#if IN_HEADER(__G_MAPPED_FILE_H__)
-#if IN_FILE(__G_MAPPED_FILE_C__)
-g_mapped_file_new G_GNUC_MALLOC
-g_mapped_file_get_length
-g_mapped_file_get_contents
-g_mapped_file_free
-#endif
-#endif
-
-#if IN_HEADER(__G_MARKUP_H__)
-#if IN_FILE(__G_MARKUP_C__)
-g_markup_error_quark
-g_markup_escape_text
-g_markup_parse_context_end_parse
-g_markup_parse_context_free
-g_markup_parse_context_get_element
-g_markup_parse_context_get_element_stack
-g_markup_parse_context_get_position
-g_markup_parse_context_get_user_data
-g_markup_parse_context_new
-g_markup_parse_context_parse
-g_markup_parse_context_push
-g_markup_parse_context_pop
-g_markup_printf_escaped G_GNUC_PRINTF(1,2)
-g_markup_vprintf_escaped
-g_markup_collect_attributes
-#endif
-#endif
-
-#if IN_HEADER(__G_MEM_H__)
-#if IN_FILE(__G_MEM_C__)
-g_free
-g_malloc G_GNUC_MALLOC
-g_malloc0 G_GNUC_MALLOC
-g_mem_is_system_malloc
-g_mem_profile
-g_mem_set_vtable
-g_realloc
-g_try_malloc G_GNUC_MALLOC
-g_try_malloc0 G_GNUC_MALLOC
-g_try_realloc
-#ifndef G_DISABLE_DEPRECATED
-g_allocator_free
-g_allocator_new
-g_mem_chunk_alloc
-g_mem_chunk_alloc0
-g_mem_chunk_clean
-g_mem_chunk_destroy
-g_mem_chunk_free
-g_mem_chunk_info
-g_mem_chunk_new
-g_mem_chunk_print
-g_mem_chunk_reset
-g_blow_chunks
-#endif
-#endif
-#endif
-
-#if IN_HEADER(__G_SLICE_H__)
-#if IN_FILE(__G_SLICE_C__)
-g_slice_alloc G_GNUC_MALLOC
-g_slice_alloc0 G_GNUC_MALLOC
-g_slice_copy G_GNUC_MALLOC
-g_slice_free1
-g_slice_free_chain_with_offset
-g_slice_set_config
-g_slice_get_config
-g_slice_get_config_state
-#ifdef G_ENABLE_DEBUG
-#ifdef INCLUDE_INTERNAL_SYMBOLS
-g_slice_debug_tree_statistics
-#endif
-#endif
-#endif
-#endif
-
-#if IN_HEADER(__G_MESSAGES_H__)
-#if IN_FILE(__G_MESSAGES_C__)
-g_printf_string_upper_bound
-g_log G_GNUC_PRINTF(3,4)
-g_log_default_handler
-g_log_remove_handler
-g_log_set_always_fatal
-g_log_set_default_handler
-g_log_set_fatal_mask
-g_log_set_handler
-g_logv
-g_return_if_fail_warning
-g_warn_message
-#ifndef G_DISABLE_DEPRECATED
-g_assert_warning G_GNUC_NORETURN
-#endif
-g_print G_GNUC_PRINTF(1,2)
-g_printerr G_GNUC_PRINTF(1,2)
-g_set_printerr_handler
-g_set_print_handler
-#endif
-#endif
-
-#if IN_HEADER(__G_NODE_H__)
-#if IN_FILE(__G_NODE_C__)
-g_node_child_index
-g_node_child_position
-g_node_children_foreach
-g_node_copy
-g_node_copy_deep
-g_node_depth
-g_node_destroy
-g_node_find
-g_node_find_child
-g_node_first_sibling
-g_node_get_root
-g_node_insert
-g_node_insert_after
-g_node_insert_before
-g_node_is_ancestor
-g_node_last_child
-g_node_last_sibling
-g_node_max_height
-g_node_n_children
-g_node_new
-g_node_n_nodes
-g_node_nth_child
-#ifndef G_DISABLE_DEPRECATED
-g_node_pop_allocator
-#endif
-g_node_prepend
-#ifndef G_DISABLE_DEPRECATED
-g_node_push_allocator
-#endif
-g_node_reverse_children
-g_node_traverse
-g_node_unlink
-#endif
-#endif
-
-#if IN_HEADER(__G_OPTION_H__)
-#if IN_FILE(__G_OPTION_C__)
-g_option_context_add_group
-g_option_context_add_main_entries
-g_option_error_quark
-g_option_context_free
-g_option_context_get_description
-g_option_context_get_help_enabled
-g_option_context_get_ignore_unknown_options
-g_option_context_get_main_group
-g_option_context_get_summary
-g_option_context_new
-g_option_context_parse
-g_option_context_set_description
-g_option_context_set_help_enabled
-g_option_context_set_ignore_unknown_options
-g_option_context_set_main_group
-g_option_context_set_summary
-g_option_context_set_translate_func
-g_option_context_set_translation_domain
-g_option_context_get_help
-g_option_group_add_entries
-g_option_group_free
-g_option_group_new
-g_option_group_set_error_hook
-g_option_group_set_parse_hooks
-g_option_group_set_translate_func
-g_option_group_set_translation_domain
-#endif
-#endif
-
-#if IN_HEADER(__G_PATTERN_H__)
-#if IN_FILE(__G_PATTERN_C__)
-g_pattern_match
-g_pattern_match_simple
-g_pattern_match_string
-g_pattern_spec_equal
-g_pattern_spec_free
-g_pattern_spec_new
-#endif
-#endif
-
-#if IN_HEADER(__G_POLL_H__)
-#if IN_FILE(__G_POLL_C__)
-g_poll
-#endif
-#endif
-
-#if IN_HEADER(__G_PRIMES_H__)
-#if IN_FILE(__G_PRIMES_C__)
-g_spaced_primes_closest G_GNUC_CONST
-#endif
-#endif
-
-#if IN_HEADER(__G_PRINTF_H__)
-#if IN_FILE(__G_PRINTF_C__)
-g_fprintf G_GNUC_PRINTF(2,3)
-g_printf G_GNUC_PRINTF(1,2)
-g_sprintf G_GNUC_PRINTF(2,3)
-g_vasprintf
-g_vfprintf
-g_vprintf
-g_vsprintf
-#endif
-#endif
-
-#if IN_HEADER(__G_UTILS_H__)
-#if IN_FILE(__G_PRINTF_C__)
-g_snprintf G_GNUC_PRINTF(3,4)
-g_vsnprintf
-#endif
-#endif
-
-#if IN_HEADER(__G_QSORT_H__)
-#if IN_FILE(__G_QSORT_C__)
-g_qsort_with_data
-#endif
-#endif
-
-#if IN_HEADER(__G_QUEUE_H__)
-#if IN_FILE(__G_QUEUE_C__)
-g_queue_clear
-g_queue_copy
-g_queue_delete_link
-g_queue_find
-g_queue_find_custom
-g_queue_foreach
-g_queue_free
-g_queue_get_length
-g_queue_index
-g_queue_init
-g_queue_insert_after
-g_queue_insert_before
-g_queue_insert_sorted
-g_queue_is_empty
-g_queue_link_index
-g_queue_new
-g_queue_peek_head
-g_queue_peek_head_link
-g_queue_peek_nth
-g_queue_peek_nth_link
-g_queue_peek_tail
-g_queue_peek_tail_link
-g_queue_pop_head
-g_queue_pop_head_link
-g_queue_pop_nth
-g_queue_pop_nth_link
-g_queue_pop_tail
-g_queue_pop_tail_link
-g_queue_push_head
-g_queue_push_head_link
-g_queue_push_nth
-g_queue_push_nth_link
-g_queue_push_tail
-g_queue_push_tail_link
-g_queue_remove
-g_queue_remove_all
-g_queue_reverse
-g_queue_sort
-g_queue_unlink
-#endif
-#endif
-
-#if IN_HEADER(__G_RAND_H__)
-#if IN_FILE(__G_RAND_C__)
-g_rand_copy
-g_rand_double
-g_rand_double_range
-g_rand_free
-g_rand_int
-g_rand_int_range
-g_rand_new
-g_rand_new_with_seed
-g_rand_new_with_seed_array
-g_random_double
-g_random_double_range
-g_random_int
-g_random_int_range
-g_random_set_seed
-g_rand_set_seed
-g_rand_set_seed_array
-#endif
-#endif
-
-#if IN_HEADER(__G_REL_H__)
-#if IN_FILE(__G_REL_C__)
-g_relation_count
-g_relation_delete
-g_relation_destroy
-g_relation_exists
-g_relation_index
-g_relation_insert
-g_relation_new
-g_relation_print
-g_relation_select
-g_tuples_destroy
-g_tuples_index
-#endif
-#endif
-
-#if IN_HEADER(__G_SCANNER_H__)
-#if IN_FILE(__G_SCANNER_C__)
-g_scanner_cur_line
-g_scanner_cur_position
-g_scanner_cur_token
-g_scanner_cur_value
-g_scanner_destroy
-g_scanner_eof
-g_scanner_error G_GNUC_PRINTF(2,3)
-g_scanner_get_next_token
-g_scanner_input_file
-g_scanner_input_text
-g_scanner_lookup_symbol
-g_scanner_new
-g_scanner_peek_next_token
-g_scanner_scope_add_symbol
-g_scanner_scope_foreach_symbol
-g_scanner_scope_lookup_symbol
-g_scanner_scope_remove_symbol
-g_scanner_set_scope
-g_scanner_sync_file_offset
-g_scanner_unexp_token
-g_scanner_warn G_GNUC_PRINTF(2,3)
-#endif
-#endif
-
-#if IN_HEADER(__G_SEQUENCE_H__)
-#if IN_FILE(__G_SEQUENCE_C__)
-g_sequence_new
-g_sequence_free
-g_sequence_get_length
-g_sequence_foreach
-g_sequence_foreach_range
-g_sequence_sort
-g_sequence_sort_iter
-g_sequence_get_begin_iter
-g_sequence_get_end_iter
-g_sequence_get_iter_at_pos
-g_sequence_append
-g_sequence_prepend
-g_sequence_insert_before
-g_sequence_move
-g_sequence_swap
-g_sequence_insert_sorted
-g_sequence_insert_sorted_iter
-g_sequence_sort_changed
-g_sequence_sort_changed_iter
-g_sequence_remove
-g_sequence_remove_range
-g_sequence_move_range
-g_sequence_search
-g_sequence_search_iter
-g_sequence_get
-g_sequence_set
-g_sequence_iter_is_begin
-g_sequence_iter_is_end
-g_sequence_iter_next
-g_sequence_iter_prev
-g_sequence_iter_get_position
-g_sequence_iter_move
-g_sequence_iter_get_sequence
-g_sequence_iter_compare
-g_sequence_range_get_midpoint
-#endif
-#endif
-
-#if IN_HEADER(__G_SHELL_H__)
-#if IN_FILE(__G_SHELL_C__)
-g_shell_error_quark
-g_shell_parse_argv
-g_shell_quote
-g_shell_unquote
-#endif
-#endif
-
-#if IN_HEADER(__G_SLIST_H__)
-#if IN_FILE(__G_SLIST_C__)
-g_slist_alloc
-g_slist_append
-g_slist_concat
-g_slist_copy
-g_slist_delete_link
-g_slist_find
-g_slist_find_custom
-g_slist_foreach
-g_slist_free
-g_slist_free_1
-g_slist_index
-g_slist_insert
-g_slist_insert_before
-g_slist_insert_sorted
-g_slist_insert_sorted_with_data
-g_slist_last
-g_slist_length
-g_slist_nth
-g_slist_nth_data
-#ifndef G_DISABLE_DEPRECATED
-g_slist_pop_allocator
-#endif
-g_slist_position
-g_slist_prepend
-#ifndef G_DISABLE_DEPRECATED
-g_slist_push_allocator
-#endif
-g_slist_remove
-g_slist_remove_all
-g_slist_remove_link
-g_slist_reverse
-g_slist_sort
-g_slist_sort_with_data
-#endif
-#endif
-
-#if IN_HEADER(__G_SPAWN_H__)
-#if IN_FILE(__G_SPAWN_C__)
-#ifndef _WIN64
-g_spawn_async PRIVATE
-g_spawn_async_with_pipes PRIVATE
-#endif
-g_spawn_close_pid
-#ifndef _WIN64
-g_spawn_command_line_async PRIVATE
-g_spawn_command_line_sync PRIVATE
-#endif
-g_spawn_error_quark
-#ifndef _WIN64
-g_spawn_sync PRIVATE
-#endif
-#ifdef G_OS_WIN32
-g_spawn_async_utf8
-g_spawn_async_with_pipes_utf8
-g_spawn_command_line_async_utf8
-g_spawn_command_line_sync_utf8
-g_spawn_sync_utf8
-#endif
-#endif
-#endif
-
-#if IN_HEADER(__G_STDIO_H__)
-#if IN_FILE(__G_STDIO_C__)
-#if !defined(G_OS_UNIX) || defined(G_STDIO_NO_WRAP_ON_UNIX)
-/* gstdio wrappers */
-g_chmod
-g_open
-g_creat
-g_rename
-g_mkdir
-g_stat
-g_lstat
-g_remove
-g_fopen
-g_freopen
-g_utime
-#endif
-g_access
-g_chdir
-g_unlink
-g_rmdir
-#endif
-#endif
-
-#if IN_HEADER(__G_STRFUNCS_H__)
-#if IN_FILE(__G_STRFUNCS_C__)
-g_ascii_digit_value G_GNUC_CONST
-g_ascii_dtostr
-g_ascii_formatd
-g_ascii_strdown G_GNUC_MALLOC
-g_ascii_strtod
-g_ascii_strtoull
-g_ascii_strtoll
-g_ascii_strup G_GNUC_MALLOC
-g_ascii_tolower G_GNUC_CONST
-g_ascii_toupper G_GNUC_CONST
-g_ascii_xdigit_value G_GNUC_CONST
-g_ascii_strcasecmp
-g_ascii_strncasecmp
-g_memdup G_GNUC_MALLOC
-g_stpcpy
-g_strcanon
-g_strchomp
-g_strchug
-g_strcompress G_GNUC_MALLOC
-g_strconcat G_GNUC_MALLOC G_GNUC_NULL_TERMINATED
-g_strdelimit
-g_strdup G_GNUC_MALLOC
-g_strdup_printf G_GNUC_PRINTF(1,2) G_GNUC_MALLOC
-g_strdupv G_GNUC_MALLOC
-g_strdup_vprintf G_GNUC_MALLOC
-g_strerror G_GNUC_CONST
-g_strescape G_GNUC_MALLOC
-g_strfreev
-g_str_has_prefix
-g_str_has_suffix
-g_strjoin G_GNUC_MALLOC G_GNUC_NULL_TERMINATED
-g_strjoinv G_GNUC_MALLOC
-g_strlcat
-g_strlcpy
-g_strndup G_GNUC_MALLOC
-g_strnfill G_GNUC_MALLOC
-g_strreverse
-g_strrstr
-g_strrstr_len
-g_strsignal G_GNUC_CONST
-g_strsplit G_GNUC_MALLOC
-g_strsplit_set G_GNUC_MALLOC
-g_strstr_len
-g_strtod
-#ifndef G_DISABLE_DEPRECATED
-g_strcasecmp
-g_strncasecmp
-g_strup
-g_strdown
-#endif
-g_strv_length
-g_strip_context G_GNUC_FORMAT(1)
-g_dgettext G_GNUC_FORMAT(2)
-g_dngettext G_GNUC_FORMAT(3)
-g_dpgettext G_GNUC_FORMAT(2)
-g_dpgettext2 G_GNUC_FORMAT(3)
-#endif
-#endif
-
-#if IN_HEADER(__G_URI_FUNCS_H__)
-#if IN_FILE(__G_URI_FUNCS_C__)
-g_uri_unescape_string
-g_uri_unescape_segment
-g_uri_parse_scheme
-g_uri_escape_string
-#endif
-#endif
-
-#if IN_HEADER(__G_STRING_H__)
-#if IN_FILE(__G_STRING_C__)
-g_string_append
-g_string_append_len
-g_string_append_printf G_GNUC_PRINTF(2,3)
-g_string_append_unichar
-g_string_append_vprintf
-g_string_ascii_down
-g_string_ascii_up
-g_string_assign
-g_string_chunk_free
-g_string_chunk_clear
-g_string_chunk_insert
-g_string_chunk_insert_const
-g_string_chunk_insert_len
-g_string_chunk_new
-g_string_equal
-g_string_erase
-g_string_free
-g_string_hash
-g_string_insert
-g_string_insert_c
-g_string_insert_len
-g_string_insert_unichar
-g_string_new
-g_string_new_len
-g_string_overwrite
-g_string_overwrite_len
-g_string_prepend
-g_string_prepend_c
-g_string_prepend_len
-g_string_prepend_unichar
-g_string_printf G_GNUC_PRINTF(2,3)
-g_string_set_size
-g_string_sized_new
-g_string_truncate
-g_string_append_uri_escaped
-#ifndef G_DISABLE_DEPRECATED
-g_string_down
-g_string_up
-#endif
-g_string_vprintf
-#ifdef INCLUDE_INTERNAL_SYMBOLS
- /* these are not internal, but we don't want to alias them */
-g_string_append_c
-#endif
-g_str_equal
-g_str_hash
-#endif
-#endif
-
-#if IN_HEADER(__G_THREAD_H__)
-#if IN_FILE(__G_THREAD_C__)
-g_once_impl
-g_once_init_enter_impl
-g_once_init_leave
-#ifdef INCLUDE_INTERNAL_SYMBOLS
-g_thread_init_glib
-g_once_init_enter
-#endif
-#ifdef INCLUDE_VARIABLES
-g_thread_functions_for_glib_use
-g_threads_got_initialized
-g_thread_use_default_impl
-g_thread_gettime
-#endif
-g_thread_create_full
-g_thread_error_quark
-g_thread_exit
-g_thread_join
-g_thread_self
-g_thread_set_priority
-g_static_mutex_free
-g_static_mutex_get_mutex_impl
-g_static_mutex_init
-g_static_private_free
-g_static_private_get
-g_static_private_init
-g_static_private_set
-g_static_rec_mutex_free
-g_static_rec_mutex_init
-g_static_rec_mutex_lock
-g_static_rec_mutex_lock_full
-g_static_rec_mutex_trylock
-g_static_rec_mutex_unlock
-g_static_rec_mutex_unlock_full
-g_static_rw_lock_free
-g_static_rw_lock_init
-g_static_rw_lock_reader_lock
-g_static_rw_lock_reader_trylock
-g_static_rw_lock_reader_unlock
-g_static_rw_lock_writer_lock
-g_static_rw_lock_writer_trylock
-g_static_rw_lock_writer_unlock
-g_thread_foreach
-g_thread_get_initialized
-#endif
-#endif
-
-#if IN_HEADER(__G_THREADPOOL_H__)
-#if IN_FILE(__G_THREADPOOL_C__)
-g_thread_pool_free
-g_thread_pool_get_max_threads
-g_thread_pool_get_max_unused_threads
-g_thread_pool_get_max_idle_time
-g_thread_pool_get_num_threads
-g_thread_pool_get_num_unused_threads
-g_thread_pool_new
-g_thread_pool_push
-g_thread_pool_set_max_threads
-g_thread_pool_set_max_unused_threads
-g_thread_pool_set_max_idle_time
-g_thread_pool_stop_unused_threads
-g_thread_pool_unprocessed
-g_thread_pool_set_sort_function
-#endif
-#endif
-
-#if IN_HEADER(__G_TEST_UTILS_H__)
-#if IN_FILE(__G_TEST_UTILS_C__)
-g_assertion_message G_GNUC_NORETURN
-g_assertion_message_cmpnum G_GNUC_NORETURN
-g_assertion_message_cmpstr G_GNUC_NORETURN
-g_assertion_message_expr G_GNUC_NORETURN
-g_assertion_message_error G_GNUC_NORETURN
-g_strcmp0
-g_test_add_data_func
-g_test_add_func
-g_test_add_vtable
-g_test_bug
-g_test_bug_base
-#ifdef INCLUDE_VARIABLES
-g_test_config_vars
-#endif
-g_test_create_case
-g_test_create_suite
-g_test_get_root
-g_test_init
-g_test_log_buffer_free
-g_test_log_buffer_new
-g_test_log_buffer_pop
-g_test_log_buffer_push
-g_test_log_msg_free
-g_test_log_type_name
-g_test_maximized_result
-g_test_message
-g_test_minimized_result
-g_test_queue_destroy
-g_test_queue_free
-g_test_rand_double
-g_test_rand_double_range
-g_test_rand_int
-g_test_rand_int_range
-g_test_run
-g_test_run_suite
-g_test_suite_add
-g_test_suite_add_suite
-g_test_timer_elapsed
-g_test_timer_last
-g_test_timer_start
-g_test_trap_assertions
-g_test_trap_fork
-g_test_trap_has_passed
-g_test_trap_reached_timeout
-#endif
-#endif
-
-#if IN_HEADER(__G_TIMER_H__)
-#if IN_FILE(__G_TIMER_C__)
-g_timer_continue
-g_timer_destroy
-g_timer_elapsed
-g_timer_new
-g_timer_reset
-g_timer_start
-g_timer_stop
-g_time_val_add
-g_time_val_from_iso8601
-g_time_val_to_iso8601 G_GNUC_MALLOC
-g_usleep
-#endif
-#endif
-
-#if IN_HEADER(__G_TREE_H__)
-#if IN_FILE(__G_TREE_C__)
-g_tree_destroy
-g_tree_foreach
-g_tree_height
-g_tree_insert
-g_tree_lookup
-g_tree_lookup_extended
-g_tree_new
-g_tree_new_full
-g_tree_new_with_data
-g_tree_nnodes
-g_tree_remove
-g_tree_replace
-g_tree_search
-g_tree_steal
-#ifndef G_DISABLE_DEPRECATED
-g_tree_traverse
-#endif
-#endif
-#endif
-
-#if IN_HEADER(__G_UNICODE_H__)
-#if IN_FILE(__G_UNIBREAK_C__)
-g_unichar_break_type G_GNUC_CONST
-#endif
-#endif
-
-#if IN_HEADER(__G_UNICODE_H__)
-#if IN_FILE(__G_UNICOLLATE_C__)
-g_utf8_collate
-g_utf8_collate_key G_GNUC_MALLOC
-g_utf8_collate_key_for_filename G_GNUC_MALLOC
-#endif
-#endif
-
-#if IN_HEADER(__G_UNICODE_H__)
-#if IN_FILE(__G_UNIDECOMP_C__)
-g_unicode_canonical_decomposition G_GNUC_MALLOC
-g_unicode_canonical_ordering
-g_unichar_combining_class G_GNUC_CONST
-g_utf8_normalize
-#endif
-#endif
-
-#if IN_HEADER(__G_UNICODE_H__)
-#if IN_FILE(__G_UNIPROP_C__)
-g_unichar_isalnum G_GNUC_CONST
-g_unichar_isalpha G_GNUC_CONST
-g_unichar_iscntrl G_GNUC_CONST
-g_unichar_isdefined G_GNUC_CONST
-g_unichar_isdigit G_GNUC_CONST
-g_unichar_isgraph G_GNUC_CONST
-g_unichar_islower G_GNUC_CONST
-g_unichar_isprint G_GNUC_CONST
-g_unichar_ispunct G_GNUC_CONST
-g_unichar_isspace G_GNUC_CONST
-g_unichar_istitle G_GNUC_CONST
-g_unichar_isupper G_GNUC_CONST
-g_unichar_iswide G_GNUC_CONST
-g_unichar_iswide_cjk G_GNUC_CONST
-g_unichar_isxdigit G_GNUC_CONST
-g_unichar_iszerowidth G_GNUC_CONST
-g_unichar_tolower G_GNUC_CONST
-g_unichar_totitle G_GNUC_CONST
-g_unichar_toupper G_GNUC_CONST
-g_unichar_ismark G_GNUC_CONST
-g_unichar_get_mirror_char
-g_unichar_get_script
-g_unichar_digit_value G_GNUC_CONST
-g_unichar_xdigit_value G_GNUC_CONST
-g_unichar_type G_GNUC_CONST
-g_utf8_casefold G_GNUC_MALLOC
-g_utf8_strup G_GNUC_MALLOC
-g_utf8_strdown G_GNUC_MALLOC
-#endif
-#endif
-
-#if IN_HEADER(__G_UNICODE_H__)
-#if IN_FILE(__G_UTF8_C__)
-g_get_charset
-g_ucs4_to_utf16 G_GNUC_MALLOC
-g_ucs4_to_utf8 G_GNUC_MALLOC
-g_utf16_to_ucs4 G_GNUC_MALLOC
-g_utf16_to_utf8 G_GNUC_MALLOC
-g_utf8_find_next_char
-g_utf8_find_prev_char
-g_utf8_get_char
-g_utf8_get_char_validated
-g_utf8_offset_to_pointer
-g_utf8_pointer_to_offset
-g_utf8_prev_char
-g_utf8_strchr
-g_utf8_strlen
-g_utf8_strncpy
-g_utf8_strrchr
-g_utf8_strreverse
-g_utf8_to_ucs4 G_GNUC_MALLOC
-g_utf8_to_ucs4_fast G_GNUC_MALLOC
-g_utf8_to_utf16 G_GNUC_MALLOC
-g_utf8_validate
-g_unichar_to_utf8
-g_unichar_validate
-#endif
-#endif
-
-#if IN_HEADER(__GLIBINTL_H__)
-#if IN_FILE(__G_UTILS_C__)
-glib_gettext G_GNUC_FORMAT(1)
-#endif
-#endif
-
-#if IN_HEADER(__G_HASH_H__)
-#if IN_FILE(__G_UTILS_C__)
-g_int_equal
-g_int_hash
-g_direct_equal G_GNUC_CONST
-g_direct_hash G_GNUC_CONST
-#endif
-#endif
-
-#if IN_HEADER(__G_UTILS_H__)
-#if IN_FILE(__G_UTILS_C__)
-g_atexit
-#ifndef G_DISABLE_DEPRECATED
-g_basename
-#endif
-g_get_application_name
-#ifndef _WIN64
-g_find_program_in_path PRIVATE
-g_get_current_dir PRIVATE
-g_getenv PRIVATE
-g_unsetenv PRIVATE
-g_get_home_dir PRIVATE
-#endif
-g_get_host_name
-#ifndef _WIN64
-g_setenv PRIVATE
-#endif
-g_listenv
-#ifdef G_OS_WIN32
-g_find_program_in_path_utf8
-g_get_current_dir_utf8
-g_getenv_utf8
-g_unsetenv_utf8
-g_setenv_utf8
-g_get_home_dir_utf8
-#endif
-g_get_language_names
-g_get_prgname
-#ifndef _WIN64
-g_get_real_name PRIVATE
-#endif
-#ifdef G_OS_WIN32
-g_get_real_name_utf8
-#endif
-g_get_system_config_dirs
-g_get_system_data_dirs
-#ifdef G_OS_WIN32
-g_win32_get_system_data_dirs_for_module
-#endif
-#ifndef _WIN64
-g_get_tmp_dir PRIVATE
-#endif
-#ifdef G_OS_WIN32
-g_get_tmp_dir_utf8
-#endif
-g_get_user_cache_dir
-g_get_user_config_dir
-g_get_user_data_dir
-g_get_user_special_dir
-#ifndef _WIN64
-g_get_user_name PRIVATE
-#endif
-#ifdef G_OS_WIN32
-g_get_user_name_utf8
-#endif
-glib_check_version
-g_nullify_pointer
-g_parse_debug_string
-g_path_get_basename G_GNUC_MALLOC
-g_path_get_dirname G_GNUC_MALLOC
-g_path_is_absolute
-g_path_skip_root
-g_set_application_name
-g_set_prgname
-#ifdef INCLUDE_INTERNAL_SYMBOLS
-g_bit_nth_lsf
-g_bit_nth_msf
-g_bit_storage
-g_trash_stack_height
-g_trash_stack_peek
-g_trash_stack_pop
-g_trash_stack_push
-g_get_codeset
-#endif
-#endif
-#endif
-
-#if IN_HEADER(__G_REGEX_H__)
-#if IN_FILE(__G_REGEX_C__)
-g_regex_error_quark
-g_regex_new
-g_regex_ref
-g_regex_unref
-g_regex_get_pattern
-g_regex_get_max_backref
-g_regex_get_capture_count
-g_regex_get_string_number
-g_regex_escape_string
-g_regex_match_simple
-g_regex_match
-g_regex_match_full
-g_regex_match_all
-g_regex_match_all_full
-g_regex_split_simple
-g_regex_split
-g_regex_split_full
-g_regex_replace
-g_regex_replace_literal
-g_regex_replace_eval
-g_regex_check_replacement
-g_match_info_get_regex
-g_match_info_get_string
-g_match_info_free
-g_match_info_next
-g_match_info_matches
-g_match_info_get_match_count
-g_match_info_is_partial_match
-g_match_info_expand_references
-g_match_info_fetch
-g_match_info_fetch_pos
-g_match_info_fetch_named
-g_match_info_fetch_named_pos
-g_match_info_fetch_all
-#endif
-#endif
-
-#if IN_HEADER(__G_WIN32_H__)
-#if IN_FILE(__G_WIN32_H__)
-#ifdef G_OS_WIN32
-g_win32_error_message
-g_win32_ftruncate
-g_win32_get_package_installation_directory_of_module
-#ifndef _WIN64
-g_win32_get_package_installation_directory PRIVATE
-#endif
-g_win32_get_package_installation_directory_utf8
-#ifndef _WIN64
-g_win32_get_package_installation_subdirectory PRIVATE
-#endif
-g_win32_get_package_installation_subdirectory_utf8
-g_win32_get_windows_version
-g_win32_getlocale
-g_win32_locale_filename_from_utf8
-#endif
-#endif
-#endif
-
-#ifdef INCLUDE_VARIABLES
-g_ascii_table
-g_utf8_skip
-g_idle_funcs
-g_timeout_funcs
-g_io_watch_funcs
-g_child_watch_funcs
-glib_binary_age
-glib_interface_age
-glib_major_version
-glib_mem_profiler_table
-glib_micro_version
-glib_minor_version
-glib_on_error_halt
-g_mem_gc_friendly
-#endif
diff --git a/glib/glibintl.h b/glib/glibintl.h
index 47a7910f8..214b26192 100644
--- a/glib/glibintl.h
+++ b/glib/glibintl.h
@@ -7,7 +7,7 @@
G_CONST_RETURN gchar *glib_gettext (const gchar *str) G_GNUC_FORMAT(1);
-#ifdef ENABLE_NLS
+#if 0
#include <libintl.h>
#define _(String) glib_gettext(String)
diff --git a/glib/gmain.c b/glib/gmain.c
index 331c0a86b..61fcdded5 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -3665,7 +3665,11 @@ g_child_watch_source_init_single (void)
sigaction (SIGCHLD, &action, NULL);
}
+#ifdef ANDROID_STUB
G_GNUC_NORETURN static gpointer
+#else
+void
+#endif
child_watch_helper_thread (gpointer data)
{
while (1)
diff --git a/glib/gmappedfile.c b/glib/gmappedfile.c
deleted file mode 100644
index 1220f410e..000000000
--- a/glib/gmappedfile.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * gmappedfile.c: Simplified wrapper around the mmap() function.
- *
- * Copyright 2005 Matthias Clasen
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-
-#include "glibconfig.h"
-
-#ifdef G_OS_WIN32
-#include <windows.h>
-#include <io.h>
-#endif
-
-#include "gconvert.h"
-#include "gerror.h"
-#include "gfileutils.h"
-#include "gmappedfile.h"
-#include "gmem.h"
-#include "gmessages.h"
-#include "gstdio.h"
-#include "gstrfuncs.h"
-
-#include "glibintl.h"
-
-#include "galias.h"
-
-#ifndef _O_BINARY
-#define _O_BINARY 0
-#endif
-
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *) -1)
-#endif
-
-struct _GMappedFile
-{
- gsize length;
- gchar *contents;
-#ifdef G_OS_WIN32
- HANDLE mapping;
-#endif
-};
-
-/**
- * g_mapped_file_new:
- * @filename: The path of the file to load, in the GLib filename encoding
- * @writable: whether the mapping should be writable
- * @error: return location for a #GError, or %NULL
- *
- * Maps a file into memory. On UNIX, this is using the mmap() function.
- *
- * If @writable is %TRUE, the mapped buffer may be modified, otherwise
- * it is an error to modify the mapped buffer. Modifications to the buffer
- * are not visible to other processes mapping the same file, and are not
- * written back to the file.
- *
- * Note that modifications of the underlying file might affect the contents
- * of the #GMappedFile. Therefore, mapping should only be used if the file
- * will not be modified, or if all modifications of the file are done
- * atomically (e.g. using g_file_set_contents()).
- *
- * Return value: a newly allocated #GMappedFile which must be freed
- * with g_mapped_file_free(), or %NULL if the mapping failed.
- *
- * Since: 2.8
- */
-GMappedFile *
-g_mapped_file_new (const gchar *filename,
- gboolean writable,
- GError **error)
-{
- GMappedFile *file;
- int fd;
- struct stat st;
-
- g_return_val_if_fail (filename != NULL, NULL);
- g_return_val_if_fail (!error || *error == NULL, NULL);
-
- fd = g_open (filename, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0);
- if (fd == -1)
- {
- int save_errno = errno;
- gchar *display_filename = g_filename_display_name (filename);
-
- g_set_error (error,
- G_FILE_ERROR,
- g_file_error_from_errno (save_errno),
- _("Failed to open file '%s': open() failed: %s"),
- display_filename,
- g_strerror (save_errno));
- g_free (display_filename);
- return NULL;
- }
-
- file = g_new0 (GMappedFile, 1);
-
- if (fstat (fd, &st) == -1)
- {
- int save_errno = errno;
- gchar *display_filename = g_filename_display_name (filename);
-
- g_set_error (error,
- G_FILE_ERROR,
- g_file_error_from_errno (save_errno),
- _("Failed to get attributes of file '%s': fstat() failed: %s"),
- display_filename,
- g_strerror (save_errno));
- g_free (display_filename);
- goto out;
- }
-
- if (st.st_size == 0)
- {
- file->length = 0;
- file->contents = "";
- close (fd);
- return file;
- }
-
- file->contents = MAP_FAILED;
-
-#ifdef HAVE_MMAP
- if (st.st_size > G_MAXSIZE)
- {
- errno = EINVAL;
- }
- else
- {
- file->length = (gsize) st.st_size;
- file->contents = (gchar *) mmap (NULL, file->length,
- writable ? PROT_READ|PROT_WRITE : PROT_READ,
- MAP_PRIVATE, fd, 0);
- }
-#endif
-#ifdef G_OS_WIN32
- file->length = st.st_size;
- file->mapping = CreateFileMapping ((HANDLE) _get_osfhandle (fd), NULL,
- writable ? PAGE_WRITECOPY : PAGE_READONLY,
- 0, 0,
- NULL);
- if (file->mapping != NULL)
- {
- file->contents = MapViewOfFile (file->mapping,
- writable ? FILE_MAP_COPY : FILE_MAP_READ,
- 0, 0,
- 0);
- if (file->contents == NULL)
- {
- file->contents = MAP_FAILED;
- CloseHandle (file->mapping);
- file->mapping = NULL;
- }
- }
-#endif
-
-
- if (file->contents == MAP_FAILED)
- {
- int save_errno = errno;
- gchar *display_filename = g_filename_display_name (filename);
-
- g_set_error (error,
- G_FILE_ERROR,
- g_file_error_from_errno (save_errno),
- _("Failed to map file '%s': mmap() failed: %s"),
- display_filename,
- g_strerror (save_errno));
- g_free (display_filename);
- goto out;
- }
-
- close (fd);
- return file;
-
- out:
- close (fd);
- g_free (file);
-
- return NULL;
-}
-
-/**
- * g_mapped_file_get_length:
- * @file: a #GMappedFile
- *
- * Returns the length of the contents of a #GMappedFile.
- *
- * Returns: the length of the contents of @file.
- *
- * Since: 2.8
- */
-gsize
-g_mapped_file_get_length (GMappedFile *file)
-{
- g_return_val_if_fail (file != NULL, 0);
-
- return file->length;
-}
-
-/**
- * g_mapped_file_get_contents:
- * @file: a #GMappedFile
- *
- * Returns the contents of a #GMappedFile.
- *
- * Note that the contents may not be zero-terminated,
- * even if the #GMappedFile is backed by a text file.
- *
- * Returns: the contents of @file.
- *
- * Since: 2.8
- */
-gchar *
-g_mapped_file_get_contents (GMappedFile *file)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- return file->contents;
-}
-
-/**
- * g_mapped_file_free:
- * @file: a #GMappedFile
- *
- * Unmaps the buffer of @file and frees it.
- *
- * Since: 2.8
- */
-void
-g_mapped_file_free (GMappedFile *file)
-{
- g_return_if_fail (file != NULL);
-
- if (file->length)
- {
-#ifdef HAVE_MMAP
- munmap (file->contents, file->length);
-#endif
-#ifdef G_OS_WIN32
- UnmapViewOfFile (file->contents);
- CloseHandle (file->mapping);
-#endif
- }
-
- g_free (file);
-}
-
-
-#define __G_MAPPED_FILE_C__
-#include "galiasdef.c"
diff --git a/glib/gmarkup.c b/glib/gmarkup.c
deleted file mode 100644
index b1f4f465f..000000000
--- a/glib/gmarkup.c
+++ /dev/null
@@ -1,2996 +0,0 @@
-/* gmarkup.c - Simple XML-like parser
- *
- * Copyright 2000, 2003 Red Hat, Inc.
- * Copyright 2007, 2008 Ryan Lortie <desrt@desrt.ca>
- *
- * GLib 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 of the
- * License, or (at your option) any later version.
- *
- * GLib 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 GLib; see the file COPYING.LIB. If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <stdarg.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "glib.h"
-#include "glibintl.h"
-#include "galias.h"
-
-GQuark
-g_markup_error_quark (void)
-{
- return g_quark_from_static_string ("g-markup-error-quark");
-}
-
-typedef enum
-{
- STATE_START,
- STATE_AFTER_OPEN_ANGLE,
- STATE_AFTER_CLOSE_ANGLE,
- STATE_AFTER_ELISION_SLASH, /* the slash that obviates need for end element */
- STATE_INSIDE_OPEN_TAG_NAME,
- STATE_INSIDE_ATTRIBUTE_NAME,
- STATE_AFTER_ATTRIBUTE_NAME,
- STATE_BETWEEN_ATTRIBUTES,
- STATE_AFTER_ATTRIBUTE_EQUALS_SIGN,
- STATE_INSIDE_ATTRIBUTE_VALUE_SQ,
- STATE_INSIDE_ATTRIBUTE_VALUE_DQ,
- STATE_INSIDE_TEXT,
- STATE_AFTER_CLOSE_TAG_SLASH,
- STATE_INSIDE_CLOSE_TAG_NAME,
- STATE_AFTER_CLOSE_TAG_NAME,
- STATE_INSIDE_PASSTHROUGH,
- STATE_ERROR
-} GMarkupParseState;
-
-typedef struct
-{
- const char *prev_element;
- const GMarkupParser *prev_parser;
- gpointer prev_user_data;
-} GMarkupRecursionTracker;
-
-struct _GMarkupParseContext
-{
- const GMarkupParser *parser;
-
- GMarkupParseFlags flags;
-
- gint line_number;
- gint char_number;
-
- gpointer user_data;
- GDestroyNotify dnotify;
-
- /* A piece of character data or an element that
- * hasn't "ended" yet so we haven't yet called
- * the callback for it.
- */
- GString *partial_chunk;
-
- GMarkupParseState state;
- GSList *tag_stack;
- gchar **attr_names;
- gchar **attr_values;
- gint cur_attr;
- gint alloc_attrs;
-
- const gchar *current_text;
- gssize current_text_len;
- const gchar *current_text_end;
-
- GString *leftover_char_portion;
-
- /* used to save the start of the last interesting thingy */
- const gchar *start;
-
- const gchar *iter;
-
- guint document_empty : 1;
- guint parsing : 1;
- guint awaiting_pop : 1;
- gint balance;
-
- /* subparser support */
- GSList *subparser_stack; /* (GMarkupRecursionTracker *) */
- const char *subparser_element;
- gpointer held_user_data;
-};
-
-/**
- * g_markup_parse_context_new:
- * @parser: a #GMarkupParser
- * @flags: one or more #GMarkupParseFlags
- * @user_data: user data to pass to #GMarkupParser functions
- * @user_data_dnotify: user data destroy notifier called when the parse context is freed
- *
- * Creates a new parse context. A parse context is used to parse
- * marked-up documents. You can feed any number of documents into
- * a context, as long as no errors occur; once an error occurs,
- * the parse context can't continue to parse text (you have to free it
- * and create a new parse context).
- *
- * Return value: a new #GMarkupParseContext
- **/
-GMarkupParseContext *
-g_markup_parse_context_new (const GMarkupParser *parser,
- GMarkupParseFlags flags,
- gpointer user_data,
- GDestroyNotify user_data_dnotify)
-{
- GMarkupParseContext *context;
-
- g_return_val_if_fail (parser != NULL, NULL);
-
- context = g_new (GMarkupParseContext, 1);
-
- context->parser = parser;
- context->flags = flags;
- context->user_data = user_data;
- context->dnotify = user_data_dnotify;
-
- context->line_number = 1;
- context->char_number = 1;
-
- context->partial_chunk = NULL;
-
- context->state = STATE_START;
- context->tag_stack = NULL;
- context->attr_names = NULL;
- context->attr_values = NULL;
- context->cur_attr = -1;
- context->alloc_attrs = 0;
-
- context->current_text = NULL;
- context->current_text_len = -1;
- context->current_text_end = NULL;
- context->leftover_char_portion = NULL;
-
- context->start = NULL;
- context->iter = NULL;
-
- context->document_empty = TRUE;
- context->parsing = FALSE;
-
- context->awaiting_pop = FALSE;
- context->subparser_stack = NULL;
- context->subparser_element = NULL;
-
- /* this is only looked at if awaiting_pop = TRUE. initialise anyway. */
- context->held_user_data = NULL;
-
- context->balance = 0;
-
- return context;
-}
-
-/**
- * g_markup_parse_context_free:
- * @context: a #GMarkupParseContext
- *
- * Frees a #GMarkupParseContext. Can't be called from inside
- * one of the #GMarkupParser functions. Can't be called while
- * a subparser is pushed.
- **/
-void
-g_markup_parse_context_free (GMarkupParseContext *context)
-{
- g_return_if_fail (context != NULL);
- g_return_if_fail (!context->parsing);
- g_return_if_fail (!context->subparser_stack);
- g_return_if_fail (!context->awaiting_pop);
-
- if (context->dnotify)
- (* context->dnotify) (context->user_data);
-
- g_strfreev (context->attr_names);
- g_strfreev (context->attr_values);
-
- g_slist_foreach (context->tag_stack, (GFunc)g_free, NULL);
- g_slist_free (context->tag_stack);
-
- if (context->partial_chunk)
- g_string_free (context->partial_chunk, TRUE);
-
- if (context->leftover_char_portion)
- g_string_free (context->leftover_char_portion, TRUE);
-
- g_free (context);
-}
-
-static void pop_subparser_stack (GMarkupParseContext *context);
-
-static void
-mark_error (GMarkupParseContext *context,
- GError *error)
-{
- context->state = STATE_ERROR;
-
- if (context->parser->error)
- (*context->parser->error) (context, error, context->user_data);
-
- /* report the error all the way up to free all the user-data */
- while (context->subparser_stack)
- {
- pop_subparser_stack (context);
- context->awaiting_pop = FALSE; /* already been freed */
-
- if (context->parser->error)
- (*context->parser->error) (context, error, context->user_data);
- }
-}
-
-static void set_error (GMarkupParseContext *context,
- GError **error,
- GMarkupError code,
- const gchar *format,
- ...) G_GNUC_PRINTF (4, 5);
-
-static void
-set_error_literal (GMarkupParseContext *context,
- GError **error,
- GMarkupError code,
- const gchar *message)
-{
- GError *tmp_error;
-
- tmp_error = g_error_new_literal (G_MARKUP_ERROR, code, message);
-
- g_prefix_error (&tmp_error,
- _("Error on line %d char %d: "),
- context->line_number,
- context->char_number);
-
- mark_error (context, tmp_error);
-
- g_propagate_error (error, tmp_error);
-}
-
-static void
-set_error (GMarkupParseContext *context,
- GError **error,
- GMarkupError code,
- const gchar *format,
- ...)
-{
- gchar *s;
- gchar *s_valid;
- va_list args;
-
- va_start (args, format);
- s = g_strdup_vprintf (format, args);
- va_end (args);
-
- /* Make sure that the GError message is valid UTF-8 even if it is
- * complaining about invalid UTF-8 in the markup: */
- s_valid = _g_utf8_make_valid (s);
- set_error_literal (context, error, code, s);
-
- g_free (s);
- g_free (s_valid);
-}
-
-static void
-propagate_error (GMarkupParseContext *context,
- GError **dest,
- GError *src)
-{
- if (context->flags & G_MARKUP_PREFIX_ERROR_POSITION)
- g_prefix_error (&src,
- _("Error on line %d char %d: "),
- context->line_number,
- context->char_number);
-
- mark_error (context, src);
-
- g_propagate_error (dest, src);
-}
-
-/* To make these faster, we first use the ascii-only tests, then check
- * for the usual non-alnum name-end chars, and only then call the
- * expensive unicode stuff. Nobody uses non-ascii in XML tag/attribute
- * names, so this is a reasonable hack that virtually always avoids
- * the guniprop call.
- */
-#define IS_COMMON_NAME_END_CHAR(c) \
- ((c) == '=' || (c) == '/' || (c) == '>' || (c) == ' ')
-
-static gboolean
-is_name_start_char (const gchar *p)
-{
- if (g_ascii_isalpha (*p) ||
- (!IS_COMMON_NAME_END_CHAR (*p) &&
- (*p == '_' ||
- *p == ':' ||
- g_unichar_isalpha (g_utf8_get_char (p)))))
- return TRUE;
- else
- return FALSE;
-}
-
-static gboolean
-is_name_char (const gchar *p)
-{
- if (g_ascii_isalnum (*p) ||
- (!IS_COMMON_NAME_END_CHAR (*p) &&
- (*p == '.' ||
- *p == '-' ||
- *p == '_' ||
- *p == ':' ||
- g_unichar_isalpha (g_utf8_get_char (p)))))
- return TRUE;
- else
- return FALSE;
-}
-
-
-static gchar*
-char_str (gunichar c,
- gchar *buf)
-{
- memset (buf, 0, 8);
- g_unichar_to_utf8 (c, buf);
- return buf;
-}
-
-static gchar*
-utf8_str (const gchar *utf8,
- gchar *buf)
-{
- char_str (g_utf8_get_char (utf8), buf);
- return buf;
-}
-
-static void
-set_unescape_error (GMarkupParseContext *context,
- GError **error,
- const gchar *remaining_text,
- const gchar *remaining_text_end,
- GMarkupError code,
- const gchar *format,
- ...)
-{
- GError *tmp_error;
- gchar *s;
- va_list args;
- gint remaining_newlines;
- const gchar *p;
-
- remaining_newlines = 0;
- p = remaining_text;
- while (p != remaining_text_end)
- {
- if (*p == '\n')
- ++remaining_newlines;
- ++p;
- }
-
- va_start (args, format);
- s = g_strdup_vprintf (format, args);
- va_end (args);
-
- tmp_error = g_error_new (G_MARKUP_ERROR,
- code,
- _("Error on line %d: %s"),
- context->line_number - remaining_newlines,
- s);
-
- g_free (s);
-
- mark_error (context, tmp_error);
-
- g_propagate_error (error, tmp_error);
-}
-
-typedef enum
-{
- USTATE_INSIDE_TEXT,
- USTATE_AFTER_AMPERSAND,
- USTATE_INSIDE_ENTITY_NAME,
- USTATE_AFTER_CHARREF_HASH
-} UnescapeState;
-
-typedef struct
-{
- GMarkupParseContext *context;
- GString *str;
- UnescapeState state;
- const gchar *text;
- const gchar *text_end;
- const gchar *entity_start;
-} UnescapeContext;
-
-static const gchar*
-unescape_text_state_inside_text (UnescapeContext *ucontext,
- const gchar *p,
- GError **error)
-{
- const gchar *start;
- gboolean normalize_attribute;
-
- if (ucontext->context->state == STATE_INSIDE_ATTRIBUTE_VALUE_SQ ||
- ucontext->context->state == STATE_INSIDE_ATTRIBUTE_VALUE_DQ)
- normalize_attribute = TRUE;
- else
- normalize_attribute = FALSE;
-
- start = p;
-
- while (p != ucontext->text_end)
- {
- if (*p == '&')
- {
- break;
- }
- else if (normalize_attribute && (*p == '\t' || *p == '\n'))
- {
- g_string_append_len (ucontext->str, start, p - start);
- g_string_append_c (ucontext->str, ' ');
- p = g_utf8_next_char (p);
- start = p;
- }
- else if (*p == '\r')
- {
- g_string_append_len (ucontext->str, start, p - start);
- g_string_append_c (ucontext->str, normalize_attribute ? ' ' : '\n');
- p = g_utf8_next_char (p);
- if (p != ucontext->text_end && *p == '\n')
- p = g_utf8_next_char (p);
- start = p;
- }
- else
- p = g_utf8_next_char (p);
- }
-
- if (p != start)
- g_string_append_len (ucontext->str, start, p - start);
-
- if (p != ucontext->text_end && *p == '&')
- {
- p = g_utf8_next_char (p);
- ucontext->state = USTATE_AFTER_AMPERSAND;
- }
-
- return p;
-}
-
-static const gchar*
-unescape_text_state_after_ampersand (UnescapeContext *ucontext,
- const gchar *p,
- GError **error)
-{
- ucontext->entity_start = NULL;
-
- if (*p == '#')
- {
- p = g_utf8_next_char (p);
-
- ucontext->entity_start = p;
- ucontext->state = USTATE_AFTER_CHARREF_HASH;
- }
- else if (!is_name_start_char (p))
- {
- if (*p == ';')
- {
- set_unescape_error (ucontext->context, error,
- p, ucontext->text_end,
- G_MARKUP_ERROR_PARSE,
- _("Empty entity '&;' seen; valid "
- "entities are: &amp; &quot; &lt; &gt; &apos;"));
- }
- else
- {
- gchar buf[8];
-
- set_unescape_error (ucontext->context, error,
- p, ucontext->text_end,
- G_MARKUP_ERROR_PARSE,
- _("Character '%s' is not valid at "
- "the start of an entity name; "
- "the & character begins an entity; "
- "if this ampersand isn't supposed "
- "to be an entity, escape it as "
- "&amp;"),
- utf8_str (p, buf));
- }
- }
- else
- {
- ucontext->entity_start = p;
- ucontext->state = USTATE_INSIDE_ENTITY_NAME;
- }
-
- return p;
-}
-
-static const gchar*
-unescape_text_state_inside_entity_name (UnescapeContext *ucontext,
- const gchar *p,
- GError **error)
-{
- while (p != ucontext->text_end)
- {
- if (*p == ';')
- break;
- else if (!is_name_char (p))
- {
- gchar ubuf[8];
-
- set_unescape_error (ucontext->context, error,
- p, ucontext->text_end,
- G_MARKUP_ERROR_PARSE,
- _("Character '%s' is not valid "
- "inside an entity name"),
- utf8_str (p, ubuf));
- break;
- }
-
- p = g_utf8_next_char (p);
- }
-
- if (ucontext->context->state != STATE_ERROR)
- {
- if (p != ucontext->text_end)
- {
- gint len = p - ucontext->entity_start;
-
- /* move to after semicolon */
- p = g_utf8_next_char (p);
- ucontext->state = USTATE_INSIDE_TEXT;
-
- if (strncmp (ucontext->entity_start, "lt", len) == 0)
- g_string_append_c (ucontext->str, '<');
- else if (strncmp (ucontext->entity_start, "gt", len) == 0)
- g_string_append_c (ucontext->str, '>');
- else if (strncmp (ucontext->entity_start, "amp", len) == 0)
- g_string_append_c (ucontext->str, '&');
- else if (strncmp (ucontext->entity_start, "quot", len) == 0)
- g_string_append_c (ucontext->str, '"');
- else if (strncmp (ucontext->entity_start, "apos", len) == 0)
- g_string_append_c (ucontext->str, '\'');
- else
- {
- gchar *name;
-
- name = g_strndup (ucontext->entity_start, len);
- set_unescape_error (ucontext->context, error,
- p, ucontext->text_end,
- G_MARKUP_ERROR_PARSE,
- _("Entity name '%s' is not known"),
- name);
- g_free (name);
- }
- }
- else
- {
- set_unescape_error (ucontext->context, error,
- /* give line number of the & */
- ucontext->entity_start, ucontext->text_end,
- G_MARKUP_ERROR_PARSE,
- _("Entity did not end with a semicolon; "
- "most likely you used an ampersand "
- "character without intending to start "
- "an entity - escape ampersand as &amp;"));
- }
- }
-#undef MAX_ENT_LEN
-
- return p;
-}
-
-static const gchar*
-unescape_text_state_after_charref_hash (UnescapeContext *ucontext,
- const gchar *p,
- GError **error)
-{
- gboolean is_hex = FALSE;
- const char *start;
-
- start = ucontext->entity_start;
-
- if (*p == 'x')
- {
- is_hex = TRUE;
- p = g_utf8_next_char (p);
- start = p;
- }
-
- while (p != ucontext->text_end && *p != ';')
- p = g_utf8_next_char (p);
-
- if (p != ucontext->text_end)
- {
- g_assert (*p == ';');
-
- /* digit is between start and p */
-
- if (start != p)
- {
- gulong l;
- gchar *end = NULL;
-
- errno = 0;
- if (is_hex)
- l = strtoul (start, &end, 16);
- else
- l = strtoul (start, &end, 10);
-
- if (end != p || errno != 0)
- {
- set_unescape_error (ucontext->context, error,
- start, ucontext->text_end,
- G_MARKUP_ERROR_PARSE,
- _("Failed to parse '%-.*s', which "
- "should have been a digit "
- "inside a character reference "
- "(&#234; for example) - perhaps "
- "the digit is too large"),
- p - start, start);
- }
- else
- {
- /* characters XML 1.1 permits */
- if ((0 < l && l <= 0xD7FF) ||
- (0xE000 <= l && l <= 0xFFFD) ||
- (0x10000 <= l && l <= 0x10FFFF))
- {
- gchar buf[8];
- g_string_append (ucontext->str, char_str (l, buf));
- }
- else
- {
- set_unescape_error (ucontext->context, error,
- start, ucontext->text_end,
- G_MARKUP_ERROR_PARSE,
- _("Character reference '%-.*s' does not "
- "encode a permitted character"),
- p - start, start);
- }
- }
-
- /* Move to next state */
- p = g_utf8_next_char (p); /* past semicolon */
- ucontext->state = USTATE_INSIDE_TEXT;
- }
- else
- {
- set_unescape_error (ucontext->context, error,
- start, ucontext->text_end,
- G_MARKUP_ERROR_PARSE,
- _("Empty character reference; "
- "should include a digit such as "
- "&#454;"));
- }
- }
- else
- {
- set_unescape_error (ucontext->context, error,
- start, ucontext->text_end,
- G_MARKUP_ERROR_PARSE,
- _("Character reference did not end with a "
- "semicolon; "
- "most likely you used an ampersand "
- "character without intending to start "
- "an entity - escape ampersand as &amp;"));
- }
-
- return p;
-}
-
-static gboolean
-unescape_text (GMarkupParseContext *context,
- const gchar *text,
- const gchar *text_end,
- GString **unescaped,
- GError **error)
-{
- UnescapeContext ucontext;
- const gchar *p;
-
- ucontext.context = context;
- ucontext.text = text;
- ucontext.text_end = text_end;
- ucontext.entity_start = NULL;
-
- ucontext.str = g_string_sized_new (text_end - text);
-
- ucontext.state = USTATE_INSIDE_TEXT;
- p = text;
-
- while (p != text_end && context->state != STATE_ERROR)
- {
- g_assert (p < text_end);
-
- switch (ucontext.state)
- {
- case USTATE_INSIDE_TEXT:
- {
- p = unescape_text_state_inside_text (&ucontext,
- p,
- error);
- }
- break;
-
- case USTATE_AFTER_AMPERSAND:
- {
- p = unescape_text_state_after_ampersand (&ucontext,
- p,
- error);
- }
- break;
-
-
- case USTATE_INSIDE_ENTITY_NAME:
- {
- p = unescape_text_state_inside_entity_name (&ucontext,
- p,
- error);
- }
- break;
-
- case USTATE_AFTER_CHARREF_HASH:
- {
- p = unescape_text_state_after_charref_hash (&ucontext,
- p,
- error);
- }
- break;
-
- default:
- g_assert_not_reached ();
- break;
- }
- }
-
- if (context->state != STATE_ERROR)
- {
- switch (ucontext.state)
- {
- case USTATE_INSIDE_TEXT:
- break;
- case USTATE_AFTER_AMPERSAND:
- case USTATE_INSIDE_ENTITY_NAME:
- set_unescape_error (context, error,
- NULL, NULL,
- G_MARKUP_ERROR_PARSE,
- _("Unfinished entity reference"));
- break;
- case USTATE_AFTER_CHARREF_HASH:
- set_unescape_error (context, error,
- NULL, NULL,
- G_MARKUP_ERROR_PARSE,
- _("Unfinished character reference"));
- break;
- }
- }
-
- if (context->state == STATE_ERROR)
- {
- g_string_free (ucontext.str, TRUE);
- *unescaped = NULL;
- return FALSE;
- }
- else
- {
- *unescaped = ucontext.str;
- return TRUE;
- }
-}
-
-static inline gboolean
-advance_char (GMarkupParseContext *context)
-{
- context->iter = g_utf8_next_char (context->iter);
- context->char_number += 1;
-
- if (context->iter == context->current_text_end)
- {
- return FALSE;
- }
- else if (*context->iter == '\n')
- {
- context->line_number += 1;
- context->char_number = 1;
- }
-
- return TRUE;
-}
-
-static inline gboolean
-xml_isspace (char c)
-{
- return c == ' ' || c == '\t' || c == '\n' || c == '\r';
-}
-
-static void
-skip_spaces (GMarkupParseContext *context)
-{
- do
- {
- if (!xml_isspace (*context->iter))
- return;
- }
- while (advance_char (context));
-}
-
-static void
-advance_to_name_end (GMarkupParseContext *context)
-{
- do
- {
- if (!is_name_char (context->iter))
- return;
- }
- while (advance_char (context));
-}
-
-static void
-add_to_partial (GMarkupParseContext *context,
- const gchar *text_start,
- const gchar *text_end)
-{
- if (context->partial_chunk == NULL)
- context->partial_chunk = g_string_sized_new (text_end - text_start);
-
- if (text_start != text_end)
- g_string_append_len (context->partial_chunk, text_start,
- text_end - text_start);
-
- /* Invariant here that partial_chunk exists */
-}
-
-static void
-truncate_partial (GMarkupParseContext *context)
-{
- if (context->partial_chunk != NULL)
- {
- context->partial_chunk = g_string_truncate (context->partial_chunk, 0);
- }
-}
-
-static const gchar*
-current_element (GMarkupParseContext *context)
-{
- return context->tag_stack->data;
-}
-
-static void
-pop_subparser_stack (GMarkupParseContext *context)
-{
- GMarkupRecursionTracker *tracker;
-
- g_assert (context->subparser_stack);
-
- tracker = context->subparser_stack->data;
-
- context->awaiting_pop = TRUE;
- context->held_user_data = context->user_data;
-
- context->user_data = tracker->prev_user_data;
- context->parser = tracker->prev_parser;
- context->subparser_element = tracker->prev_element;
- g_slice_free (GMarkupRecursionTracker, tracker);
-
- context->subparser_stack = g_slist_delete_link (context->subparser_stack,
- context->subparser_stack);
-}
-
-static void
-possibly_finish_subparser (GMarkupParseContext *context)
-{
- if (current_element (context) == context->subparser_element)
- pop_subparser_stack (context);
-}
-
-static void
-ensure_no_outstanding_subparser (GMarkupParseContext *context)
-{
- if (context->awaiting_pop)
- g_critical ("During the first end_element call after invoking a "
- "subparser you must pop the subparser stack and handle "
- "the freeing of the subparser user_data. This can be "
- "done by calling the end function of the subparser. "
- "Very probably, your program just leaked memory.");
-
- /* let valgrind watch the pointer disappear... */
- context->held_user_data = NULL;
- context->awaiting_pop = FALSE;
-}
-
-static const gchar*
-current_attribute (GMarkupParseContext *context)
-{
- g_assert (context->cur_attr >= 0);
- return context->attr_names[context->cur_attr];
-}
-
-static void
-find_current_text_end (GMarkupParseContext *context)
-{
- /* This function must be safe (non-segfaulting) on invalid UTF8.
- * It assumes the string starts with a character start
- */
- const gchar *end = context->current_text + context->current_text_len;
- const gchar *p;
- const gchar *next;
-
- g_assert (context->current_text_len > 0);
-
- p = g_utf8_find_prev_char (context->current_text, end);
-
- g_assert (p != NULL); /* since current_text was a char start */
-
- /* p is now the start of the last character or character portion. */
- g_assert (p != end);
- next = g_utf8_next_char (p); /* this only touches *p, nothing beyond */
-
- if (next == end)
- {
- /* whole character */
- context->current_text_end = end;
- }
- else
- {
- /* portion */
- context->leftover_char_portion = g_string_new_len (p, end - p);
- context->current_text_len -= (end - p);
- context->current_text_end = p;
- }
-}
-
-
-static void
-add_attribute (GMarkupParseContext *context, char *name)
-{
- if (context->cur_attr + 2 >= context->alloc_attrs)
- {
- context->alloc_attrs += 5; /* silly magic number */
- context->attr_names = g_realloc (context->attr_names, sizeof(char*)*context->alloc_attrs);
- context->attr_values = g_realloc (context->attr_values, sizeof(char*)*context->alloc_attrs);
- }
- context->cur_attr++;
- context->attr_names[context->cur_attr] = name;
- context->attr_values[context->cur_attr] = NULL;
- context->attr_names[context->cur_attr+1] = NULL;
- context->attr_values[context->cur_attr+1] = NULL;
-}
-
-/**
- * g_markup_parse_context_parse:
- * @context: a #GMarkupParseContext
- * @text: chunk of text to parse
- * @text_len: length of @text in bytes
- * @error: return location for a #GError
- *
- * Feed some data to the #GMarkupParseContext. The data need not
- * be valid UTF-8; an error will be signaled if it's invalid.
- * The data need not be an entire document; you can feed a document
- * into the parser incrementally, via multiple calls to this function.
- * Typically, as you receive data from a network connection or file,
- * you feed each received chunk of data into this function, aborting
- * the process if an error occurs. Once an error is reported, no further
- * data may be fed to the #GMarkupParseContext; all errors are fatal.
- *
- * Return value: %FALSE if an error occurred, %TRUE on success
- **/
-gboolean
-g_markup_parse_context_parse (GMarkupParseContext *context,
- const gchar *text,
- gssize text_len,
- GError **error)
-{
- const gchar *first_invalid;
-
- g_return_val_if_fail (context != NULL, FALSE);
- g_return_val_if_fail (text != NULL, FALSE);
- g_return_val_if_fail (context->state != STATE_ERROR, FALSE);
- g_return_val_if_fail (!context->parsing, FALSE);
-
- if (text_len < 0)
- text_len = strlen (text);
-
- if (text_len == 0)
- return TRUE;
-
- context->parsing = TRUE;
-
- if (context->leftover_char_portion)
- {
- const gchar *first_char;
-
- if ((*text & 0xc0) != 0x80)
- first_char = text;
- else
- first_char = g_utf8_find_next_char (text, text + text_len);
-
- if (first_char)
- {
- /* leftover_char_portion was completed. Parse it. */
- GString *portion = context->leftover_char_portion;
-
- g_string_append_len (context->leftover_char_portion,
- text, first_char - text);
-
- /* hacks to allow recursion */
- context->parsing = FALSE;
- context->leftover_char_portion = NULL;
-
- if (!g_markup_parse_context_parse (context,
- portion->str, portion->len,
- error))
- {
- g_assert (context->state == STATE_ERROR);
- }
-
- g_string_free (portion, TRUE);
- context->parsing = TRUE;
-
- /* Skip the fraction of char that was in this text */
- text_len -= (first_char - text);
- text = first_char;
- }
- else
- {
- /* another little chunk of the leftover char; geez
- * someone is inefficient.
- */
- g_string_append_len (context->leftover_char_portion,
- text, text_len);
-
- if (context->leftover_char_portion->len > 7)
- {
- /* The leftover char portion is too big to be
- * a UTF-8 character
- */
- set_error_literal (context,
- error,
- G_MARKUP_ERROR_BAD_UTF8,
- _("Invalid UTF-8 encoded text - overlong sequence"));
- }
-
- goto finished;
- }
- }
-
- context->current_text = text;
- context->current_text_len = text_len;
- context->iter = context->current_text;
- context->start = context->iter;
-
- /* Nothing left after finishing the leftover char, or nothing
- * passed in to begin with.
- */
- if (context->current_text_len == 0)
- goto finished;
-
- /* find_current_text_end () assumes the string starts at
- * a character start, so we need to validate at least
- * that much. It doesn't assume any following bytes
- * are valid.
- */
- if ((*context->current_text & 0xc0) == 0x80) /* not a char start */
- {
- set_error_literal (context,
- error,
- G_MARKUP_ERROR_BAD_UTF8,
- _("Invalid UTF-8 encoded text - not a start char"));
- goto finished;
- }
-
- /* Initialize context->current_text_end, possibly adjusting
- * current_text_len, and add any leftover char portion
- */
- find_current_text_end (context);
-
- /* Validate UTF8 (must be done after we find the end, since
- * we could have a trailing incomplete char)
- */
- if (!g_utf8_validate (context->current_text,
- context->current_text_len,
- &first_invalid))
- {
- gint newlines = 0;
- const gchar *p, *q;
- gchar *current_text_dup;
-
- q = p = context->current_text;
- while (p != first_invalid)
- {
- if (*p == '\n')
- {
- ++newlines;
- q = p + 1;
- context->char_number = 1;
- }
- ++p;
- }
-
- context->line_number += newlines;
- context->char_number += g_utf8_strlen (q, first_invalid - q);
-
- current_text_dup = g_strndup (context->current_text, context->current_text_len);
- set_error (context,
- error,
- G_MARKUP_ERROR_BAD_UTF8,
- _("Invalid UTF-8 encoded text - not valid '%s'"),
- current_text_dup);
- g_free (current_text_dup);
- goto finished;
- }
-
- while (context->iter != context->current_text_end)
- {
- switch (context->state)
- {
- case STATE_START:
- /* Possible next state: AFTER_OPEN_ANGLE */
-
- g_assert (context->tag_stack == NULL);
-
- /* whitespace is ignored outside of any elements */
- skip_spaces (context);
-
- if (context->iter != context->current_text_end)
- {
- if (*context->iter == '<')
- {
- /* Move after the open angle */
- advance_char (context);
-
- context->state = STATE_AFTER_OPEN_ANGLE;
-
- /* this could start a passthrough */
- context->start = context->iter;
-
- /* document is now non-empty */
- context->document_empty = FALSE;
- }
- else
- {
- set_error_literal (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("Document must begin with an element (e.g. <book>)"));
- }
- }
- break;
-
- case STATE_AFTER_OPEN_ANGLE:
- /* Possible next states: INSIDE_OPEN_TAG_NAME,
- * AFTER_CLOSE_TAG_SLASH, INSIDE_PASSTHROUGH
- */
- if (*context->iter == '?' ||
- *context->iter == '!')
- {
- /* include < in the passthrough */
- const gchar *openangle = "<";
- add_to_partial (context, openangle, openangle + 1);
- context->start = context->iter;
- context->balance = 1;
- context->state = STATE_INSIDE_PASSTHROUGH;
- }
- else if (*context->iter == '/')
- {
- /* move after it */
- advance_char (context);
-
- context->state = STATE_AFTER_CLOSE_TAG_SLASH;
- }
- else if (is_name_start_char (context->iter))
- {
- context->state = STATE_INSIDE_OPEN_TAG_NAME;
-
- /* start of tag name */
- context->start = context->iter;
- }
- else
- {
- gchar buf[8];
-
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("'%s' is not a valid character following "
- "a '<' character; it may not begin an "
- "element name"),
- utf8_str (context->iter, buf));
- }
- break;
-
- /* The AFTER_CLOSE_ANGLE state is actually sort of
- * broken, because it doesn't correspond to a range
- * of characters in the input stream as the others do,
- * and thus makes things harder to conceptualize
- */
- case STATE_AFTER_CLOSE_ANGLE:
- /* Possible next states: INSIDE_TEXT, STATE_START */
- if (context->tag_stack == NULL)
- {
- context->start = NULL;
- context->state = STATE_START;
- }
- else
- {
- context->start = context->iter;
- context->state = STATE_INSIDE_TEXT;
- }
- break;
-
- case STATE_AFTER_ELISION_SLASH:
- /* Possible next state: AFTER_CLOSE_ANGLE */
-
- {
- /* We need to pop the tag stack and call the end_element
- * function, since this is the close tag
- */
- GError *tmp_error = NULL;
-
- g_assert (context->tag_stack != NULL);
-
- possibly_finish_subparser (context);
-
- tmp_error = NULL;
- if (context->parser->end_element)
- (* context->parser->end_element) (context,
- context->tag_stack->data,
- context->user_data,
- &tmp_error);
-
- ensure_no_outstanding_subparser (context);
-
- if (tmp_error)
- {
- mark_error (context, tmp_error);
- g_propagate_error (error, tmp_error);
- }
- else
- {
- if (*context->iter == '>')
- {
- /* move after the close angle */
- advance_char (context);
- context->state = STATE_AFTER_CLOSE_ANGLE;
- }
- else
- {
- gchar buf[8];
-
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("Odd character '%s', expected a '>' character "
- "to end the empty-element tag '%s'"),
- utf8_str (context->iter, buf),
- current_element (context));
- }
- }
-
- g_free (context->tag_stack->data);
- context->tag_stack = g_slist_delete_link (context->tag_stack,
- context->tag_stack);
- }
- break;
-
- case STATE_INSIDE_OPEN_TAG_NAME:
- /* Possible next states: BETWEEN_ATTRIBUTES */
-
- /* if there's a partial chunk then it's the first part of the
- * tag name. If there's a context->start then it's the start
- * of the tag name in current_text, the partial chunk goes
- * before that start though.
- */
- advance_to_name_end (context);
-
- if (context->iter == context->current_text_end)
- {
- /* The name hasn't necessarily ended. Merge with
- * partial chunk, leave state unchanged.
- */
- add_to_partial (context, context->start, context->iter);
- }
- else
- {
- /* The name has ended. Combine it with the partial chunk
- * if any; push it on the stack; enter next state.
- */
- add_to_partial (context, context->start, context->iter);
- context->tag_stack =
- g_slist_prepend (context->tag_stack,
- g_string_free (context->partial_chunk,
- FALSE));
-
- context->partial_chunk = NULL;
-
- context->state = STATE_BETWEEN_ATTRIBUTES;
- context->start = NULL;
- }
- break;
-
- case STATE_INSIDE_ATTRIBUTE_NAME:
- /* Possible next states: AFTER_ATTRIBUTE_NAME */
-
- advance_to_name_end (context);
- add_to_partial (context, context->start, context->iter);
-
- /* read the full name, if we enter the equals sign state
- * then add the attribute to the list (without the value),
- * otherwise store a partial chunk to be prepended later.
- */
- if (context->iter != context->current_text_end)
- context->state = STATE_AFTER_ATTRIBUTE_NAME;
- break;
-
- case STATE_AFTER_ATTRIBUTE_NAME:
- /* Possible next states: AFTER_ATTRIBUTE_EQUALS_SIGN */
-
- skip_spaces (context);
-
- if (context->iter != context->current_text_end)
- {
- /* The name has ended. Combine it with the partial chunk
- * if any; push it on the stack; enter next state.
- */
- add_attribute (context, g_string_free (context->partial_chunk, FALSE));
-
- context->partial_chunk = NULL;
- context->start = NULL;
-
- if (*context->iter == '=')
- {
- advance_char (context);
- context->state = STATE_AFTER_ATTRIBUTE_EQUALS_SIGN;
- }
- else
- {
- gchar buf[8];
-
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("Odd character '%s', expected a '=' after "
- "attribute name '%s' of element '%s'"),
- utf8_str (context->iter, buf),
- current_attribute (context),
- current_element (context));
-
- }
- }
- break;
-
- case STATE_BETWEEN_ATTRIBUTES:
- /* Possible next states: AFTER_CLOSE_ANGLE,
- * AFTER_ELISION_SLASH, INSIDE_ATTRIBUTE_NAME
- */
- skip_spaces (context);
-
- if (context->iter != context->current_text_end)
- {
- if (*context->iter == '/')
- {
- advance_char (context);
- context->state = STATE_AFTER_ELISION_SLASH;
- }
- else if (*context->iter == '>')
- {
-
- advance_char (context);
- context->state = STATE_AFTER_CLOSE_ANGLE;
- }
- else if (is_name_start_char (context->iter))
- {
- context->state = STATE_INSIDE_ATTRIBUTE_NAME;
- /* start of attribute name */
- context->start = context->iter;
- }
- else
- {
- gchar buf[8];
-
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("Odd character '%s', expected a '>' or '/' "
- "character to end the start tag of "
- "element '%s', or optionally an attribute; "
- "perhaps you used an invalid character in "
- "an attribute name"),
- utf8_str (context->iter, buf),
- current_element (context));
- }
-
- /* If we're done with attributes, invoke
- * the start_element callback
- */
- if (context->state == STATE_AFTER_ELISION_SLASH ||
- context->state == STATE_AFTER_CLOSE_ANGLE)
- {
- const gchar *start_name;
- /* Ugly, but the current code expects an empty array instead of NULL */
- const gchar *empty = NULL;
- const gchar **attr_names = &empty;
- const gchar **attr_values = &empty;
- GError *tmp_error;
-
- /* Call user callback for element start */
- start_name = current_element (context);
-
- if (context->cur_attr >= 0)
- {
- attr_names = (const gchar**)context->attr_names;
- attr_values = (const gchar**)context->attr_values;
- }
-
- tmp_error = NULL;
- if (context->parser->start_element)
- (* context->parser->start_element) (context,
- start_name,
- (const gchar **)attr_names,
- (const gchar **)attr_values,
- context->user_data,
- &tmp_error);
-
- /* Go ahead and free the attributes. */
- for (; context->cur_attr >= 0; context->cur_attr--)
- {
- int pos = context->cur_attr;
- g_free (context->attr_names[pos]);
- g_free (context->attr_values[pos]);
- context->attr_names[pos] = context->attr_values[pos] = NULL;
- }
- g_assert (context->cur_attr == -1);
- g_assert (context->attr_names == NULL ||
- context->attr_names[0] == NULL);
- g_assert (context->attr_values == NULL ||
- context->attr_values[0] == NULL);
-
- if (tmp_error != NULL)
- propagate_error (context, error, tmp_error);
- }
- }
- break;
-
- case STATE_AFTER_ATTRIBUTE_EQUALS_SIGN:
- /* Possible next state: INSIDE_ATTRIBUTE_VALUE_[SQ/DQ] */
-
- skip_spaces (context);
-
- if (context->iter != context->current_text_end)
- {
- if (*context->iter == '"')
- {
- advance_char (context);
- context->state = STATE_INSIDE_ATTRIBUTE_VALUE_DQ;
- context->start = context->iter;
- }
- else if (*context->iter == '\'')
- {
- advance_char (context);
- context->state = STATE_INSIDE_ATTRIBUTE_VALUE_SQ;
- context->start = context->iter;
- }
- else
- {
- gchar buf[8];
-
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("Odd character '%s', expected an open quote mark "
- "after the equals sign when giving value for "
- "attribute '%s' of element '%s'"),
- utf8_str (context->iter, buf),
- current_attribute (context),
- current_element (context));
- }
- }
- break;
-
- case STATE_INSIDE_ATTRIBUTE_VALUE_SQ:
- case STATE_INSIDE_ATTRIBUTE_VALUE_DQ:
- /* Possible next states: BETWEEN_ATTRIBUTES */
- {
- gchar delim;
-
- if (context->state == STATE_INSIDE_ATTRIBUTE_VALUE_SQ)
- {
- delim = '\'';
- }
- else
- {
- delim = '"';
- }
-
- do
- {
- if (*context->iter == delim)
- break;
- }
- while (advance_char (context));
- }
- if (context->iter == context->current_text_end)
- {
- /* The value hasn't necessarily ended. Merge with
- * partial chunk, leave state unchanged.
- */
- add_to_partial (context, context->start, context->iter);
- }
- else
- {
- /* The value has ended at the quote mark. Combine it
- * with the partial chunk if any; set it for the current
- * attribute.
- */
- GString *unescaped;
-
- add_to_partial (context, context->start, context->iter);
-
- g_assert (context->cur_attr >= 0);
-
- if (unescape_text (context,
- context->partial_chunk->str,
- context->partial_chunk->str +
- context->partial_chunk->len,
- &unescaped,
- error))
- {
- /* success, advance past quote and set state. */
- context->attr_values[context->cur_attr] = g_string_free (unescaped, FALSE);
- advance_char (context);
- context->state = STATE_BETWEEN_ATTRIBUTES;
- context->start = NULL;
- }
-
- truncate_partial (context);
- }
- break;
-
- case STATE_INSIDE_TEXT:
- /* Possible next states: AFTER_OPEN_ANGLE */
- do
- {
- if (*context->iter == '<')
- break;
- }
- while (advance_char (context));
-
- /* The text hasn't necessarily ended. Merge with
- * partial chunk, leave state unchanged.
- */
-
- add_to_partial (context, context->start, context->iter);
-
- if (context->iter != context->current_text_end)
- {
- GString *unescaped = NULL;
-
- /* The text has ended at the open angle. Call the text
- * callback.
- */
-
- if (unescape_text (context,
- context->partial_chunk->str,
- context->partial_chunk->str +
- context->partial_chunk->len,
- &unescaped,
- error))
- {
- GError *tmp_error = NULL;
-
- if (context->parser->text)
- (*context->parser->text) (context,
- unescaped->str,
- unescaped->len,
- context->user_data,
- &tmp_error);
-
- g_string_free (unescaped, TRUE);
-
- if (tmp_error == NULL)
- {
- /* advance past open angle and set state. */
- advance_char (context);
- context->state = STATE_AFTER_OPEN_ANGLE;
- /* could begin a passthrough */
- context->start = context->iter;
- }
- else
- propagate_error (context, error, tmp_error);
- }
-
- truncate_partial (context);
- }
- break;
-
- case STATE_AFTER_CLOSE_TAG_SLASH:
- /* Possible next state: INSIDE_CLOSE_TAG_NAME */
- if (is_name_start_char (context->iter))
- {
- context->state = STATE_INSIDE_CLOSE_TAG_NAME;
-
- /* start of tag name */
- context->start = context->iter;
- }
- else
- {
- gchar buf[8];
-
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("'%s' is not a valid character following "
- "the characters '</'; '%s' may not begin an "
- "element name"),
- utf8_str (context->iter, buf),
- utf8_str (context->iter, buf));
- }
- break;
-
- case STATE_INSIDE_CLOSE_TAG_NAME:
- /* Possible next state: AFTER_CLOSE_TAG_NAME */
- advance_to_name_end (context);
- add_to_partial (context, context->start, context->iter);
-
- if (context->iter != context->current_text_end)
- context->state = STATE_AFTER_CLOSE_TAG_NAME;
- break;
-
- case STATE_AFTER_CLOSE_TAG_NAME:
- /* Possible next state: AFTER_CLOSE_TAG_SLASH */
-
- skip_spaces (context);
-
- if (context->iter != context->current_text_end)
- {
- gchar *close_name;
-
- /* The name has ended. Combine it with the partial chunk
- * if any; check that it matches stack top and pop
- * stack; invoke proper callback; enter next state.
- */
- close_name = g_string_free (context->partial_chunk, FALSE);
- context->partial_chunk = NULL;
-
- if (*context->iter != '>')
- {
- gchar buf[8];
-
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("'%s' is not a valid character following "
- "the close element name '%s'; the allowed "
- "character is '>'"),
- utf8_str (context->iter, buf),
- close_name);
- }
- else if (context->tag_stack == NULL)
- {
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("Element '%s' was closed, no element "
- "is currently open"),
- close_name);
- }
- else if (strcmp (close_name, current_element (context)) != 0)
- {
- set_error (context,
- error,
- G_MARKUP_ERROR_PARSE,
- _("Element '%s' was closed, but the currently "
- "open element is '%s'"),
- close_name,
- current_element (context));
- }
- else
- {
- GError *tmp_error;
- advance_char (context);
- context->state = STATE_AFTER_CLOSE_ANGLE;
- context->start = NULL;
-
- possibly_finish_subparser (context);
-
- /* call the end_element callback */
- tmp_error = NULL;
- if (context->parser->end_element)
- (* context->parser->end_element) (context,
- close_name,
- context->user_data,
- &tmp_error);
-
- ensure_no_outstanding_subparser (context);
-
- /* Pop the tag stack */
- g_free (context->tag_stack->data);
- context->tag_stack = g_slist_delete_link (context->tag_stack,
- context->tag_stack);
-
- if (tmp_error)
- propagate_error (context, error, tmp_error);
- }
-
- g_free (close_name);
- }
- break;
-
- case STATE_INSIDE_PASSTHROUGH:
- /* Possible next state: AFTER_CLOSE_ANGLE */
- do
- {
- if (*context->iter == '<')
- context->balance++;
- if (*context->iter == '>')
- {
- gchar *str;
- gsize len;
-
- context->balance--;
- add_to_partial (context, context->start, context->iter);
- context->start = context->iter;
-
- str = context->partial_chunk->str;
- len = context->partial_chunk->len;
-
- if (str[1] == '?' && str[len - 1] == '?')
- break;
- if (strncmp (str, "<!--", 4) == 0 &&
- strcmp (str + len - 2, "--") == 0)
- break;
- if (strncmp (str, "<![CDATA[", 9) == 0 &&
- strcmp (str + len - 2, "]]") == 0)
- break;
- if (strncmp (str, "<!DOCTYPE", 9) == 0 &&
- context->balance == 0)
- break;
- }
- }
- while (advance_char (context));
-
- if (context->iter == context->current_text_end)
- {
- /* The passthrough hasn't necessarily ended. Merge with
- * partial chunk, leave state unchanged.
- */
- add_to_partial (context, context->start, context->iter);
- }
- else
- {
- /* The passthrough has ended at the close angle. Combine
- * it with the partial chunk if any. Call the passthrough
- * callback. Note that the open/close angles are
- * included in the text of the passthrough.
- */
- GError *tmp_error = NULL;
-
- advance_char (context); /* advance past close angle */
- add_to_partial (context, context->start, context->iter);
-
- if (context->flags & G_MARKUP_TREAT_CDATA_AS_TEXT &&
- strncmp (context->partial_chunk->str, "<![CDATA[", 9) == 0)
- {
- if (context->parser->text)
- (*context->parser->text) (context,
- context->partial_chunk->str + 9,
- context->partial_chunk->len - 12,
- context->user_data,
- &tmp_error);
- }
- else if (context->parser->passthrough)
- (*context->parser->passthrough) (context,
- context->partial_chunk->str,
- context->partial_chunk->len,
- context->user_data,
- &tmp_error);
-
- truncate_partial (context);
-
- if (tmp_error == NULL)
- {
- context->state = STATE_AFTER_CLOSE_ANGLE;
- context->start = context->iter; /* could begin text */
- }
- else
- propagate_error (context, error, tmp_error);
- }
- break;
-
- case STATE_ERROR:
- goto finished;
- break;
-
- default:
- g_assert_not_reached ();
- break;
- }
- }
-
- finished:
- context->parsing = FALSE;
-
- return context->state != STATE_ERROR;
-}
-
-/**
- * g_markup_parse_context_end_parse:
- * @context: a #GMarkupParseContext
- * @error: return location for a #GError
- *
- * Signals to the #GMarkupParseContext that all data has been
- * fed into the parse context with g_markup_parse_context_parse().
- * This function reports an error if the document isn't complete,
- * for example if elements are still open.
- *
- * Return value: %TRUE on success, %FALSE if an error was set
- **/
-gboolean
-g_markup_parse_context_end_parse (GMarkupParseContext *context,
- GError **error)
-{
- g_return_val_if_fail (context != NULL, FALSE);
- g_return_val_if_fail (!context->parsing, FALSE);
- g_return_val_if_fail (context->state != STATE_ERROR, FALSE);
-
- if (context->partial_chunk != NULL)
- {
- g_string_free (context->partial_chunk, TRUE);
- context->partial_chunk = NULL;
- }
-
- if (context->document_empty)
- {
- set_error_literal (context, error, G_MARKUP_ERROR_EMPTY,
- _("Document was empty or contained only whitespace"));
- return FALSE;
- }
-
- context->parsing = TRUE;
-
- switch (context->state)
- {
- case STATE_START:
- /* Nothing to do */
- break;
-
- case STATE_AFTER_OPEN_ANGLE:
- set_error_literal (context, error, G_MARKUP_ERROR_PARSE,
- _("Document ended unexpectedly just after an open angle bracket '<'"));
- break;
-
- case STATE_AFTER_CLOSE_ANGLE:
- if (context->tag_stack != NULL)
- {
- /* Error message the same as for INSIDE_TEXT */
- set_error (context, error, G_MARKUP_ERROR_PARSE,
- _("Document ended unexpectedly with elements still open - "
- "'%s' was the last element opened"),
- current_element (context));
- }
- break;
-
- case STATE_AFTER_ELISION_SLASH:
- set_error (context, error, G_MARKUP_ERROR_PARSE,
- _("Document ended unexpectedly, expected to see a close angle "
- "bracket ending the tag <%s/>"), current_element (context));
- break;
-
- case STATE_INSIDE_OPEN_TAG_NAME:
- set_error_literal (context, error, G_MARKUP_ERROR_PARSE,
- _("Document ended unexpectedly inside an element name"));
- break;
-
- case STATE_INSIDE_ATTRIBUTE_NAME:
- case STATE_AFTER_ATTRIBUTE_NAME:
- set_error_literal (context, error, G_MARKUP_ERROR_PARSE,
- _("Document ended unexpectedly inside an attribute name"));
- break;
-
- case STATE_BETWEEN_ATTRIBUTES:
- set_error_literal (context, error, G_MARKUP_ERROR_PARSE,
- _("Document ended unexpectedly inside an element-opening "
- "tag."));
- break;
-
- case STATE_AFTER_ATTRIBUTE_EQUALS_SIGN:
- set_error_literal (context, error, G_MARKUP_ERROR_PARSE,
- _("Document ended unexpectedly after the equals sign "
- "following an attribute name; no attribute value"));
- break;
-
- case STATE_INSIDE_ATTRIBUTE_VALUE_SQ:
- case STATE_INSIDE_ATTRIBUTE_VALUE_DQ:
- set_error_literal (context, error, G_MARKUP_ERROR_PARSE,
- _("Document ended unexpectedly while inside an attribute "
- "value"));
- break;
-
- case STATE_INSIDE_TEXT:
- g_assert (context->tag_stack != NULL);
- set_error (context, error, G_MARKUP_ERROR_PARSE,
- _("Document ended unexpectedly with elements still open - "
- "'%s' was the last element opened"),
- current_element (context));
- break;
-
- case STATE_AFTER_CLOSE_TAG_SLASH:
- case STATE_INSIDE_CLOSE_TAG_NAME:
- case STATE_AFTER_CLOSE_TAG_NAME:
- set_error (context, error, G_MARKUP_ERROR_PARSE,
- _("Document ended unexpectedly inside the close tag for "
- "element '%s'"), current_element (context));
- break;
-
- case STATE_INSIDE_PASSTHROUGH:
- set_error_literal (context, error, G_MARKUP_ERROR_PARSE,
- _("Document ended unexpectedly inside a comment or "
- "processing instruction"));
- break;
-
- case STATE_ERROR:
- default:
- g_assert_not_reached ();
- break;
- }
-
- context->parsing = FALSE;
-
- return context->state != STATE_ERROR;
-}
-
-/**
- * g_markup_parse_context_get_element:
- * @context: a #GMarkupParseContext
- * @returns: the name of the currently open element, or %NULL
- *
- * Retrieves the name of the currently open element.
- *
- * If called from the start_element or end_element handlers this will
- * give the element_name as passed to those functions. For the parent
- * elements, see g_markup_parse_context_get_element_stack().
- *
- * Since: 2.2
- **/
-G_CONST_RETURN gchar *
-g_markup_parse_context_get_element (GMarkupParseContext *context)
-{
- g_return_val_if_fail (context != NULL, NULL);
-
- if (context->tag_stack == NULL)
- return NULL;
- else
- return current_element (context);
-}
-
-/**
- * g_markup_parse_context_get_element_stack:
- * @context: a #GMarkupParseContext
- *
- * Retrieves the element stack from the internal state of the parser.
- * The returned #GSList is a list of strings where the first item is
- * the currently open tag (as would be returned by
- * g_markup_parse_context_get_element()) and the next item is its
- * immediate parent.
- *
- * This function is intended to be used in the start_element and
- * end_element handlers where g_markup_parse_context_get_element()
- * would merely return the name of the element that is being
- * processed.
- *
- * Returns: the element stack, which must not be modified
- *
- * Since: 2.16
- **/
-G_CONST_RETURN GSList *
-g_markup_parse_context_get_element_stack (GMarkupParseContext *context)
-{
- g_return_val_if_fail (context != NULL, NULL);
-
- return context->tag_stack;
-}
-
-/**
- * g_markup_parse_context_get_position:
- * @context: a #GMarkupParseContext
- * @line_number: return location for a line number, or %NULL
- * @char_number: return location for a char-on-line number, or %NULL
- *
- * Retrieves the current line number and the number of the character on
- * that line. Intended for use in error messages; there are no strict
- * semantics for what constitutes the "current" line number other than
- * "the best number we could come up with for error messages."
- *
- **/
-void
-g_markup_parse_context_get_position (GMarkupParseContext *context,
- gint *line_number,
- gint *char_number)
-{
- g_return_if_fail (context != NULL);
-
- if (line_number)
- *line_number = context->line_number;
-
- if (char_number)
- *char_number = context->char_number;
-}
-
-/**
- * g_markup_parse_context_get_user_data:
- * @context: a #GMarkupParseContext
- *
- * Returns the user_data associated with @context. This will either
- * be the user_data that was provided to g_markup_parse_context_new()
- * or to the most recent call of g_markup_parse_context_push().
- *
- * Returns: the provided user_data. The returned data belongs to
- * the markup context and will be freed when g_markup_context_free()
- * is called.
- *
- * Since: 2.18
- **/
-gpointer
-g_markup_parse_context_get_user_data (GMarkupParseContext *context)
-{
- return context->user_data;
-}
-
-/**
- * g_markup_parse_context_push:
- * @context: a #GMarkupParseContext
- * @parser: a #GMarkupParser
- * @user_data: user data to pass to #GMarkupParser functions
- *
- * Temporarily redirects markup data to a sub-parser.
- *
- * This function may only be called from the start_element handler of
- * a #GMarkupParser. It must be matched with a corresponding call to
- * g_markup_parse_context_pop() in the matching end_element handler
- * (except in the case that the parser aborts due to an error).
- *
- * All tags, text and other data between the matching tags is
- * redirected to the subparser given by @parser. @user_data is used
- * as the user_data for that parser. @user_data is also passed to the
- * error callback in the event that an error occurs. This includes
- * errors that occur in subparsers of the subparser.
- *
- * The end tag matching the start tag for which this call was made is
- * handled by the previous parser (which is given its own user_data)
- * which is why g_markup_parse_context_pop() is provided to allow "one
- * last access" to the @user_data provided to this function. In the
- * case of error, the @user_data provided here is passed directly to
- * the error callback of the subparser and g_markup_parse_context()
- * should not be called. In either case, if @user_data was allocated
- * then it ought to be freed from both of these locations.
- *
- * This function is not intended to be directly called by users
- * interested in invoking subparsers. Instead, it is intended to be
- * used by the subparsers themselves to implement a higher-level
- * interface.
- *
- * As an example, see the following implementation of a simple
- * parser that counts the number of tags encountered.
- *
- * |[
- * typedef struct
- * {
- * gint tag_count;
- * } CounterData;
- *
- * static void
- * counter_start_element (GMarkupParseContext *context,
- * const gchar *element_name,
- * const gchar **attribute_names,
- * const gchar **attribute_values,
- * gpointer user_data,
- * GError **error)
- * {
- * CounterData *data = user_data;
- *
- * data->tag_count++;
- * }
- *
- * static void
- * counter_error (GMarkupParseContext *context,
- * GError *error,
- * gpointer user_data)
- * {
- * CounterData *data = user_data;
- *
- * g_slice_free (CounterData, data);
- * }
- *
- * static GMarkupParser counter_subparser =
- * {
- * counter_start_element,
- * NULL,
- * NULL,
- * NULL,
- * counter_error
- * };
- * ]|
- *
- * In order to allow this parser to be easily used as a subparser, the
- * following interface is provided:
- *
- * |[
- * void
- * start_counting (GMarkupParseContext *context)
- * {
- * CounterData *data = g_slice_new (CounterData);
- *
- * data->tag_count = 0;
- * g_markup_parse_context_push (context, &counter_subparser, data);
- * }
- *
- * gint
- * end_counting (GMarkupParseContext *context)
- * {
- * CounterData *data = g_markup_parse_context_pop (context);
- * int result;
- *
- * result = data->tag_count;
- * g_slice_free (CounterData, data);
- *
- * return result;
- * }
- * ]|
- *
- * The subparser would then be used as follows:
- *
- * |[
- * static void start_element (context, element_name, ...)
- * {
- * if (strcmp (element_name, "count-these") == 0)
- * start_counting (context);
- *
- * /&ast; else, handle other tags... &ast;/
- * }
- *
- * static void end_element (context, element_name, ...)
- * {
- * if (strcmp (element_name, "count-these") == 0)
- * g_print ("Counted %d tags\n", end_counting (context));
- *
- * /&ast; else, handle other tags... &ast;/
- * }
- * ]|
- *
- * Since: 2.18
- **/
-void
-g_markup_parse_context_push (GMarkupParseContext *context,
- GMarkupParser *parser,
- gpointer user_data)
-{
- GMarkupRecursionTracker *tracker;
-
- tracker = g_slice_new (GMarkupRecursionTracker);
- tracker->prev_element = context->subparser_element;
- tracker->prev_parser = context->parser;
- tracker->prev_user_data = context->user_data;
-
- context->subparser_element = current_element (context);
- context->parser = parser;
- context->user_data = user_data;
-
- context->subparser_stack = g_slist_prepend (context->subparser_stack,
- tracker);
-}
-
-/**
- * g_markup_parse_context_pop:
- * @context: a #GMarkupParseContext
- *
- * Completes the process of a temporary sub-parser redirection.
- *
- * This function exists to collect the user_data allocated by a
- * matching call to g_markup_parse_context_push(). It must be called
- * in the end_element handler corresponding to the start_element
- * handler during which g_markup_parse_context_push() was called. You
- * must not call this function from the error callback -- the
- * @user_data is provided directly to the callback in that case.
- *
- * This function is not intended to be directly called by users
- * interested in invoking subparsers. Instead, it is intended to be
- * used by the subparsers themselves to implement a higher-level
- * interface.
- *
- * Returns: the user_data passed to g_markup_parse_context_push().
- *
- * Since: 2.18
- **/
-gpointer
-g_markup_parse_context_pop (GMarkupParseContext *context)
-{
- gpointer user_data;
-
- if (!context->awaiting_pop)
- possibly_finish_subparser (context);
-
- g_assert (context->awaiting_pop);
-
- context->awaiting_pop = FALSE;
-
- /* valgrind friendliness */
- user_data = context->held_user_data;
- context->held_user_data = NULL;
-
- return user_data;
-}
-
-static void
-append_escaped_text (GString *str,
- const gchar *text,
- gssize length)
-{
- const gchar *p;
- const gchar *end;
- gunichar c;
-
- p = text;
- end = text + length;
-
- while (p != end)
- {
- const gchar *next;
- next = g_utf8_next_char (p);
-
- switch (*p)
- {
- case '&':
- g_string_append (str, "&amp;");
- break;
-
- case '<':
- g_string_append (str, "&lt;");
- break;
-
- case '>':
- g_string_append (str, "&gt;");
- break;
-
- case '\'':
- g_string_append (str, "&apos;");
- break;
-
- case '"':
- g_string_append (str, "&quot;");
- break;
-
- default:
- c = g_utf8_get_char (p);
- if ((0x1 <= c && c <= 0x8) ||
- (0xb <= c && c <= 0xc) ||
- (0xe <= c && c <= 0x1f) ||
- (0x7f <= c && c <= 0x84) ||
- (0x86 <= c && c <= 0x9f))
- g_string_append_printf (str, "&#x%x;", c);
- else
- g_string_append_len (str, p, next - p);
- break;
- }
-
- p = next;
- }
-}
-
-/**
- * g_markup_escape_text:
- * @text: some valid UTF-8 text
- * @length: length of @text in bytes, or -1 if the text is nul-terminated
- *
- * Escapes text so that the markup parser will parse it verbatim.
- * Less than, greater than, ampersand, etc. are replaced with the
- * corresponding entities. This function would typically be used
- * when writing out a file to be parsed with the markup parser.
- *
- * Note that this function doesn't protect whitespace and line endings
- * from being processed according to the XML rules for normalization
- * of line endings and attribute values.
- *
- * Note also that if given a string containing them, this function
- * will produce character references in the range of &amp;#x1; ..
- * &amp;#x1f; for all control sequences except for tabstop, newline
- * and carriage return. The character references in this range are
- * not valid XML 1.0, but they are valid XML 1.1 and will be accepted
- * by the GMarkup parser.
- *
- * Return value: a newly allocated string with the escaped text
- **/
-gchar*
-g_markup_escape_text (const gchar *text,
- gssize length)
-{
- GString *str;
-
- g_return_val_if_fail (text != NULL, NULL);
-
- if (length < 0)
- length = strlen (text);
-
- /* prealloc at least as long as original text */
- str = g_string_sized_new (length);
- append_escaped_text (str, text, length);
-
- return g_string_free (str, FALSE);
-}
-
-/**
- * find_conversion:
- * @format: a printf-style format string
- * @after: location to store a pointer to the character after
- * the returned conversion. On a %NULL return, returns the
- * pointer to the trailing NUL in the string
- *
- * Find the next conversion in a printf-style format string.
- * Partially based on code from printf-parser.c,
- * Copyright (C) 1999-2000, 2002-2003 Free Software Foundation, Inc.
- *
- * Return value: pointer to the next conversion in @format,
- * or %NULL, if none.
- **/
-static const char *
-find_conversion (const char *format,
- const char **after)
-{
- const char *start = format;
- const char *cp;
-
- while (*start != '\0' && *start != '%')
- start++;
-
- if (*start == '\0')
- {
- *after = start;
- return NULL;
- }
-
- cp = start + 1;
-
- if (*cp == '\0')
- {
- *after = cp;
- return NULL;
- }
-
- /* Test for positional argument. */
- if (*cp >= '0' && *cp <= '9')
- {
- const char *np;
-
- for (np = cp; *np >= '0' && *np <= '9'; np++)
- ;
- if (*np == '$')
- cp = np + 1;
- }
-
- /* Skip the flags. */
- for (;;)
- {
- if (*cp == '\'' ||
- *cp == '-' ||
- *cp == '+' ||
- *cp == ' ' ||
- *cp == '#' ||
- *cp == '0')
- cp++;
- else
- break;
- }
-
- /* Skip the field width. */
- if (*cp == '*')
- {
- cp++;
-
- /* Test for positional argument. */
- if (*cp >= '0' && *cp <= '9')
- {
- const char *np;
-
- for (np = cp; *np >= '0' && *np <= '9'; np++)
- ;
- if (*np == '$')
- cp = np + 1;
- }
- }
- else
- {
- for (; *cp >= '0' && *cp <= '9'; cp++)
- ;
- }
-
- /* Skip the precision. */
- if (*cp == '.')
- {
- cp++;
- if (*cp == '*')
- {
- /* Test for positional argument. */
- if (*cp >= '0' && *cp <= '9')
- {
- const char *np;
-
- for (np = cp; *np >= '0' && *np <= '9'; np++)
- ;
- if (*np == '$')
- cp = np + 1;
- }
- }
- else
- {
- for (; *cp >= '0' && *cp <= '9'; cp++)
- ;
- }
- }
-
- /* Skip argument type/size specifiers. */
- while (*cp == 'h' ||
- *cp == 'L' ||
- *cp == 'l' ||
- *cp == 'j' ||
- *cp == 'z' ||
- *cp == 'Z' ||
- *cp == 't')
- cp++;
-
- /* Skip the conversion character. */
- cp++;
-
- *after = cp;
- return start;
-}
-
-/**
- * g_markup_vprintf_escaped:
- * @format: printf() style format string
- * @args: variable argument list, similar to vprintf()
- *
- * Formats the data in @args according to @format, escaping
- * all string and character arguments in the fashion
- * of g_markup_escape_text(). See g_markup_printf_escaped().
- *
- * Return value: newly allocated result from formatting
- * operation. Free with g_free().
- *
- * Since: 2.4
- **/
-char *
-g_markup_vprintf_escaped (const char *format,
- va_list args)
-{
- GString *format1;
- GString *format2;
- GString *result = NULL;
- gchar *output1 = NULL;
- gchar *output2 = NULL;
- const char *p, *op1, *op2;
- va_list args2;
-
- /* The technique here, is that we make two format strings that
- * have the identical conversions in the identical order to the
- * original strings, but differ in the text in-between. We
- * then use the normal g_strdup_vprintf() to format the arguments
- * with the two new format strings. By comparing the results,
- * we can figure out what segments of the output come from
- * the the original format string, and what from the arguments,
- * and thus know what portions of the string to escape.
- *
- * For instance, for:
- *
- * g_markup_printf_escaped ("%s ate %d apples", "Susan & Fred", 5);
- *
- * We form the two format strings "%sX%dX" and %sY%sY". The results
- * of formatting with those two strings are
- *
- * "%sX%dX" => "Susan & FredX5X"
- * "%sY%dY" => "Susan & FredY5Y"
- *
- * To find the span of the first argument, we find the first position
- * where the two arguments differ, which tells us that the first
- * argument formatted to "Susan & Fred". We then escape that
- * to "Susan &amp; Fred" and join up with the intermediate portions
- * of the format string and the second argument to get
- * "Susan &amp; Fred ate 5 apples".
- */
-
- /* Create the two modified format strings
- */
- format1 = g_string_new (NULL);
- format2 = g_string_new (NULL);
- p = format;
- while (TRUE)
- {
- const char *after;
- const char *conv = find_conversion (p, &after);
- if (!conv)
- break;
-
- g_string_append_len (format1, conv, after - conv);
- g_string_append_c (format1, 'X');
- g_string_append_len (format2, conv, after - conv);
- g_string_append_c (format2, 'Y');
-
- p = after;
- }
-
- /* Use them to format the arguments
- */
- G_VA_COPY (args2, args);
-
- output1 = g_strdup_vprintf (format1->str, args);
- if (!output1)
- {
- va_end (args2);
- goto cleanup;
- }
-
- output2 = g_strdup_vprintf (format2->str, args2);
- va_end (args2);
- if (!output2)
- goto cleanup;
-
- result = g_string_new (NULL);
-
- /* Iterate through the original format string again,
- * copying the non-conversion portions and the escaped
- * converted arguments to the output string.
- */
- op1 = output1;
- op2 = output2;
- p = format;
- while (TRUE)
- {
- const char *after;
- const char *output_start;
- const char *conv = find_conversion (p, &after);
- char *escaped;
-
- if (!conv) /* The end, after points to the trailing \0 */
- {
- g_string_append_len (result, p, after - p);
- break;
- }
-
- g_string_append_len (result, p, conv - p);
- output_start = op1;
- while (*op1 == *op2)
- {
- op1++;
- op2++;
- }
-
- escaped = g_markup_escape_text (output_start, op1 - output_start);
- g_string_append (result, escaped);
- g_free (escaped);
-
- p = after;
- op1++;
- op2++;
- }
-
- cleanup:
- g_string_free (format1, TRUE);
- g_string_free (format2, TRUE);
- g_free (output1);
- g_free (output2);
-
- if (result)
- return g_string_free (result, FALSE);
- else
- return NULL;
-}
-
-/**
- * g_markup_printf_escaped:
- * @format: printf() style format string
- * @Varargs: the arguments to insert in the format string
- *
- * Formats arguments according to @format, escaping
- * all string and character arguments in the fashion
- * of g_markup_escape_text(). This is useful when you
- * want to insert literal strings into XML-style markup
- * output, without having to worry that the strings
- * might themselves contain markup.
- *
- * |[
- * const char *store = "Fortnum &amp; Mason";
- * const char *item = "Tea";
- * char *output;
- * &nbsp;
- * output = g_markup_printf_escaped ("&lt;purchase&gt;"
- * "&lt;store&gt;&percnt;s&lt;/store&gt;"
- * "&lt;item&gt;&percnt;s&lt;/item&gt;"
- * "&lt;/purchase&gt;",
- * store, item);
- * ]|
- *
- * Return value: newly allocated result from formatting
- * operation. Free with g_free().
- *
- * Since: 2.4
- **/
-char *
-g_markup_printf_escaped (const char *format, ...)
-{
- char *result;
- va_list args;
-
- va_start (args, format);
- result = g_markup_vprintf_escaped (format, args);
- va_end (args);
-
- return result;
-}
-
-static gboolean
-g_markup_parse_boolean (const char *string,
- gboolean *value)
-{
- char const * const falses[] = { "false", "f", "no", "n", "0" };
- char const * const trues[] = { "true", "t", "yes", "y", "1" };
- int i;
-
- for (i = 0; i < G_N_ELEMENTS (falses); i++)
- {
- if (g_ascii_strcasecmp (string, falses[i]) == 0)
- {
- if (value != NULL)
- *value = FALSE;
-
- return TRUE;
- }
- }
-
- for (i = 0; i < G_N_ELEMENTS (trues); i++)
- {
- if (g_ascii_strcasecmp (string, trues[i]) == 0)
- {
- if (value != NULL)
- *value = TRUE;
-
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/**
- * GMarkupCollectType:
- * @G_MARKUP_COLLECT_INVALID: used to terminate the list of attributes
- * to collect.
- * @G_MARKUP_COLLECT_STRING: collect the string pointer directly from
- * the attribute_values[] array. Expects a
- * parameter of type (const char **). If
- * %G_MARKUP_COLLECT_OPTIONAL is specified
- * and the attribute isn't present then the
- * pointer will be set to %NULL.
- * @G_MARKUP_COLLECT_STRDUP: as with %G_MARKUP_COLLECT_STRING, but
- * expects a paramter of type (char **) and
- * g_strdup()s the returned pointer. The
- * pointer must be freed with g_free().
- * @G_MARKUP_COLLECT_BOOLEAN: expects a parameter of type (gboolean *)
- * and parses the attribute value as a
- * boolean. Sets %FALSE if the attribute
- * isn't present. Valid boolean values
- * consist of (case insensitive) "false",
- * "f", "no", "n", "0" and "true", "t",
- * "yes", "y", "1".
- * @G_MARKUP_COLLECT_TRISTATE: as with %G_MARKUP_COLLECT_BOOLEAN, but
- * in the case of a missing attribute a
- * value is set that compares equal to
- * neither %FALSE nor %TRUE.
- * G_MARKUP_COLLECT_OPTIONAL is implied.
- * @G_MARKUP_COLLECT_OPTIONAL: can be bitwise ORed with the other
- * fields. If present, allows the
- * attribute not to appear. A default
- * value is set depending on what value
- * type is used.
- *
- * A mixed enumerated type and flags field. You must specify one type
- * (string, strdup, boolean, tristate). Additionally, you may
- * optionally bitwise OR the type with the flag
- * %G_MARKUP_COLLECT_OPTIONAL.
- *
- * It is likely that this enum will be extended in the future to
- * support other types.
- **/
-
-/**
- * g_markup_collect_attributes:
- * @element_name: the current tag name
- * @attribute_names: the attribute names
- * @attribute_values: the attribute values
- * @error: a pointer to a #GError or %NULL
- * @first_type: the #GMarkupCollectType of the
- * first attribute
- * @first_attr: the name of the first attribute
- * @...: a pointer to the storage location of the
- * first attribute (or %NULL), followed by
- * more types names and pointers, ending
- * with %G_MARKUP_COLLECT_INVALID.
- *
- * Collects the attributes of the element from the
- * data passed to the #GMarkupParser start_element
- * function, dealing with common error conditions
- * and supporting boolean values.
- *
- * This utility function is not required to write
- * a parser but can save a lot of typing.
- *
- * The @element_name, @attribute_names,
- * @attribute_values and @error parameters passed
- * to the start_element callback should be passed
- * unmodified to this function.
- *
- * Following these arguments is a list of
- * "supported" attributes to collect. It is an
- * error to specify multiple attributes with the
- * same name. If any attribute not in the list
- * appears in the @attribute_names array then an
- * unknown attribute error will result.
- *
- * The #GMarkupCollectType field allows specifying
- * the type of collection to perform and if a
- * given attribute must appear or is optional.
- *
- * The attribute name is simply the name of the
- * attribute to collect.
- *
- * The pointer should be of the appropriate type
- * (see the descriptions under
- * #GMarkupCollectType) and may be %NULL in case a
- * particular attribute is to be allowed but
- * ignored.
- *
- * This function deals with issuing errors for missing attributes
- * (of type %G_MARKUP_ERROR_MISSING_ATTRIBUTE), unknown attributes
- * (of type %G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE) and duplicate
- * attributes (of type %G_MARKUP_ERROR_INVALID_CONTENT) as well
- * as parse errors for boolean-valued attributes (again of type
- * %G_MARKUP_ERROR_INVALID_CONTENT). In all of these cases %FALSE
- * will be returned and @error will be set as appropriate.
- *
- * Return value: %TRUE if successful
- *
- * Since: 2.16
- **/
-gboolean
-g_markup_collect_attributes (const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- GError **error,
- GMarkupCollectType first_type,
- const gchar *first_attr,
- ...)
-{
- GMarkupCollectType type;
- const gchar *attr;
- guint64 collected;
- int written;
- va_list ap;
- int i;
-
- type = first_type;
- attr = first_attr;
- collected = 0;
- written = 0;
-
- va_start (ap, first_attr);
- while (type != G_MARKUP_COLLECT_INVALID)
- {
- gboolean mandatory;
- const gchar *value;
-
- mandatory = !(type & G_MARKUP_COLLECT_OPTIONAL);
- type &= (G_MARKUP_COLLECT_OPTIONAL - 1);
-
- /* tristate records a value != TRUE and != FALSE
- * for the case where the attribute is missing
- */
- if (type == G_MARKUP_COLLECT_TRISTATE)
- mandatory = FALSE;
-
- for (i = 0; attribute_names[i]; i++)
- if (i >= 40 || !(collected & (G_GUINT64_CONSTANT(1) << i)))
- if (!strcmp (attribute_names[i], attr))
- break;
-
- /* ISO C99 only promises that the user can pass up to 127 arguments.
- * Subtracting the first 4 arguments plus the final NULL and dividing
- * by 3 arguments per collected attribute, we are left with a maximum
- * number of supported attributes of (127 - 5) / 3 = 40.
- *
- * In reality, nobody is ever going to call us with anywhere close to
- * 40 attributes to collect, so it is safe to assume that if i > 40
- * then the user has given some invalid or repeated arguments. These
- * problems will be caught and reported at the end of the function.
- *
- * We know at this point that we have an error, but we don't know
- * what error it is, so just continue...
- */
- if (i < 40)
- collected |= (G_GUINT64_CONSTANT(1) << i);
-
- value = attribute_values[i];
-
- if (value == NULL && mandatory)
- {
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_MISSING_ATTRIBUTE,
- "element '%s' requires attribute '%s'",
- element_name, attr);
-
- va_end (ap);
- goto failure;
- }
-
- switch (type)
- {
- case G_MARKUP_COLLECT_STRING:
- {
- const char **str_ptr;
-
- str_ptr = va_arg (ap, const char **);
-
- if (str_ptr != NULL)
- *str_ptr = value;
- }
- break;
-
- case G_MARKUP_COLLECT_STRDUP:
- {
- char **str_ptr;
-
- str_ptr = va_arg (ap, char **);
-
- if (str_ptr != NULL)
- *str_ptr = g_strdup (value);
- }
- break;
-
- case G_MARKUP_COLLECT_BOOLEAN:
- case G_MARKUP_COLLECT_TRISTATE:
- if (value == NULL)
- {
- gboolean *bool_ptr;
-
- bool_ptr = va_arg (ap, gboolean *);
-
- if (bool_ptr != NULL)
- {
- if (type == G_MARKUP_COLLECT_TRISTATE)
- /* constructivists rejoice!
- * neither false nor true...
- */
- *bool_ptr = -1;
-
- else /* G_MARKUP_COLLECT_BOOLEAN */
- *bool_ptr = FALSE;
- }
- }
- else
- {
- if (!g_markup_parse_boolean (value, va_arg (ap, gboolean *)))
- {
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "element '%s', attribute '%s', value '%s' "
- "cannot be parsed as a boolean value",
- element_name, attr, value);
-
- va_end (ap);
- goto failure;
- }
- }
-
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- type = va_arg (ap, GMarkupCollectType);
- attr = va_arg (ap, const char *);
- written++;
- }
- va_end (ap);
-
- /* ensure we collected all the arguments */
- for (i = 0; attribute_names[i]; i++)
- if ((collected & (G_GUINT64_CONSTANT(1) << i)) == 0)
- {
- /* attribute not collected: could be caused by two things.
- *
- * 1) it doesn't exist in our list of attributes
- * 2) it existed but was matched by a duplicate attribute earlier
- *
- * find out.
- */
- int j;
-
- for (j = 0; j < i; j++)
- if (strcmp (attribute_names[i], attribute_names[j]) == 0)
- /* duplicate! */
- break;
-
- /* j is now the first occurrence of attribute_names[i] */
- if (i == j)
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
- "attribute '%s' invalid for element '%s'",
- attribute_names[i], element_name);
- else
- g_set_error (error, G_MARKUP_ERROR,
- G_MARKUP_ERROR_INVALID_CONTENT,
- "attribute '%s' given multiple times for element '%s'",
- attribute_names[i], element_name);
-
- goto failure;
- }
-
- return TRUE;
-
-failure:
- /* replay the above to free allocations */
- type = first_type;
- attr = first_attr;
-
- va_start (ap, first_attr);
- while (type != G_MARKUP_COLLECT_INVALID)
- {
- gpointer ptr;
-
- ptr = va_arg (ap, gpointer);
-
- if (ptr == NULL)
- continue;
-
- switch (type & (G_MARKUP_COLLECT_OPTIONAL - 1))
- {
- case G_MARKUP_COLLECT_STRDUP:
- if (written)
- g_free (*(char **) ptr);
-
- case G_MARKUP_COLLECT_STRING:
- *(char **) ptr = NULL;
- break;
-
- case G_MARKUP_COLLECT_BOOLEAN:
- *(gboolean *) ptr = FALSE;
- break;
-
- case G_MARKUP_COLLECT_TRISTATE:
- *(gboolean *) ptr = -1;
- break;
- }
-
- type = va_arg (ap, GMarkupCollectType);
- attr = va_arg (ap, const char *);
-
- if (written)
- written--;
- }
- va_end (ap);
-
- return FALSE;
-}
-
-#define __G_MARKUP_C__
-#include "galiasdef.c"
diff --git a/glib/gnode.c b/glib/gnode.c
deleted file mode 100644
index 142eadeed..000000000
--- a/glib/gnode.c
+++ /dev/null
@@ -1,1165 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * GNode: N-way tree implementation.
- * Copyright (C) 1998 Tim Janik
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#include "glib.h"
-#include "galias.h"
-
-void g_node_push_allocator (gpointer dummy) { /* present for binary compat only */ }
-void g_node_pop_allocator (void) { /* present for binary compat only */ }
-
-#define g_node_alloc0() g_slice_new0 (GNode)
-#define g_node_free(node) g_slice_free (GNode, node)
-
-/* --- functions --- */
-/**
- * g_node_new:
- * @data: the data of the new node
- *
- * Creates a new #GNode containing the given data.
- * Used to create the first node in a tree.
- *
- * Returns: a new #GNode
- */
-GNode*
-g_node_new (gpointer data)
-{
- GNode *node = g_node_alloc0 ();
- node->data = data;
- return node;
-}
-
-static void
-g_nodes_free (GNode *node)
-{
- while (node)
- {
- GNode *next = node->next;
- if (node->children)
- g_nodes_free (node->children);
- g_node_free (node);
- node = next;
- }
-}
-
-/**
- * g_node_destroy:
- * @root: the root of the tree/subtree to destroy
- *
- * Removes @root and its children from the tree, freeing any memory
- * allocated.
- */
-void
-g_node_destroy (GNode *root)
-{
- g_return_if_fail (root != NULL);
-
- if (!G_NODE_IS_ROOT (root))
- g_node_unlink (root);
-
- g_nodes_free (root);
-}
-
-/**
- * g_node_unlink:
- * @node: the #GNode to unlink, which becomes the root of a new tree
- *
- * Unlinks a #GNode from a tree, resulting in two separate trees.
- */
-void
-g_node_unlink (GNode *node)
-{
- g_return_if_fail (node != NULL);
-
- if (node->prev)
- node->prev->next = node->next;
- else if (node->parent)
- node->parent->children = node->next;
- node->parent = NULL;
- if (node->next)
- {
- node->next->prev = node->prev;
- node->next = NULL;
- }
- node->prev = NULL;
-}
-
-/**
- * g_node_copy_deep:
- * @node: a #GNode
- * @copy_func: the function which is called to copy the data inside each node,
- * or %NULL to use the original data.
- * @data: data to pass to @copy_func
- *
- * Recursively copies a #GNode and its data.
- *
- * Return value: a new #GNode containing copies of the data in @node.
- *
- * Since: 2.4
- **/
-GNode*
-g_node_copy_deep (GNode *node,
- GCopyFunc copy_func,
- gpointer data)
-{
- GNode *new_node = NULL;
-
- if (copy_func == NULL)
- return g_node_copy (node);
-
- if (node)
- {
- GNode *child, *new_child;
-
- new_node = g_node_new (copy_func (node->data, data));
-
- for (child = g_node_last_child (node); child; child = child->prev)
- {
- new_child = g_node_copy_deep (child, copy_func, data);
- g_node_prepend (new_node, new_child);
- }
- }
-
- return new_node;
-}
-
-/**
- * g_node_copy:
- * @node: a #GNode
- *
- * Recursively copies a #GNode (but does not deep-copy the data inside the
- * nodes, see g_node_copy_deep() if you need that).
- *
- * Returns: a new #GNode containing the same data pointers
- */
-GNode*
-g_node_copy (GNode *node)
-{
- GNode *new_node = NULL;
-
- if (node)
- {
- GNode *child;
-
- new_node = g_node_new (node->data);
-
- for (child = g_node_last_child (node); child; child = child->prev)
- g_node_prepend (new_node, g_node_copy (child));
- }
-
- return new_node;
-}
-
-/**
- * g_node_insert:
- * @parent: the #GNode to place @node under
- * @position: the position to place @node at, with respect to its siblings
- * If position is -1, @node is inserted as the last child of @parent
- * @node: the #GNode to insert
- *
- * Inserts a #GNode beneath the parent at the given position.
- *
- * Returns: the inserted #GNode
- */
-GNode*
-g_node_insert (GNode *parent,
- gint position,
- GNode *node)
-{
- g_return_val_if_fail (parent != NULL, node);
- g_return_val_if_fail (node != NULL, node);
- g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
-
- if (position > 0)
- return g_node_insert_before (parent,
- g_node_nth_child (parent, position),
- node);
- else if (position == 0)
- return g_node_prepend (parent, node);
- else /* if (position < 0) */
- return g_node_append (parent, node);
-}
-
-/**
- * g_node_insert_before:
- * @parent: the #GNode to place @node under
- * @sibling: the sibling #GNode to place @node before.
- * If sibling is %NULL, the node is inserted as the last child of @parent.
- * @node: the #GNode to insert
- *
- * Inserts a #GNode beneath the parent before the given sibling.
- *
- * Returns: the inserted #GNode
- */
-GNode*
-g_node_insert_before (GNode *parent,
- GNode *sibling,
- GNode *node)
-{
- g_return_val_if_fail (parent != NULL, node);
- g_return_val_if_fail (node != NULL, node);
- g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
- if (sibling)
- g_return_val_if_fail (sibling->parent == parent, node);
-
- node->parent = parent;
-
- if (sibling)
- {
- if (sibling->prev)
- {
- node->prev = sibling->prev;
- node->prev->next = node;
- node->next = sibling;
- sibling->prev = node;
- }
- else
- {
- node->parent->children = node;
- node->next = sibling;
- sibling->prev = node;
- }
- }
- else
- {
- if (parent->children)
- {
- sibling = parent->children;
- while (sibling->next)
- sibling = sibling->next;
- node->prev = sibling;
- sibling->next = node;
- }
- else
- node->parent->children = node;
- }
-
- return node;
-}
-
-/**
- * g_node_insert_after:
- * @parent: the #GNode to place @node under
- * @sibling: the sibling #GNode to place @node after.
- * If sibling is %NULL, the node is inserted as the first child of @parent.
- * @node: the #GNode to insert
- *
- * Inserts a #GNode beneath the parent after the given sibling.
- *
- * Returns: the inserted #GNode
- */
-GNode*
-g_node_insert_after (GNode *parent,
- GNode *sibling,
- GNode *node)
-{
- g_return_val_if_fail (parent != NULL, node);
- g_return_val_if_fail (node != NULL, node);
- g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
- if (sibling)
- g_return_val_if_fail (sibling->parent == parent, node);
-
- node->parent = parent;
-
- if (sibling)
- {
- if (sibling->next)
- {
- sibling->next->prev = node;
- }
- node->next = sibling->next;
- node->prev = sibling;
- sibling->next = node;
- }
- else
- {
- if (parent->children)
- {
- node->next = parent->children;
- parent->children->prev = node;
- }
- parent->children = node;
- }
-
- return node;
-}
-
-/**
- * g_node_prepend:
- * @parent: the #GNode to place the new #GNode under
- * @node: the #GNode to insert
- *
- * Inserts a #GNode as the first child of the given parent.
- *
- * Returns: the inserted #GNode
- */
-GNode*
-g_node_prepend (GNode *parent,
- GNode *node)
-{
- g_return_val_if_fail (parent != NULL, node);
-
- return g_node_insert_before (parent, parent->children, node);
-}
-
-/**
- * g_node_get_root:
- * @node: a #GNode
- *
- * Gets the root of a tree.
- *
- * Returns: the root of the tree
- */
-GNode*
-g_node_get_root (GNode *node)
-{
- g_return_val_if_fail (node != NULL, NULL);
-
- while (node->parent)
- node = node->parent;
-
- return node;
-}
-
-/**
- * g_node_is_ancestor:
- * @node: a #GNode
- * @descendant: a #GNode
- *
- * Returns %TRUE if @node is an ancestor of @descendant.
- * This is true if node is the parent of @descendant,
- * or if node is the grandparent of @descendant etc.
- *
- * Returns: %TRUE if @node is an ancestor of @descendant
- */
-gboolean
-g_node_is_ancestor (GNode *node,
- GNode *descendant)
-{
- g_return_val_if_fail (node != NULL, FALSE);
- g_return_val_if_fail (descendant != NULL, FALSE);
-
- while (descendant)
- {
- if (descendant->parent == node)
- return TRUE;
-
- descendant = descendant->parent;
- }
-
- return FALSE;
-}
-
-/**
- * g_node_depth:
- * @node: a #GNode
- *
- * Gets the depth of a #GNode.
- *
- * If @node is %NULL the depth is 0. The root node has a depth of 1.
- * For the children of the root node the depth is 2. And so on.
- *
- * Returns: the depth of the #GNode
- */
-guint
-g_node_depth (GNode *node)
-{
- guint depth = 0;
-
- while (node)
- {
- depth++;
- node = node->parent;
- }
-
- return depth;
-}
-
-/**
- * g_node_reverse_children:
- * @node: a #GNode.
- *
- * Reverses the order of the children of a #GNode.
- * (It doesn't change the order of the grandchildren.)
- */
-void
-g_node_reverse_children (GNode *node)
-{
- GNode *child;
- GNode *last;
-
- g_return_if_fail (node != NULL);
-
- child = node->children;
- last = NULL;
- while (child)
- {
- last = child;
- child = last->next;
- last->next = last->prev;
- last->prev = child;
- }
- node->children = last;
-}
-
-/**
- * g_node_max_height:
- * @root: a #GNode
- *
- * Gets the maximum height of all branches beneath a #GNode.
- * This is the maximum distance from the #GNode to all leaf nodes.
- *
- * If @root is %NULL, 0 is returned. If @root has no children,
- * 1 is returned. If @root has children, 2 is returned. And so on.
- *
- * Returns: the maximum height of the tree beneath @root
- */
-guint
-g_node_max_height (GNode *root)
-{
- GNode *child;
- guint max_height = 0;
-
- if (!root)
- return 0;
-
- child = root->children;
- while (child)
- {
- guint tmp_height;
-
- tmp_height = g_node_max_height (child);
- if (tmp_height > max_height)
- max_height = tmp_height;
- child = child->next;
- }
-
- return max_height + 1;
-}
-
-static gboolean
-g_node_traverse_pre_order (GNode *node,
- GTraverseFlags flags,
- GNodeTraverseFunc func,
- gpointer data)
-{
- if (node->children)
- {
- GNode *child;
-
- if ((flags & G_TRAVERSE_NON_LEAFS) &&
- func (node, data))
- return TRUE;
-
- child = node->children;
- while (child)
- {
- GNode *current;
-
- current = child;
- child = current->next;
- if (g_node_traverse_pre_order (current, flags, func, data))
- return TRUE;
- }
- }
- else if ((flags & G_TRAVERSE_LEAFS) &&
- func (node, data))
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-g_node_depth_traverse_pre_order (GNode *node,
- GTraverseFlags flags,
- guint depth,
- GNodeTraverseFunc func,
- gpointer data)
-{
- if (node->children)
- {
- GNode *child;
-
- if ((flags & G_TRAVERSE_NON_LEAFS) &&
- func (node, data))
- return TRUE;
-
- depth--;
- if (!depth)
- return FALSE;
-
- child = node->children;
- while (child)
- {
- GNode *current;
-
- current = child;
- child = current->next;
- if (g_node_depth_traverse_pre_order (current, flags, depth, func, data))
- return TRUE;
- }
- }
- else if ((flags & G_TRAVERSE_LEAFS) &&
- func (node, data))
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-g_node_traverse_post_order (GNode *node,
- GTraverseFlags flags,
- GNodeTraverseFunc func,
- gpointer data)
-{
- if (node->children)
- {
- GNode *child;
-
- child = node->children;
- while (child)
- {
- GNode *current;
-
- current = child;
- child = current->next;
- if (g_node_traverse_post_order (current, flags, func, data))
- return TRUE;
- }
-
- if ((flags & G_TRAVERSE_NON_LEAFS) &&
- func (node, data))
- return TRUE;
-
- }
- else if ((flags & G_TRAVERSE_LEAFS) &&
- func (node, data))
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-g_node_depth_traverse_post_order (GNode *node,
- GTraverseFlags flags,
- guint depth,
- GNodeTraverseFunc func,
- gpointer data)
-{
- if (node->children)
- {
- depth--;
- if (depth)
- {
- GNode *child;
-
- child = node->children;
- while (child)
- {
- GNode *current;
-
- current = child;
- child = current->next;
- if (g_node_depth_traverse_post_order (current, flags, depth, func, data))
- return TRUE;
- }
- }
-
- if ((flags & G_TRAVERSE_NON_LEAFS) &&
- func (node, data))
- return TRUE;
-
- }
- else if ((flags & G_TRAVERSE_LEAFS) &&
- func (node, data))
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-g_node_traverse_in_order (GNode *node,
- GTraverseFlags flags,
- GNodeTraverseFunc func,
- gpointer data)
-{
- if (node->children)
- {
- GNode *child;
- GNode *current;
-
- child = node->children;
- current = child;
- child = current->next;
-
- if (g_node_traverse_in_order (current, flags, func, data))
- return TRUE;
-
- if ((flags & G_TRAVERSE_NON_LEAFS) &&
- func (node, data))
- return TRUE;
-
- while (child)
- {
- current = child;
- child = current->next;
- if (g_node_traverse_in_order (current, flags, func, data))
- return TRUE;
- }
- }
- else if ((flags & G_TRAVERSE_LEAFS) &&
- func (node, data))
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-g_node_depth_traverse_in_order (GNode *node,
- GTraverseFlags flags,
- guint depth,
- GNodeTraverseFunc func,
- gpointer data)
-{
- if (node->children)
- {
- depth--;
- if (depth)
- {
- GNode *child;
- GNode *current;
-
- child = node->children;
- current = child;
- child = current->next;
-
- if (g_node_depth_traverse_in_order (current, flags, depth, func, data))
- return TRUE;
-
- if ((flags & G_TRAVERSE_NON_LEAFS) &&
- func (node, data))
- return TRUE;
-
- while (child)
- {
- current = child;
- child = current->next;
- if (g_node_depth_traverse_in_order (current, flags, depth, func, data))
- return TRUE;
- }
- }
- else if ((flags & G_TRAVERSE_NON_LEAFS) &&
- func (node, data))
- return TRUE;
- }
- else if ((flags & G_TRAVERSE_LEAFS) &&
- func (node, data))
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-g_node_traverse_level (GNode *node,
- GTraverseFlags flags,
- guint level,
- GNodeTraverseFunc func,
- gpointer data,
- gboolean *more_levels)
-{
- if (level == 0)
- {
- if (node->children)
- {
- *more_levels = TRUE;
- return (flags & G_TRAVERSE_NON_LEAFS) && func (node, data);
- }
- else
- {
- return (flags & G_TRAVERSE_LEAFS) && func (node, data);
- }
- }
- else
- {
- node = node->children;
-
- while (node)
- {
- if (g_node_traverse_level (node, flags, level - 1, func, data, more_levels))
- return TRUE;
-
- node = node->next;
- }
- }
-
- return FALSE;
-}
-
-static gboolean
-g_node_depth_traverse_level (GNode *node,
- GTraverseFlags flags,
- guint depth,
- GNodeTraverseFunc func,
- gpointer data)
-{
- guint level;
- gboolean more_levels;
-
- level = 0;
- while (level != depth)
- {
- more_levels = FALSE;
- if (g_node_traverse_level (node, flags, level, func, data, &more_levels))
- return TRUE;
- if (!more_levels)
- break;
- level++;
- }
- return FALSE;
-}
-
-/**
- * g_node_traverse:
- * @root: the root #GNode of the tree to traverse
- * @order: the order in which nodes are visited - %G_IN_ORDER,
- * %G_PRE_ORDER, %G_POST_ORDER, or %G_LEVEL_ORDER.
- * @flags: which types of children are to be visited, one of
- * %G_TRAVERSE_ALL, %G_TRAVERSE_LEAVES and %G_TRAVERSE_NON_LEAVES
- * @max_depth: the maximum depth of the traversal. Nodes below this
- * depth will not be visited. If max_depth is -1 all nodes in
- * the tree are visited. If depth is 1, only the root is visited.
- * If depth is 2, the root and its children are visited. And so on.
- * @func: the function to call for each visited #GNode
- * @data: user data to pass to the function
- *
- * Traverses a tree starting at the given root #GNode.
- * It calls the given function for each node visited.
- * The traversal can be halted at any point by returning %TRUE from @func.
- */
-void
-g_node_traverse (GNode *root,
- GTraverseType order,
- GTraverseFlags flags,
- gint depth,
- GNodeTraverseFunc func,
- gpointer data)
-{
- g_return_if_fail (root != NULL);
- g_return_if_fail (func != NULL);
- g_return_if_fail (order <= G_LEVEL_ORDER);
- g_return_if_fail (flags <= G_TRAVERSE_MASK);
- g_return_if_fail (depth == -1 || depth > 0);
-
- switch (order)
- {
- case G_PRE_ORDER:
- if (depth < 0)
- g_node_traverse_pre_order (root, flags, func, data);
- else
- g_node_depth_traverse_pre_order (root, flags, depth, func, data);
- break;
- case G_POST_ORDER:
- if (depth < 0)
- g_node_traverse_post_order (root, flags, func, data);
- else
- g_node_depth_traverse_post_order (root, flags, depth, func, data);
- break;
- case G_IN_ORDER:
- if (depth < 0)
- g_node_traverse_in_order (root, flags, func, data);
- else
- g_node_depth_traverse_in_order (root, flags, depth, func, data);
- break;
- case G_LEVEL_ORDER:
- g_node_depth_traverse_level (root, flags, depth, func, data);
- break;
- }
-}
-
-static gboolean
-g_node_find_func (GNode *node,
- gpointer data)
-{
- gpointer *d = data;
-
- if (*d != node->data)
- return FALSE;
-
- *(++d) = node;
-
- return TRUE;
-}
-
-/**
- * g_node_find:
- * @root: the root #GNode of the tree to search
- * @order: the order in which nodes are visited - %G_IN_ORDER,
- * %G_PRE_ORDER, %G_POST_ORDER, or %G_LEVEL_ORDER
- * @flags: which types of children are to be searched, one of
- * %G_TRAVERSE_ALL, %G_TRAVERSE_LEAVES and %G_TRAVERSE_NON_LEAVES
- * @data: the data to find
- *
- * Finds a #GNode in a tree.
- *
- * Returns: the found #GNode, or %NULL if the data is not found
- */
-GNode*
-g_node_find (GNode *root,
- GTraverseType order,
- GTraverseFlags flags,
- gpointer data)
-{
- gpointer d[2];
-
- g_return_val_if_fail (root != NULL, NULL);
- g_return_val_if_fail (order <= G_LEVEL_ORDER, NULL);
- g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
-
- d[0] = data;
- d[1] = NULL;
-
- g_node_traverse (root, order, flags, -1, g_node_find_func, d);
-
- return d[1];
-}
-
-static void
-g_node_count_func (GNode *node,
- GTraverseFlags flags,
- guint *n)
-{
- if (node->children)
- {
- GNode *child;
-
- if (flags & G_TRAVERSE_NON_LEAFS)
- (*n)++;
-
- child = node->children;
- while (child)
- {
- g_node_count_func (child, flags, n);
- child = child->next;
- }
- }
- else if (flags & G_TRAVERSE_LEAFS)
- (*n)++;
-}
-
-/**
- * g_node_n_nodes:
- * @root: a #GNode
- * @flags: which types of children are to be counted, one of
- * %G_TRAVERSE_ALL, %G_TRAVERSE_LEAVES and %G_TRAVERSE_NON_LEAVES
- *
- * Gets the number of nodes in a tree.
- *
- * Returns: the number of nodes in the tree
- */
-guint
-g_node_n_nodes (GNode *root,
- GTraverseFlags flags)
-{
- guint n = 0;
-
- g_return_val_if_fail (root != NULL, 0);
- g_return_val_if_fail (flags <= G_TRAVERSE_MASK, 0);
-
- g_node_count_func (root, flags, &n);
-
- return n;
-}
-
-/**
- * g_node_last_child:
- * @node: a #GNode (must not be %NULL)
- *
- * Gets the last child of a #GNode.
- *
- * Returns: the last child of @node, or %NULL if @node has no children
- */
-GNode*
-g_node_last_child (GNode *node)
-{
- g_return_val_if_fail (node != NULL, NULL);
-
- node = node->children;
- if (node)
- while (node->next)
- node = node->next;
-
- return node;
-}
-
-/**
- * g_node_nth_child:
- * @node: a #GNode
- * @n: the index of the desired child
- *
- * Gets a child of a #GNode, using the given index.
- * The first child is at index 0. If the index is
- * too big, %NULL is returned.
- *
- * Returns: the child of @node at index @n
- */
-GNode*
-g_node_nth_child (GNode *node,
- guint n)
-{
- g_return_val_if_fail (node != NULL, NULL);
-
- node = node->children;
- if (node)
- while ((n-- > 0) && node)
- node = node->next;
-
- return node;
-}
-
-/**
- * g_node_n_children:
- * @node: a #GNode
- *
- * Gets the number of children of a #GNode.
- *
- * Returns: the number of children of @node
- */
-guint
-g_node_n_children (GNode *node)
-{
- guint n = 0;
-
- g_return_val_if_fail (node != NULL, 0);
-
- node = node->children;
- while (node)
- {
- n++;
- node = node->next;
- }
-
- return n;
-}
-
-/**
- * g_node_find_child:
- * @node: a #GNode
- * @flags: which types of children are to be searched, one of
- * %G_TRAVERSE_ALL, %G_TRAVERSE_LEAVES and %G_TRAVERSE_NON_LEAVES
- * @data: the data to find
- *
- * Finds the first child of a #GNode with the given data.
- *
- * Returns: the found child #GNode, or %NULL if the data is not found
- */
-GNode*
-g_node_find_child (GNode *node,
- GTraverseFlags flags,
- gpointer data)
-{
- g_return_val_if_fail (node != NULL, NULL);
- g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
-
- node = node->children;
- while (node)
- {
- if (node->data == data)
- {
- if (G_NODE_IS_LEAF (node))
- {
- if (flags & G_TRAVERSE_LEAFS)
- return node;
- }
- else
- {
- if (flags & G_TRAVERSE_NON_LEAFS)
- return node;
- }
- }
- node = node->next;
- }
-
- return NULL;
-}
-
-/**
- * g_node_child_position:
- * @node: a #GNode
- * @child: a child of @node
- *
- * Gets the position of a #GNode with respect to its siblings.
- * @child must be a child of @node. The first child is numbered 0,
- * the second 1, and so on.
- *
- * Returns: the position of @child with respect to its siblings
- */
-gint
-g_node_child_position (GNode *node,
- GNode *child)
-{
- guint n = 0;
-
- g_return_val_if_fail (node != NULL, -1);
- g_return_val_if_fail (child != NULL, -1);
- g_return_val_if_fail (child->parent == node, -1);
-
- node = node->children;
- while (node)
- {
- if (node == child)
- return n;
- n++;
- node = node->next;
- }
-
- return -1;
-}
-
-/**
- * g_node_child_index:
- * @node: a #GNode
- * @data: the data to find
- *
- * Gets the position of the first child of a #GNode
- * which contains the given data.
- *
- * Returns: the index of the child of @node which contains
- * @data, or -1 if the data is not found
- */
-gint
-g_node_child_index (GNode *node,
- gpointer data)
-{
- guint n = 0;
-
- g_return_val_if_fail (node != NULL, -1);
-
- node = node->children;
- while (node)
- {
- if (node->data == data)
- return n;
- n++;
- node = node->next;
- }
-
- return -1;
-}
-
-/**
- * g_node_first_sibling:
- * @node: a #GNode
- *
- * Gets the first sibling of a #GNode.
- * This could possibly be the node itself.
- *
- * Returns: the first sibling of @node
- */
-GNode*
-g_node_first_sibling (GNode *node)
-{
- g_return_val_if_fail (node != NULL, NULL);
-
- if (node->parent)
- return node->parent->children;
-
- while (node->prev)
- node = node->prev;
-
- return node;
-}
-
-/**
- * g_node_last_sibling:
- * @node: a #GNode
- *
- * Gets the last sibling of a #GNode.
- * This could possibly be the node itself.
- *
- * Returns: the last sibling of @node
- */
-GNode*
-g_node_last_sibling (GNode *node)
-{
- g_return_val_if_fail (node != NULL, NULL);
-
- while (node->next)
- node = node->next;
-
- return node;
-}
-
-/**
- * g_node_children_foreach:
- * @node: a #GNode
- * @flags: which types of children are to be visited, one of
- * %G_TRAVERSE_ALL, %G_TRAVERSE_LEAVES and %G_TRAVERSE_NON_LEAVES
- * @func: the function to call for each visited node
- * @data: user data to pass to the function
- *
- * Calls a function for each of the children of a #GNode.
- * Note that it doesn't descend beneath the child nodes.
- */
-void
-g_node_children_foreach (GNode *node,
- GTraverseFlags flags,
- GNodeForeachFunc func,
- gpointer data)
-{
- g_return_if_fail (node != NULL);
- g_return_if_fail (flags <= G_TRAVERSE_MASK);
- g_return_if_fail (func != NULL);
-
- node = node->children;
- while (node)
- {
- GNode *current;
-
- current = node;
- node = current->next;
- if (G_NODE_IS_LEAF (current))
- {
- if (flags & G_TRAVERSE_LEAFS)
- func (current, data);
- }
- else
- {
- if (flags & G_TRAVERSE_NON_LEAFS)
- func (current, data);
- }
- }
-}
-
-#define __G_NODE_C__
-#include "galiasdef.c"
diff --git a/glib/gprimes.c b/glib/gprimes.c
deleted file mode 100644
index 7beca710c..000000000
--- a/glib/gprimes.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#include "glib.h"
-#include "galias.h"
-
-
-static const guint g_primes[] =
-{
- 11,
- 19,
- 37,
- 73,
- 109,
- 163,
- 251,
- 367,
- 557,
- 823,
- 1237,
- 1861,
- 2777,
- 4177,
- 6247,
- 9371,
- 14057,
- 21089,
- 31627,
- 47431,
- 71143,
- 106721,
- 160073,
- 240101,
- 360163,
- 540217,
- 810343,
- 1215497,
- 1823231,
- 2734867,
- 4102283,
- 6153409,
- 9230113,
- 13845163,
-};
-
-static const guint g_nprimes = sizeof (g_primes) / sizeof (g_primes[0]);
-
-guint
-g_spaced_primes_closest (guint num)
-{
- gint i;
-
- for (i = 0; i < g_nprimes; i++)
- if (g_primes[i] > num)
- return g_primes[i];
-
- return g_primes[g_nprimes - 1];
-}
-
-#define __G_PRIMES_C__
-#include "galiasdef.c"
diff --git a/glib/gqueue.c b/glib/gqueue.c
deleted file mode 100644
index 1368e2614..000000000
--- a/glib/gqueue.c
+++ /dev/null
@@ -1,1013 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * GQueue: Double ended queue implementation, piggy backed on GList.
- * Copyright (C) 1998 Tim Janik
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#include "glib.h"
-#include "galias.h"
-
-/**
- * g_queue_new:
- *
- * Creates a new #GQueue.
- *
- * Returns: a new #GQueue.
- **/
-GQueue*
-g_queue_new (void)
-{
- return g_slice_new0 (GQueue);
-}
-
-/**
- * g_queue_free:
- * @queue: a #GQueue.
- *
- * Frees the memory allocated for the #GQueue. Only call this function if
- * @queue was created with g_queue_new(). If queue elements contain
- * dynamically-allocated memory, they should be freed first.
- **/
-void
-g_queue_free (GQueue *queue)
-{
- g_return_if_fail (queue != NULL);
-
- g_list_free (queue->head);
- g_slice_free (GQueue, queue);
-}
-
-/**
- * g_queue_init:
- * @queue: an uninitialized #GQueue
- *
- * A statically-allocated #GQueue must be initialized with this function
- * before it can be used. Alternatively you can initialize it with
- * #G_QUEUE_INIT. It is not necessary to initialize queues created with
- * g_queue_new().
- *
- * Since: 2.14
- **/
-void
-g_queue_init (GQueue *queue)
-{
- g_return_if_fail (queue != NULL);
-
- queue->head = queue->tail = NULL;
- queue->length = 0;
-}
-
-/**
- * g_queue_clear:
- * @queue: a #GQueue
- *
- * Removes all the elements in @queue. If queue elements contain
- * dynamically-allocated memory, they should be freed first.
- *
- * Since: 2.14
- */
-void
-g_queue_clear (GQueue *queue)
-{
- g_return_if_fail (queue != NULL);
-
- g_list_free (queue->head);
- g_queue_init (queue);
-}
-
-/**
- * g_queue_is_empty:
- * @queue: a #GQueue.
- *
- * Returns %TRUE if the queue is empty.
- *
- * Returns: %TRUE if the queue is empty.
- **/
-gboolean
-g_queue_is_empty (GQueue *queue)
-{
- g_return_val_if_fail (queue != NULL, TRUE);
-
- return queue->head == NULL;
-}
-
-/**
- * g_queue_get_length:
- * @queue: a #GQueue
- *
- * Returns the number of items in @queue.
- *
- * Return value: The number of items in @queue.
- *
- * Since: 2.4
- **/
-guint
-g_queue_get_length (GQueue *queue)
-{
- g_return_val_if_fail (queue != NULL, 0);
-
- return queue->length;
-}
-
-/**
- * g_queue_reverse:
- * @queue: a #GQueue
- *
- * Reverses the order of the items in @queue.
- *
- * Since: 2.4
- **/
-void
-g_queue_reverse (GQueue *queue)
-{
- g_return_if_fail (queue != NULL);
-
- queue->tail = queue->head;
- queue->head = g_list_reverse (queue->head);
-}
-
-/**
- * g_queue_copy:
- * @queue: a #GQueue
- *
- * Copies a @queue. Note that is a shallow copy. If the elements in the
- * queue consist of pointers to data, the pointers are copied, but the
- * actual data is not.
- *
- * Return value: A copy of @queue
- *
- * Since: 2.4
- **/
-GQueue *
-g_queue_copy (GQueue *queue)
-{
- GQueue *result;
- GList *list;
-
- g_return_val_if_fail (queue != NULL, NULL);
-
- result = g_queue_new ();
-
- for (list = queue->head; list != NULL; list = list->next)
- g_queue_push_tail (result, list->data);
-
- return result;
-}
-
-/**
- * g_queue_foreach:
- * @queue: a #GQueue
- * @func: the function to call for each element's data
- * @user_data: user data to pass to @func
- *
- * Calls @func for each element in the queue passing @user_data to the
- * function.
- *
- * Since: 2.4
- **/
-void
-g_queue_foreach (GQueue *queue,
- GFunc func,
- gpointer user_data)
-{
- GList *list;
-
- g_return_if_fail (queue != NULL);
- g_return_if_fail (func != NULL);
-
- list = queue->head;
- while (list)
- {
- GList *next = list->next;
- func (list->data, user_data);
- list = next;
- }
-}
-
-/**
- * g_queue_find:
- * @queue: a #GQueue
- * @data: data to find
- *
- * Finds the first link in @queue which contains @data.
- *
- * Return value: The first link in @queue which contains @data.
- *
- * Since: 2.4
- **/
-GList *
-g_queue_find (GQueue *queue,
- gconstpointer data)
-{
- g_return_val_if_fail (queue != NULL, NULL);
-
- return g_list_find (queue->head, data);
-}
-
-/**
- * g_queue_find_custom:
- * @queue: a #GQueue
- * @data: user data passed to @func
- * @func: a #GCompareFunc to call for each element. It should return 0
- * when the desired element is found
- *
- * Finds an element in a #GQueue, using a supplied function to find the
- * desired element. It iterates over the queue, calling the given function
- * which should return 0 when the desired element is found. The function
- * takes two gconstpointer arguments, the #GQueue element's data as the
- * first argument and the given user data as the second argument.
- *
- * Return value: The found link, or %NULL if it wasn't found
- *
- * Since: 2.4
- **/
-GList *
-g_queue_find_custom (GQueue *queue,
- gconstpointer data,
- GCompareFunc func)
-{
- g_return_val_if_fail (queue != NULL, NULL);
- g_return_val_if_fail (func != NULL, NULL);
-
- return g_list_find_custom (queue->head, data, func);
-}
-
-/**
- * g_queue_sort:
- * @queue: a #GQueue
- * @compare_func: the #GCompareDataFunc used to sort @queue. This function
- * is passed two elements of the queue and should return 0 if they are
- * equal, a negative value if the first comes before the second, and
- * a positive value if the second comes before the first.
- * @user_data: user data passed to @compare_func
- *
- * Sorts @queue using @compare_func.
- *
- * Since: 2.4
- **/
-void
-g_queue_sort (GQueue *queue,
- GCompareDataFunc compare_func,
- gpointer user_data)
-{
- g_return_if_fail (queue != NULL);
- g_return_if_fail (compare_func != NULL);
-
- queue->head = g_list_sort_with_data (queue->head, compare_func, user_data);
- queue->tail = g_list_last (queue->head);
-}
-
-/**
- * g_queue_push_head:
- * @queue: a #GQueue.
- * @data: the data for the new element.
- *
- * Adds a new element at the head of the queue.
- **/
-void
-g_queue_push_head (GQueue *queue,
- gpointer data)
-{
- g_return_if_fail (queue != NULL);
-
- queue->head = g_list_prepend (queue->head, data);
- if (!queue->tail)
- queue->tail = queue->head;
- queue->length++;
-}
-
-/**
- * g_queue_push_nth:
- * @queue: a #GQueue
- * @data: the data for the new element
- * @n: the position to insert the new element. If @n is negative or
- * larger than the number of elements in the @queue, the element is
- * added to the end of the queue.
- *
- * Inserts a new element into @queue at the given position
- *
- * Since: 2.4
- **/
-void
-g_queue_push_nth (GQueue *queue,
- gpointer data,
- gint n)
-{
- g_return_if_fail (queue != NULL);
-
- if (n < 0 || n >= queue->length)
- {
- g_queue_push_tail (queue, data);
- return;
- }
-
- g_queue_insert_before (queue, g_queue_peek_nth_link (queue, n), data);
-}
-
-/**
- * g_queue_push_head_link:
- * @queue: a #GQueue.
- * @link_: a single #GList element, <emphasis>not</emphasis> a list with
- * more than one element.
- *
- * Adds a new element at the head of the queue.
- **/
-void
-g_queue_push_head_link (GQueue *queue,
- GList *link)
-{
- g_return_if_fail (queue != NULL);
- g_return_if_fail (link != NULL);
- g_return_if_fail (link->prev == NULL);
- g_return_if_fail (link->next == NULL);
-
- link->next = queue->head;
- if (queue->head)
- queue->head->prev = link;
- else
- queue->tail = link;
- queue->head = link;
- queue->length++;
-}
-
-/**
- * g_queue_push_tail:
- * @queue: a #GQueue.
- * @data: the data for the new element.
- *
- * Adds a new element at the tail of the queue.
- **/
-void
-g_queue_push_tail (GQueue *queue,
- gpointer data)
-{
- g_return_if_fail (queue != NULL);
-
- queue->tail = g_list_append (queue->tail, data);
- if (queue->tail->next)
- queue->tail = queue->tail->next;
- else
- queue->head = queue->tail;
- queue->length++;
-}
-
-/**
- * g_queue_push_tail_link:
- * @queue: a #GQueue.
- * @link_: a single #GList element, <emphasis>not</emphasis> a list with
- * more than one element.
- *
- * Adds a new element at the tail of the queue.
- **/
-void
-g_queue_push_tail_link (GQueue *queue,
- GList *link)
-{
- g_return_if_fail (queue != NULL);
- g_return_if_fail (link != NULL);
- g_return_if_fail (link->prev == NULL);
- g_return_if_fail (link->next == NULL);
-
- link->prev = queue->tail;
- if (queue->tail)
- queue->tail->next = link;
- else
- queue->head = link;
- queue->tail = link;
- queue->length++;
-}
-
-/**
- * g_queue_push_nth_link:
- * @queue: a #GQueue
- * @n: the position to insert the link. If this is negative or larger than
- * the number of elements in @queue, the link is added to the end of
- * @queue.
- * @link_: the link to add to @queue
- *
- * Inserts @link into @queue at the given position.
- *
- * Since: 2.4
- **/
-void
-g_queue_push_nth_link (GQueue *queue,
- gint n,
- GList *link_)
-{
- GList *next;
- GList *prev;
-
- g_return_if_fail (queue != NULL);
- g_return_if_fail (link_ != NULL);
-
- if (n < 0 || n >= queue->length)
- {
- g_queue_push_tail_link (queue, link_);
- return;
- }
-
- g_assert (queue->head);
- g_assert (queue->tail);
-
- next = g_queue_peek_nth_link (queue, n);
- prev = next->prev;
-
- if (prev)
- prev->next = link_;
- next->prev = link_;
-
- link_->next = next;
- link_->prev = prev;
-
- if (queue->head->prev)
- queue->head = queue->head->prev;
-
- if (queue->tail->next)
- queue->tail = queue->tail->next;
-
- queue->length++;
-}
-
-/**
- * g_queue_pop_head:
- * @queue: a #GQueue.
- *
- * Removes the first element of the queue.
- *
- * Returns: the data of the first element in the queue, or %NULL if the queue
- * is empty.
- **/
-gpointer
-g_queue_pop_head (GQueue *queue)
-{
- g_return_val_if_fail (queue != NULL, NULL);
-
- if (queue->head)
- {
- GList *node = queue->head;
- gpointer data = node->data;
-
- queue->head = node->next;
- if (queue->head)
- queue->head->prev = NULL;
- else
- queue->tail = NULL;
- g_list_free_1 (node);
- queue->length--;
-
- return data;
- }
-
- return NULL;
-}
-
-/**
- * g_queue_pop_head_link:
- * @queue: a #GQueue.
- *
- * Removes the first element of the queue.
- *
- * Returns: the #GList element at the head of the queue, or %NULL if the queue
- * is empty.
- **/
-GList*
-g_queue_pop_head_link (GQueue *queue)
-{
- g_return_val_if_fail (queue != NULL, NULL);
-
- if (queue->head)
- {
- GList *node = queue->head;
-
- queue->head = node->next;
- if (queue->head)
- {
- queue->head->prev = NULL;
- node->next = NULL;
- }
- else
- queue->tail = NULL;
- queue->length--;
-
- return node;
- }
-
- return NULL;
-}
-
-/**
- * g_queue_peek_head_link:
- * @queue: a #GQueue
- *
- * Returns the first link in @queue
- *
- * Return value: the first link in @queue, or %NULL if @queue is empty
- *
- * Since: 2.4
- **/
-GList*
-g_queue_peek_head_link (GQueue *queue)
-{
- g_return_val_if_fail (queue != NULL, NULL);
-
- return queue->head;
-}
-
-/**
- * g_queue_peek_tail_link:
- * @queue: a #GQueue
- *
- * Returns the last link @queue.
- *
- * Return value: the last link in @queue, or %NULL if @queue is empty
- *
- * Since: 2.4
- **/
-GList*
-g_queue_peek_tail_link (GQueue *queue)
-{
- g_return_val_if_fail (queue != NULL, NULL);
-
- return queue->tail;
-}
-
-/**
- * g_queue_pop_tail:
- * @queue: a #GQueue.
- *
- * Removes the last element of the queue.
- *
- * Returns: the data of the last element in the queue, or %NULL if the queue
- * is empty.
- **/
-gpointer
-g_queue_pop_tail (GQueue *queue)
-{
- g_return_val_if_fail (queue != NULL, NULL);
-
- if (queue->tail)
- {
- GList *node = queue->tail;
- gpointer data = node->data;
-
- queue->tail = node->prev;
- if (queue->tail)
- queue->tail->next = NULL;
- else
- queue->head = NULL;
- queue->length--;
- g_list_free_1 (node);
-
- return data;
- }
-
- return NULL;
-}
-
-/**
- * g_queue_pop_nth:
- * @queue: a #GQueue
- * @n: the position of the element.
- *
- * Removes the @n'th element of @queue.
- *
- * Return value: the element's data, or %NULL if @n is off the end of @queue.
- *
- * Since: 2.4
- **/
-gpointer
-g_queue_pop_nth (GQueue *queue,
- guint n)
-{
- GList *nth_link;
- gpointer result;
-
- g_return_val_if_fail (queue != NULL, NULL);
-
- if (n >= queue->length)
- return NULL;
-
- nth_link = g_queue_peek_nth_link (queue, n);
- result = nth_link->data;
-
- g_queue_delete_link (queue, nth_link);
-
- return result;
-}
-
-/**
- * g_queue_pop_tail_link:
- * @queue: a #GQueue.
- *
- * Removes the last element of the queue.
- *
- * Returns: the #GList element at the tail of the queue, or %NULL if the queue
- * is empty.
- **/
-GList*
-g_queue_pop_tail_link (GQueue *queue)
-{
- g_return_val_if_fail (queue != NULL, NULL);
-
- if (queue->tail)
- {
- GList *node = queue->tail;
-
- queue->tail = node->prev;
- if (queue->tail)
- {
- queue->tail->next = NULL;
- node->prev = NULL;
- }
- else
- queue->head = NULL;
- queue->length--;
-
- return node;
- }
-
- return NULL;
-}
-
-/**
- * g_queue_pop_nth_link:
- * @queue: a #GQueue
- * @n: the link's position
- *
- * Removes and returns the link at the given position.
- *
- * Return value: The @n'th link, or %NULL if @n is off the end of @queue.
- *
- * Since: 2.4
- **/
-GList*
-g_queue_pop_nth_link (GQueue *queue,
- guint n)
-{
- GList *link;
-
- g_return_val_if_fail (queue != NULL, NULL);
-
- if (n >= queue->length)
- return NULL;
-
- link = g_queue_peek_nth_link (queue, n);
- g_queue_unlink (queue, link);
-
- return link;
-}
-
-/**
- * g_queue_peek_nth_link:
- * @queue: a #GQueue
- * @n: the position of the link
- *
- * Returns the link at the given position
- *
- * Return value: The link at the @n'th position, or %NULL if @n is off the
- * end of the list
- *
- * Since: 2.4
- **/
-GList *
-g_queue_peek_nth_link (GQueue *queue,
- guint n)
-{
- GList *link;
- gint i;
-
- g_return_val_if_fail (queue != NULL, NULL);
-
- if (n >= queue->length)
- return NULL;
-
- if (n > queue->length / 2)
- {
- n = queue->length - n - 1;
-
- link = queue->tail;
- for (i = 0; i < n; ++i)
- link = link->prev;
- }
- else
- {
- link = queue->head;
- for (i = 0; i < n; ++i)
- link = link->next;
- }
-
- return link;
-}
-
-/**
- * g_queue_link_index:
- * @queue: a #Gqueue
- * @link_: A #GList link
- *
- * Returns the position of @link_ in @queue.
- *
- * Return value: The position of @link_, or -1 if the link is
- * not part of @queue
- *
- * Since: 2.4
- **/
-gint
-g_queue_link_index (GQueue *queue,
- GList *link_)
-{
- g_return_val_if_fail (queue != NULL, -1);
-
- return g_list_position (queue->head, link_);
-}
-
-/**
- * g_queue_unlink
- * @queue: a #GQueue
- * @link_: a #GList link that <emphasis>must</emphasis> be part of @queue
- *
- * Unlinks @link_ so that it will no longer be part of @queue. The link is
- * not freed.
- *
- * @link_ must be part of @queue,
- *
- * Since: 2.4
- **/
-void
-g_queue_unlink (GQueue *queue,
- GList *link_)
-{
- g_return_if_fail (queue != NULL);
- g_return_if_fail (link_ != NULL);
-
- if (link_ == queue->tail)
- queue->tail = queue->tail->prev;
-
- queue->head = g_list_remove_link (queue->head, link_);
- queue->length--;
-}
-
-/**
- * g_queue_delete_link:
- * @queue: a #GQueue
- * @link_: a #GList link that <emphasis>must</emphasis> be part of @queue
- *
- * Removes @link_ from @queue and frees it.
- *
- * @link_ must be part of @queue.
- *
- * Since: 2.4
- **/
-void
-g_queue_delete_link (GQueue *queue,
- GList *link_)
-{
- g_return_if_fail (queue != NULL);
- g_return_if_fail (link_ != NULL);
-
- g_queue_unlink (queue, link_);
- g_list_free (link_);
-}
-
-/**
- * g_queue_peek_head:
- * @queue: a #GQueue.
- *
- * Returns the first element of the queue.
- *
- * Returns: the data of the first element in the queue, or %NULL if the queue
- * is empty.
- **/
-gpointer
-g_queue_peek_head (GQueue *queue)
-{
- g_return_val_if_fail (queue != NULL, NULL);
-
- return queue->head ? queue->head->data : NULL;
-}
-
-/**
- * g_queue_peek_tail:
- * @queue: a #GQueue.
- *
- * Returns the last element of the queue.
- *
- * Returns: the data of the last element in the queue, or %NULL if the queue
- * is empty.
- **/
-gpointer
-g_queue_peek_tail (GQueue *queue)
-{
- g_return_val_if_fail (queue != NULL, NULL);
-
- return queue->tail ? queue->tail->data : NULL;
-}
-
-/**
- * g_queue_peek_nth:
- * @queue: a #GQueue
- * @n: the position of the element.
- *
- * Returns the @n'th element of @queue.
- *
- * Return value: The data for the @n'th element of @queue, or %NULL if @n is
- * off the end of @queue.
- *
- * Since: 2.4
- **/
-gpointer
-g_queue_peek_nth (GQueue *queue,
- guint n)
-{
- GList *link;
-
- g_return_val_if_fail (queue != NULL, NULL);
-
- link = g_queue_peek_nth_link (queue, n);
-
- if (link)
- return link->data;
-
- return NULL;
-}
-
-/**
- * g_queue_index:
- * @queue: a #GQueue
- * @data: the data to find.
- *
- * Returns the position of the first element in @queue which contains @data.
- *
- * Return value: The position of the first element in @queue which contains @data, or -1 if no element in @queue contains @data.
- *
- * Since: 2.4
- **/
-gint
-g_queue_index (GQueue *queue,
- gconstpointer data)
-{
- g_return_val_if_fail (queue != NULL, -1);
-
- return g_list_index (queue->head, data);
-}
-
-/**
- * g_queue_remove:
- * @queue: a #GQueue
- * @data: data to remove.
- *
- * Removes the first element in @queue that contains @data.
- *
- * Since: 2.4
- **/
-void
-g_queue_remove (GQueue *queue,
- gconstpointer data)
-{
- GList *link;
-
- g_return_if_fail (queue != NULL);
-
- link = g_list_find (queue->head, data);
-
- if (link)
- g_queue_delete_link (queue, link);
-}
-
-/**
- * g_queue_remove_all:
- * @queue: a #GQueue
- * @data: data to remove
- *
- * Remove all elemeents in @queue which contains @data.
- *
- * Since: 2.4
- **/
-void
-g_queue_remove_all (GQueue *queue,
- gconstpointer data)
-{
- GList *list;
-
- g_return_if_fail (queue != NULL);
-
- list = queue->head;
- while (list)
- {
- GList *next = list->next;
-
- if (list->data == data)
- g_queue_delete_link (queue, list);
-
- list = next;
- }
-}
-
-/**
- * g_queue_insert_before:
- * @queue: a #GQueue
- * @sibling: a #GList link that <emphasis>must</emphasis> be part of @queue
- * @data: the data to insert
- *
- * Inserts @data into @queue before @sibling.
- *
- * @sibling must be part of @queue.
- *
- * Since: 2.4
- **/
-void
-g_queue_insert_before (GQueue *queue,
- GList *sibling,
- gpointer data)
-{
- g_return_if_fail (queue != NULL);
- g_return_if_fail (sibling != NULL);
-
- queue->head = g_list_insert_before (queue->head, sibling, data);
- queue->length++;
-}
-
-/**
- * g_queue_insert_after:
- * @queue: a #GQueue
- * @sibling: a #GList link that <emphasis>must</emphasis> be part of @queue
- * @data: the data to insert
- *
- * Inserts @data into @queue after @sibling
- *
- * @sibling must be part of @queue
- *
- * Since: 2.4
- **/
-void
-g_queue_insert_after (GQueue *queue,
- GList *sibling,
- gpointer data)
-{
- g_return_if_fail (queue != NULL);
- g_return_if_fail (sibling != NULL);
-
- if (sibling == queue->tail)
- g_queue_push_tail (queue, data);
- else
- g_queue_insert_before (queue, sibling->next, data);
-}
-
-/**
- * g_queue_insert_sorted:
- * @queue: a #GQueue
- * @data: the data to insert
- * @func: the #GCompareDataFunc used to compare elements in the queue. It is
- * called with two elements of the @queue and @user_data. It should
- * return 0 if the elements are equal, a negative value if the first
- * element comes before the second, and a positive value if the second
- * element comes before the first.
- * @user_data: user data passed to @func.
- *
- * Inserts @data into @queue using @func to determine the new position.
- *
- * Since: 2.4
- **/
-void
-g_queue_insert_sorted (GQueue *queue,
- gpointer data,
- GCompareDataFunc func,
- gpointer user_data)
-{
- GList *list;
-
- g_return_if_fail (queue != NULL);
-
- list = queue->head;
- while (list && func (list->data, data, user_data) < 0)
- list = list->next;
-
- if (list)
- g_queue_insert_before (queue, list, data);
- else
- g_queue_push_tail (queue, data);
-}
-
-#define __G_QUEUE_C__
-#include "galiasdef.c"
diff --git a/glib/gregex.c b/glib/gregex.c
deleted file mode 100644
index 091b418eb..000000000
--- a/glib/gregex.c
+++ /dev/null
@@ -1,2762 +0,0 @@
-/* GRegex -- regular expression API wrapper around PCRE.
- *
- * Copyright (C) 1999, 2000 Scott Wimer
- * Copyright (C) 2004, Matthias Clasen <mclasen@redhat.com>
- * Copyright (C) 2005 - 2007, Marco Barisione <marco@barisione.org>
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include "glib.h"
-#include "glibintl.h"
-#include "gregex.h"
-
-#ifdef USE_SYSTEM_PCRE
-#include <pcre.h>
-#else
-#include "pcre/pcre.h"
-#endif
-
-/* PCRE 7.3 does not contain the definition of PCRE_ERROR_NULLWSLIMIT */
-#ifndef PCRE_ERROR_NULLWSLIMIT
-#define PCRE_ERROR_NULLWSLIMIT (-22)
-#endif
-
-#include "galias.h"
-
-/* Mask of all the possible values for GRegexCompileFlags. */
-#define G_REGEX_COMPILE_MASK (G_REGEX_CASELESS | \
- G_REGEX_MULTILINE | \
- G_REGEX_DOTALL | \
- G_REGEX_EXTENDED | \
- G_REGEX_ANCHORED | \
- G_REGEX_DOLLAR_ENDONLY | \
- G_REGEX_UNGREEDY | \
- G_REGEX_RAW | \
- G_REGEX_NO_AUTO_CAPTURE | \
- G_REGEX_OPTIMIZE | \
- G_REGEX_DUPNAMES | \
- G_REGEX_NEWLINE_CR | \
- G_REGEX_NEWLINE_LF | \
- G_REGEX_NEWLINE_CRLF)
-
-/* Mask of all the possible values for GRegexMatchFlags. */
-#define G_REGEX_MATCH_MASK (G_REGEX_MATCH_ANCHORED | \
- G_REGEX_MATCH_NOTBOL | \
- G_REGEX_MATCH_NOTEOL | \
- G_REGEX_MATCH_NOTEMPTY | \
- G_REGEX_MATCH_PARTIAL | \
- G_REGEX_MATCH_NEWLINE_CR | \
- G_REGEX_MATCH_NEWLINE_LF | \
- G_REGEX_MATCH_NEWLINE_CRLF | \
- G_REGEX_MATCH_NEWLINE_ANY)
-
-/* if the string is in UTF-8 use g_utf8_ functions, else use
- * use just +/- 1. */
-#define NEXT_CHAR(re, s) (((re)->compile_opts & PCRE_UTF8) ? \
- g_utf8_next_char (s) : \
- ((s) + 1))
-#define PREV_CHAR(re, s) (((re)->compile_opts & PCRE_UTF8) ? \
- g_utf8_prev_char (s) : \
- ((s) - 1))
-
-struct _GMatchInfo
-{
- GRegex *regex; /* the regex */
- GRegexMatchFlags match_opts; /* options used at match time on the regex */
- gint matches; /* number of matching sub patterns */
- gint pos; /* position in the string where last match left off */
- gint *offsets; /* array of offsets paired 0,1 ; 2,3 ; 3,4 etc */
- gint n_offsets; /* number of offsets */
- gint *workspace; /* workspace for pcre_dfa_exec() */
- gint n_workspace; /* number of workspace elements */
- const gchar *string; /* string passed to the match function */
- gssize string_len; /* length of string */
-};
-
-struct _GRegex
-{
- volatile gint ref_count; /* the ref count for the immutable part */
- gchar *pattern; /* the pattern */
- pcre *pcre_re; /* compiled form of the pattern */
- GRegexCompileFlags compile_opts; /* options used at compile time on the pattern */
- GRegexMatchFlags match_opts; /* options used at match time on the regex */
- pcre_extra *extra; /* data stored when G_REGEX_OPTIMIZE is used */
-};
-
-/* TRUE if ret is an error code, FALSE otherwise. */
-#define IS_PCRE_ERROR(ret) ((ret) < PCRE_ERROR_NOMATCH && (ret) != PCRE_ERROR_PARTIAL)
-
-typedef struct _InterpolationData InterpolationData;
-static gboolean interpolation_list_needs_match (GList *list);
-static gboolean interpolate_replacement (const GMatchInfo *match_info,
- GString *result,
- gpointer data);
-static GList *split_replacement (const gchar *replacement,
- GError **error);
-static void free_interpolation_data (InterpolationData *data);
-
-
-static const gchar *
-match_error (gint errcode)
-{
- switch (errcode)
- {
- case PCRE_ERROR_NOMATCH:
- /* not an error */
- break;
- case PCRE_ERROR_NULL:
- /* NULL argument, this should not happen in GRegex */
- g_warning ("A NULL argument was passed to PCRE");
- break;
- case PCRE_ERROR_BADOPTION:
- return "bad options";
- case PCRE_ERROR_BADMAGIC:
- return _("corrupted object");
- case PCRE_ERROR_UNKNOWN_OPCODE:
- return N_("internal error or corrupted object");
- case PCRE_ERROR_NOMEMORY:
- return _("out of memory");
- case PCRE_ERROR_NOSUBSTRING:
- /* not used by pcre_exec() */
- break;
- case PCRE_ERROR_MATCHLIMIT:
- return _("backtracking limit reached");
- case PCRE_ERROR_CALLOUT:
- /* callouts are not implemented */
- break;
- case PCRE_ERROR_BADUTF8:
- case PCRE_ERROR_BADUTF8_OFFSET:
- /* we do not check if strings are valid */
- break;
- case PCRE_ERROR_PARTIAL:
- /* not an error */
- break;
- case PCRE_ERROR_BADPARTIAL:
- return _("the pattern contains items not supported for partial matching");
- case PCRE_ERROR_INTERNAL:
- return _("internal error");
- case PCRE_ERROR_BADCOUNT:
- /* negative ovecsize, this should not happen in GRegex */
- g_warning ("A negative ovecsize was passed to PCRE");
- break;
- case PCRE_ERROR_DFA_UITEM:
- return _("the pattern contains items not supported for partial matching");
- case PCRE_ERROR_DFA_UCOND:
- return _("back references as conditions are not supported for partial matching");
- case PCRE_ERROR_DFA_UMLIMIT:
- /* the match_field field is not used in GRegex */
- break;
- case PCRE_ERROR_DFA_WSSIZE:
- /* handled expanding the workspace */
- break;
- case PCRE_ERROR_DFA_RECURSE:
- case PCRE_ERROR_RECURSIONLIMIT:
- return _("recursion limit reached");
- case PCRE_ERROR_NULLWSLIMIT:
- return _("workspace limit for empty substrings reached");
- case PCRE_ERROR_BADNEWLINE:
- return _("invalid combination of newline flags");
- default:
- break;
- }
- return _("unknown error");
-}
-
-static void
-translate_compile_error (gint *errcode, const gchar **errmsg)
-{
- /* Compile errors are created adding 100 to the error code returned
- * by PCRE.
- * If errcode is known we put the translatable error message in
- * erromsg. If errcode is unknown we put the generic
- * G_REGEX_ERROR_COMPILE error code in errcode and keep the
- * untranslated error message returned by PCRE.
- * Note that there can be more PCRE errors with the same GRegexError
- * and that some PCRE errors are useless for us.
- */
- *errcode += 100;
-
- switch (*errcode)
- {
- case G_REGEX_ERROR_STRAY_BACKSLASH:
- *errmsg = _("\\ at end of pattern");
- break;
- case G_REGEX_ERROR_MISSING_CONTROL_CHAR:
- *errmsg = _("\\c at end of pattern");
- break;
- case G_REGEX_ERROR_UNRECOGNIZED_ESCAPE:
- *errmsg = _("unrecognized character follows \\");
- break;
- case 137:
- /* A number of Perl escapes are not handled by PCRE.
- * Therefore it explicitly raises ERR37.
- */
- *errcode = G_REGEX_ERROR_UNRECOGNIZED_ESCAPE;
- *errmsg = _("case-changing escapes (\\l, \\L, \\u, \\U) are not allowed here");
- break;
- case G_REGEX_ERROR_QUANTIFIERS_OUT_OF_ORDER:
- *errmsg = _("numbers out of order in {} quantifier");
- break;
- case G_REGEX_ERROR_QUANTIFIER_TOO_BIG:
- *errmsg = _("number too big in {} quantifier");
- break;
- case G_REGEX_ERROR_UNTERMINATED_CHARACTER_CLASS:
- *errmsg = _("missing terminating ] for character class");
- break;
- case G_REGEX_ERROR_INVALID_ESCAPE_IN_CHARACTER_CLASS:
- *errmsg = _("invalid escape sequence in character class");
- break;
- case G_REGEX_ERROR_RANGE_OUT_OF_ORDER:
- *errmsg = _("range out of order in character class");
- break;
- case G_REGEX_ERROR_NOTHING_TO_REPEAT:
- *errmsg = _("nothing to repeat");
- break;
- case G_REGEX_ERROR_UNRECOGNIZED_CHARACTER:
- *errmsg = _("unrecognized character after (?");
- break;
- case 124:
- *errcode = G_REGEX_ERROR_UNRECOGNIZED_CHARACTER;
- *errmsg = _("unrecognized character after (?<");
- break;
- case 141:
- *errcode = G_REGEX_ERROR_UNRECOGNIZED_CHARACTER;
- *errmsg = _("unrecognized character after (?P");
- break;
- case G_REGEX_ERROR_POSIX_NAMED_CLASS_OUTSIDE_CLASS:
- *errmsg = _("POSIX named classes are supported only within a class");
- break;
- case G_REGEX_ERROR_UNMATCHED_PARENTHESIS:
- *errmsg = _("missing terminating )");
- break;
- case 122:
- *errcode = G_REGEX_ERROR_UNMATCHED_PARENTHESIS;
- *errmsg = _(") without opening (");
- break;
- case 129:
- *errcode = G_REGEX_ERROR_UNMATCHED_PARENTHESIS;
- /* translators: '(?R' and '(?[+-]digits' are both meant as (groups of)
- * sequences here, '(?-54' would be an example for the second group.
- */
- *errmsg = _("(?R or (?[+-]digits must be followed by )");
- break;
- case G_REGEX_ERROR_INEXISTENT_SUBPATTERN_REFERENCE:
- *errmsg = _("reference to non-existent subpattern");
- break;
- case G_REGEX_ERROR_UNTERMINATED_COMMENT:
- *errmsg = _("missing ) after comment");
- break;
- case G_REGEX_ERROR_EXPRESSION_TOO_LARGE:
- *errmsg = _("regular expression too large");
- break;
- case G_REGEX_ERROR_MEMORY_ERROR:
- *errmsg = _("failed to get memory");
- break;
- case G_REGEX_ERROR_VARIABLE_LENGTH_LOOKBEHIND:
- *errmsg = _("lookbehind assertion is not fixed length");
- break;
- case G_REGEX_ERROR_MALFORMED_CONDITION:
- *errmsg = _("malformed number or name after (?(");
- break;
- case G_REGEX_ERROR_TOO_MANY_CONDITIONAL_BRANCHES:
- *errmsg = _("conditional group contains more than two branches");
- break;
- case G_REGEX_ERROR_ASSERTION_EXPECTED:
- *errmsg = _("assertion expected after (?(");
- break;
- case G_REGEX_ERROR_UNKNOWN_POSIX_CLASS_NAME:
- *errmsg = _("unknown POSIX class name");
- break;
- case G_REGEX_ERROR_POSIX_COLLATING_ELEMENTS_NOT_SUPPORTED:
- *errmsg = _("POSIX collating elements are not supported");
- break;
- case G_REGEX_ERROR_HEX_CODE_TOO_LARGE:
- *errmsg = _("character value in \\x{...} sequence is too large");
- break;
- case G_REGEX_ERROR_INVALID_CONDITION:
- *errmsg = _("invalid condition (?(0)");
- break;
- case G_REGEX_ERROR_SINGLE_BYTE_MATCH_IN_LOOKBEHIND:
- *errmsg = _("\\C not allowed in lookbehind assertion");
- break;
- case G_REGEX_ERROR_INFINITE_LOOP:
- *errmsg = _("recursive call could loop indefinitely");
- break;
- case G_REGEX_ERROR_MISSING_SUBPATTERN_NAME_TERMINATOR:
- *errmsg = _("missing terminator in subpattern name");
- break;
- case G_REGEX_ERROR_DUPLICATE_SUBPATTERN_NAME:
- *errmsg = _("two named subpatterns have the same name");
- break;
- case G_REGEX_ERROR_MALFORMED_PROPERTY:
- *errmsg = _("malformed \\P or \\p sequence");
- break;
- case G_REGEX_ERROR_UNKNOWN_PROPERTY:
- *errmsg = _("unknown property name after \\P or \\p");
- break;
- case G_REGEX_ERROR_SUBPATTERN_NAME_TOO_LONG:
- *errmsg = _("subpattern name is too long (maximum 32 characters)");
- break;
- case G_REGEX_ERROR_TOO_MANY_SUBPATTERNS:
- *errmsg = _("too many named subpatterns (maximum 10,000)");
- break;
- case G_REGEX_ERROR_INVALID_OCTAL_VALUE:
- *errmsg = _("octal value is greater than \\377");
- break;
- case G_REGEX_ERROR_TOO_MANY_BRANCHES_IN_DEFINE:
- *errmsg = _("DEFINE group contains more than one branch");
- break;
- case G_REGEX_ERROR_DEFINE_REPETION:
- *errmsg = _("repeating a DEFINE group is not allowed");
- break;
- case G_REGEX_ERROR_INCONSISTENT_NEWLINE_OPTIONS:
- *errmsg = _("inconsistent NEWLINE options");
- break;
- case G_REGEX_ERROR_MISSING_BACK_REFERENCE:
- *errmsg = _("\\g is not followed by a braced name or an optionally "
- "braced non-zero number");
- break;
- case 11:
- *errcode = G_REGEX_ERROR_INTERNAL;
- *errmsg = _("unexpected repeat");
- break;
- case 23:
- *errcode = G_REGEX_ERROR_INTERNAL;
- *errmsg = _("code overflow");
- break;
- case 52:
- *errcode = G_REGEX_ERROR_INTERNAL;
- *errmsg = _("overran compiling workspace");
- break;
- case 53:
- *errcode = G_REGEX_ERROR_INTERNAL;
- *errmsg = _("previously-checked referenced subpattern not found");
- break;
- case 16:
- /* This should not happen as we never pass a NULL erroffset */
- g_warning ("erroffset passed as NULL");
- *errcode = G_REGEX_ERROR_COMPILE;
- break;
- case 17:
- /* This should not happen as we check options before passing them
- * to pcre_compile2() */
- g_warning ("unknown option bit(s) set");
- *errcode = G_REGEX_ERROR_COMPILE;
- break;
- case 32:
- case 44:
- case 45:
- /* These errors should not happen as we are using an UTF8-enabled PCRE
- * and we do not check if strings are valid */
- g_warning ("%s", *errmsg);
- *errcode = G_REGEX_ERROR_COMPILE;
- break;
- default:
- *errcode = G_REGEX_ERROR_COMPILE;
- }
-}
-
-/* GMatchInfo */
-
-static GMatchInfo *
-match_info_new (const GRegex *regex,
- const gchar *string,
- gint string_len,
- gint start_position,
- gint match_options,
- gboolean is_dfa)
-{
- GMatchInfo *match_info;
-
- if (string_len < 0)
- string_len = strlen (string);
-
- match_info = g_new0 (GMatchInfo, 1);
- match_info->regex = g_regex_ref ((GRegex *)regex);
- match_info->string = string;
- match_info->string_len = string_len;
- match_info->matches = PCRE_ERROR_NOMATCH;
- match_info->pos = start_position;
- match_info->match_opts = match_options;
-
- if (is_dfa)
- {
- /* These values should be enough for most cases, if they are not
- * enough g_regex_match_all_full() will expand them. */
- match_info->n_offsets = 24;
- match_info->n_workspace = 100;
- match_info->workspace = g_new (gint, match_info->n_workspace);
- }
- else
- {
- gint capture_count;
- pcre_fullinfo (regex->pcre_re, regex->extra,
- PCRE_INFO_CAPTURECOUNT, &capture_count);
- match_info->n_offsets = (capture_count + 1) * 3;
- }
-
- match_info->offsets = g_new0 (gint, match_info->n_offsets);
- /* Set an invalid position for the previous match. */
- match_info->offsets[0] = -1;
- match_info->offsets[1] = -1;
-
- return match_info;
-}
-
-/**
- * g_match_info_get_regex:
- * @match_info: a #GMatchInfo
- *
- * Returns #GRegex object used in @match_info. It belongs to Glib
- * and must not be freed. Use g_regex_ref() if you need to keep it
- * after you free @match_info object.
- *
- * Returns: #GRegex object used in @match_info
- *
- * Since: 2.14
- */
-GRegex *
-g_match_info_get_regex (const GMatchInfo *match_info)
-{
- g_return_val_if_fail (match_info != NULL, NULL);
- return match_info->regex;
-}
-
-/**
- * g_match_info_get_string:
- * @match_info: a #GMatchInfo
- *
- * Returns the string searched with @match_info. This is the
- * string passed to g_regex_match() or g_regex_replace() so
- * you may not free it before calling this function.
- *
- * Returns: the string searched with @match_info
- *
- * Since: 2.14
- */
-const gchar *
-g_match_info_get_string (const GMatchInfo *match_info)
-{
- g_return_val_if_fail (match_info != NULL, NULL);
- return match_info->string;
-}
-
-/**
- * g_match_info_free:
- * @match_info: a #GMatchInfo
- *
- * Frees all the memory associated with the #GMatchInfo structure.
- *
- * Since: 2.14
- */
-void
-g_match_info_free (GMatchInfo *match_info)
-{
- if (match_info)
- {
- g_regex_unref (match_info->regex);
- g_free (match_info->offsets);
- g_free (match_info->workspace);
- g_free (match_info);
- }
-}
-
-/**
- * g_match_info_next:
- * @match_info: a #GMatchInfo structure
- * @error: location to store the error occuring, or %NULL to ignore errors
- *
- * Scans for the next match using the same parameters of the previous
- * call to g_regex_match_full() or g_regex_match() that returned
- * @match_info.
- *
- * The match is done on the string passed to the match function, so you
- * cannot free it before calling this function.
- *
- * Returns: %TRUE is the string matched, %FALSE otherwise
- *
- * Since: 2.14
- */
-gboolean
-g_match_info_next (GMatchInfo *match_info,
- GError **error)
-{
- gint opts;
- gint prev_match_start;
- gint prev_match_end;
-
- g_return_val_if_fail (match_info != NULL, FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- g_return_val_if_fail (match_info->pos >= 0, FALSE);
-
- opts = match_info->regex->match_opts | match_info->match_opts;
-
- prev_match_start = match_info->offsets[0];
- prev_match_end = match_info->offsets[1];
-
- match_info->matches = pcre_exec (match_info->regex->pcre_re,
- match_info->regex->extra,
- match_info->string,
- match_info->string_len,
- match_info->pos,
- match_info->regex->match_opts |
- match_info->match_opts,
- match_info->offsets,
- match_info->n_offsets);
- if (IS_PCRE_ERROR (match_info->matches))
- {
- g_set_error (error, G_REGEX_ERROR, G_REGEX_ERROR_MATCH,
- _("Error while matching regular expression %s: %s"),
- match_info->regex->pattern, match_error (match_info->matches));
- return FALSE;
- }
-
- /* avoid infinite loops if the pattern is an empty string or something
- * equivalent */
- if (match_info->pos == match_info->offsets[1])
- {
- if (match_info->pos > match_info->string_len)
- {
- /* we have reached the end of the string */
- match_info->pos = -1;
- match_info->matches = PCRE_ERROR_NOMATCH;
- return FALSE;
- }
-
- match_info->pos = NEXT_CHAR (match_info->regex,
- &match_info->string[match_info->pos]) -
- match_info->string;
- }
- else
- {
- match_info->pos = match_info->offsets[1];
- }
-
- /* it's possibile to get two identical matches when we are matching
- * empty strings, for instance if the pattern is "(?=[A-Z0-9])" and
- * the string is "RegExTest" we have:
- * - search at position 0: match from 0 to 0
- * - search at position 1: match from 3 to 3
- * - search at position 3: match from 3 to 3 (duplicate)
- * - search at position 4: match from 5 to 5
- * - search at position 5: match from 5 to 5 (duplicate)
- * - search at position 6: no match -> stop
- * so we have to ignore the duplicates.
- * see bug #515944: http://bugzilla.gnome.org/show_bug.cgi?id=515944 */
- if (match_info->matches >= 0 &&
- prev_match_start == match_info->offsets[0] &&
- prev_match_end == match_info->offsets[1])
- {
- /* ignore this match and search the next one */
- return g_match_info_next (match_info, error);
- }
-
- return match_info->matches >= 0;
-}
-
-/**
- * g_match_info_matches:
- * @match_info: a #GMatchInfo structure
- *
- * Returns whether the previous match operation succeeded.
- *
- * Returns: %TRUE if the previous match operation succeeded,
- * %FALSE otherwise
- *
- * Since: 2.14
- */
-gboolean
-g_match_info_matches (const GMatchInfo *match_info)
-{
- g_return_val_if_fail (match_info != NULL, FALSE);
-
- return match_info->matches >= 0;
-}
-
-/**
- * g_match_info_get_match_count:
- * @match_info: a #GMatchInfo structure
- *
- * Retrieves the number of matched substrings (including substring 0,
- * that is the whole matched text), so 1 is returned if the pattern
- * has no substrings in it and 0 is returned if the match failed.
- *
- * If the last match was obtained using the DFA algorithm, that is
- * using g_regex_match_all() or g_regex_match_all_full(), the retrieved
- * count is not that of the number of capturing parentheses but that of
- * the number of matched substrings.
- *
- * Returns: Number of matched substrings, or -1 if an error occurred
- *
- * Since: 2.14
- */
-gint
-g_match_info_get_match_count (const GMatchInfo *match_info)
-{
- g_return_val_if_fail (match_info, -1);
-
- if (match_info->matches == PCRE_ERROR_NOMATCH)
- /* no match */
- return 0;
- else if (match_info->matches < PCRE_ERROR_NOMATCH)
- /* error */
- return -1;
- else
- /* match */
- return match_info->matches;
-}
-
-/**
- * g_match_info_is_partial_match:
- * @match_info: a #GMatchInfo structure
- *
- * Usually if the string passed to g_regex_match*() matches as far as
- * it goes, but is too short to match the entire pattern, %FALSE is
- * returned. There are circumstances where it might be helpful to
- * distinguish this case from other cases in which there is no match.
- *
- * Consider, for example, an application where a human is required to
- * type in data for a field with specific formatting requirements. An
- * example might be a date in the form ddmmmyy, defined by the pattern
- * "^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$".
- * If the application sees the user’s keystrokes one by one, and can
- * check that what has been typed so far is potentially valid, it is
- * able to raise an error as soon as a mistake is made.
- *
- * GRegex supports the concept of partial matching by means of the
- * #G_REGEX_MATCH_PARTIAL flag. When this is set the return code for
- * g_regex_match() or g_regex_match_full() is, as usual, %TRUE
- * for a complete match, %FALSE otherwise. But, when these functions
- * return %FALSE, you can check if the match was partial calling
- * g_match_info_is_partial_match().
- *
- * When using partial matching you cannot use g_match_info_fetch*().
- *
- * Because of the way certain internal optimizations are implemented
- * the partial matching algorithm cannot be used with all patterns.
- * So repeated single characters such as "a{2,4}" and repeated single
- * meta-sequences such as "\d+" are not permitted if the maximum number
- * of occurrences is greater than one. Optional items such as "\d?"
- * (where the maximum is one) are permitted. Quantifiers with any values
- * are permitted after parentheses, so the invalid examples above can be
- * coded thus "(a){2,4}" and "(\d)+". If #G_REGEX_MATCH_PARTIAL is set
- * for a pattern that does not conform to the restrictions, matching
- * functions return an error.
- *
- * Returns: %TRUE if the match was partial, %FALSE otherwise
- *
- * Since: 2.14
- */
-gboolean
-g_match_info_is_partial_match (const GMatchInfo *match_info)
-{
- g_return_val_if_fail (match_info != NULL, FALSE);
-
- return match_info->matches == PCRE_ERROR_PARTIAL;
-}
-
-/**
- * g_match_info_expand_references:
- * @match_info: a #GMatchInfo or %NULL
- * @string_to_expand: the string to expand
- * @error: location to store the error occuring, or %NULL to ignore errors
- *
- * Returns a new string containing the text in @string_to_expand with
- * references and escape sequences expanded. References refer to the last
- * match done with @string against @regex and have the same syntax used by
- * g_regex_replace().
- *
- * The @string_to_expand must be UTF-8 encoded even if #G_REGEX_RAW was
- * passed to g_regex_new().
- *
- * The backreferences are extracted from the string passed to the match
- * function, so you cannot call this function after freeing the string.
- *
- * @match_info may be %NULL in which case @string_to_expand must not
- * contain references. For instance "foo\n" does not refer to an actual
- * pattern and '\n' merely will be replaced with \n character,
- * while to expand "\0" (whole match) one needs the result of a match.
- * Use g_regex_check_replacement() to find out whether @string_to_expand
- * contains references.
- *
- * Returns: the expanded string, or %NULL if an error occurred
- *
- * Since: 2.14
- */
-gchar *
-g_match_info_expand_references (const GMatchInfo *match_info,
- const gchar *string_to_expand,
- GError **error)
-{
- GString *result;
- GList *list;
- GError *tmp_error = NULL;
-
- g_return_val_if_fail (string_to_expand != NULL, NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- list = split_replacement (string_to_expand, &tmp_error);
- if (tmp_error != NULL)
- {
- g_propagate_error (error, tmp_error);
- return NULL;
- }
-
- if (!match_info && interpolation_list_needs_match (list))
- {
- g_critical ("String '%s' contains references to the match, can't "
- "expand references without GMatchInfo object",
- string_to_expand);
- return NULL;
- }
-
- result = g_string_sized_new (strlen (string_to_expand));
- interpolate_replacement (match_info, result, list);
-
- g_list_foreach (list, (GFunc)free_interpolation_data, NULL);
- g_list_free (list);
-
- return g_string_free (result, FALSE);
-}
-
-/**
- * g_match_info_fetch:
- * @match_info: #GMatchInfo structure
- * @match_num: number of the sub expression
- *
- * Retrieves the text matching the @match_num<!-- -->'th capturing
- * parentheses. 0 is the full text of the match, 1 is the first paren
- * set, 2 the second, and so on.
- *
- * If @match_num is a valid sub pattern but it didn't match anything
- * (e.g. sub pattern 1, matching "b" against "(a)?b") then an empty
- * string is returned.
- *
- * If the match was obtained using the DFA algorithm, that is using
- * g_regex_match_all() or g_regex_match_all_full(), the retrieved
- * string is not that of a set of parentheses but that of a matched
- * substring. Substrings are matched in reverse order of length, so
- * 0 is the longest match.
- *
- * The string is fetched from the string passed to the match function,
- * so you cannot call this function after freeing the string.
- *
- * Returns: The matched substring, or %NULL if an error occurred.
- * You have to free the string yourself
- *
- * Since: 2.14
- */
-gchar *
-g_match_info_fetch (const GMatchInfo *match_info,
- gint match_num)
-{
- /* we cannot use pcre_get_substring() because it allocates the
- * string using pcre_malloc(). */
- gchar *match = NULL;
- gint start, end;
-
- g_return_val_if_fail (match_info != NULL, NULL);
- g_return_val_if_fail (match_num >= 0, NULL);
-
- /* match_num does not exist or it didn't matched, i.e. matching "b"
- * against "(a)?b" then group 0 is empty. */
- if (!g_match_info_fetch_pos (match_info, match_num, &start, &end))
- match = NULL;
- else if (start == -1)
- match = g_strdup ("");
- else
- match = g_strndup (&match_info->string[start], end - start);
-
- return match;
-}
-
-/**
- * g_match_info_fetch_pos:
- * @match_info: #GMatchInfo structure
- * @match_num: number of the sub expression
- * @start_pos: pointer to location where to store the start position
- * @end_pos: pointer to location where to store the end position
- *
- * Retrieves the position in bytes of the @match_num<!-- -->'th capturing
- * parentheses. 0 is the full text of the match, 1 is the first
- * paren set, 2 the second, and so on.
- *
- * If @match_num is a valid sub pattern but it didn't match anything
- * (e.g. sub pattern 1, matching "b" against "(a)?b") then @start_pos
- * and @end_pos are set to -1 and %TRUE is returned.
- *
- * If the match was obtained using the DFA algorithm, that is using
- * g_regex_match_all() or g_regex_match_all_full(), the retrieved
- * position is not that of a set of parentheses but that of a matched
- * substring. Substrings are matched in reverse order of length, so
- * 0 is the longest match.
- *
- * Returns: %TRUE if the position was fetched, %FALSE otherwise. If
- * the position cannot be fetched, @start_pos and @end_pos are left
- * unchanged
- *
- * Since: 2.14
- */
-gboolean
-g_match_info_fetch_pos (const GMatchInfo *match_info,
- gint match_num,
- gint *start_pos,
- gint *end_pos)
-{
- g_return_val_if_fail (match_info != NULL, FALSE);
- g_return_val_if_fail (match_num >= 0, FALSE);
-
- /* make sure the sub expression number they're requesting is less than
- * the total number of sub expressions that were matched. */
- if (match_num >= match_info->matches)
- return FALSE;
-
- if (start_pos != NULL)
- *start_pos = match_info->offsets[2 * match_num];
-
- if (end_pos != NULL)
- *end_pos = match_info->offsets[2 * match_num + 1];
-
- return TRUE;
-}
-
-/*
- * Returns number of first matched subpattern with name @name.
- * There may be more than one in case when DUPNAMES is used,
- * and not all subpatterns with that name match;
- * pcre_get_stringnumber() does not work in that case.
- */
-static gint
-get_matched_substring_number (const GMatchInfo *match_info,
- const gchar *name)
-{
- gint entrysize;
- gchar *first, *last;
- guchar *entry;
-
- if (!(match_info->regex->compile_opts & G_REGEX_DUPNAMES))
- return pcre_get_stringnumber (match_info->regex->pcre_re, name);
-
- /* This code is copied from pcre_get.c: get_first_set() */
- entrysize = pcre_get_stringtable_entries (match_info->regex->pcre_re,
- name,
- &first,
- &last);
-
- if (entrysize <= 0)
- return entrysize;
-
- for (entry = (guchar*) first; entry <= (guchar*) last; entry += entrysize)
- {
- gint n = (entry[0] << 8) + entry[1];
- if (match_info->offsets[n*2] >= 0)
- return n;
- }
-
- return (first[0] << 8) + first[1];
-}
-
-/**
- * g_match_info_fetch_named:
- * @match_info: #GMatchInfo structure
- * @name: name of the subexpression
- *
- * Retrieves the text matching the capturing parentheses named @name.
- *
- * If @name is a valid sub pattern name but it didn't match anything
- * (e.g. sub pattern "X", matching "b" against "(?P&lt;X&gt;a)?b")
- * then an empty string is returned.
- *
- * The string is fetched from the string passed to the match function,
- * so you cannot call this function after freeing the string.
- *
- * Returns: The matched substring, or %NULL if an error occurred.
- * You have to free the string yourself
- *
- * Since: 2.14
- */
-gchar *
-g_match_info_fetch_named (const GMatchInfo *match_info,
- const gchar *name)
-{
- /* we cannot use pcre_get_named_substring() because it allocates the
- * string using pcre_malloc(). */
- gint num;
-
- g_return_val_if_fail (match_info != NULL, NULL);
- g_return_val_if_fail (name != NULL, NULL);
-
- num = get_matched_substring_number (match_info, name);
- if (num < 0)
- return NULL;
- else
- return g_match_info_fetch (match_info, num);
-}
-
-/**
- * g_match_info_fetch_named_pos:
- * @match_info: #GMatchInfo structure
- * @name: name of the subexpression
- * @start_pos: pointer to location where to store the start position
- * @end_pos: pointer to location where to store the end position
- *
- * Retrieves the position in bytes of the capturing parentheses named @name.
- *
- * If @name is a valid sub pattern name but it didn't match anything
- * (e.g. sub pattern "X", matching "b" against "(?P&lt;X&gt;a)?b")
- * then @start_pos and @end_pos are set to -1 and %TRUE is returned.
- *
- * Returns: %TRUE if the position was fetched, %FALSE otherwise. If
- * the position cannot be fetched, @start_pos and @end_pos are left
- * unchanged
- *
- * Since: 2.14
- */
-gboolean
-g_match_info_fetch_named_pos (const GMatchInfo *match_info,
- const gchar *name,
- gint *start_pos,
- gint *end_pos)
-{
- gint num;
-
- g_return_val_if_fail (match_info != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
-
- num = get_matched_substring_number (match_info, name);
- if (num < 0)
- return FALSE;
-
- return g_match_info_fetch_pos (match_info, num, start_pos, end_pos);
-}
-
-/**
- * g_match_info_fetch_all:
- * @match_info: a #GMatchInfo structure
- *
- * Bundles up pointers to each of the matching substrings from a match
- * and stores them in an array of gchar pointers. The first element in
- * the returned array is the match number 0, i.e. the entire matched
- * text.
- *
- * If a sub pattern didn't match anything (e.g. sub pattern 1, matching
- * "b" against "(a)?b") then an empty string is inserted.
- *
- * If the last match was obtained using the DFA algorithm, that is using
- * g_regex_match_all() or g_regex_match_all_full(), the retrieved
- * strings are not that matched by sets of parentheses but that of the
- * matched substring. Substrings are matched in reverse order of length,
- * so the first one is the longest match.
- *
- * The strings are fetched from the string passed to the match function,
- * so you cannot call this function after freeing the string.
- *
- * Returns: a %NULL-terminated array of gchar * pointers. It must be
- * freed using g_strfreev(). If the previous match failed %NULL is
- * returned
- *
- * Since: 2.14
- */
-gchar **
-g_match_info_fetch_all (const GMatchInfo *match_info)
-{
- /* we cannot use pcre_get_substring_list() because the returned value
- * isn't suitable for g_strfreev(). */
- gchar **result;
- gint i;
-
- g_return_val_if_fail (match_info != NULL, NULL);
-
- if (match_info->matches < 0)
- return NULL;
-
- result = g_new (gchar *, match_info->matches + 1);
- for (i = 0; i < match_info->matches; i++)
- result[i] = g_match_info_fetch (match_info, i);
- result[i] = NULL;
-
- return result;
-}
-
-
-/* GRegex */
-
-GQuark
-g_regex_error_quark (void)
-{
- static GQuark error_quark = 0;
-
- if (error_quark == 0)
- error_quark = g_quark_from_static_string ("g-regex-error-quark");
-
- return error_quark;
-}
-
-/**
- * g_regex_ref:
- * @regex: a #GRegex
- *
- * Increases reference count of @regex by 1.
- *
- * Returns: @regex
- *
- * Since: 2.14
- */
-GRegex *
-g_regex_ref (GRegex *regex)
-{
- g_return_val_if_fail (regex != NULL, NULL);
- g_atomic_int_inc (&regex->ref_count);
- return regex;
-}
-
-/**
- * g_regex_unref:
- * @regex: a #GRegex
- *
- * Decreases reference count of @regex by 1. When reference count drops
- * to zero, it frees all the memory associated with the regex structure.
- *
- * Since: 2.14
- */
-void
-g_regex_unref (GRegex *regex)
-{
- g_return_if_fail (regex != NULL);
-
- if (g_atomic_int_exchange_and_add (&regex->ref_count, -1) - 1 == 0)
- {
- g_free (regex->pattern);
- if (regex->pcre_re != NULL)
- pcre_free (regex->pcre_re);
- if (regex->extra != NULL)
- pcre_free (regex->extra);
- g_free (regex);
- }
-}
-
-/**
- * g_regex_new:
- * @pattern: the regular expression
- * @compile_options: compile options for the regular expression, or 0
- * @match_options: match options for the regular expression, or 0
- * @error: return location for a #GError
- *
- * Compiles the regular expression to an internal form, and does
- * the initial setup of the #GRegex structure.
- *
- * Returns: a #GRegex structure. Call g_regex_unref() when you
- * are done with it
- *
- * Since: 2.14
- */
-GRegex *
-g_regex_new (const gchar *pattern,
- GRegexCompileFlags compile_options,
- GRegexMatchFlags match_options,
- GError **error)
-{
- GRegex *regex;
- pcre *re;
- const gchar *errmsg;
- gint erroffset;
- gint errcode;
- gboolean optimize = FALSE;
- static gboolean initialized = FALSE;
- unsigned long int pcre_compile_options;
-
- g_return_val_if_fail (pattern != NULL, NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- g_return_val_if_fail ((compile_options & ~G_REGEX_COMPILE_MASK) == 0, NULL);
- g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, NULL);
-
- if (!initialized)
- {
- gint support;
- const gchar *msg;
-
- pcre_config (PCRE_CONFIG_UTF8, &support);
- if (!support)
- {
- msg = N_("PCRE library is compiled without UTF8 support");
- g_critical ("%s", msg);
- g_set_error_literal (error, G_REGEX_ERROR, G_REGEX_ERROR_COMPILE, gettext (msg));
- return NULL;
- }
-
- pcre_config (PCRE_CONFIG_UNICODE_PROPERTIES, &support);
- if (!support)
- {
- msg = N_("PCRE library is compiled without UTF8 properties support");
- g_critical ("%s", msg);
- g_set_error_literal (error, G_REGEX_ERROR, G_REGEX_ERROR_COMPILE, gettext (msg));
- return NULL;
- }
-
- initialized = TRUE;
- }
-
- /* G_REGEX_OPTIMIZE has the same numeric value of PCRE_NO_UTF8_CHECK,
- * as we do not need to wrap PCRE_NO_UTF8_CHECK. */
- if (compile_options & G_REGEX_OPTIMIZE)
- optimize = TRUE;
-
- /* In GRegex the string are, by default, UTF-8 encoded. PCRE
- * instead uses UTF-8 only if required with PCRE_UTF8. */
- if (compile_options & G_REGEX_RAW)
- {
- /* disable utf-8 */
- compile_options &= ~G_REGEX_RAW;
- }
- else
- {
- /* enable utf-8 */
- compile_options |= PCRE_UTF8 | PCRE_NO_UTF8_CHECK;
- match_options |= PCRE_NO_UTF8_CHECK;
- }
-
- /* PCRE_NEWLINE_ANY is the default for the internal PCRE but
- * not for the system one. */
- if (!(compile_options & G_REGEX_NEWLINE_CR) &&
- !(compile_options & G_REGEX_NEWLINE_LF))
- {
- compile_options |= PCRE_NEWLINE_ANY;
- }
-
- /* compile the pattern */
- re = pcre_compile2 (pattern, compile_options, &errcode,
- &errmsg, &erroffset, NULL);
-
- /* if the compilation failed, set the error member and return
- * immediately */
- if (re == NULL)
- {
- GError *tmp_error;
-
- /* Translate the PCRE error code to GRegexError and use a translated
- * error message if possible */
- translate_compile_error (&errcode, &errmsg);
-
- /* PCRE uses byte offsets but we want to show character offsets */
- erroffset = g_utf8_pointer_to_offset (pattern, &pattern[erroffset]);
-
- tmp_error = g_error_new (G_REGEX_ERROR, errcode,
- _("Error while compiling regular "
- "expression %s at char %d: %s"),
- pattern, erroffset, errmsg);
- g_propagate_error (error, tmp_error);
-
- return NULL;
- }
-
- /* For options set at the beginning of the pattern, pcre puts them into
- * compile options, e.g. "(?i)foo" will make the pcre structure store
- * PCRE_CASELESS even though it wasn't explicitly given for compilation. */
- pcre_fullinfo (re, NULL, PCRE_INFO_OPTIONS, &pcre_compile_options);
- compile_options = pcre_compile_options;
-
- if (!(compile_options & G_REGEX_DUPNAMES))
- {
- gboolean jchanged = FALSE;
- pcre_fullinfo (re, NULL, PCRE_INFO_JCHANGED, &jchanged);
- if (jchanged)
- compile_options |= G_REGEX_DUPNAMES;
- }
-
- regex = g_new0 (GRegex, 1);
- regex->ref_count = 1;
- regex->pattern = g_strdup (pattern);
- regex->pcre_re = re;
- regex->compile_opts = compile_options;
- regex->match_opts = match_options;
-
- if (optimize)
- {
- regex->extra = pcre_study (regex->pcre_re, 0, &errmsg);
- if (errmsg != NULL)
- {
- GError *tmp_error = g_error_new (G_REGEX_ERROR,
- G_REGEX_ERROR_OPTIMIZE,
- _("Error while optimizing "
- "regular expression %s: %s"),
- regex->pattern,
- errmsg);
- g_propagate_error (error, tmp_error);
-
- g_regex_unref (regex);
- return NULL;
- }
- }
-
- return regex;
-}
-
-/**
- * g_regex_get_pattern:
- * @regex: a #GRegex structure
- *
- * Gets the pattern string associated with @regex, i.e. a copy of
- * the string passed to g_regex_new().
- *
- * Returns: the pattern of @regex
- *
- * Since: 2.14
- */
-const gchar *
-g_regex_get_pattern (const GRegex *regex)
-{
- g_return_val_if_fail (regex != NULL, NULL);
-
- return regex->pattern;
-}
-
-/**
- * g_regex_get_max_backref:
- * @regex: a #GRegex
- *
- * Returns the number of the highest back reference
- * in the pattern, or 0 if the pattern does not contain
- * back references.
- *
- * Returns: the number of the highest back reference
- *
- * Since: 2.14
- */
-gint
-g_regex_get_max_backref (const GRegex *regex)
-{
- gint value;
-
- pcre_fullinfo (regex->pcre_re, regex->extra,
- PCRE_INFO_BACKREFMAX, &value);
-
- return value;
-}
-
-/**
- * g_regex_get_capture_count:
- * @regex: a #GRegex
- *
- * Returns the number of capturing subpatterns in the pattern.
- *
- * Returns: the number of capturing subpatterns
- *
- * Since: 2.14
- */
-gint
-g_regex_get_capture_count (const GRegex *regex)
-{
- gint value;
-
- pcre_fullinfo (regex->pcre_re, regex->extra,
- PCRE_INFO_CAPTURECOUNT, &value);
-
- return value;
-}
-
-/**
- * g_regex_match_simple:
- * @pattern: the regular expression
- * @string: the string to scan for matches
- * @compile_options: compile options for the regular expression, or 0
- * @match_options: match options, or 0
- *
- * Scans for a match in @string for @pattern.
- *
- * This function is equivalent to g_regex_match() but it does not
- * require to compile the pattern with g_regex_new(), avoiding some
- * lines of code when you need just to do a match without extracting
- * substrings, capture counts, and so on.
- *
- * If this function is to be called on the same @pattern more than
- * once, it's more efficient to compile the pattern once with
- * g_regex_new() and then use g_regex_match().
- *
- * Returns: %TRUE if the string matched, %FALSE otherwise
- *
- * Since: 2.14
- */
-gboolean
-g_regex_match_simple (const gchar *pattern,
- const gchar *string,
- GRegexCompileFlags compile_options,
- GRegexMatchFlags match_options)
-{
- GRegex *regex;
- gboolean result;
-
- regex = g_regex_new (pattern, compile_options, 0, NULL);
- if (!regex)
- return FALSE;
- result = g_regex_match_full (regex, string, -1, 0, match_options, NULL, NULL);
- g_regex_unref (regex);
- return result;
-}
-
-/**
- * g_regex_match:
- * @regex: a #GRegex structure from g_regex_new()
- * @string: the string to scan for matches
- * @match_options: match options
- * @match_info: pointer to location where to store the #GMatchInfo,
- * or %NULL if you do not need it
- *
- * Scans for a match in string for the pattern in @regex.
- * The @match_options are combined with the match options specified
- * when the @regex structure was created, letting you have more
- * flexibility in reusing #GRegex structures.
- *
- * A #GMatchInfo structure, used to get information on the match,
- * is stored in @match_info if not %NULL. Note that if @match_info
- * is not %NULL then it is created even if the function returns %FALSE,
- * i.e. you must free it regardless if regular expression actually matched.
- *
- * To retrieve all the non-overlapping matches of the pattern in
- * string you can use g_match_info_next().
- *
- * |[
- * static void
- * print_uppercase_words (const gchar *string)
- * {
- * /&ast; Print all uppercase-only words. &ast;/
- * GRegex *regex;
- * GMatchInfo *match_info;
- * &nbsp;
- * regex = g_regex_new ("[A-Z]+", 0, 0, NULL);
- * g_regex_match (regex, string, 0, &amp;match_info);
- * while (g_match_info_matches (match_info))
- * {
- * gchar *word = g_match_info_fetch (match_info, 0);
- * g_print ("Found: %s\n", word);
- * g_free (word);
- * g_match_info_next (match_info, NULL);
- * }
- * g_match_info_free (match_info);
- * g_regex_unref (regex);
- * }
- * ]|
- *
- * @string is not copied and is used in #GMatchInfo internally. If
- * you use any #GMatchInfo method (except g_match_info_free()) after
- * freeing or modifying @string then the behaviour is undefined.
- *
- * Returns: %TRUE is the string matched, %FALSE otherwise
- *
- * Since: 2.14
- */
-gboolean
-g_regex_match (const GRegex *regex,
- const gchar *string,
- GRegexMatchFlags match_options,
- GMatchInfo **match_info)
-{
- return g_regex_match_full (regex, string, -1, 0, match_options,
- match_info, NULL);
-}
-
-/**
- * g_regex_match_full:
- * @regex: a #GRegex structure from g_regex_new()
- * @string: the string to scan for matches
- * @string_len: the length of @string, or -1 if @string is nul-terminated
- * @start_position: starting index of the string to match
- * @match_options: match options
- * @match_info: pointer to location where to store the #GMatchInfo,
- * or %NULL if you do not need it
- * @error: location to store the error occuring, or %NULL to ignore errors
- *
- * Scans for a match in string for the pattern in @regex.
- * The @match_options are combined with the match options specified
- * when the @regex structure was created, letting you have more
- * flexibility in reusing #GRegex structures.
- *
- * Setting @start_position differs from just passing over a shortened
- * string and setting #G_REGEX_MATCH_NOTBOL in the case of a pattern
- * that begins with any kind of lookbehind assertion, such as "\b".
- *
- * A #GMatchInfo structure, used to get information on the match, is
- * stored in @match_info if not %NULL. Note that if @match_info is
- * not %NULL then it is created even if the function returns %FALSE,
- * i.e. you must free it regardless if regular expression actually
- * matched.
- *
- * @string is not copied and is used in #GMatchInfo internally. If
- * you use any #GMatchInfo method (except g_match_info_free()) after
- * freeing or modifying @string then the behaviour is undefined.
- *
- * To retrieve all the non-overlapping matches of the pattern in
- * string you can use g_match_info_next().
- *
- * |[
- * static void
- * print_uppercase_words (const gchar *string)
- * {
- * /&ast; Print all uppercase-only words. &ast;/
- * GRegex *regex;
- * GMatchInfo *match_info;
- * GError *error = NULL;
- * &nbsp;
- * regex = g_regex_new ("[A-Z]+", 0, 0, NULL);
- * g_regex_match_full (regex, string, -1, 0, 0, &amp;match_info, &amp;error);
- * while (g_match_info_matches (match_info))
- * {
- * gchar *word = g_match_info_fetch (match_info, 0);
- * g_print ("Found: %s\n", word);
- * g_free (word);
- * g_match_info_next (match_info, &amp;error);
- * }
- * g_match_info_free (match_info);
- * g_regex_unref (regex);
- * if (error != NULL)
- * {
- * g_printerr ("Error while matching: %s\n", error->message);
- * g_error_free (error);
- * }
- * }
- * ]|
- *
- * Returns: %TRUE is the string matched, %FALSE otherwise
- *
- * Since: 2.14
- */
-gboolean
-g_regex_match_full (const GRegex *regex,
- const gchar *string,
- gssize string_len,
- gint start_position,
- GRegexMatchFlags match_options,
- GMatchInfo **match_info,
- GError **error)
-{
- GMatchInfo *info;
- gboolean match_ok;
-
- g_return_val_if_fail (regex != NULL, FALSE);
- g_return_val_if_fail (string != NULL, FALSE);
- g_return_val_if_fail (start_position >= 0, FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, FALSE);
-
- info = match_info_new (regex, string, string_len, start_position,
- match_options, FALSE);
- match_ok = g_match_info_next (info, error);
- if (match_info != NULL)
- *match_info = info;
- else
- g_match_info_free (info);
-
- return match_ok;
-}
-
-/**
- * g_regex_match_all:
- * @regex: a #GRegex structure from g_regex_new()
- * @string: the string to scan for matches
- * @match_options: match options
- * @match_info: pointer to location where to store the #GMatchInfo,
- * or %NULL if you do not need it
- *
- * Using the standard algorithm for regular expression matching only
- * the longest match in the string is retrieved. This function uses
- * a different algorithm so it can retrieve all the possible matches.
- * For more documentation see g_regex_match_all_full().
- *
- * A #GMatchInfo structure, used to get information on the match, is
- * stored in @match_info if not %NULL. Note that if @match_info is
- * not %NULL then it is created even if the function returns %FALSE,
- * i.e. you must free it regardless if regular expression actually
- * matched.
- *
- * @string is not copied and is used in #GMatchInfo internally. If
- * you use any #GMatchInfo method (except g_match_info_free()) after
- * freeing or modifying @string then the behaviour is undefined.
- *
- * Returns: %TRUE is the string matched, %FALSE otherwise
- *
- * Since: 2.14
- */
-gboolean
-g_regex_match_all (const GRegex *regex,
- const gchar *string,
- GRegexMatchFlags match_options,
- GMatchInfo **match_info)
-{
- return g_regex_match_all_full (regex, string, -1, 0, match_options,
- match_info, NULL);
-}
-
-/**
- * g_regex_match_all_full:
- * @regex: a #GRegex structure from g_regex_new()
- * @string: the string to scan for matches
- * @string_len: the length of @string, or -1 if @string is nul-terminated
- * @start_position: starting index of the string to match
- * @match_options: match options
- * @match_info: pointer to location where to store the #GMatchInfo,
- * or %NULL if you do not need it
- * @error: location to store the error occuring, or %NULL to ignore errors
- *
- * Using the standard algorithm for regular expression matching only
- * the longest match in the string is retrieved, it is not possibile
- * to obtain all the available matches. For instance matching
- * "&lt;a&gt; &lt;b&gt; &lt;c&gt;" against the pattern "&lt;.*&gt;"
- * you get "&lt;a&gt; &lt;b&gt; &lt;c&gt;".
- *
- * This function uses a different algorithm (called DFA, i.e. deterministic
- * finite automaton), so it can retrieve all the possible matches, all
- * starting at the same point in the string. For instance matching
- * "&lt;a&gt; &lt;b&gt; &lt;c&gt;" against the pattern "&lt;.*&gt;"
- * you would obtain three matches: "&lt;a&gt; &lt;b&gt; &lt;c&gt;",
- * "&lt;a&gt; &lt;b&gt;" and "&lt;a&gt;".
- *
- * The number of matched strings is retrieved using
- * g_match_info_get_match_count(). To obtain the matched strings and
- * their position you can use, respectively, g_match_info_fetch() and
- * g_match_info_fetch_pos(). Note that the strings are returned in
- * reverse order of length; that is, the longest matching string is
- * given first.
- *
- * Note that the DFA algorithm is slower than the standard one and it
- * is not able to capture substrings, so backreferences do not work.
- *
- * Setting @start_position differs from just passing over a shortened
- * string and setting #G_REGEX_MATCH_NOTBOL in the case of a pattern
- * that begins with any kind of lookbehind assertion, such as "\b".
- *
- * A #GMatchInfo structure, used to get information on the match, is
- * stored in @match_info if not %NULL. Note that if @match_info is
- * not %NULL then it is created even if the function returns %FALSE,
- * i.e. you must free it regardless if regular expression actually
- * matched.
- *
- * @string is not copied and is used in #GMatchInfo internally. If
- * you use any #GMatchInfo method (except g_match_info_free()) after
- * freeing or modifying @string then the behaviour is undefined.
- *
- * Returns: %TRUE is the string matched, %FALSE otherwise
- *
- * Since: 2.14
- */
-gboolean
-g_regex_match_all_full (const GRegex *regex,
- const gchar *string,
- gssize string_len,
- gint start_position,
- GRegexMatchFlags match_options,
- GMatchInfo **match_info,
- GError **error)
-{
- GMatchInfo *info;
- gboolean done;
-
- g_return_val_if_fail (regex != NULL, FALSE);
- g_return_val_if_fail (string != NULL, FALSE);
- g_return_val_if_fail (start_position >= 0, FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, FALSE);
-
- info = match_info_new (regex, string, string_len, start_position,
- match_options, TRUE);
-
- done = FALSE;
- while (!done)
- {
- done = TRUE;
- info->matches = pcre_dfa_exec (regex->pcre_re, regex->extra,
- info->string, info->string_len,
- info->pos,
- regex->match_opts | match_options,
- info->offsets, info->n_offsets,
- info->workspace, info->n_workspace);
- if (info->matches == PCRE_ERROR_DFA_WSSIZE)
- {
- /* info->workspace is too small. */
- info->n_workspace *= 2;
- info->workspace = g_realloc (info->workspace,
- info->n_workspace * sizeof (gint));
- done = FALSE;
- }
- else if (info->matches == 0)
- {
- /* info->offsets is too small. */
- info->n_offsets *= 2;
- info->offsets = g_realloc (info->offsets,
- info->n_offsets * sizeof (gint));
- done = FALSE;
- }
- else if (IS_PCRE_ERROR (info->matches))
- {
- g_set_error (error, G_REGEX_ERROR, G_REGEX_ERROR_MATCH,
- _("Error while matching regular expression %s: %s"),
- regex->pattern, match_error (info->matches));
- }
- }
-
- /* set info->pos to -1 so that a call to g_match_info_next() fails. */
- info->pos = -1;
-
- if (match_info != NULL)
- *match_info = info;
- else
- g_match_info_free (info);
-
- return info->matches >= 0;
-}
-
-/**
- * g_regex_get_string_number:
- * @regex: #GRegex structure
- * @name: name of the subexpression
- *
- * Retrieves the number of the subexpression named @name.
- *
- * Returns: The number of the subexpression or -1 if @name
- * does not exists
- *
- * Since: 2.14
- */
-gint
-g_regex_get_string_number (const GRegex *regex,
- const gchar *name)
-{
- gint num;
-
- g_return_val_if_fail (regex != NULL, -1);
- g_return_val_if_fail (name != NULL, -1);
-
- num = pcre_get_stringnumber (regex->pcre_re, name);
- if (num == PCRE_ERROR_NOSUBSTRING)
- num = -1;
-
- return num;
-}
-
-/**
- * g_regex_split_simple:
- * @pattern: the regular expression
- * @string: the string to scan for matches
- * @compile_options: compile options for the regular expression, or 0
- * @match_options: match options, or 0
- *
- * Breaks the string on the pattern, and returns an array of
- * the tokens. If the pattern contains capturing parentheses,
- * then the text for each of the substrings will also be returned.
- * If the pattern does not match anywhere in the string, then the
- * whole string is returned as the first token.
- *
- * This function is equivalent to g_regex_split() but it does
- * not require to compile the pattern with g_regex_new(), avoiding
- * some lines of code when you need just to do a split without
- * extracting substrings, capture counts, and so on.
- *
- * If this function is to be called on the same @pattern more than
- * once, it's more efficient to compile the pattern once with
- * g_regex_new() and then use g_regex_split().
- *
- * As a special case, the result of splitting the empty string ""
- * is an empty vector, not a vector containing a single string.
- * The reason for this special case is that being able to represent
- * a empty vector is typically more useful than consistent handling
- * of empty elements. If you do need to represent empty elements,
- * you'll need to check for the empty string before calling this
- * function.
- *
- * A pattern that can match empty strings splits @string into
- * separate characters wherever it matches the empty string between
- * characters. For example splitting "ab c" using as a separator
- * "\s*", you will get "a", "b" and "c".
- *
- * Returns: a %NULL-terminated array of strings. Free it using g_strfreev()
- *
- * Since: 2.14
- **/
-gchar **
-g_regex_split_simple (const gchar *pattern,
- const gchar *string,
- GRegexCompileFlags compile_options,
- GRegexMatchFlags match_options)
-{
- GRegex *regex;
- gchar **result;
-
- regex = g_regex_new (pattern, compile_options, 0, NULL);
- if (!regex)
- return NULL;
- result = g_regex_split_full (regex, string, -1, 0, match_options, 0, NULL);
- g_regex_unref (regex);
- return result;
-}
-
-/**
- * g_regex_split:
- * @regex: a #GRegex structure
- * @string: the string to split with the pattern
- * @match_options: match time option flags
- *
- * Breaks the string on the pattern, and returns an array of the tokens.
- * If the pattern contains capturing parentheses, then the text for each
- * of the substrings will also be returned. If the pattern does not match
- * anywhere in the string, then the whole string is returned as the first
- * token.
- *
- * As a special case, the result of splitting the empty string "" is an
- * empty vector, not a vector containing a single string. The reason for
- * this special case is that being able to represent a empty vector is
- * typically more useful than consistent handling of empty elements. If
- * you do need to represent empty elements, you'll need to check for the
- * empty string before calling this function.
- *
- * A pattern that can match empty strings splits @string into separate
- * characters wherever it matches the empty string between characters.
- * For example splitting "ab c" using as a separator "\s*", you will get
- * "a", "b" and "c".
- *
- * Returns: a %NULL-terminated gchar ** array. Free it using g_strfreev()
- *
- * Since: 2.14
- **/
-gchar **
-g_regex_split (const GRegex *regex,
- const gchar *string,
- GRegexMatchFlags match_options)
-{
- return g_regex_split_full (regex, string, -1, 0,
- match_options, 0, NULL);
-}
-
-/**
- * g_regex_split_full:
- * @regex: a #GRegex structure
- * @string: the string to split with the pattern
- * @string_len: the length of @string, or -1 if @string is nul-terminated
- * @start_position: starting index of the string to match
- * @match_options: match time option flags
- * @max_tokens: the maximum number of tokens to split @string into.
- * If this is less than 1, the string is split completely
- * @error: return location for a #GError
- *
- * Breaks the string on the pattern, and returns an array of the tokens.
- * If the pattern contains capturing parentheses, then the text for each
- * of the substrings will also be returned. If the pattern does not match
- * anywhere in the string, then the whole string is returned as the first
- * token.
- *
- * As a special case, the result of splitting the empty string "" is an
- * empty vector, not a vector containing a single string. The reason for
- * this special case is that being able to represent a empty vector is
- * typically more useful than consistent handling of empty elements. If
- * you do need to represent empty elements, you'll need to check for the
- * empty string before calling this function.
- *
- * A pattern that can match empty strings splits @string into separate
- * characters wherever it matches the empty string between characters.
- * For example splitting "ab c" using as a separator "\s*", you will get
- * "a", "b" and "c".
- *
- * Setting @start_position differs from just passing over a shortened
- * string and setting #G_REGEX_MATCH_NOTBOL in the case of a pattern
- * that begins with any kind of lookbehind assertion, such as "\b".
- *
- * Returns: a %NULL-terminated gchar ** array. Free it using g_strfreev()
- *
- * Since: 2.14
- **/
-gchar **
-g_regex_split_full (const GRegex *regex,
- const gchar *string,
- gssize string_len,
- gint start_position,
- GRegexMatchFlags match_options,
- gint max_tokens,
- GError **error)
-{
- GError *tmp_error = NULL;
- GMatchInfo *match_info;
- GList *list, *last;
- gint i;
- gint token_count;
- gboolean match_ok;
- /* position of the last separator. */
- gint last_separator_end;
- /* was the last match 0 bytes long? */
- gboolean last_match_is_empty;
- /* the returned array of char **s */
- gchar **string_list;
-
- g_return_val_if_fail (regex != NULL, NULL);
- g_return_val_if_fail (string != NULL, NULL);
- g_return_val_if_fail (start_position >= 0, NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, NULL);
-
- if (max_tokens <= 0)
- max_tokens = G_MAXINT;
-
- if (string_len < 0)
- string_len = strlen (string);
-
- /* zero-length string */
- if (string_len - start_position == 0)
- return g_new0 (gchar *, 1);
-
- if (max_tokens == 1)
- {
- string_list = g_new0 (gchar *, 2);
- string_list[0] = g_strndup (&string[start_position],
- string_len - start_position);
- return string_list;
- }
-
- list = NULL;
- token_count = 0;
- last_separator_end = start_position;
- last_match_is_empty = FALSE;
-
- match_ok = g_regex_match_full (regex, string, string_len, start_position,
- match_options, &match_info, &tmp_error);
- while (tmp_error == NULL)
- {
- if (match_ok)
- {
- last_match_is_empty =
- (match_info->offsets[0] == match_info->offsets[1]);
-
- /* we need to skip empty separators at the same position of the end
- * of another separator. e.g. the string is "a b" and the separator
- * is " *", so from 1 to 2 we have a match and at position 2 we have
- * an empty match. */
- if (last_separator_end != match_info->offsets[1])
- {
- gchar *token;
- gint match_count;
-
- token = g_strndup (string + last_separator_end,
- match_info->offsets[0] - last_separator_end);
- list = g_list_prepend (list, token);
- token_count++;
-
- /* if there were substrings, these need to be added to
- * the list. */
- match_count = g_match_info_get_match_count (match_info);
- if (match_count > 1)
- {
- for (i = 1; i < match_count; i++)
- list = g_list_prepend (list, g_match_info_fetch (match_info, i));
- }
- }
- }
- else
- {
- /* if there was no match, copy to end of string. */
- if (!last_match_is_empty)
- {
- gchar *token = g_strndup (string + last_separator_end,
- match_info->string_len - last_separator_end);
- list = g_list_prepend (list, token);
- }
- /* no more tokens, end the loop. */
- break;
- }
-
- /* -1 to leave room for the last part. */
- if (token_count >= max_tokens - 1)
- {
- /* we have reached the maximum number of tokens, so we copy
- * the remaining part of the string. */
- if (last_match_is_empty)
- {
- /* the last match was empty, so we have moved one char
- * after the real position to avoid empty matches at the
- * same position. */
- match_info->pos = PREV_CHAR (regex, &string[match_info->pos]) - string;
- }
- /* the if is needed in the case we have terminated the available
- * tokens, but we are at the end of the string, so there are no
- * characters left to copy. */
- if (string_len > match_info->pos)
- {
- gchar *token = g_strndup (string + match_info->pos,
- string_len - match_info->pos);
- list = g_list_prepend (list, token);
- }
- /* end the loop. */
- break;
- }
-
- last_separator_end = match_info->pos;
- if (last_match_is_empty)
- /* if the last match was empty, g_match_info_next() has moved
- * forward to avoid infinite loops, but we still need to copy that
- * character. */
- last_separator_end = PREV_CHAR (regex, &string[last_separator_end]) - string;
-
- match_ok = g_match_info_next (match_info, &tmp_error);
- }
- g_match_info_free (match_info);
- if (tmp_error != NULL)
- {
- g_propagate_error (error, tmp_error);
- g_list_foreach (list, (GFunc)g_free, NULL);
- g_list_free (list);
- match_info->pos = -1;
- return NULL;
- }
-
- string_list = g_new (gchar *, g_list_length (list) + 1);
- i = 0;
- for (last = g_list_last (list); last; last = g_list_previous (last))
- string_list[i++] = last->data;
- string_list[i] = NULL;
- g_list_free (list);
-
- return string_list;
-}
-
-enum
-{
- REPL_TYPE_STRING,
- REPL_TYPE_CHARACTER,
- REPL_TYPE_SYMBOLIC_REFERENCE,
- REPL_TYPE_NUMERIC_REFERENCE,
- REPL_TYPE_CHANGE_CASE
-};
-
-typedef enum
-{
- CHANGE_CASE_NONE = 1 << 0,
- CHANGE_CASE_UPPER = 1 << 1,
- CHANGE_CASE_LOWER = 1 << 2,
- CHANGE_CASE_UPPER_SINGLE = 1 << 3,
- CHANGE_CASE_LOWER_SINGLE = 1 << 4,
- CHANGE_CASE_SINGLE_MASK = CHANGE_CASE_UPPER_SINGLE | CHANGE_CASE_LOWER_SINGLE,
- CHANGE_CASE_LOWER_MASK = CHANGE_CASE_LOWER | CHANGE_CASE_LOWER_SINGLE,
- CHANGE_CASE_UPPER_MASK = CHANGE_CASE_UPPER | CHANGE_CASE_UPPER_SINGLE
-} ChangeCase;
-
-struct _InterpolationData
-{
- gchar *text;
- gint type;
- gint num;
- gchar c;
- ChangeCase change_case;
-};
-
-static void
-free_interpolation_data (InterpolationData *data)
-{
- g_free (data->text);
- g_free (data);
-}
-
-static const gchar *
-expand_escape (const gchar *replacement,
- const gchar *p,
- InterpolationData *data,
- GError **error)
-{
- const gchar *q, *r;
- gint x, d, h, i;
- const gchar *error_detail;
- gint base = 0;
- GError *tmp_error = NULL;
-
- p++;
- switch (*p)
- {
- case 't':
- p++;
- data->c = '\t';
- data->type = REPL_TYPE_CHARACTER;
- break;
- case 'n':
- p++;
- data->c = '\n';
- data->type = REPL_TYPE_CHARACTER;
- break;
- case 'v':
- p++;
- data->c = '\v';
- data->type = REPL_TYPE_CHARACTER;
- break;
- case 'r':
- p++;
- data->c = '\r';
- data->type = REPL_TYPE_CHARACTER;
- break;
- case 'f':
- p++;
- data->c = '\f';
- data->type = REPL_TYPE_CHARACTER;
- break;
- case 'a':
- p++;
- data->c = '\a';
- data->type = REPL_TYPE_CHARACTER;
- break;
- case 'b':
- p++;
- data->c = '\b';
- data->type = REPL_TYPE_CHARACTER;
- break;
- case '\\':
- p++;
- data->c = '\\';
- data->type = REPL_TYPE_CHARACTER;
- break;
- case 'x':
- p++;
- x = 0;
- if (*p == '{')
- {
- p++;
- do
- {
- h = g_ascii_xdigit_value (*p);
- if (h < 0)
- {
- error_detail = _("hexadecimal digit or '}' expected");
- goto error;
- }
- x = x * 16 + h;
- p++;
- }
- while (*p != '}');
- p++;
- }
- else
- {
- for (i = 0; i < 2; i++)
- {
- h = g_ascii_xdigit_value (*p);
- if (h < 0)
- {
- error_detail = _("hexadecimal digit expected");
- goto error;
- }
- x = x * 16 + h;
- p++;
- }
- }
- data->type = REPL_TYPE_STRING;
- data->text = g_new0 (gchar, 8);
- g_unichar_to_utf8 (x, data->text);
- break;
- case 'l':
- p++;
- data->type = REPL_TYPE_CHANGE_CASE;
- data->change_case = CHANGE_CASE_LOWER_SINGLE;
- break;
- case 'u':
- p++;
- data->type = REPL_TYPE_CHANGE_CASE;
- data->change_case = CHANGE_CASE_UPPER_SINGLE;
- break;
- case 'L':
- p++;
- data->type = REPL_TYPE_CHANGE_CASE;
- data->change_case = CHANGE_CASE_LOWER;
- break;
- case 'U':
- p++;
- data->type = REPL_TYPE_CHANGE_CASE;
- data->change_case = CHANGE_CASE_UPPER;
- break;
- case 'E':
- p++;
- data->type = REPL_TYPE_CHANGE_CASE;
- data->change_case = CHANGE_CASE_NONE;
- break;
- case 'g':
- p++;
- if (*p != '<')
- {
- error_detail = _("missing '<' in symbolic reference");
- goto error;
- }
- q = p + 1;
- do
- {
- p++;
- if (!*p)
- {
- error_detail = _("unfinished symbolic reference");
- goto error;
- }
- }
- while (*p != '>');
- if (p - q == 0)
- {
- error_detail = _("zero-length symbolic reference");
- goto error;
- }
- if (g_ascii_isdigit (*q))
- {
- x = 0;
- do
- {
- h = g_ascii_digit_value (*q);
- if (h < 0)
- {
- error_detail = _("digit expected");
- p = q;
- goto error;
- }
- x = x * 10 + h;
- q++;
- }
- while (q != p);
- data->num = x;
- data->type = REPL_TYPE_NUMERIC_REFERENCE;
- }
- else
- {
- r = q;
- do
- {
- if (!g_ascii_isalnum (*r))
- {
- error_detail = _("illegal symbolic reference");
- p = r;
- goto error;
- }
- r++;
- }
- while (r != p);
- data->text = g_strndup (q, p - q);
- data->type = REPL_TYPE_SYMBOLIC_REFERENCE;
- }
- p++;
- break;
- case '0':
- /* if \0 is followed by a number is an octal number representing a
- * character, else it is a numeric reference. */
- if (g_ascii_digit_value (*g_utf8_next_char (p)) >= 0)
- {
- base = 8;
- p = g_utf8_next_char (p);
- }
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- x = 0;
- d = 0;
- for (i = 0; i < 3; i++)
- {
- h = g_ascii_digit_value (*p);
- if (h < 0)
- break;
- if (h > 7)
- {
- if (base == 8)
- break;
- else
- base = 10;
- }
- if (i == 2 && base == 10)
- break;
- x = x * 8 + h;
- d = d * 10 + h;
- p++;
- }
- if (base == 8 || i == 3)
- {
- data->type = REPL_TYPE_STRING;
- data->text = g_new0 (gchar, 8);
- g_unichar_to_utf8 (x, data->text);
- }
- else
- {
- data->type = REPL_TYPE_NUMERIC_REFERENCE;
- data->num = d;
- }
- break;
- case 0:
- error_detail = _("stray final '\\'");
- goto error;
- break;
- default:
- error_detail = _("unknown escape sequence");
- goto error;
- }
-
- return p;
-
- error:
- /* G_GSSIZE_FORMAT doesn't work with gettext, so we use %lu */
- tmp_error = g_error_new (G_REGEX_ERROR,
- G_REGEX_ERROR_REPLACE,
- _("Error while parsing replacement "
- "text \"%s\" at char %lu: %s"),
- replacement,
- (gulong)(p - replacement),
- error_detail);
- g_propagate_error (error, tmp_error);
-
- return NULL;
-}
-
-static GList *
-split_replacement (const gchar *replacement,
- GError **error)
-{
- GList *list = NULL;
- InterpolationData *data;
- const gchar *p, *start;
-
- start = p = replacement;
- while (*p)
- {
- if (*p == '\\')
- {
- data = g_new0 (InterpolationData, 1);
- start = p = expand_escape (replacement, p, data, error);
- if (p == NULL)
- {
- g_list_foreach (list, (GFunc)free_interpolation_data, NULL);
- g_list_free (list);
- free_interpolation_data (data);
-
- return NULL;
- }
- list = g_list_prepend (list, data);
- }
- else
- {
- p++;
- if (*p == '\\' || *p == '\0')
- {
- if (p - start > 0)
- {
- data = g_new0 (InterpolationData, 1);
- data->text = g_strndup (start, p - start);
- data->type = REPL_TYPE_STRING;
- list = g_list_prepend (list, data);
- }
- }
- }
- }
-
- return g_list_reverse (list);
-}
-
-/* Change the case of c based on change_case. */
-#define CHANGE_CASE(c, change_case) \
- (((change_case) & CHANGE_CASE_LOWER_MASK) ? \
- g_unichar_tolower (c) : \
- g_unichar_toupper (c))
-
-static void
-string_append (GString *string,
- const gchar *text,
- ChangeCase *change_case)
-{
- gunichar c;
-
- if (text[0] == '\0')
- return;
-
- if (*change_case == CHANGE_CASE_NONE)
- {
- g_string_append (string, text);
- }
- else if (*change_case & CHANGE_CASE_SINGLE_MASK)
- {
- c = g_utf8_get_char (text);
- g_string_append_unichar (string, CHANGE_CASE (c, *change_case));
- g_string_append (string, g_utf8_next_char (text));
- *change_case = CHANGE_CASE_NONE;
- }
- else
- {
- while (*text != '\0')
- {
- c = g_utf8_get_char (text);
- g_string_append_unichar (string, CHANGE_CASE (c, *change_case));
- text = g_utf8_next_char (text);
- }
- }
-}
-
-static gboolean
-interpolate_replacement (const GMatchInfo *match_info,
- GString *result,
- gpointer data)
-{
- GList *list;
- InterpolationData *idata;
- gchar *match;
- ChangeCase change_case = CHANGE_CASE_NONE;
-
- for (list = data; list; list = list->next)
- {
- idata = list->data;
- switch (idata->type)
- {
- case REPL_TYPE_STRING:
- string_append (result, idata->text, &change_case);
- break;
- case REPL_TYPE_CHARACTER:
- g_string_append_c (result, CHANGE_CASE (idata->c, change_case));
- if (change_case & CHANGE_CASE_SINGLE_MASK)
- change_case = CHANGE_CASE_NONE;
- break;
- case REPL_TYPE_NUMERIC_REFERENCE:
- match = g_match_info_fetch (match_info, idata->num);
- if (match)
- {
- string_append (result, match, &change_case);
- g_free (match);
- }
- break;
- case REPL_TYPE_SYMBOLIC_REFERENCE:
- match = g_match_info_fetch_named (match_info, idata->text);
- if (match)
- {
- string_append (result, match, &change_case);
- g_free (match);
- }
- break;
- case REPL_TYPE_CHANGE_CASE:
- change_case = idata->change_case;
- break;
- }
- }
-
- return FALSE;
-}
-
-/* whether actual match_info is needed for replacement, i.e.
- * whether there are references
- */
-static gboolean
-interpolation_list_needs_match (GList *list)
-{
- while (list != NULL)
- {
- InterpolationData *data = list->data;
-
- if (data->type == REPL_TYPE_SYMBOLIC_REFERENCE ||
- data->type == REPL_TYPE_NUMERIC_REFERENCE)
- {
- return TRUE;
- }
-
- list = list->next;
- }
-
- return FALSE;
-}
-
-/**
- * g_regex_replace:
- * @regex: a #GRegex structure
- * @string: the string to perform matches against
- * @string_len: the length of @string, or -1 if @string is nul-terminated
- * @start_position: starting index of the string to match
- * @replacement: text to replace each match with
- * @match_options: options for the match
- * @error: location to store the error occuring, or %NULL to ignore errors
- *
- * Replaces all occurrences of the pattern in @regex with the
- * replacement text. Backreferences of the form '\number' or
- * '\g&lt;number&gt;' in the replacement text are interpolated by the
- * number-th captured subexpression of the match, '\g&lt;name&gt;' refers
- * to the captured subexpression with the given name. '\0' refers to the
- * complete match, but '\0' followed by a number is the octal representation
- * of a character. To include a literal '\' in the replacement, write '\\'.
- * There are also escapes that changes the case of the following text:
- *
- * <variablelist>
- * <varlistentry><term>\l</term>
- * <listitem>
- * <para>Convert to lower case the next character</para>
- * </listitem>
- * </varlistentry>
- * <varlistentry><term>\u</term>
- * <listitem>
- * <para>Convert to upper case the next character</para>
- * </listitem>
- * </varlistentry>
- * <varlistentry><term>\L</term>
- * <listitem>
- * <para>Convert to lower case till \E</para>
- * </listitem>
- * </varlistentry>
- * <varlistentry><term>\U</term>
- * <listitem>
- * <para>Convert to upper case till \E</para>
- * </listitem>
- * </varlistentry>
- * <varlistentry><term>\E</term>
- * <listitem>
- * <para>End case modification</para>
- * </listitem>
- * </varlistentry>
- * </variablelist>
- *
- * If you do not need to use backreferences use g_regex_replace_literal().
- *
- * The @replacement string must be UTF-8 encoded even if #G_REGEX_RAW was
- * passed to g_regex_new(). If you want to use not UTF-8 encoded stings
- * you can use g_regex_replace_literal().
- *
- * Setting @start_position differs from just passing over a shortened
- * string and setting #G_REGEX_MATCH_NOTBOL in the case of a pattern that
- * begins with any kind of lookbehind assertion, such as "\b".
- *
- * Returns: a newly allocated string containing the replacements
- *
- * Since: 2.14
- */
-gchar *
-g_regex_replace (const GRegex *regex,
- const gchar *string,
- gssize string_len,
- gint start_position,
- const gchar *replacement,
- GRegexMatchFlags match_options,
- GError **error)
-{
- gchar *result;
- GList *list;
- GError *tmp_error = NULL;
-
- g_return_val_if_fail (regex != NULL, NULL);
- g_return_val_if_fail (string != NULL, NULL);
- g_return_val_if_fail (start_position >= 0, NULL);
- g_return_val_if_fail (replacement != NULL, NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, NULL);
-
- list = split_replacement (replacement, &tmp_error);
- if (tmp_error != NULL)
- {
- g_propagate_error (error, tmp_error);
- return NULL;
- }
-
- result = g_regex_replace_eval (regex,
- string, string_len, start_position,
- match_options,
- interpolate_replacement,
- (gpointer)list,
- &tmp_error);
- if (tmp_error != NULL)
- g_propagate_error (error, tmp_error);
-
- g_list_foreach (list, (GFunc)free_interpolation_data, NULL);
- g_list_free (list);
-
- return result;
-}
-
-static gboolean
-literal_replacement (const GMatchInfo *match_info,
- GString *result,
- gpointer data)
-{
- g_string_append (result, data);
- return FALSE;
-}
-
-/**
- * g_regex_replace_literal:
- * @regex: a #GRegex structure
- * @string: the string to perform matches against
- * @string_len: the length of @string, or -1 if @string is nul-terminated
- * @start_position: starting index of the string to match
- * @replacement: text to replace each match with
- * @match_options: options for the match
- * @error: location to store the error occuring, or %NULL to ignore errors
- *
- * Replaces all occurrences of the pattern in @regex with the
- * replacement text. @replacement is replaced literally, to
- * include backreferences use g_regex_replace().
- *
- * Setting @start_position differs from just passing over a
- * shortened string and setting #G_REGEX_MATCH_NOTBOL in the
- * case of a pattern that begins with any kind of lookbehind
- * assertion, such as "\b".
- *
- * Returns: a newly allocated string containing the replacements
- *
- * Since: 2.14
- */
-gchar *
-g_regex_replace_literal (const GRegex *regex,
- const gchar *string,
- gssize string_len,
- gint start_position,
- const gchar *replacement,
- GRegexMatchFlags match_options,
- GError **error)
-{
- g_return_val_if_fail (replacement != NULL, NULL);
- g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, NULL);
-
- return g_regex_replace_eval (regex,
- string, string_len, start_position,
- match_options,
- literal_replacement,
- (gpointer)replacement,
- error);
-}
-
-/**
- * g_regex_replace_eval:
- * @regex: a #GRegex structure from g_regex_new()
- * @string: string to perform matches against
- * @string_len: the length of @string, or -1 if @string is nul-terminated
- * @start_position: starting index of the string to match
- * @match_options: options for the match
- * @eval: a function to call for each match
- * @user_data: user data to pass to the function
- * @error: location to store the error occuring, or %NULL to ignore errors
- *
- * Replaces occurrences of the pattern in regex with the output of
- * @eval for that occurrence.
- *
- * Setting @start_position differs from just passing over a shortened
- * string and setting #G_REGEX_MATCH_NOTBOL in the case of a pattern
- * that begins with any kind of lookbehind assertion, such as "\b".
- *
- * The following example uses g_regex_replace_eval() to replace multiple
- * strings at once:
- * |[
- * static gboolean
- * eval_cb (const GMatchInfo *info,
- * GString *res,
- * gpointer data)
- * {
- * gchar *match;
- * gchar *r;
- *
- * match = g_match_info_fetch (info, 0);
- * r = g_hash_table_lookup ((GHashTable *)data, match);
- * g_string_append (res, r);
- * g_free (match);
- *
- * return FALSE;
- * }
- *
- * /&ast; ... &ast;/
- *
- * GRegex *reg;
- * GHashTable *h;
- * gchar *res;
- *
- * h = g_hash_table_new (g_str_hash, g_str_equal);
- *
- * g_hash_table_insert (h, "1", "ONE");
- * g_hash_table_insert (h, "2", "TWO");
- * g_hash_table_insert (h, "3", "THREE");
- * g_hash_table_insert (h, "4", "FOUR");
- *
- * reg = g_regex_new ("1|2|3|4", 0, 0, NULL);
- * res = g_regex_replace_eval (reg, text, -1, 0, 0, eval_cb, h, NULL);
- * g_hash_table_destroy (h);
- *
- * /&ast; ... &ast;/
- * ]|
- *
- * Returns: a newly allocated string containing the replacements
- *
- * Since: 2.14
- */
-gchar *
-g_regex_replace_eval (const GRegex *regex,
- const gchar *string,
- gssize string_len,
- gint start_position,
- GRegexMatchFlags match_options,
- GRegexEvalCallback eval,
- gpointer user_data,
- GError **error)
-{
- GMatchInfo *match_info;
- GString *result;
- gint str_pos = 0;
- gboolean done = FALSE;
- GError *tmp_error = NULL;
-
- g_return_val_if_fail (regex != NULL, NULL);
- g_return_val_if_fail (string != NULL, NULL);
- g_return_val_if_fail (start_position >= 0, NULL);
- g_return_val_if_fail (eval != NULL, NULL);
- g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, NULL);
-
- if (string_len < 0)
- string_len = strlen (string);
-
- result = g_string_sized_new (string_len);
-
- /* run down the string making matches. */
- g_regex_match_full (regex, string, string_len, start_position,
- match_options, &match_info, &tmp_error);
- while (!done && g_match_info_matches (match_info))
- {
- g_string_append_len (result,
- string + str_pos,
- match_info->offsets[0] - str_pos);
- done = (*eval) (match_info, result, user_data);
- str_pos = match_info->offsets[1];
- g_match_info_next (match_info, &tmp_error);
- }
- g_match_info_free (match_info);
- if (tmp_error != NULL)
- {
- g_propagate_error (error, tmp_error);
- g_string_free (result, TRUE);
- return NULL;
- }
-
- g_string_append_len (result, string + str_pos, string_len - str_pos);
- return g_string_free (result, FALSE);
-}
-
-/**
- * g_regex_check_replacement:
- * @replacement: the replacement string
- * @has_references: location to store information about
- * references in @replacement or %NULL
- * @error: location to store error
- *
- * Checks whether @replacement is a valid replacement string
- * (see g_regex_replace()), i.e. that all escape sequences in
- * it are valid.
- *
- * If @has_references is not %NULL then @replacement is checked
- * for pattern references. For instance, replacement text 'foo\n'
- * does not contain references and may be evaluated without information
- * about actual match, but '\0\1' (whole match followed by first
- * subpattern) requires valid #GMatchInfo object.
- *
- * Returns: whether @replacement is a valid replacement string
- *
- * Since: 2.14
- */
-gboolean
-g_regex_check_replacement (const gchar *replacement,
- gboolean *has_references,
- GError **error)
-{
- GList *list;
- GError *tmp = NULL;
-
- list = split_replacement (replacement, &tmp);
-
- if (tmp)
- {
- g_propagate_error (error, tmp);
- return FALSE;
- }
-
- if (has_references)
- *has_references = interpolation_list_needs_match (list);
-
- g_list_foreach (list, (GFunc) free_interpolation_data, NULL);
- g_list_free (list);
-
- return TRUE;
-}
-
-/**
- * g_regex_escape_string:
- * @string: the string to escape
- * @length: the length of @string, or -1 if @string is nul-terminated
- *
- * Escapes the special characters used for regular expressions
- * in @string, for instance "a.b*c" becomes "a\.b\*c". This
- * function is useful to dynamically generate regular expressions.
- *
- * @string can contain nul characters that are replaced with "\0",
- * in this case remember to specify the correct length of @string
- * in @length.
- *
- * Returns: a newly-allocated escaped string
- *
- * Since: 2.14
- */
-gchar *
-g_regex_escape_string (const gchar *string,
- gint length)
-{
- GString *escaped;
- const char *p, *piece_start, *end;
-
- g_return_val_if_fail (string != NULL, NULL);
-
- if (length < 0)
- length = strlen (string);
-
- end = string + length;
- p = piece_start = string;
- escaped = g_string_sized_new (length + 1);
-
- while (p < end)
- {
- switch (*p)
- {
- case '\0':
- case '\\':
- case '|':
- case '(':
- case ')':
- case '[':
- case ']':
- case '{':
- case '}':
- case '^':
- case '$':
- case '*':
- case '+':
- case '?':
- case '.':
- if (p != piece_start)
- /* copy the previous piece. */
- g_string_append_len (escaped, piece_start, p - piece_start);
- g_string_append_c (escaped, '\\');
- if (*p == '\0')
- g_string_append_c (escaped, '0');
- else
- g_string_append_c (escaped, *p);
- piece_start = ++p;
- break;
- default:
- p = g_utf8_next_char (p);
- break;
- }
- }
-
- if (piece_start < end)
- g_string_append_len (escaped, piece_start, end - piece_start);
-
- return g_string_free (escaped, FALSE);
-}
-
-#define __G_REGEX_C__
-#include "galiasdef.c"
diff --git a/glib/grel.c b/glib/grel.c
deleted file mode 100644
index b6ee65110..000000000
--- a/glib/grel.c
+++ /dev/null
@@ -1,484 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * 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 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, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#include <stdarg.h>
-#include <string.h>
-
-#include "glib.h"
-#include "galias.h"
-
-
-typedef struct _GRealTuples GRealTuples;
-
-struct _GRelation
-{
- gint fields;
- gint current_field;
-
- GHashTable *all_tuples;
- GHashTable **hashed_tuple_tables;
-
- gint count;
-};
-
-struct _GRealTuples
-{
- gint len;
- gint width;
- gpointer *data;
-};
-
-static gboolean
-tuple_equal_2 (gconstpointer v_a,
- gconstpointer v_b)
-{
- gpointer* a = (gpointer*) v_a;
- gpointer* b = (gpointer*) v_b;
-
- return a[0] == b[0] && a[1] == b[1];
-}
-
-static guint
-tuple_hash_2 (gconstpointer v_a)
-{
-#if GLIB_SIZEOF_VOID_P > GLIB_SIZEOF_LONG
- /* In practise this snippet has been written for 64-bit Windows
- * where ints are 32 bits, pointers 64 bits. More exotic platforms
- * need more tweaks.
- */
- guint* a = (guint*) v_a;
-
- return (a[0] ^ a[1] ^ a[2] ^ a[3]);
-#else
- gpointer* a = (gpointer*) v_a;
-
- return (gulong)a[0] ^ (gulong)a[1];
-#endif
-}
-
-static GHashFunc
-tuple_hash (gint fields)
-{
- switch (fields)
- {
- case 2:
- return tuple_hash_2;
- default:
- g_error ("no tuple hash for %d", fields);
- }
-
- return NULL;
-}
-
-static GEqualFunc
-tuple_equal (gint fields)
-{
- switch (fields)
- {
- case 2:
- return tuple_equal_2;
- default:
- g_error ("no tuple equal for %d", fields);
- }
-
- return NULL;
-}
-
-GRelation*
-g_relation_new (gint fields)
-{
- GRelation* rel = g_new0 (GRelation, 1);
-
- rel->fields = fields;
- rel->all_tuples = g_hash_table_new (tuple_hash (fields), tuple_equal (fields));
- rel->hashed_tuple_tables = g_new0 (GHashTable*, fields);
-
- return rel;
-}
-
-static void
-relation_delete_value_tuple (gpointer tuple_key,
- gpointer tuple_value,
- gpointer user_data)
-{
- GRelation *relation = user_data;
- gpointer *tuple = tuple_value;
- g_slice_free1 (relation->fields * sizeof (gpointer), tuple);
-}
-
-static void
-g_relation_free_array (gpointer key, gpointer value, gpointer user_data)
-{
- g_hash_table_destroy ((GHashTable*) value);
-}
-
-void
-g_relation_destroy (GRelation *relation)
-{
- gint i;
-
- if (relation)
- {
- for (i = 0; i < relation->fields; i += 1)
- {
- if (relation->hashed_tuple_tables[i])
- {
- g_hash_table_foreach (relation->hashed_tuple_tables[i], g_relation_free_array, NULL);
- g_hash_table_destroy (relation->hashed_tuple_tables[i]);
- }
- }
-
- g_hash_table_foreach (relation->all_tuples, relation_delete_value_tuple, relation);
- g_hash_table_destroy (relation->all_tuples);
-
- g_free (relation->hashed_tuple_tables);
- g_free (relation);
- }
-}
-
-void
-g_relation_index (GRelation *relation,
- gint field,
- GHashFunc hash_func,
- GEqualFunc key_equal_func)
-{
- g_return_if_fail (relation != NULL);
-
- g_return_if_fail (relation->count == 0 && relation->hashed_tuple_tables[field] == NULL);
-
- relation->hashed_tuple_tables[field] = g_hash_table_new (hash_func, key_equal_func);
-}
-
-void
-g_relation_insert (GRelation *relation,
- ...)
-{
- gpointer* tuple = g_slice_alloc (relation->fields * sizeof (gpointer));
- va_list args;
- gint i;
-
- va_start (args, relation);
-
- for (i = 0; i < relation->fields; i += 1)
- tuple[i] = va_arg (args, gpointer);
-
- va_end (args);
-
- g_hash_table_insert (relation->all_tuples, tuple, tuple);
-
- relation->count += 1;
-
- for (i = 0; i < relation->fields; i += 1)
- {
- GHashTable *table;
- gpointer key;
- GHashTable *per_key_table;
-
- table = relation->hashed_tuple_tables[i];
-
- if (table == NULL)
- continue;
-
- key = tuple[i];
- per_key_table = g_hash_table_lookup (table, key);
-
- if (per_key_table == NULL)
- {
- per_key_table = g_hash_table_new (tuple_hash (relation->fields), tuple_equal (relation->fields));
- g_hash_table_insert (table, key, per_key_table);
- }
-
- g_hash_table_insert (per_key_table, tuple, tuple);
- }
-}
-
-static void
-g_relation_delete_tuple (gpointer tuple_key,
- gpointer tuple_value,
- gpointer user_data)
-{
- gpointer *tuple = (gpointer*) tuple_value;
- GRelation *relation = (GRelation *) user_data;
- gint j;
-
- g_assert (tuple_key == tuple_value);
-
- for (j = 0; j < relation->fields; j += 1)
- {
- GHashTable *one_table = relation->hashed_tuple_tables[j];
- gpointer one_key;
- GHashTable *per_key_table;
-
- if (one_table == NULL)
- continue;
-
- if (j == relation->current_field)
- /* can't delete from the table we're foreaching in */
- continue;
-
- one_key = tuple[j];
-
- per_key_table = g_hash_table_lookup (one_table, one_key);
-
- g_hash_table_remove (per_key_table, tuple);
- }
-
- if (g_hash_table_remove (relation->all_tuples, tuple))
- g_slice_free1 (relation->fields * sizeof (gpointer), tuple);
-
- relation->count -= 1;
-}
-
-gint
-g_relation_delete (GRelation *relation,
- gconstpointer key,
- gint field)
-{
- GHashTable *table;
- GHashTable *key_table;
- gint count;
-
- g_return_val_if_fail (relation != NULL, 0);
-
- table = relation->hashed_tuple_tables[field];
- count = relation->count;
-
- g_return_val_if_fail (table != NULL, 0);
-
- key_table = g_hash_table_lookup (table, key);
-
- if (!key_table)
- return 0;
-
- relation->current_field = field;
-
- g_hash_table_foreach (key_table, g_relation_delete_tuple, relation);
-
- g_hash_table_remove (table, key);
-
- g_hash_table_destroy (key_table);
-
- /* @@@ FIXME: Remove empty hash tables. */
-
- return count - relation->count;
-}
-
-static void
-g_relation_select_tuple (gpointer tuple_key,
- gpointer tuple_value,
- gpointer user_data)
-{
- gpointer *tuple = (gpointer*) tuple_value;
- GRealTuples *tuples = (GRealTuples*) user_data;
- gint stride = sizeof (gpointer) * tuples->width;
-
- g_assert (tuple_key == tuple_value);
-
- memcpy (tuples->data + (tuples->len * tuples->width),
- tuple,
- stride);
-
- tuples->len += 1;
-}
-
-GTuples*
-g_relation_select (GRelation *relation,
- gconstpointer key,
- gint field)
-{
- GHashTable *table;
- GHashTable *key_table;
- GRealTuples *tuples;
- gint count;
-
- g_return_val_if_fail (relation != NULL, NULL);
-
- table = relation->hashed_tuple_tables[field];
-
- g_return_val_if_fail (table != NULL, NULL);
-
- tuples = g_new0 (GRealTuples, 1);
- key_table = g_hash_table_lookup (table, key);
-
- if (!key_table)
- return (GTuples*)tuples;
-
- count = g_relation_count (relation, key, field);
-
- tuples->data = g_malloc (sizeof (gpointer) * relation->fields * count);
- tuples->width = relation->fields;
-
- g_hash_table_foreach (key_table, g_relation_select_tuple, tuples);
-
- g_assert (count == tuples->len);
-
- return (GTuples*)tuples;
-}
-
-gint
-g_relation_count (GRelation *relation,
- gconstpointer key,
- gint field)
-{
- GHashTable *table;
- GHashTable *key_table;
-
- g_return_val_if_fail (relation != NULL, 0);
-
- table = relation->hashed_tuple_tables[field];
-
- g_return_val_if_fail (table != NULL, 0);
-
- key_table = g_hash_table_lookup (table, key);
-
- if (!key_table)
- return 0;
-
- return g_hash_table_size (key_table);
-}
-
-gboolean
-g_relation_exists (GRelation *relation, ...)
-{
- gpointer *tuple = g_slice_alloc (relation->fields * sizeof (gpointer));
- va_list args;
- gint i;
- gboolean result;
-
- va_start(args, relation);
-
- for (i = 0; i < relation->fields; i += 1)
- tuple[i] = va_arg(args, gpointer);
-
- va_end(args);
-
- result = g_hash_table_lookup (relation->all_tuples, tuple) != NULL;
-
- g_slice_free1 (relation->fields * sizeof (gpointer), tuple);
-
- return result;
-}
-
-void
-g_tuples_destroy (GTuples *tuples0)
-{
- GRealTuples *tuples = (GRealTuples*) tuples0;
-
- if (tuples)
- {
- g_free (tuples->data);
- g_free (tuples);
- }
-}
-
-gpointer
-g_tuples_index (GTuples *tuples0,
- gint index,
- gint field)
-{
- GRealTuples *tuples = (GRealTuples*) tuples0;
-
- g_return_val_if_fail (tuples0 != NULL, NULL);
- g_return_val_if_fail (field < tuples->width, NULL);
-
- return tuples->data[index * tuples->width + field];
-}
-
-/* Print
- */
-
-static void
-g_relation_print_one (gpointer tuple_key,
- gpointer tuple_value,
- gpointer user_data)
-{
- gint i;
- GString *gstring;
- GRelation* rel = (GRelation*) user_data;
- gpointer* tuples = (gpointer*) tuple_value;
-
- gstring = g_string_new ("[");
-
- for (i = 0; i < rel->fields; i += 1)
- {
- g_string_append_printf (gstring, "%p", tuples[i]);
-
- if (i < (rel->fields - 1))
- g_string_append (gstring, ",");
- }
-
- g_string_append (gstring, "]");
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "%s", gstring->str);
- g_string_free (gstring, TRUE);
-}
-
-static void
-g_relation_print_index (gpointer tuple_key,
- gpointer tuple_value,
- gpointer user_data)
-{
- GRelation* rel = (GRelation*) user_data;
- GHashTable* table = (GHashTable*) tuple_value;
-
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** key %p", tuple_key);
-
- g_hash_table_foreach (table,
- g_relation_print_one,
- rel);
-}
-
-void
-g_relation_print (GRelation *relation)
-{
- gint i;
-
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** all tuples (%d)", relation->count);
-
- g_hash_table_foreach (relation->all_tuples,
- g_relation_print_one,
- relation);
-
- for (i = 0; i < relation->fields; i += 1)
- {
- if (relation->hashed_tuple_tables[i] == NULL)
- continue;
-
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** index %d", i);
-
- g_hash_table_foreach (relation->hashed_tuple_tables[i],
- g_relation_print_index,
- relation);
- }
-
-}
-
-#define __G_REL_C__
-#include "galiasdef.c"
diff --git a/glib/gscanner.c b/glib/gscanner.c
deleted file mode 100644
index 233cc73b9..000000000
--- a/glib/gscanner.c
+++ /dev/null
@@ -1,1767 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * GScanner: Flexible lexical scanner for general purpose.
- * Copyright (C) 1997, 1998 Tim Janik
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#include <errno.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdio.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "glib.h"
-#include "gprintfint.h"
-#include "galias.h"
-
-#ifdef G_OS_WIN32
-#include <io.h> /* For _read() */
-#endif
-
-/* --- defines --- */
-#define to_lower(c) ( \
- (guchar) ( \
- ( (((guchar)(c))>='A' && ((guchar)(c))<='Z') * ('a'-'A') ) | \
- ( (((guchar)(c))>=192 && ((guchar)(c))<=214) * (224-192) ) | \
- ( (((guchar)(c))>=216 && ((guchar)(c))<=222) * (248-216) ) | \
- ((guchar)(c)) \
- ) \
-)
-#define READ_BUFFER_SIZE (4000)
-
-
-/* --- typedefs --- */
-typedef struct _GScannerKey GScannerKey;
-
-struct _GScannerKey
-{
- guint scope_id;
- gchar *symbol;
- gpointer value;
-};
-
-
-/* --- variables --- */
-static const GScannerConfig g_scanner_config_template =
-{
- (
- " \t\r\n"
- ) /* cset_skip_characters */,
- (
- G_CSET_a_2_z
- "_"
- G_CSET_A_2_Z
- ) /* cset_identifier_first */,
- (
- G_CSET_a_2_z
- "_"
- G_CSET_A_2_Z
- G_CSET_DIGITS
- G_CSET_LATINS
- G_CSET_LATINC
- ) /* cset_identifier_nth */,
- ( "#\n" ) /* cpair_comment_single */,
-
- FALSE /* case_sensitive */,
-
- TRUE /* skip_comment_multi */,
- TRUE /* skip_comment_single */,
- TRUE /* scan_comment_multi */,
- TRUE /* scan_identifier */,
- FALSE /* scan_identifier_1char */,
- FALSE /* scan_identifier_NULL */,
- TRUE /* scan_symbols */,
- FALSE /* scan_binary */,
- TRUE /* scan_octal */,
- TRUE /* scan_float */,
- TRUE /* scan_hex */,
- FALSE /* scan_hex_dollar */,
- TRUE /* scan_string_sq */,
- TRUE /* scan_string_dq */,
- TRUE /* numbers_2_int */,
- FALSE /* int_2_float */,
- FALSE /* identifier_2_string */,
- TRUE /* char_2_token */,
- FALSE /* symbol_2_token */,
- FALSE /* scope_0_fallback */,
- FALSE /* store_int64 */,
-};
-
-
-/* --- prototypes --- */
-static inline
-GScannerKey* g_scanner_lookup_internal (GScanner *scanner,
- guint scope_id,
- const gchar *symbol);
-static gboolean g_scanner_key_equal (gconstpointer v1,
- gconstpointer v2);
-static guint g_scanner_key_hash (gconstpointer v);
-static void g_scanner_get_token_ll (GScanner *scanner,
- GTokenType *token_p,
- GTokenValue *value_p,
- guint *line_p,
- guint *position_p);
-static void g_scanner_get_token_i (GScanner *scanner,
- GTokenType *token_p,
- GTokenValue *value_p,
- guint *line_p,
- guint *position_p);
-
-static guchar g_scanner_peek_next_char (GScanner *scanner);
-static guchar g_scanner_get_char (GScanner *scanner,
- guint *line_p,
- guint *position_p);
-static void g_scanner_msg_handler (GScanner *scanner,
- gchar *message,
- gboolean is_error);
-
-
-/* --- functions --- */
-static inline gint
-g_scanner_char_2_num (guchar c,
- guchar base)
-{
- if (c >= '0' && c <= '9')
- c -= '0';
- else if (c >= 'A' && c <= 'Z')
- c -= 'A' - 10;
- else if (c >= 'a' && c <= 'z')
- c -= 'a' - 10;
- else
- return -1;
-
- if (c < base)
- return c;
-
- return -1;
-}
-
-GScanner*
-g_scanner_new (const GScannerConfig *config_templ)
-{
- GScanner *scanner;
-
- if (!config_templ)
- config_templ = &g_scanner_config_template;
-
- scanner = g_new0 (GScanner, 1);
-
- scanner->user_data = NULL;
- scanner->max_parse_errors = 1;
- scanner->parse_errors = 0;
- scanner->input_name = NULL;
- g_datalist_init (&scanner->qdata);
-
- scanner->config = g_new0 (GScannerConfig, 1);
-
- scanner->config->case_sensitive = config_templ->case_sensitive;
- scanner->config->cset_skip_characters = config_templ->cset_skip_characters;
- if (!scanner->config->cset_skip_characters)
- scanner->config->cset_skip_characters = "";
- scanner->config->cset_identifier_first = config_templ->cset_identifier_first;
- scanner->config->cset_identifier_nth = config_templ->cset_identifier_nth;
- scanner->config->cpair_comment_single = config_templ->cpair_comment_single;
- scanner->config->skip_comment_multi = config_templ->skip_comment_multi;
- scanner->config->skip_comment_single = config_templ->skip_comment_single;
- scanner->config->scan_comment_multi = config_templ->scan_comment_multi;
- scanner->config->scan_identifier = config_templ->scan_identifier;
- scanner->config->scan_identifier_1char = config_templ->scan_identifier_1char;
- scanner->config->scan_identifier_NULL = config_templ->scan_identifier_NULL;
- scanner->config->scan_symbols = config_templ->scan_symbols;
- scanner->config->scan_binary = config_templ->scan_binary;
- scanner->config->scan_octal = config_templ->scan_octal;
- scanner->config->scan_float = config_templ->scan_float;
- scanner->config->scan_hex = config_templ->scan_hex;
- scanner->config->scan_hex_dollar = config_templ->scan_hex_dollar;
- scanner->config->scan_string_sq = config_templ->scan_string_sq;
- scanner->config->scan_string_dq = config_templ->scan_string_dq;
- scanner->config->numbers_2_int = config_templ->numbers_2_int;
- scanner->config->int_2_float = config_templ->int_2_float;
- scanner->config->identifier_2_string = config_templ->identifier_2_string;
- scanner->config->char_2_token = config_templ->char_2_token;
- scanner->config->symbol_2_token = config_templ->symbol_2_token;
- scanner->config->scope_0_fallback = config_templ->scope_0_fallback;
- scanner->config->store_int64 = config_templ->store_int64;
-
- scanner->token = G_TOKEN_NONE;
- scanner->value.v_int64 = 0;
- scanner->line = 1;
- scanner->position = 0;
-
- scanner->next_token = G_TOKEN_NONE;
- scanner->next_value.v_int64 = 0;
- scanner->next_line = 1;
- scanner->next_position = 0;
-
- scanner->symbol_table = g_hash_table_new (g_scanner_key_hash, g_scanner_key_equal);
- scanner->input_fd = -1;
- scanner->text = NULL;
- scanner->text_end = NULL;
- scanner->buffer = NULL;
- scanner->scope_id = 0;
-
- scanner->msg_handler = g_scanner_msg_handler;
-
- return scanner;
-}
-
-static inline void
-g_scanner_free_value (GTokenType *token_p,
- GTokenValue *value_p)
-{
- switch (*token_p)
- {
- case G_TOKEN_STRING:
- case G_TOKEN_IDENTIFIER:
- case G_TOKEN_IDENTIFIER_NULL:
- case G_TOKEN_COMMENT_SINGLE:
- case G_TOKEN_COMMENT_MULTI:
- g_free (value_p->v_string);
- break;
-
- default:
- break;
- }
-
- *token_p = G_TOKEN_NONE;
-}
-
-static void
-g_scanner_destroy_symbol_table_entry (gpointer _key,
- gpointer _value,
- gpointer _data)
-{
- GScannerKey *key = _key;
-
- g_free (key->symbol);
- g_free (key);
-}
-
-void
-g_scanner_destroy (GScanner *scanner)
-{
- g_return_if_fail (scanner != NULL);
-
- g_datalist_clear (&scanner->qdata);
- g_hash_table_foreach (scanner->symbol_table,
- g_scanner_destroy_symbol_table_entry, NULL);
- g_hash_table_destroy (scanner->symbol_table);
- g_scanner_free_value (&scanner->token, &scanner->value);
- g_scanner_free_value (&scanner->next_token, &scanner->next_value);
- g_free (scanner->config);
- g_free (scanner->buffer);
- g_free (scanner);
-}
-
-static void
-g_scanner_msg_handler (GScanner *scanner,
- gchar *message,
- gboolean is_error)
-{
- g_return_if_fail (scanner != NULL);
-
- _g_fprintf (stderr, "%s:%d: ",
- scanner->input_name ? scanner->input_name : "<memory>",
- scanner->line);
- if (is_error)
- _g_fprintf (stderr, "error: ");
- _g_fprintf (stderr, "%s\n", message);
-}
-
-void
-g_scanner_error (GScanner *scanner,
- const gchar *format,
- ...)
-{
- g_return_if_fail (scanner != NULL);
- g_return_if_fail (format != NULL);
-
- scanner->parse_errors++;
-
- if (scanner->msg_handler)
- {
- va_list args;
- gchar *string;
-
- va_start (args, format);
- string = g_strdup_vprintf (format, args);
- va_end (args);
-
- scanner->msg_handler (scanner, string, TRUE);
-
- g_free (string);
- }
-}
-
-void
-g_scanner_warn (GScanner *scanner,
- const gchar *format,
- ...)
-{
- g_return_if_fail (scanner != NULL);
- g_return_if_fail (format != NULL);
-
- if (scanner->msg_handler)
- {
- va_list args;
- gchar *string;
-
- va_start (args, format);
- string = g_strdup_vprintf (format, args);
- va_end (args);
-
- scanner->msg_handler (scanner, string, FALSE);
-
- g_free (string);
- }
-}
-
-static gboolean
-g_scanner_key_equal (gconstpointer v1,
- gconstpointer v2)
-{
- const GScannerKey *key1 = v1;
- const GScannerKey *key2 = v2;
-
- return (key1->scope_id == key2->scope_id) && (strcmp (key1->symbol, key2->symbol) == 0);
-}
-
-static guint
-g_scanner_key_hash (gconstpointer v)
-{
- const GScannerKey *key = v;
- gchar *c;
- guint h;
-
- h = key->scope_id;
- for (c = key->symbol; *c; c++)
- h = (h << 5) - h + *c;
-
- return h;
-}
-
-static inline GScannerKey*
-g_scanner_lookup_internal (GScanner *scanner,
- guint scope_id,
- const gchar *symbol)
-{
- GScannerKey *key_p;
- GScannerKey key;
-
- key.scope_id = scope_id;
-
- if (!scanner->config->case_sensitive)
- {
- gchar *d;
- const gchar *c;
-
- key.symbol = g_new (gchar, strlen (symbol) + 1);
- for (d = key.symbol, c = symbol; *c; c++, d++)
- *d = to_lower (*c);
- *d = 0;
- key_p = g_hash_table_lookup (scanner->symbol_table, &key);
- g_free (key.symbol);
- }
- else
- {
- key.symbol = (gchar*) symbol;
- key_p = g_hash_table_lookup (scanner->symbol_table, &key);
- }
-
- return key_p;
-}
-
-void
-g_scanner_scope_add_symbol (GScanner *scanner,
- guint scope_id,
- const gchar *symbol,
- gpointer value)
-{
- GScannerKey *key;
-
- g_return_if_fail (scanner != NULL);
- g_return_if_fail (symbol != NULL);
-
- key = g_scanner_lookup_internal (scanner, scope_id, symbol);
-
- if (!key)
- {
- key = g_new (GScannerKey, 1);
- key->scope_id = scope_id;
- key->symbol = g_strdup (symbol);
- key->value = value;
- if (!scanner->config->case_sensitive)
- {
- gchar *c;
-
- c = key->symbol;
- while (*c != 0)
- {
- *c = to_lower (*c);
- c++;
- }
- }
- g_hash_table_insert (scanner->symbol_table, key, key);
- }
- else
- key->value = value;
-}
-
-void
-g_scanner_scope_remove_symbol (GScanner *scanner,
- guint scope_id,
- const gchar *symbol)
-{
- GScannerKey *key;
-
- g_return_if_fail (scanner != NULL);
- g_return_if_fail (symbol != NULL);
-
- key = g_scanner_lookup_internal (scanner, scope_id, symbol);
-
- if (key)
- {
- g_hash_table_remove (scanner->symbol_table, key);
- g_free (key->symbol);
- g_free (key);
- }
-}
-
-gpointer
-g_scanner_lookup_symbol (GScanner *scanner,
- const gchar *symbol)
-{
- GScannerKey *key;
- guint scope_id;
-
- g_return_val_if_fail (scanner != NULL, NULL);
-
- if (!symbol)
- return NULL;
-
- scope_id = scanner->scope_id;
- key = g_scanner_lookup_internal (scanner, scope_id, symbol);
- if (!key && scope_id && scanner->config->scope_0_fallback)
- key = g_scanner_lookup_internal (scanner, 0, symbol);
-
- if (key)
- return key->value;
- else
- return NULL;
-}
-
-gpointer
-g_scanner_scope_lookup_symbol (GScanner *scanner,
- guint scope_id,
- const gchar *symbol)
-{
- GScannerKey *key;
-
- g_return_val_if_fail (scanner != NULL, NULL);
-
- if (!symbol)
- return NULL;
-
- key = g_scanner_lookup_internal (scanner, scope_id, symbol);
-
- if (key)
- return key->value;
- else
- return NULL;
-}
-
-guint
-g_scanner_set_scope (GScanner *scanner,
- guint scope_id)
-{
- guint old_scope_id;
-
- g_return_val_if_fail (scanner != NULL, 0);
-
- old_scope_id = scanner->scope_id;
- scanner->scope_id = scope_id;
-
- return old_scope_id;
-}
-
-static void
-g_scanner_foreach_internal (gpointer _key,
- gpointer _value,
- gpointer _user_data)
-{
- GScannerKey *key;
- gpointer *d;
- GHFunc func;
- gpointer user_data;
- guint *scope_id;
-
- d = _user_data;
- func = (GHFunc) d[0];
- user_data = d[1];
- scope_id = d[2];
- key = _value;
-
- if (key->scope_id == *scope_id)
- func (key->symbol, key->value, user_data);
-}
-
-void
-g_scanner_scope_foreach_symbol (GScanner *scanner,
- guint scope_id,
- GHFunc func,
- gpointer user_data)
-{
- gpointer d[3];
-
- g_return_if_fail (scanner != NULL);
-
- d[0] = (gpointer) func;
- d[1] = user_data;
- d[2] = &scope_id;
-
- g_hash_table_foreach (scanner->symbol_table, g_scanner_foreach_internal, d);
-}
-
-GTokenType
-g_scanner_peek_next_token (GScanner *scanner)
-{
- g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
-
- if (scanner->next_token == G_TOKEN_NONE)
- {
- scanner->next_line = scanner->line;
- scanner->next_position = scanner->position;
- g_scanner_get_token_i (scanner,
- &scanner->next_token,
- &scanner->next_value,
- &scanner->next_line,
- &scanner->next_position);
- }
-
- return scanner->next_token;
-}
-
-GTokenType
-g_scanner_get_next_token (GScanner *scanner)
-{
- g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
-
- if (scanner->next_token != G_TOKEN_NONE)
- {
- g_scanner_free_value (&scanner->token, &scanner->value);
-
- scanner->token = scanner->next_token;
- scanner->value = scanner->next_value;
- scanner->line = scanner->next_line;
- scanner->position = scanner->next_position;
- scanner->next_token = G_TOKEN_NONE;
- }
- else
- g_scanner_get_token_i (scanner,
- &scanner->token,
- &scanner->value,
- &scanner->line,
- &scanner->position);
-
- return scanner->token;
-}
-
-GTokenType
-g_scanner_cur_token (GScanner *scanner)
-{
- g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
-
- return scanner->token;
-}
-
-GTokenValue
-g_scanner_cur_value (GScanner *scanner)
-{
- GTokenValue v;
-
- v.v_int64 = 0;
-
- g_return_val_if_fail (scanner != NULL, v);
-
- /* MSC isn't capable of handling return scanner->value; ? */
-
- v = scanner->value;
-
- return v;
-}
-
-guint
-g_scanner_cur_line (GScanner *scanner)
-{
- g_return_val_if_fail (scanner != NULL, 0);
-
- return scanner->line;
-}
-
-guint
-g_scanner_cur_position (GScanner *scanner)
-{
- g_return_val_if_fail (scanner != NULL, 0);
-
- return scanner->position;
-}
-
-gboolean
-g_scanner_eof (GScanner *scanner)
-{
- g_return_val_if_fail (scanner != NULL, TRUE);
-
- return scanner->token == G_TOKEN_EOF || scanner->token == G_TOKEN_ERROR;
-}
-
-void
-g_scanner_input_file (GScanner *scanner,
- gint input_fd)
-{
- g_return_if_fail (scanner != NULL);
- g_return_if_fail (input_fd >= 0);
-
- if (scanner->input_fd >= 0)
- g_scanner_sync_file_offset (scanner);
-
- scanner->token = G_TOKEN_NONE;
- scanner->value.v_int64 = 0;
- scanner->line = 1;
- scanner->position = 0;
- scanner->next_token = G_TOKEN_NONE;
-
- scanner->input_fd = input_fd;
- scanner->text = NULL;
- scanner->text_end = NULL;
-
- if (!scanner->buffer)
- scanner->buffer = g_new (gchar, READ_BUFFER_SIZE + 1);
-}
-
-void
-g_scanner_input_text (GScanner *scanner,
- const gchar *text,
- guint text_len)
-{
- g_return_if_fail (scanner != NULL);
- if (text_len)
- g_return_if_fail (text != NULL);
- else
- text = NULL;
-
- if (scanner->input_fd >= 0)
- g_scanner_sync_file_offset (scanner);
-
- scanner->token = G_TOKEN_NONE;
- scanner->value.v_int64 = 0;
- scanner->line = 1;
- scanner->position = 0;
- scanner->next_token = G_TOKEN_NONE;
-
- scanner->input_fd = -1;
- scanner->text = text;
- scanner->text_end = text + text_len;
-
- if (scanner->buffer)
- {
- g_free (scanner->buffer);
- scanner->buffer = NULL;
- }
-}
-
-static guchar
-g_scanner_peek_next_char (GScanner *scanner)
-{
- if (scanner->text < scanner->text_end)
- {
- return *scanner->text;
- }
- else if (scanner->input_fd >= 0)
- {
- gint count;
- gchar *buffer;
-
- buffer = scanner->buffer;
- do
- {
- count = read (scanner->input_fd, buffer, READ_BUFFER_SIZE);
- }
- while (count == -1 && (errno == EINTR || errno == EAGAIN));
-
- if (count < 1)
- {
- scanner->input_fd = -1;
-
- return 0;
- }
- else
- {
- scanner->text = buffer;
- scanner->text_end = buffer + count;
-
- return *buffer;
- }
- }
- else
- return 0;
-}
-
-void
-g_scanner_sync_file_offset (GScanner *scanner)
-{
- g_return_if_fail (scanner != NULL);
-
- /* for file input, rewind the filedescriptor to the current
- * buffer position and blow the file read ahead buffer. useful
- * for third party uses of our file descriptor, which hooks
- * onto the current scanning position.
- */
-
- if (scanner->input_fd >= 0 && scanner->text_end > scanner->text)
- {
- gint buffered;
-
- buffered = scanner->text_end - scanner->text;
- if (lseek (scanner->input_fd, - buffered, SEEK_CUR) >= 0)
- {
- /* we succeeded, blow our buffer's contents now */
- scanner->text = NULL;
- scanner->text_end = NULL;
- }
- else
- errno = 0;
- }
-}
-
-static guchar
-g_scanner_get_char (GScanner *scanner,
- guint *line_p,
- guint *position_p)
-{
- guchar fchar;
-
- if (scanner->text < scanner->text_end)
- fchar = *(scanner->text++);
- else if (scanner->input_fd >= 0)
- {
- gint count;
- gchar *buffer;
-
- buffer = scanner->buffer;
- do
- {
- count = read (scanner->input_fd, buffer, READ_BUFFER_SIZE);
- }
- while (count == -1 && (errno == EINTR || errno == EAGAIN));
-
- if (count < 1)
- {
- scanner->input_fd = -1;
- fchar = 0;
- }
- else
- {
- scanner->text = buffer + 1;
- scanner->text_end = buffer + count;
- fchar = *buffer;
- if (!fchar)
- {
- g_scanner_sync_file_offset (scanner);
- scanner->text_end = scanner->text;
- scanner->input_fd = -1;
- }
- }
- }
- else
- fchar = 0;
-
- if (fchar == '\n')
- {
- (*position_p) = 0;
- (*line_p)++;
- }
- else if (fchar)
- {
- (*position_p)++;
- }
-
- return fchar;
-}
-
-void
-g_scanner_unexp_token (GScanner *scanner,
- GTokenType expected_token,
- const gchar *identifier_spec,
- const gchar *symbol_spec,
- const gchar *symbol_name,
- const gchar *message,
- gint is_error)
-{
- gchar *token_string;
- guint token_string_len;
- gchar *expected_string;
- guint expected_string_len;
- gchar *message_prefix;
- gboolean print_unexp;
- void (*msg_handler) (GScanner*, const gchar*, ...);
-
- g_return_if_fail (scanner != NULL);
-
- if (is_error)
- msg_handler = g_scanner_error;
- else
- msg_handler = g_scanner_warn;
-
- if (!identifier_spec)
- identifier_spec = "identifier";
- if (!symbol_spec)
- symbol_spec = "symbol";
-
- token_string_len = 56;
- token_string = g_new (gchar, token_string_len + 1);
- expected_string_len = 64;
- expected_string = g_new (gchar, expected_string_len + 1);
- print_unexp = TRUE;
-
- switch (scanner->token)
- {
- case G_TOKEN_EOF:
- _g_snprintf (token_string, token_string_len, "end of file");
- break;
-
- default:
- if (scanner->token >= 1 && scanner->token <= 255)
- {
- if ((scanner->token >= ' ' && scanner->token <= '~') ||
- strchr (scanner->config->cset_identifier_first, scanner->token) ||
- strchr (scanner->config->cset_identifier_nth, scanner->token))
- _g_snprintf (token_string, token_string_len, "character `%c'", scanner->token);
- else
- _g_snprintf (token_string, token_string_len, "character `\\%o'", scanner->token);
- break;
- }
- else if (!scanner->config->symbol_2_token)
- {
- _g_snprintf (token_string, token_string_len, "(unknown) token <%d>", scanner->token);
- break;
- }
- /* fall through */
- case G_TOKEN_SYMBOL:
- if (expected_token == G_TOKEN_SYMBOL ||
- (scanner->config->symbol_2_token &&
- expected_token > G_TOKEN_LAST))
- print_unexp = FALSE;
- if (symbol_name)
- _g_snprintf (token_string,
- token_string_len,
- "%s%s `%s'",
- print_unexp ? "" : "invalid ",
- symbol_spec,
- symbol_name);
- else
- _g_snprintf (token_string,
- token_string_len,
- "%s%s",
- print_unexp ? "" : "invalid ",
- symbol_spec);
- break;
-
- case G_TOKEN_ERROR:
- print_unexp = FALSE;
- expected_token = G_TOKEN_NONE;
- switch (scanner->value.v_error)
- {
- case G_ERR_UNEXP_EOF:
- _g_snprintf (token_string, token_string_len, "scanner: unexpected end of file");
- break;
-
- case G_ERR_UNEXP_EOF_IN_STRING:
- _g_snprintf (token_string, token_string_len, "scanner: unterminated string constant");
- break;
-
- case G_ERR_UNEXP_EOF_IN_COMMENT:
- _g_snprintf (token_string, token_string_len, "scanner: unterminated comment");
- break;
-
- case G_ERR_NON_DIGIT_IN_CONST:
- _g_snprintf (token_string, token_string_len, "scanner: non digit in constant");
- break;
-
- case G_ERR_FLOAT_RADIX:
- _g_snprintf (token_string, token_string_len, "scanner: invalid radix for floating constant");
- break;
-
- case G_ERR_FLOAT_MALFORMED:
- _g_snprintf (token_string, token_string_len, "scanner: malformed floating constant");
- break;
-
- case G_ERR_DIGIT_RADIX:
- _g_snprintf (token_string, token_string_len, "scanner: digit is beyond radix");
- break;
-
- case G_ERR_UNKNOWN:
- default:
- _g_snprintf (token_string, token_string_len, "scanner: unknown error");
- break;
- }
- break;
-
- case G_TOKEN_CHAR:
- _g_snprintf (token_string, token_string_len, "character `%c'", scanner->value.v_char);
- break;
-
- case G_TOKEN_IDENTIFIER:
- case G_TOKEN_IDENTIFIER_NULL:
- if (expected_token == G_TOKEN_IDENTIFIER ||
- expected_token == G_TOKEN_IDENTIFIER_NULL)
- print_unexp = FALSE;
- _g_snprintf (token_string,
- token_string_len,
- "%s%s `%s'",
- print_unexp ? "" : "invalid ",
- identifier_spec,
- scanner->token == G_TOKEN_IDENTIFIER ? scanner->value.v_string : "null");
- break;
-
- case G_TOKEN_BINARY:
- case G_TOKEN_OCTAL:
- case G_TOKEN_INT:
- case G_TOKEN_HEX:
- if (scanner->config->store_int64)
- _g_snprintf (token_string, token_string_len, "number `%" G_GUINT64_FORMAT "'", scanner->value.v_int64);
- else
- _g_snprintf (token_string, token_string_len, "number `%lu'", scanner->value.v_int);
- break;
-
- case G_TOKEN_FLOAT:
- _g_snprintf (token_string, token_string_len, "number `%.3f'", scanner->value.v_float);
- break;
-
- case G_TOKEN_STRING:
- if (expected_token == G_TOKEN_STRING)
- print_unexp = FALSE;
- _g_snprintf (token_string,
- token_string_len,
- "%s%sstring constant \"%s\"",
- print_unexp ? "" : "invalid ",
- scanner->value.v_string[0] == 0 ? "empty " : "",
- scanner->value.v_string);
- token_string[token_string_len - 2] = '"';
- token_string[token_string_len - 1] = 0;
- break;
-
- case G_TOKEN_COMMENT_SINGLE:
- case G_TOKEN_COMMENT_MULTI:
- _g_snprintf (token_string, token_string_len, "comment");
- break;
-
- case G_TOKEN_NONE:
- /* somehow the user's parsing code is screwed, there isn't much
- * we can do about it.
- * Note, a common case to trigger this is
- * g_scanner_peek_next_token(); g_scanner_unexp_token();
- * without an intermediate g_scanner_get_next_token().
- */
- g_assert_not_reached ();
- break;
- }
-
-
- switch (expected_token)
- {
- gboolean need_valid;
- gchar *tstring;
- case G_TOKEN_EOF:
- _g_snprintf (expected_string, expected_string_len, "end of file");
- break;
- default:
- if (expected_token >= 1 && expected_token <= 255)
- {
- if ((expected_token >= ' ' && expected_token <= '~') ||
- strchr (scanner->config->cset_identifier_first, expected_token) ||
- strchr (scanner->config->cset_identifier_nth, expected_token))
- _g_snprintf (expected_string, expected_string_len, "character `%c'", expected_token);
- else
- _g_snprintf (expected_string, expected_string_len, "character `\\%o'", expected_token);
- break;
- }
- else if (!scanner->config->symbol_2_token)
- {
- _g_snprintf (expected_string, expected_string_len, "(unknown) token <%d>", expected_token);
- break;
- }
- /* fall through */
- case G_TOKEN_SYMBOL:
- need_valid = (scanner->token == G_TOKEN_SYMBOL ||
- (scanner->config->symbol_2_token &&
- scanner->token > G_TOKEN_LAST));
- _g_snprintf (expected_string,
- expected_string_len,
- "%s%s",
- need_valid ? "valid " : "",
- symbol_spec);
- /* FIXME: should we attempt to lookup the symbol_name for symbol_2_token? */
- break;
- case G_TOKEN_CHAR:
- _g_snprintf (expected_string, expected_string_len, "%scharacter",
- scanner->token == G_TOKEN_CHAR ? "valid " : "");
- break;
- case G_TOKEN_BINARY:
- tstring = "binary";
- _g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
- scanner->token == expected_token ? "valid " : "", tstring);
- break;
- case G_TOKEN_OCTAL:
- tstring = "octal";
- _g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
- scanner->token == expected_token ? "valid " : "", tstring);
- break;
- case G_TOKEN_INT:
- tstring = "integer";
- _g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
- scanner->token == expected_token ? "valid " : "", tstring);
- break;
- case G_TOKEN_HEX:
- tstring = "hexadecimal";
- _g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
- scanner->token == expected_token ? "valid " : "", tstring);
- break;
- case G_TOKEN_FLOAT:
- tstring = "float";
- _g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
- scanner->token == expected_token ? "valid " : "", tstring);
- break;
- case G_TOKEN_STRING:
- _g_snprintf (expected_string,
- expected_string_len,
- "%sstring constant",
- scanner->token == G_TOKEN_STRING ? "valid " : "");
- break;
- case G_TOKEN_IDENTIFIER:
- case G_TOKEN_IDENTIFIER_NULL:
- need_valid = (scanner->token == G_TOKEN_IDENTIFIER_NULL ||
- scanner->token == G_TOKEN_IDENTIFIER);
- _g_snprintf (expected_string,
- expected_string_len,
- "%s%s",
- need_valid ? "valid " : "",
- identifier_spec);
- break;
- case G_TOKEN_COMMENT_SINGLE:
- tstring = "single-line";
- _g_snprintf (expected_string, expected_string_len, "%scomment (%s)",
- scanner->token == expected_token ? "valid " : "", tstring);
- break;
- case G_TOKEN_COMMENT_MULTI:
- tstring = "multi-line";
- _g_snprintf (expected_string, expected_string_len, "%scomment (%s)",
- scanner->token == expected_token ? "valid " : "", tstring);
- break;
- case G_TOKEN_NONE:
- case G_TOKEN_ERROR:
- /* this is handled upon printout */
- break;
- }
-
- if (message && message[0] != 0)
- message_prefix = " - ";
- else
- {
- message_prefix = "";
- message = "";
- }
- if (expected_token == G_TOKEN_ERROR)
- {
- msg_handler (scanner,
- "failure around %s%s%s",
- token_string,
- message_prefix,
- message);
- }
- else if (expected_token == G_TOKEN_NONE)
- {
- if (print_unexp)
- msg_handler (scanner,
- "unexpected %s%s%s",
- token_string,
- message_prefix,
- message);
- else
- msg_handler (scanner,
- "%s%s%s",
- token_string,
- message_prefix,
- message);
- }
- else
- {
- if (print_unexp)
- msg_handler (scanner,
- "unexpected %s, expected %s%s%s",
- token_string,
- expected_string,
- message_prefix,
- message);
- else
- msg_handler (scanner,
- "%s, expected %s%s%s",
- token_string,
- expected_string,
- message_prefix,
- message);
- }
-
- g_free (token_string);
- g_free (expected_string);
-}
-
-static void
-g_scanner_get_token_i (GScanner *scanner,
- GTokenType *token_p,
- GTokenValue *value_p,
- guint *line_p,
- guint *position_p)
-{
- do
- {
- g_scanner_free_value (token_p, value_p);
- g_scanner_get_token_ll (scanner, token_p, value_p, line_p, position_p);
- }
- while (((*token_p > 0 && *token_p < 256) &&
- strchr (scanner->config->cset_skip_characters, *token_p)) ||
- (*token_p == G_TOKEN_CHAR &&
- strchr (scanner->config->cset_skip_characters, value_p->v_char)) ||
- (*token_p == G_TOKEN_COMMENT_MULTI &&
- scanner->config->skip_comment_multi) ||
- (*token_p == G_TOKEN_COMMENT_SINGLE &&
- scanner->config->skip_comment_single));
-
- switch (*token_p)
- {
- case G_TOKEN_IDENTIFIER:
- if (scanner->config->identifier_2_string)
- *token_p = G_TOKEN_STRING;
- break;
-
- case G_TOKEN_SYMBOL:
- if (scanner->config->symbol_2_token)
- *token_p = (GTokenType) value_p->v_symbol;
- break;
-
- case G_TOKEN_BINARY:
- case G_TOKEN_OCTAL:
- case G_TOKEN_HEX:
- if (scanner->config->numbers_2_int)
- *token_p = G_TOKEN_INT;
- break;
-
- default:
- break;
- }
-
- if (*token_p == G_TOKEN_INT &&
- scanner->config->int_2_float)
- {
- *token_p = G_TOKEN_FLOAT;
- if (scanner->config->store_int64)
- {
-#ifdef _MSC_VER
- /* work around error C2520, see gvaluetransform.c */
- value_p->v_float = (__int64)value_p->v_int64;
-#else
- value_p->v_float = value_p->v_int64;
-#endif
- }
- else
- value_p->v_float = value_p->v_int;
- }
-
- errno = 0;
-}
-
-static void
-g_scanner_get_token_ll (GScanner *scanner,
- GTokenType *token_p,
- GTokenValue *value_p,
- guint *line_p,
- guint *position_p)
-{
- GScannerConfig *config;
- GTokenType token;
- gboolean in_comment_multi;
- gboolean in_comment_single;
- gboolean in_string_sq;
- gboolean in_string_dq;
- GString *gstring;
- GTokenValue value;
- guchar ch;
-
- config = scanner->config;
- (*value_p).v_int64 = 0;
-
- if ((scanner->text >= scanner->text_end && scanner->input_fd < 0) ||
- scanner->token == G_TOKEN_EOF)
- {
- *token_p = G_TOKEN_EOF;
- return;
- }
-
- in_comment_multi = FALSE;
- in_comment_single = FALSE;
- in_string_sq = FALSE;
- in_string_dq = FALSE;
- gstring = NULL;
-
- do /* while (ch != 0) */
- {
- gboolean dotted_float = FALSE;
-
- ch = g_scanner_get_char (scanner, line_p, position_p);
-
- value.v_int64 = 0;
- token = G_TOKEN_NONE;
-
- /* this is *evil*, but needed ;(
- * we first check for identifier first character, because it
- * might interfere with other key chars like slashes or numbers
- */
- if (config->scan_identifier &&
- ch && strchr (config->cset_identifier_first, ch))
- goto identifier_precedence;
-
- switch (ch)
- {
- case 0:
- token = G_TOKEN_EOF;
- (*position_p)++;
- /* ch = 0; */
- break;
-
- case '/':
- if (!config->scan_comment_multi ||
- g_scanner_peek_next_char (scanner) != '*')
- goto default_case;
- g_scanner_get_char (scanner, line_p, position_p);
- token = G_TOKEN_COMMENT_MULTI;
- in_comment_multi = TRUE;
- gstring = g_string_new (NULL);
- while ((ch = g_scanner_get_char (scanner, line_p, position_p)) != 0)
- {
- if (ch == '*' && g_scanner_peek_next_char (scanner) == '/')
- {
- g_scanner_get_char (scanner, line_p, position_p);
- in_comment_multi = FALSE;
- break;
- }
- else
- gstring = g_string_append_c (gstring, ch);
- }
- ch = 0;
- break;
-
- case '\'':
- if (!config->scan_string_sq)
- goto default_case;
- token = G_TOKEN_STRING;
- in_string_sq = TRUE;
- gstring = g_string_new (NULL);
- while ((ch = g_scanner_get_char (scanner, line_p, position_p)) != 0)
- {
- if (ch == '\'')
- {
- in_string_sq = FALSE;
- break;
- }
- else
- gstring = g_string_append_c (gstring, ch);
- }
- ch = 0;
- break;
-
- case '"':
- if (!config->scan_string_dq)
- goto default_case;
- token = G_TOKEN_STRING;
- in_string_dq = TRUE;
- gstring = g_string_new (NULL);
- while ((ch = g_scanner_get_char (scanner, line_p, position_p)) != 0)
- {
- if (ch == '"')
- {
- in_string_dq = FALSE;
- break;
- }
- else
- {
- if (ch == '\\')
- {
- ch = g_scanner_get_char (scanner, line_p, position_p);
- switch (ch)
- {
- guint i;
- guint fchar;
-
- case 0:
- break;
-
- case '\\':
- gstring = g_string_append_c (gstring, '\\');
- break;
-
- case 'n':
- gstring = g_string_append_c (gstring, '\n');
- break;
-
- case 't':
- gstring = g_string_append_c (gstring, '\t');
- break;
-
- case 'r':
- gstring = g_string_append_c (gstring, '\r');
- break;
-
- case 'b':
- gstring = g_string_append_c (gstring, '\b');
- break;
-
- case 'f':
- gstring = g_string_append_c (gstring, '\f');
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- i = ch - '0';
- fchar = g_scanner_peek_next_char (scanner);
- if (fchar >= '0' && fchar <= '7')
- {
- ch = g_scanner_get_char (scanner, line_p, position_p);
- i = i * 8 + ch - '0';
- fchar = g_scanner_peek_next_char (scanner);
- if (fchar >= '0' && fchar <= '7')
- {
- ch = g_scanner_get_char (scanner, line_p, position_p);
- i = i * 8 + ch - '0';
- }
- }
- gstring = g_string_append_c (gstring, i);
- break;
-
- default:
- gstring = g_string_append_c (gstring, ch);
- break;
- }
- }
- else
- gstring = g_string_append_c (gstring, ch);
- }
- }
- ch = 0;
- break;
-
- case '.':
- if (!config->scan_float)
- goto default_case;
- token = G_TOKEN_FLOAT;
- dotted_float = TRUE;
- ch = g_scanner_get_char (scanner, line_p, position_p);
- goto number_parsing;
-
- case '$':
- if (!config->scan_hex_dollar)
- goto default_case;
- token = G_TOKEN_HEX;
- ch = g_scanner_get_char (scanner, line_p, position_p);
- goto number_parsing;
-
- case '0':
- if (config->scan_octal)
- token = G_TOKEN_OCTAL;
- else
- token = G_TOKEN_INT;
- ch = g_scanner_peek_next_char (scanner);
- if (config->scan_hex && (ch == 'x' || ch == 'X'))
- {
- token = G_TOKEN_HEX;
- g_scanner_get_char (scanner, line_p, position_p);
- ch = g_scanner_get_char (scanner, line_p, position_p);
- if (ch == 0)
- {
- token = G_TOKEN_ERROR;
- value.v_error = G_ERR_UNEXP_EOF;
- (*position_p)++;
- break;
- }
- if (g_scanner_char_2_num (ch, 16) < 0)
- {
- token = G_TOKEN_ERROR;
- value.v_error = G_ERR_DIGIT_RADIX;
- ch = 0;
- break;
- }
- }
- else if (config->scan_binary && (ch == 'b' || ch == 'B'))
- {
- token = G_TOKEN_BINARY;
- g_scanner_get_char (scanner, line_p, position_p);
- ch = g_scanner_get_char (scanner, line_p, position_p);
- if (ch == 0)
- {
- token = G_TOKEN_ERROR;
- value.v_error = G_ERR_UNEXP_EOF;
- (*position_p)++;
- break;
- }
- if (g_scanner_char_2_num (ch, 10) < 0)
- {
- token = G_TOKEN_ERROR;
- value.v_error = G_ERR_NON_DIGIT_IN_CONST;
- ch = 0;
- break;
- }
- }
- else
- ch = '0';
- /* fall through */
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- number_parsing:
- {
- gboolean in_number = TRUE;
- gchar *endptr;
-
- if (token == G_TOKEN_NONE)
- token = G_TOKEN_INT;
-
- gstring = g_string_new (dotted_float ? "0." : "");
- gstring = g_string_append_c (gstring, ch);
-
- do /* while (in_number) */
- {
- gboolean is_E;
-
- is_E = token == G_TOKEN_FLOAT && (ch == 'e' || ch == 'E');
-
- ch = g_scanner_peek_next_char (scanner);
-
- if (g_scanner_char_2_num (ch, 36) >= 0 ||
- (config->scan_float && ch == '.') ||
- (is_E && (ch == '+' || ch == '-')))
- {
- ch = g_scanner_get_char (scanner, line_p, position_p);
-
- switch (ch)
- {
- case '.':
- if (token != G_TOKEN_INT && token != G_TOKEN_OCTAL)
- {
- value.v_error = token == G_TOKEN_FLOAT ? G_ERR_FLOAT_MALFORMED : G_ERR_FLOAT_RADIX;
- token = G_TOKEN_ERROR;
- in_number = FALSE;
- }
- else
- {
- token = G_TOKEN_FLOAT;
- gstring = g_string_append_c (gstring, ch);
- }
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- gstring = g_string_append_c (gstring, ch);
- break;
-
- case '-':
- case '+':
- if (token != G_TOKEN_FLOAT)
- {
- token = G_TOKEN_ERROR;
- value.v_error = G_ERR_NON_DIGIT_IN_CONST;
- in_number = FALSE;
- }
- else
- gstring = g_string_append_c (gstring, ch);
- break;
-
- case 'e':
- case 'E':
- if ((token != G_TOKEN_HEX && !config->scan_float) ||
- (token != G_TOKEN_HEX &&
- token != G_TOKEN_OCTAL &&
- token != G_TOKEN_FLOAT &&
- token != G_TOKEN_INT))
- {
- token = G_TOKEN_ERROR;
- value.v_error = G_ERR_NON_DIGIT_IN_CONST;
- in_number = FALSE;
- }
- else
- {
- if (token != G_TOKEN_HEX)
- token = G_TOKEN_FLOAT;
- gstring = g_string_append_c (gstring, ch);
- }
- break;
-
- default:
- if (token != G_TOKEN_HEX)
- {
- token = G_TOKEN_ERROR;
- value.v_error = G_ERR_NON_DIGIT_IN_CONST;
- in_number = FALSE;
- }
- else
- gstring = g_string_append_c (gstring, ch);
- break;
- }
- }
- else
- in_number = FALSE;
- }
- while (in_number);
-
- endptr = NULL;
- if (token == G_TOKEN_FLOAT)
- value.v_float = g_strtod (gstring->str, &endptr);
- else
- {
- guint64 ui64 = 0;
- switch (token)
- {
- case G_TOKEN_BINARY:
- ui64 = g_ascii_strtoull (gstring->str, &endptr, 2);
- break;
- case G_TOKEN_OCTAL:
- ui64 = g_ascii_strtoull (gstring->str, &endptr, 8);
- break;
- case G_TOKEN_INT:
- ui64 = g_ascii_strtoull (gstring->str, &endptr, 10);
- break;
- case G_TOKEN_HEX:
- ui64 = g_ascii_strtoull (gstring->str, &endptr, 16);
- break;
- default: ;
- }
- if (scanner->config->store_int64)
- value.v_int64 = ui64;
- else
- value.v_int = ui64;
- }
- if (endptr && *endptr)
- {
- token = G_TOKEN_ERROR;
- if (*endptr == 'e' || *endptr == 'E')
- value.v_error = G_ERR_NON_DIGIT_IN_CONST;
- else
- value.v_error = G_ERR_DIGIT_RADIX;
- }
- g_string_free (gstring, TRUE);
- gstring = NULL;
- ch = 0;
- } /* number_parsing:... */
- break;
-
- default:
- default_case:
- {
- if (config->cpair_comment_single &&
- ch == config->cpair_comment_single[0])
- {
- token = G_TOKEN_COMMENT_SINGLE;
- in_comment_single = TRUE;
- gstring = g_string_new (NULL);
- ch = g_scanner_get_char (scanner, line_p, position_p);
- while (ch != 0)
- {
- if (ch == config->cpair_comment_single[1])
- {
- in_comment_single = FALSE;
- ch = 0;
- break;
- }
-
- gstring = g_string_append_c (gstring, ch);
- ch = g_scanner_get_char (scanner, line_p, position_p);
- }
- /* ignore a missing newline at EOF for single line comments */
- if (in_comment_single &&
- config->cpair_comment_single[1] == '\n')
- in_comment_single = FALSE;
- }
- else if (config->scan_identifier && ch &&
- strchr (config->cset_identifier_first, ch))
- {
- identifier_precedence:
-
- if (config->cset_identifier_nth && ch &&
- strchr (config->cset_identifier_nth,
- g_scanner_peek_next_char (scanner)))
- {
- token = G_TOKEN_IDENTIFIER;
- gstring = g_string_new (NULL);
- gstring = g_string_append_c (gstring, ch);
- do
- {
- ch = g_scanner_get_char (scanner, line_p, position_p);
- gstring = g_string_append_c (gstring, ch);
- ch = g_scanner_peek_next_char (scanner);
- }
- while (ch && strchr (config->cset_identifier_nth, ch));
- ch = 0;
- }
- else if (config->scan_identifier_1char)
- {
- token = G_TOKEN_IDENTIFIER;
- value.v_identifier = g_new0 (gchar, 2);
- value.v_identifier[0] = ch;
- ch = 0;
- }
- }
- if (ch)
- {
- if (config->char_2_token)
- token = ch;
- else
- {
- token = G_TOKEN_CHAR;
- value.v_char = ch;
- }
- ch = 0;
- }
- } /* default_case:... */
- break;
- }
- g_assert (ch == 0 && token != G_TOKEN_NONE); /* paranoid */
- }
- while (ch != 0);
-
- if (in_comment_multi || in_comment_single ||
- in_string_sq || in_string_dq)
- {
- token = G_TOKEN_ERROR;
- if (gstring)
- {
- g_string_free (gstring, TRUE);
- gstring = NULL;
- }
- (*position_p)++;
- if (in_comment_multi || in_comment_single)
- value.v_error = G_ERR_UNEXP_EOF_IN_COMMENT;
- else /* (in_string_sq || in_string_dq) */
- value.v_error = G_ERR_UNEXP_EOF_IN_STRING;
- }
-
- if (gstring)
- {
- value.v_string = g_string_free (gstring, FALSE);
- gstring = NULL;
- }
-
- if (token == G_TOKEN_IDENTIFIER)
- {
- if (config->scan_symbols)
- {
- GScannerKey *key;
- guint scope_id;
-
- scope_id = scanner->scope_id;
- key = g_scanner_lookup_internal (scanner, scope_id, value.v_identifier);
- if (!key && scope_id && scanner->config->scope_0_fallback)
- key = g_scanner_lookup_internal (scanner, 0, value.v_identifier);
-
- if (key)
- {
- g_free (value.v_identifier);
- token = G_TOKEN_SYMBOL;
- value.v_symbol = key->value;
- }
- }
-
- if (token == G_TOKEN_IDENTIFIER &&
- config->scan_identifier_NULL &&
- strlen (value.v_identifier) == 4)
- {
- gchar *null_upper = "NULL";
- gchar *null_lower = "null";
-
- if (scanner->config->case_sensitive)
- {
- if (value.v_identifier[0] == null_upper[0] &&
- value.v_identifier[1] == null_upper[1] &&
- value.v_identifier[2] == null_upper[2] &&
- value.v_identifier[3] == null_upper[3])
- token = G_TOKEN_IDENTIFIER_NULL;
- }
- else
- {
- if ((value.v_identifier[0] == null_upper[0] ||
- value.v_identifier[0] == null_lower[0]) &&
- (value.v_identifier[1] == null_upper[1] ||
- value.v_identifier[1] == null_lower[1]) &&
- (value.v_identifier[2] == null_upper[2] ||
- value.v_identifier[2] == null_lower[2]) &&
- (value.v_identifier[3] == null_upper[3] ||
- value.v_identifier[3] == null_lower[3]))
- token = G_TOKEN_IDENTIFIER_NULL;
- }
- }
- }
-
- *token_p = token;
- *value_p = value;
-}
-
-#define __G_SCANNER_C__
-#include "galiasdef.c"
diff --git a/glib/gsequence.c b/glib/gsequence.c
deleted file mode 100644
index fb64658b6..000000000
--- a/glib/gsequence.c
+++ /dev/null
@@ -1,1750 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
- * Soeren Sandmann (sandmann@daimi.au.dk)
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include "glib.h"
-#include "galias.h"
-
-typedef struct _GSequenceNode GSequenceNode;
-
-struct _GSequence
-{
- GSequenceNode * end_node;
- GDestroyNotify data_destroy_notify;
- gboolean access_prohibited;
-
- /* The 'real_sequence' is used when temporary sequences are created
- * to hold nodes that are being rearranged. The 'real_sequence' of such
- * a temporary sequence points to the sequence that is actually being
- * manipulated. The only reason we need this is so that when the
- * sort/sort_changed/search_iter() functions call out to the application
- * g_sequence_iter_get_sequence() will return the correct sequence.
- */
- GSequence * real_sequence;
-};
-
-struct _GSequenceNode
-{
- gint n_nodes;
- GSequenceNode * parent;
- GSequenceNode * left;
- GSequenceNode * right;
- gpointer data; /* For the end node, this field points
- * to the sequence
- */
-};
-
-/*
- * Declaration of GSequenceNode methods
- */
-static GSequenceNode *node_new (gpointer data);
-static GSequenceNode *node_get_first (GSequenceNode *node);
-static GSequenceNode *node_get_last (GSequenceNode *node);
-static GSequenceNode *node_get_prev (GSequenceNode *node);
-static GSequenceNode *node_get_next (GSequenceNode *node);
-static gint node_get_pos (GSequenceNode *node);
-static GSequenceNode *node_get_by_pos (GSequenceNode *node,
- gint pos);
-static GSequenceNode *node_find_closest (GSequenceNode *haystack,
- GSequenceNode *needle,
- GSequenceNode *end,
- GSequenceIterCompareFunc cmp,
- gpointer user_data);
-static gint node_get_length (GSequenceNode *node);
-static void node_free (GSequenceNode *node,
- GSequence *seq);
-static void node_cut (GSequenceNode *split);
-static void node_insert_before (GSequenceNode *node,
- GSequenceNode *new);
-static void node_unlink (GSequenceNode *node);
-static void node_join (GSequenceNode *left,
- GSequenceNode *right);
-static void node_insert_sorted (GSequenceNode *node,
- GSequenceNode *new,
- GSequenceNode *end,
- GSequenceIterCompareFunc cmp_func,
- gpointer cmp_data);
-
-
-/*
- * Various helper functions
- */
-static void
-check_seq_access (GSequence *seq)
-{
- if (G_UNLIKELY (seq->access_prohibited))
- {
- g_warning ("Accessing a sequence while it is "
- "being sorted or searched is not allowed");
- }
-}
-
-static GSequence *
-get_sequence (GSequenceNode *node)
-{
- return (GSequence *)node_get_last (node)->data;
-}
-
-static void
-check_iter_access (GSequenceIter *iter)
-{
- check_seq_access (get_sequence (iter));
-}
-
-static gboolean
-is_end (GSequenceIter *iter)
-{
- GSequence *seq;
-
- if (iter->right)
- return FALSE;
-
- if (!iter->parent)
- return TRUE;
-
- if (iter->parent->right != iter)
- return FALSE;
-
- seq = get_sequence (iter);
-
- return seq->end_node == iter;
-}
-
-typedef struct
-{
- GCompareDataFunc cmp_func;
- gpointer cmp_data;
- GSequenceNode *end_node;
-} SortInfo;
-
-/* This function compares two iters using a normal compare
- * function and user_data passed in in a SortInfo struct
- */
-static gint
-iter_compare (GSequenceIter *node1,
- GSequenceIter *node2,
- gpointer data)
-{
- const SortInfo *info = data;
- gint retval;
-
- if (node1 == info->end_node)
- return 1;
-
- if (node2 == info->end_node)
- return -1;
-
- retval = info->cmp_func (node1->data, node2->data, info->cmp_data);
-
- return retval;
-}
-
-/*
- * Public API
- */
-
-/**
- * g_sequence_new:
- * @data_destroy: a #GDestroyNotify function, or %NULL
- *
- * Creates a new GSequence. The @data_destroy function, if non-%NULL will
- * be called on all items when the sequence is destroyed and on items that
- * are removed from the sequence.
- *
- * Return value: a new #GSequence
- *
- * Since: 2.14
- **/
-GSequence *
-g_sequence_new (GDestroyNotify data_destroy)
-{
- GSequence *seq = g_new (GSequence, 1);
- seq->data_destroy_notify = data_destroy;
-
- seq->end_node = node_new (seq);
-
- seq->access_prohibited = FALSE;
-
- seq->real_sequence = seq;
-
- return seq;
-}
-
-/**
- * g_sequence_free:
- * @seq: a #GSequence
- *
- * Frees the memory allocated for @seq. If @seq has a data destroy
- * function associated with it, that function is called on all items in
- * @seq.
- *
- * Since: 2.14
- **/
-void
-g_sequence_free (GSequence *seq)
-{
- g_return_if_fail (seq != NULL);
-
- check_seq_access (seq);
-
- node_free (seq->end_node, seq);
-
- g_free (seq);
-}
-
-/**
- * g_sequence_foreach_range:
- * @begin: a #GSequenceIter
- * @end: a #GSequenceIter
- * @func: a #GFunc
- * @user_data: user data passed to @func
- *
- * Calls @func for each item in the range (@begin, @end) passing
- * @user_data to the function.
- *
- * Since: 2.14
- **/
-void
-g_sequence_foreach_range (GSequenceIter *begin,
- GSequenceIter *end,
- GFunc func,
- gpointer user_data)
-{
- GSequence *seq;
- GSequenceIter *iter;
-
- g_return_if_fail (func != NULL);
- g_return_if_fail (begin != NULL);
- g_return_if_fail (end != NULL);
-
- seq = get_sequence (begin);
-
- seq->access_prohibited = TRUE;
-
- iter = begin;
- while (iter != end)
- {
- GSequenceIter *next = node_get_next (iter);
-
- func (iter->data, user_data);
-
- iter = next;
- }
-
- seq->access_prohibited = FALSE;
-}
-
-/**
- * g_sequence_foreach:
- * @seq: a #GSequence
- * @func: the function to call for each item in @seq
- * @user_data: user data passed to @func
- *
- * Calls @func for each item in the sequence passing @user_data
- * to the function.
- *
- * Since: 2.14
- **/
-void
-g_sequence_foreach (GSequence *seq,
- GFunc func,
- gpointer user_data)
-{
- GSequenceIter *begin, *end;
-
- check_seq_access (seq);
-
- begin = g_sequence_get_begin_iter (seq);
- end = g_sequence_get_end_iter (seq);
-
- g_sequence_foreach_range (begin, end, func, user_data);
-}
-
-/**
- * g_sequence_range_get_midpoint:
- * @begin: a #GSequenceIter
- * @end: a #GSequenceIter
- *
- * Finds an iterator somewhere in the range (@begin, @end). This
- * iterator will be close to the middle of the range, but is not
- * guaranteed to be <emphasis>exactly</emphasis> in the middle.
- *
- * The @begin and @end iterators must both point to the same sequence and
- * @begin must come before or be equal to @end in the sequence.
- *
- * Return value: A #GSequenceIter pointing somewhere in the
- * (@begin, @end) range.
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_range_get_midpoint (GSequenceIter *begin,
- GSequenceIter *end)
-{
- int begin_pos, end_pos, mid_pos;
-
- g_return_val_if_fail (begin != NULL, NULL);
- g_return_val_if_fail (end != NULL, NULL);
- g_return_val_if_fail (get_sequence (begin) == get_sequence (end), NULL);
-
- begin_pos = node_get_pos (begin);
- end_pos = node_get_pos (end);
-
- g_return_val_if_fail (end_pos >= begin_pos, NULL);
-
- mid_pos = begin_pos + (end_pos - begin_pos) / 2;
-
- return node_get_by_pos (begin, mid_pos);
-}
-
-/**
- * g_sequence_iter_compare:
- * @a: a #GSequenceIter
- * @b: a #GSequenceIter
- *
- * Returns a negative number if @a comes before @b, 0 if they are equal,
- * and a positive number if @a comes after @b.
- *
- * The @a and @b iterators must point into the same sequence.
- *
- * Return value: A negative number if @a comes before @b, 0 if they are
- * equal, and a positive number if @a comes after @b.
- *
- * Since: 2.14
- **/
-gint
-g_sequence_iter_compare (GSequenceIter *a,
- GSequenceIter *b)
-{
- gint a_pos, b_pos;
-
- g_return_val_if_fail (a != NULL, 0);
- g_return_val_if_fail (b != NULL, 0);
- g_return_val_if_fail (get_sequence (a) == get_sequence (b), 0);
-
- check_iter_access (a);
- check_iter_access (b);
-
- a_pos = node_get_pos (a);
- b_pos = node_get_pos (b);
-
- if (a_pos == b_pos)
- return 0;
- else if (a_pos > b_pos)
- return 1;
- else
- return -1;
-}
-
-/**
- * g_sequence_append:
- * @seq: a #GSequencePointer
- * @data: the data for the new item
- *
- * Adds a new item to the end of @seq.
- *
- * Return value: an iterator pointing to the new item
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_append (GSequence *seq,
- gpointer data)
-{
- GSequenceNode *node;
-
- g_return_val_if_fail (seq != NULL, NULL);
-
- check_seq_access (seq);
-
- node = node_new (data);
- node_insert_before (seq->end_node, node);
-
- return node;
-}
-
-/**
- * g_sequence_prepend:
- * @seq: a #GSequence
- * @data: the data for the new item
- *
- * Adds a new item to the front of @seq
- *
- * Return value: an iterator pointing to the new item
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_prepend (GSequence *seq,
- gpointer data)
-{
- GSequenceNode *node, *first;
-
- g_return_val_if_fail (seq != NULL, NULL);
-
- check_seq_access (seq);
-
- node = node_new (data);
- first = node_get_first (seq->end_node);
-
- node_insert_before (first, node);
-
- return node;
-}
-
-/**
- * g_sequence_insert_before:
- * @iter: a #GSequenceIter
- * @data: the data for the new item
- *
- * Inserts a new item just before the item pointed to by @iter.
- *
- * Return value: an iterator pointing to the new item
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_insert_before (GSequenceIter *iter,
- gpointer data)
-{
- GSequenceNode *node;
-
- g_return_val_if_fail (iter != NULL, NULL);
-
- check_iter_access (iter);
-
- node = node_new (data);
-
- node_insert_before (iter, node);
-
- return node;
-}
-
-/**
- * g_sequence_remove:
- * @iter: a #GSequenceIter
- *
- * Removes the item pointed to by @iter. It is an error to pass the
- * end iterator to this function.
- *
- * If the sequnce has a data destroy function associated with it, this
- * function is called on the data for the removed item.
- *
- * Since: 2.14
- **/
-void
-g_sequence_remove (GSequenceIter *iter)
-{
- GSequence *seq;
-
- g_return_if_fail (iter != NULL);
- g_return_if_fail (!is_end (iter));
-
- check_iter_access (iter);
-
- seq = get_sequence (iter);
-
- node_unlink (iter);
- node_free (iter, seq);
-}
-
-/**
- * g_sequence_remove_range:
- * @begin: a #GSequenceIter
- * @end: a #GSequenceIter
- *
- * Removes all items in the (@begin, @end) range.
- *
- * If the sequence has a data destroy function associated with it, this
- * function is called on the data for the removed items.
- *
- * Since: 2.14
- **/
-void
-g_sequence_remove_range (GSequenceIter *begin,
- GSequenceIter *end)
-{
- g_return_if_fail (get_sequence (begin) == get_sequence (end));
-
- check_iter_access (begin);
- check_iter_access (end);
-
- g_sequence_move_range (NULL, begin, end);
-}
-
-/**
- * g_sequence_move_range:
- * @dest: a #GSequenceIter
- * @begin: a #GSequenceIter
- * @end: a #GSequenceIter
- *
- * Inserts the (@begin, @end) range at the destination pointed to by ptr.
- * The @begin and @end iters must point into the same sequence. It is
- * allowed for @dest to point to a different sequence than the one pointed
- * into by @begin and @end.
- *
- * If @dest is NULL, the range indicated by @begin and @end is
- * removed from the sequence. If @dest iter points to a place within
- * the (@begin, @end) range, the range does not move.
- *
- * Since: 2.14
- **/
-void
-g_sequence_move_range (GSequenceIter *dest,
- GSequenceIter *begin,
- GSequenceIter *end)
-{
- GSequence *src_seq;
- GSequenceNode *first;
-
- g_return_if_fail (begin != NULL);
- g_return_if_fail (end != NULL);
-
- check_iter_access (begin);
- check_iter_access (end);
- if (dest)
- check_iter_access (dest);
-
- src_seq = get_sequence (begin);
-
- g_return_if_fail (src_seq == get_sequence (end));
-
- /* Dest points to begin or end? */
- if (dest == begin || dest == end)
- return;
-
- /* begin comes after end? */
- if (g_sequence_iter_compare (begin, end) >= 0)
- return;
-
- /* dest points somewhere in the (begin, end) range? */
- if (dest && get_sequence (dest) == src_seq &&
- g_sequence_iter_compare (dest, begin) > 0 &&
- g_sequence_iter_compare (dest, end) < 0)
- {
- return;
- }
-
- src_seq = get_sequence (begin);
-
- first = node_get_first (begin);
-
- node_cut (begin);
-
- node_cut (end);
-
- if (first != begin)
- node_join (first, end);
-
- if (dest)
- {
- first = node_get_first (dest);
-
- node_cut (dest);
-
- node_join (begin, dest);
-
- if (dest != first)
- node_join (first, begin);
- }
- else
- {
- node_free (begin, src_seq);
- }
-}
-
-/**
- * g_sequence_sort:
- * @seq: a #GSequence
- * @cmp_func: the #GCompareDataFunc used to sort @seq. This function is
- * passed two items of @seq and should return 0 if they are equal,
- * a negative value fi the first comes before the second, and a
- * positive value if the second comes before the first.
- * @cmp_data: user data passed to @cmp_func
- *
- * Sorts @seq using @cmp_func.
- *
- * Since: 2.14
- **/
-void
-g_sequence_sort (GSequence *seq,
- GCompareDataFunc cmp_func,
- gpointer cmp_data)
-{
- SortInfo info;
-
- info.cmp_func = cmp_func;
- info.cmp_data = cmp_data;
- info.end_node = seq->end_node;
-
- check_seq_access (seq);
-
- g_sequence_sort_iter (seq, iter_compare, &info);
-}
-
-/**
- * g_sequence_insert_sorted:
- * @seq: a #GSequence
- * @data: the data to insert
- * @cmp_func: the #GCompareDataFunc used to compare items in the sequence. It
- * is called with two items of the @seq and @user_data. It should
- * return 0 if the items are equal, a negative value if the first
- * item comes before the second, and a positive value if the second
- * item comes before the first.
- * @cmp_data: user data passed to @cmp_func.
- *
- * Inserts @data into @sequence using @func to determine the new position.
- * The sequence must already be sorted according to @cmp_func; otherwise the
- * new position of @data is undefined.
- *
- * Return value: a #GSequenceIter pointing to the new item.
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_insert_sorted (GSequence *seq,
- gpointer data,
- GCompareDataFunc cmp_func,
- gpointer cmp_data)
-{
- SortInfo info;
-
- g_return_val_if_fail (seq != NULL, NULL);
- g_return_val_if_fail (cmp_func != NULL, NULL);
-
- info.cmp_func = cmp_func;
- info.cmp_data = cmp_data;
- info.end_node = seq->end_node;
- check_seq_access (seq);
-
- return g_sequence_insert_sorted_iter (seq, data, iter_compare, &info);
-}
-
-/**
- * g_sequence_sort_changed:
- * @iter: A #GSequenceIter
- * @cmp_func: the #GCompareDataFunc used to compare items in the sequence. It
- * is called with two items of the @seq and @user_data. It should
- * return 0 if the items are equal, a negative value if the first
- * item comes before the second, and a positive value if the second
- * item comes before the first.
- * @cmp_data: user data passed to @cmp_func.
- *
- * Moves the data pointed to a new position as indicated by @cmp_func. This
- * function should be called for items in a sequence already sorted according
- * to @cmp_func whenever some aspect of an item changes so that @cmp_func
- * may return different values for that item.
- *
- * Since: 2.14
- **/
-void
-g_sequence_sort_changed (GSequenceIter *iter,
- GCompareDataFunc cmp_func,
- gpointer cmp_data)
-{
- SortInfo info;
-
- g_return_if_fail (!is_end (iter));
-
- info.cmp_func = cmp_func;
- info.cmp_data = cmp_data;
- info.end_node = get_sequence (iter)->end_node;
- check_iter_access (iter);
-
- g_sequence_sort_changed_iter (iter, iter_compare, &info);
-}
-
-/**
- * g_sequence_search:
- * @seq: a #GSequence
- * @data: data for the new item
- * @cmp_func: the #GCompareDataFunc used to compare items in the sequence. It
- * is called with two items of the @seq and @user_data. It should
- * return 0 if the items are equal, a negative value if the first
- * item comes before the second, and a positive value if the second
- * item comes before the first.
- * @cmp_data: user data passed to @cmp_func.
- *
- * Returns an iterator pointing to the position where @data would
- * be inserted according to @cmp_func and @cmp_data.
- *
- * Return value: an #GSequenceIter pointing to the position where @data
- * would have been inserted according to @cmp_func and @cmp_data.
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_search (GSequence *seq,
- gpointer data,
- GCompareDataFunc cmp_func,
- gpointer cmp_data)
-{
- SortInfo info;
-
- g_return_val_if_fail (seq != NULL, NULL);
-
- info.cmp_func = cmp_func;
- info.cmp_data = cmp_data;
- info.end_node = seq->end_node;
- check_seq_access (seq);
-
- return g_sequence_search_iter (seq, data, iter_compare, &info);
-}
-
-/**
- * g_sequence_sort_iter:
- * @seq: a #GSequence
- * @cmp_func: the #GSequenceItercompare used to compare iterators in the
- * sequence. It is called with two iterators pointing into @seq. It should
- * return 0 if the iterators are equal, a negative value if the first
- * iterator comes before the second, and a positive value if the second
- * iterator comes before the first.
- * @cmp_data: user data passed to @cmp_func
- *
- * Like g_sequence_sort(), but uses a #GSequenceIterCompareFunc instead
- * of a GCompareDataFunc as the compare function
- *
- * Since: 2.14
- **/
-void
-g_sequence_sort_iter (GSequence *seq,
- GSequenceIterCompareFunc cmp_func,
- gpointer cmp_data)
-{
- GSequence *tmp;
- GSequenceNode *begin, *end;
-
- g_return_if_fail (seq != NULL);
- g_return_if_fail (cmp_func != NULL);
-
- check_seq_access (seq);
-
- begin = g_sequence_get_begin_iter (seq);
- end = g_sequence_get_end_iter (seq);
-
- tmp = g_sequence_new (NULL);
- tmp->real_sequence = seq;
-
- g_sequence_move_range (g_sequence_get_begin_iter (tmp), begin, end);
-
- seq->access_prohibited = TRUE;
- tmp->access_prohibited = TRUE;
-
- while (g_sequence_get_length (tmp) > 0)
- {
- GSequenceNode *node = g_sequence_get_begin_iter (tmp);
-
- node_insert_sorted (seq->end_node, node, seq->end_node,
- cmp_func, cmp_data);
- }
-
- tmp->access_prohibited = FALSE;
- seq->access_prohibited = FALSE;
-
- g_sequence_free (tmp);
-}
-
-/**
- * g_sequence_sort_changed_iter:
- * @iter: a #GSequenceIter
- * @iter_cmp: the #GSequenceItercompare used to compare iterators in the
- * sequence. It is called with two iterators pointing into @seq. It should
- * return 0 if the iterators are equal, a negative value if the first
- * iterator comes before the second, and a positive value if the second
- * iterator comes before the first.
- * @cmp_data: user data passed to @cmp_func
- *
- * Like g_sequence_sort_changed(), but uses
- * a #GSequenceIterCompareFunc instead of a #GCompareDataFunc as
- * the compare function.
- *
- * Since: 2.14
- **/
-void
-g_sequence_sort_changed_iter (GSequenceIter *iter,
- GSequenceIterCompareFunc iter_cmp,
- gpointer cmp_data)
-{
- GSequence *seq, *tmp_seq;
- GSequenceIter *next, *prev;
-
- g_return_if_fail (iter != NULL);
- g_return_if_fail (!is_end (iter));
- g_return_if_fail (iter_cmp != NULL);
- check_iter_access (iter);
-
- /* If one of the neighbours is equal to iter, then
- * don't move it. This ensures that sort_changed() is
- * a stable operation.
- */
-
- next = node_get_next (iter);
- prev = node_get_prev (iter);
-
- if (prev != iter && iter_cmp (prev, iter, cmp_data) == 0)
- return;
-
- if (!is_end (next) && iter_cmp (next, iter, cmp_data) == 0)
- return;
-
- seq = get_sequence (iter);
-
- seq->access_prohibited = TRUE;
-
- tmp_seq = g_sequence_new (NULL);
- tmp_seq->real_sequence = seq;
-
- node_unlink (iter);
- node_insert_before (tmp_seq->end_node, iter);
-
- node_insert_sorted (seq->end_node, iter, seq->end_node,
- iter_cmp, cmp_data);
-
- g_sequence_free (tmp_seq);
-
- seq->access_prohibited = FALSE;
-}
-
-/**
- * g_sequence_insert_sorted_iter:
- * @seq: a #GSequence
- * @data: data for the new item
- * @iter_cmp: the #GSequenceItercompare used to compare iterators in the
- * sequence. It is called with two iterators pointing into @seq. It should
- * return 0 if the iterators are equal, a negative value if the first
- * iterator comes before the second, and a positive value if the second
- * iterator comes before the first.
- * @cmp_data: user data passed to @cmp_func
- *
- * Like g_sequence_insert_sorted(), but uses
- * a #GSequenceIterCompareFunc instead of a #GCompareDataFunc as
- * the compare function.
- *
- * Return value: a #GSequenceIter pointing to the new item
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_insert_sorted_iter (GSequence *seq,
- gpointer data,
- GSequenceIterCompareFunc iter_cmp,
- gpointer cmp_data)
-{
- GSequenceNode *new_node;
- GSequence *tmp_seq;
-
- g_return_val_if_fail (seq != NULL, NULL);
- g_return_val_if_fail (iter_cmp != NULL, NULL);
-
- check_seq_access (seq);
-
- seq->access_prohibited = TRUE;
-
- /* Create a new temporary sequence and put the new node into
- * that. The reason for this is that the user compare function
- * will be called with the new node, and if it dereferences,
- * "is_end" will be called on it. But that will crash if the
- * node is not actually in a sequence.
- *
- * node_insert_sorted() makes sure the node is unlinked before
- * it is inserted.
- *
- * The reason we need the "iter" versions at all is that that
- * is the only kind of compare functions GtkTreeView can use.
- */
- tmp_seq = g_sequence_new (NULL);
- tmp_seq->real_sequence = seq;
-
- new_node = g_sequence_append (tmp_seq, data);
-
- node_insert_sorted (seq->end_node, new_node,
- seq->end_node, iter_cmp, cmp_data);
-
- g_sequence_free (tmp_seq);
-
- seq->access_prohibited = FALSE;
-
- return new_node;
-}
-
-/**
- * g_sequence_search_iter:
- * @seq: a #GSequence
- * @data: data for the new item
- * @iter_cmp: the #GSequenceIterCompare function used to compare iterators
- * in the sequence. It is called with two iterators pointing into @seq.
- * It should return 0 if the iterators are equal, a negative value if the
- * first iterator comes before the second, and a positive value if the
- * second iterator comes before the first.
- * @cmp_data: user data passed to @iter_cmp
- *
- * Like g_sequence_search(), but uses
- * a #GSequenceIterCompareFunc instead of a #GCompareDataFunc as
- * the compare function.
- *
- * Return value: a #GSequenceIter pointing to the position in @seq
- * where @data would have been inserted according to @iter_cmp and @cmp_data.
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_search_iter (GSequence *seq,
- gpointer data,
- GSequenceIterCompareFunc iter_cmp,
- gpointer cmp_data)
-{
- GSequenceNode *node;
- GSequenceNode *dummy;
- GSequence *tmp_seq;
-
- g_return_val_if_fail (seq != NULL, NULL);
-
- check_seq_access (seq);
-
- seq->access_prohibited = TRUE;
-
- tmp_seq = g_sequence_new (NULL);
- tmp_seq->real_sequence = seq;
-
- dummy = g_sequence_append (tmp_seq, data);
-
- node = node_find_closest (seq->end_node, dummy,
- seq->end_node, iter_cmp, cmp_data);
-
- g_sequence_free (tmp_seq);
-
- seq->access_prohibited = FALSE;
-
- return node;
-}
-
-/**
- * g_sequence_iter_get_sequence:
- * @iter: a #GSequenceIter
- *
- * Returns the #GSequence that @iter points into.
- *
- * Return value: the #GSequence that @iter points into.
- *
- * Since: 2.14
- **/
-GSequence *
-g_sequence_iter_get_sequence (GSequenceIter *iter)
-{
- GSequence *seq;
-
- g_return_val_if_fail (iter != NULL, NULL);
-
- seq = get_sequence (iter);
-
- /* For temporary sequences, this points to the sequence that
- * is actually being manipulated
- */
- return seq->real_sequence;
-}
-
-/**
- * g_sequence_get:
- * @iter: a #GSequenceIter
- *
- * Returns the data that @iter points to.
- *
- * Return value: the data that @iter points to
- *
- * Since: 2.14
- **/
-gpointer
-g_sequence_get (GSequenceIter *iter)
-{
- g_return_val_if_fail (iter != NULL, NULL);
- g_return_val_if_fail (!is_end (iter), NULL);
-
- return iter->data;
-}
-
-/**
- * g_sequence_set:
- * @iter: a #GSequenceIter
- * @data: new data for the item
- *
- * Changes the data for the item pointed to by @iter to be @data. If
- * the sequence has a data destroy function associated with it, that
- * function is called on the existing data that @iter pointed to.
- *
- * Since: 2.14
- **/
-void
-g_sequence_set (GSequenceIter *iter,
- gpointer data)
-{
- GSequence *seq;
-
- g_return_if_fail (iter != NULL);
- g_return_if_fail (!is_end (iter));
-
- seq = get_sequence (iter);
-
- /* If @data is identical to iter->data, it is destroyed
- * here. This will work right in case of ref-counted objects. Also
- * it is similar to what ghashtables do.
- *
- * For non-refcounted data it's a little less convenient, but
- * code relying on self-setting not destroying would be
- * pretty dubious anyway ...
- */
-
- if (seq->data_destroy_notify)
- seq->data_destroy_notify (iter->data);
-
- iter->data = data;
-}
-
-/**
- * g_sequence_get_length:
- * @seq: a #GSequence
- *
- * Returns the length of @seq
- *
- * Return value: the length of @seq
- *
- * Since: 2.14
- **/
-gint
-g_sequence_get_length (GSequence *seq)
-{
- return node_get_length (seq->end_node) - 1;
-}
-
-/**
- * g_sequence_get_end_iter:
- * @seq: a #GSequence
- *
- * Returns the end iterator for @seg
- *
- * Return value: the end iterator for @seq
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_get_end_iter (GSequence *seq)
-{
- g_return_val_if_fail (seq != NULL, NULL);
-
- return seq->end_node;
-}
-
-/**
- * g_sequence_get_begin_iter:
- * @seq: a #GSequence
- *
- * Returns the begin iterator for @seq.
- *
- * Return value: the begin iterator for @seq.
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_get_begin_iter (GSequence *seq)
-{
- g_return_val_if_fail (seq != NULL, NULL);
-
- return node_get_first (seq->end_node);
-}
-
-static int
-clamp_position (GSequence *seq,
- int pos)
-{
- gint len = g_sequence_get_length (seq);
-
- if (pos > len || pos < 0)
- pos = len;
-
- return pos;
-}
-
-/*
- * if pos > number of items or -1, will return end pointer
- */
-/**
- * g_sequence_get_iter_at_pos:
- * @seq: a #GSequence
- * @pos: a position in @seq, or -1 for the end.
- *
- * Returns the iterator at position @pos. If @pos is negative or larger
- * than the number of items in @seq, the end iterator is returned.
- *
- * Return value: The #GSequenceIter at position @pos
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_get_iter_at_pos (GSequence *seq,
- gint pos)
-{
- g_return_val_if_fail (seq != NULL, NULL);
-
- pos = clamp_position (seq, pos);
-
- return node_get_by_pos (seq->end_node, pos);
-}
-
-/**
- * g_sequence_move:
- * @src: a #GSequenceIter pointing to the item to move
- * @dest: a #GSequenceIter pointing to the position to which
- * the item is moved.
- *
- * Moves the item pointed to by @src to the position indicated by @dest.
- * After calling this function @dest will point to the position immediately
- * after @src. It is allowed for @src and @dest to point into different
- * sequences.
- *
- * Since: 2.14
- **/
-void
-g_sequence_move (GSequenceIter *src,
- GSequenceIter *dest)
-{
- g_return_if_fail (src != NULL);
- g_return_if_fail (dest != NULL);
- g_return_if_fail (!is_end (src));
-
- if (src == dest)
- return;
-
- node_unlink (src);
- node_insert_before (dest, src);
-}
-
-/* GSequenceIter */
-
-/**
- * g_sequence_iter_is_end:
- * @iter: a #GSequenceIter
- *
- * Returns whether @iter is the end iterator
- *
- * Return value: Whether @iter is the end iterator.
- *
- * Since: 2.14
- **/
-gboolean
-g_sequence_iter_is_end (GSequenceIter *iter)
-{
- g_return_val_if_fail (iter != NULL, FALSE);
-
- return is_end (iter);
-}
-
-/**
- * g_sequence_iter_is_begin:
- * @iter: a #GSequenceIter
- *
- * Returns whether @iter is the begin iterator
- *
- * Return value: whether @iter is the begin iterator
- *
- * Since: 2.14
- **/
-gboolean
-g_sequence_iter_is_begin (GSequenceIter *iter)
-{
- g_return_val_if_fail (iter != NULL, FALSE);
-
- return (node_get_prev (iter) == iter);
-}
-
-/**
- * g_sequence_iter_get_position:
- * @iter: a #GSequenceIter
- *
- * Returns the position of @iter
- *
- * Return value: the position of @iter
- *
- * Since: 2.14
- **/
-gint
-g_sequence_iter_get_position (GSequenceIter *iter)
-{
- g_return_val_if_fail (iter != NULL, -1);
-
- return node_get_pos (iter);
-}
-
-/**
- * g_sequence_iter_next:
- * @iter: a #GSequenceIter
- *
- * Returns an iterator pointing to the next position after @iter. If
- * @iter is the end iterator, the end iterator is returned.
- *
- * Return value: a #GSequenceIter pointing to the next position after @iter.
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_iter_next (GSequenceIter *iter)
-{
- g_return_val_if_fail (iter != NULL, NULL);
-
- return node_get_next (iter);
-}
-
-/**
- * g_sequence_iter_prev:
- * @iter: a #GSequenceIter
- *
- * Returns an iterator pointing to the previous position before @iter. If
- * @iter is the begin iterator, the begin iterator is returned.
- *
- * Return value: a #GSequenceIter pointing to the previous position before
- * @iter.
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_iter_prev (GSequenceIter *iter)
-{
- g_return_val_if_fail (iter != NULL, NULL);
-
- return node_get_prev (iter);
-}
-
-/**
- * g_sequence_iter_move:
- * @iter: a #GSequenceIter
- * @delta: A positive or negative number indicating how many positions away
- * from @iter the returned #GSequenceIter will be.
- *
- * Returns the #GSequenceIter which is @delta positions away from @iter.
- * If @iter is closer than -@delta positions to the beginning of the sequence,
- * the begin iterator is returned. If @iter is closer than @delta positions
- * to the end of the sequence, the end iterator is returned.
- *
- * Return value: a #GSequenceIter which is @delta positions away from @iter.
- *
- * Since: 2.14
- **/
-GSequenceIter *
-g_sequence_iter_move (GSequenceIter *iter,
- gint delta)
-{
- gint new_pos;
-
- g_return_val_if_fail (iter != NULL, NULL);
-
- new_pos = node_get_pos (iter) + delta;
-
- new_pos = clamp_position (get_sequence (iter), new_pos);
-
- return node_get_by_pos (iter, new_pos);
-}
-
-/**
- * g_sequence_swap:
- * @a: a #GSequenceIter
- * @b: a #GSequenceIter
- *
- * Swaps the items pointed to by @a and @b. It is allowed for @a and @b
- * to point into difference sequences.
- *
- * Since: 2.14
- **/
-void
-g_sequence_swap (GSequenceIter *a,
- GSequenceIter *b)
-{
- GSequenceNode *leftmost, *rightmost, *rightmost_next;
- int a_pos, b_pos;
-
- g_return_if_fail (!g_sequence_iter_is_end (a));
- g_return_if_fail (!g_sequence_iter_is_end (b));
-
- if (a == b)
- return;
-
- a_pos = g_sequence_iter_get_position (a);
- b_pos = g_sequence_iter_get_position (b);
-
- if (a_pos > b_pos)
- {
- leftmost = b;
- rightmost = a;
- }
- else
- {
- leftmost = a;
- rightmost = b;
- }
-
- rightmost_next = node_get_next (rightmost);
-
- /* The situation is now like this:
- *
- * ..., leftmost, ......., rightmost, rightmost_next, ...
- *
- */
- g_sequence_move (rightmost, leftmost);
- g_sequence_move (leftmost, rightmost_next);
-}
-
-/*
- * Implementation of a treap
- *
- *
- */
-static guint
-get_priority (GSequenceNode *node)
-{
- guint key = GPOINTER_TO_UINT (node);
-
- /* This hash function is based on one found on Thomas Wang's
- * web page at
- *
- * http://www.concentric.net/~Ttwang/tech/inthash.htm
- *
- */
- key = (key << 15) - key - 1;
- key = key ^ (key >> 12);
- key = key + (key << 2);
- key = key ^ (key >> 4);
- key = key + (key << 3) + (key << 11);
- key = key ^ (key >> 16);
-
- /* We rely on 0 being less than all other priorities */
- return key? key : 1;
-}
-
-static GSequenceNode *
-find_root (GSequenceNode *node)
-{
- while (node->parent)
- node = node->parent;
-
- return node;
-}
-
-static GSequenceNode *
-node_new (gpointer data)
-{
- GSequenceNode *node = g_slice_new0 (GSequenceNode);
-
- node->n_nodes = 1;
- node->data = data;
- node->left = NULL;
- node->right = NULL;
- node->parent = NULL;
-
- return node;
-}
-
-static GSequenceNode *
-node_get_first (GSequenceNode *node)
-{
- node = find_root (node);
-
- while (node->left)
- node = node->left;
-
- return node;
-}
-
-static GSequenceNode *
-node_get_last (GSequenceNode *node)
-{
- node = find_root (node);
-
- while (node->right)
- node = node->right;
-
- return node;
-}
-
-#define NODE_LEFT_CHILD(n) (((n)->parent) && ((n)->parent->left) == (n))
-#define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
-
-static GSequenceNode *
-node_get_next (GSequenceNode *node)
-{
- GSequenceNode *n = node;
-
- if (n->right)
- {
- n = n->right;
- while (n->left)
- n = n->left;
- }
- else
- {
- while (NODE_RIGHT_CHILD (n))
- n = n->parent;
-
- if (n->parent)
- n = n->parent;
- else
- n = node;
- }
-
- return n;
-}
-
-static GSequenceNode *
-node_get_prev (GSequenceNode *node)
-{
- GSequenceNode *n = node;
-
- if (n->left)
- {
- n = n->left;
- while (n->right)
- n = n->right;
- }
- else
- {
- while (NODE_LEFT_CHILD (n))
- n = n->parent;
-
- if (n->parent)
- n = n->parent;
- else
- n = node;
- }
-
- return n;
-}
-
-#define N_NODES(n) ((n)? (n)->n_nodes : 0)
-
-static gint
-node_get_pos (GSequenceNode *node)
-{
- int n_smaller = 0;
-
- if (node->left)
- n_smaller = node->left->n_nodes;
-
- while (node)
- {
- if (NODE_RIGHT_CHILD (node))
- n_smaller += N_NODES (node->parent->left) + 1;
-
- node = node->parent;
- }
-
- return n_smaller;
-}
-
-static GSequenceNode *
-node_get_by_pos (GSequenceNode *node,
- gint pos)
-{
- int i;
-
- node = find_root (node);
-
- while ((i = N_NODES (node->left)) != pos)
- {
- if (i < pos)
- {
- node = node->right;
- pos -= (i + 1);
- }
- else
- {
- node = node->left;
- }
- }
-
- return node;
-}
-
-static GSequenceNode *
-node_find_closest (GSequenceNode *haystack,
- GSequenceNode *needle,
- GSequenceNode *end,
- GSequenceIterCompareFunc iter_cmp,
- gpointer cmp_data)
-{
- GSequenceNode *best;
- gint c;
-
- haystack = find_root (haystack);
-
- do
- {
- best = haystack;
-
- /* iter_cmp can't be passed the end node, since the function may
- * be user-supplied
- */
- if (haystack == end)
- c = 1;
- else
- c = iter_cmp (haystack, needle, cmp_data);
-
- /* In the following we don't break even if c == 0. Instaed we go on
- * searching along the 'bigger' nodes, so that we find the last one
- * that is equal to the needle.
- */
- if (c > 0)
- haystack = haystack->left;
- else
- haystack = haystack->right;
- }
- while (haystack != NULL);
-
- /* If the best node is smaller or equal to the data, then move one step
- * to the right to make sure the best one is strictly bigger than the data
- */
- if (best != end && c <= 0)
- best = node_get_next (best);
-
- return best;
-}
-
-static gint
-node_get_length (GSequenceNode *node)
-{
- node = find_root (node);
-
- return node->n_nodes;
-}
-
-static void
-real_node_free (GSequenceNode *node,
- GSequence *seq)
-{
- if (node)
- {
- real_node_free (node->left, seq);
- real_node_free (node->right, seq);
-
- if (seq && seq->data_destroy_notify && node != seq->end_node)
- seq->data_destroy_notify (node->data);
-
- g_slice_free (GSequenceNode, node);
- }
-}
-
-static void
-node_free (GSequenceNode *node,
- GSequence *seq)
-{
- node = find_root (node);
-
- real_node_free (node, seq);
-}
-
-static void
-node_update_fields (GSequenceNode *node)
-{
- int n_nodes = 1;
-
- n_nodes += N_NODES (node->left);
- n_nodes += N_NODES (node->right);
-
- node->n_nodes = n_nodes;
-}
-
-static void
-node_rotate (GSequenceNode *node)
-{
- GSequenceNode *tmp, *old;
-
- g_assert (node->parent);
- g_assert (node->parent != node);
-
- if (NODE_LEFT_CHILD (node))
- {
- /* rotate right */
- tmp = node->right;
-
- node->right = node->parent;
- node->parent = node->parent->parent;
- if (node->parent)
- {
- if (node->parent->left == node->right)
- node->parent->left = node;
- else
- node->parent->right = node;
- }
-
- g_assert (node->right);
-
- node->right->parent = node;
- node->right->left = tmp;
-
- if (node->right->left)
- node->right->left->parent = node->right;
-
- old = node->right;
- }
- else
- {
- /* rotate left */
- tmp = node->left;
-
- node->left = node->parent;
- node->parent = node->parent->parent;
- if (node->parent)
- {
- if (node->parent->right == node->left)
- node->parent->right = node;
- else
- node->parent->left = node;
- }
-
- g_assert (node->left);
-
- node->left->parent = node;
- node->left->right = tmp;
-
- if (node->left->right)
- node->left->right->parent = node->left;
-
- old = node->left;
- }
-
- node_update_fields (old);
- node_update_fields (node);
-}
-
-static void
-node_update_fields_deep (GSequenceNode *node)
-{
- if (node)
- {
- node_update_fields (node);
-
- node_update_fields_deep (node->parent);
- }
-}
-
-static void
-rotate_down (GSequenceNode *node,
- guint priority)
-{
- guint left, right;
-
- left = node->left ? get_priority (node->left) : 0;
- right = node->right ? get_priority (node->right) : 0;
-
- while (priority < left || priority < right)
- {
- if (left > right)
- node_rotate (node->left);
- else
- node_rotate (node->right);
-
- left = node->left ? get_priority (node->left) : 0;
- right = node->right ? get_priority (node->right) : 0;
- }
-}
-
-static void
-node_cut (GSequenceNode *node)
-{
- while (node->parent)
- node_rotate (node);
-
- if (node->left)
- node->left->parent = NULL;
-
- node->left = NULL;
- node_update_fields (node);
-
- rotate_down (node, get_priority (node));
-}
-
-static void
-node_join (GSequenceNode *left,
- GSequenceNode *right)
-{
- GSequenceNode *fake = node_new (NULL);
-
- fake->left = find_root (left);
- fake->right = find_root (right);
- fake->left->parent = fake;
- fake->right->parent = fake;
-
- node_update_fields (fake);
-
- node_unlink (fake);
-
- node_free (fake, NULL);
-}
-
-static void
-node_insert_before (GSequenceNode *node,
- GSequenceNode *new)
-{
- new->left = node->left;
- if (new->left)
- new->left->parent = new;
-
- new->parent = node;
- node->left = new;
-
- node_update_fields_deep (new);
-
- while (new->parent && get_priority (new) > get_priority (new->parent))
- node_rotate (new);
-
- rotate_down (new, get_priority (new));
-}
-
-static void
-node_unlink (GSequenceNode *node)
-{
- rotate_down (node, 0);
-
- if (NODE_RIGHT_CHILD (node))
- node->parent->right = NULL;
- else if (NODE_LEFT_CHILD (node))
- node->parent->left = NULL;
-
- if (node->parent)
- node_update_fields_deep (node->parent);
-
- node->parent = NULL;
-}
-
-static void
-node_insert_sorted (GSequenceNode *node,
- GSequenceNode *new,
- GSequenceNode *end,
- GSequenceIterCompareFunc iter_cmp,
- gpointer cmp_data)
-{
- GSequenceNode *closest;
-
- closest = node_find_closest (node, new, end, iter_cmp, cmp_data);
-
- node_unlink (new);
-
- node_insert_before (closest, new);
-}
-
-
-#define __G_SEQUENCE_C__
-#include "galiasdef.c"
diff --git a/glib/gshell.c b/glib/gshell.c
deleted file mode 100644
index 711cdee09..000000000
--- a/glib/gshell.c
+++ /dev/null
@@ -1,673 +0,0 @@
-/* gshell.c - Shell-related utilities
- *
- * Copyright 2000 Red Hat, Inc.
- * g_execvpe implementation based on GNU libc execvp:
- * Copyright 1991, 92, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
- *
- * GLib 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 of the
- * License, or (at your option) any later version.
- *
- * GLib 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 GLib; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include "glib.h"
-
-#ifdef _
-#warning "FIXME remove gettext hack"
-#endif
-
-#include "glibintl.h"
-#include "galias.h"
-
-GQuark
-g_shell_error_quark (void)
-{
- return g_quark_from_static_string ("g-shell-error-quark");
-}
-
-/* Single quotes preserve the literal string exactly. escape
- * sequences are not allowed; not even \' - if you want a '
- * in the quoted text, you have to do something like 'foo'\''bar'
- *
- * Double quotes allow $ ` " \ and newline to be escaped with backslash.
- * Otherwise double quotes preserve things literally.
- */
-
-static gboolean
-unquote_string_inplace (gchar* str, gchar** end, GError** err)
-{
- gchar* dest;
- gchar* s;
- gchar quote_char;
-
- g_return_val_if_fail(end != NULL, FALSE);
- g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
- g_return_val_if_fail(str != NULL, FALSE);
-
- dest = s = str;
-
- quote_char = *s;
-
- if (!(*s == '"' || *s == '\''))
- {
- g_set_error_literal (err,
- G_SHELL_ERROR,
- G_SHELL_ERROR_BAD_QUOTING,
- _("Quoted text doesn't begin with a quotation mark"));
- *end = str;
- return FALSE;
- }
-
- /* Skip the initial quote mark */
- ++s;
-
- if (quote_char == '"')
- {
- while (*s)
- {
- g_assert(s > dest); /* loop invariant */
-
- switch (*s)
- {
- case '"':
- /* End of the string, return now */
- *dest = '\0';
- ++s;
- *end = s;
- return TRUE;
- break;
-
- case '\\':
- /* Possible escaped quote or \ */
- ++s;
- switch (*s)
- {
- case '"':
- case '\\':
- case '`':
- case '$':
- case '\n':
- *dest = *s;
- ++s;
- ++dest;
- break;
-
- default:
- /* not an escaped char */
- *dest = '\\';
- ++dest;
- /* ++s already done. */
- break;
- }
- break;
-
- default:
- *dest = *s;
- ++dest;
- ++s;
- break;
- }
-
- g_assert(s > dest); /* loop invariant */
- }
- }
- else
- {
- while (*s)
- {
- g_assert(s > dest); /* loop invariant */
-
- if (*s == '\'')
- {
- /* End of the string, return now */
- *dest = '\0';
- ++s;
- *end = s;
- return TRUE;
- }
- else
- {
- *dest = *s;
- ++dest;
- ++s;
- }
-
- g_assert(s > dest); /* loop invariant */
- }
- }
-
- /* If we reach here this means the close quote was never encountered */
-
- *dest = '\0';
-
- g_set_error_literal (err,
- G_SHELL_ERROR,
- G_SHELL_ERROR_BAD_QUOTING,
- _("Unmatched quotation mark in command line or other shell-quoted text"));
- *end = s;
- return FALSE;
-}
-
-/**
- * g_shell_quote:
- * @unquoted_string: a literal string
- *
- * Quotes a string so that the shell (/bin/sh) will interpret the
- * quoted string to mean @unquoted_string. If you pass a filename to
- * the shell, for example, you should first quote it with this
- * function. The return value must be freed with g_free(). The
- * quoting style used is undefined (single or double quotes may be
- * used).
- *
- * Return value: quoted string
- **/
-gchar*
-g_shell_quote (const gchar *unquoted_string)
-{
- /* We always use single quotes, because the algorithm is cheesier.
- * We could use double if we felt like it, that might be more
- * human-readable.
- */
-
- const gchar *p;
- GString *dest;
-
- g_return_val_if_fail (unquoted_string != NULL, NULL);
-
- dest = g_string_new ("'");
-
- p = unquoted_string;
-
- /* could speed this up a lot by appending chunks of text at a
- * time.
- */
- while (*p)
- {
- /* Replace literal ' with a close ', a \', and a open ' */
- if (*p == '\'')
- g_string_append (dest, "'\\''");
- else
- g_string_append_c (dest, *p);
-
- ++p;
- }
-
- /* close the quote */
- g_string_append_c (dest, '\'');
-
- return g_string_free (dest, FALSE);
-}
-
-/**
- * g_shell_unquote:
- * @quoted_string: shell-quoted string
- * @error: error return location or NULL
- *
- * Unquotes a string as the shell (/bin/sh) would. Only handles
- * quotes; if a string contains file globs, arithmetic operators,
- * variables, backticks, redirections, or other special-to-the-shell
- * features, the result will be different from the result a real shell
- * would produce (the variables, backticks, etc. will be passed
- * through literally instead of being expanded). This function is
- * guaranteed to succeed if applied to the result of
- * g_shell_quote(). If it fails, it returns %NULL and sets the
- * error. The @quoted_string need not actually contain quoted or
- * escaped text; g_shell_unquote() simply goes through the string and
- * unquotes/unescapes anything that the shell would. Both single and
- * double quotes are handled, as are escapes including escaped
- * newlines. The return value must be freed with g_free(). Possible
- * errors are in the #G_SHELL_ERROR domain.
- *
- * Shell quoting rules are a bit strange. Single quotes preserve the
- * literal string exactly. escape sequences are not allowed; not even
- * \' - if you want a ' in the quoted text, you have to do something
- * like 'foo'\''bar'. Double quotes allow $, `, ", \, and newline to
- * be escaped with backslash. Otherwise double quotes preserve things
- * literally.
- *
- * Return value: an unquoted string
- **/
-gchar*
-g_shell_unquote (const gchar *quoted_string,
- GError **error)
-{
- gchar *unquoted;
- gchar *end;
- gchar *start;
- GString *retval;
-
- g_return_val_if_fail (quoted_string != NULL, NULL);
-
- unquoted = g_strdup (quoted_string);
-
- start = unquoted;
- end = unquoted;
- retval = g_string_new (NULL);
-
- /* The loop allows cases such as
- * "foo"blah blah'bar'woo foo"baz"la la la\'\''foo'
- */
- while (*start)
- {
- /* Append all non-quoted chars, honoring backslash escape
- */
-
- while (*start && !(*start == '"' || *start == '\''))
- {
- if (*start == '\\')
- {
- /* all characters can get escaped by backslash,
- * except newline, which is removed if it follows
- * a backslash outside of quotes
- */
-
- ++start;
- if (*start)
- {
- if (*start != '\n')
- g_string_append_c (retval, *start);
- ++start;
- }
- }
- else
- {
- g_string_append_c (retval, *start);
- ++start;
- }
- }
-
- if (*start)
- {
- if (!unquote_string_inplace (start, &end, error))
- {
- goto error;
- }
- else
- {
- g_string_append (retval, start);
- start = end;
- }
- }
- }
-
- g_free (unquoted);
- return g_string_free (retval, FALSE);
-
- error:
- g_assert (error == NULL || *error != NULL);
-
- g_free (unquoted);
- g_string_free (retval, TRUE);
- return NULL;
-}
-
-/* g_parse_argv() does a semi-arbitrary weird subset of the way
- * the shell parses a command line. We don't do variable expansion,
- * don't understand that operators are tokens, don't do tilde expansion,
- * don't do command substitution, no arithmetic expansion, IFS gets ignored,
- * don't do filename globs, don't remove redirection stuff, etc.
- *
- * READ THE UNIX98 SPEC on "Shell Command Language" before changing
- * the behavior of this code.
- *
- * Steps to parsing the argv string:
- *
- * - tokenize the string (but since we ignore operators,
- * our tokenization may diverge from what the shell would do)
- * note that tokenization ignores the internals of a quoted
- * word and it always splits on spaces, not on IFS even
- * if we used IFS. We also ignore "end of input indicator"
- * (I guess this is control-D?)
- *
- * Tokenization steps, from UNIX98 with operator stuff removed,
- * are:
- *
- * 1) "If the current character is backslash, single-quote or
- * double-quote (\, ' or ") and it is not quoted, it will affect
- * quoting for subsequent characters up to the end of the quoted
- * text. The rules for quoting are as described in Quoting
- * . During token recognition no substitutions will be actually
- * performed, and the result token will contain exactly the
- * characters that appear in the input (except for newline
- * character joining), unmodified, including any embedded or
- * enclosing quotes or substitution operators, between the quote
- * mark and the end of the quoted text. The token will not be
- * delimited by the end of the quoted field."
- *
- * 2) "If the current character is an unquoted newline character,
- * the current token will be delimited."
- *
- * 3) "If the current character is an unquoted blank character, any
- * token containing the previous character is delimited and the
- * current character will be discarded."
- *
- * 4) "If the previous character was part of a word, the current
- * character will be appended to that word."
- *
- * 5) "If the current character is a "#", it and all subsequent
- * characters up to, but excluding, the next newline character
- * will be discarded as a comment. The newline character that
- * ends the line is not considered part of the comment. The
- * "#" starts a comment only when it is at the beginning of a
- * token. Since the search for the end-of-comment does not
- * consider an escaped newline character specially, a comment
- * cannot be continued to the next line."
- *
- * 6) "The current character will be used as the start of a new word."
- *
- *
- * - for each token (word), perform portions of word expansion, namely
- * field splitting (using default whitespace IFS) and quote
- * removal. Field splitting may increase the number of words.
- * Quote removal does not increase the number of words.
- *
- * "If the complete expansion appropriate for a word results in an
- * empty field, that empty field will be deleted from the list of
- * fields that form the completely expanded command, unless the
- * original word contained single-quote or double-quote characters."
- * - UNIX98 spec
- *
- *
- */
-
-static inline void
-ensure_token (GString **token)
-{
- if (*token == NULL)
- *token = g_string_new (NULL);
-}
-
-static void
-delimit_token (GString **token,
- GSList **retval)
-{
- if (*token == NULL)
- return;
-
- *retval = g_slist_prepend (*retval, g_string_free (*token, FALSE));
-
- *token = NULL;
-}
-
-static GSList*
-tokenize_command_line (const gchar *command_line,
- GError **error)
-{
- gchar current_quote;
- const gchar *p;
- GString *current_token = NULL;
- GSList *retval = NULL;
- gboolean quoted;;
-
- current_quote = '\0';
- quoted = FALSE;
- p = command_line;
-
- while (*p)
- {
- if (current_quote == '\\')
- {
- if (*p == '\n')
- {
- /* we append nothing; backslash-newline become nothing */
- }
- else
- {
- /* we append the backslash and the current char,
- * to be interpreted later after tokenization
- */
- ensure_token (&current_token);
- g_string_append_c (current_token, '\\');
- g_string_append_c (current_token, *p);
- }
-
- current_quote = '\0';
- }
- else if (current_quote == '#')
- {
- /* Discard up to and including next newline */
- while (*p && *p != '\n')
- ++p;
-
- current_quote = '\0';
-
- if (*p == '\0')
- break;
- }
- else if (current_quote)
- {
- if (*p == current_quote &&
- /* check that it isn't an escaped double quote */
- !(current_quote == '"' && quoted))
- {
- /* close the quote */
- current_quote = '\0';
- }
-
- /* Everything inside quotes, and the close quote,
- * gets appended literally.
- */
-
- ensure_token (&current_token);
- g_string_append_c (current_token, *p);
- }
- else
- {
- switch (*p)
- {
- case '\n':
- delimit_token (&current_token, &retval);
- break;
-
- case ' ':
- case '\t':
- /* If the current token contains the previous char, delimit
- * the current token. A nonzero length
- * token should always contain the previous char.
- */
- if (current_token &&
- current_token->len > 0)
- {
- delimit_token (&current_token, &retval);
- }
-
- /* discard all unquoted blanks (don't add them to a token) */
- break;
-
-
- /* single/double quotes are appended to the token,
- * escapes are maybe appended next time through the loop,
- * comment chars are never appended.
- */
-
- case '\'':
- case '"':
- ensure_token (&current_token);
- g_string_append_c (current_token, *p);
-
- /* FALL THRU */
-
- case '#':
- case '\\':
- current_quote = *p;
- break;
-
- default:
- /* Combines rules 4) and 6) - if we have a token, append to it,
- * otherwise create a new token.
- */
- ensure_token (&current_token);
- g_string_append_c (current_token, *p);
- break;
- }
- }
-
- /* We need to count consecutive backslashes mod 2,
- * to detect escaped doublequotes.
- */
- if (*p != '\\')
- quoted = FALSE;
- else
- quoted = !quoted;
-
- ++p;
- }
-
- delimit_token (&current_token, &retval);
-
- if (current_quote)
- {
- if (current_quote == '\\')
- g_set_error (error,
- G_SHELL_ERROR,
- G_SHELL_ERROR_BAD_QUOTING,
- _("Text ended just after a '\\' character."
- " (The text was '%s')"),
- command_line);
- else
- g_set_error (error,
- G_SHELL_ERROR,
- G_SHELL_ERROR_BAD_QUOTING,
- _("Text ended before matching quote was found for %c."
- " (The text was '%s')"),
- current_quote, command_line);
-
- goto error;
- }
-
- if (retval == NULL)
- {
- g_set_error_literal (error,
- G_SHELL_ERROR,
- G_SHELL_ERROR_EMPTY_STRING,
- _("Text was empty (or contained only whitespace)"));
-
- goto error;
- }
-
- /* we appended backward */
- retval = g_slist_reverse (retval);
-
- return retval;
-
- error:
- g_assert (error == NULL || *error != NULL);
-
- if (retval)
- {
- g_slist_foreach (retval, (GFunc)g_free, NULL);
- g_slist_free (retval);
- }
-
- return NULL;
-}
-
-/**
- * g_shell_parse_argv:
- * @command_line: command line to parse
- * @argcp: return location for number of args
- * @argvp: return location for array of args
- * @error: return location for error
- *
- * Parses a command line into an argument vector, in much the same way
- * the shell would, but without many of the expansions the shell would
- * perform (variable expansion, globs, operators, filename expansion,
- * etc. are not supported). The results are defined to be the same as
- * those you would get from a UNIX98 /bin/sh, as long as the input
- * contains none of the unsupported shell expansions. If the input
- * does contain such expansions, they are passed through
- * literally. Possible errors are those from the #G_SHELL_ERROR
- * domain. Free the returned vector with g_strfreev().
- *
- * Return value: %TRUE on success, %FALSE if error set
- **/
-gboolean
-g_shell_parse_argv (const gchar *command_line,
- gint *argcp,
- gchar ***argvp,
- GError **error)
-{
- /* Code based on poptParseArgvString() from libpopt */
- gint argc = 0;
- gchar **argv = NULL;
- GSList *tokens = NULL;
- gint i;
- GSList *tmp_list;
-
- g_return_val_if_fail (command_line != NULL, FALSE);
-
- tokens = tokenize_command_line (command_line, error);
- if (tokens == NULL)
- return FALSE;
-
- /* Because we can't have introduced any new blank space into the
- * tokens (we didn't do any new expansions), we don't need to
- * perform field splitting. If we were going to honor IFS or do any
- * expansions, we would have to do field splitting on each word
- * here. Also, if we were going to do any expansion we would need to
- * remove any zero-length words that didn't contain quotes
- * originally; but since there's no expansion we know all words have
- * nonzero length, unless they contain quotes.
- *
- * So, we simply remove quotes, and don't do any field splitting or
- * empty word removal, since we know there was no way to introduce
- * such things.
- */
-
- argc = g_slist_length (tokens);
- argv = g_new0 (gchar*, argc + 1);
- i = 0;
- tmp_list = tokens;
- while (tmp_list)
- {
- argv[i] = g_shell_unquote (tmp_list->data, error);
-
- /* Since we already checked that quotes matched up in the
- * tokenizer, this shouldn't be possible to reach I guess.
- */
- if (argv[i] == NULL)
- goto failed;
-
- tmp_list = g_slist_next (tmp_list);
- ++i;
- }
-
- g_slist_foreach (tokens, (GFunc)g_free, NULL);
- g_slist_free (tokens);
-
- if (argcp)
- *argcp = argc;
-
- if (argvp)
- *argvp = argv;
- else
- g_strfreev (argv);
-
- return TRUE;
-
- failed:
-
- g_assert (error == NULL || *error != NULL);
- g_strfreev (argv);
- g_slist_foreach (tokens, (GFunc) g_free, NULL);
- g_slist_free (tokens);
-
- return FALSE;
-}
-
-#define __G_SHELL_C__
-#include "galiasdef.c"
diff --git a/glib/gspawn-win32-helper.c b/glib/gspawn-win32-helper.c
deleted file mode 100644
index 40108bb67..000000000
--- a/glib/gspawn-win32-helper.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/* gspawn-win32-helper.c - Helper program for process launching on Win32.
- *
- * Copyright 2000 Red Hat, Inc.
- * Copyright 2000 Tor Lillqvist
- *
- * GLib 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 of the
- * License, or (at your option) any later version.
- *
- * GLib 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 GLib; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <fcntl.h>
-
-#undef G_LOG_DOMAIN
-#include "glib.h"
-#define GSPAWN_HELPER
-#include "gspawn-win32.c" /* For shared definitions */
-
-
-static void
-write_err_and_exit (gint fd,
- gintptr msg)
-{
- gintptr en = errno;
-
- write (fd, &msg, sizeof(gintptr));
- write (fd, &en, sizeof(gintptr));
-
- _exit (1);
-}
-
-#ifdef __GNUC__
-# ifndef _stdcall
-# define _stdcall __attribute__((stdcall))
-# endif
-#endif
-
-/* We build gspawn-win32-helper.exe as a Windows GUI application
- * to avoid any temporarily flashing console windows in case
- * the gspawn function is invoked by a GUI program. Thus, no main()
- * but a WinMain(). We do, however, still use argc and argv tucked
- * away in the global __argc and __argv by the C runtime startup code.
- */
-
-/* Info peeked from mingw runtime's source code. __wgetmainargs() is a
- * function to get the program's argv in wide char format.
- */
-
-typedef struct {
- int newmode;
-} _startupinfo;
-
-extern void __wgetmainargs(int *argc,
- wchar_t ***wargv,
- wchar_t ***wenviron,
- int expand_wildcards,
- _startupinfo *startupinfo);
-
-/* Copy of protect_argv that handles wchar_t strings */
-
-static gint
-protect_wargv (wchar_t **wargv,
- wchar_t ***new_wargv)
-{
- gint i;
- gint argc = 0;
-
- while (wargv[argc])
- ++argc;
- *new_wargv = g_new (wchar_t *, argc+1);
-
- /* Quote each argv element if necessary, so that it will get
- * reconstructed correctly in the C runtime startup code. Note that
- * the unquoting algorithm in the C runtime is really weird, and
- * rather different than what Unix shells do. See stdargv.c in the C
- * runtime sources (in the Platform SDK, in src/crt).
- *
- * Note that an new_wargv[0] constructed by this function should
- * *not* be passed as the filename argument to a _wspawn* or _wexec*
- * family function. That argument should be the real file name
- * without any quoting.
- */
- for (i = 0; i < argc; i++)
- {
- wchar_t *p = wargv[i];
- wchar_t *q;
- gint len = 0;
- gboolean need_dblquotes = FALSE;
- while (*p)
- {
- if (*p == ' ' || *p == '\t')
- need_dblquotes = TRUE;
- else if (*p == '"')
- len++;
- else if (*p == '\\')
- {
- wchar_t *pp = p;
- while (*pp && *pp == '\\')
- pp++;
- if (*pp == '"')
- len++;
- }
- len++;
- p++;
- }
-
- q = (*new_wargv)[i] = g_new (wchar_t, len + need_dblquotes*2 + 1);
- p = wargv[i];
-
- if (need_dblquotes)
- *q++ = '"';
-
- while (*p)
- {
- if (*p == '"')
- *q++ = '\\';
- else if (*p == '\\')
- {
- wchar_t *pp = p;
- while (*pp && *pp == '\\')
- pp++;
- if (*pp == '"')
- *q++ = '\\';
- }
- *q++ = *p;
- p++;
- }
-
- if (need_dblquotes)
- *q++ = '"';
- *q++ = '\0';
- }
- (*new_wargv)[argc] = NULL;
-
- return argc;
-}
-
-#ifndef HELPER_CONSOLE
-int _stdcall
-WinMain (struct HINSTANCE__ *hInstance,
- struct HINSTANCE__ *hPrevInstance,
- char *lpszCmdLine,
- int nCmdShow)
-#else
-int
-main (int ignored_argc, char **ignored_argv)
-#endif
-{
- int child_err_report_fd = -1;
- int helper_sync_fd = -1;
- int i;
- int fd;
- int mode;
- gintptr handle;
- int saved_errno;
- gintptr no_error = CHILD_NO_ERROR;
- gint argv_zero_offset = ARG_PROGRAM;
- wchar_t **new_wargv;
- int argc;
- wchar_t **wargv, **wenvp;
- _startupinfo si = { 0 };
- char c;
-
- g_assert (__argc >= ARG_COUNT);
-
- /* Fetch the wide-char argument vector */
- __wgetmainargs (&argc, &wargv, &wenvp, 0, &si);
-
- /* We still have the system codepage args in __argv. We can look
- * at the first args in which gspawn-win32.c passes us flags and
- * fd numbers in __argv, as we know those are just ASCII anyway.
- */
- g_assert (argc == __argc);
-
- /* argv[ARG_CHILD_ERR_REPORT] is the file descriptor number onto
- * which write error messages.
- */
- child_err_report_fd = atoi (__argv[ARG_CHILD_ERR_REPORT]);
-
- /* Hack to implement G_SPAWN_FILE_AND_ARGV_ZERO. If
- * argv[ARG_CHILD_ERR_REPORT] is suffixed with a '#' it means we get
- * the program to run and its argv[0] separately.
- */
- if (__argv[ARG_CHILD_ERR_REPORT][strlen (__argv[ARG_CHILD_ERR_REPORT]) - 1] == '#')
- argv_zero_offset++;
-
- /* argv[ARG_HELPER_SYNC] is the file descriptor number we read a
- * byte that tells us it is OK to exit. We have to wait until the
- * parent allows us to exit, so that the parent has had time to
- * duplicate the process handle we sent it. Duplicating a handle
- * from another process works only if that other process exists.
- */
- helper_sync_fd = atoi (__argv[ARG_HELPER_SYNC]);
-
- /* argv[ARG_STDIN..ARG_STDERR] are the file descriptor numbers that
- * should be dup2'd to 0, 1 and 2. '-' if the corresponding fd
- * should be left alone, and 'z' if it should be connected to the
- * bit bucket NUL:.
- */
- if (__argv[ARG_STDIN][0] == '-')
- ; /* Nothing */
- else if (__argv[ARG_STDIN][0] == 'z')
- {
- fd = open ("NUL:", O_RDONLY);
- if (fd != 0)
- {
- dup2 (fd, 0);
- close (fd);
- }
- }
- else
- {
- fd = atoi (__argv[ARG_STDIN]);
- if (fd != 0)
- {
- dup2 (fd, 0);
- close (fd);
- }
- }
-
- if (__argv[ARG_STDOUT][0] == '-')
- ; /* Nothing */
- else if (__argv[ARG_STDOUT][0] == 'z')
- {
- fd = open ("NUL:", O_WRONLY);
- if (fd != 1)
- {
- dup2 (fd, 1);
- close (fd);
- }
- }
- else
- {
- fd = atoi (__argv[ARG_STDOUT]);
- if (fd != 1)
- {
- dup2 (fd, 1);
- close (fd);
- }
- }
-
- if (__argv[ARG_STDERR][0] == '-')
- ; /* Nothing */
- else if (__argv[ARG_STDERR][0] == 'z')
- {
- fd = open ("NUL:", O_WRONLY);
- if (fd != 2)
- {
- dup2 (fd, 2);
- close (fd);
- }
- }
- else
- {
- fd = atoi (__argv[ARG_STDERR]);
- if (fd != 2)
- {
- dup2 (fd, 2);
- close (fd);
- }
- }
-
- /* __argv[ARG_WORKING_DIRECTORY] is the directory in which to run the
- * process. If "-", don't change directory.
- */
- if (__argv[ARG_WORKING_DIRECTORY][0] == '-' &&
- __argv[ARG_WORKING_DIRECTORY][1] == 0)
- ; /* Nothing */
- else if (_wchdir (wargv[ARG_WORKING_DIRECTORY]) < 0)
- write_err_and_exit (child_err_report_fd, CHILD_CHDIR_FAILED);
-
- /* __argv[ARG_CLOSE_DESCRIPTORS] is "y" if file descriptors from 3
- * upwards should be closed
- */
- if (__argv[ARG_CLOSE_DESCRIPTORS][0] == 'y')
- for (i = 3; i < 1000; i++) /* FIXME real limit? */
- if (i != child_err_report_fd && i != helper_sync_fd)
- close (i);
-
- /* We don't want our child to inherit the error report and
- * helper sync fds.
- */
- child_err_report_fd = dup_noninherited (child_err_report_fd, _O_WRONLY);
- helper_sync_fd = dup_noninherited (helper_sync_fd, _O_RDONLY);
-
- /* __argv[ARG_WAIT] is "w" to wait for the program to exit */
- if (__argv[ARG_WAIT][0] == 'w')
- mode = P_WAIT;
- else
- mode = P_NOWAIT;
-
- /* __argv[ARG_USE_PATH] is "y" to use PATH, otherwise not */
-
- /* __argv[ARG_PROGRAM] is executable file to run,
- * __argv[argv_zero_offset]... is its argv. argv_zero_offset equals
- * ARG_PROGRAM unless G_SPAWN_FILE_AND_ARGV_ZERO was used, in which
- * case we have a separate executable name and argv[0].
- */
-
- /* For the program name passed to spawnv(), don't use the quoted
- * version.
- */
- protect_wargv (wargv + argv_zero_offset, &new_wargv);
-
- if (__argv[ARG_USE_PATH][0] == 'y')
- handle = _wspawnvp (mode, wargv[ARG_PROGRAM], (const wchar_t **) new_wargv);
- else
- handle = _wspawnv (mode, wargv[ARG_PROGRAM], (const wchar_t **) new_wargv);
-
- saved_errno = errno;
-
- if (handle == -1 && saved_errno != 0)
- write_err_and_exit (child_err_report_fd, CHILD_SPAWN_FAILED);
-
- write (child_err_report_fd, &no_error, sizeof (no_error));
- write (child_err_report_fd, &handle, sizeof (handle));
-
- read (helper_sync_fd, &c, 1);
-
- return 0;
-}
diff --git a/glib/gspawn-win32.c b/glib/gspawn-win32.c
deleted file mode 100644
index ba7970bb1..000000000
--- a/glib/gspawn-win32.c
+++ /dev/null
@@ -1,1494 +0,0 @@
-/* gspawn-win32.c - Process launching on Win32
- *
- * Copyright 2000 Red Hat, Inc.
- * Copyright 2003 Tor Lillqvist
- *
- * GLib 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 of the
- * License, or (at your option) any later version.
- *
- * GLib 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 GLib; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Implementation details on Win32.
- *
- * - There is no way to set the no-inherit flag for
- * a "file descriptor" in the MS C runtime. The flag is there,
- * and the dospawn() function uses it, but unfortunately
- * this flag can only be set when opening the file.
- * - As there is no fork(), we cannot reliably change directory
- * before starting the child process. (There might be several threads
- * running, and the current directory is common for all threads.)
- *
- * Thus, we must in many cases use a helper program to handle closing
- * of (inherited) file descriptors and changing of directory. The
- * helper process is also needed if the standard input, standard
- * output, or standard error of the process to be run are supposed to
- * be redirected somewhere.
- *
- * The structure of the source code in this file is a mess, I know.
- */
-
-/* Define this to get some logging all the time */
-/* #define G_SPAWN_WIN32_DEBUG */
-
-#include "config.h"
-
-#include "glib.h"
-#include "gprintfint.h"
-#include "glibintl.h"
-#include "galias.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <windows.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <io.h>
-#include <process.h>
-#include <direct.h>
-#include <wchar.h>
-
-#ifdef G_SPAWN_WIN32_DEBUG
- static int debug = 1;
- #define SETUP_DEBUG() /* empty */
-#else
- static int debug = -1;
- #define SETUP_DEBUG() \
- G_STMT_START \
- { \
- if (debug == -1) \
- { \
- if (getenv ("G_SPAWN_WIN32_DEBUG") != NULL) \
- debug = 1; \
- else \
- debug = 0; \
- } \
- } \
- G_STMT_END
-#endif
-
-enum
-{
- CHILD_NO_ERROR,
- CHILD_CHDIR_FAILED,
- CHILD_SPAWN_FAILED,
-};
-
-enum {
- ARG_CHILD_ERR_REPORT = 1,
- ARG_HELPER_SYNC,
- ARG_STDIN,
- ARG_STDOUT,
- ARG_STDERR,
- ARG_WORKING_DIRECTORY,
- ARG_CLOSE_DESCRIPTORS,
- ARG_USE_PATH,
- ARG_WAIT,
- ARG_PROGRAM,
- ARG_COUNT = ARG_PROGRAM
-};
-
-static int
-dup_noninherited (int fd,
- int mode)
-{
- HANDLE filehandle;
-
- DuplicateHandle (GetCurrentProcess (), (LPHANDLE) _get_osfhandle (fd),
- GetCurrentProcess (), &filehandle,
- 0, FALSE, DUPLICATE_SAME_ACCESS);
- close (fd);
- return _open_osfhandle ((gintptr) filehandle, mode | _O_NOINHERIT);
-}
-
-#ifndef GSPAWN_HELPER
-
-#ifdef _WIN64
-#define HELPER_PROCESS "gspawn-win64-helper"
-#else
-#define HELPER_PROCESS "gspawn-win32-helper"
-#endif
-
-static gchar *
-protect_argv_string (const gchar *string)
-{
- const gchar *p = string;
- gchar *retval, *q;
- gint len = 0;
- gboolean need_dblquotes = FALSE;
- while (*p)
- {
- if (*p == ' ' || *p == '\t')
- need_dblquotes = TRUE;
- else if (*p == '"')
- len++;
- else if (*p == '\\')
- {
- const gchar *pp = p;
- while (*pp && *pp == '\\')
- pp++;
- if (*pp == '"')
- len++;
- }
- len++;
- p++;
- }
-
- q = retval = g_malloc (len + need_dblquotes*2 + 1);
- p = string;
-
- if (need_dblquotes)
- *q++ = '"';
-
- while (*p)
- {
- if (*p == '"')
- *q++ = '\\';
- else if (*p == '\\')
- {
- const gchar *pp = p;
- while (*pp && *pp == '\\')
- pp++;
- if (*pp == '"')
- *q++ = '\\';
- }
- *q++ = *p;
- p++;
- }
-
- if (need_dblquotes)
- *q++ = '"';
- *q++ = '\0';
-
- return retval;
-}
-
-static gint
-protect_argv (gchar **argv,
- gchar ***new_argv)
-{
- gint i;
- gint argc = 0;
-
- while (argv[argc])
- ++argc;
- *new_argv = g_new (gchar *, argc+1);
-
- /* Quote each argv element if necessary, so that it will get
- * reconstructed correctly in the C runtime startup code. Note that
- * the unquoting algorithm in the C runtime is really weird, and
- * rather different than what Unix shells do. See stdargv.c in the C
- * runtime sources (in the Platform SDK, in src/crt).
- *
- * Note that an new_argv[0] constructed by this function should
- * *not* be passed as the filename argument to a spawn* or exec*
- * family function. That argument should be the real file name
- * without any quoting.
- */
- for (i = 0; i < argc; i++)
- (*new_argv)[i] = protect_argv_string (argv[i]);
-
- (*new_argv)[argc] = NULL;
-
- return argc;
-}
-
-GQuark
-g_spawn_error_quark (void)
-{
- return g_quark_from_static_string ("g-exec-error-quark");
-}
-
-gboolean
-g_spawn_async_utf8 (const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_handle,
- GError **error)
-{
- g_return_val_if_fail (argv != NULL, FALSE);
-
- return g_spawn_async_with_pipes_utf8 (working_directory,
- argv, envp,
- flags,
- child_setup,
- user_data,
- child_handle,
- NULL, NULL, NULL,
- error);
-}
-
-/* Avoids a danger in threaded situations (calling close()
- * on a file descriptor twice, and another thread has
- * re-opened it since the first close)
- */
-static void
-close_and_invalidate (gint *fd)
-{
- if (*fd < 0)
- return;
-
- close (*fd);
- *fd = -1;
-}
-
-typedef enum
-{
- READ_FAILED = 0, /* FALSE */
- READ_OK,
- READ_EOF
-} ReadResult;
-
-static ReadResult
-read_data (GString *str,
- GIOChannel *iochannel,
- GError **error)
-{
- GIOStatus giostatus;
- gsize bytes;
- gchar buf[4096];
-
- again:
-
- giostatus = g_io_channel_read_chars (iochannel, buf, sizeof (buf), &bytes, NULL);
-
- if (bytes == 0)
- return READ_EOF;
- else if (bytes > 0)
- {
- g_string_append_len (str, buf, bytes);
- return READ_OK;
- }
- else if (giostatus == G_IO_STATUS_AGAIN)
- goto again;
- else if (giostatus == G_IO_STATUS_ERROR)
- {
- g_set_error_literal (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
- _("Failed to read data from child process"));
-
- return READ_FAILED;
- }
- else
- return READ_OK;
-}
-
-static gboolean
-make_pipe (gint p[2],
- GError **error)
-{
- if (_pipe (p, 4096, _O_BINARY) < 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to create pipe for communicating with child process (%s)"),
- g_strerror (errno));
- return FALSE;
- }
- else
- return TRUE;
-}
-
-/* The helper process writes a status report back to us, through a
- * pipe, consisting of two ints.
- */
-static gboolean
-read_helper_report (int fd,
- gintptr report[2],
- GError **error)
-{
- gint bytes = 0;
-
- while (bytes < sizeof(gintptr)*2)
- {
- gint chunk;
-
- if (debug)
- g_print ("%s:read_helper_report: read %" G_GSIZE_FORMAT "...\n",
- __FILE__,
- sizeof(gintptr)*2 - bytes);
-
- chunk = read (fd, ((gchar*)report) + bytes,
- sizeof(gintptr)*2 - bytes);
-
- if (debug)
- g_print ("...got %d bytes\n", chunk);
-
- if (chunk < 0)
- {
- /* Some weird shit happened, bail out */
-
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to read from child pipe (%s)"),
- g_strerror (errno));
-
- return FALSE;
- }
- else if (chunk == 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to read from child pipe (%s)"),
- "EOF");
- break; /* EOF */
- }
- else
- bytes += chunk;
- }
-
- if (bytes < sizeof(gintptr)*2)
- return FALSE;
-
- return TRUE;
-}
-
-static void
-set_child_error (gintptr report[2],
- const gchar *working_directory,
- GError **error)
-{
- switch (report[0])
- {
- case CHILD_CHDIR_FAILED:
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
- _("Failed to change to directory '%s' (%s)"),
- working_directory,
- g_strerror (report[1]));
- break;
- case CHILD_SPAWN_FAILED:
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to execute child process (%s)"),
- g_strerror (report[1]));
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
-static gboolean
-utf8_charv_to_wcharv (char **utf8_charv,
- wchar_t ***wcharv,
- int *error_index,
- GError **error)
-{
- wchar_t **retval = NULL;
-
- *wcharv = NULL;
- if (utf8_charv != NULL)
- {
- int n = 0, i;
-
- while (utf8_charv[n])
- n++;
- retval = g_new (wchar_t *, n + 1);
-
- for (i = 0; i < n; i++)
- {
- retval[i] = g_utf8_to_utf16 (utf8_charv[i], -1, NULL, NULL, error);
- if (retval[i] == NULL)
- {
- if (error_index)
- *error_index = i;
- while (i)
- g_free (retval[--i]);
- g_free (retval);
- return FALSE;
- }
- }
-
- retval[n] = NULL;
- }
- *wcharv = retval;
- return TRUE;
-}
-
-static gboolean
-do_spawn_directly (gint *exit_status,
- gboolean do_return_handle,
- GSpawnFlags flags,
- gchar **argv,
- char **envp,
- char **protected_argv,
- GPid *child_handle,
- GError **error)
-{
- const int mode = (exit_status == NULL) ? P_NOWAIT : P_WAIT;
- char **new_argv;
- gintptr rc = -1;
- int saved_errno;
- GError *conv_error = NULL;
- gint conv_error_index;
- wchar_t *wargv0, **wargv, **wenvp;
-
- new_argv = (flags & G_SPAWN_FILE_AND_ARGV_ZERO) ? protected_argv + 1 : protected_argv;
-
- wargv0 = g_utf8_to_utf16 (argv[0], -1, NULL, NULL, &conv_error);
- if (wargv0 == NULL)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid program name: %s"),
- conv_error->message);
- g_error_free (conv_error);
-
- return FALSE;
- }
-
- if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in argument vector at %d: %s"),
- conv_error_index, conv_error->message);
- g_error_free (conv_error);
- g_free (wargv0);
-
- return FALSE;
- }
-
- if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in environment: %s"),
- conv_error->message);
- g_error_free (conv_error);
- g_free (wargv0);
- g_strfreev ((gchar **) wargv);
-
- return FALSE;
- }
-
- if (flags & G_SPAWN_SEARCH_PATH)
- if (wenvp != NULL)
- rc = _wspawnvpe (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
- else
- rc = _wspawnvp (mode, wargv0, (const wchar_t **) wargv);
- else
- if (wenvp != NULL)
- rc = _wspawnve (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
- else
- rc = _wspawnv (mode, wargv0, (const wchar_t **) wargv);
-
- g_free (wargv0);
- g_strfreev ((gchar **) wargv);
- g_strfreev ((gchar **) wenvp);
-
- saved_errno = errno;
-
- if (rc == -1 && saved_errno != 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to execute child process (%s)"),
- g_strerror (saved_errno));
- return FALSE;
- }
-
- if (exit_status == NULL)
- {
- if (child_handle && do_return_handle)
- *child_handle = (GPid) rc;
- else
- {
- CloseHandle ((HANDLE) rc);
- if (child_handle)
- *child_handle = 0;
- }
- }
- else
- *exit_status = rc;
-
- return TRUE;
-}
-
-static gboolean
-do_spawn_with_pipes (gint *exit_status,
- gboolean do_return_handle,
- const gchar *working_directory,
- gchar **argv,
- char **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- GPid *child_handle,
- gint *standard_input,
- gint *standard_output,
- gint *standard_error,
- gint *err_report,
- GError **error)
-{
- char **protected_argv;
- char args[ARG_COUNT][10];
- char **new_argv;
- int i;
- gintptr rc = -1;
- int saved_errno;
- int argc;
- int stdin_pipe[2] = { -1, -1 };
- int stdout_pipe[2] = { -1, -1 };
- int stderr_pipe[2] = { -1, -1 };
- int child_err_report_pipe[2] = { -1, -1 };
- int helper_sync_pipe[2] = { -1, -1 };
- gintptr helper_report[2];
- static gboolean warned_about_child_setup = FALSE;
- GError *conv_error = NULL;
- gint conv_error_index;
- gchar *helper_process;
- CONSOLE_CURSOR_INFO cursor_info;
- wchar_t *whelper, **wargv, **wenvp;
- extern gchar *_glib_get_dll_directory (void);
- gchar *glib_dll_directory;
-
- if (child_setup && !warned_about_child_setup)
- {
- warned_about_child_setup = TRUE;
- g_warning ("passing a child setup function to the g_spawn functions is pointless on Windows and it is ignored");
- }
-
- argc = protect_argv (argv, &protected_argv);
-
- if (!standard_input && !standard_output && !standard_error &&
- (flags & G_SPAWN_CHILD_INHERITS_STDIN) &&
- !(flags & G_SPAWN_STDOUT_TO_DEV_NULL) &&
- !(flags & G_SPAWN_STDERR_TO_DEV_NULL) &&
- (working_directory == NULL || !*working_directory) &&
- (flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
- {
- /* We can do without the helper process */
- gboolean retval =
- do_spawn_directly (exit_status, do_return_handle, flags,
- argv, envp, protected_argv,
- child_handle, error);
- g_strfreev (protected_argv);
- return retval;
- }
-
- if (standard_input && !make_pipe (stdin_pipe, error))
- goto cleanup_and_fail;
-
- if (standard_output && !make_pipe (stdout_pipe, error))
- goto cleanup_and_fail;
-
- if (standard_error && !make_pipe (stderr_pipe, error))
- goto cleanup_and_fail;
-
- if (!make_pipe (child_err_report_pipe, error))
- goto cleanup_and_fail;
-
- if (!make_pipe (helper_sync_pipe, error))
- goto cleanup_and_fail;
-
- new_argv = g_new (char *, argc + 1 + ARG_COUNT);
- if (GetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cursor_info))
- helper_process = HELPER_PROCESS "-console.exe";
- else
- helper_process = HELPER_PROCESS ".exe";
-
- glib_dll_directory = _glib_get_dll_directory ();
- if (glib_dll_directory != NULL)
- {
- helper_process = g_build_filename (glib_dll_directory, helper_process, NULL);
- g_free (glib_dll_directory);
- }
- else
- helper_process = g_strdup (helper_process);
-
- new_argv[0] = protect_argv_string (helper_process);
-
- _g_sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_pipe[1]);
- new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
-
- /* Make the read end of the child error report pipe
- * noninherited. Otherwise it will needlessly be inherited by the
- * helper process, and the started actual user process. As such that
- * shouldn't harm, but it is unnecessary.
- */
- child_err_report_pipe[0] = dup_noninherited (child_err_report_pipe[0], _O_RDONLY);
-
- if (flags & G_SPAWN_FILE_AND_ARGV_ZERO)
- {
- /* Overload ARG_CHILD_ERR_REPORT to also encode the
- * G_SPAWN_FILE_AND_ARGV_ZERO functionality.
- */
- strcat (args[ARG_CHILD_ERR_REPORT], "#");
- }
-
- _g_sprintf (args[ARG_HELPER_SYNC], "%d", helper_sync_pipe[0]);
- new_argv[ARG_HELPER_SYNC] = args[ARG_HELPER_SYNC];
-
- /* Make the write end of the sync pipe noninherited. Otherwise the
- * helper process will inherit it, and thus if this process happens
- * to crash before writing the sync byte to the pipe, the helper
- * process won't read but won't get any EOF either, as it has the
- * write end open itself.
- */
- helper_sync_pipe[1] = dup_noninherited (helper_sync_pipe[1], _O_WRONLY);
-
- if (standard_input)
- {
- _g_sprintf (args[ARG_STDIN], "%d", stdin_pipe[0]);
- new_argv[ARG_STDIN] = args[ARG_STDIN];
- }
- else if (flags & G_SPAWN_CHILD_INHERITS_STDIN)
- {
- /* Let stdin be alone */
- new_argv[ARG_STDIN] = "-";
- }
- else
- {
- /* Keep process from blocking on a read of stdin */
- new_argv[ARG_STDIN] = "z";
- }
-
- if (standard_output)
- {
- _g_sprintf (args[ARG_STDOUT], "%d", stdout_pipe[1]);
- new_argv[ARG_STDOUT] = args[ARG_STDOUT];
- }
- else if (flags & G_SPAWN_STDOUT_TO_DEV_NULL)
- {
- new_argv[ARG_STDOUT] = "z";
- }
- else
- {
- new_argv[ARG_STDOUT] = "-";
- }
-
- if (standard_error)
- {
- _g_sprintf (args[ARG_STDERR], "%d", stderr_pipe[1]);
- new_argv[ARG_STDERR] = args[ARG_STDERR];
- }
- else if (flags & G_SPAWN_STDERR_TO_DEV_NULL)
- {
- new_argv[ARG_STDERR] = "z";
- }
- else
- {
- new_argv[ARG_STDERR] = "-";
- }
-
- if (working_directory && *working_directory)
- new_argv[ARG_WORKING_DIRECTORY] = protect_argv_string (working_directory);
- else
- new_argv[ARG_WORKING_DIRECTORY] = g_strdup ("-");
-
- if (!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
- new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
- else
- new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
-
- if (flags & G_SPAWN_SEARCH_PATH)
- new_argv[ARG_USE_PATH] = "y";
- else
- new_argv[ARG_USE_PATH] = "-";
-
- if (exit_status == NULL)
- new_argv[ARG_WAIT] = "-";
- else
- new_argv[ARG_WAIT] = "w";
-
- for (i = 0; i <= argc; i++)
- new_argv[ARG_PROGRAM + i] = protected_argv[i];
-
- SETUP_DEBUG();
-
- if (debug)
- {
- g_print ("calling %s with argv:\n", helper_process);
- for (i = 0; i < argc + 1 + ARG_COUNT; i++)
- g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
- }
-
- if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
- {
- if (conv_error_index == ARG_WORKING_DIRECTORY)
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
- _("Invalid working directory: %s"),
- conv_error->message);
- else
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in argument vector at %d: %s"),
- conv_error_index - ARG_PROGRAM, conv_error->message);
- g_error_free (conv_error);
- g_strfreev (protected_argv);
- g_free (new_argv[0]);
- g_free (new_argv[ARG_WORKING_DIRECTORY]);
- g_free (new_argv);
- g_free (helper_process);
-
- goto cleanup_and_fail;
- }
-
- if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in environment: %s"),
- conv_error->message);
- g_error_free (conv_error);
- g_strfreev (protected_argv);
- g_free (new_argv[0]);
- g_free (new_argv[ARG_WORKING_DIRECTORY]);
- g_free (new_argv);
- g_free (helper_process);
- g_strfreev ((gchar **) wargv);
-
- goto cleanup_and_fail;
- }
-
- whelper = g_utf8_to_utf16 (helper_process, -1, NULL, NULL, NULL);
- g_free (helper_process);
-
- if (wenvp != NULL)
- rc = _wspawnvpe (P_NOWAIT, whelper, (const wchar_t **) wargv, (const wchar_t **) wenvp);
- else
- rc = _wspawnvp (P_NOWAIT, whelper, (const wchar_t **) wargv);
-
- saved_errno = errno;
-
- g_free (whelper);
- g_strfreev ((gchar **) wargv);
- g_strfreev ((gchar **) wenvp);
-
- /* Close the other process's ends of the pipes in this process,
- * otherwise the reader will never get EOF.
- */
- close_and_invalidate (&child_err_report_pipe[1]);
- close_and_invalidate (&helper_sync_pipe[0]);
- close_and_invalidate (&stdin_pipe[0]);
- close_and_invalidate (&stdout_pipe[1]);
- close_and_invalidate (&stderr_pipe[1]);
-
- g_strfreev (protected_argv);
-
- g_free (new_argv[0]);
- g_free (new_argv[ARG_WORKING_DIRECTORY]);
- g_free (new_argv);
-
- /* Check if gspawn-win32-helper couldn't be run */
- if (rc == -1 && saved_errno != 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to execute helper program (%s)"),
- g_strerror (saved_errno));
- goto cleanup_and_fail;
- }
-
- if (exit_status != NULL)
- {
- /* Synchronous case. Pass helper's report pipe back to caller,
- * which takes care of reading it after the grandchild has
- * finished.
- */
- g_assert (err_report != NULL);
- *err_report = child_err_report_pipe[0];
- write (helper_sync_pipe[1], " ", 1);
- close_and_invalidate (&helper_sync_pipe[1]);
- }
- else
- {
- /* Asynchronous case. We read the helper's report right away. */
- if (!read_helper_report (child_err_report_pipe[0], helper_report, error))
- goto cleanup_and_fail;
-
- close_and_invalidate (&child_err_report_pipe[0]);
-
- switch (helper_report[0])
- {
- case CHILD_NO_ERROR:
- if (child_handle && do_return_handle)
- {
- /* rc is our HANDLE for gspawn-win32-helper. It has
- * told us the HANDLE of its child. Duplicate that into
- * a HANDLE valid in this process.
- */
- if (!DuplicateHandle ((HANDLE) rc, (HANDLE) helper_report[1],
- GetCurrentProcess (), (LPHANDLE) child_handle,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- {
- char *emsg = g_win32_error_message (GetLastError ());
- g_print("%s\n", emsg);
- *child_handle = 0;
- }
- }
- else if (child_handle)
- *child_handle = 0;
- write (helper_sync_pipe[1], " ", 1);
- close_and_invalidate (&helper_sync_pipe[1]);
- break;
-
- default:
- write (helper_sync_pipe[1], " ", 1);
- close_and_invalidate (&helper_sync_pipe[1]);
- set_child_error (helper_report, working_directory, error);
- goto cleanup_and_fail;
- }
- }
-
- /* Success against all odds! return the information */
-
- if (standard_input)
- *standard_input = stdin_pipe[1];
- if (standard_output)
- *standard_output = stdout_pipe[0];
- if (standard_error)
- *standard_error = stderr_pipe[0];
- if (rc != -1)
- CloseHandle ((HANDLE) rc);
-
- return TRUE;
-
- cleanup_and_fail:
-
- if (rc != -1)
- CloseHandle ((HANDLE) rc);
- if (child_err_report_pipe[0] != -1)
- close (child_err_report_pipe[0]);
- if (child_err_report_pipe[1] != -1)
- close (child_err_report_pipe[1]);
- if (helper_sync_pipe[0] != -1)
- close (helper_sync_pipe[0]);
- if (helper_sync_pipe[1] != -1)
- close (helper_sync_pipe[1]);
- if (stdin_pipe[0] != -1)
- close (stdin_pipe[0]);
- if (stdin_pipe[1] != -1)
- close (stdin_pipe[1]);
- if (stdout_pipe[0] != -1)
- close (stdout_pipe[0]);
- if (stdout_pipe[1] != -1)
- close (stdout_pipe[1]);
- if (stderr_pipe[0] != -1)
- close (stderr_pipe[0]);
- if (stderr_pipe[1] != -1)
- close (stderr_pipe[1]);
-
- return FALSE;
-}
-
-gboolean
-g_spawn_sync_utf8 (const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- gchar **standard_output,
- gchar **standard_error,
- gint *exit_status,
- GError **error)
-{
- gint outpipe = -1;
- gint errpipe = -1;
- gint reportpipe = -1;
- GIOChannel *outchannel = NULL;
- GIOChannel *errchannel = NULL;
- GPollFD outfd, errfd;
- GPollFD fds[2];
- gint nfds;
- gint outindex = -1;
- gint errindex = -1;
- gint ret;
- GString *outstr = NULL;
- GString *errstr = NULL;
- gboolean failed;
- gint status;
-
- g_return_val_if_fail (argv != NULL, FALSE);
- g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
- g_return_val_if_fail (standard_output == NULL ||
- !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
- g_return_val_if_fail (standard_error == NULL ||
- !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
-
- /* Just to ensure segfaults if callers try to use
- * these when an error is reported.
- */
- if (standard_output)
- *standard_output = NULL;
-
- if (standard_error)
- *standard_error = NULL;
-
- if (!do_spawn_with_pipes (&status,
- FALSE,
- working_directory,
- argv,
- envp,
- flags,
- child_setup,
- NULL,
- NULL,
- standard_output ? &outpipe : NULL,
- standard_error ? &errpipe : NULL,
- &reportpipe,
- error))
- return FALSE;
-
- /* Read data from child. */
-
- failed = FALSE;
-
- if (outpipe >= 0)
- {
- outstr = g_string_new (NULL);
- outchannel = g_io_channel_win32_new_fd (outpipe);
- g_io_channel_set_encoding (outchannel, NULL, NULL);
- g_io_channel_set_buffered (outchannel, FALSE);
- g_io_channel_win32_make_pollfd (outchannel,
- G_IO_IN | G_IO_ERR | G_IO_HUP,
- &outfd);
- if (debug)
- g_print ("outfd=%p\n", (HANDLE) outfd.fd);
- }
-
- if (errpipe >= 0)
- {
- errstr = g_string_new (NULL);
- errchannel = g_io_channel_win32_new_fd (errpipe);
- g_io_channel_set_encoding (errchannel, NULL, NULL);
- g_io_channel_set_buffered (errchannel, FALSE);
- g_io_channel_win32_make_pollfd (errchannel,
- G_IO_IN | G_IO_ERR | G_IO_HUP,
- &errfd);
- if (debug)
- g_print ("errfd=%p\n", (HANDLE) errfd.fd);
- }
-
- /* Read data until we get EOF on all pipes. */
- while (!failed && (outpipe >= 0 || errpipe >= 0))
- {
- nfds = 0;
- if (outpipe >= 0)
- {
- fds[nfds] = outfd;
- outindex = nfds;
- nfds++;
- }
- if (errpipe >= 0)
- {
- fds[nfds] = errfd;
- errindex = nfds;
- nfds++;
- }
-
- if (debug)
- g_print ("g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
- nfds);
-
- ret = g_io_channel_win32_poll (fds, nfds, -1);
-
- if (ret < 0)
- {
- failed = TRUE;
-
- g_set_error_literal (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
- _("Unexpected error in g_io_channel_win32_poll() reading data from a child process"));
-
- break;
- }
-
- if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
- {
- switch (read_data (outstr, outchannel, error))
- {
- case READ_FAILED:
- if (debug)
- g_print ("g_spawn_sync: outchannel: READ_FAILED\n");
- failed = TRUE;
- break;
- case READ_EOF:
- if (debug)
- g_print ("g_spawn_sync: outchannel: READ_EOF\n");
- g_io_channel_unref (outchannel);
- outchannel = NULL;
- close_and_invalidate (&outpipe);
- break;
- default:
- if (debug)
- g_print ("g_spawn_sync: outchannel: OK\n");
- break;
- }
-
- if (failed)
- break;
- }
-
- if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
- {
- switch (read_data (errstr, errchannel, error))
- {
- case READ_FAILED:
- if (debug)
- g_print ("g_spawn_sync: errchannel: READ_FAILED\n");
- failed = TRUE;
- break;
- case READ_EOF:
- if (debug)
- g_print ("g_spawn_sync: errchannel: READ_EOF\n");
- g_io_channel_unref (errchannel);
- errchannel = NULL;
- close_and_invalidate (&errpipe);
- break;
- default:
- if (debug)
- g_print ("g_spawn_sync: errchannel: OK\n");
- break;
- }
-
- if (failed)
- break;
- }
- }
-
- if (reportpipe == -1)
- {
- /* No helper process, exit status of actual spawned process
- * already available.
- */
- if (exit_status)
- *exit_status = status;
- }
- else
- {
- /* Helper process was involved. Read its report now after the
- * grandchild has finished.
- */
- gintptr helper_report[2];
-
- if (!read_helper_report (reportpipe, helper_report, error))
- failed = TRUE;
- else
- {
- switch (helper_report[0])
- {
- case CHILD_NO_ERROR:
- if (exit_status)
- *exit_status = helper_report[1];
- break;
- default:
- set_child_error (helper_report, working_directory, error);
- failed = TRUE;
- break;
- }
- }
- close_and_invalidate (&reportpipe);
- }
-
-
- /* These should only be open still if we had an error. */
-
- if (outchannel != NULL)
- g_io_channel_unref (outchannel);
- if (errchannel != NULL)
- g_io_channel_unref (errchannel);
- if (outpipe >= 0)
- close_and_invalidate (&outpipe);
- if (errpipe >= 0)
- close_and_invalidate (&errpipe);
-
- if (failed)
- {
- if (outstr)
- g_string_free (outstr, TRUE);
- if (errstr)
- g_string_free (errstr, TRUE);
-
- return FALSE;
- }
- else
- {
- if (standard_output)
- *standard_output = g_string_free (outstr, FALSE);
-
- if (standard_error)
- *standard_error = g_string_free (errstr, FALSE);
-
- return TRUE;
- }
-}
-
-gboolean
-g_spawn_async_with_pipes_utf8 (const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_handle,
- gint *standard_input,
- gint *standard_output,
- gint *standard_error,
- GError **error)
-{
- g_return_val_if_fail (argv != NULL, FALSE);
- g_return_val_if_fail (standard_output == NULL ||
- !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
- g_return_val_if_fail (standard_error == NULL ||
- !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
- /* can't inherit stdin if we have an input pipe. */
- g_return_val_if_fail (standard_input == NULL ||
- !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
-
- return do_spawn_with_pipes (NULL,
- (flags & G_SPAWN_DO_NOT_REAP_CHILD),
- working_directory,
- argv,
- envp,
- flags,
- child_setup,
- child_handle,
- standard_input,
- standard_output,
- standard_error,
- NULL,
- error);
-}
-
-gboolean
-g_spawn_command_line_sync_utf8 (const gchar *command_line,
- gchar **standard_output,
- gchar **standard_error,
- gint *exit_status,
- GError **error)
-{
- gboolean retval;
- gchar **argv = 0;
-
- g_return_val_if_fail (command_line != NULL, FALSE);
-
- if (!g_shell_parse_argv (command_line,
- NULL, &argv,
- error))
- return FALSE;
-
- retval = g_spawn_sync_utf8 (NULL,
- argv,
- NULL,
- G_SPAWN_SEARCH_PATH,
- NULL,
- NULL,
- standard_output,
- standard_error,
- exit_status,
- error);
- g_strfreev (argv);
-
- return retval;
-}
-
-gboolean
-g_spawn_command_line_async_utf8 (const gchar *command_line,
- GError **error)
-{
- gboolean retval;
- gchar **argv = 0;
-
- g_return_val_if_fail (command_line != NULL, FALSE);
-
- if (!g_shell_parse_argv (command_line,
- NULL, &argv,
- error))
- return FALSE;
-
- retval = g_spawn_async_utf8 (NULL,
- argv,
- NULL,
- G_SPAWN_SEARCH_PATH,
- NULL,
- NULL,
- NULL,
- error);
- g_strfreev (argv);
-
- return retval;
-}
-
-void
-g_spawn_close_pid (GPid pid)
-{
- CloseHandle (pid);
-}
-
-#if !defined (_WIN64)
-
-/* Binary compatibility versions that take system codepage pathnames,
- * argument vectors and environments. These get used only by code
- * built against 2.8.1 or earlier. Code built against 2.8.2 or later
- * will use the _utf8 versions above (see the #defines in gspawn.h).
- */
-
-#undef g_spawn_async
-#undef g_spawn_async_with_pipes
-#undef g_spawn_sync
-#undef g_spawn_command_line_sync
-#undef g_spawn_command_line_async
-
-static gboolean
-setup_utf8_copies (const gchar *working_directory,
- gchar **utf8_working_directory,
- gchar **argv,
- gchar ***utf8_argv,
- gchar **envp,
- gchar ***utf8_envp,
- GError **error)
-{
- gint i, argc, envc;
-
- if (working_directory == NULL)
- *utf8_working_directory = NULL;
- else
- {
- GError *conv_error = NULL;
-
- *utf8_working_directory = g_locale_to_utf8 (working_directory, -1, NULL, NULL, &conv_error);
- if (*utf8_working_directory == NULL)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
- _("Invalid working directory: %s"),
- conv_error->message);
- g_error_free (conv_error);
- return FALSE;
- }
- }
-
- argc = 0;
- while (argv[argc])
- ++argc;
- *utf8_argv = g_new (gchar *, argc + 1);
- for (i = 0; i < argc; i++)
- {
- GError *conv_error = NULL;
-
- (*utf8_argv)[i] = g_locale_to_utf8 (argv[i], -1, NULL, NULL, &conv_error);
- if ((*utf8_argv)[i] == NULL)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in argument vector at %d: %s"),
- i, conv_error->message);
- g_error_free (conv_error);
-
- g_strfreev (*utf8_argv);
- *utf8_argv = NULL;
-
- g_free (*utf8_working_directory);
- *utf8_working_directory = NULL;
-
- return FALSE;
- }
- }
- (*utf8_argv)[argc] = NULL;
-
- if (envp == NULL)
- {
- *utf8_envp = NULL;
- }
- else
- {
- envc = 0;
- while (envp[envc])
- ++envc;
- *utf8_envp = g_new (gchar *, envc + 1);
- for (i = 0; i < envc; i++)
- {
- GError *conv_error = NULL;
-
- (*utf8_envp)[i] = g_locale_to_utf8 (envp[i], -1, NULL, NULL, &conv_error);
- if ((*utf8_envp)[i] == NULL)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in environment: %s"),
- conv_error->message);
- g_error_free (conv_error);
-
- g_strfreev (*utf8_envp);
- *utf8_envp = NULL;
-
- g_strfreev (*utf8_argv);
- *utf8_argv = NULL;
-
- g_free (*utf8_working_directory);
- *utf8_working_directory = NULL;
-
- return FALSE;
- }
- }
- (*utf8_envp)[envc] = NULL;
- }
- return TRUE;
-}
-
-static void
-free_utf8_copies (gchar *utf8_working_directory,
- gchar **utf8_argv,
- gchar **utf8_envp)
-{
- g_free (utf8_working_directory);
- g_strfreev (utf8_argv);
- g_strfreev (utf8_envp);
-}
-
-gboolean
-g_spawn_async_with_pipes (const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_handle,
- gint *standard_input,
- gint *standard_output,
- gint *standard_error,
- GError **error)
-{
- gchar *utf8_working_directory;
- gchar **utf8_argv;
- gchar **utf8_envp;
- gboolean retval;
-
- if (!setup_utf8_copies (working_directory, &utf8_working_directory,
- argv, &utf8_argv,
- envp, &utf8_envp,
- error))
- return FALSE;
-
- retval = g_spawn_async_with_pipes_utf8 (utf8_working_directory,
- utf8_argv, utf8_envp,
- flags, child_setup, user_data,
- child_handle,
- standard_input, standard_output, standard_error,
- error);
-
- free_utf8_copies (utf8_working_directory, utf8_argv, utf8_envp);
-
- return retval;
-}
-
-gboolean
-g_spawn_async (const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_handle,
- GError **error)
-{
- return g_spawn_async_with_pipes (working_directory,
- argv, envp,
- flags,
- child_setup,
- user_data,
- child_handle,
- NULL, NULL, NULL,
- error);
-}
-
-gboolean
-g_spawn_sync (const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- gchar **standard_output,
- gchar **standard_error,
- gint *exit_status,
- GError **error)
-{
- gchar *utf8_working_directory;
- gchar **utf8_argv;
- gchar **utf8_envp;
- gboolean retval;
-
- if (!setup_utf8_copies (working_directory, &utf8_working_directory,
- argv, &utf8_argv,
- envp, &utf8_envp,
- error))
- return FALSE;
-
- retval = g_spawn_sync_utf8 (utf8_working_directory,
- utf8_argv, utf8_envp,
- flags, child_setup, user_data,
- standard_output, standard_error, exit_status,
- error);
-
- free_utf8_copies (utf8_working_directory, utf8_argv, utf8_envp);
-
- return retval;
-}
-
-gboolean
-g_spawn_command_line_sync (const gchar *command_line,
- gchar **standard_output,
- gchar **standard_error,
- gint *exit_status,
- GError **error)
-{
- gboolean retval;
- gchar **argv = 0;
-
- g_return_val_if_fail (command_line != NULL, FALSE);
-
- if (!g_shell_parse_argv (command_line,
- NULL, &argv,
- error))
- return FALSE;
-
- retval = g_spawn_sync (NULL,
- argv,
- NULL,
- G_SPAWN_SEARCH_PATH,
- NULL,
- NULL,
- standard_output,
- standard_error,
- exit_status,
- error);
- g_strfreev (argv);
-
- return retval;
-}
-
-gboolean
-g_spawn_command_line_async (const gchar *command_line,
- GError **error)
-{
- gboolean retval;
- gchar **argv = 0;
-
- g_return_val_if_fail (command_line != NULL, FALSE);
-
- if (!g_shell_parse_argv (command_line,
- NULL, &argv,
- error))
- return FALSE;
-
- retval = g_spawn_async (NULL,
- argv,
- NULL,
- G_SPAWN_SEARCH_PATH,
- NULL,
- NULL,
- NULL,
- error);
- g_strfreev (argv);
-
- return retval;
-}
-
-#endif /* !_WIN64 */
-
-#endif /* !GSPAWN_HELPER */
-
-#define __G_SPAWN_C__
-#include "galiasdef.c"
diff --git a/glib/gspawn.c b/glib/gspawn.c
deleted file mode 100644
index 406ef2b4b..000000000
--- a/glib/gspawn.c
+++ /dev/null
@@ -1,1671 +0,0 @@
-/* gspawn.c - Process launching
- *
- * Copyright 2000 Red Hat, Inc.
- * g_execvpe implementation based on GNU libc execvp:
- * Copyright 1991, 92, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
- *
- * GLib 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 of the
- * License, or (at your option) any later version.
- *
- * GLib 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 GLib; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <string.h>
-#include <stdlib.h> /* for fdwalk */
-#include <dirent.h>
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif /* HAVE_SYS_SELECT_H */
-
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif /* HAVE_SYS_RESOURCE_H */
-
-#include "glib.h"
-#include "glibintl.h"
-#include "galias.h"
-
-static gint g_execute (const gchar *file,
- gchar **argv,
- gchar **envp,
- gboolean search_path);
-
-static gboolean make_pipe (gint p[2],
- GError **error);
-static gboolean fork_exec_with_pipes (gboolean intermediate_child,
- const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- gboolean close_descriptors,
- gboolean search_path,
- gboolean stdout_to_null,
- gboolean stderr_to_null,
- gboolean child_inherits_stdin,
- gboolean file_and_argv_zero,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_pid,
- gint *standard_input,
- gint *standard_output,
- gint *standard_error,
- GError **error);
-
-GQuark
-g_spawn_error_quark (void)
-{
- return g_quark_from_static_string ("g-exec-error-quark");
-}
-
-/**
- * g_spawn_async:
- * @working_directory: child's current working directory, or %NULL to inherit parent's
- * @argv: child's argument vector
- * @envp: child's environment, or %NULL to inherit parent's
- * @flags: flags from #GSpawnFlags
- * @child_setup: function to run in the child just before exec()
- * @user_data: user data for @child_setup
- * @child_pid: return location for child process reference, or %NULL
- * @error: return location for error
- *
- * See g_spawn_async_with_pipes() for a full description; this function
- * simply calls the g_spawn_async_with_pipes() without any pipes.
- *
- * You should call g_spawn_close_pid() on the returned child process
- * reference when you don't need it any more.
- *
- * <note><para>
- * If you are writing a GTK+ application, and the program you
- * are spawning is a graphical application, too, then you may
- * want to use gdk_spawn_on_screen() instead to ensure that
- * the spawned program opens its windows on the right screen.
- * </para></note>
- *
- * <note><para> Note that the returned @child_pid on Windows is a
- * handle to the child process and not its identifier. Process handles
- * and process identifiers are different concepts on Windows.
- * </para></note>
- *
- * Return value: %TRUE on success, %FALSE if error is set
- **/
-gboolean
-g_spawn_async (const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_pid,
- GError **error)
-{
- g_return_val_if_fail (argv != NULL, FALSE);
-
- return g_spawn_async_with_pipes (working_directory,
- argv, envp,
- flags,
- child_setup,
- user_data,
- child_pid,
- NULL, NULL, NULL,
- error);
-}
-
-/* Avoids a danger in threaded situations (calling close()
- * on a file descriptor twice, and another thread has
- * re-opened it since the first close)
- */
-static gint
-close_and_invalidate (gint *fd)
-{
- gint ret;
-
- if (*fd < 0)
- return -1;
- else
- {
- ret = close (*fd);
- *fd = -1;
- }
-
- return ret;
-}
-
-/* Some versions of OS X define READ_OK in public headers */
-#undef READ_OK
-
-typedef enum
-{
- READ_FAILED = 0, /* FALSE */
- READ_OK,
- READ_EOF
-} ReadResult;
-
-static ReadResult
-read_data (GString *str,
- gint fd,
- GError **error)
-{
- gssize bytes;
- gchar buf[4096];
-
- again:
-
- bytes = read (fd, buf, 4096);
-
- if (bytes == 0)
- return READ_EOF;
- else if (bytes > 0)
- {
- g_string_append_len (str, buf, bytes);
- return READ_OK;
- }
- else if (bytes < 0 && errno == EINTR)
- goto again;
- else if (bytes < 0)
- {
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_READ,
- _("Failed to read data from child process (%s)"),
- g_strerror (errno));
-
- return READ_FAILED;
- }
- else
- return READ_OK;
-}
-
-/**
- * g_spawn_sync:
- * @working_directory: child's current working directory, or %NULL to inherit parent's
- * @argv: child's argument vector
- * @envp: child's environment, or %NULL to inherit parent's
- * @flags: flags from #GSpawnFlags
- * @child_setup: function to run in the child just before exec()
- * @user_data: user data for @child_setup
- * @standard_output: return location for child output, or %NULL
- * @standard_error: return location for child error messages, or %NULL
- * @exit_status: return location for child exit status, as returned by waitpid(), or %NULL
- * @error: return location for error, or %NULL
- *
- * Executes a child synchronously (waits for the child to exit before returning).
- * All output from the child is stored in @standard_output and @standard_error,
- * if those parameters are non-%NULL. Note that you must set the
- * %G_SPAWN_STDOUT_TO_DEV_NULL and %G_SPAWN_STDERR_TO_DEV_NULL flags when
- * passing %NULL for @standard_output and @standard_error.
- * If @exit_status is non-%NULL, the exit status of the child is stored
- * there as it would be returned by waitpid(); standard UNIX macros such
- * as WIFEXITED() and WEXITSTATUS() must be used to evaluate the exit status.
- * Note that this function call waitpid() even if @exit_status is %NULL, and
- * does not accept the %G_SPAWN_DO_NOT_REAP_CHILD flag.
- * If an error occurs, no data is returned in @standard_output,
- * @standard_error, or @exit_status.
- *
- * This function calls g_spawn_async_with_pipes() internally; see that
- * function for full details on the other parameters and details on
- * how these functions work on Windows.
- *
- * Return value: %TRUE on success, %FALSE if an error was set.
- **/
-gboolean
-g_spawn_sync (const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- gchar **standard_output,
- gchar **standard_error,
- gint *exit_status,
- GError **error)
-{
- gint outpipe = -1;
- gint errpipe = -1;
- GPid pid;
- fd_set fds;
- gint ret;
- GString *outstr = NULL;
- GString *errstr = NULL;
- gboolean failed;
- gint status;
-
- g_return_val_if_fail (argv != NULL, FALSE);
- g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
- g_return_val_if_fail (standard_output == NULL ||
- !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
- g_return_val_if_fail (standard_error == NULL ||
- !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
-
- /* Just to ensure segfaults if callers try to use
- * these when an error is reported.
- */
- if (standard_output)
- *standard_output = NULL;
-
- if (standard_error)
- *standard_error = NULL;
-
- if (!fork_exec_with_pipes (FALSE,
- working_directory,
- argv,
- envp,
- !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
- (flags & G_SPAWN_SEARCH_PATH) != 0,
- (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
- (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
- (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
- (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
- child_setup,
- user_data,
- &pid,
- NULL,
- standard_output ? &outpipe : NULL,
- standard_error ? &errpipe : NULL,
- error))
- return FALSE;
-
- /* Read data from child. */
-
- failed = FALSE;
-
- if (outpipe >= 0)
- {
- outstr = g_string_new (NULL);
- }
-
- if (errpipe >= 0)
- {
- errstr = g_string_new (NULL);
- }
-
- /* Read data until we get EOF on both pipes. */
- while (!failed &&
- (outpipe >= 0 ||
- errpipe >= 0))
- {
- ret = 0;
-
- FD_ZERO (&fds);
- if (outpipe >= 0)
- FD_SET (outpipe, &fds);
- if (errpipe >= 0)
- FD_SET (errpipe, &fds);
-
- ret = select (MAX (outpipe, errpipe) + 1,
- &fds,
- NULL, NULL,
- NULL /* no timeout */);
-
- if (ret < 0 && errno != EINTR)
- {
- failed = TRUE;
-
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_READ,
- _("Unexpected error in select() reading data from a child process (%s)"),
- g_strerror (errno));
-
- break;
- }
-
- if (outpipe >= 0 && FD_ISSET (outpipe, &fds))
- {
- switch (read_data (outstr, outpipe, error))
- {
- case READ_FAILED:
- failed = TRUE;
- break;
- case READ_EOF:
- close_and_invalidate (&outpipe);
- outpipe = -1;
- break;
- default:
- break;
- }
-
- if (failed)
- break;
- }
-
- if (errpipe >= 0 && FD_ISSET (errpipe, &fds))
- {
- switch (read_data (errstr, errpipe, error))
- {
- case READ_FAILED:
- failed = TRUE;
- break;
- case READ_EOF:
- close_and_invalidate (&errpipe);
- errpipe = -1;
- break;
- default:
- break;
- }
-
- if (failed)
- break;
- }
- }
-
- /* These should only be open still if we had an error. */
-
- if (outpipe >= 0)
- close_and_invalidate (&outpipe);
- if (errpipe >= 0)
- close_and_invalidate (&errpipe);
-
- /* Wait for child to exit, even if we have
- * an error pending.
- */
- again:
-
- ret = waitpid (pid, &status, 0);
-
- if (ret < 0)
- {
- if (errno == EINTR)
- goto again;
- else if (errno == ECHILD)
- {
- if (exit_status)
- {
- g_warning ("In call to g_spawn_sync(), exit status of a child process was requested but SIGCHLD action was set to SIG_IGN and ECHILD was received by waitpid(), so exit status can't be returned. This is a bug in the program calling g_spawn_sync(); either don't request the exit status, or don't set the SIGCHLD action.");
- }
- else
- {
- /* We don't need the exit status. */
- }
- }
- else
- {
- if (!failed) /* avoid error pileups */
- {
- failed = TRUE;
-
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_READ,
- _("Unexpected error in waitpid() (%s)"),
- g_strerror (errno));
- }
- }
- }
-
- if (failed)
- {
- if (outstr)
- g_string_free (outstr, TRUE);
- if (errstr)
- g_string_free (errstr, TRUE);
-
- return FALSE;
- }
- else
- {
- if (exit_status)
- *exit_status = status;
-
- if (standard_output)
- *standard_output = g_string_free (outstr, FALSE);
-
- if (standard_error)
- *standard_error = g_string_free (errstr, FALSE);
-
- return TRUE;
- }
-}
-
-/**
- * g_spawn_async_with_pipes:
- * @working_directory: child's current working directory, or %NULL to inherit parent's, in the GLib file name encoding
- * @argv: child's argument vector, in the GLib file name encoding
- * @envp: child's environment, or %NULL to inherit parent's, in the GLib file name encoding
- * @flags: flags from #GSpawnFlags
- * @child_setup: function to run in the child just before exec()
- * @user_data: user data for @child_setup
- * @child_pid: return location for child process ID, or %NULL
- * @standard_input: return location for file descriptor to write to child's stdin, or %NULL
- * @standard_output: return location for file descriptor to read child's stdout, or %NULL
- * @standard_error: return location for file descriptor to read child's stderr, or %NULL
- * @error: return location for error
- *
- * Executes a child program asynchronously (your program will not
- * block waiting for the child to exit). The child program is
- * specified by the only argument that must be provided, @argv. @argv
- * should be a %NULL-terminated array of strings, to be passed as the
- * argument vector for the child. The first string in @argv is of
- * course the name of the program to execute. By default, the name of
- * the program must be a full path; the <envar>PATH</envar> shell variable
- * will only be searched if you pass the %G_SPAWN_SEARCH_PATH flag.
- *
- * On Windows, note that all the string or string vector arguments to
- * this function and the other g_spawn*() functions are in UTF-8, the
- * GLib file name encoding. Unicode characters that are not part of
- * the system codepage passed in these arguments will be correctly
- * available in the spawned program only if it uses wide character API
- * to retrieve its command line. For C programs built with Microsoft's
- * tools it is enough to make the program have a wmain() instead of
- * main(). wmain() has a wide character argument vector as parameter.
- *
- * At least currently, mingw doesn't support wmain(), so if you use
- * mingw to develop the spawned program, it will have to call the
- * undocumented function __wgetmainargs() to get the wide character
- * argument vector and environment. See gspawn-win32-helper.c in the
- * GLib sources or init.c in the mingw runtime sources for a prototype
- * for that function. Alternatively, you can retrieve the Win32 system
- * level wide character command line passed to the spawned program
- * using the GetCommandLineW() function.
- *
- * On Windows the low-level child process creation API
- * <function>CreateProcess()</function> doesn't use argument vectors,
- * but a command line. The C runtime library's
- * <function>spawn*()</function> family of functions (which
- * g_spawn_async_with_pipes() eventually calls) paste the argument
- * vector elements together into a command line, and the C runtime startup code
- * does a corresponding reconstruction of an argument vector from the
- * command line, to be passed to main(). Complications arise when you have
- * argument vector elements that contain spaces of double quotes. The
- * <function>spawn*()</function> functions don't do any quoting or
- * escaping, but on the other hand the startup code does do unquoting
- * and unescaping in order to enable receiving arguments with embedded
- * spaces or double quotes. To work around this asymmetry,
- * g_spawn_async_with_pipes() will do quoting and escaping on argument
- * vector elements that need it before calling the C runtime
- * spawn() function.
- *
- * The returned @child_pid on Windows is a handle to the child
- * process, not its identifier. Process handles and process
- * identifiers are different concepts on Windows.
- *
- * @envp is a %NULL-terminated array of strings, where each string
- * has the form <literal>KEY=VALUE</literal>. This will become
- * the child's environment. If @envp is %NULL, the child inherits its
- * parent's environment.
- *
- * @flags should be the bitwise OR of any flags you want to affect the
- * function's behaviour. The %G_SPAWN_DO_NOT_REAP_CHILD means that
- * the child will not automatically be reaped; you must use a
- * #GChildWatch source to be notified about the death of the child
- * process. Eventually you must call g_spawn_close_pid() on the
- * @child_pid, in order to free resources which may be associated
- * with the child process. (On Unix, using a #GChildWatch source is
- * equivalent to calling waitpid() or handling the %SIGCHLD signal
- * manually. On Windows, calling g_spawn_close_pid() is equivalent
- * to calling CloseHandle() on the process handle returned in
- * @child_pid).
- *
- * %G_SPAWN_LEAVE_DESCRIPTORS_OPEN means that the parent's open file
- * descriptors will be inherited by the child; otherwise all
- * descriptors except stdin/stdout/stderr will be closed before
- * calling exec() in the child. %G_SPAWN_SEARCH_PATH
- * means that <literal>argv[0]</literal> need not be an absolute path, it
- * will be looked for in the user's <envar>PATH</envar>.
- * %G_SPAWN_STDOUT_TO_DEV_NULL means that the child's standard output will
- * be discarded, instead of going to the same location as the parent's
- * standard output. If you use this flag, @standard_output must be %NULL.
- * %G_SPAWN_STDERR_TO_DEV_NULL means that the child's standard error
- * will be discarded, instead of going to the same location as the parent's
- * standard error. If you use this flag, @standard_error must be %NULL.
- * %G_SPAWN_CHILD_INHERITS_STDIN means that the child will inherit the parent's
- * standard input (by default, the child's standard input is attached to
- * /dev/null). If you use this flag, @standard_input must be %NULL.
- * %G_SPAWN_FILE_AND_ARGV_ZERO means that the first element of @argv is
- * the file to execute, while the remaining elements are the
- * actual argument vector to pass to the file. Normally
- * g_spawn_async_with_pipes() uses @argv[0] as the file to execute, and
- * passes all of @argv to the child.
- *
- * @child_setup and @user_data are a function and user data. On POSIX
- * platforms, the function is called in the child after GLib has
- * performed all the setup it plans to perform (including creating
- * pipes, closing file descriptors, etc.) but before calling
- * exec(). That is, @child_setup is called just
- * before calling exec() in the child. Obviously
- * actions taken in this function will only affect the child, not the
- * parent.
- *
- * On Windows, there is no separate fork() and exec()
- * functionality. Child processes are created and run with a single
- * API call, CreateProcess(). There is no sensible thing @child_setup
- * could be used for on Windows so it is ignored and not called.
- *
- * If non-%NULL, @child_pid will on Unix be filled with the child's
- * process ID. You can use the process ID to send signals to the
- * child, or to use g_child_watch_add() (or waitpid()) if you specified the
- * %G_SPAWN_DO_NOT_REAP_CHILD flag. On Windows, @child_pid will be
- * filled with a handle to the child process only if you specified the
- * %G_SPAWN_DO_NOT_REAP_CHILD flag. You can then access the child
- * process using the Win32 API, for example wait for its termination
- * with the <function>WaitFor*()</function> functions, or examine its
- * exit code with GetExitCodeProcess(). You should close the handle
- * with CloseHandle() or g_spawn_close_pid() when you no longer need it.
- *
- * If non-%NULL, the @standard_input, @standard_output, @standard_error
- * locations will be filled with file descriptors for writing to the child's
- * standard input or reading from its standard output or standard error.
- * The caller of g_spawn_async_with_pipes() must close these file descriptors
- * when they are no longer in use. If these parameters are %NULL, the corresponding
- * pipe won't be created.
- *
- * If @standard_input is NULL, the child's standard input is attached to
- * /dev/null unless %G_SPAWN_CHILD_INHERITS_STDIN is set.
- *
- * If @standard_error is NULL, the child's standard error goes to the same
- * location as the parent's standard error unless %G_SPAWN_STDERR_TO_DEV_NULL
- * is set.
- *
- * If @standard_output is NULL, the child's standard output goes to the same
- * location as the parent's standard output unless %G_SPAWN_STDOUT_TO_DEV_NULL
- * is set.
- *
- * @error can be %NULL to ignore errors, or non-%NULL to report errors.
- * If an error is set, the function returns %FALSE. Errors
- * are reported even if they occur in the child (for example if the
- * executable in <literal>argv[0]</literal> is not found). Typically
- * the <literal>message</literal> field of returned errors should be displayed
- * to users. Possible errors are those from the #G_SPAWN_ERROR domain.
- *
- * If an error occurs, @child_pid, @standard_input, @standard_output,
- * and @standard_error will not be filled with valid values.
- *
- * If @child_pid is not %NULL and an error does not occur then the returned
- * process reference must be closed using g_spawn_close_pid().
- *
- * <note><para>
- * If you are writing a GTK+ application, and the program you
- * are spawning is a graphical application, too, then you may
- * want to use gdk_spawn_on_screen_with_pipes() instead to ensure that
- * the spawned program opens its windows on the right screen.
- * </para></note>
- *
- * Return value: %TRUE on success, %FALSE if an error was set
- **/
-gboolean
-g_spawn_async_with_pipes (const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_pid,
- gint *standard_input,
- gint *standard_output,
- gint *standard_error,
- GError **error)
-{
- g_return_val_if_fail (argv != NULL, FALSE);
- g_return_val_if_fail (standard_output == NULL ||
- !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
- g_return_val_if_fail (standard_error == NULL ||
- !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
- /* can't inherit stdin if we have an input pipe. */
- g_return_val_if_fail (standard_input == NULL ||
- !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
-
- return fork_exec_with_pipes (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
- working_directory,
- argv,
- envp,
- !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
- (flags & G_SPAWN_SEARCH_PATH) != 0,
- (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
- (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
- (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
- (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
- child_setup,
- user_data,
- child_pid,
- standard_input,
- standard_output,
- standard_error,
- error);
-}
-
-/**
- * g_spawn_command_line_sync:
- * @command_line: a command line
- * @standard_output: return location for child output
- * @standard_error: return location for child errors
- * @exit_status: return location for child exit status, as returned by waitpid()
- * @error: return location for errors
- *
- * A simple version of g_spawn_sync() with little-used parameters
- * removed, taking a command line instead of an argument vector. See
- * g_spawn_sync() for full details. @command_line will be parsed by
- * g_shell_parse_argv(). Unlike g_spawn_sync(), the %G_SPAWN_SEARCH_PATH flag
- * is enabled. Note that %G_SPAWN_SEARCH_PATH can have security
- * implications, so consider using g_spawn_sync() directly if
- * appropriate. Possible errors are those from g_spawn_sync() and those
- * from g_shell_parse_argv().
- *
- * If @exit_status is non-%NULL, the exit status of the child is stored there as
- * it would be returned by waitpid(); standard UNIX macros such as WIFEXITED()
- * and WEXITSTATUS() must be used to evaluate the exit status.
- *
- * On Windows, please note the implications of g_shell_parse_argv()
- * parsing @command_line. Parsing is done according to Unix shell rules, not
- * Windows command interpreter rules.
- * Space is a separator, and backslashes are
- * special. Thus you cannot simply pass a @command_line containing
- * canonical Windows paths, like "c:\\program files\\app\\app.exe", as
- * the backslashes will be eaten, and the space will act as a
- * separator. You need to enclose such paths with single quotes, like
- * "'c:\\program files\\app\\app.exe' 'e:\\folder\\argument.txt'".
- *
- * Return value: %TRUE on success, %FALSE if an error was set
- **/
-gboolean
-g_spawn_command_line_sync (const gchar *command_line,
- gchar **standard_output,
- gchar **standard_error,
- gint *exit_status,
- GError **error)
-{
- gboolean retval;
- gchar **argv = NULL;
-
- g_return_val_if_fail (command_line != NULL, FALSE);
-
- if (!g_shell_parse_argv (command_line,
- NULL, &argv,
- error))
- return FALSE;
-
- retval = g_spawn_sync (NULL,
- argv,
- NULL,
- G_SPAWN_SEARCH_PATH,
- NULL,
- NULL,
- standard_output,
- standard_error,
- exit_status,
- error);
- g_strfreev (argv);
-
- return retval;
-}
-
-/**
- * g_spawn_command_line_async:
- * @command_line: a command line
- * @error: return location for errors
- *
- * A simple version of g_spawn_async() that parses a command line with
- * g_shell_parse_argv() and passes it to g_spawn_async(). Runs a
- * command line in the background. Unlike g_spawn_async(), the
- * %G_SPAWN_SEARCH_PATH flag is enabled, other flags are not. Note
- * that %G_SPAWN_SEARCH_PATH can have security implications, so
- * consider using g_spawn_async() directly if appropriate. Possible
- * errors are those from g_shell_parse_argv() and g_spawn_async().
- *
- * The same concerns on Windows apply as for g_spawn_command_line_sync().
- *
- * Return value: %TRUE on success, %FALSE if error is set.
- **/
-gboolean
-g_spawn_command_line_async (const gchar *command_line,
- GError **error)
-{
- gboolean retval;
- gchar **argv = NULL;
-
- g_return_val_if_fail (command_line != NULL, FALSE);
-
- if (!g_shell_parse_argv (command_line,
- NULL, &argv,
- error))
- return FALSE;
-
- retval = g_spawn_async (NULL,
- argv,
- NULL,
- G_SPAWN_SEARCH_PATH,
- NULL,
- NULL,
- NULL,
- error);
- g_strfreev (argv);
-
- return retval;
-}
-
-static gint
-exec_err_to_g_error (gint en)
-{
- switch (en)
- {
-#ifdef EACCES
- case EACCES:
- return G_SPAWN_ERROR_ACCES;
- break;
-#endif
-
-#ifdef EPERM
- case EPERM:
- return G_SPAWN_ERROR_PERM;
- break;
-#endif
-
-#ifdef E2BIG
- case E2BIG:
- return G_SPAWN_ERROR_2BIG;
- break;
-#endif
-
-#ifdef ENOEXEC
- case ENOEXEC:
- return G_SPAWN_ERROR_NOEXEC;
- break;
-#endif
-
-#ifdef ENAMETOOLONG
- case ENAMETOOLONG:
- return G_SPAWN_ERROR_NAMETOOLONG;
- break;
-#endif
-
-#ifdef ENOENT
- case ENOENT:
- return G_SPAWN_ERROR_NOENT;
- break;
-#endif
-
-#ifdef ENOMEM
- case ENOMEM:
- return G_SPAWN_ERROR_NOMEM;
- break;
-#endif
-
-#ifdef ENOTDIR
- case ENOTDIR:
- return G_SPAWN_ERROR_NOTDIR;
- break;
-#endif
-
-#ifdef ELOOP
- case ELOOP:
- return G_SPAWN_ERROR_LOOP;
- break;
-#endif
-
-#ifdef ETXTBUSY
- case ETXTBUSY:
- return G_SPAWN_ERROR_TXTBUSY;
- break;
-#endif
-
-#ifdef EIO
- case EIO:
- return G_SPAWN_ERROR_IO;
- break;
-#endif
-
-#ifdef ENFILE
- case ENFILE:
- return G_SPAWN_ERROR_NFILE;
- break;
-#endif
-
-#ifdef EMFILE
- case EMFILE:
- return G_SPAWN_ERROR_MFILE;
- break;
-#endif
-
-#ifdef EINVAL
- case EINVAL:
- return G_SPAWN_ERROR_INVAL;
- break;
-#endif
-
-#ifdef EISDIR
- case EISDIR:
- return G_SPAWN_ERROR_ISDIR;
- break;
-#endif
-
-#ifdef ELIBBAD
- case ELIBBAD:
- return G_SPAWN_ERROR_LIBBAD;
- break;
-#endif
-
- default:
- return G_SPAWN_ERROR_FAILED;
- break;
- }
-}
-
-static gssize
-write_all (gint fd, gconstpointer vbuf, gsize to_write)
-{
- gchar *buf = (gchar *) vbuf;
-
- while (to_write > 0)
- {
- gssize count = write (fd, buf, to_write);
- if (count < 0)
- {
- if (errno != EINTR)
- return FALSE;
- }
- else
- {
- to_write -= count;
- buf += count;
- }
- }
-
- return TRUE;
-}
-
-G_GNUC_NORETURN
-static void
-write_err_and_exit (gint fd, gint msg)
-{
- gint en = errno;
-
- write_all (fd, &msg, sizeof(msg));
- write_all (fd, &en, sizeof(en));
-
- _exit (1);
-}
-
-static int
-set_cloexec (void *data, gint fd)
-{
- if (fd >= GPOINTER_TO_INT (data))
- fcntl (fd, F_SETFD, FD_CLOEXEC);
-
- return 0;
-}
-
-#ifndef HAVE_FDWALK
-static int
-fdwalk (int (*cb)(void *data, int fd), void *data)
-{
- gint open_max;
- gint fd;
- gint res = 0;
-
-#ifdef HAVE_SYS_RESOURCE_H
- struct rlimit rl;
-#endif
-
-#ifdef __linux__
- DIR *d;
-
- if ((d = opendir("/proc/self/fd"))) {
- struct dirent *de;
-
- while ((de = readdir(d))) {
- glong l;
- gchar *e = NULL;
-
- if (de->d_name[0] == '.')
- continue;
-
- errno = 0;
- l = strtol(de->d_name, &e, 10);
- if (errno != 0 || !e || *e)
- continue;
-
- fd = (gint) l;
-
- if ((glong) fd != l)
- continue;
-
- if (fd == dirfd(d))
- continue;
-
- if ((res = cb (data, fd)) != 0)
- break;
- }
-
- closedir(d);
- return res;
- }
-
- /* If /proc is not mounted or not accessible we fall back to the old
- * rlimit trick */
-
-#endif
-
-#ifdef HAVE_SYS_RESOURCE_H
-
- if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY)
- open_max = rl.rlim_max;
- else
-#endif
- open_max = sysconf (_SC_OPEN_MAX);
-
- for (fd = 0; fd < open_max; fd++)
- if ((res = cb (data, fd)) != 0)
- break;
-
- return res;
-}
-#endif
-
-static gint
-sane_dup2 (gint fd1, gint fd2)
-{
- gint ret;
-
- retry:
- ret = dup2 (fd1, fd2);
- if (ret < 0 && errno == EINTR)
- goto retry;
-
- return ret;
-}
-
-enum
-{
- CHILD_CHDIR_FAILED,
- CHILD_EXEC_FAILED,
- CHILD_DUP2_FAILED,
- CHILD_FORK_FAILED
-};
-
-static void
-do_exec (gint child_err_report_fd,
- gint stdin_fd,
- gint stdout_fd,
- gint stderr_fd,
- const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- gboolean close_descriptors,
- gboolean search_path,
- gboolean stdout_to_null,
- gboolean stderr_to_null,
- gboolean child_inherits_stdin,
- gboolean file_and_argv_zero,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data)
-{
- if (working_directory && chdir (working_directory) < 0)
- write_err_and_exit (child_err_report_fd,
- CHILD_CHDIR_FAILED);
-
- /* Close all file descriptors but stdin stdout and stderr as
- * soon as we exec. Note that this includes
- * child_err_report_fd, which keeps the parent from blocking
- * forever on the other end of that pipe.
- */
- if (close_descriptors)
- {
- fdwalk (set_cloexec, GINT_TO_POINTER(3));
- }
- else
- {
- /* We need to do child_err_report_fd anyway */
- set_cloexec (GINT_TO_POINTER(0), child_err_report_fd);
- }
-
- /* Redirect pipes as required */
-
- if (stdin_fd >= 0)
- {
- /* dup2 can't actually fail here I don't think */
-
- if (sane_dup2 (stdin_fd, 0) < 0)
- write_err_and_exit (child_err_report_fd,
- CHILD_DUP2_FAILED);
-
- /* ignore this if it doesn't work */
- close_and_invalidate (&stdin_fd);
- }
- else if (!child_inherits_stdin)
- {
- /* Keep process from blocking on a read of stdin */
- gint read_null = open ("/dev/null", O_RDONLY);
- sane_dup2 (read_null, 0);
- close_and_invalidate (&read_null);
- }
-
- if (stdout_fd >= 0)
- {
- /* dup2 can't actually fail here I don't think */
-
- if (sane_dup2 (stdout_fd, 1) < 0)
- write_err_and_exit (child_err_report_fd,
- CHILD_DUP2_FAILED);
-
- /* ignore this if it doesn't work */
- close_and_invalidate (&stdout_fd);
- }
- else if (stdout_to_null)
- {
- gint write_null = open ("/dev/null", O_WRONLY);
- sane_dup2 (write_null, 1);
- close_and_invalidate (&write_null);
- }
-
- if (stderr_fd >= 0)
- {
- /* dup2 can't actually fail here I don't think */
-
- if (sane_dup2 (stderr_fd, 2) < 0)
- write_err_and_exit (child_err_report_fd,
- CHILD_DUP2_FAILED);
-
- /* ignore this if it doesn't work */
- close_and_invalidate (&stderr_fd);
- }
- else if (stderr_to_null)
- {
- gint write_null = open ("/dev/null", O_WRONLY);
- sane_dup2 (write_null, 2);
- close_and_invalidate (&write_null);
- }
-
- /* Call user function just before we exec */
- if (child_setup)
- {
- (* child_setup) (user_data);
- }
-
- g_execute (argv[0],
- file_and_argv_zero ? argv + 1 : argv,
- envp, search_path);
-
- /* Exec failed */
- write_err_and_exit (child_err_report_fd,
- CHILD_EXEC_FAILED);
-}
-
-static gboolean
-read_ints (int fd,
- gint* buf,
- gint n_ints_in_buf,
- gint *n_ints_read,
- GError **error)
-{
- gsize bytes = 0;
-
- while (TRUE)
- {
- gssize chunk;
-
- if (bytes >= sizeof(gint)*2)
- break; /* give up, who knows what happened, should not be
- * possible.
- */
-
- again:
- chunk = read (fd,
- ((gchar*)buf) + bytes,
- sizeof(gint) * n_ints_in_buf - bytes);
- if (chunk < 0 && errno == EINTR)
- goto again;
-
- if (chunk < 0)
- {
- /* Some weird shit happened, bail out */
-
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_FAILED,
- _("Failed to read from child pipe (%s)"),
- g_strerror (errno));
-
- return FALSE;
- }
- else if (chunk == 0)
- break; /* EOF */
- else /* chunk > 0 */
- bytes += chunk;
- }
-
- *n_ints_read = (gint)(bytes / sizeof(gint));
-
- return TRUE;
-}
-
-static gboolean
-fork_exec_with_pipes (gboolean intermediate_child,
- const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- gboolean close_descriptors,
- gboolean search_path,
- gboolean stdout_to_null,
- gboolean stderr_to_null,
- gboolean child_inherits_stdin,
- gboolean file_and_argv_zero,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_pid,
- gint *standard_input,
- gint *standard_output,
- gint *standard_error,
- GError **error)
-{
- GPid pid = -1;
- gint stdin_pipe[2] = { -1, -1 };
- gint stdout_pipe[2] = { -1, -1 };
- gint stderr_pipe[2] = { -1, -1 };
- gint child_err_report_pipe[2] = { -1, -1 };
- gint child_pid_report_pipe[2] = { -1, -1 };
- gint status;
-
- if (!make_pipe (child_err_report_pipe, error))
- return FALSE;
-
- if (intermediate_child && !make_pipe (child_pid_report_pipe, error))
- goto cleanup_and_fail;
-
- if (standard_input && !make_pipe (stdin_pipe, error))
- goto cleanup_and_fail;
-
- if (standard_output && !make_pipe (stdout_pipe, error))
- goto cleanup_and_fail;
-
- if (standard_error && !make_pipe (stderr_pipe, error))
- goto cleanup_and_fail;
-
- pid = fork ();
-
- if (pid < 0)
- {
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_FORK,
- _("Failed to fork (%s)"),
- g_strerror (errno));
-
- goto cleanup_and_fail;
- }
- else if (pid == 0)
- {
- /* Immediate child. This may or may not be the child that
- * actually execs the new process.
- */
-
- /* Be sure we crash if the parent exits
- * and we write to the err_report_pipe
- */
- signal (SIGPIPE, SIG_DFL);
-
- /* Close the parent's end of the pipes;
- * not needed in the close_descriptors case,
- * though
- */
- close_and_invalidate (&child_err_report_pipe[0]);
- close_and_invalidate (&child_pid_report_pipe[0]);
- close_and_invalidate (&stdin_pipe[1]);
- close_and_invalidate (&stdout_pipe[0]);
- close_and_invalidate (&stderr_pipe[0]);
-
- if (intermediate_child)
- {
- /* We need to fork an intermediate child that launches the
- * final child. The purpose of the intermediate child
- * is to exit, so we can waitpid() it immediately.
- * Then the grandchild will not become a zombie.
- */
- GPid grandchild_pid;
-
- grandchild_pid = fork ();
-
- if (grandchild_pid < 0)
- {
- /* report -1 as child PID */
- write_all (child_pid_report_pipe[1], &grandchild_pid,
- sizeof(grandchild_pid));
-
- write_err_and_exit (child_err_report_pipe[1],
- CHILD_FORK_FAILED);
- }
- else if (grandchild_pid == 0)
- {
- do_exec (child_err_report_pipe[1],
- stdin_pipe[0],
- stdout_pipe[1],
- stderr_pipe[1],
- working_directory,
- argv,
- envp,
- close_descriptors,
- search_path,
- stdout_to_null,
- stderr_to_null,
- child_inherits_stdin,
- file_and_argv_zero,
- child_setup,
- user_data);
- }
- else
- {
- write_all (child_pid_report_pipe[1], &grandchild_pid, sizeof(grandchild_pid));
- close_and_invalidate (&child_pid_report_pipe[1]);
-
- _exit (0);
- }
- }
- else
- {
- /* Just run the child.
- */
-
- do_exec (child_err_report_pipe[1],
- stdin_pipe[0],
- stdout_pipe[1],
- stderr_pipe[1],
- working_directory,
- argv,
- envp,
- close_descriptors,
- search_path,
- stdout_to_null,
- stderr_to_null,
- child_inherits_stdin,
- file_and_argv_zero,
- child_setup,
- user_data);
- }
- }
- else
- {
- /* Parent */
-
- gint buf[2];
- gint n_ints = 0;
-
- /* Close the uncared-about ends of the pipes */
- close_and_invalidate (&child_err_report_pipe[1]);
- close_and_invalidate (&child_pid_report_pipe[1]);
- close_and_invalidate (&stdin_pipe[0]);
- close_and_invalidate (&stdout_pipe[1]);
- close_and_invalidate (&stderr_pipe[1]);
-
- /* If we had an intermediate child, reap it */
- if (intermediate_child)
- {
- wait_again:
- if (waitpid (pid, &status, 0) < 0)
- {
- if (errno == EINTR)
- goto wait_again;
- else if (errno == ECHILD)
- ; /* do nothing, child already reaped */
- else
- g_warning ("waitpid() should not fail in "
- "'fork_exec_with_pipes'");
- }
- }
-
-
- if (!read_ints (child_err_report_pipe[0],
- buf, 2, &n_ints,
- error))
- goto cleanup_and_fail;
-
- if (n_ints >= 2)
- {
- /* Error from the child. */
-
- switch (buf[0])
- {
- case CHILD_CHDIR_FAILED:
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_CHDIR,
- _("Failed to change to directory '%s' (%s)"),
- working_directory,
- g_strerror (buf[1]));
-
- break;
-
- case CHILD_EXEC_FAILED:
- g_set_error (error,
- G_SPAWN_ERROR,
- exec_err_to_g_error (buf[1]),
- _("Failed to execute child process \"%s\" (%s)"),
- argv[0],
- g_strerror (buf[1]));
-
- break;
-
- case CHILD_DUP2_FAILED:
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_FAILED,
- _("Failed to redirect output or input of child process (%s)"),
- g_strerror (buf[1]));
-
- break;
-
- case CHILD_FORK_FAILED:
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_FORK,
- _("Failed to fork child process (%s)"),
- g_strerror (buf[1]));
- break;
-
- default:
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_FAILED,
- _("Unknown error executing child process \"%s\""),
- argv[0]);
- break;
- }
-
- goto cleanup_and_fail;
- }
-
- /* Get child pid from intermediate child pipe. */
- if (intermediate_child)
- {
- n_ints = 0;
-
- if (!read_ints (child_pid_report_pipe[0],
- buf, 1, &n_ints, error))
- goto cleanup_and_fail;
-
- if (n_ints < 1)
- {
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_FAILED,
- _("Failed to read enough data from child pid pipe (%s)"),
- g_strerror (errno));
- goto cleanup_and_fail;
- }
- else
- {
- /* we have the child pid */
- pid = buf[0];
- }
- }
-
- /* Success against all odds! return the information */
- close_and_invalidate (&child_err_report_pipe[0]);
- close_and_invalidate (&child_pid_report_pipe[0]);
-
- if (child_pid)
- *child_pid = pid;
-
- if (standard_input)
- *standard_input = stdin_pipe[1];
- if (standard_output)
- *standard_output = stdout_pipe[0];
- if (standard_error)
- *standard_error = stderr_pipe[0];
-
- return TRUE;
- }
-
- cleanup_and_fail:
-
- /* There was an error from the Child, reap the child to avoid it being
- a zombie.
- */
-
- if (pid > 0)
- {
- wait_failed:
- if (waitpid (pid, NULL, 0) < 0)
- {
- if (errno == EINTR)
- goto wait_failed;
- else if (errno == ECHILD)
- ; /* do nothing, child already reaped */
- else
- g_warning ("waitpid() should not fail in "
- "'fork_exec_with_pipes'");
- }
- }
-
- close_and_invalidate (&child_err_report_pipe[0]);
- close_and_invalidate (&child_err_report_pipe[1]);
- close_and_invalidate (&child_pid_report_pipe[0]);
- close_and_invalidate (&child_pid_report_pipe[1]);
- close_and_invalidate (&stdin_pipe[0]);
- close_and_invalidate (&stdin_pipe[1]);
- close_and_invalidate (&stdout_pipe[0]);
- close_and_invalidate (&stdout_pipe[1]);
- close_and_invalidate (&stderr_pipe[0]);
- close_and_invalidate (&stderr_pipe[1]);
-
- return FALSE;
-}
-
-static gboolean
-make_pipe (gint p[2],
- GError **error)
-{
- if (pipe (p) < 0)
- {
- gint errsv = errno;
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_FAILED,
- _("Failed to create pipe for communicating with child process (%s)"),
- g_strerror (errsv));
- return FALSE;
- }
- else
- return TRUE;
-}
-
-/* Based on execvp from GNU C Library */
-
-static void
-script_execute (const gchar *file,
- gchar **argv,
- gchar **envp,
- gboolean search_path)
-{
- /* Count the arguments. */
- int argc = 0;
- while (argv[argc])
- ++argc;
-
- /* Construct an argument list for the shell. */
- {
- gchar **new_argv;
-
- new_argv = g_new0 (gchar*, argc + 2); /* /bin/sh and NULL */
-
- new_argv[0] = (char *) "/bin/sh";
- new_argv[1] = (char *) file;
- while (argc > 0)
- {
- new_argv[argc + 1] = argv[argc];
- --argc;
- }
-
- /* Execute the shell. */
- if (envp)
- execve (new_argv[0], new_argv, envp);
- else
- execv (new_argv[0], new_argv);
-
- g_free (new_argv);
- }
-}
-
-static gchar*
-my_strchrnul (const gchar *str, gchar c)
-{
- gchar *p = (gchar*) str;
- while (*p && (*p != c))
- ++p;
-
- return p;
-}
-
-static gint
-g_execute (const gchar *file,
- gchar **argv,
- gchar **envp,
- gboolean search_path)
-{
- if (*file == '\0')
- {
- /* We check the simple case first. */
- errno = ENOENT;
- return -1;
- }
-
- if (!search_path || strchr (file, '/') != NULL)
- {
- /* Don't search when it contains a slash. */
- if (envp)
- execve (file, argv, envp);
- else
- execv (file, argv);
-
- if (errno == ENOEXEC)
- script_execute (file, argv, envp, FALSE);
- }
- else
- {
- gboolean got_eacces = 0;
- const gchar *path, *p;
- gchar *name, *freeme;
- gsize len;
- gsize pathlen;
-
- path = g_getenv ("PATH");
- if (path == NULL)
- {
- /* There is no `PATH' in the environment. The default
- * search path in libc is the current directory followed by
- * the path `confstr' returns for `_CS_PATH'.
- */
-
- /* In GLib we put . last, for security, and don't use the
- * unportable confstr(); UNIX98 does not actually specify
- * what to search if PATH is unset. POSIX may, dunno.
- */
-
- path = "/bin:/usr/bin:.";
- }
-
- len = strlen (file) + 1;
- pathlen = strlen (path);
- freeme = name = g_malloc (pathlen + len + 1);
-
- /* Copy the file name at the top, including '\0' */
- memcpy (name + pathlen + 1, file, len);
- name = name + pathlen;
- /* And add the slash before the filename */
- *name = '/';
-
- p = path;
- do
- {
- char *startp;
-
- path = p;
- p = my_strchrnul (path, ':');
-
- if (p == path)
- /* Two adjacent colons, or a colon at the beginning or the end
- * of `PATH' means to search the current directory.
- */
- startp = name + 1;
- else
- startp = memcpy (name - (p - path), path, p - path);
-
- /* Try to execute this name. If it works, execv will not return. */
- if (envp)
- execve (startp, argv, envp);
- else
- execv (startp, argv);
-
- if (errno == ENOEXEC)
- script_execute (startp, argv, envp, search_path);
-
- switch (errno)
- {
- case EACCES:
- /* Record the we got a `Permission denied' error. If we end
- * up finding no executable we can use, we want to diagnose
- * that we did find one but were denied access.
- */
- got_eacces = TRUE;
-
- /* FALL THRU */
-
- case ENOENT:
-#ifdef ESTALE
- case ESTALE:
-#endif
-#ifdef ENOTDIR
- case ENOTDIR:
-#endif
- /* Those errors indicate the file is missing or not executable
- * by us, in which case we want to just try the next path
- * directory.
- */
- break;
-
- default:
- /* Some other error means we found an executable file, but
- * something went wrong executing it; return the error to our
- * caller.
- */
- g_free (freeme);
- return -1;
- }
- }
- while (*p++ != '\0');
-
- /* We tried every element and none of them worked. */
- if (got_eacces)
- /* At least one failure was due to permissions, so report that
- * error.
- */
- errno = EACCES;
-
- g_free (freeme);
- }
-
- /* Return the error from the last attempt (probably ENOENT). */
- return -1;
-}
-
-/**
- * g_spawn_close_pid:
- * @pid: The process reference to close
- *
- * On some platforms, notably Windows, the #GPid type represents a resource
- * which must be closed to prevent resource leaking. g_spawn_close_pid()
- * is provided for this purpose. It should be used on all platforms, even
- * though it doesn't do anything under UNIX.
- **/
-void
-g_spawn_close_pid (GPid pid)
-{
-}
-
-#define __G_SPAWN_C__
-#include "galiasdef.c"
diff --git a/glib/gstrfuncs.c b/glib/gstrfuncs.c
index 3aed62c9c..b076aa9ee 100644
--- a/glib/gstrfuncs.c
+++ b/glib/gstrfuncs.c
@@ -428,7 +428,9 @@ g_ascii_strtod (const gchar *nptr,
fail_pos = NULL;
+#ifdef ANDROID_STUB
locale_data = localeconv ();
+
decimal_point = locale_data->decimal_point;
decimal_point_len = strlen (decimal_point);
@@ -547,6 +549,7 @@ g_ascii_strtod (const gchar *nptr,
g_free (copy);
}
else
+#endif
{
errno = 0;
val = strtod (nptr, &fail_pos);
@@ -561,7 +564,6 @@ g_ascii_strtod (const gchar *nptr,
return val;
}
-
/**
* g_ascii_dtostr:
* @buffer: A buffer to place the resulting string in
@@ -643,6 +645,7 @@ g_ascii_formatd (gchar *buffer,
_g_snprintf (buffer, buf_len, format, d);
+#ifdef ANDROID_STUB
locale_data = localeconv ();
decimal_point = locale_data->decimal_point;
decimal_point_len = strlen (decimal_point);
@@ -675,6 +678,7 @@ g_ascii_formatd (gchar *buffer,
}
}
}
+#endif
return buffer;
}
diff --git a/glib/gtester-report b/glib/gtester-report
deleted file mode 100755
index b385094f0..000000000
--- a/glib/gtester-report
+++ /dev/null
@@ -1,358 +0,0 @@
-#! /usr/bin/env python
-# GLib Testing Framework Utility -*- Mode: python; -*-
-# Copyright (C) 2007 Imendio AB
-# Authors: Tim Janik
-#
-# 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 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, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-import sys, re, xml.dom.minidom
-pkginstall_configvars = {
- #@PKGINSTALL_CONFIGVARS_IN24LINES@ # configvars are substituted upon script installation
-}
-
-# xml utilities
-def find_child (node, child_name):
- for child in node.childNodes:
- if child.nodeName == child_name:
- return child
- return None
-def list_children (node, child_name):
- rlist = []
- for child in node.childNodes:
- if child.nodeName == child_name:
- rlist += [ child ]
- return rlist
-def find_node (node, name = None):
- if not node or node.nodeName == name or not name:
- return node
- for child in node.childNodes:
- c = find_node (child, name)
- if c:
- return c
- return None
-def node_as_text (node, name = None):
- if name:
- node = find_node (node, name)
- txt = ''
- if node:
- if node.nodeValue:
- txt += node.nodeValue
- for child in node.childNodes:
- txt += node_as_text (child)
- return txt
-def attribute_as_text (node, aname, node_name = None):
- node = find_node (node, node_name)
- if not node:
- return ''
- attr = node.attributes.get (aname, '')
- if hasattr (attr, 'value'):
- return attr.value
- return ''
-
-# HTML utilities
-def html_indent_string (n):
- uncollapsible_space = ' &nbsp;' # HTML won't compress alternating sequences of ' ' and '&nbsp;'
- string = ''
- for i in range (0, (n + 1) / 2):
- string += uncollapsible_space
- return string
-
-# TestBinary object, instantiated per test binary in the log file
-class TestBinary:
- def __init__ (self, name):
- self.name = name
- self.testcases = []
- self.duration = 0
- self.success_cases = 0
- self.skipped_cases = 0
- self.file = '???'
- self.random_seed = ''
-
-# base class to handle processing/traversion of XML nodes
-class TreeProcess:
- def __init__ (self):
- self.nest_level = 0
- def trampoline (self, node):
- name = node.nodeName
- if name == '#text':
- self.handle_text (node)
- else:
- try: method = getattr (self, 'handle_' + re.sub ('[^a-zA-Z0-9]', '_', name))
- except: method = None
- if method:
- return method (node)
- else:
- return self.process_recursive (name, node)
- def process_recursive (self, node_name, node):
- self.process_children (node)
- def process_children (self, node):
- self.nest_level += 1
- for child in node.childNodes:
- self.trampoline (child)
- self.nest_level += 1
-
-# test report reader, this class collects some statistics and merges duplicate test binary runs
-class ReportReader (TreeProcess):
- def __init__ (self):
- TreeProcess.__init__ (self)
- self.binary_names = []
- self.binaries = {}
- self.last_binary = None
- def binary_list (self):
- lst = []
- for name in self.binary_names:
- lst += [ self.binaries[name] ]
- return lst
- def handle_testcase (self, node):
- self.last_binary.testcases += [ node ]
- result = attribute_as_text (node, 'result', 'status')
- if result == 'success':
- self.last_binary.success_cases += 1
- if bool (int (attribute_as_text (node, 'skipped') + '0')):
- self.last_binary.skipped_cases += 1
- def handle_text (self, node):
- pass
- def handle_testbinary (self, node):
- path = node.attributes.get ('path', None).value
- if self.binaries.get (path, -1) == -1:
- self.binaries[path] = TestBinary (path)
- self.binary_names += [ path ]
- self.last_binary = self.binaries[path]
- dn = find_child (node, 'duration')
- dur = node_as_text (dn)
- try: dur = float (dur)
- except: dur = 0
- if dur:
- self.last_binary.duration += dur
- bin = find_child (node, 'binary')
- if bin:
- self.last_binary.file = attribute_as_text (bin, 'file')
- rseed = find_child (node, 'random-seed')
- if rseed:
- self.last_binary.random_seed = node_as_text (rseed)
- self.process_children (node)
-
-# HTML report generation class
-class ReportWriter (TreeProcess):
- # Javascript/CSS snippet to toggle element visibility
- cssjs = r'''
- <style type="text/css" media="screen">
- .VisibleSection { }
- .HiddenSection { display: none; }
- </style>
- <script language="javascript" type="text/javascript"><!--
- function toggle_display (parentid, tagtype, idmatch, keymatch) {
- ptag = document.getElementById (parentid);
- tags = ptag.getElementsByTagName (tagtype);
- for (var i = 0; i < tags.length; i++) {
- tag = tags[i];
- var key = tag.getAttribute ("keywords");
- if (tag.id.indexOf (idmatch) == 0 && key && key.match (keymatch)) {
- if (tag.className.indexOf ("HiddenSection") >= 0)
- tag.className = "VisibleSection";
- else
- tag.className = "HiddenSection";
- }
- }
- }
- message_array = Array();
- function view_testlog (wname, file, random_seed, tcase, msgtitle, msgid) {
- txt = message_array[msgid];
- var w = window.open ("", // URI
- wname,
- "resizable,scrollbars,status,width=790,height=400");
- var doc = w.document;
- doc.write ("<h2>File: " + file + "</h2>\n");
- doc.write ("<h3>Case: " + tcase + "</h3>\n");
- doc.write ("<strong>Random Seed:</strong> <code>" + random_seed + "</code> <br /><br />\n");
- doc.write ("<strong>" + msgtitle + "</strong><br />\n");
- doc.write ("<pre>");
- doc.write (txt);
- doc.write ("</pre>\n");
- doc.write ("<a href=\'javascript:window.close()\'>Close Window</a>\n");
- doc.close();
- }
- --></script>
- '''
- def __init__ (self, binary_list):
- TreeProcess.__init__ (self)
- self.binaries = binary_list
- self.bcounter = 0
- self.tcounter = 0
- self.total_tcounter = 0
- self.total_fcounter = 0
- self.total_duration = 0
- self.indent_depth = 0
- self.lastchar = ''
- def oprint (self, message):
- sys.stdout.write (message)
- if message:
- self.lastchar = message[-1]
- def handle_text (self, node):
- self.oprint (node.nodeValue)
- def handle_testcase (self, node, binary):
- skipped = bool (int (attribute_as_text (node, 'skipped') + '0'))
- if skipped:
- return # skipped tests are uninteresting for HTML reports
- path = attribute_as_text (node, 'path')
- duration = node_as_text (node, 'duration')
- result = attribute_as_text (node, 'result', 'status')
- rcolor = {
- 'success': 'bgcolor="lightgreen"',
- 'failed': 'bgcolor="red"',
- }.get (result, '')
- if result != 'success':
- duration = '-' # ignore bogus durations
- self.oprint ('<tr id="b%u_t%u_" keywords="%s all" class="HiddenSection">\n' % (self.bcounter, self.tcounter, result))
- self.oprint ('<td>%s %s</td> <td align="right">%s</td> \n' % (html_indent_string (4), path, duration))
- perflist = list_children (node, 'performance')
- if result != 'success':
- rlist = list_children (node, 'error')
- txt = ''
- for enode in rlist:
- txt += node_as_text (enode)
- if txt and txt[-1] != '\n':
- txt += '\n'
- txt = re.sub (r'"', r'\\"', txt)
- txt = re.sub (r'\n', r'\\n', txt)
- txt = re.sub (r'&', r'&amp;', txt)
- txt = re.sub (r'<', r'&lt;', txt)
- self.oprint ('<script language="javascript" type="text/javascript">message_array["b%u_t%u_"] = "%s";</script>\n' % (self.bcounter, self.tcounter, txt))
- self.oprint ('<td align="center"><a href="javascript:view_testlog (\'%s\', \'%s\', \'%s\', \'%s\', \'Output:\', \'b%u_t%u_\')">Details</a></td>\n' %
- ('TestResultWindow', binary.file, binary.random_seed, path, self.bcounter, self.tcounter))
- elif perflist:
- presults = []
- for perf in perflist:
- pmin = bool (int (attribute_as_text (perf, 'minimize')))
- pmax = bool (int (attribute_as_text (perf, 'maximize')))
- pval = float (attribute_as_text (perf, 'value'))
- txt = node_as_text (perf)
- txt = re.sub (r'&', r'&amp;', txt)
- txt = re.sub (r'<', r'&gt;', txt)
- txt = '<strong>Performace(' + (pmin and '<em>minimized</em>' or '<em>maximized</em>') + '):</strong> ' + txt.strip() + '<br />\n'
- txt = re.sub (r'"', r'\\"', txt)
- txt = re.sub (r'\n', r'\\n', txt)
- presults += [ (pval, txt) ]
- presults.sort()
- ptxt = ''.join ([e[1] for e in presults])
- self.oprint ('<script language="javascript" type="text/javascript">message_array["b%u_t%u_"] = "%s";</script>\n' % (self.bcounter, self.tcounter, ptxt))
- self.oprint ('<td align="center"><a href="javascript:view_testlog (\'%s\', \'%s\', \'%s\', \'%s\', \'Test Results:\', \'b%u_t%u_\')">Details</a></td>\n' %
- ('TestResultWindow', binary.file, binary.random_seed, path, self.bcounter, self.tcounter))
- else:
- self.oprint ('<td align="center">-</td>\n')
- self.oprint ('<td align="right" %s>%s</td>\n' % (rcolor, result))
- self.oprint ('</tr>\n')
- self.tcounter += 1
- self.total_tcounter += 1
- self.total_fcounter += result != 'success'
- def handle_binary (self, binary):
- self.tcounter = 1
- self.bcounter += 1
- self.total_duration += binary.duration
- self.oprint ('<tr><td><strong>%s</strong></td><td align="right">%f</td> <td align="center">\n' % (binary.name, binary.duration))
- erlink, oklink = ('', '')
- real_cases = len (binary.testcases) - binary.skipped_cases
- if binary.success_cases < real_cases:
- erlink = 'href="javascript:toggle_display (\'ResultTable\', \'tr\', \'b%u_\', \'failed\')"' % self.bcounter
- if binary.success_cases:
- oklink = 'href="javascript:toggle_display (\'ResultTable\', \'tr\', \'b%u_\', \'success\')"' % self.bcounter
- self.oprint ('<a %s>ER</a>\n' % erlink)
- self.oprint ('<a %s>OK</a>\n' % oklink)
- self.oprint ('</td>\n')
- perc = binary.success_cases * 100.0 / real_cases
- pcolor = {
- 100 : 'bgcolor="lightgreen"',
- 0 : 'bgcolor="red"',
- }.get (int (perc), 'bgcolor="yellow"')
- self.oprint ('<td align="right" %s>%.2f%%</td>\n' % (pcolor, perc))
- self.oprint ('</tr>\n')
- for tc in binary.testcases:
- self.handle_testcase (tc, binary)
- def handle_totals (self):
- self.oprint ('<tr>')
- self.oprint ('<td><strong>Totals:</strong> %u Binaries, %u Tests, %u Failed, %u Succeeded</td>' %
- (self.bcounter, self.total_tcounter, self.total_fcounter, self.total_tcounter - self.total_fcounter))
- self.oprint ('<td align="right">%f</td>\n' % self.total_duration)
- self.oprint ('<td align="center">-</td>\n')
- perc = (self.total_tcounter - self.total_fcounter) * 100.0 / self.total_tcounter
- pcolor = {
- 100 : 'bgcolor="lightgreen"',
- 0 : 'bgcolor="red"',
- }.get (int (perc), 'bgcolor="yellow"')
- self.oprint ('<td align="right" %s>%.2f%%</td>\n' % (pcolor, perc))
- self.oprint ('</tr>\n')
- def printout (self):
- self.oprint ('<html><head>\n')
- self.oprint ('<title>GTester Unit Test Report</title>\n')
- self.oprint (self.cssjs)
- self.oprint ('</head>\n')
- self.oprint ('<body>\n')
- self.oprint ('<h2>GTester Unit Test Report</h2>\n')
- self.oprint ('<table id="ResultTable" width="100%" border="1">\n<tr>\n')
- self.oprint ('<th>Program / Testcase </th>\n')
- self.oprint ('<th style="width:8em">Duration (sec)</th>\n')
- self.oprint ('<th style="width:5em">View</th>\n')
- self.oprint ('<th style="width:5em">Result</th>\n')
- self.oprint ('</tr>\n')
- for tb in self.binaries:
- self.handle_binary (tb)
- self.handle_totals()
- self.oprint ('</table>\n')
- self.oprint ('</body>\n')
- self.oprint ('</html>\n')
-
-# main program handling
-def parse_files_and_args ():
- from sys import argv, stdin
- files = []
- arg_iter = sys.argv[1:].__iter__()
- rest = len (sys.argv) - 1
- for arg in arg_iter:
- rest -= 1
- if arg == '--help' or arg == '-h':
- print_help ()
- sys.exit (0)
- elif arg == '--version' or arg == '-v':
- print_help (False)
- sys.exit (0)
- else:
- files = files + [ arg ]
- return files
-
-def print_help (with_help = True):
- import os
- print "gtester-report (GLib utils) version", pkginstall_configvars.get ('glib-version', '0.0-uninstalled')
- if not with_help:
- return
- print "Usage: %s [OPTIONS] <gtester-log.xml>" % os.path.basename (sys.argv[0])
- print "Generate HTML reports from the XML log files generated by gtester."
- print "Options:"
- print " --help, -h print this help message"
- print " --version, -v print version info"
-
-def main():
- from sys import argv, stdin
- files = parse_files_and_args()
- if len (files) != 1:
- print_help (True)
- sys.exit (1)
- xd = xml.dom.minidom.parse (files[0])
- rr = ReportReader()
- rr.trampoline (xd)
- rw = ReportWriter (rr.binary_list())
- rw.printout()
-
-if __name__ == '__main__':
- main()
diff --git a/glib/gtester.c b/glib/gtester.c
deleted file mode 100644
index ecc9f77fd..000000000
--- a/glib/gtester.c
+++ /dev/null
@@ -1,711 +0,0 @@
-/* GLib testing framework runner
- * Copyright (C) 2007 Sven Herzberg
- * Copyright (C) 2007 Tim Janik
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#include <glib.h>
-#include <gstdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <signal.h>
-
-/* the read buffer size in bytes */
-#define READ_BUFFER_SIZE 4096
-
-/* --- prototypes --- */
-static int main_selftest (int argc,
- char **argv);
-static void parse_args (gint *argc_p,
- gchar ***argv_p);
-
-/* --- variables --- */
-static GIOChannel *ioc_report = NULL;
-static gboolean gtester_quiet = FALSE;
-static gboolean gtester_verbose = FALSE;
-static gboolean gtester_list_tests = FALSE;
-static gboolean gtester_selftest = FALSE;
-static gboolean subtest_running = FALSE;
-static gint subtest_exitstatus = 0;
-static gboolean subtest_io_pending = FALSE;
-static gboolean subtest_quiet = TRUE;
-static gboolean subtest_verbose = FALSE;
-static gboolean subtest_mode_fatal = TRUE;
-static gboolean subtest_mode_perf = FALSE;
-static gboolean subtest_mode_quick = TRUE;
-static const gchar *subtest_seedstr = NULL;
-static gchar *subtest_last_seed = NULL;
-static GSList *subtest_paths = NULL;
-static GSList *subtest_args = NULL;
-static gboolean testcase_open = FALSE;
-static guint testcase_count = 0;
-static guint testcase_fail_count = 0;
-static const gchar *output_filename = NULL;
-static guint log_indent = 0;
-static gint log_fd = -1;
-
-/* --- functions --- */
-static const char*
-sindent (guint n)
-{
- static const char spaces[] = " ";
- int l = sizeof (spaces) - 1;
- n = MIN (n, l);
- return spaces + l - n;
-}
-
-static void G_GNUC_PRINTF (1, 2)
-test_log_printfe (const char *format,
- ...)
-{
- char *result;
- int r;
- va_list args;
- va_start (args, format);
- result = g_markup_vprintf_escaped (format, args);
- va_end (args);
- do
- r = write (log_fd, result, strlen (result));
- while (r < 0 && errno == EINTR);
- g_free (result);
-}
-
-static void
-terminate (void)
-{
- kill (getpid(), SIGTERM);
- abort();
-}
-
-static void
-testcase_close (long double duration,
- gint exit_status,
- guint n_forks)
-{
- g_return_if_fail (testcase_open > 0);
- test_log_printfe ("%s<duration>%.6Lf</duration>\n", sindent (log_indent), duration);
- test_log_printfe ("%s<status exit-status=\"%d\" n-forks=\"%d\" result=\"%s\"/>\n",
- sindent (log_indent), exit_status, n_forks,
- exit_status ? "failed" : "success");
- log_indent -= 2;
- test_log_printfe ("%s</testcase>\n", sindent (log_indent));
- testcase_open--;
- if (gtester_verbose)
- g_print ("%s\n", exit_status ? "FAIL" : "OK");
- if (exit_status && subtest_last_seed)
- g_print ("GTester: last random seed: %s\n", subtest_last_seed);
- if (exit_status)
- testcase_fail_count += 1;
- if (subtest_mode_fatal && testcase_fail_count)
- terminate();
-}
-
-static void
-test_log_msg (GTestLogMsg *msg)
-{
- switch (msg->log_type)
- {
- guint i;
- gchar **strv;
- case G_TEST_LOG_NONE:
- break;
- case G_TEST_LOG_ERROR:
- strv = g_strsplit (msg->strings[0], "\n", -1);
- for (i = 0; strv[i]; i++)
- test_log_printfe ("%s<error>%s</error>\n", sindent (log_indent), strv[i]);
- g_strfreev (strv);
- break;
- case G_TEST_LOG_START_BINARY:
- test_log_printfe ("%s<binary file=\"%s\"/>\n", sindent (log_indent), msg->strings[0]);
- subtest_last_seed = g_strdup (msg->strings[1]);
- test_log_printfe ("%s<random-seed>%s</random-seed>\n", sindent (log_indent), subtest_last_seed);
- break;
- case G_TEST_LOG_LIST_CASE:
- g_print ("%s\n", msg->strings[0]);
- break;
- case G_TEST_LOG_START_CASE:
- testcase_count++;
- if (gtester_verbose)
- {
- gchar *sc = g_strconcat (msg->strings[0], ":", NULL);
- gchar *sleft = g_strdup_printf ("%-68s", sc);
- g_free (sc);
- g_print ("%70s ", sleft);
- g_free (sleft);
- }
- g_return_if_fail (testcase_open == 0);
- testcase_open++;
- test_log_printfe ("%s<testcase path=\"%s\">\n", sindent (log_indent), msg->strings[0]);
- log_indent += 2;
- break;
- case G_TEST_LOG_SKIP_CASE:
- if (FALSE && gtester_verbose) /* enable to debug test case skipping logic */
- {
- gchar *sc = g_strconcat (msg->strings[0], ":", NULL);
- gchar *sleft = g_strdup_printf ("%-68s", sc);
- g_free (sc);
- g_print ("%70s SKIPPED\n", sleft);
- g_free (sleft);
- }
- test_log_printfe ("%s<testcase path=\"%s\" skipped=\"1\"/>\n", sindent (log_indent), msg->strings[0]);
- break;
- case G_TEST_LOG_STOP_CASE:
- testcase_close (msg->nums[2], (int) msg->nums[0], (int) msg->nums[1]);
- break;
- case G_TEST_LOG_MIN_RESULT:
- case G_TEST_LOG_MAX_RESULT:
- test_log_printfe ("%s<performance minimize=\"%d\" maximize=\"%d\" value=\"%.16Lg\">\n",
- sindent (log_indent), msg->log_type == G_TEST_LOG_MIN_RESULT, msg->log_type == G_TEST_LOG_MAX_RESULT, msg->nums[0]);
- test_log_printfe ("%s%s\n", sindent (log_indent + 2), msg->strings[0]);
- test_log_printfe ("%s</performance>\n", sindent (log_indent));
- break;
- case G_TEST_LOG_MESSAGE:
- test_log_printfe ("%s<message>\n%s\n%s</message>\n", sindent (log_indent), msg->strings[0], sindent (log_indent));
- break;
- }
-}
-
-static gboolean
-child_report_cb (GIOChannel *source,
- GIOCondition condition,
- gpointer data)
-{
- GTestLogBuffer *tlb = data;
- GIOStatus status = G_IO_STATUS_NORMAL;
- gboolean first_read_eof = FALSE, first_read = TRUE;
- gsize length = 0;
- do
- {
- guint8 buffer[READ_BUFFER_SIZE];
- GError *error = NULL;
- status = g_io_channel_read_chars (source, (gchar*) buffer, sizeof (buffer), &length, &error);
- if (first_read && (condition & G_IO_IN))
- {
- /* on some unixes (MacOS) we need to detect non-blocking fd EOF
- * by an IO_IN select/poll followed by read()==0.
- */
- first_read_eof = length == 0;
- }
- first_read = FALSE;
- if (length)
- {
- GTestLogMsg *msg;
- g_test_log_buffer_push (tlb, length, buffer);
- do
- {
- msg = g_test_log_buffer_pop (tlb);
- if (msg)
- {
- test_log_msg (msg);
- g_test_log_msg_free (msg);
- }
- }
- while (msg);
- }
- g_clear_error (&error);
- /* ignore the io channel status, which will report intermediate EOFs for non blocking fds */
- (void) status;
- }
- while (length > 0);
- /* g_print ("LASTIOSTATE: first_read_eof=%d condition=%d\n", first_read_eof, condition); */
- if (first_read_eof || (condition & (G_IO_ERR | G_IO_HUP)))
- {
- /* if there's no data to read and select() reports an error or hangup,
- * the fd must have been closed remotely
- */
- subtest_io_pending = FALSE;
- return FALSE;
- }
- return TRUE; /* keep polling */
-}
-
-static void
-child_watch_cb (GPid pid,
- gint status,
- gpointer data)
-{
- g_spawn_close_pid (pid);
- if (WIFEXITED (status)) /* normal exit */
- subtest_exitstatus = WEXITSTATUS (status);
- else /* signal or core dump, etc */
- subtest_exitstatus = 0xffffffff;
- subtest_running = FALSE;
-}
-
-static gchar*
-queue_gfree (GSList **slistp,
- gchar *string)
-{
- *slistp = g_slist_prepend (*slistp, string);
- return string;
-}
-
-static void
-unset_cloexec_fdp (gpointer fdp_data)
-{
- int r, *fdp = fdp_data;
- do
- r = fcntl (*fdp, F_SETFD, 0 /* FD_CLOEXEC */);
- while (r < 0 && errno == EINTR);
-}
-
-static gboolean
-launch_test_binary (const char *binary,
- guint skip_tests)
-{
- GTestLogBuffer *tlb;
- GSList *slist, *free_list = NULL;
- GError *error = NULL;
- int argc = 0;
- const gchar **argv;
- GPid pid = 0;
- gint report_pipe[2] = { -1, -1 };
- guint child_report_cb_id = 0;
- gboolean loop_pending;
- gint i = 0;
-
- if (pipe (report_pipe) < 0)
- {
- if (subtest_mode_fatal)
- g_error ("Failed to open pipe for test binary: %s: %s", binary, g_strerror (errno));
- else
- g_warning ("Failed to open pipe for test binary: %s: %s", binary, g_strerror (errno));
- return FALSE;
- }
-
- /* setup argc */
- for (slist = subtest_args; slist; slist = slist->next)
- argc++;
- /* argc++; */
- if (subtest_quiet)
- argc++;
- if (subtest_verbose)
- argc++;
- if (!subtest_mode_fatal)
- argc++;
- if (subtest_mode_quick)
- argc++;
- else
- argc++;
- if (subtest_mode_perf)
- argc++;
- if (gtester_list_tests)
- argc++;
- if (subtest_seedstr)
- argc++;
- argc++;
- if (skip_tests)
- argc++;
- for (slist = subtest_paths; slist; slist = slist->next)
- argc++;
-
- /* setup argv */
- argv = g_malloc ((argc + 2) * sizeof(gchar *));
- argv[i++] = binary;
- for (slist = subtest_args; slist; slist = slist->next)
- argv[i++] = (gchar*) slist->data;
- /* argv[i++] = "--debug-log"; */
- if (subtest_quiet)
- argv[i++] = "--quiet";
- if (subtest_verbose)
- argv[i++] = "--verbose";
- if (!subtest_mode_fatal)
- argv[i++] = "--keep-going";
- if (subtest_mode_quick)
- argv[i++] = "-m=quick";
- else
- argv[i++] = "-m=slow";
- if (subtest_mode_perf)
- argv[i++] = "-m=perf";
- if (gtester_list_tests)
- argv[i++] = "-l";
- if (subtest_seedstr)
- argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--seed=%s", subtest_seedstr));
- argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestLogFD=%u", report_pipe[1]));
- if (skip_tests)
- argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestSkipCount=%u", skip_tests));
- for (slist = subtest_paths; slist; slist = slist->next)
- argv[i++] = queue_gfree (&free_list, g_strdup_printf ("-p=%s", (gchar*) slist->data));
- argv[i++] = NULL;
-
- g_spawn_async_with_pipes (NULL, /* g_get_current_dir() */
- (gchar**) argv,
- NULL, /* envp */
- G_SPAWN_DO_NOT_REAP_CHILD, /* G_SPAWN_SEARCH_PATH */
- unset_cloexec_fdp, &report_pipe[1], /* pre-exec callback */
- &pid,
- NULL, /* standard_input */
- NULL, /* standard_output */
- NULL, /* standard_error */
- &error);
- g_slist_foreach (free_list, (void(*)(void*,void*)) g_free, NULL);
- g_slist_free (free_list);
- free_list = NULL;
- close (report_pipe[1]);
-
- if (!gtester_quiet)
- g_print ("(pid=%lu)\n", (unsigned long) pid);
-
- if (error)
- {
- close (report_pipe[0]);
- if (subtest_mode_fatal)
- g_error ("Failed to execute test binary: %s: %s", argv[0], error->message);
- else
- g_warning ("Failed to execute test binary: %s: %s", argv[0], error->message);
- g_clear_error (&error);
- g_free (argv);
- return FALSE;
- }
- g_free (argv);
-
- subtest_running = TRUE;
- subtest_io_pending = TRUE;
- tlb = g_test_log_buffer_new();
- if (report_pipe[0] >= 0)
- {
- ioc_report = g_io_channel_unix_new (report_pipe[0]);
- g_io_channel_set_flags (ioc_report, G_IO_FLAG_NONBLOCK, NULL);
- g_io_channel_set_encoding (ioc_report, NULL, NULL);
- g_io_channel_set_buffered (ioc_report, FALSE);
- child_report_cb_id = g_io_add_watch_full (ioc_report, G_PRIORITY_DEFAULT - 1, G_IO_IN | G_IO_ERR | G_IO_HUP, child_report_cb, tlb, NULL);
- g_io_channel_unref (ioc_report);
- }
- g_child_watch_add_full (G_PRIORITY_DEFAULT + 1, pid, child_watch_cb, NULL, NULL);
-
- loop_pending = g_main_context_pending (NULL);
- while (subtest_running || /* FALSE once child exits */
- subtest_io_pending || /* FALSE once ioc_report closes */
- loop_pending) /* TRUE while idler, etc are running */
- {
- /* g_print ("LOOPSTATE: subtest_running=%d subtest_io_pending=%d\n", subtest_running, subtest_io_pending); */
- /* check for unexpected hangs that are not signalled on report_pipe */
- if (!subtest_running && /* child exited */
- subtest_io_pending && /* no EOF detected on report_pipe */
- !loop_pending) /* no IO events pending however */
- break;
- g_main_context_iteration (NULL, TRUE);
- loop_pending = g_main_context_pending (NULL);
- }
-
- g_source_remove (child_report_cb_id);
- close (report_pipe[0]);
- g_test_log_buffer_free (tlb);
-
- return TRUE;
-}
-
-static void
-launch_test (const char *binary)
-{
- gboolean success = TRUE;
- GTimer *btimer = g_timer_new();
- gboolean need_restart;
- testcase_count = 0;
- testcase_fail_count = 0;
- if (!gtester_quiet)
- g_print ("TEST: %s... ", binary);
-
- retry:
- test_log_printfe ("%s<testbinary path=\"%s\">\n", sindent (log_indent), binary);
- log_indent += 2;
- g_timer_start (btimer);
- subtest_exitstatus = 0;
- success &= launch_test_binary (binary, testcase_count);
- success &= subtest_exitstatus == 0;
- need_restart = testcase_open != 0;
- if (testcase_open)
- testcase_close (0, -256, 0);
- g_timer_stop (btimer);
- test_log_printfe ("%s<duration>%.6f</duration>\n", sindent (log_indent), g_timer_elapsed (btimer, NULL));
- log_indent -= 2;
- test_log_printfe ("%s</testbinary>\n", sindent (log_indent));
- g_free (subtest_last_seed);
- subtest_last_seed = NULL;
- if (need_restart)
- {
- /* restart test binary, skipping processed test cases */
- goto retry;
- }
-
- if (!gtester_quiet)
- g_print ("%s: %s\n", testcase_fail_count || !success ? "FAIL" : "PASS", binary);
- g_timer_destroy (btimer);
- if (subtest_mode_fatal && !success)
- terminate();
-}
-
-static void
-usage (gboolean just_version)
-{
- if (just_version)
- {
- g_print ("gtester version %d.%d.%d\n", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
- return;
- }
- g_print ("Usage: gtester [OPTIONS] testprogram...\n");
- /* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
- g_print ("Options:\n");
- g_print (" -h, --help show this help message\n");
- g_print (" -v, --version print version informations\n");
- g_print (" --g-fatal-warnings make warnings fatal (abort)\n");
- g_print (" -k, --keep-going continue running after tests failed\n");
- g_print (" -l list paths of available test cases\n");
- g_print (" -m=perf, -m=slow, -m=quick -m=thorough\n");
- g_print (" run test cases in mode perf, slow/thorough or quick (default)\n");
- g_print (" -p=TESTPATH only start test cases matching TESTPATH\n");
- g_print (" --seed=SEEDSTRING start all tests with random number seed SEEDSTRING\n");
- g_print (" -o=LOGFILE write the test log to LOGFILE\n");
- g_print (" -q, --quiet suppress per test binary output\n");
- g_print (" --verbose report success per testcase\n");
-}
-
-static void
-parse_args (gint *argc_p,
- gchar ***argv_p)
-{
- guint argc = *argc_p;
- gchar **argv = *argv_p;
- guint i, e;
- /* parse known args */
- for (i = 1; i < argc; i++)
- {
- if (strcmp (argv[i], "--g-fatal-warnings") == 0)
- {
- GLogLevelFlags fatal_mask = (GLogLevelFlags) g_log_set_always_fatal ((GLogLevelFlags) G_LOG_FATAL_MASK);
- fatal_mask = (GLogLevelFlags) (fatal_mask | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
- g_log_set_always_fatal (fatal_mask);
- argv[i] = NULL;
- }
- else if (strcmp (argv[i], "--gtester-selftest") == 0)
- {
- gtester_selftest = TRUE;
- argv[i] = NULL;
- break; /* stop parsing regular gtester arguments */
- }
- else if (strcmp (argv[i], "-h") == 0 || strcmp (argv[i], "--help") == 0)
- {
- usage (FALSE);
- exit (0);
- argv[i] = NULL;
- }
- else if (strcmp (argv[i], "-v") == 0 || strcmp (argv[i], "--version") == 0)
- {
- usage (TRUE);
- exit (0);
- argv[i] = NULL;
- }
- else if (strcmp (argv[i], "--keep-going") == 0 ||
- strcmp (argv[i], "-k") == 0)
- {
- subtest_mode_fatal = FALSE;
- argv[i] = NULL;
- }
- else if (strcmp ("-p", argv[i]) == 0 || strncmp ("-p=", argv[i], 3) == 0)
- {
- gchar *equal = argv[i] + 2;
- if (*equal == '=')
- subtest_paths = g_slist_prepend (subtest_paths, equal + 1);
- else if (i + 1 < argc)
- {
- argv[i++] = NULL;
- subtest_paths = g_slist_prepend (subtest_paths, argv[i]);
- }
- argv[i] = NULL;
- }
- else if (strcmp ("--test-arg", argv[i]) == 0 || strncmp ("--test-arg=", argv[i], 11) == 0)
- {
- gchar *equal = argv[i] + 10;
- if (*equal == '=')
- subtest_args = g_slist_prepend (subtest_args, equal + 1);
- else if (i + 1 < argc)
- {
- argv[i++] = NULL;
- subtest_args = g_slist_prepend (subtest_args, argv[i]);
- }
- argv[i] = NULL;
- }
- else if (strcmp ("-o", argv[i]) == 0 || strncmp ("-o=", argv[i], 3) == 0)
- {
- gchar *equal = argv[i] + 2;
- if (*equal == '=')
- output_filename = equal + 1;
- else if (i + 1 < argc)
- {
- argv[i++] = NULL;
- output_filename = argv[i];
- }
- argv[i] = NULL;
- }
- else if (strcmp ("-m", argv[i]) == 0 || strncmp ("-m=", argv[i], 3) == 0)
- {
- gchar *equal = argv[i] + 2;
- const gchar *mode = "";
- if (*equal == '=')
- mode = equal + 1;
- else if (i + 1 < argc)
- {
- argv[i++] = NULL;
- mode = argv[i];
- }
- if (strcmp (mode, "perf") == 0)
- subtest_mode_perf = TRUE;
- else if (strcmp (mode, "slow") == 0 || strcmp (mode, "thorough") == 0)
- subtest_mode_quick = FALSE;
- else if (strcmp (mode, "quick") == 0)
- {
- subtest_mode_quick = TRUE;
- subtest_mode_perf = FALSE;
- }
- else
- g_error ("unknown test mode: -m %s", mode);
- argv[i] = NULL;
- }
- else if (strcmp ("-q", argv[i]) == 0 || strcmp ("--quiet", argv[i]) == 0)
- {
- gtester_quiet = TRUE;
- gtester_verbose = FALSE;
- argv[i] = NULL;
- }
- else if (strcmp ("--verbose", argv[i]) == 0)
- {
- gtester_quiet = FALSE;
- gtester_verbose = TRUE;
- argv[i] = NULL;
- }
- else if (strcmp ("-l", argv[i]) == 0)
- {
- gtester_list_tests = TRUE;
- argv[i] = NULL;
- }
- else if (strcmp ("--seed", argv[i]) == 0 || strncmp ("--seed=", argv[i], 7) == 0)
- {
- gchar *equal = argv[i] + 6;
- if (*equal == '=')
- subtest_seedstr = equal + 1;
- else if (i + 1 < argc)
- {
- argv[i++] = NULL;
- subtest_seedstr = argv[i];
- }
- argv[i] = NULL;
- }
- }
- /* collapse argv */
- e = 1;
- for (i = 1; i < argc; i++)
- if (argv[i])
- {
- argv[e++] = argv[i];
- if (i >= e)
- argv[i] = NULL;
- }
- *argc_p = e;
-}
-
-int
-main (int argc,
- char **argv)
-{
- guint ui;
-
- /* some unices need SA_RESTART for SIGCHLD to return -EAGAIN for io.
- * we must fiddle with sigaction() *before* glib is used, otherwise
- * we could revoke signal hanmdler setups from glib initialization code.
- */
- if (TRUE)
- {
- struct sigaction sa;
- struct sigaction osa;
- sa.sa_handler = SIG_DFL;
- sigfillset (&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- sigaction (SIGCHLD, &sa, &osa);
- }
-
- g_set_prgname (argv[0]);
- parse_args (&argc, &argv);
- if (gtester_selftest)
- return main_selftest (argc, argv);
-
- if (argc <= 1)
- {
- usage (FALSE);
- return 1;
- }
-
- if (output_filename)
- {
- log_fd = g_open (output_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
- if (log_fd < 0)
- g_error ("Failed to open log file '%s': %s", output_filename, g_strerror (errno));
- }
-
- test_log_printfe ("<?xml version=\"1.0\"?>\n");
- test_log_printfe ("%s<gtester>\n", sindent (log_indent));
- log_indent += 2;
- for (ui = 1; ui < argc; ui++)
- {
- const char *binary = argv[ui];
- launch_test (binary);
- /* we only get here on success or if !subtest_mode_fatal */
- }
- log_indent -= 2;
- test_log_printfe ("%s</gtester>\n", sindent (log_indent));
-
- close (log_fd);
-
- return 0;
-}
-
-static void
-fixture_setup (guint *fix,
- gconstpointer test_data)
-{
- g_assert_cmphex (*fix, ==, 0);
- *fix = 0xdeadbeef;
-}
-static void
-fixture_test (guint *fix,
- gconstpointer test_data)
-{
- g_assert_cmphex (*fix, ==, 0xdeadbeef);
- g_test_message ("This is a test message API test message.");
- g_test_bug_base ("http://www.example.com/bugtracker/");
- g_test_bug ("123");
- g_test_bug_base ("http://www.example.com/bugtracker?bugnum=%s;cmd=showbug");
- g_test_bug ("456");
-}
-static void
-fixture_teardown (guint *fix,
- gconstpointer test_data)
-{
- g_assert_cmphex (*fix, ==, 0xdeadbeef);
-}
-
-static int
-main_selftest (int argc,
- char **argv)
-{
- /* gtester main() for --gtester-selftest invokations */
- g_test_init (&argc, &argv, NULL);
- g_test_add ("/gtester/fixture-test", guint, NULL, fixture_setup, fixture_test, fixture_teardown);
- return g_test_run();
-}
diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c
deleted file mode 100644
index 2059a999d..000000000
--- a/glib/gthreadpool.c
+++ /dev/null
@@ -1,945 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * GAsyncQueue: thread pool implementation.
- * Copyright (C) 2000 Sebastian Wilhelmi; University of Karlsruhe
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#include "glib.h"
-#include "galias.h"
-
-#define DEBUG_MSG(x)
-/* #define DEBUG_MSG(args) g_printerr args ; g_printerr ("\n"); */
-
-typedef struct _GRealThreadPool GRealThreadPool;
-
-struct _GRealThreadPool
-{
- GThreadPool pool;
- GAsyncQueue* queue;
- GCond* cond;
- gint max_threads;
- gint num_threads;
- gboolean running;
- gboolean immediate;
- gboolean waiting;
- GCompareDataFunc sort_func;
- gpointer sort_user_data;
-};
-
-/* The following is just an address to mark the wakeup order for a
- * thread, it could be any address (as long, as it isn't a valid
- * GThreadPool address) */
-static const gpointer wakeup_thread_marker = (gpointer) &g_thread_pool_new;
-static gint wakeup_thread_serial = 0;
-
-/* Here all unused threads are waiting */
-static GAsyncQueue *unused_thread_queue = NULL;
-static gint unused_threads = 0;
-static gint max_unused_threads = 0;
-static gint kill_unused_threads = 0;
-static guint max_idle_time = 0;
-
-static void g_thread_pool_queue_push_unlocked (GRealThreadPool *pool,
- gpointer data);
-static void g_thread_pool_free_internal (GRealThreadPool *pool);
-static gpointer g_thread_pool_thread_proxy (gpointer data);
-static void g_thread_pool_start_thread (GRealThreadPool *pool,
- GError **error);
-static void g_thread_pool_wakeup_and_stop_all (GRealThreadPool *pool);
-static GRealThreadPool* g_thread_pool_wait_for_new_pool (void);
-static gpointer g_thread_pool_wait_for_new_task (GRealThreadPool *pool);
-
-static void
-g_thread_pool_queue_push_unlocked (GRealThreadPool *pool,
- gpointer data)
-{
- if (pool->sort_func)
- g_async_queue_push_sorted_unlocked (pool->queue,
- data,
- pool->sort_func,
- pool->sort_user_data);
- else
- g_async_queue_push_unlocked (pool->queue, data);
-}
-
-static GRealThreadPool*
-g_thread_pool_wait_for_new_pool (void)
-{
- GRealThreadPool *pool;
- gint local_wakeup_thread_serial;
- guint local_max_unused_threads;
- gint local_max_idle_time;
- gint last_wakeup_thread_serial;
- gboolean have_relayed_thread_marker = FALSE;
-
- local_max_unused_threads = g_atomic_int_get (&max_unused_threads);
- local_max_idle_time = g_atomic_int_get (&max_idle_time);
- last_wakeup_thread_serial = g_atomic_int_get (&wakeup_thread_serial);
-
- g_atomic_int_inc (&unused_threads);
-
- do
- {
- if (g_atomic_int_get (&unused_threads) >= local_max_unused_threads)
- {
- /* If this is a superfluous thread, stop it. */
- pool = NULL;
- }
- else if (local_max_idle_time > 0)
- {
- /* If a maximal idle time is given, wait for the given time. */
- GTimeVal end_time;
-
- g_get_current_time (&end_time);
- g_time_val_add (&end_time, local_max_idle_time * 1000);
-
- DEBUG_MSG (("thread %p waiting in global pool for %f seconds.",
- g_thread_self (), local_max_idle_time / 1000.0));
-
- pool = g_async_queue_timed_pop (unused_thread_queue, &end_time);
- }
- else
- {
- /* If no maximal idle time is given, wait indefinitely. */
- DEBUG_MSG (("thread %p waiting in global pool.",
- g_thread_self ()));
- pool = g_async_queue_pop (unused_thread_queue);
- }
-
- if (pool == wakeup_thread_marker)
- {
- local_wakeup_thread_serial = g_atomic_int_get (&wakeup_thread_serial);
- if (last_wakeup_thread_serial == local_wakeup_thread_serial)
- {
- if (!have_relayed_thread_marker)
- {
- /* If this wakeup marker has been received for
- * the second time, relay it.
- */
- DEBUG_MSG (("thread %p relaying wakeup message to "
- "waiting thread with lower serial.",
- g_thread_self ()));
-
- g_async_queue_push (unused_thread_queue, wakeup_thread_marker);
- have_relayed_thread_marker = TRUE;
-
- /* If a wakeup marker has been relayed, this thread
- * will get out of the way for 100 microseconds to
- * avoid receiving this marker again. */
- g_usleep (100);
- }
- }
- else
- {
- if (g_atomic_int_exchange_and_add (&kill_unused_threads, -1) > 0)
- {
- pool = NULL;
- break;
- }
-
- DEBUG_MSG (("thread %p updating to new limits.",
- g_thread_self ()));
-
- local_max_unused_threads = g_atomic_int_get (&max_unused_threads);
- local_max_idle_time = g_atomic_int_get (&max_idle_time);
- last_wakeup_thread_serial = local_wakeup_thread_serial;
-
- have_relayed_thread_marker = FALSE;
- }
- }
- }
- while (pool == wakeup_thread_marker);
-
- g_atomic_int_add (&unused_threads, -1);
-
- return pool;
-}
-
-static gpointer
-g_thread_pool_wait_for_new_task (GRealThreadPool *pool)
-{
- gpointer task = NULL;
-
- if (pool->running || (!pool->immediate &&
- g_async_queue_length_unlocked (pool->queue) > 0))
- {
- /* This thread pool is still active. */
- if (pool->num_threads > pool->max_threads && pool->max_threads != -1)
- {
- /* This is a superfluous thread, so it goes to the global pool. */
- DEBUG_MSG (("superfluous thread %p in pool %p.",
- g_thread_self (), pool));
- }
- else if (pool->pool.exclusive)
- {
- /* Exclusive threads stay attached to the pool. */
- task = g_async_queue_pop_unlocked (pool->queue);
-
- DEBUG_MSG (("thread %p in exclusive pool %p waits for task "
- "(%d running, %d unprocessed).",
- g_thread_self (), pool, pool->num_threads,
- g_async_queue_length_unlocked (pool->queue)));
- }
- else
- {
- /* A thread will wait for new tasks for at most 1/2
- * second before going to the global pool.
- */
- GTimeVal end_time;
-
- g_get_current_time (&end_time);
- g_time_val_add (&end_time, G_USEC_PER_SEC / 2); /* 1/2 second */
-
- DEBUG_MSG (("thread %p in pool %p waits for up to a 1/2 second for task "
- "(%d running, %d unprocessed).",
- g_thread_self (), pool, pool->num_threads,
- g_async_queue_length_unlocked (pool->queue)));
-
- task = g_async_queue_timed_pop_unlocked (pool->queue, &end_time);
- }
- }
- else
- {
- /* This thread pool is inactive, it will no longer process tasks. */
- DEBUG_MSG (("pool %p not active, thread %p will go to global pool "
- "(running: %s, immediate: %s, len: %d).",
- pool, g_thread_self (),
- pool->running ? "true" : "false",
- pool->immediate ? "true" : "false",
- g_async_queue_length_unlocked (pool->queue)));
- }
-
- return task;
-}
-
-
-static gpointer
-g_thread_pool_thread_proxy (gpointer data)
-{
- GRealThreadPool *pool;
-
- pool = data;
-
- DEBUG_MSG (("thread %p started for pool %p.",
- g_thread_self (), pool));
-
- g_async_queue_lock (pool->queue);
-
- while (TRUE)
- {
- gpointer task;
-
- task = g_thread_pool_wait_for_new_task (pool);
- if (task)
- {
- if (pool->running || !pool->immediate)
- {
- /* A task was received and the thread pool is active, so
- * execute the function.
- */
- g_async_queue_unlock (pool->queue);
- DEBUG_MSG (("thread %p in pool %p calling func.",
- g_thread_self (), pool));
- pool->pool.func (task, pool->pool.user_data);
- g_async_queue_lock (pool->queue);
- }
- }
- else
- {
- /* No task was received, so this thread goes to the global
- * pool.
- */
- gboolean free_pool = FALSE;
-
- DEBUG_MSG (("thread %p leaving pool %p for global pool.",
- g_thread_self (), pool));
- pool->num_threads--;
-
- if (!pool->running)
- {
- if (!pool->waiting)
- {
- if (pool->num_threads == 0)
- {
- /* If the pool is not running and no other
- * thread is waiting for this thread pool to
- * finish and this is the last thread of this
- * pool, free the pool.
- */
- free_pool = TRUE;
- }
- else
- {
- /* If the pool is not running and no other
- * thread is waiting for this thread pool to
- * finish and this is not the last thread of
- * this pool and there are no tasks left in the
- * queue, wakeup the remaining threads.
- */
- if (g_async_queue_length_unlocked (pool->queue) ==
- - pool->num_threads)
- g_thread_pool_wakeup_and_stop_all (pool);
- }
- }
- else if (pool->immediate ||
- g_async_queue_length_unlocked (pool->queue) <= 0)
- {
- /* If the pool is not running and another thread is
- * waiting for this thread pool to finish and there
- * are either no tasks left or the pool shall stop
- * immediatly, inform the waiting thread of a change
- * of the thread pool state.
- */
- g_cond_broadcast (pool->cond);
- }
- }
-
- g_async_queue_unlock (pool->queue);
-
- if (free_pool)
- g_thread_pool_free_internal (pool);
-
- if ((pool = g_thread_pool_wait_for_new_pool ()) == NULL)
- break;
-
- g_async_queue_lock (pool->queue);
-
- DEBUG_MSG (("thread %p entering pool %p from global pool.",
- g_thread_self (), pool));
-
- /* pool->num_threads++ is not done here, but in
- * g_thread_pool_start_thread to make the new started thread
- * known to the pool, before itself can do it.
- */
- }
- }
-
- return NULL;
-}
-
-static void
-g_thread_pool_start_thread (GRealThreadPool *pool,
- GError **error)
-{
- gboolean success = FALSE;
-
- if (pool->num_threads >= pool->max_threads && pool->max_threads != -1)
- /* Enough threads are already running */
- return;
-
- g_async_queue_lock (unused_thread_queue);
-
- if (g_async_queue_length_unlocked (unused_thread_queue) < 0)
- {
- g_async_queue_push_unlocked (unused_thread_queue, pool);
- success = TRUE;
- }
-
- g_async_queue_unlock (unused_thread_queue);
-
- if (!success)
- {
- GError *local_error = NULL;
- /* No thread was found, we have to start a new one */
- g_thread_create (g_thread_pool_thread_proxy, pool, FALSE, &local_error);
-
- if (local_error)
- {
- g_propagate_error (error, local_error);
- return;
- }
- }
-
- /* See comment in g_thread_pool_thread_proxy as to why this is done
- * here and not there
- */
- pool->num_threads++;
-}
-
-/**
- * g_thread_pool_new:
- * @func: a function to execute in the threads of the new thread pool
- * @user_data: user data that is handed over to @func every time it
- * is called
- * @max_threads: the maximal number of threads to execute concurrently in
- * the new thread pool, -1 means no limit
- * @exclusive: should this thread pool be exclusive?
- * @error: return location for error
- *
- * This function creates a new thread pool.
- *
- * Whenever you call g_thread_pool_push(), either a new thread is
- * created or an unused one is reused. At most @max_threads threads
- * are running concurrently for this thread pool. @max_threads = -1
- * allows unlimited threads to be created for this thread pool. The
- * newly created or reused thread now executes the function @func with
- * the two arguments. The first one is the parameter to
- * g_thread_pool_push() and the second one is @user_data.
- *
- * The parameter @exclusive determines, whether the thread pool owns
- * all threads exclusive or whether the threads are shared
- * globally. If @exclusive is %TRUE, @max_threads threads are started
- * immediately and they will run exclusively for this thread pool until
- * it is destroyed by g_thread_pool_free(). If @exclusive is %FALSE,
- * threads are created, when needed and shared between all
- * non-exclusive thread pools. This implies that @max_threads may not
- * be -1 for exclusive thread pools.
- *
- * @error can be %NULL to ignore errors, or non-%NULL to report
- * errors. An error can only occur when @exclusive is set to %TRUE and
- * not all @max_threads threads could be created.
- *
- * Return value: the new #GThreadPool
- **/
-GThreadPool*
-g_thread_pool_new (GFunc func,
- gpointer user_data,
- gint max_threads,
- gboolean exclusive,
- GError **error)
-{
- GRealThreadPool *retval;
- G_LOCK_DEFINE_STATIC (init);
-
- g_return_val_if_fail (func, NULL);
- g_return_val_if_fail (!exclusive || max_threads != -1, NULL);
- g_return_val_if_fail (max_threads >= -1, NULL);
- g_return_val_if_fail (g_thread_supported (), NULL);
-
- retval = g_new (GRealThreadPool, 1);
-
- retval->pool.func = func;
- retval->pool.user_data = user_data;
- retval->pool.exclusive = exclusive;
- retval->queue = g_async_queue_new ();
- retval->cond = NULL;
- retval->max_threads = max_threads;
- retval->num_threads = 0;
- retval->running = TRUE;
- retval->sort_func = NULL;
- retval->sort_user_data = NULL;
-
- G_LOCK (init);
- if (!unused_thread_queue)
- unused_thread_queue = g_async_queue_new ();
- G_UNLOCK (init);
-
- if (retval->pool.exclusive)
- {
- g_async_queue_lock (retval->queue);
-
- while (retval->num_threads < retval->max_threads)
- {
- GError *local_error = NULL;
- g_thread_pool_start_thread (retval, &local_error);
- if (local_error)
- {
- g_propagate_error (error, local_error);
- break;
- }
- }
-
- g_async_queue_unlock (retval->queue);
- }
-
- return (GThreadPool*) retval;
-}
-
-/**
- * g_thread_pool_push:
- * @pool: a #GThreadPool
- * @data: a new task for @pool
- * @error: return location for error
- *
- * Inserts @data into the list of tasks to be executed by @pool. When
- * the number of currently running threads is lower than the maximal
- * allowed number of threads, a new thread is started (or reused) with
- * the properties given to g_thread_pool_new (). Otherwise @data stays
- * in the queue until a thread in this pool finishes its previous task
- * and processes @data.
- *
- * @error can be %NULL to ignore errors, or non-%NULL to report
- * errors. An error can only occur when a new thread couldn't be
- * created. In that case @data is simply appended to the queue of work
- * to do.
- **/
-void
-g_thread_pool_push (GThreadPool *pool,
- gpointer data,
- GError **error)
-{
- GRealThreadPool *real;
-
- real = (GRealThreadPool*) pool;
-
- g_return_if_fail (real);
- g_return_if_fail (real->running);
-
- g_async_queue_lock (real->queue);
-
- if (g_async_queue_length_unlocked (real->queue) >= 0)
- /* No thread is waiting in the queue */
- g_thread_pool_start_thread (real, error);
-
- g_thread_pool_queue_push_unlocked (real, data);
- g_async_queue_unlock (real->queue);
-}
-
-/**
- * g_thread_pool_set_max_threads:
- * @pool: a #GThreadPool
- * @max_threads: a new maximal number of threads for @pool
- * @error: return location for error
- *
- * Sets the maximal allowed number of threads for @pool. A value of -1
- * means, that the maximal number of threads is unlimited.
- *
- * Setting @max_threads to 0 means stopping all work for @pool. It is
- * effectively frozen until @max_threads is set to a non-zero value
- * again.
- *
- * A thread is never terminated while calling @func, as supplied by
- * g_thread_pool_new (). Instead the maximal number of threads only
- * has effect for the allocation of new threads in g_thread_pool_push().
- * A new thread is allocated, whenever the number of currently
- * running threads in @pool is smaller than the maximal number.
- *
- * @error can be %NULL to ignore errors, or non-%NULL to report
- * errors. An error can only occur when a new thread couldn't be
- * created.
- **/
-void
-g_thread_pool_set_max_threads (GThreadPool *pool,
- gint max_threads,
- GError **error)
-{
- GRealThreadPool *real;
- gint to_start;
-
- real = (GRealThreadPool*) pool;
-
- g_return_if_fail (real);
- g_return_if_fail (real->running);
- g_return_if_fail (!real->pool.exclusive || max_threads != -1);
- g_return_if_fail (max_threads >= -1);
-
- g_async_queue_lock (real->queue);
-
- real->max_threads = max_threads;
-
- if (pool->exclusive)
- to_start = real->max_threads - real->num_threads;
- else
- to_start = g_async_queue_length_unlocked (real->queue);
-
- for ( ; to_start > 0; to_start--)
- {
- GError *local_error = NULL;
-
- g_thread_pool_start_thread (real, &local_error);
- if (local_error)
- {
- g_propagate_error (error, local_error);
- break;
- }
- }
-
- g_async_queue_unlock (real->queue);
-}
-
-/**
- * g_thread_pool_get_max_threads:
- * @pool: a #GThreadPool
- *
- * Returns the maximal number of threads for @pool.
- *
- * Return value: the maximal number of threads
- **/
-gint
-g_thread_pool_get_max_threads (GThreadPool *pool)
-{
- GRealThreadPool *real;
- gint retval;
-
- real = (GRealThreadPool*) pool;
-
- g_return_val_if_fail (real, 0);
- g_return_val_if_fail (real->running, 0);
-
- g_async_queue_lock (real->queue);
- retval = real->max_threads;
- g_async_queue_unlock (real->queue);
-
- return retval;
-}
-
-/**
- * g_thread_pool_get_num_threads:
- * @pool: a #GThreadPool
- *
- * Returns the number of threads currently running in @pool.
- *
- * Return value: the number of threads currently running
- **/
-guint
-g_thread_pool_get_num_threads (GThreadPool *pool)
-{
- GRealThreadPool *real;
- guint retval;
-
- real = (GRealThreadPool*) pool;
-
- g_return_val_if_fail (real, 0);
- g_return_val_if_fail (real->running, 0);
-
- g_async_queue_lock (real->queue);
- retval = real->num_threads;
- g_async_queue_unlock (real->queue);
-
- return retval;
-}
-
-/**
- * g_thread_pool_unprocessed:
- * @pool: a #GThreadPool
- *
- * Returns the number of tasks still unprocessed in @pool.
- *
- * Return value: the number of unprocessed tasks
- **/
-guint
-g_thread_pool_unprocessed (GThreadPool *pool)
-{
- GRealThreadPool *real;
- gint unprocessed;
-
- real = (GRealThreadPool*) pool;
-
- g_return_val_if_fail (real, 0);
- g_return_val_if_fail (real->running, 0);
-
- unprocessed = g_async_queue_length (real->queue);
-
- return MAX (unprocessed, 0);
-}
-
-/**
- * g_thread_pool_free:
- * @pool: a #GThreadPool
- * @immediate: should @pool shut down immediately?
- * @wait_: should the function wait for all tasks to be finished?
- *
- * Frees all resources allocated for @pool.
- *
- * If @immediate is %TRUE, no new task is processed for
- * @pool. Otherwise @pool is not freed before the last task is
- * processed. Note however, that no thread of this pool is
- * interrupted, while processing a task. Instead at least all still
- * running threads can finish their tasks before the @pool is freed.
- *
- * If @wait_ is %TRUE, the functions does not return before all tasks
- * to be processed (dependent on @immediate, whether all or only the
- * currently running) are ready. Otherwise the function returns immediately.
- *
- * After calling this function @pool must not be used anymore.
- **/
-void
-g_thread_pool_free (GThreadPool *pool,
- gboolean immediate,
- gboolean wait_)
-{
- GRealThreadPool *real;
-
- real = (GRealThreadPool*) pool;
-
- g_return_if_fail (real);
- g_return_if_fail (real->running);
-
- /* If there's no thread allowed here, there is not much sense in
- * not stopping this pool immediately, when it's not empty
- */
- g_return_if_fail (immediate ||
- real->max_threads != 0 ||
- g_async_queue_length (real->queue) == 0);
-
- g_async_queue_lock (real->queue);
-
- real->running = FALSE;
- real->immediate = immediate;
- real->waiting = wait_;
-
- if (wait_)
- {
- real->cond = g_cond_new ();
-
- while (g_async_queue_length_unlocked (real->queue) != -real->num_threads &&
- !(immediate && real->num_threads == 0))
- g_cond_wait (real->cond, _g_async_queue_get_mutex (real->queue));
- }
-
- if (immediate || g_async_queue_length_unlocked (real->queue) == -real->num_threads)
- {
- /* No thread is currently doing something (and nothing is left
- * to process in the queue)
- */
- if (real->num_threads == 0)
- {
- /* No threads left, we clean up */
- g_async_queue_unlock (real->queue);
- g_thread_pool_free_internal (real);
- return;
- }
-
- g_thread_pool_wakeup_and_stop_all (real);
- }
-
- /* The last thread should cleanup the pool */
- real->waiting = FALSE;
- g_async_queue_unlock (real->queue);
-}
-
-static void
-g_thread_pool_free_internal (GRealThreadPool* pool)
-{
- g_return_if_fail (pool);
- g_return_if_fail (pool->running == FALSE);
- g_return_if_fail (pool->num_threads == 0);
-
- g_async_queue_unref (pool->queue);
-
- if (pool->cond)
- g_cond_free (pool->cond);
-
- g_free (pool);
-}
-
-static void
-g_thread_pool_wakeup_and_stop_all (GRealThreadPool* pool)
-{
- guint i;
-
- g_return_if_fail (pool);
- g_return_if_fail (pool->running == FALSE);
- g_return_if_fail (pool->num_threads != 0);
-
- pool->immediate = TRUE;
-
- for (i = 0; i < pool->num_threads; i++)
- g_thread_pool_queue_push_unlocked (pool, GUINT_TO_POINTER (1));
-}
-
-/**
- * g_thread_pool_set_max_unused_threads:
- * @max_threads: maximal number of unused threads
- *
- * Sets the maximal number of unused threads to @max_threads. If
- * @max_threads is -1, no limit is imposed on the number of unused
- * threads.
- **/
-void
-g_thread_pool_set_max_unused_threads (gint max_threads)
-{
- g_return_if_fail (max_threads >= -1);
-
- g_atomic_int_set (&max_unused_threads, max_threads);
-
- if (max_threads != -1)
- {
- max_threads -= g_atomic_int_get (&unused_threads);
- if (max_threads < 0)
- {
- g_atomic_int_set (&kill_unused_threads, -max_threads);
- g_atomic_int_inc (&wakeup_thread_serial);
-
- g_async_queue_lock (unused_thread_queue);
-
- do
- {
- g_async_queue_push_unlocked (unused_thread_queue,
- wakeup_thread_marker);
- }
- while (++max_threads);
-
- g_async_queue_unlock (unused_thread_queue);
- }
- }
-}
-
-/**
- * g_thread_pool_get_max_unused_threads:
- *
- * Returns the maximal allowed number of unused threads.
- *
- * Return value: the maximal number of unused threads
- **/
-gint
-g_thread_pool_get_max_unused_threads (void)
-{
- return g_atomic_int_get (&max_unused_threads);
-}
-
-/**
- * g_thread_pool_get_num_unused_threads:
- *
- * Returns the number of currently unused threads.
- *
- * Return value: the number of currently unused threads
- **/
-guint
-g_thread_pool_get_num_unused_threads (void)
-{
- return g_atomic_int_get (&unused_threads);
-}
-
-/**
- * g_thread_pool_stop_unused_threads:
- *
- * Stops all currently unused threads. This does not change the
- * maximal number of unused threads. This function can be used to
- * regularly stop all unused threads e.g. from g_timeout_add().
- **/
-void
-g_thread_pool_stop_unused_threads (void)
-{
- guint oldval;
-
- oldval = g_thread_pool_get_max_unused_threads ();
-
- g_thread_pool_set_max_unused_threads (0);
- g_thread_pool_set_max_unused_threads (oldval);
-}
-
-/**
- * g_thread_pool_set_sort_function:
- * @pool: a #GThreadPool
- * @func: the #GCompareDataFunc used to sort the list of tasks.
- * This function is passed two tasks. It should return
- * 0 if the order in which they are handled does not matter,
- * a negative value if the first task should be processed before
- * the second or a positive value if the second task should be
- * processed first.
- * @user_data: user data passed to @func.
- *
- * Sets the function used to sort the list of tasks. This allows the
- * tasks to be processed by a priority determined by @func, and not
- * just in the order in which they were added to the pool.
- *
- * Note, if the maximum number of threads is more than 1, the order
- * that threads are executed can not be guranteed 100%. Threads are
- * scheduled by the operating system and are executed at random. It
- * cannot be assumed that threads are executed in the order they are
- * created.
- *
- * Since: 2.10
- **/
-void
-g_thread_pool_set_sort_function (GThreadPool *pool,
- GCompareDataFunc func,
- gpointer user_data)
-{
- GRealThreadPool *real;
-
- real = (GRealThreadPool*) pool;
-
- g_return_if_fail (real);
- g_return_if_fail (real->running);
-
- g_async_queue_lock (real->queue);
-
- real->sort_func = func;
- real->sort_user_data = user_data;
-
- if (func)
- g_async_queue_sort_unlocked (real->queue,
- real->sort_func,
- real->sort_user_data);
-
- g_async_queue_unlock (real->queue);
-}
-
-/**
- * g_thread_pool_set_max_idle_time:
- * @interval: the maximum @interval (1/1000ths of a second) a thread
- * can be idle.
- *
- * This function will set the maximum @interval that a thread waiting
- * in the pool for new tasks can be idle for before being
- * stopped. This function is similar to calling
- * g_thread_pool_stop_unused_threads() on a regular timeout, except,
- * this is done on a per thread basis.
- *
- * By setting @interval to 0, idle threads will not be stopped.
- *
- * This function makes use of g_async_queue_timed_pop () using
- * @interval.
- *
- * Since: 2.10
- **/
-void
-g_thread_pool_set_max_idle_time (guint interval)
-{
- guint i;
-
- g_atomic_int_set (&max_idle_time, interval);
-
- i = g_atomic_int_get (&unused_threads);
- if (i > 0)
- {
- g_atomic_int_inc (&wakeup_thread_serial);
- g_async_queue_lock (unused_thread_queue);
-
- do
- {
- g_async_queue_push_unlocked (unused_thread_queue,
- wakeup_thread_marker);
- }
- while (--i);
-
- g_async_queue_unlock (unused_thread_queue);
- }
-}
-
-/**
- * g_thread_pool_get_max_idle_time:
- *
- * This function will return the maximum @interval that a thread will
- * wait in the thread pool for new tasks before being stopped.
- *
- * If this function returns 0, threads waiting in the thread pool for
- * new work are not stopped.
- *
- * Return value: the maximum @interval to wait for new tasks in the
- * thread pool before stopping the thread (1/1000ths of a second).
- *
- * Since: 2.10
- **/
-guint
-g_thread_pool_get_max_idle_time (void)
-{
- return g_atomic_int_get (&max_idle_time);
-}
-
-#define __G_THREADPOOL_C__
-#include "galiasdef.c"
diff --git a/glib/gtree.c b/glib/gtree.c
deleted file mode 100644
index 8ae5e9812..000000000
--- a/glib/gtree.c
+++ /dev/null
@@ -1,1290 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * MT safe
- */
-
-#include "config.h"
-
-#include "glib.h"
-#include "galias.h"
-
-#undef G_TREE_DEBUG
-
-#define MAX_GTREE_HEIGHT 40
-
-typedef struct _GTreeNode GTreeNode;
-
-struct _GTree
-{
- GTreeNode *root;
- GCompareDataFunc key_compare;
- GDestroyNotify key_destroy_func;
- GDestroyNotify value_destroy_func;
- gpointer key_compare_data;
- guint nnodes;
-};
-
-struct _GTreeNode
-{
- gpointer key; /* key for this node */
- gpointer value; /* value stored at this node */
- GTreeNode *left; /* left subtree */
- GTreeNode *right; /* right subtree */
- gint8 balance; /* height (left) - height (right) */
- guint8 left_child;
- guint8 right_child;
-};
-
-
-static GTreeNode* g_tree_node_new (gpointer key,
- gpointer value);
-static void g_tree_insert_internal (GTree *tree,
- gpointer key,
- gpointer value,
- gboolean replace);
-static gboolean g_tree_remove_internal (GTree *tree,
- gconstpointer key,
- gboolean steal);
-static GTreeNode* g_tree_node_balance (GTreeNode *node);
-static GTreeNode *g_tree_find_node (GTree *tree,
- gconstpointer key);
-static gint g_tree_node_pre_order (GTreeNode *node,
- GTraverseFunc traverse_func,
- gpointer data);
-static gint g_tree_node_in_order (GTreeNode *node,
- GTraverseFunc traverse_func,
- gpointer data);
-static gint g_tree_node_post_order (GTreeNode *node,
- GTraverseFunc traverse_func,
- gpointer data);
-static gpointer g_tree_node_search (GTreeNode *node,
- GCompareFunc search_func,
- gconstpointer data);
-static GTreeNode* g_tree_node_rotate_left (GTreeNode *node);
-static GTreeNode* g_tree_node_rotate_right (GTreeNode *node);
-#ifdef G_TREE_DEBUG
-static void g_tree_node_check (GTreeNode *node);
-#endif
-
-
-static GTreeNode*
-g_tree_node_new (gpointer key,
- gpointer value)
-{
- GTreeNode *node = g_slice_new (GTreeNode);
-
- node->balance = 0;
- node->left = NULL;
- node->right = NULL;
- node->left_child = FALSE;
- node->right_child = FALSE;
- node->key = key;
- node->value = value;
-
- return node;
-}
-
-/**
- * g_tree_new:
- * @key_compare_func: the function used to order the nodes in the #GTree.
- * It should return values similar to the standard strcmp() function -
- * 0 if the two arguments are equal, a negative value if the first argument
- * comes before the second, or a positive value if the first argument comes
- * after the second.
- *
- * Creates a new #GTree.
- *
- * Return value: a new #GTree.
- **/
-GTree*
-g_tree_new (GCompareFunc key_compare_func)
-{
- g_return_val_if_fail (key_compare_func != NULL, NULL);
-
- return g_tree_new_full ((GCompareDataFunc) key_compare_func, NULL,
- NULL, NULL);
-}
-
-/**
- * g_tree_new_with_data:
- * @key_compare_func: qsort()-style comparison function.
- * @key_compare_data: data to pass to comparison function.
- *
- * Creates a new #GTree with a comparison function that accepts user data.
- * See g_tree_new() for more details.
- *
- * Return value: a new #GTree.
- **/
-GTree*
-g_tree_new_with_data (GCompareDataFunc key_compare_func,
- gpointer key_compare_data)
-{
- g_return_val_if_fail (key_compare_func != NULL, NULL);
-
- return g_tree_new_full (key_compare_func, key_compare_data,
- NULL, NULL);
-}
-
-/**
- * g_tree_new_full:
- * @key_compare_func: qsort()-style comparison function.
- * @key_compare_data: data to pass to comparison function.
- * @key_destroy_func: a function to free the memory allocated for the key
- * used when removing the entry from the #GTree or %NULL if you don't
- * want to supply such a function.
- * @value_destroy_func: a function to free the memory allocated for the
- * value used when removing the entry from the #GTree or %NULL if you
- * don't want to supply such a function.
- *
- * Creates a new #GTree like g_tree_new() and allows to specify functions
- * to free the memory allocated for the key and value that get called when
- * removing the entry from the #GTree.
- *
- * Return value: a new #GTree.
- **/
-GTree*
-g_tree_new_full (GCompareDataFunc key_compare_func,
- gpointer key_compare_data,
- GDestroyNotify key_destroy_func,
- GDestroyNotify value_destroy_func)
-{
- GTree *tree;
-
- g_return_val_if_fail (key_compare_func != NULL, NULL);
-
- tree = g_new (GTree, 1);
- tree->root = NULL;
- tree->key_compare = key_compare_func;
- tree->key_destroy_func = key_destroy_func;
- tree->value_destroy_func = value_destroy_func;
- tree->key_compare_data = key_compare_data;
- tree->nnodes = 0;
-
- return tree;
-}
-
-static inline GTreeNode *
-g_tree_first_node (GTree *tree)
-{
- GTreeNode *tmp;
-
- if (!tree->root)
- return NULL;
-
- tmp = tree->root;
-
- while (tmp->left_child)
- tmp = tmp->left;
-
- return tmp;
-}
-
-static inline GTreeNode *
-g_tree_node_previous (GTreeNode *node)
-{
- GTreeNode *tmp;
-
- tmp = node->left;
-
- if (node->left_child)
- while (tmp->right_child)
- tmp = tmp->right;
-
- return tmp;
-}
-
-static inline GTreeNode *
-g_tree_node_next (GTreeNode *node)
-{
- GTreeNode *tmp;
-
- tmp = node->right;
-
- if (node->right_child)
- while (tmp->left_child)
- tmp = tmp->left;
-
- return tmp;
-}
-
-/**
- * g_tree_destroy:
- * @tree: a #GTree.
- *
- * Destroys the #GTree. If keys and/or values are dynamically allocated, you
- * should either free them first or create the #GTree using g_tree_new_full().
- * In the latter case the destroy functions you supplied will be called on
- * all keys and values before destroying the #GTree.
- **/
-void
-g_tree_destroy (GTree *tree)
-{
- GTreeNode *node;
- GTreeNode *next;
-
- g_return_if_fail (tree != NULL);
-
- node = g_tree_first_node (tree);
-
- while (node)
- {
- next = g_tree_node_next (node);
-
- if (tree->key_destroy_func)
- tree->key_destroy_func (node->key);
- if (tree->value_destroy_func)
- tree->value_destroy_func (node->value);
- g_slice_free (GTreeNode, node);
-
- node = next;
- }
-
- g_free (tree);
-}
-
-/**
- * g_tree_insert:
- * @tree: a #GTree.
- * @key: the key to insert.
- * @value: the value corresponding to the key.
- *
- * Inserts a key/value pair into a #GTree. If the given key already exists
- * in the #GTree its corresponding value is set to the new value. If you
- * supplied a value_destroy_func when creating the #GTree, the old value is
- * freed using that function. If you supplied a @key_destroy_func when
- * creating the #GTree, the passed key is freed using that function.
- *
- * The tree is automatically 'balanced' as new key/value pairs are added,
- * so that the distance from the root to every leaf is as small as possible.
- **/
-void
-g_tree_insert (GTree *tree,
- gpointer key,
- gpointer value)
-{
- g_return_if_fail (tree != NULL);
-
- g_tree_insert_internal (tree, key, value, FALSE);
-
-#ifdef G_TREE_DEBUG
- g_tree_node_check (tree->root);
-#endif
-}
-
-/**
- * g_tree_replace:
- * @tree: a #GTree.
- * @key: the key to insert.
- * @value: the value corresponding to the key.
- *
- * Inserts a new key and value into a #GTree similar to g_tree_insert().
- * The difference is that if the key already exists in the #GTree, it gets
- * replaced by the new key. If you supplied a @value_destroy_func when
- * creating the #GTree, the old value is freed using that function. If you
- * supplied a @key_destroy_func when creating the #GTree, the old key is
- * freed using that function.
- *
- * The tree is automatically 'balanced' as new key/value pairs are added,
- * so that the distance from the root to every leaf is as small as possible.
- **/
-void
-g_tree_replace (GTree *tree,
- gpointer key,
- gpointer value)
-{
- g_return_if_fail (tree != NULL);
-
- g_tree_insert_internal (tree, key, value, TRUE);
-
-#ifdef G_TREE_DEBUG
- g_tree_node_check (tree->root);
-#endif
-}
-
-/* internal insert routine */
-static void
-g_tree_insert_internal (GTree *tree,
- gpointer key,
- gpointer value,
- gboolean replace)
-{
- GTreeNode *node;
- GTreeNode *path[MAX_GTREE_HEIGHT];
- int idx;
-
- g_return_if_fail (tree != NULL);
-
- if (!tree->root)
- {
- tree->root = g_tree_node_new (key, value);
- tree->nnodes++;
- return;
- }
-
- idx = 0;
- path[idx++] = NULL;
- node = tree->root;
-
- while (1)
- {
- int cmp = tree->key_compare (key, node->key, tree->key_compare_data);
-
- if (cmp == 0)
- {
- if (tree->value_destroy_func)
- tree->value_destroy_func (node->value);
-
- node->value = value;
-
- if (replace)
- {
- if (tree->key_destroy_func)
- tree->key_destroy_func (node->key);
-
- node->key = key;
- }
- else
- {
- /* free the passed key */
- if (tree->key_destroy_func)
- tree->key_destroy_func (key);
- }
-
- return;
- }
- else if (cmp < 0)
- {
- if (node->left_child)
- {
- path[idx++] = node;
- node = node->left;
- }
- else
- {
- GTreeNode *child = g_tree_node_new (key, value);
-
- child->left = node->left;
- child->right = node;
- node->left = child;
- node->left_child = TRUE;
- node->balance -= 1;
-
- tree->nnodes++;
-
- break;
- }
- }
- else
- {
- if (node->right_child)
- {
- path[idx++] = node;
- node = node->right;
- }
- else
- {
- GTreeNode *child = g_tree_node_new (key, value);
-
- child->right = node->right;
- child->left = node;
- node->right = child;
- node->right_child = TRUE;
- node->balance += 1;
-
- tree->nnodes++;
-
- break;
- }
- }
- }
-
- /* restore balance. This is the goodness of a non-recursive
- implementation, when we are done with balancing we 'break'
- the loop and we are done. */
- while (1)
- {
- GTreeNode *bparent = path[--idx];
- gboolean left_node = (bparent && node == bparent->left);
- g_assert (!bparent || bparent->left == node || bparent->right == node);
-
- if (node->balance < -1 || node->balance > 1)
- {
- node = g_tree_node_balance (node);
- if (bparent == NULL)
- tree->root = node;
- else if (left_node)
- bparent->left = node;
- else
- bparent->right = node;
- }
-
- if (node->balance == 0 || bparent == NULL)
- break;
-
- if (left_node)
- bparent->balance -= 1;
- else
- bparent->balance += 1;
-
- node = bparent;
- }
-}
-
-/**
- * g_tree_remove:
- * @tree: a #GTree.
- * @key: the key to remove.
- *
- * Removes a key/value pair from a #GTree.
- *
- * If the #GTree was created using g_tree_new_full(), the key and value
- * are freed using the supplied destroy functions, otherwise you have to
- * make sure that any dynamically allocated values are freed yourself.
- * If the key does not exist in the #GTree, the function does nothing.
- *
- * Returns: %TRUE if the key was found (prior to 2.8, this function returned
- * nothing)
- **/
-gboolean
-g_tree_remove (GTree *tree,
- gconstpointer key)
-{
- gboolean removed;
-
- g_return_val_if_fail (tree != NULL, FALSE);
-
- removed = g_tree_remove_internal (tree, key, FALSE);
-
-#ifdef G_TREE_DEBUG
- g_tree_node_check (tree->root);
-#endif
-
- return removed;
-}
-
-/**
- * g_tree_steal:
- * @tree: a #GTree.
- * @key: the key to remove.
- *
- * Removes a key and its associated value from a #GTree without calling
- * the key and value destroy functions.
- *
- * If the key does not exist in the #GTree, the function does nothing.
- *
- * Returns: %TRUE if the key was found (prior to 2.8, this function returned
- * nothing)
- **/
-gboolean
-g_tree_steal (GTree *tree,
- gconstpointer key)
-{
- gboolean removed;
-
- g_return_val_if_fail (tree != NULL, FALSE);
-
- removed = g_tree_remove_internal (tree, key, TRUE);
-
-#ifdef G_TREE_DEBUG
- g_tree_node_check (tree->root);
-#endif
-
- return removed;
-}
-
-/* internal remove routine */
-static gboolean
-g_tree_remove_internal (GTree *tree,
- gconstpointer key,
- gboolean steal)
-{
- GTreeNode *node, *parent, *balance;
- GTreeNode *path[MAX_GTREE_HEIGHT];
- int idx;
- gboolean left_node;
-
- g_return_val_if_fail (tree != NULL, FALSE);
-
- if (!tree->root)
- return FALSE;
-
- idx = 0;
- path[idx++] = NULL;
- node = tree->root;
-
- while (1)
- {
- int cmp = tree->key_compare (key, node->key, tree->key_compare_data);
-
- if (cmp == 0)
- break;
- else if (cmp < 0)
- {
- if (!node->left_child)
- return FALSE;
-
- path[idx++] = node;
- node = node->left;
- }
- else
- {
- if (!node->right_child)
- return FALSE;
-
- path[idx++] = node;
- node = node->right;
- }
- }
-
- /* the following code is almost equal to g_tree_remove_node,
- except that we do not have to call g_tree_node_parent. */
- balance = parent = path[--idx];
- g_assert (!parent || parent->left == node || parent->right == node);
- left_node = (parent && node == parent->left);
-
- if (!node->left_child)
- {
- if (!node->right_child)
- {
- if (!parent)
- tree->root = NULL;
- else if (left_node)
- {
- parent->left_child = FALSE;
- parent->left = node->left;
- parent->balance += 1;
- }
- else
- {
- parent->right_child = FALSE;
- parent->right = node->right;
- parent->balance -= 1;
- }
- }
- else /* node has a right child */
- {
- GTreeNode *tmp = g_tree_node_next (node);
- tmp->left = node->left;
-
- if (!parent)
- tree->root = node->right;
- else if (left_node)
- {
- parent->left = node->right;
- parent->balance += 1;
- }
- else
- {
- parent->right = node->right;
- parent->balance -= 1;
- }
- }
- }
- else /* node has a left child */
- {
- if (!node->right_child)
- {
- GTreeNode *tmp = g_tree_node_previous (node);
- tmp->right = node->right;
-
- if (parent == NULL)
- tree->root = node->left;
- else if (left_node)
- {
- parent->left = node->left;
- parent->balance += 1;
- }
- else
- {
- parent->right = node->left;
- parent->balance -= 1;
- }
- }
- else /* node has a both children (pant, pant!) */
- {
- GTreeNode *prev = node->left;
- GTreeNode *next = node->right;
- GTreeNode *nextp = node;
- int old_idx = idx + 1;
- idx++;
-
- /* path[idx] == parent */
- /* find the immediately next node (and its parent) */
- while (next->left_child)
- {
- path[++idx] = nextp = next;
- next = next->left;
- }
-
- path[old_idx] = next;
- balance = path[idx];
-
- /* remove 'next' from the tree */
- if (nextp != node)
- {
- if (next->right_child)
- nextp->left = next->right;
- else
- nextp->left_child = FALSE;
- nextp->balance += 1;
-
- next->right_child = TRUE;
- next->right = node->right;
- }
- else
- node->balance -= 1;
-
- /* set the prev to point to the right place */
- while (prev->right_child)
- prev = prev->right;
- prev->right = next;
-
- /* prepare 'next' to replace 'node' */
- next->left_child = TRUE;
- next->left = node->left;
- next->balance = node->balance;
-
- if (!parent)
- tree->root = next;
- else if (left_node)
- parent->left = next;
- else
- parent->right = next;
- }
- }
-
- /* restore balance */
- if (balance)
- while (1)
- {
- GTreeNode *bparent = path[--idx];
- g_assert (!bparent || bparent->left == balance || bparent->right == balance);
- left_node = (bparent && balance == bparent->left);
-
- if(balance->balance < -1 || balance->balance > 1)
- {
- balance = g_tree_node_balance (balance);
- if (!bparent)
- tree->root = balance;
- else if (left_node)
- bparent->left = balance;
- else
- bparent->right = balance;
- }
-
- if (balance->balance != 0 || !bparent)
- break;
-
- if (left_node)
- bparent->balance += 1;
- else
- bparent->balance -= 1;
-
- balance = bparent;
- }
-
- if (!steal)
- {
- if (tree->key_destroy_func)
- tree->key_destroy_func (node->key);
- if (tree->value_destroy_func)
- tree->value_destroy_func (node->value);
- }
-
- g_slice_free (GTreeNode, node);
-
- tree->nnodes--;
-
- return TRUE;
-}
-
-/**
- * g_tree_lookup:
- * @tree: a #GTree.
- * @key: the key to look up.
- *
- * Gets the value corresponding to the given key. Since a #GTree is
- * automatically balanced as key/value pairs are added, key lookup is very
- * fast.
- *
- * Return value: the value corresponding to the key, or %NULL if the key was
- * not found.
- **/
-gpointer
-g_tree_lookup (GTree *tree,
- gconstpointer key)
-{
- GTreeNode *node;
-
- g_return_val_if_fail (tree != NULL, NULL);
-
- node = g_tree_find_node (tree, key);
-
- return node ? node->value : NULL;
-}
-
-/**
- * g_tree_lookup_extended:
- * @tree: a #GTree.
- * @lookup_key: the key to look up.
- * @orig_key: returns the original key.
- * @value: returns the value associated with the key.
- *
- * Looks up a key in the #GTree, returning the original key and the
- * associated value and a #gboolean which is %TRUE if the key was found. This
- * is useful if you need to free the memory allocated for the original key,
- * for example before calling g_tree_remove().
- *
- * Return value: %TRUE if the key was found in the #GTree.
- **/
-gboolean
-g_tree_lookup_extended (GTree *tree,
- gconstpointer lookup_key,
- gpointer *orig_key,
- gpointer *value)
-{
- GTreeNode *node;
-
- g_return_val_if_fail (tree != NULL, FALSE);
-
- node = g_tree_find_node (tree, lookup_key);
-
- if (node)
- {
- if (orig_key)
- *orig_key = node->key;
- if (value)
- *value = node->value;
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * g_tree_foreach:
- * @tree: a #GTree.
- * @func: the function to call for each node visited. If this function
- * returns %TRUE, the traversal is stopped.
- * @user_data: user data to pass to the function.
- *
- * Calls the given function for each of the key/value pairs in the #GTree.
- * The function is passed the key and value of each pair, and the given
- * @data parameter. The tree is traversed in sorted order.
- *
- * The tree may not be modified while iterating over it (you can't
- * add/remove items). To remove all items matching a predicate, you need
- * to add each item to a list in your #GTraverseFunc as you walk over
- * the tree, then walk the list and remove each item.
- **/
-void
-g_tree_foreach (GTree *tree,
- GTraverseFunc func,
- gpointer user_data)
-{
- GTreeNode *node;
-
- g_return_if_fail (tree != NULL);
-
- if (!tree->root)
- return;
-
- node = g_tree_first_node (tree);
-
- while (node)
- {
- if ((*func) (node->key, node->value, user_data))
- break;
-
- node = g_tree_node_next (node);
- }
-}
-
-/**
- * g_tree_traverse:
- * @tree: a #GTree.
- * @traverse_func: the function to call for each node visited. If this
- * function returns %TRUE, the traversal is stopped.
- * @traverse_type: the order in which nodes are visited, one of %G_IN_ORDER,
- * %G_PRE_ORDER and %G_POST_ORDER.
- * @user_data: user data to pass to the function.
- *
- * Calls the given function for each node in the #GTree.
- *
- * Deprecated:2.2: The order of a balanced tree is somewhat arbitrary. If you
- * just want to visit all nodes in sorted order, use g_tree_foreach()
- * instead. If you really need to visit nodes in a different order, consider
- * using an <link linkend="glib-N-ary-Trees">N-ary Tree</link>.
- **/
-void
-g_tree_traverse (GTree *tree,
- GTraverseFunc traverse_func,
- GTraverseType traverse_type,
- gpointer user_data)
-{
- g_return_if_fail (tree != NULL);
-
- if (!tree->root)
- return;
-
- switch (traverse_type)
- {
- case G_PRE_ORDER:
- g_tree_node_pre_order (tree->root, traverse_func, user_data);
- break;
-
- case G_IN_ORDER:
- g_tree_node_in_order (tree->root, traverse_func, user_data);
- break;
-
- case G_POST_ORDER:
- g_tree_node_post_order (tree->root, traverse_func, user_data);
- break;
-
- case G_LEVEL_ORDER:
- g_warning ("g_tree_traverse(): traverse type G_LEVEL_ORDER isn't implemented.");
- break;
- }
-}
-
-/**
- * g_tree_search:
- * @tree: a #GTree.
- * @search_func: a function used to search the #GTree.
- * @user_data: the data passed as the second argument to the @search_func
- * function.
- *
- * Searches a #GTree using @search_func.
- *
- * The @search_func is called with a pointer to the key of a key/value pair in
- * the tree, and the passed in @user_data. If @search_func returns 0 for a
- * key/value pair, then g_tree_search_func() will return the value of that
- * pair. If @search_func returns -1, searching will proceed among the
- * key/value pairs that have a smaller key; if @search_func returns 1,
- * searching will proceed among the key/value pairs that have a larger key.
- *
- * Return value: the value corresponding to the found key, or %NULL if the key
- * was not found.
- **/
-gpointer
-g_tree_search (GTree *tree,
- GCompareFunc search_func,
- gconstpointer user_data)
-{
- g_return_val_if_fail (tree != NULL, NULL);
-
- if (tree->root)
- return g_tree_node_search (tree->root, search_func, user_data);
- else
- return NULL;
-}
-
-/**
- * g_tree_height:
- * @tree: a #GTree.
- *
- * Gets the height of a #GTree.
- *
- * If the #GTree contains no nodes, the height is 0.
- * If the #GTree contains only one root node the height is 1.
- * If the root node has children the height is 2, etc.
- *
- * Return value: the height of the #GTree.
- **/
-gint
-g_tree_height (GTree *tree)
-{
- GTreeNode *node;
- gint height;
-
- g_return_val_if_fail (tree != NULL, 0);
-
- if (!tree->root)
- return 0;
-
- height = 0;
- node = tree->root;
-
- while (1)
- {
- height += 1 + MAX(node->balance, 0);
-
- if (!node->left_child)
- return height;
-
- node = node->left;
- }
-}
-
-/**
- * g_tree_nnodes:
- * @tree: a #GTree.
- *
- * Gets the number of nodes in a #GTree.
- *
- * Return value: the number of nodes in the #GTree.
- **/
-gint
-g_tree_nnodes (GTree *tree)
-{
- g_return_val_if_fail (tree != NULL, 0);
-
- return tree->nnodes;
-}
-
-static GTreeNode*
-g_tree_node_balance (GTreeNode *node)
-{
- if (node->balance < -1)
- {
- if (node->left->balance > 0)
- node->left = g_tree_node_rotate_left (node->left);
- node = g_tree_node_rotate_right (node);
- }
- else if (node->balance > 1)
- {
- if (node->right->balance < 0)
- node->right = g_tree_node_rotate_right (node->right);
- node = g_tree_node_rotate_left (node);
- }
-
- return node;
-}
-
-static GTreeNode *
-g_tree_find_node (GTree *tree,
- gconstpointer key)
-{
- GTreeNode *node;
- gint cmp;
-
- node = tree->root;
- if (!node)
- return NULL;
-
- while (1)
- {
- cmp = tree->key_compare (key, node->key, tree->key_compare_data);
- if (cmp == 0)
- return node;
- else if (cmp < 0)
- {
- if (!node->left_child)
- return NULL;
-
- node = node->left;
- }
- else
- {
- if (!node->right_child)
- return NULL;
-
- node = node->right;
- }
- }
-}
-
-static gint
-g_tree_node_pre_order (GTreeNode *node,
- GTraverseFunc traverse_func,
- gpointer data)
-{
- if ((*traverse_func) (node->key, node->value, data))
- return TRUE;
-
- if (node->left_child)
- {
- if (g_tree_node_pre_order (node->left, traverse_func, data))
- return TRUE;
- }
-
- if (node->right_child)
- {
- if (g_tree_node_pre_order (node->right, traverse_func, data))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gint
-g_tree_node_in_order (GTreeNode *node,
- GTraverseFunc traverse_func,
- gpointer data)
-{
- if (node->left_child)
- {
- if (g_tree_node_in_order (node->left, traverse_func, data))
- return TRUE;
- }
-
- if ((*traverse_func) (node->key, node->value, data))
- return TRUE;
-
- if (node->right_child)
- {
- if (g_tree_node_in_order (node->right, traverse_func, data))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gint
-g_tree_node_post_order (GTreeNode *node,
- GTraverseFunc traverse_func,
- gpointer data)
-{
- if (node->left_child)
- {
- if (g_tree_node_post_order (node->left, traverse_func, data))
- return TRUE;
- }
-
- if (node->right_child)
- {
- if (g_tree_node_post_order (node->right, traverse_func, data))
- return TRUE;
- }
-
- if ((*traverse_func) (node->key, node->value, data))
- return TRUE;
-
- return FALSE;
-}
-
-static gpointer
-g_tree_node_search (GTreeNode *node,
- GCompareFunc search_func,
- gconstpointer data)
-{
- gint dir;
-
- if (!node)
- return NULL;
-
- while (1)
- {
- dir = (* search_func) (node->key, data);
- if (dir == 0)
- return node->value;
- else if (dir < 0)
- {
- if (!node->left_child)
- return NULL;
-
- node = node->left;
- }
- else
- {
- if (!node->right_child)
- return NULL;
-
- node = node->right;
- }
- }
-}
-
-static GTreeNode*
-g_tree_node_rotate_left (GTreeNode *node)
-{
- GTreeNode *right;
- gint a_bal;
- gint b_bal;
-
- right = node->right;
-
- if (right->left_child)
- node->right = right->left;
- else
- {
- node->right_child = FALSE;
- node->right = right;
- right->left_child = TRUE;
- }
- right->left = node;
-
- a_bal = node->balance;
- b_bal = right->balance;
-
- if (b_bal <= 0)
- {
- if (a_bal >= 1)
- right->balance = b_bal - 1;
- else
- right->balance = a_bal + b_bal - 2;
- node->balance = a_bal - 1;
- }
- else
- {
- if (a_bal <= b_bal)
- right->balance = a_bal - 2;
- else
- right->balance = b_bal - 1;
- node->balance = a_bal - b_bal - 1;
- }
-
- return right;
-}
-
-static GTreeNode*
-g_tree_node_rotate_right (GTreeNode *node)
-{
- GTreeNode *left;
- gint a_bal;
- gint b_bal;
-
- left = node->left;
-
- if (left->right_child)
- node->left = left->right;
- else
- {
- node->left_child = FALSE;
- node->left = left;
- left->right_child = TRUE;
- }
- left->right = node;
-
- a_bal = node->balance;
- b_bal = left->balance;
-
- if (b_bal <= 0)
- {
- if (b_bal > a_bal)
- left->balance = b_bal + 1;
- else
- left->balance = a_bal + 2;
- node->balance = a_bal - b_bal + 1;
- }
- else
- {
- if (a_bal <= -1)
- left->balance = b_bal + 1;
- else
- left->balance = a_bal + b_bal + 2;
- node->balance = a_bal + 1;
- }
-
- return left;
-}
-
-#ifdef G_TREE_DEBUG
-static gint
-g_tree_node_height (GTreeNode *node)
-{
- gint left_height;
- gint right_height;
-
- if (node)
- {
- left_height = 0;
- right_height = 0;
-
- if (node->left_child)
- left_height = g_tree_node_height (node->left);
-
- if (node->right_child)
- right_height = g_tree_node_height (node->right);
-
- return MAX (left_height, right_height) + 1;
- }
-
- return 0;
-}
-
-static void
-g_tree_node_check (GTreeNode *node)
-{
- gint left_height;
- gint right_height;
- gint balance;
- GTreeNode *tmp;
-
- if (node)
- {
- if (node->left_child)
- {
- tmp = g_tree_node_previous (node);
- g_assert (tmp->right == node);
- }
-
- if (node->right_child)
- {
- tmp = g_tree_node_next (node);
- g_assert (tmp->left == node);
- }
-
- left_height = 0;
- right_height = 0;
-
- if (node->left_child)
- left_height = g_tree_node_height (node->left);
- if (node->right_child)
- right_height = g_tree_node_height (node->right);
-
- balance = right_height - left_height;
- g_assert (balance == node->balance);
-
- if (node->left_child)
- g_tree_node_check (node->left);
- if (node->right_child)
- g_tree_node_check (node->right);
- }
-}
-
-static void
-g_tree_node_dump (GTreeNode *node,
- gint indent)
-{
- g_print ("%*s%c\n", indent, "", *(char *)node->key);
-
- if (node->left_child)
- g_tree_node_dump (node->left, indent + 2);
- else if (node->left)
- g_print ("%*s<%c\n", indent + 2, "", *(char *)node->left->key);
-
- if (node->right_child)
- g_tree_node_dump (node->right, indent + 2);
- else if (node->right)
- g_print ("%*s>%c\n", indent + 2, "", *(char *)node->right->key);
-}
-
-
-void
-g_tree_dump (GTree *tree)
-{
- if (tree->root)
- g_tree_node_dump (tree->root, 0);
-}
-#endif
-
-
-#define __G_TREE_C__
-#include "galiasdef.c"
-
diff --git a/glib/gunibreak.c b/glib/gunibreak.c
deleted file mode 100644
index 9c129218c..000000000
--- a/glib/gunibreak.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* gunibreak.c - line break properties
- *
- * Copyright 2000 Red Hat, Inc.
- *
- * The Gnome 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 of the
- * License, or (at your option) any later version.
- *
- * The Gnome 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 the Gnome Library; see the file COPYING.LIB. If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-
-#include "glib.h"
-#include "gunibreak.h"
-#include "galias.h"
-
-#define TPROP_PART1(Page, Char) \
- ((break_property_table_part1[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
- ? (break_property_table_part1[Page] - G_UNICODE_MAX_TABLE_INDEX) \
- : (break_property_data[break_property_table_part1[Page]][Char]))
-
-#define TPROP_PART2(Page, Char) \
- ((break_property_table_part2[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
- ? (break_property_table_part2[Page] - G_UNICODE_MAX_TABLE_INDEX) \
- : (break_property_data[break_property_table_part2[Page]][Char]))
-
-#define PROP(Char) \
- (((Char) <= G_UNICODE_LAST_CHAR_PART1) \
- ? TPROP_PART1 ((Char) >> 8, (Char) & 0xff) \
- : (((Char) >= 0xe0000 && (Char) <= G_UNICODE_LAST_CHAR) \
- ? TPROP_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \
- : G_UNICODE_BREAK_UNKNOWN))
-
-/**
- * g_unichar_break_type:
- * @c: a Unicode character
- *
- * Determines the break type of @c. @c should be a Unicode character
- * (to derive a character from UTF-8 encoded text, use
- * g_utf8_get_char()). The break type is used to find word and line
- * breaks ("text boundaries"), Pango implements the Unicode boundary
- * resolution algorithms and normally you would use a function such
- * as pango_break() instead of caring about break types yourself.
- *
- * Return value: the break type of @c
- **/
-GUnicodeBreakType
-g_unichar_break_type (gunichar c)
-{
- return PROP (c);
-}
-
-#define __G_UNIBREAK_C__
-#include "galiasdef.c"
diff --git a/glib/gunicollate.c b/glib/gunicollate.c
deleted file mode 100644
index 2bf579eca..000000000
--- a/glib/gunicollate.c
+++ /dev/null
@@ -1,679 +0,0 @@
-/* gunicollate.c - Collation
- *
- * Copyright 2001,2005 Red Hat, Inc.
- *
- * The Gnome 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 of the
- * License, or (at your option) any later version.
- *
- * The Gnome 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 the Gnome Library; see the file COPYING.LIB. If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <locale.h>
-#include <string.h>
-#ifdef __STDC_ISO_10646__
-#include <wchar.h>
-#endif
-
-#ifdef HAVE_CARBON
-#include <CoreServices/CoreServices.h>
-#endif
-
-#include "glib.h"
-#include "gunicodeprivate.h"
-#include "galias.h"
-
-#ifdef _MSC_VER
-/* Workaround for bug in MSVCR80.DLL */
-static gsize
-msc_strxfrm_wrapper (char *string1,
- const char *string2,
- gsize count)
-{
- if (!string1 || count <= 0)
- {
- char tmp;
-
- return strxfrm (&tmp, string2, 1);
- }
- return strxfrm (string1, string2, count);
-}
-#define strxfrm msc_strxfrm_wrapper
-#endif
-
-/**
- * g_utf8_collate:
- * @str1: a UTF-8 encoded string
- * @str2: a UTF-8 encoded string
- *
- * Compares two strings for ordering using the linguistically
- * correct rules for the <link linkend="setlocale">current locale</link>.
- * When sorting a large number of strings, it will be significantly
- * faster to obtain collation keys with g_utf8_collate_key() and
- * compare the keys with strcmp() when sorting instead of sorting
- * the original strings.
- *
- * Return value: &lt; 0 if @str1 compares before @str2,
- * 0 if they compare equal, &gt; 0 if @str1 compares after @str2.
- **/
-gint
-g_utf8_collate (const gchar *str1,
- const gchar *str2)
-{
- gint result;
-
-#ifdef HAVE_CARBON
-
- UniChar *str1_utf16;
- UniChar *str2_utf16;
- glong len1;
- glong len2;
- SInt32 retval = 0;
-
- g_return_val_if_fail (str1 != NULL, 0);
- g_return_val_if_fail (str2 != NULL, 0);
-
- str1_utf16 = g_utf8_to_utf16 (str1, -1, NULL, &len1, NULL);
- str2_utf16 = g_utf8_to_utf16 (str2, -1, NULL, &len2, NULL);
-
- UCCompareTextDefault (kUCCollateStandardOptions,
- str1_utf16, len1, str2_utf16, len2,
- NULL, &retval);
- result = retval;
-
- g_free (str2_utf16);
- g_free (str1_utf16);
-
-#elif defined(__STDC_ISO_10646__)
-
- gunichar *str1_norm;
- gunichar *str2_norm;
-
- g_return_val_if_fail (str1 != NULL, 0);
- g_return_val_if_fail (str2 != NULL, 0);
-
- str1_norm = _g_utf8_normalize_wc (str1, -1, G_NORMALIZE_ALL_COMPOSE);
- str2_norm = _g_utf8_normalize_wc (str2, -1, G_NORMALIZE_ALL_COMPOSE);
-
- result = wcscoll ((wchar_t *)str1_norm, (wchar_t *)str2_norm);
-
- g_free (str1_norm);
- g_free (str2_norm);
-
-#else /* !__STDC_ISO_10646__ */
-
- const gchar *charset;
- gchar *str1_norm;
- gchar *str2_norm;
-
- g_return_val_if_fail (str1 != NULL, 0);
- g_return_val_if_fail (str2 != NULL, 0);
-
- str1_norm = g_utf8_normalize (str1, -1, G_NORMALIZE_ALL_COMPOSE);
- str2_norm = g_utf8_normalize (str2, -1, G_NORMALIZE_ALL_COMPOSE);
-
- if (g_get_charset (&charset))
- {
- result = strcoll (str1_norm, str2_norm);
- }
- else
- {
- gchar *str1_locale = g_convert (str1_norm, -1, charset, "UTF-8", NULL, NULL, NULL);
- gchar *str2_locale = g_convert (str2_norm, -1, charset, "UTF-8", NULL, NULL, NULL);
-
- if (str1_locale && str2_locale)
- result = strcoll (str1_locale, str2_locale);
- else if (str1_locale)
- result = -1;
- else if (str2_locale)
- result = 1;
- else
- result = strcmp (str1_norm, str2_norm);
-
- g_free (str1_locale);
- g_free (str2_locale);
- }
-
- g_free (str1_norm);
- g_free (str2_norm);
-
-#endif /* __STDC_ISO_10646__ */
-
- return result;
-}
-
-#if defined(__STDC_ISO_10646__) || defined(HAVE_CARBON)
-/* We need UTF-8 encoding of numbers to encode the weights if
- * we are using wcsxfrm. However, we aren't encoding Unicode
- * characters, so we can't simply use g_unichar_to_utf8.
- *
- * The following routine is taken (with modification) from GNU
- * libc's strxfrm routine:
- *
- * Copyright (C) 1995-1999,2000,2001 Free Software Foundation, Inc.
- * Written by Ulrich Drepper <drepper@cygnus.com>, 1995.
- */
-static inline int
-utf8_encode (char *buf, wchar_t val)
-{
- int retval;
-
- if (val < 0x80)
- {
- if (buf)
- *buf++ = (char) val;
- retval = 1;
- }
- else
- {
- int step;
-
- for (step = 2; step < 6; ++step)
- if ((val & (~(guint32)0 << (5 * step + 1))) == 0)
- break;
- retval = step;
-
- if (buf)
- {
- *buf = (unsigned char) (~0xff >> step);
- --step;
- do
- {
- buf[step] = 0x80 | (val & 0x3f);
- val >>= 6;
- }
- while (--step > 0);
- *buf |= val;
- }
- }
-
- return retval;
-}
-#endif /* __STDC_ISO_10646__ || HAVE_CARBON */
-
-#ifdef HAVE_CARBON
-
-static gchar *
-collate_key_to_string (UCCollationValue *key,
- gsize key_len)
-{
- gchar *result;
- gsize result_len;
- gsize i;
-
- /* Pretty smart algorithm here: ignore first eight bytes of the
- * collation key. It doesn't produce results equivalent to
- * UCCompareCollationKeys's, but the difference seems to be only
- * that UCCompareCollationKeys in some cases produces 0 where our
- * comparison gets -1 or 1. */
-
- if (key_len * sizeof (UCCollationValue) <= 8)
- return g_strdup ("");
-
- result_len = 0;
- for (i = 8; i < key_len * sizeof (UCCollationValue); i++)
- /* there may be nul bytes, encode byteval+1 */
- result_len += utf8_encode (NULL, *((guchar*)key + i) + 1);
-
- result = g_malloc (result_len + 1);
- result_len = 0;
- for (i = 8; i < key_len * sizeof (UCCollationValue); i++)
- result_len += utf8_encode (result + result_len, *((guchar*)key + i) + 1);
-
- result[result_len] = 0;
- return result;
-}
-
-static gchar *
-carbon_collate_key_with_collator (const gchar *str,
- gssize len,
- CollatorRef collator)
-{
- UniChar *str_utf16 = NULL;
- glong len_utf16;
- OSStatus ret;
- UCCollationValue staticbuf[512];
- UCCollationValue *freeme = NULL;
- UCCollationValue *buf;
- ItemCount buf_len;
- ItemCount key_len;
- ItemCount try_len;
- gchar *result = NULL;
-
- str_utf16 = g_utf8_to_utf16 (str, len, NULL, &len_utf16, NULL);
- try_len = len_utf16 * 5 + 2;
-
- if (try_len <= sizeof staticbuf)
- {
- buf = staticbuf;
- buf_len = sizeof staticbuf;
- }
- else
- {
- freeme = g_new (UCCollationValue, try_len);
- buf = freeme;
- buf_len = try_len;
- }
-
- ret = UCGetCollationKey (collator, str_utf16, len_utf16,
- buf_len, &key_len, buf);
-
- if (ret == kCollateBufferTooSmall)
- {
- freeme = g_renew (UCCollationValue, freeme, try_len * 2);
- buf = freeme;
- buf_len = try_len * 2;
- ret = UCGetCollationKey (collator, str_utf16, len_utf16,
- buf_len, &key_len, buf);
- }
-
- if (ret == 0)
- result = collate_key_to_string (buf, key_len);
- else
- result = g_strdup ("");
-
- g_free (freeme);
- g_free (str_utf16);
- return result;
-}
-
-static gchar *
-carbon_collate_key (const gchar *str,
- gssize len)
-{
- static CollatorRef collator;
-
- if (G_UNLIKELY (!collator))
- {
- UCCreateCollator (NULL, 0, kUCCollateStandardOptions, &collator);
-
- if (!collator)
- {
- static gboolean been_here;
- if (!been_here)
- g_warning ("%s: UCCreateCollator failed", G_STRLOC);
- been_here = TRUE;
- return g_strdup ("");
- }
- }
-
- return carbon_collate_key_with_collator (str, len, collator);
-}
-
-static gchar *
-carbon_collate_key_for_filename (const gchar *str,
- gssize len)
-{
- static CollatorRef collator;
-
- if (G_UNLIKELY (!collator))
- {
- /* http://developer.apple.com/qa/qa2004/qa1159.html */
- UCCreateCollator (NULL, 0,
- kUCCollateComposeInsensitiveMask
- | kUCCollateWidthInsensitiveMask
- | kUCCollateCaseInsensitiveMask
- | kUCCollateDigitsOverrideMask
- | kUCCollateDigitsAsNumberMask
- | kUCCollatePunctuationSignificantMask,
- &collator);
-
- if (!collator)
- {
- static gboolean been_here;
- if (!been_here)
- g_warning ("%s: UCCreateCollator failed", G_STRLOC);
- been_here = TRUE;
- return g_strdup ("");
- }
- }
-
- return carbon_collate_key_with_collator (str, len, collator);
-}
-
-#endif /* HAVE_CARBON */
-
-/**
- * g_utf8_collate_key:
- * @str: a UTF-8 encoded string.
- * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
- *
- * Converts a string into a collation key that can be compared
- * with other collation keys produced by the same function using
- * strcmp().
- *
- * The results of comparing the collation keys of two strings
- * with strcmp() will always be the same as comparing the two
- * original keys with g_utf8_collate().
- *
- * Note that this function depends on the
- * <link linkend="setlocale">current locale</link>.
- *
- * Return value: a newly allocated string. This string should
- * be freed with g_free() when you are done with it.
- **/
-gchar *
-g_utf8_collate_key (const gchar *str,
- gssize len)
-{
- gchar *result;
-
-#ifdef HAVE_CARBON
-
- g_return_val_if_fail (str != NULL, NULL);
- result = carbon_collate_key (str, len);
-
-#elif defined(__STDC_ISO_10646__)
-
- gsize xfrm_len;
- gunichar *str_norm;
- wchar_t *result_wc;
- gsize i;
- gsize result_len = 0;
-
- g_return_val_if_fail (str != NULL, NULL);
-
- str_norm = _g_utf8_normalize_wc (str, len, G_NORMALIZE_ALL_COMPOSE);
-
- xfrm_len = wcsxfrm (NULL, (wchar_t *)str_norm, 0);
- result_wc = g_new (wchar_t, xfrm_len + 1);
- wcsxfrm (result_wc, (wchar_t *)str_norm, xfrm_len + 1);
-
- for (i=0; i < xfrm_len; i++)
- result_len += utf8_encode (NULL, result_wc[i]);
-
- result = g_malloc (result_len + 1);
- result_len = 0;
- for (i=0; i < xfrm_len; i++)
- result_len += utf8_encode (result + result_len, result_wc[i]);
-
- result[result_len] = '\0';
-
- g_free (result_wc);
- g_free (str_norm);
-
- return result;
-#else /* !__STDC_ISO_10646__ */
-
- gsize xfrm_len;
- const gchar *charset;
- gchar *str_norm;
-
- g_return_val_if_fail (str != NULL, NULL);
-
- str_norm = g_utf8_normalize (str, len, G_NORMALIZE_ALL_COMPOSE);
-
- result = NULL;
-
- if (g_get_charset (&charset))
- {
- xfrm_len = strxfrm (NULL, str_norm, 0);
- if (xfrm_len >= 0 && xfrm_len < G_MAXINT - 2)
- {
- result = g_malloc (xfrm_len + 1);
- strxfrm (result, str_norm, xfrm_len + 1);
- }
- }
- else
- {
- gchar *str_locale = g_convert (str_norm, -1, charset, "UTF-8", NULL, NULL, NULL);
-
- if (str_locale)
- {
- xfrm_len = strxfrm (NULL, str_locale, 0);
- if (xfrm_len < 0 || xfrm_len >= G_MAXINT - 2)
- {
- g_free (str_locale);
- str_locale = NULL;
- }
- }
- if (str_locale)
- {
- result = g_malloc (xfrm_len + 2);
- result[0] = 'A';
- strxfrm (result + 1, str_locale, xfrm_len + 1);
-
- g_free (str_locale);
- }
- }
-
- if (!result)
- {
- xfrm_len = strlen (str_norm);
- result = g_malloc (xfrm_len + 2);
- result[0] = 'B';
- memcpy (result + 1, str_norm, xfrm_len);
- result[xfrm_len+1] = '\0';
- }
-
- g_free (str_norm);
-#endif /* __STDC_ISO_10646__ */
-
- return result;
-}
-
-/* This is a collation key that is very very likely to sort before any
- collation key that libc strxfrm generates. We use this before any
- special case (dot or number) to make sure that its sorted before
- anything else.
- */
-#define COLLATION_SENTINEL "\1\1\1"
-
-/**
- * g_utf8_collate_key_for_filename:
- * @str: a UTF-8 encoded string.
- * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
- *
- * Converts a string into a collation key that can be compared
- * with other collation keys produced by the same function using strcmp().
- *
- * In order to sort filenames correctly, this function treats the dot '.'
- * as a special case. Most dictionary orderings seem to consider it
- * insignificant, thus producing the ordering "event.c" "eventgenerator.c"
- * "event.h" instead of "event.c" "event.h" "eventgenerator.c". Also, we
- * would like to treat numbers intelligently so that "file1" "file10" "file5"
- * is sorted as "file1" "file5" "file10".
- *
- * Note that this function depends on the
- * <link linkend="setlocale">current locale</link>.
- *
- * Return value: a newly allocated string. This string should
- * be freed with g_free() when you are done with it.
- *
- * Since: 2.8
- */
-gchar*
-g_utf8_collate_key_for_filename (const gchar *str,
- gssize len)
-{
-#ifndef HAVE_CARBON
- GString *result;
- GString *append;
- const gchar *p;
- const gchar *prev;
- const gchar *end;
- gchar *collate_key;
- gint digits;
- gint leading_zeros;
-
- /*
- * How it works:
- *
- * Split the filename into collatable substrings which do
- * not contain [.0-9] and special-cased substrings. The collatable
- * substrings are run through the normal g_utf8_collate_key() and the
- * resulting keys are concatenated with keys generated from the
- * special-cased substrings.
- *
- * Special cases: Dots are handled by replacing them with '\1' which
- * implies that short dot-delimited substrings are before long ones,
- * e.g.
- *
- * a\1a (a.a)
- * a-\1a (a-.a)
- * aa\1a (aa.a)
- *
- * Numbers are handled by prepending to each number d-1 superdigits
- * where d = number of digits in the number and SUPERDIGIT is a
- * character with an integer value higher than any digit (for instance
- * ':'). This ensures that single-digit numbers are sorted before
- * double-digit numbers which in turn are sorted separately from
- * triple-digit numbers, etc. To avoid strange side-effects when
- * sorting strings that already contain SUPERDIGITs, a '\2'
- * is also prepended, like this
- *
- * file\21 (file1)
- * file\25 (file5)
- * file\2:10 (file10)
- * file\2:26 (file26)
- * file\2::100 (file100)
- * file:foo (file:foo)
- *
- * This has the side-effect of sorting numbers before everything else (except
- * dots), but this is probably OK.
- *
- * Leading digits are ignored when doing the above. To discriminate
- * numbers which differ only in the number of leading digits, we append
- * the number of leading digits as a byte at the very end of the collation
- * key.
- *
- * To try avoid conflict with any collation key sequence generated by libc we
- * start each switch to a special cased part with a sentinel that hopefully
- * will sort before anything libc will generate.
- */
-
- if (len < 0)
- len = strlen (str);
-
- result = g_string_sized_new (len * 2);
- append = g_string_sized_new (0);
-
- end = str + len;
-
- /* No need to use utf8 functions, since we're only looking for ascii chars */
- for (prev = p = str; p < end; p++)
- {
- switch (*p)
- {
- case '.':
- if (prev != p)
- {
- collate_key = g_utf8_collate_key (prev, p - prev);
- g_string_append (result, collate_key);
- g_free (collate_key);
- }
-
- g_string_append (result, COLLATION_SENTINEL "\1");
-
- /* skip the dot */
- prev = p + 1;
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (prev != p)
- {
- collate_key = g_utf8_collate_key (prev, p - prev);
- g_string_append (result, collate_key);
- g_free (collate_key);
- }
-
- g_string_append (result, COLLATION_SENTINEL "\2");
-
- prev = p;
-
- /* write d-1 colons */
- if (*p == '0')
- {
- leading_zeros = 1;
- digits = 0;
- }
- else
- {
- leading_zeros = 0;
- digits = 1;
- }
-
- while (++p < end)
- {
- if (*p == '0' && !digits)
- ++leading_zeros;
- else if (g_ascii_isdigit(*p))
- ++digits;
- else
- {
- /* count an all-zero sequence as
- * one digit plus leading zeros
- */
- if (!digits)
- {
- ++digits;
- --leading_zeros;
- }
- break;
- }
- }
-
- while (digits > 1)
- {
- g_string_append_c (result, ':');
- --digits;
- }
-
- if (leading_zeros > 0)
- {
- g_string_append_c (append, (char)leading_zeros);
- prev += leading_zeros;
- }
-
- /* write the number itself */
- g_string_append_len (result, prev, p - prev);
-
- prev = p;
- --p; /* go one step back to avoid disturbing outer loop */
- break;
-
- default:
- /* other characters just accumulate */
- break;
- }
- }
-
- if (prev != p)
- {
- collate_key = g_utf8_collate_key (prev, p - prev);
- g_string_append (result, collate_key);
- g_free (collate_key);
- }
-
- g_string_append (result, append->str);
- g_string_free (append, TRUE);
-
- return g_string_free (result, FALSE);
-#else /* HAVE_CARBON */
- return carbon_collate_key_for_filename (str, len);
-#endif
-}
-
-
-#define __G_UNICOLLATE_C__
-#include "galiasdef.c"
diff --git a/glib/gurifuncs.c b/glib/gurifuncs.c
deleted file mode 100644
index 40f97498d..000000000
--- a/glib/gurifuncs.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/* GIO - GLib Input, Output and Streaming Library
- *
- * Copyright (C) 2006-2007 Red Hat, Inc.
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Alexander Larsson <alexl@redhat.com>
- */
-
-#include "config.h"
-#include "gurifuncs.h"
-#include "string.h"
-
-#include "galias.h"
-
-/**
- * SECTION:gurifuncs
- * @short_description: URI Functions
- *
- * Functions for manipulating Universal Resource Identifiers (URIs) as
- * defined by <ulink url="http://www.ietf.org/rfc/rfc3986.txt">
- * RFC 3986</ulink>. It is highly recommended that you have read and
- * understand RFC 3986 for understanding this API.
- */
-
-static int
-unescape_character (const char *scanner)
-{
- int first_digit;
- int second_digit;
-
- first_digit = g_ascii_xdigit_value (*scanner++);
- if (first_digit < 0)
- return -1;
-
- second_digit = g_ascii_xdigit_value (*scanner++);
- if (second_digit < 0)
- return -1;
-
- return (first_digit << 4) | second_digit;
-}
-
-/**
- * g_uri_unescape_segment:
- * @escaped_string: a string.
- * @escaped_string_end: a string.
- * @illegal_characters: an optional string of illegal characters not to be allowed.
- *
- * Unescapes a segment of an escaped string.
- *
- * If any of the characters in @illegal_characters or the character zero appears
- * as an escaped character in @escaped_string then that is an error and %NULL
- * will be returned. This is useful it you want to avoid for instance having a
- * slash being expanded in an escaped path element, which might confuse pathname
- * handling.
- *
- * Returns: an unescaped version of @escaped_string or %NULL on error.
- * The returned string should be freed when no longer needed.
- *
- * Since: 2.16
- **/
-char *
-g_uri_unescape_segment (const char *escaped_string,
- const char *escaped_string_end,
- const char *illegal_characters)
-{
- const char *in;
- char *out, *result;
- gint character;
-
- if (escaped_string == NULL)
- return NULL;
-
- if (escaped_string_end == NULL)
- escaped_string_end = escaped_string + strlen (escaped_string);
-
- result = g_malloc (escaped_string_end - escaped_string + 1);
-
- out = result;
- for (in = escaped_string; in < escaped_string_end; in++)
- {
- character = *in;
-
- if (*in == '%')
- {
- in++;
-
- if (escaped_string_end - in < 2)
- {
- /* Invalid escaped char (to short) */
- g_free (result);
- return NULL;
- }
-
- character = unescape_character (in);
-
- /* Check for an illegal character. We consider '\0' illegal here. */
- if (character <= 0 ||
- (illegal_characters != NULL &&
- strchr (illegal_characters, (char)character) != NULL))
- {
- g_free (result);
- return NULL;
- }
-
- in++; /* The other char will be eaten in the loop header */
- }
- *out++ = (char)character;
- }
-
- *out = '\0';
-
- return result;
-}
-
-/**
- * g_uri_unescape_string:
- * @escaped_string: an escaped string to be unescaped.
- * @illegal_characters: an optional string of illegal characters not to be allowed.
- *
- * Unescapes a whole escaped string.
- *
- * If any of the characters in @illegal_characters or the character zero appears
- * as an escaped character in @escaped_string then that is an error and %NULL
- * will be returned. This is useful it you want to avoid for instance having a
- * slash being expanded in an escaped path element, which might confuse pathname
- * handling.
- *
- * Returns: an unescaped version of @escaped_string. The returned string
- * should be freed when no longer needed.
- *
- * Since: 2.16
- **/
-char *
-g_uri_unescape_string (const char *escaped_string,
- const char *illegal_characters)
-{
- return g_uri_unescape_segment (escaped_string, NULL, illegal_characters);
-}
-
-/**
- * g_uri_parse_scheme:
- * @uri: a valid URI.
- *
- * Gets the scheme portion of a URI string. RFC 3986 decodes the scheme as:
- * <programlisting>
- * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
- * </programlisting>
- * Common schemes include "file", "http", "svn+ssh", etc.
- *
- * Returns: The "Scheme" component of the URI, or %NULL on error.
- * The returned string should be freed when no longer needed.
- *
- * Since: 2.16
- **/
-char *
-g_uri_parse_scheme (const char *uri)
-{
- const char *p;
- char c;
-
- g_return_val_if_fail (uri != NULL, NULL);
-
- /* From RFC 3986 Decodes:
- * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
- */
-
- p = uri;
-
- /* Decode scheme:
- scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
- */
-
- if (!g_ascii_isalpha (*p))
- return NULL;
-
- while (1)
- {
- c = *p++;
-
- if (c == ':')
- break;
-
- if (!(g_ascii_isalnum(c) ||
- c == '+' ||
- c == '-' ||
- c == '.'))
- return NULL;
- }
-
- return g_strndup (uri, p - uri - 1);
-}
-
-/**
- * g_uri_escape_string:
- * @unescaped: the unescaped input string.
- * @reserved_chars_allowed: a string of reserved characters that are
- * allowed to be used.
- * @allow_utf8: %TRUE if the result can include UTF-8 characters.
- *
- * Escapes a string for use in a URI.
- *
- * Normally all characters that are not "unreserved" (i.e. ASCII alphanumerical
- * characters plus dash, dot, underscore and tilde) are escaped.
- * But if you specify characters in @reserved_chars_allowed they are not
- * escaped. This is useful for the "reserved" characters in the URI
- * specification, since those are allowed unescaped in some portions of
- * a URI.
- *
- * Returns: an escaped version of @unescaped. The returned string should be
- * freed when no longer needed.
- *
- * Since: 2.16
- **/
-char *
-g_uri_escape_string (const char *unescaped,
- const char *reserved_chars_allowed,
- gboolean allow_utf8)
-{
- GString *s;
-
- g_return_val_if_fail (unescaped != NULL, NULL);
-
- s = g_string_sized_new (strlen (unescaped) + 10);
-
- g_string_append_uri_escaped (s, unescaped, reserved_chars_allowed, allow_utf8);
-
- return g_string_free (s, FALSE);
-}
-
-#define __G_URI_FUNCS_C__
-#include "galiasdef.c"
diff --git a/glib/gutf8.c b/glib/gutf8.c
index da4a769cc..9f98cc172 100644
--- a/glib/gutf8.c
+++ b/glib/gutf8.c
@@ -22,9 +22,11 @@
#include "config.h"
#include <stdlib.h>
+#ifdef ANDROID_STUB
#ifdef HAVE_CODESET
#include <langinfo.h>
#endif
+#endif
#include <string.h>
#include "glib.h"
@@ -36,7 +38,9 @@
#undef STRICT
#endif
+#ifdef ANDROID_STUB
#include "libcharset/libcharset.h"
+#endif
#include "glibintl.h"
#include "galias.h"
@@ -443,6 +447,7 @@ get_alias_hash (void)
/* As an abuse of the alias table, the following routines gets
* the charsets that are aliases for the canonical name.
*/
+#ifdef ANDROID_STUB
G_GNUC_INTERNAL const char **
_g_charset_get_aliases (const char *canonical_name)
{
@@ -450,6 +455,7 @@ _g_charset_get_aliases (const char *canonical_name)
return g_hash_table_lookup (alias_hash, canonical_name);
}
+#endif
static gboolean
g_utf8_get_charset_internal (const char *raw_data,
@@ -471,9 +477,11 @@ g_utf8_get_charset_internal (const char *raw_data,
* a lock, but has a memory leak and a missing memory
* barrier, so we lock for it
*/
+#ifdef ANDROID_STUB
G_LOCK (aliases);
charset = _g_locale_charset_unalias (raw_data);
G_UNLOCK (aliases);
+#endif
if (charset && *charset)
{
@@ -545,6 +553,7 @@ g_get_charset (G_CONST_RETURN char **charset)
g_static_private_set (&cache_private, cache, charset_cache_free);
}
+#ifdef ANDROID_STUB
raw = _g_locale_charset_raw ();
if (!(cache->raw && strcmp (cache->raw, raw) == 0))
@@ -557,7 +566,7 @@ g_get_charset (G_CONST_RETURN char **charset)
cache->is_utf8 = g_utf8_get_charset_internal (raw, &new_charset);
cache->charset = g_strdup (new_charset);
}
-
+#endif
if (charset)
*charset = cache->charset;
diff --git a/glib/gutils.c b/glib/gutils.c
index 858603b8d..8228babae 100644
--- a/glib/gutils.c
+++ b/glib/gutils.c
@@ -116,9 +116,11 @@
#include <CoreServices/CoreServices.h>
#endif
+#ifdef ANDROID_STUB
#ifdef HAVE_CODESET
#include <langinfo.h>
#endif
+#endif
const guint glib_major_version = GLIB_MAJOR_VERSION;
const guint glib_minor_version = GLIB_MINOR_VERSION;
@@ -1679,16 +1681,19 @@ g_get_any_init_do (void)
while (!pw);
# endif /* HAVE_POSIX_GETPWUID_R || HAVE_NONPOSIX_GETPWUID_R */
+#ifdef ANDROID_STUB
if (!pw)
{
setpwent ();
pw = getpwuid (getuid ());
endpwent ();
}
+#endif
if (pw)
{
g_user_name = g_strdup (pw->pw_name);
+ #ifdef ANDROID_STUB
if (pw->pw_gecos && *pw->pw_gecos != '\0')
{
gchar **gecos_fields;
@@ -1702,7 +1707,7 @@ g_get_any_init_do (void)
g_strfreev (gecos_fields);
g_strfreev (name_parts);
}
-
+ #endif
if (!g_home_dir)
g_home_dir = g_strdup (pw->pw_dir);
}
diff --git a/glib/gwin32.c b/glib/gwin32.c
deleted file mode 100644
index c2ced69d4..000000000
--- a/glib/gwin32.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 1998-1999 Tor Lillqvist
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/*
- * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
- */
-
-#include "config.h"
-
-#include "glibconfig.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <wchar.h>
-#include <errno.h>
-
-#define STRICT /* Strict typing, please */
-#include <windows.h>
-#undef STRICT
-#ifndef G_WITH_CYGWIN
-#include <direct.h>
-#endif
-#include <errno.h>
-#include <ctype.h>
-#if defined(_MSC_VER) || defined(__DMC__)
-# include <io.h>
-#endif /* _MSC_VER || __DMC__ */
-
-#include "glib.h"
-#include "galias.h"
-
-#ifdef G_WITH_CYGWIN
-#include <sys/cygwin.h>
-#endif
-
-#ifndef G_WITH_CYGWIN
-
-gint
-g_win32_ftruncate (gint fd,
- guint size)
-{
- return _chsize (fd, size);
-}
-
-#endif
-
-/**
- * g_win32_getlocale:
- *
- * The setlocale() function in the Microsoft C library uses locale
- * names of the form "English_United States.1252" etc. We want the
- * UNIXish standard form "en_US", "zh_TW" etc. This function gets the
- * current thread locale from Windows - without any encoding info -
- * and returns it as a string of the above form for use in forming
- * file names etc. The returned string should be deallocated with
- * g_free().
- *
- * Returns: newly-allocated locale name.
- **/
-
-#ifndef SUBLANG_SERBIAN_LATIN_BA
-#define SUBLANG_SERBIAN_LATIN_BA 0x06
-#endif
-
-gchar *
-g_win32_getlocale (void)
-{
- LCID lcid;
- LANGID langid;
- gchar *ev;
- gint primary, sub;
- char iso639[10];
- char iso3166[10];
- const gchar *script = NULL;
-
- /* Let the user override the system settings through environment
- * variables, as on POSIX systems. Note that in GTK+ applications
- * since GTK+ 2.10.7 setting either LC_ALL or LANG also sets the
- * Win32 locale and C library locale through code in gtkmain.c.
- */
- if (((ev = getenv ("LC_ALL")) != NULL && ev[0] != '\0')
- || ((ev = getenv ("LC_MESSAGES")) != NULL && ev[0] != '\0')
- || ((ev = getenv ("LANG")) != NULL && ev[0] != '\0'))
- return g_strdup (ev);
-
- lcid = GetThreadLocale ();
-
- if (!GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) ||
- !GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
- return g_strdup ("C");
-
- /* Strip off the sorting rules, keep only the language part. */
- langid = LANGIDFROMLCID (lcid);
-
- /* Split into language and territory part. */
- primary = PRIMARYLANGID (langid);
- sub = SUBLANGID (langid);
-
- /* Handle special cases */
- switch (primary)
- {
- case LANG_AZERI:
- switch (sub)
- {
- case SUBLANG_AZERI_LATIN:
- script = "@Latn";
- break;
- case SUBLANG_AZERI_CYRILLIC:
- script = "@Cyrl";
- break;
- }
- break;
- case LANG_SERBIAN: /* LANG_CROATIAN == LANG_SERBIAN */
- switch (sub)
- {
- case SUBLANG_SERBIAN_LATIN:
- case 0x06: /* Serbian (Latin) - Bosnia and Herzegovina */
- script = "@Latn";
- break;
- }
- break;
- case LANG_UZBEK:
- switch (sub)
- {
- case SUBLANG_UZBEK_LATIN:
- script = "@Latn";
- break;
- case SUBLANG_UZBEK_CYRILLIC:
- script = "@Cyrl";
- break;
- }
- break;
- }
- return g_strconcat (iso639, "_", iso3166, script, NULL);
-}
-
-/**
- * g_win32_error_message:
- * @error: error code.
- *
- * Translate a Win32 error code (as returned by GetLastError()) into
- * the corresponding message. The message is either language neutral,
- * or in the thread's language, or the user's language, the system's
- * language, or US English (see docs for FormatMessage()). The
- * returned string is in UTF-8. It should be deallocated with
- * g_free().
- *
- * Returns: newly-allocated error message
- **/
-gchar *
-g_win32_error_message (gint error)
-{
- gchar *retval;
- wchar_t *msg = NULL;
- int nchars;
-
- FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER
- |FORMAT_MESSAGE_IGNORE_INSERTS
- |FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, error, 0,
- (LPWSTR) &msg, 0, NULL);
- if (msg != NULL)
- {
- nchars = wcslen (msg);
-
- if (nchars > 2 && msg[nchars-1] == '\n' && msg[nchars-2] == '\r')
- msg[nchars-2] = '\0';
-
- retval = g_utf16_to_utf8 (msg, -1, NULL, NULL, NULL);
-
- LocalFree (msg);
- }
- else
- retval = g_strdup ("");
-
- return retval;
-}
-
-/**
- * g_win32_get_package_installation_directory_of_module:
- * @hmodule: The Win32 handle for a DLL loaded into the current process, or %NULL
- *
- * This function tries to determine the installation directory of a
- * software package based on the location of a DLL of the software
- * package.
- *
- * @hmodule should be the handle of a loaded DLL or %NULL. The
- * function looks up the directory that DLL was loaded from. If
- * @hmodule is NULL, the directory the main executable of the current
- * process is looked up. If that directory's last component is "bin"
- * or "lib", its parent directory is returned, otherwise the directory
- * itself.
- *
- * It thus makes sense to pass only the handle to a "public" DLL of a
- * software package to this function, as such DLLs typically are known
- * to be installed in a "bin" or occasionally "lib" subfolder of the
- * installation folder. DLLs that are of the dynamically loaded module
- * or plugin variety are often located in more private locations
- * deeper down in the tree, from which it is impossible for GLib to
- * deduce the root of the package installation.
- *
- * The typical use case for this function is to have a DllMain() that
- * saves the handle for the DLL. Then when code in the DLL needs to
- * construct names of files in the installation tree it calls this
- * function passing the DLL handle.
- *
- * Returns: a string containing the guessed installation directory for
- * the software package @hmodule is from. The string is in the GLib
- * file name encoding, i.e. UTF-8. The return value should be freed
- * with g_free() when not needed any longer. If the function fails
- * %NULL is returned.
- *
- * Since: 2.16
- */
-gchar *
-g_win32_get_package_installation_directory_of_module (gpointer hmodule)
-{
- gchar *retval;
- gchar *p;
- wchar_t wc_fn[MAX_PATH];
-
- if (!GetModuleFileNameW (hmodule, wc_fn, MAX_PATH))
- return NULL;
-
- retval = g_utf16_to_utf8 (wc_fn, -1, NULL, NULL, NULL);
-
- if ((p = strrchr (retval, G_DIR_SEPARATOR)) != NULL)
- *p = '\0';
-
- p = strrchr (retval, G_DIR_SEPARATOR);
- if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0 ||
- g_ascii_strcasecmp (p + 1, "lib") == 0))
- *p = '\0';
-
-#ifdef G_WITH_CYGWIN
- /* In Cygwin we need to have POSIX paths */
- {
- gchar tmp[MAX_PATH];
-
- cygwin_conv_to_posix_path (retval, tmp);
- g_free (retval);
- retval = g_strdup (tmp);
- }
-#endif
-
- return retval;
-}
-
-static gchar *
-get_package_directory_from_module (const gchar *module_name)
-{
- static GHashTable *module_dirs = NULL;
- G_LOCK_DEFINE_STATIC (module_dirs);
- HMODULE hmodule = NULL;
- gchar *fn;
-
- G_LOCK (module_dirs);
-
- if (module_dirs == NULL)
- module_dirs = g_hash_table_new (g_str_hash, g_str_equal);
-
- fn = g_hash_table_lookup (module_dirs, module_name ? module_name : "");
-
- if (fn)
- {
- G_UNLOCK (module_dirs);
- return g_strdup (fn);
- }
-
- if (module_name)
- {
- wchar_t *wc_module_name = g_utf8_to_utf16 (module_name, -1, NULL, NULL, NULL);
- hmodule = GetModuleHandleW (wc_module_name);
- g_free (wc_module_name);
-
- if (!hmodule)
- {
- G_UNLOCK (module_dirs);
- return NULL;
- }
- }
-
- fn = g_win32_get_package_installation_directory_of_module (hmodule);
-
- if (fn == NULL)
- {
- G_UNLOCK (module_dirs);
- return NULL;
- }
-
- g_hash_table_insert (module_dirs, module_name ? g_strdup (module_name) : "", fn);
-
- G_UNLOCK (module_dirs);
-
- return g_strdup (fn);
-}
-
-/**
- * g_win32_get_package_installation_directory:
- * @package: You should pass %NULL for this.
- * @dll_name: The name of a DLL that a package provides in UTF-8, or %NULL.
- *
- * Try to determine the installation directory for a software package.
- *
- * This function is deprecated. Use
- * g_win32_get_package_installation_directory_of_module() instead.
- *
- * The use of @package is deprecated. You should always pass %NULL. A
- * warning is printed if non-NULL is passed as @package.
- *
- * The original intended use of @package was for a short identifier of
- * the package, typically the same identifier as used for
- * <literal>GETTEXT_PACKAGE</literal> in software configured using GNU
- * autotools. The function first looks in the Windows Registry for the
- * value <literal>&num;InstallationDirectory</literal> in the key
- * <literal>&num;HKLM\Software\@package</literal>, and if that value
- * exists and is a string, returns that.
- *
- * It is strongly recommended that packagers of GLib-using libraries
- * for Windows do not store installation paths in the Registry to be
- * used by this function as that interfers with having several
- * parallel installations of the library. Enabling multiple
- * installations of different versions of some GLib-using library, or
- * GLib itself, is desirable for various reasons.
- *
- * For this reason it is recommeded to always pass %NULL as
- * @package to this function, to avoid the temptation to use the
- * Registry. In version 2.20 of GLib the @package parameter
- * will be ignored and this function won't look in the Registry at all.
- *
- * If @package is %NULL, or the above value isn't found in the
- * Registry, but @dll_name is non-%NULL, it should name a DLL loaded
- * into the current process. Typically that would be the name of the
- * DLL calling this function, looking for its installation
- * directory. The function then asks Windows what directory that DLL
- * was loaded from. If that directory's last component is "bin" or
- * "lib", the parent directory is returned, otherwise the directory
- * itself. If that DLL isn't loaded, the function proceeds as if
- * @dll_name was %NULL.
- *
- * If both @package and @dll_name are %NULL, the directory from where
- * the main executable of the process was loaded is used instead in
- * the same way as above.
- *
- * Returns: a string containing the installation directory for
- * @package. The string is in the GLib file name encoding,
- * i.e. UTF-8. The return value should be freed with g_free() when not
- * needed any longer. If the function fails %NULL is returned.
- *
- * @Deprecated:2.18: Pass the HMODULE of a DLL or EXE to
- * g_win32_get_package_installation_directory_of_module() instead.
- **/
-
- gchar *
-g_win32_get_package_installation_directory_utf8 (const gchar *package,
- const gchar *dll_name)
-{
- gchar *result = NULL;
-
- if (package != NULL)
- g_warning ("Passing a non-NULL package to g_win32_get_package_installation_directory() is deprecated and it is ignored.");
-
- if (dll_name != NULL)
- result = get_package_directory_from_module (dll_name);
-
- if (result == NULL)
- result = get_package_directory_from_module (NULL);
-
- return result;
-}
-
-#if !defined (_WIN64)
-
-/* DLL ABI binary compatibility version that uses system codepage file names */
-
-gchar *
-g_win32_get_package_installation_directory (const gchar *package,
- const gchar *dll_name)
-{
- gchar *utf8_package = NULL, *utf8_dll_name = NULL;
- gchar *utf8_retval, *retval;
-
- if (package != NULL)
- utf8_package = g_locale_to_utf8 (package, -1, NULL, NULL, NULL);
-
- if (dll_name != NULL)
- utf8_dll_name = g_locale_to_utf8 (dll_name, -1, NULL, NULL, NULL);
-
- utf8_retval =
- g_win32_get_package_installation_directory_utf8 (utf8_package,
- utf8_dll_name);
-
- retval = g_locale_from_utf8 (utf8_retval, -1, NULL, NULL, NULL);
-
- g_free (utf8_package);
- g_free (utf8_dll_name);
- g_free (utf8_retval);
-
- return retval;
-}
-
-#endif
-
-/**
- * g_win32_get_package_installation_subdirectory:
- * @package: You should pass %NULL for this.
- * @dll_name: The name of a DLL that a package provides, in UTF-8, or %NULL.
- * @subdir: A subdirectory of the package installation directory, also in UTF-8
- *
- * This function is deprecated. Use
- * g_win32_get_package_installation_directory_of_module() and
- * g_build_filename() instead.
- *
- * Returns a newly-allocated string containing the path of the
- * subdirectory @subdir in the return value from calling
- * g_win32_get_package_installation_directory() with the @package and
- * @dll_name parameters. See the documentation for
- * g_win32_get_package_installation_directory() for more details. In
- * particular, note that it is deprecated to pass anything except NULL
- * as @package.
- *
- * Returns: a string containing the complete path to @subdir inside
- * the installation directory of @package. The returned string is in
- * the GLib file name encoding, i.e. UTF-8. The return value should be
- * freed with g_free() when no longer needed. If something goes wrong,
- * %NULL is returned.
- *
- * @Deprecated:2.18: Pass the HMODULE of a DLL or EXE to
- * g_win32_get_package_installation_directory_of_module() instead, and
- * then construct a subdirectory pathname with g_build_filename().
- **/
-
-gchar *
-g_win32_get_package_installation_subdirectory_utf8 (const gchar *package,
- const gchar *dll_name,
- const gchar *subdir)
-{
- gchar *prefix;
- gchar *dirname;
-
- prefix = g_win32_get_package_installation_directory_utf8 (package, dll_name);
-
- dirname = g_build_filename (prefix, subdir, NULL);
- g_free (prefix);
-
- return dirname;
-}
-
-#if !defined (_WIN64)
-
-/* DLL ABI binary compatibility version that uses system codepage file names */
-
-gchar *
-g_win32_get_package_installation_subdirectory (const gchar *package,
- const gchar *dll_name,
- const gchar *subdir)
-{
- gchar *prefix;
- gchar *dirname;
-
- prefix = g_win32_get_package_installation_directory (package, dll_name);
-
- dirname = g_build_filename (prefix, subdir, NULL);
- g_free (prefix);
-
- return dirname;
-}
-
-#endif
-
-static guint windows_version;
-
-static void
-g_win32_windows_version_init (void)
-{
- static gboolean beenhere = FALSE;
-
- if (!beenhere)
- {
- beenhere = TRUE;
- windows_version = GetVersion ();
-
- if (windows_version & 0x80000000)
- g_error ("This version of GLib requires NT-based Windows.");
- }
-}
-
-void
-_g_win32_thread_init (void)
-{
- g_win32_windows_version_init ();
-}
-
-/**
- * g_win32_get_windows_version:
- *
- * Returns version information for the Windows operating system the
- * code is running on. See MSDN documentation for the GetVersion()
- * function. To summarize, the most significant bit is one on Win9x,
- * and zero on NT-based systems. Since version 2.14, GLib works only
- * on NT-based systems, so checking whether your are running on Win9x
- * in your own software is moot. The least significant byte is 4 on
- * Windows NT 4, and 5 on Windows XP. Software that needs really
- * detailled version and feature information should use Win32 API like
- * GetVersionEx() and VerifyVersionInfo().
- *
- * Returns: The version information.
- *
- * Since: 2.6
- **/
-guint
-g_win32_get_windows_version (void)
-{
- g_win32_windows_version_init ();
-
- return windows_version;
-}
-
-/**
- * g_win32_locale_filename_from_utf8:
- * @utf8filename: a UTF-8 encoded filename.
- *
- * Converts a filename from UTF-8 to the system codepage.
- *
- * On NT-based Windows, on NTFS file systems, file names are in
- * Unicode. It is quite possible that Unicode file names contain
- * characters not representable in the system codepage. (For instance,
- * Greek or Cyrillic characters on Western European or US Windows
- * installations, or various less common CJK characters on CJK Windows
- * installations.)
- *
- * In such a case, and if the filename refers to an existing file, and
- * the file system stores alternate short (8.3) names for directory
- * entries, the short form of the filename is returned. Note that the
- * "short" name might in fact be longer than the Unicode name if the
- * Unicode name has very short pathname components containing
- * non-ASCII characters. If no system codepage name for the file is
- * possible, %NULL is returned.
- *
- * The return value is dynamically allocated and should be freed with
- * g_free() when no longer needed.
- *
- * Return value: The converted filename, or %NULL on conversion
- * failure and lack of short names.
- *
- * Since: 2.8
- */
-gchar *
-g_win32_locale_filename_from_utf8 (const gchar *utf8filename)
-{
- gchar *retval = g_locale_from_utf8 (utf8filename, -1, NULL, NULL, NULL);
-
- if (retval == NULL)
- {
- /* Conversion failed, so convert to wide chars, check if there
- * is a 8.3 version, and use that.
- */
- wchar_t *wname = g_utf8_to_utf16 (utf8filename, -1, NULL, NULL, NULL);
- if (wname != NULL)
- {
- wchar_t wshortname[MAX_PATH + 1];
- if (GetShortPathNameW (wname, wshortname, G_N_ELEMENTS (wshortname)))
- {
- gchar *tem = g_utf16_to_utf8 (wshortname, -1, NULL, NULL, NULL);
- retval = g_locale_from_utf8 (tem, -1, NULL, NULL, NULL);
- g_free (tem);
- }
- g_free (wname);
- }
- }
- return retval;
-}
-
-#define __G_WIN32_C__
-#include "galiasdef.c"
diff --git a/glib/libcharset/.gitignore b/glib/libcharset/.gitignore
deleted file mode 100644
index 0cef4408e..000000000
--- a/glib/libcharset/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-charset.alias
-ref-add.sed
-ref-del.sed
diff --git a/glib/libcharset/Makefile.am b/glib/libcharset/Makefile.am
deleted file mode 100644
index cfa341218..000000000
--- a/glib/libcharset/Makefile.am
+++ /dev/null
@@ -1,64 +0,0 @@
-## Process this file with automake to produce Makefile.in
-include $(top_srcdir)/Makefile.decl
-
-INCLUDES = \
- -DLIBDIR=\"$(libdir)\" -I$(top_srcdir)
-
-noinst_LTLIBRARIES = libcharset.la
-
-libcharset_la_SOURCES = \
- libcharset.h \
- localcharset.h \
- localcharset.c
-
-EXTRA_DIST += \
- README \
- config.charset \
- ref-add.sin \
- ref-del.sin \
- glibc21.m4 \
- codeset.m4 \
- update.sh \
- make-patch.sh \
- libcharset-glib.patch
-
-charset_alias = $(DESTDIR)$(libdir)/charset.alias
-charset_tmp = $(DESTDIR)$(libdir)/charset.tmp
-install-exec-local: all-local
- $(mkinstalldirs) $(DESTDIR)$(libdir)
- if test -f $(charset_alias); then \
- sed -f ref-add.sed $(charset_alias) > $(charset_tmp) ; \
- $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \
- rm -f $(charset_tmp) ; \
- else \
- if test @GLIBC21@ = no; then \
- sed -f ref-add.sed charset.alias > $(charset_tmp) ; \
- $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \
- rm -f $(charset_tmp) ; \
- fi ; \
- fi
-
-uninstall-local: all-local
- if test -f $(charset_alias); then \
- sed -f ref-del.sed $(charset_alias) > $(charset_tmp); \
- if grep '^# Packages using this file: $$' $(charset_tmp) \
- > /dev/null; then \
- rm -f $(charset_alias); \
- else \
- $(INSTALL_DATA) $(charset_tmp) $(charset_alias); \
- fi; \
- rm -f $(charset_tmp); \
- fi
-
-charset.alias: config.charset
- $(SHELL) $(srcdir)/config.charset '@host@' > t-$@
- mv t-$@ $@
-
-all-local: ref-add.sed ref-del.sed charset.alias
-
-SUFFIXES = .sed .sin
-.sin.sed:
- sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $< > t-$@
- mv t-$@ $@
-
-CLEANFILES = charset.alias ref-add.sed ref-del.sed
diff --git a/glib/libcharset/README b/glib/libcharset/README
deleted file mode 100644
index c8f53bde6..000000000
--- a/glib/libcharset/README
+++ /dev/null
@@ -1,46 +0,0 @@
-The sources are derived from Bruno Haible's libcharset library included
-with libiconv:
-
- http//www.gnu.org/software/libiconv
-
-The 'update.sh' script in this directory, when pointed at
-the original sources updates the files in this directory
-(and elsewhere in the GLib distribution) to the new version
-
-The 'make-patch.sh' script in this directory regenerates
-the patch files included in this directory from a copy
-of the pristine sources and the files in this directory.
-
-The license on the portions from libiconv portions is reproduced
-below.
-
-Owen Taylor
-26 September 2001
-
-Updated to libiconv-1.12.
-
-Behdad Esfahbod
-20 May 2008
-
-====
-
-/* Determine a canonical name for the current locale's character encoding.
-
- Copyright (C) 2000-2001 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Library General Public License as published
- by the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library 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. */
-
-/* Written by Bruno Haible <haible@clisp.cons.org>. */
diff --git a/glib/libcharset/codeset.m4 b/glib/libcharset/codeset.m4
deleted file mode 100644
index a6e67ec49..000000000
--- a/glib/libcharset/codeset.m4
+++ /dev/null
@@ -1,21 +0,0 @@
-# codeset.m4 serial AM1 (gettext-0.10.40)
-dnl Copyright (C) 2000-2002 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-dnl From Bruno Haible.
-
-AC_DEFUN([AM_LANGINFO_CODESET],
-[
- AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset,
- [AC_TRY_LINK([#include <langinfo.h>],
- [char* cs = nl_langinfo(CODESET);],
- am_cv_langinfo_codeset=yes,
- am_cv_langinfo_codeset=no)
- ])
- if test $am_cv_langinfo_codeset = yes; then
- AC_DEFINE(HAVE_LANGINFO_CODESET, 1,
- [Define if you have <langinfo.h> and nl_langinfo(CODESET).])
- fi
-])
diff --git a/glib/libcharset/config.charset b/glib/libcharset/config.charset
deleted file mode 100755
index e8c258b3f..000000000
--- a/glib/libcharset/config.charset
+++ /dev/null
@@ -1,640 +0,0 @@
-#! /bin/sh
-# Output a system dependent table of character encoding aliases.
-#
-# Copyright (C) 2000-2004, 2006 Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Library General Public License as published
-# by the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-# USA.
-#
-# The table consists of lines of the form
-# ALIAS CANONICAL
-#
-# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)".
-# ALIAS is compared in a case sensitive way.
-#
-# CANONICAL is the GNU canonical name for this character encoding.
-# It must be an encoding supported by libiconv. Support by GNU libc is
-# also desirable. CANONICAL is case insensitive. Usually an upper case
-# MIME charset name is preferred.
-# The current list of GNU canonical charset names is as follows.
-#
-# name MIME? used by which systems
-# ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin
-# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd darwin
-# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd darwin
-# ISO-8859-3 Y glibc solaris
-# ISO-8859-4 Y osf solaris freebsd netbsd darwin
-# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd darwin
-# ISO-8859-6 Y glibc aix hpux solaris
-# ISO-8859-7 Y glibc aix hpux irix osf solaris netbsd darwin
-# ISO-8859-8 Y glibc aix hpux osf solaris
-# ISO-8859-9 Y glibc aix hpux irix osf solaris darwin
-# ISO-8859-13 glibc netbsd darwin
-# ISO-8859-14 glibc
-# ISO-8859-15 glibc aix osf solaris freebsd darwin
-# KOI8-R Y glibc solaris freebsd netbsd darwin
-# KOI8-U Y glibc freebsd netbsd darwin
-# KOI8-T glibc
-# CP437 dos
-# CP775 dos
-# CP850 aix osf dos
-# CP852 dos
-# CP855 dos
-# CP856 aix
-# CP857 dos
-# CP861 dos
-# CP862 dos
-# CP864 dos
-# CP865 dos
-# CP866 freebsd netbsd darwin dos
-# CP869 dos
-# CP874 woe32 dos
-# CP922 aix
-# CP932 aix woe32 dos
-# CP943 aix
-# CP949 osf woe32 dos
-# CP950 woe32 dos
-# CP1046 aix
-# CP1124 aix
-# CP1125 dos
-# CP1129 aix
-# CP1250 woe32
-# CP1251 glibc solaris netbsd darwin woe32
-# CP1252 aix woe32
-# CP1253 woe32
-# CP1254 woe32
-# CP1255 glibc woe32
-# CP1256 woe32
-# CP1257 woe32
-# GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin
-# EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin
-# EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin
-# EUC-TW glibc aix hpux irix osf solaris netbsd
-# BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin
-# BIG5-HKSCS glibc solaris
-# GBK glibc aix osf solaris woe32 dos
-# GB18030 glibc solaris netbsd
-# SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin
-# JOHAB glibc solaris woe32
-# TIS-620 glibc aix hpux osf solaris
-# VISCII Y glibc
-# TCVN5712-1 glibc
-# GEORGIAN-PS glibc
-# HP-ROMAN8 hpux
-# HP-ARABIC8 hpux
-# HP-GREEK8 hpux
-# HP-HEBREW8 hpux
-# HP-TURKISH8 hpux
-# HP-KANA8 hpux
-# DEC-KANJI osf
-# DEC-HANYU osf
-# UTF-8 Y glibc aix hpux osf solaris netbsd darwin
-#
-# Note: Names which are not marked as being a MIME name should not be used in
-# Internet protocols for information interchange (mail, news, etc.).
-#
-# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications
-# must understand both names and treat them as equivalent.
-#
-# The first argument passed to this file is the canonical host specification,
-# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
-# or
-# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
-
-host="$1"
-os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'`
-echo "# This file contains a table of character encoding aliases,"
-echo "# suitable for operating system '${os}'."
-echo "# It was automatically generated from config.charset."
-# List of references, updated during installation:
-echo "# Packages using this file: "
-case "$os" in
- linux-gnulibc1*)
- # Linux libc5 doesn't have nl_langinfo(CODESET); therefore
- # localcharset.c falls back to using the full locale name
- # from the environment variables.
- echo "C ASCII"
- echo "POSIX ASCII"
- for l in af af_ZA ca ca_ES da da_DK de de_AT de_BE de_CH de_DE de_LU \
- en en_AU en_BW en_CA en_DK en_GB en_IE en_NZ en_US en_ZA \
- en_ZW es es_AR es_BO es_CL es_CO es_DO es_EC es_ES es_GT \
- es_HN es_MX es_PA es_PE es_PY es_SV es_US es_UY es_VE et \
- et_EE eu eu_ES fi fi_FI fo fo_FO fr fr_BE fr_CA fr_CH fr_FR \
- fr_LU ga ga_IE gl gl_ES id id_ID in in_ID is is_IS it it_CH \
- it_IT kl kl_GL nl nl_BE nl_NL no no_NO pt pt_BR pt_PT sv \
- sv_FI sv_SE; do
- echo "$l ISO-8859-1"
- echo "$l.iso-8859-1 ISO-8859-1"
- echo "$l.iso-8859-15 ISO-8859-15"
- echo "$l.iso-8859-15@euro ISO-8859-15"
- echo "$l@euro ISO-8859-15"
- echo "$l.cp-437 CP437"
- echo "$l.cp-850 CP850"
- echo "$l.cp-1252 CP1252"
- echo "$l.cp-1252@euro CP1252"
- #echo "$l.atari-st ATARI-ST" # not a commonly used encoding
- echo "$l.utf-8 UTF-8"
- echo "$l.utf-8@euro UTF-8"
- done
- for l in cs cs_CZ hr hr_HR hu hu_HU pl pl_PL ro ro_RO sk sk_SK sl \
- sl_SI sr sr_CS sr_YU; do
- echo "$l ISO-8859-2"
- echo "$l.iso-8859-2 ISO-8859-2"
- echo "$l.cp-852 CP852"
- echo "$l.cp-1250 CP1250"
- echo "$l.utf-8 UTF-8"
- done
- for l in mk mk_MK ru ru_RU; do
- echo "$l ISO-8859-5"
- echo "$l.iso-8859-5 ISO-8859-5"
- echo "$l.koi8-r KOI8-R"
- echo "$l.cp-866 CP866"
- echo "$l.cp-1251 CP1251"
- echo "$l.utf-8 UTF-8"
- done
- for l in ar ar_SA; do
- echo "$l ISO-8859-6"
- echo "$l.iso-8859-6 ISO-8859-6"
- echo "$l.cp-864 CP864"
- #echo "$l.cp-868 CP868" # not a commonly used encoding
- echo "$l.cp-1256 CP1256"
- echo "$l.utf-8 UTF-8"
- done
- for l in el el_GR gr gr_GR; do
- echo "$l ISO-8859-7"
- echo "$l.iso-8859-7 ISO-8859-7"
- echo "$l.cp-869 CP869"
- echo "$l.cp-1253 CP1253"
- echo "$l.cp-1253@euro CP1253"
- echo "$l.utf-8 UTF-8"
- echo "$l.utf-8@euro UTF-8"
- done
- for l in he he_IL iw iw_IL; do
- echo "$l ISO-8859-8"
- echo "$l.iso-8859-8 ISO-8859-8"
- echo "$l.cp-862 CP862"
- echo "$l.cp-1255 CP1255"
- echo "$l.utf-8 UTF-8"
- done
- for l in tr tr_TR; do
- echo "$l ISO-8859-9"
- echo "$l.iso-8859-9 ISO-8859-9"
- echo "$l.cp-857 CP857"
- echo "$l.cp-1254 CP1254"
- echo "$l.utf-8 UTF-8"
- done
- for l in lt lt_LT lv lv_LV; do
- #echo "$l BALTIC" # not a commonly used encoding, wrong encoding name
- echo "$l ISO-8859-13"
- done
- for l in ru_UA uk uk_UA; do
- echo "$l KOI8-U"
- done
- for l in zh zh_CN; do
- #echo "$l GB_2312-80" # not a commonly used encoding, wrong encoding name
- echo "$l GB2312"
- done
- for l in ja ja_JP ja_JP.EUC; do
- echo "$l EUC-JP"
- done
- for l in ko ko_KR; do
- echo "$l EUC-KR"
- done
- for l in th th_TH; do
- echo "$l TIS-620"
- done
- for l in fa fa_IR; do
- #echo "$l ISIRI-3342" # a broken encoding
- echo "$l.utf-8 UTF-8"
- done
- ;;
- linux* | *-gnu*)
- # With glibc-2.1 or newer, we don't need any canonicalization,
- # because glibc has iconv and both glibc and libiconv support all
- # GNU canonical names directly. Therefore, the Makefile does not
- # need to install the alias file at all.
- # The following applies only to glibc-2.0.x and older libcs.
- echo "ISO_646.IRV:1983 ASCII"
- ;;
- aix*)
- echo "ISO8859-1 ISO-8859-1"
- echo "ISO8859-2 ISO-8859-2"
- echo "ISO8859-5 ISO-8859-5"
- echo "ISO8859-6 ISO-8859-6"
- echo "ISO8859-7 ISO-8859-7"
- echo "ISO8859-8 ISO-8859-8"
- echo "ISO8859-9 ISO-8859-9"
- echo "ISO8859-15 ISO-8859-15"
- echo "IBM-850 CP850"
- echo "IBM-856 CP856"
- echo "IBM-921 ISO-8859-13"
- echo "IBM-922 CP922"
- echo "IBM-932 CP932"
- echo "IBM-943 CP943"
- echo "IBM-1046 CP1046"
- echo "IBM-1124 CP1124"
- echo "IBM-1129 CP1129"
- echo "IBM-1252 CP1252"
- echo "IBM-eucCN GB2312"
- echo "IBM-eucJP EUC-JP"
- echo "IBM-eucKR EUC-KR"
- echo "IBM-eucTW EUC-TW"
- echo "big5 BIG5"
- echo "GBK GBK"
- echo "TIS-620 TIS-620"
- echo "UTF-8 UTF-8"
- ;;
- hpux*)
- echo "iso88591 ISO-8859-1"
- echo "iso88592 ISO-8859-2"
- echo "iso88595 ISO-8859-5"
- echo "iso88596 ISO-8859-6"
- echo "iso88597 ISO-8859-7"
- echo "iso88598 ISO-8859-8"
- echo "iso88599 ISO-8859-9"
- echo "iso885915 ISO-8859-15"
- echo "roman8 HP-ROMAN8"
- echo "arabic8 HP-ARABIC8"
- echo "greek8 HP-GREEK8"
- echo "hebrew8 HP-HEBREW8"
- echo "turkish8 HP-TURKISH8"
- echo "kana8 HP-KANA8"
- echo "tis620 TIS-620"
- echo "big5 BIG5"
- echo "eucJP EUC-JP"
- echo "eucKR EUC-KR"
- echo "eucTW EUC-TW"
- echo "hp15CN GB2312"
- #echo "ccdc ?" # what is this?
- echo "SJIS SHIFT_JIS"
- echo "utf8 UTF-8"
- ;;
- irix*)
- echo "ISO8859-1 ISO-8859-1"
- echo "ISO8859-2 ISO-8859-2"
- echo "ISO8859-5 ISO-8859-5"
- echo "ISO8859-7 ISO-8859-7"
- echo "ISO8859-9 ISO-8859-9"
- echo "eucCN GB2312"
- echo "eucJP EUC-JP"
- echo "eucKR EUC-KR"
- echo "eucTW EUC-TW"
- ;;
- osf*)
- echo "ISO8859-1 ISO-8859-1"
- echo "ISO8859-2 ISO-8859-2"
- echo "ISO8859-4 ISO-8859-4"
- echo "ISO8859-5 ISO-8859-5"
- echo "ISO8859-7 ISO-8859-7"
- echo "ISO8859-8 ISO-8859-8"
- echo "ISO8859-9 ISO-8859-9"
- echo "ISO8859-15 ISO-8859-15"
- echo "cp850 CP850"
- echo "big5 BIG5"
- echo "dechanyu DEC-HANYU"
- echo "dechanzi GB2312"
- echo "deckanji DEC-KANJI"
- echo "deckorean EUC-KR"
- echo "eucJP EUC-JP"
- echo "eucKR EUC-KR"
- echo "eucTW EUC-TW"
- echo "GBK GBK"
- echo "KSC5601 CP949"
- echo "sdeckanji EUC-JP"
- echo "SJIS SHIFT_JIS"
- echo "TACTIS TIS-620"
- echo "UTF-8 UTF-8"
- ;;
- solaris*)
- echo "646 ASCII"
- echo "ISO8859-1 ISO-8859-1"
- echo "ISO8859-2 ISO-8859-2"
- echo "ISO8859-3 ISO-8859-3"
- echo "ISO8859-4 ISO-8859-4"
- echo "ISO8859-5 ISO-8859-5"
- echo "ISO8859-6 ISO-8859-6"
- echo "ISO8859-7 ISO-8859-7"
- echo "ISO8859-8 ISO-8859-8"
- echo "ISO8859-9 ISO-8859-9"
- echo "ISO8859-15 ISO-8859-15"
- echo "koi8-r KOI8-R"
- echo "ansi-1251 CP1251"
- echo "BIG5 BIG5"
- echo "Big5-HKSCS BIG5-HKSCS"
- echo "gb2312 GB2312"
- echo "GBK GBK"
- echo "GB18030 GB18030"
- echo "cns11643 EUC-TW"
- echo "5601 EUC-KR"
- echo "ko_KR.johap92 JOHAB"
- echo "eucJP EUC-JP"
- echo "PCK SHIFT_JIS"
- echo "TIS620.2533 TIS-620"
- #echo "sun_eu_greek ?" # what is this?
- echo "UTF-8 UTF-8"
- ;;
- freebsd* | os2*)
- # FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore
- # localcharset.c falls back to using the full locale name
- # from the environment variables.
- # Likewise for OS/2. OS/2 has XFree86 just like FreeBSD. Just
- # reuse FreeBSD's locale data for OS/2.
- echo "C ASCII"
- echo "US-ASCII ASCII"
- for l in la_LN lt_LN; do
- echo "$l.ASCII ASCII"
- done
- for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
- fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \
- lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do
- echo "$l.ISO_8859-1 ISO-8859-1"
- echo "$l.DIS_8859-15 ISO-8859-15"
- done
- for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do
- echo "$l.ISO_8859-2 ISO-8859-2"
- done
- for l in la_LN lt_LT; do
- echo "$l.ISO_8859-4 ISO-8859-4"
- done
- for l in ru_RU ru_SU; do
- echo "$l.KOI8-R KOI8-R"
- echo "$l.ISO_8859-5 ISO-8859-5"
- echo "$l.CP866 CP866"
- done
- echo "uk_UA.KOI8-U KOI8-U"
- echo "zh_TW.BIG5 BIG5"
- echo "zh_TW.Big5 BIG5"
- echo "zh_CN.EUC GB2312"
- echo "ja_JP.EUC EUC-JP"
- echo "ja_JP.SJIS SHIFT_JIS"
- echo "ja_JP.Shift_JIS SHIFT_JIS"
- echo "ko_KR.EUC EUC-KR"
- ;;
- netbsd*)
- echo "646 ASCII"
- echo "ISO8859-1 ISO-8859-1"
- echo "ISO8859-2 ISO-8859-2"
- echo "ISO8859-4 ISO-8859-4"
- echo "ISO8859-5 ISO-8859-5"
- echo "ISO8859-7 ISO-8859-7"
- echo "ISO8859-13 ISO-8859-13"
- echo "ISO8859-15 ISO-8859-15"
- echo "eucCN GB2312"
- echo "eucJP EUC-JP"
- echo "eucKR EUC-KR"
- echo "eucTW EUC-TW"
- echo "BIG5 BIG5"
- echo "SJIS SHIFT_JIS"
- ;;
- darwin[56]*)
- # Darwin 6.8 doesn't have nl_langinfo(CODESET); therefore
- # localcharset.c falls back to using the full locale name
- # from the environment variables.
- echo "C ASCII"
- for l in en_AU en_CA en_GB en_US la_LN; do
- echo "$l.US-ASCII ASCII"
- done
- for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
- fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT nl_BE \
- nl_NL no_NO pt_PT sv_SE; do
- echo "$l ISO-8859-1"
- echo "$l.ISO8859-1 ISO-8859-1"
- echo "$l.ISO8859-15 ISO-8859-15"
- done
- for l in la_LN; do
- echo "$l.ISO8859-1 ISO-8859-1"
- echo "$l.ISO8859-15 ISO-8859-15"
- done
- for l in cs_CZ hr_HR hu_HU la_LN pl_PL sl_SI; do
- echo "$l.ISO8859-2 ISO-8859-2"
- done
- for l in la_LN lt_LT; do
- echo "$l.ISO8859-4 ISO-8859-4"
- done
- for l in ru_RU; do
- echo "$l.KOI8-R KOI8-R"
- echo "$l.ISO8859-5 ISO-8859-5"
- echo "$l.CP866 CP866"
- done
- for l in bg_BG; do
- echo "$l.CP1251 CP1251"
- done
- echo "uk_UA.KOI8-U KOI8-U"
- echo "zh_TW.BIG5 BIG5"
- echo "zh_TW.Big5 BIG5"
- echo "zh_CN.EUC GB2312"
- echo "ja_JP.EUC EUC-JP"
- echo "ja_JP.SJIS SHIFT_JIS"
- echo "ko_KR.EUC EUC-KR"
- ;;
- darwin*)
- # Darwin 7.5 has nl_langinfo(CODESET), but it is useless:
- # - It returns the empty string when LANG is set to a locale of the
- # form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8
- # LC_CTYPE file.
- # - The environment variables LANG, LC_CTYPE, LC_ALL are not set by
- # the system; nl_langinfo(CODESET) returns "US-ASCII" in this case.
- # - The documentation says:
- # "... all code that calls BSD system routines should ensure
- # that the const *char parameters of these routines are in UTF-8
- # encoding. All BSD system functions expect their string
- # parameters to be in UTF-8 encoding and nothing else."
- # It also says
- # "An additional caveat is that string parameters for files,
- # paths, and other file-system entities must be in canonical
- # UTF-8. In a canonical UTF-8 Unicode string, all decomposable
- # characters are decomposed ..."
- # but this is not true: You can pass non-decomposed UTF-8 strings
- # to file system functions, and it is the OS which will convert
- # them to decomposed UTF-8 before accessing the file system.
- # - The Apple Terminal application displays UTF-8 by default.
- # - However, other applications are free to use different encodings:
- # - xterm uses ISO-8859-1 by default.
- # - TextEdit uses MacRoman by default.
- # We prefer UTF-8 over decomposed UTF-8-MAC because one should
- # minimize the use of decomposed Unicode. Unfortunately, through the
- # Darwin file system, decomposed UTF-8 strings are leaked into user
- # space nevertheless.
- echo "* UTF-8"
- ;;
- beos*)
- # BeOS has a single locale, and it has UTF-8 encoding.
- echo "* UTF-8"
- ;;
- msdosdjgpp*)
- # DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore
- # localcharset.c falls back to using the full locale name
- # from the environment variables.
- echo "#"
- echo "# The encodings given here may not all be correct."
- echo "# If you find that the encoding given for your language and"
- echo "# country is not the one your DOS machine actually uses, just"
- echo "# correct it in this file, and send a mail to"
- echo "# Juan Manuel Guerrero <juan.guerrero@gmx.de>"
- echo "# and Bruno Haible <bruno@clisp.org>."
- echo "#"
- echo "C ASCII"
- # ISO-8859-1 languages
- echo "ca CP850"
- echo "ca_ES CP850"
- echo "da CP865" # not CP850 ??
- echo "da_DK CP865" # not CP850 ??
- echo "de CP850"
- echo "de_AT CP850"
- echo "de_CH CP850"
- echo "de_DE CP850"
- echo "en CP850"
- echo "en_AU CP850" # not CP437 ??
- echo "en_CA CP850"
- echo "en_GB CP850"
- echo "en_NZ CP437"
- echo "en_US CP437"
- echo "en_ZA CP850" # not CP437 ??
- echo "es CP850"
- echo "es_AR CP850"
- echo "es_BO CP850"
- echo "es_CL CP850"
- echo "es_CO CP850"
- echo "es_CR CP850"
- echo "es_CU CP850"
- echo "es_DO CP850"
- echo "es_EC CP850"
- echo "es_ES CP850"
- echo "es_GT CP850"
- echo "es_HN CP850"
- echo "es_MX CP850"
- echo "es_NI CP850"
- echo "es_PA CP850"
- echo "es_PY CP850"
- echo "es_PE CP850"
- echo "es_SV CP850"
- echo "es_UY CP850"
- echo "es_VE CP850"
- echo "et CP850"
- echo "et_EE CP850"
- echo "eu CP850"
- echo "eu_ES CP850"
- echo "fi CP850"
- echo "fi_FI CP850"
- echo "fr CP850"
- echo "fr_BE CP850"
- echo "fr_CA CP850"
- echo "fr_CH CP850"
- echo "fr_FR CP850"
- echo "ga CP850"
- echo "ga_IE CP850"
- echo "gd CP850"
- echo "gd_GB CP850"
- echo "gl CP850"
- echo "gl_ES CP850"
- echo "id CP850" # not CP437 ??
- echo "id_ID CP850" # not CP437 ??
- echo "is CP861" # not CP850 ??
- echo "is_IS CP861" # not CP850 ??
- echo "it CP850"
- echo "it_CH CP850"
- echo "it_IT CP850"
- echo "lt CP775"
- echo "lt_LT CP775"
- echo "lv CP775"
- echo "lv_LV CP775"
- echo "nb CP865" # not CP850 ??
- echo "nb_NO CP865" # not CP850 ??
- echo "nl CP850"
- echo "nl_BE CP850"
- echo "nl_NL CP850"
- echo "nn CP865" # not CP850 ??
- echo "nn_NO CP865" # not CP850 ??
- echo "no CP865" # not CP850 ??
- echo "no_NO CP865" # not CP850 ??
- echo "pt CP850"
- echo "pt_BR CP850"
- echo "pt_PT CP850"
- echo "sv CP850"
- echo "sv_SE CP850"
- # ISO-8859-2 languages
- echo "cs CP852"
- echo "cs_CZ CP852"
- echo "hr CP852"
- echo "hr_HR CP852"
- echo "hu CP852"
- echo "hu_HU CP852"
- echo "pl CP852"
- echo "pl_PL CP852"
- echo "ro CP852"
- echo "ro_RO CP852"
- echo "sk CP852"
- echo "sk_SK CP852"
- echo "sl CP852"
- echo "sl_SI CP852"
- echo "sq CP852"
- echo "sq_AL CP852"
- echo "sr CP852" # CP852 or CP866 or CP855 ??
- echo "sr_CS CP852" # CP852 or CP866 or CP855 ??
- echo "sr_YU CP852" # CP852 or CP866 or CP855 ??
- # ISO-8859-3 languages
- echo "mt CP850"
- echo "mt_MT CP850"
- # ISO-8859-5 languages
- echo "be CP866"
- echo "be_BE CP866"
- echo "bg CP866" # not CP855 ??
- echo "bg_BG CP866" # not CP855 ??
- echo "mk CP866" # not CP855 ??
- echo "mk_MK CP866" # not CP855 ??
- echo "ru CP866"
- echo "ru_RU CP866"
- echo "uk CP1125"
- echo "uk_UA CP1125"
- # ISO-8859-6 languages
- echo "ar CP864"
- echo "ar_AE CP864"
- echo "ar_DZ CP864"
- echo "ar_EG CP864"
- echo "ar_IQ CP864"
- echo "ar_IR CP864"
- echo "ar_JO CP864"
- echo "ar_KW CP864"
- echo "ar_MA CP864"
- echo "ar_OM CP864"
- echo "ar_QA CP864"
- echo "ar_SA CP864"
- echo "ar_SY CP864"
- # ISO-8859-7 languages
- echo "el CP869"
- echo "el_GR CP869"
- # ISO-8859-8 languages
- echo "he CP862"
- echo "he_IL CP862"
- # ISO-8859-9 languages
- echo "tr CP857"
- echo "tr_TR CP857"
- # Japanese
- echo "ja CP932"
- echo "ja_JP CP932"
- # Chinese
- echo "zh_CN GBK"
- echo "zh_TW CP950" # not CP938 ??
- # Korean
- echo "kr CP949" # not CP934 ??
- echo "kr_KR CP949" # not CP934 ??
- # Thai
- echo "th CP874"
- echo "th_TH CP874"
- # Other
- echo "eo CP850"
- echo "eo_EO CP850"
- ;;
-esac
diff --git a/glib/libcharset/glibc21.m4 b/glib/libcharset/glibc21.m4
deleted file mode 100644
index d95fd9861..000000000
--- a/glib/libcharset/glibc21.m4
+++ /dev/null
@@ -1,30 +0,0 @@
-# glibc21.m4 serial 3
-dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-# Test for the GNU C Library, version 2.1 or newer.
-# From Bruno Haible.
-
-AC_DEFUN([gl_GLIBC21],
- [
- AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer,
- ac_cv_gnu_library_2_1,
- [AC_EGREP_CPP([Lucky GNU user],
- [
-#include <features.h>
-#ifdef __GNU_LIBRARY__
- #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2)
- Lucky GNU user
- #endif
-#endif
- ],
- ac_cv_gnu_library_2_1=yes,
- ac_cv_gnu_library_2_1=no)
- ]
- )
- AC_SUBST(GLIBC21)
- GLIBC21="$ac_cv_gnu_library_2_1"
- ]
-)
diff --git a/glib/libcharset/libcharset-glib.patch b/glib/libcharset/libcharset-glib.patch
deleted file mode 100644
index 358d774cf..000000000
--- a/glib/libcharset/libcharset-glib.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-# Patch against libcharset version 1.4
---- libiconv-1.12/libcharset//lib/localcharset.c 2006-10-18 07:55:49.000000000 -0400
-+++ localcharset.c 2008-05-20 18:36:24.000000000 -0400
-@@ -103,8 +103,8 @@
- static const char * volatile charset_aliases;
-
- /* Return a pointer to the contents of the charset.alias file. */
--static const char *
--get_charset_aliases (void)
-+const char *
-+_g_locale_get_charset_aliases (void)
- {
- const char *cp;
-
-@@ -280,14 +280,10 @@
- If the canonical name cannot be determined, the result is a non-canonical
- name. */
-
--#ifdef STATIC
--STATIC
--#endif
- const char *
--locale_charset (void)
-+_g_locale_charset_raw (void)
- {
- const char *codeset;
-- const char *aliases;
-
- #if !(defined WIN32_NATIVE || defined OS2)
-
-@@ -436,12 +432,20 @@
-
- #endif
-
-+ return codeset;
-+}
-+
-+const char *
-+_g_locale_charset_unalias (const char *codeset)
-+{
-+ const char *aliases;
-+
- if (codeset == NULL)
- /* The canonical name cannot be determined. */
- codeset = "";
-
- /* Resolve alias. */
-- for (aliases = get_charset_aliases ();
-+ for (aliases = _g_locale_get_charset_aliases ();
- *aliases != '\0';
- aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
- if (strcmp (codeset, aliases) == 0
---- libiconv-1.12/libcharset//include/libcharset.h.in 2005-05-19 13:14:56.000000000 -0400
-+++ libcharset.h 2008-05-20 18:39:44.000000000 -0400
-@@ -19,7 +19,7 @@
- #ifndef _LIBCHARSET_H
- #define _LIBCHARSET_H
-
--#include <localcharset.h>
-+#include "localcharset.h"
-
-
- #ifdef __cplusplus
---- libiconv-1.12/libcharset//include/localcharset.h.in 2005-05-19 13:14:57.000000000 -0400
-+++ localcharset.h 2008-05-20 18:36:24.000000000 -0400
-@@ -31,8 +31,9 @@
- The result must not be freed; it is statically allocated.
- If the canonical name cannot be determined, the result is a non-canonical
- name. */
--extern const char * locale_charset (void);
--
-+extern const char * _g_locale_charset_raw (void);
-+extern const char * _g_locale_charset_unalias (const char *codeset);
-+extern const char * _g_locale_get_charset_aliases (void);
-
- #ifdef __cplusplus
- }
diff --git a/glib/libcharset/libcharset.h b/glib/libcharset/libcharset.h
deleted file mode 100644
index 686241e74..000000000
--- a/glib/libcharset/libcharset.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
- This file is part of the GNU CHARSET Library.
-
- The GNU CHARSET Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU CHARSET 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with the GNU CHARSET Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 51 Franklin Street,
- Fifth Floor, Boston, MA 02110-1301, USA. */
-
-#ifndef _LIBCHARSET_H
-#define _LIBCHARSET_H
-
-#include "localcharset.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Support for relocatable packages. */
-
-/* Sets the original and the current installation prefix of the package.
- Relocation simply replaces a pathname starting with the original prefix
- by the corresponding pathname with the current prefix instead. Both
- prefixes should be directory names without trailing slash (i.e. use ""
- instead of "/"). */
-extern void libcharset_set_relocation_prefix (const char *orig_prefix,
- const char *curr_prefix);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* _LIBCHARSET_H */
diff --git a/glib/libcharset/localcharset.c b/glib/libcharset/localcharset.c
deleted file mode 100644
index 0d001f94c..000000000
--- a/glib/libcharset/localcharset.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/* Determine a canonical name for the current locale's character encoding.
-
- Copyright (C) 2000-2006 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Library General Public License as published
- by the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- USA. */
-
-/* Written by Bruno Haible <bruno@clisp.org>. */
-
-#include "config.h"
-
-/* Specification. */
-#include "localcharset.h"
-
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#if defined _WIN32 || defined __WIN32__
-# define WIN32_NATIVE
-#endif
-
-#if defined __EMX__
-/* Assume EMX program runs on OS/2, even if compiled under DOS. */
-# define OS2
-#endif
-
-#if !defined WIN32_NATIVE
-# if HAVE_LANGINFO_CODESET
-# include <langinfo.h>
-# else
-# if 0 /* see comment below */
-# include <locale.h>
-# endif
-# endif
-# ifdef __CYGWIN__
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-# endif
-#elif defined WIN32_NATIVE
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-#endif
-#if defined OS2
-# define INCL_DOS
-# include <os2.h>
-#endif
-
-#if ENABLE_RELOCATABLE
-# include "relocatable.h"
-#else
-# define relocate(pathname) (pathname)
-#endif
-
-/* Get LIBDIR. */
-#ifndef LIBDIR
-# include "configmake.h"
-#endif
-
-#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
- /* Win32, Cygwin, OS/2, DOS */
-# define ISSLASH(C) ((C) == '/' || (C) == '\\')
-#endif
-
-#ifndef DIRECTORY_SEPARATOR
-# define DIRECTORY_SEPARATOR '/'
-#endif
-
-#ifndef ISSLASH
-# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
-#endif
-
-#if HAVE_DECL_GETC_UNLOCKED
-# undef getc
-# define getc getc_unlocked
-#endif
-
-/* The following static variable is declared 'volatile' to avoid a
- possible multithread problem in the function get_charset_aliases. If we
- are running in a threaded environment, and if two threads initialize
- 'charset_aliases' simultaneously, both will produce the same value,
- and everything will be ok if the two assignments to 'charset_aliases'
- are atomic. But I don't know what will happen if the two assignments mix. */
-#if __STDC__ != 1
-# define volatile /* empty */
-#endif
-/* Pointer to the contents of the charset.alias file, if it has already been
- read, else NULL. Its format is:
- ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */
-static const char * volatile charset_aliases;
-
-/* Return a pointer to the contents of the charset.alias file. */
-const char *
-_g_locale_get_charset_aliases (void)
-{
- const char *cp;
-
- cp = charset_aliases;
- if (cp == NULL)
- {
-#if !(defined VMS || defined WIN32_NATIVE || defined __CYGWIN__)
- FILE *fp;
- const char *dir;
- const char *base = "charset.alias";
- char *file_name;
-
- /* Make it possible to override the charset.alias location. This is
- necessary for running the testsuite before "make install". */
- dir = getenv ("CHARSETALIASDIR");
- if (dir == NULL || dir[0] == '\0')
- dir = relocate (LIBDIR);
-
- /* Concatenate dir and base into freshly allocated file_name. */
- {
- size_t dir_len = strlen (dir);
- size_t base_len = strlen (base);
- int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1]));
- file_name = (char *) malloc (dir_len + add_slash + base_len + 1);
- if (file_name != NULL)
- {
- memcpy (file_name, dir, dir_len);
- if (add_slash)
- file_name[dir_len] = DIRECTORY_SEPARATOR;
- memcpy (file_name + dir_len + add_slash, base, base_len + 1);
- }
- }
-
- if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL)
- /* Out of memory or file not found, treat it as empty. */
- cp = "";
- else
- {
- /* Parse the file's contents. */
- char *res_ptr = NULL;
- size_t res_size = 0;
-
- for (;;)
- {
- int c;
- char buf1[50+1];
- char buf2[50+1];
- size_t l1, l2;
- char *old_res_ptr;
-
- c = getc (fp);
- if (c == EOF)
- break;
- if (c == '\n' || c == ' ' || c == '\t')
- continue;
- if (c == '#')
- {
- /* Skip comment, to end of line. */
- do
- c = getc (fp);
- while (!(c == EOF || c == '\n'));
- if (c == EOF)
- break;
- continue;
- }
- ungetc (c, fp);
- if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
- break;
- l1 = strlen (buf1);
- l2 = strlen (buf2);
- old_res_ptr = res_ptr;
- if (res_size == 0)
- {
- res_size = l1 + 1 + l2 + 1;
- res_ptr = (char *) malloc (res_size + 1);
- }
- else
- {
- res_size += l1 + 1 + l2 + 1;
- res_ptr = (char *) realloc (res_ptr, res_size + 1);
- }
- if (res_ptr == NULL)
- {
- /* Out of memory. */
- res_size = 0;
- if (old_res_ptr != NULL)
- free (old_res_ptr);
- break;
- }
- strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
- strcpy (res_ptr + res_size - (l2 + 1), buf2);
- }
- fclose (fp);
- if (res_size == 0)
- cp = "";
- else
- {
- *(res_ptr + res_size) = '\0';
- cp = res_ptr;
- }
- }
-
- if (file_name != NULL)
- free (file_name);
-
-#else
-
-# if defined VMS
- /* To avoid the troubles of an extra file charset.alias_vms in the
- sources of many GNU packages, simply inline the aliases here. */
- /* The list of encodings is taken from the OpenVMS 7.3-1 documentation
- "Compaq C Run-Time Library Reference Manual for OpenVMS systems"
- section 10.7 "Handling Different Character Sets". */
- cp = "ISO8859-1" "\0" "ISO-8859-1" "\0"
- "ISO8859-2" "\0" "ISO-8859-2" "\0"
- "ISO8859-5" "\0" "ISO-8859-5" "\0"
- "ISO8859-7" "\0" "ISO-8859-7" "\0"
- "ISO8859-8" "\0" "ISO-8859-8" "\0"
- "ISO8859-9" "\0" "ISO-8859-9" "\0"
- /* Japanese */
- "eucJP" "\0" "EUC-JP" "\0"
- "SJIS" "\0" "SHIFT_JIS" "\0"
- "DECKANJI" "\0" "DEC-KANJI" "\0"
- "SDECKANJI" "\0" "EUC-JP" "\0"
- /* Chinese */
- "eucTW" "\0" "EUC-TW" "\0"
- "DECHANYU" "\0" "DEC-HANYU" "\0"
- "DECHANZI" "\0" "GB2312" "\0"
- /* Korean */
- "DECKOREAN" "\0" "EUC-KR" "\0";
-# endif
-
-# if defined WIN32_NATIVE || defined __CYGWIN__
- /* To avoid the troubles of installing a separate file in the same
- directory as the DLL and of retrieving the DLL's directory at
- runtime, simply inline the aliases here. */
-
- cp = "CP936" "\0" "GBK" "\0"
- "CP1361" "\0" "JOHAB" "\0"
- "CP20127" "\0" "ASCII" "\0"
- "CP20866" "\0" "KOI8-R" "\0"
- "CP20936" "\0" "GB2312" "\0"
- "CP21866" "\0" "KOI8-RU" "\0"
- "CP28591" "\0" "ISO-8859-1" "\0"
- "CP28592" "\0" "ISO-8859-2" "\0"
- "CP28593" "\0" "ISO-8859-3" "\0"
- "CP28594" "\0" "ISO-8859-4" "\0"
- "CP28595" "\0" "ISO-8859-5" "\0"
- "CP28596" "\0" "ISO-8859-6" "\0"
- "CP28597" "\0" "ISO-8859-7" "\0"
- "CP28598" "\0" "ISO-8859-8" "\0"
- "CP28599" "\0" "ISO-8859-9" "\0"
- "CP28605" "\0" "ISO-8859-15" "\0"
- "CP38598" "\0" "ISO-8859-8" "\0"
- "CP51932" "\0" "EUC-JP" "\0"
- "CP51936" "\0" "GB2312" "\0"
- "CP51949" "\0" "EUC-KR" "\0"
- "CP51950" "\0" "EUC-TW" "\0"
- "CP54936" "\0" "GB18030" "\0"
- "CP65001" "\0" "UTF-8" "\0";
-# endif
-#endif
-
- charset_aliases = cp;
- }
-
- return cp;
-}
-
-/* Determine the current locale's character encoding, and canonicalize it
- into one of the canonical names listed in config.charset.
- The result must not be freed; it is statically allocated.
- If the canonical name cannot be determined, the result is a non-canonical
- name. */
-
-const char *
-_g_locale_charset_raw (void)
-{
- const char *codeset;
-
-#if !(defined WIN32_NATIVE || defined OS2)
-
-# if HAVE_LANGINFO_CODESET
-
- /* Most systems support nl_langinfo (CODESET) nowadays. */
- codeset = nl_langinfo (CODESET);
-
-# ifdef __CYGWIN__
- /* Cygwin 2006 does not have locales. nl_langinfo (CODESET) always
- returns "US-ASCII". As long as this is not fixed, return the suffix
- of the locale name from the environment variables (if present) or
- the codepage as a number. */
- if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0)
- {
- const char *locale;
- static char buf[2 + 10 + 1];
-
- locale = getenv ("LC_ALL");
- if (locale == NULL || locale[0] == '\0')
- {
- locale = getenv ("LC_CTYPE");
- if (locale == NULL || locale[0] == '\0')
- locale = getenv ("LANG");
- }
- if (locale != NULL && locale[0] != '\0')
- {
- /* If the locale name contains an encoding after the dot, return
- it. */
- const char *dot = strchr (locale, '.');
-
- if (dot != NULL)
- {
- const char *modifier;
-
- dot++;
- /* Look for the possible @... trailer and remove it, if any. */
- modifier = strchr (dot, '@');
- if (modifier == NULL)
- return dot;
- if (modifier - dot < sizeof (buf))
- {
- memcpy (buf, dot, modifier - dot);
- buf [modifier - dot] = '\0';
- return buf;
- }
- }
- }
-
- /* Woe32 has a function returning the locale's codepage as a number. */
- sprintf (buf, "CP%u", GetACP ());
- codeset = buf;
- }
-# endif
-
-# else
-
- /* On old systems which lack it, use setlocale or getenv. */
- const char *locale = NULL;
-
- /* But most old systems don't have a complete set of locales. Some
- (like SunOS 4 or DJGPP) have only the C locale. Therefore we don't
- use setlocale here; it would return "C" when it doesn't support the
- locale name the user has set. */
-# if 0
- locale = setlocale (LC_CTYPE, NULL);
-# endif
- if (locale == NULL || locale[0] == '\0')
- {
- locale = getenv ("LC_ALL");
- if (locale == NULL || locale[0] == '\0')
- {
- locale = getenv ("LC_CTYPE");
- if (locale == NULL || locale[0] == '\0')
- locale = getenv ("LANG");
- }
- }
-
- /* On some old systems, one used to set locale = "iso8859_1". On others,
- you set it to "language_COUNTRY.charset". In any case, we resolve it
- through the charset.alias file. */
- codeset = locale;
-
-# endif
-
-#elif defined WIN32_NATIVE
-
- static char buf[2 + 10 + 1];
-
- /* Woe32 has a function returning the locale's codepage as a number. */
- sprintf (buf, "CP%u", GetACP ());
- codeset = buf;
-
-#elif defined OS2
-
- const char *locale;
- static char buf[2 + 10 + 1];
- ULONG cp[3];
- ULONG cplen;
-
- /* Allow user to override the codeset, as set in the operating system,
- with standard language environment variables. */
- locale = getenv ("LC_ALL");
- if (locale == NULL || locale[0] == '\0')
- {
- locale = getenv ("LC_CTYPE");
- if (locale == NULL || locale[0] == '\0')
- locale = getenv ("LANG");
- }
- if (locale != NULL && locale[0] != '\0')
- {
- /* If the locale name contains an encoding after the dot, return it. */
- const char *dot = strchr (locale, '.');
-
- if (dot != NULL)
- {
- const char *modifier;
-
- dot++;
- /* Look for the possible @... trailer and remove it, if any. */
- modifier = strchr (dot, '@');
- if (modifier == NULL)
- return dot;
- if (modifier - dot < sizeof (buf))
- {
- memcpy (buf, dot, modifier - dot);
- buf [modifier - dot] = '\0';
- return buf;
- }
- }
-
- /* Resolve through the charset.alias file. */
- codeset = locale;
- }
- else
- {
- /* OS/2 has a function returning the locale's codepage as a number. */
- if (DosQueryCp (sizeof (cp), cp, &cplen))
- codeset = "";
- else
- {
- sprintf (buf, "CP%u", cp[0]);
- codeset = buf;
- }
- }
-
-#endif
-
- return codeset;
-}
-
-const char *
-_g_locale_charset_unalias (const char *codeset)
-{
- const char *aliases;
-
- if (codeset == NULL)
- /* The canonical name cannot be determined. */
- codeset = "";
-
- /* Resolve alias. */
- for (aliases = _g_locale_get_charset_aliases ();
- *aliases != '\0';
- aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
- if (strcmp (codeset, aliases) == 0
- || (aliases[0] == '*' && aliases[1] == '\0'))
- {
- codeset = aliases + strlen (aliases) + 1;
- break;
- }
-
- /* Don't return an empty string. GNU libc and GNU libiconv interpret
- the empty string as denoting "the locale's character encoding",
- thus GNU libiconv would call this function a second time. */
- if (codeset[0] == '\0')
- codeset = "ASCII";
-
- return codeset;
-}
diff --git a/glib/libcharset/localcharset.h b/glib/libcharset/localcharset.h
deleted file mode 100644
index 674aa3ab7..000000000
--- a/glib/libcharset/localcharset.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Determine a canonical name for the current locale's character encoding.
- Copyright (C) 2000-2003 Free Software Foundation, Inc.
- This file is part of the GNU CHARSET Library.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Library General Public License as published
- by the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- USA. */
-
-#ifndef _LOCALCHARSET_H
-#define _LOCALCHARSET_H
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Determine the current locale's character encoding, and canonicalize it
- into one of the canonical names listed in config.charset.
- The result must not be freed; it is statically allocated.
- If the canonical name cannot be determined, the result is a non-canonical
- name. */
-extern const char * _g_locale_charset_raw (void);
-extern const char * _g_locale_charset_unalias (const char *codeset);
-extern const char * _g_locale_get_charset_aliases (void);
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* _LOCALCHARSET_H */
diff --git a/glib/libcharset/make-patch.sh b/glib/libcharset/make-patch.sh
deleted file mode 100755
index e60014abd..000000000
--- a/glib/libcharset/make-patch.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-
-if test $# = 1 ; then
- ORIGINAL=$1
-else
- echo "Usage: make-patch.sh /path/to/libcharset" 1>&2
- exit 1
-fi
-
-if test -f $ORIGINAL/lib/localcharset.c ; then : ; else
- echo "Usage: make-patch.sh /path/to/libcharset" 1>&2
- exit 1
-fi
-
-VERSION=`grep VERSION= $ORIGINAL/configure.ac | sed s/VERSION=//`
-
-echo "# Patch against libcharset version $VERSION" > libcharset-glib.patch
-
-for i in localcharset.c ref-add.sin ref-del.sin ; do
- diff -u $ORIGINAL/lib/$i $i >> libcharset-glib.patch
-done
-
-for i in glibc21.m4 codeset.m4 ; do
- diff -u $ORIGINAL/m4/$i $i >> libcharset-glib.patch
-done
-
-diff -u $ORIGINAL/include/libcharset.h.in libcharset.h >> libcharset-glib.patch
-diff -u $ORIGINAL/include/localcharset.h.in localcharset.h >> libcharset-glib.patch
diff --git a/glib/libcharset/ref-add.sin b/glib/libcharset/ref-add.sin
deleted file mode 100644
index 0e2b97b05..000000000
--- a/glib/libcharset/ref-add.sin
+++ /dev/null
@@ -1,31 +0,0 @@
-# Add this package to a list of references stored in a text file.
-#
-# Copyright (C) 2000 Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Library General Public License as published
-# by the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-# USA.
-#
-# Written by Bruno Haible <bruno@clisp.org>.
-#
-/^# Packages using this file: / {
- s/# Packages using this file://
- ta
- :a
- s/ @PACKAGE@ / @PACKAGE@ /
- tb
- s/ $/ @PACKAGE@ /
- :b
- s/^/# Packages using this file:/
-}
diff --git a/glib/libcharset/ref-del.sin b/glib/libcharset/ref-del.sin
deleted file mode 100644
index 1fafbfc02..000000000
--- a/glib/libcharset/ref-del.sin
+++ /dev/null
@@ -1,26 +0,0 @@
-# Remove this package from a list of references stored in a text file.
-#
-# Copyright (C) 2000 Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Library General Public License as published
-# by the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program 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
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-# USA.
-#
-# Written by Bruno Haible <bruno@clisp.org>.
-#
-/^# Packages using this file: / {
- s/# Packages using this file://
- s/ @PACKAGE@ / /
- s/^/# Packages using this file:/
-}
diff --git a/glib/libcharset/update.sh b/glib/libcharset/update.sh
deleted file mode 100755
index 5873fc768..000000000
--- a/glib/libcharset/update.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-
-if test $# = 1 ; then
- ORIGINAL=$1
-else
- echo "Usage: update.sh /path/to/libcharset" 1>&2
- exit 1
-fi
-
-if test -f $ORIGINAL/lib/localcharset.c ; then : ; else
- echo "Usage: update.sh /path/to/libcharset" 1>&2
- exit 1
-fi
-
-VERSION=`grep VERSION= $ORIGINAL/configure.ac | sed s/VERSION=//`
-
-for i in localcharset.c ref-add.sin ref-del.sin config.charset ; do
- cp $ORIGINAL/lib/$i .
-done
-
-for i in libcharset.h localcharset.h ; do
- cp $ORIGINAL/include/$i.in ./$i
-done
-
-for i in codeset.m4 glibc21.m4 ; do
- cp $ORIGINAL/m4/$i .
-done
-
-patch -p0 < libcharset-glib.patch
-
-echo "dnl From libcharset $VERSION" > ../../aclibcharset.m4
-
-
diff --git a/glib/makefile.msc.in b/glib/makefile.msc.in
deleted file mode 100644
index ebaeff308..000000000
--- a/glib/makefile.msc.in
+++ /dev/null
@@ -1,141 +0,0 @@
-## Makefile for building the GLib dlls with Microsoft C
-## Use: nmake -f makefile.msc
-
-TOP = ..\..
-
-!INCLUDE ..\build\win32\make.msc
-
-################################################################
-
-INCLUDES = -FImsvc_recommended_pragmas.h -I . -I ..
-DEFINES = -DHAVE_CONFIG_H -DGLIB_COMPILATION -DG_LOG_DOMAIN=\"GLib\" -DG_ENABLE_DEBUG -DPCRE_STATIC
-DEPCFLAGS = -Zm400 $(INTL_CFLAGS) $(DIRENT_CFLAGS)
-
-all : \
- ..\config.h \
- ..\glibconfig.h \
- galias.h \
- galiasdef.c \
- gnulib\gnulib.lib \
- pcre\pcre.lib \
- libglib-2.0-0.dll \
- glib-@GLIB_MAJOR_VERSION@.@GLIB_MINOR_VERSION@s.lib \
- gspawn-win32-helper.exe \
-
-
-gnulib\gnulib.lib :
- cd gnulib
- nmake -f makefile.msc
- cd ..
-
-pcre\pcre.lib :
- cd pcre
- nmake -f makefile.msc
- cd ..
-
-glib_OBJECTS = \
- garray.obj \
- gasyncqueue.obj \
- gatomic.obj \
- gbacktrace.obj \
- gbase64.obj \
- gbookmarkfile.obj \
- gcache.obj \
- gchecksum.obj \
- gcompletion.obj \
- gconvert.obj \
- gdataset.obj \
- gdate.obj \
- gdir.obj \
- gerror.obj \
- gfileutils.obj \
- ghash.obj \
- ghook.obj \
- giochannel.obj \
- giowin32.obj \
- gkeyfile.obj \
- glist.obj \
- gmain.obj \
- gmappedfile.obj \
- gmarkup.obj \
- gmem.obj \
- gmessages.obj \
- gnode.obj \
- goption.obj \
- gpattern.obj \
- gprimes.obj \
- gprintf.obj \
- gqsort.obj \
- gqueue.obj \
- grand.obj \
- gregex.obj \
- grel.obj \
- gscanner.obj \
- gsequence.obj \
- gshell.obj \
- gslice.obj \
- gslist.obj \
- gspawn-win32.obj \
- gstdio.obj \
- gstrfuncs.obj \
- gstring.obj \
- gtestutils.obj \
- gthread.obj \
- gthreadpool.obj \
- gtimer.obj \
- gtree.obj \
- gunibreak.obj \
- gunicollate.obj \
- gunidecomp.obj \
- guniprop.obj \
- gurifuncs.obj \
- gutf8.obj \
- gutils.obj \
- gwin32.obj \
- localcharset.obj
-
-..\glibconfig.h: ..\glibconfig.h.win32
- copy ..\glibconfig.h.win32 ..\glibconfig.h
-
-..\config.h: ..\config.h.win32
- copy ..\config.h.win32 ..\config.h
-
-galias.h: glib.symbols
- perl makegalias.pl < glib.symbols > galias.h
-
-galiasdef.c: glib.symbols
- perl makegalias.pl -def < glib.symbols > galiasdef.c
-
-localcharset.c : libcharset/localcharset.c
- copy libcharset\localcharset.c localcharset.c
-
-glib.def: glib.symbols
- echo EXPORTS > glib.def
- cl /EP -DINCLUDE_VARIABLES -DG_OS_WIN32 -DINCLUDE_INTERNAL_SYMBOLS -DALL_FILES \
- -DG_GNUC_MALLOC= -DG_GNUC_CONST= -DG_GNUC_NULL_TERMINATED= -DG_GNUC_NORETURN= \
- -DG_GNUC_PRINTF=;G_GNUC_PRINTF glib.symbols >> glib.def
-
-glib.res : glib.rc
- rc -DBUILDNUMBER=0 -r -fo glib.res glib.rc
-
-################ glib
-
-# create a static libary
-# static library can well have the real version number in the name
-glib-@GLIB_MAJOR_VERSION@.@GLIB_MINOR_VERSION@s.lib : $(glib_OBJECTS) gnulib\gnulib.lib pcre\pcre.lib
- lib /out:glib-@GLIB_MAJOR_VERSION@.@GLIB_MINOR_VERSION@s.lib $(glib_OBJECTS) gnulib\gnulib.lib pcre\pcre.lib
-
-libglib-2.0-0.dll : $(glib_OBJECTS) gnulib\gnulib.lib pcre\pcre.lib glib.def glib.res
- $(CC) $(CFLAGS) -LD -Fe$@ $(glib_OBJECTS) glib.res $(INTL_LIBS) \
- gnulib\gnulib.lib pcre\pcre.lib $(DIRENT_LIBS) user32.lib advapi32.lib shell32.lib wsock32.lib ole32.lib ws2_32.lib \
- $(LDFLAGS) /implib:glib-2.0.lib /def:glib.def
-
-gspawn-win32-helper.exe : gspawn-win32-helper.c libglib-2.0-@LT_CURRENT_MINUS_AGE@.dll
- $(CC) $(CFLAGS) -Fe$@ -DG_LOG_DOMAIN=\"gspawn-win32-helper\" gspawn-win32-helper.c glib-2.0.lib $(LDFLAGS) /subsystem:windows user32.lib
-
-################ other stuff
-
-clean::
- del ..\config.h
- del ..\glibconfig.h
-
diff --git a/glib/makegalias.pl b/glib/makegalias.pl
deleted file mode 100755
index 622026a91..000000000
--- a/glib/makegalias.pl
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/usr/bin/perl -w
-
-my $do_def = 0;
-
-if (($#ARGV >= 0) && ($ARGV[0] eq "-def")) {
- shift;
- $do_def = 1;
-}
-
-print <<EOF;
-/* Generated by makegalias.pl */
-
-#ifndef DISABLE_VISIBILITY
-
-#include "glibconfig.h"
-
-#ifdef G_HAVE_GNUC_VISIBILITY
-
-EOF
-
-if ($do_def) {
- print <<EOF
-#undef IN_FILE
-#define IN_FILE defined
-
-#undef IN_HEADER
-#define IN_HEADER(x) 1
-
-EOF
-}
-else {
- print <<EOF
-#define IN_FILE(x) 1
-#define IN_HEADER defined
-
-EOF
-}
-
-my $in_comment = 0;
-my $in_skipped_section = 0;
-
-while (<>) {
-
- # ignore empty lines
- next if /^\s*$/;
-
- # skip comments
- if ($_ =~ /^\s*\/\*/)
- {
- $in_comment = 1;
- }
-
- if ($in_comment)
- {
- if ($_ =~ /\*\/\s$/)
- {
- $in_comment = 0;
- }
-
- next;
- }
-
- # handle ifdefs
- if ($_ =~ /^\#endif/)
- {
- if (!$in_skipped_section)
- {
- print $_;
- }
-
- $in_skipped_section = 0;
-
- next;
- }
-
- if ($_ =~ /^\#ifdef\s+(INCLUDE_VARIABLES|INCLUDE_INTERNAL_SYMBOLS|ALL_FILES)/)
- {
- $in_skipped_section = 1;
- }
-
- if ($in_skipped_section)
- {
- next;
- }
-
- if ($_ =~ /^\#ifn?def\s+(G|DISABLE_MEM_POOLS|_WIN64)/)
- {
- print $_;
-
- next;
- }
-
- if ($_ =~ /^\#if.*(G_STDIO_NO_WRAP_ON_UNIX|IN_FILE|IN_HEADER|IN_FILE)/)
- {
- print $_;
-
- next;
- }
-
- chop;
- my $str = $_;
- my @words;
- my $attributes = "";
-
- @words = split(/ /, $str);
- $str = shift(@words);
- chomp($str);
- my $alias = "IA__".$str;
-
- # Drop any Win32 specific .def file syntax, but keep attributes
- foreach $word (@words) {
- $attributes = "$attributes $word" unless $word eq "PRIVATE";
- }
-
- if (!$do_def) {
- print <<EOF
-extern __typeof ($str) $alias __attribute((visibility("hidden")))$attributes;
-\#define $str $alias
-
-EOF
- }
- else {
- print <<EOF
-\#undef $str
-extern __typeof ($str) $str __attribute((alias("$alias"), visibility("default")));
-
-EOF
- }
-}
-
-print <<EOF
-
-#endif /* G_HAVE_GNUC_VISIBILITY */
-#endif /* DISABLE_VISIBILITY */
-EOF
-
diff --git a/glib/pcre/COPYING b/glib/pcre/COPYING
deleted file mode 100644
index 58eed01b6..000000000
--- a/glib/pcre/COPYING
+++ /dev/null
@@ -1,5 +0,0 @@
-PCRE LICENCE
-
-Please see the file LICENCE in the PCRE distribution for licensing details.
-
-End
diff --git a/glib/pcre/Makefile.am b/glib/pcre/Makefile.am
deleted file mode 100644
index b01c44f4d..000000000
--- a/glib/pcre/Makefile.am
+++ /dev/null
@@ -1,66 +0,0 @@
-include $(top_srcdir)/Makefile.decl
-
-INCLUDES = \
- -DG_LOG_DOMAIN=\"GLib-GRegex\" \
- -DSUPPORT_UCP \
- -DSUPPORT_UTF8 \
- -DNEWLINE=-1 \
- -DMATCH_LIMIT=10000000 \
- -DMATCH_LIMIT_RECURSION=8192 \
- -DMAX_NAME_SIZE=32 \
- -DMAX_NAME_COUNT=10000 \
- -DMAX_DUPLENGTH=30000 \
- -DLINK_SIZE=2 \
- -DPOSIX_MALLOC_THRESHOLD=10 \
- -DPCRE_STATIC \
- -I$(top_srcdir) \
- -I$(srcdir) \
- -I$(top_srcdir)/glib \
- -I$(top_builddir)/glib \
- @GLIB_DEBUG_FLAGS@ \
- -DG_DISABLE_DEPRECATED \
- -DGLIB_COMPILATION \
- $(DEPRECATED_FLAGS)\
- $(WARN_CFLAGS) \
- $(PCRE_WARN_CFLAGS) \
- $(DEP_CFLAGS)
-
-noinst_LTLIBRARIES = libpcre.la
-
-libpcre_headers =
-
-libpcre_la_SOURCES = \
- pcre_compile.c \
- pcre_chartables.c \
- pcre_config.c \
- pcre_dfa_exec.c \
- pcre_exec.c \
- pcre_fullinfo.c \
- pcre_get.c \
- pcre_globals.c \
- pcre_info.c \
- pcre_maketables.c \
- pcre_newline.c \
- pcre_ord2utf8.c \
- pcre_refcount.c \
- pcre_study.c \
- pcre_tables.c \
- pcre_try_flipped.c \
- pcre_ucp_searchfuncs.c \
- pcre_valid_utf8.c \
- pcre_version.c \
- pcre_xclass.c \
- pcre.h \
- pcre_internal.h \
- ucp.h \
- ucpinternal.h \
- $(libpcre_headers)
-
-libpcre_la_LIBADD = $(DEP_LIBS)
-
-libpcre_la_LDFLAGS = -no-undefined
-
-EXTRA_DIST += \
- COPYING \
- makefile.msc
-
diff --git a/glib/pcre/makefile.msc b/glib/pcre/makefile.msc
deleted file mode 100644
index 1ec1d72c8..000000000
--- a/glib/pcre/makefile.msc
+++ /dev/null
@@ -1,30 +0,0 @@
-TOP = ..\..\..
-!INCLUDE ..\..\build\win32\make.msc
-
-INCLUDES = \
- -I ..\.. \
- -I ..
-
-DEFINES = \
- -DPCRE_STATIC \
- -DHAVE_CONFIG_H \
- -DHAVE_LONG_LONG_FORMAT \
- -DSUPPORT_UCP \
- -DSUPPORT_UTF8 \
- -DNEWLINE=-1 \
- -DMATCH_LIMIT=10000000 \
- -DMATCH_LIMIT_RECURSION=10000000 \
- -DMAX_NAME_SIZE=32 \
- -DMAX_NAME_COUNT=10000 \
- -DMAX_DUPLENGTH=30000 \
- -DLINK_SIZE=2 \
- -DEBCDIC=0 \
- -DPOSIX_MALLOC_THRESHOLD=10
-
-OBJECTS = \
-
-
-all : pcre.lib
-
-pcre.lib : $(OBJECTS)
- lib -out:pcre.lib $(OBJECTS)
diff --git a/glib/pcre/pcre.h b/glib/pcre/pcre.h
deleted file mode 100644
index 8fc80a70e..000000000
--- a/glib/pcre/pcre.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* This is the public header file for the PCRE library, to be #included by
-applications that call the PCRE functions.
-
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-#ifndef _PCRE_H
-#define _PCRE_H
-
-/* The current PCRE version information. */
-
-#define PCRE_MAJOR 7
-#define PCRE_MINOR 8
-#define PCRE_PRERELEASE
-#define PCRE_DATE 2008-09-05
-
-/* When an application links to a PCRE DLL in Windows, the symbols that are
-imported have to be identified as such. When building PCRE, the appropriate
-export setting is defined in pcre_internal.h, which includes this file. So we
-don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */
-
-#if defined(_WIN32) && !defined(PCRE_STATIC)
-# ifndef PCRE_EXP_DECL
-# define PCRE_EXP_DECL extern __declspec(dllimport)
-# endif
-# ifdef __cplusplus
-# ifndef PCRECPP_EXP_DECL
-# define PCRECPP_EXP_DECL extern __declspec(dllimport)
-# endif
-# ifndef PCRECPP_EXP_DEFN
-# define PCRECPP_EXP_DEFN __declspec(dllimport)
-# endif
-# endif
-#endif
-
-/* By default, we use the standard "extern" declarations. */
-
-#ifndef PCRE_EXP_DECL
-# ifdef __cplusplus
-# define PCRE_EXP_DECL extern "C"
-# else
-# define PCRE_EXP_DECL extern
-# endif
-#endif
-
-#ifdef __cplusplus
-# ifndef PCRECPP_EXP_DECL
-# define PCRECPP_EXP_DECL extern
-# endif
-# ifndef PCRECPP_EXP_DEFN
-# define PCRECPP_EXP_DEFN
-# endif
-#endif
-
-/* Have to include stdlib.h in order to ensure that size_t is defined;
-it is needed here for malloc. */
-
-#include <stdlib.h>
-
-/* Allow for C++ users */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Options */
-
-#define PCRE_CASELESS 0x00000001
-#define PCRE_MULTILINE 0x00000002
-#define PCRE_DOTALL 0x00000004
-#define PCRE_EXTENDED 0x00000008
-#define PCRE_ANCHORED 0x00000010
-#define PCRE_DOLLAR_ENDONLY 0x00000020
-#define PCRE_EXTRA 0x00000040
-#define PCRE_NOTBOL 0x00000080
-#define PCRE_NOTEOL 0x00000100
-#define PCRE_UNGREEDY 0x00000200
-#define PCRE_NOTEMPTY 0x00000400
-#define PCRE_UTF8 0x00000800
-#define PCRE_NO_AUTO_CAPTURE 0x00001000
-#define PCRE_NO_UTF8_CHECK 0x00002000
-#define PCRE_AUTO_CALLOUT 0x00004000
-#define PCRE_PARTIAL 0x00008000
-#define PCRE_DFA_SHORTEST 0x00010000
-#define PCRE_DFA_RESTART 0x00020000
-#define PCRE_FIRSTLINE 0x00040000
-#define PCRE_DUPNAMES 0x00080000
-#define PCRE_NEWLINE_CR 0x00100000
-#define PCRE_NEWLINE_LF 0x00200000
-#define PCRE_NEWLINE_CRLF 0x00300000
-#define PCRE_NEWLINE_ANY 0x00400000
-#define PCRE_NEWLINE_ANYCRLF 0x00500000
-#define PCRE_BSR_ANYCRLF 0x00800000
-#define PCRE_BSR_UNICODE 0x01000000
-#define PCRE_JAVASCRIPT_COMPAT 0x02000000
-
-/* Exec-time and get/set-time error codes */
-
-#define PCRE_ERROR_NOMATCH (-1)
-#define PCRE_ERROR_NULL (-2)
-#define PCRE_ERROR_BADOPTION (-3)
-#define PCRE_ERROR_BADMAGIC (-4)
-#define PCRE_ERROR_UNKNOWN_OPCODE (-5)
-#define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */
-#define PCRE_ERROR_NOMEMORY (-6)
-#define PCRE_ERROR_NOSUBSTRING (-7)
-#define PCRE_ERROR_MATCHLIMIT (-8)
-#define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */
-#define PCRE_ERROR_BADUTF8 (-10)
-#define PCRE_ERROR_BADUTF8_OFFSET (-11)
-#define PCRE_ERROR_PARTIAL (-12)
-#define PCRE_ERROR_BADPARTIAL (-13)
-#define PCRE_ERROR_INTERNAL (-14)
-#define PCRE_ERROR_BADCOUNT (-15)
-#define PCRE_ERROR_DFA_UITEM (-16)
-#define PCRE_ERROR_DFA_UCOND (-17)
-#define PCRE_ERROR_DFA_UMLIMIT (-18)
-#define PCRE_ERROR_DFA_WSSIZE (-19)
-#define PCRE_ERROR_DFA_RECURSE (-20)
-#define PCRE_ERROR_RECURSIONLIMIT (-21)
-#define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */
-#define PCRE_ERROR_BADNEWLINE (-23)
-
-/* Request types for pcre_fullinfo() */
-
-#define PCRE_INFO_OPTIONS 0
-#define PCRE_INFO_SIZE 1
-#define PCRE_INFO_CAPTURECOUNT 2
-#define PCRE_INFO_BACKREFMAX 3
-#define PCRE_INFO_FIRSTBYTE 4
-#define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */
-#define PCRE_INFO_FIRSTTABLE 5
-#define PCRE_INFO_LASTLITERAL 6
-#define PCRE_INFO_NAMEENTRYSIZE 7
-#define PCRE_INFO_NAMECOUNT 8
-#define PCRE_INFO_NAMETABLE 9
-#define PCRE_INFO_STUDYSIZE 10
-#define PCRE_INFO_DEFAULT_TABLES 11
-#define PCRE_INFO_OKPARTIAL 12
-#define PCRE_INFO_JCHANGED 13
-#define PCRE_INFO_HASCRORLF 14
-
-/* Request types for pcre_config(). Do not re-arrange, in order to remain
-compatible. */
-
-#define PCRE_CONFIG_UTF8 0
-#define PCRE_CONFIG_NEWLINE 1
-#define PCRE_CONFIG_LINK_SIZE 2
-#define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3
-#define PCRE_CONFIG_MATCH_LIMIT 4
-#define PCRE_CONFIG_STACKRECURSE 5
-#define PCRE_CONFIG_UNICODE_PROPERTIES 6
-#define PCRE_CONFIG_MATCH_LIMIT_RECURSION 7
-#define PCRE_CONFIG_BSR 8
-
-/* Bit flags for the pcre_extra structure. Do not re-arrange or redefine
-these bits, just add new ones on the end, in order to remain compatible. */
-
-#define PCRE_EXTRA_STUDY_DATA 0x0001
-#define PCRE_EXTRA_MATCH_LIMIT 0x0002
-#define PCRE_EXTRA_CALLOUT_DATA 0x0004
-#define PCRE_EXTRA_TABLES 0x0008
-#define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0x0010
-
-/* Types */
-
-struct real_pcre; /* declaration; the definition is private */
-typedef struct real_pcre pcre;
-
-/* When PCRE is compiled as a C++ library, the subject pointer type can be
-replaced with a custom type. For conventional use, the public interface is a
-const char *. */
-
-#ifndef PCRE_SPTR
-#define PCRE_SPTR const char *
-#endif
-
-/* The structure for passing additional data to pcre_exec(). This is defined in
-such as way as to be extensible. Always add new fields at the end, in order to
-remain compatible. */
-
-typedef struct pcre_extra {
- unsigned long int flags; /* Bits for which fields are set */
- void *study_data; /* Opaque data from pcre_study() */
- unsigned long int match_limit; /* Maximum number of calls to match() */
- void *callout_data; /* Data passed back in callouts */
- const unsigned char *tables; /* Pointer to character tables */
- unsigned long int match_limit_recursion; /* Max recursive calls to match() */
-} pcre_extra;
-
-/* The structure for passing out data via the pcre_callout_function. We use a
-structure so that new fields can be added on the end in future versions,
-without changing the API of the function, thereby allowing old clients to work
-without modification. */
-
-typedef struct pcre_callout_block {
- int version; /* Identifies version of block */
- /* ------------------------ Version 0 ------------------------------- */
- int callout_number; /* Number compiled into pattern */
- int *offset_vector; /* The offset vector */
- PCRE_SPTR subject; /* The subject being matched */
- int subject_length; /* The length of the subject */
- int start_match; /* Offset to start of this match attempt */
- int current_position; /* Where we currently are in the subject */
- int capture_top; /* Max current capture */
- int capture_last; /* Most recently closed capture */
- void *callout_data; /* Data passed in with the call */
- /* ------------------- Added for Version 1 -------------------------- */
- int pattern_position; /* Offset to next item in the pattern */
- int next_item_length; /* Length of next item in the pattern */
- /* ------------------------------------------------------------------ */
-} pcre_callout_block;
-
-#include "glib.h"
-#include "galias.h"
-
-#define pcre_malloc g_try_malloc
-#define pcre_free g_free
-#define pcre_stack_malloc g_try_malloc
-
-PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *);
-
-/* Exported PCRE functions */
-
-PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *,
- const unsigned char *);
-PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **,
- int *, const unsigned char *);
-PCRE_EXP_DECL int pcre_config(int, void *);
-PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *,
- int *, int, const char *, char *, int);
-PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int, char *,
- int);
-PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *,
- const char *, int, int, int, int *, int , int *, int);
-PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR,
- int, int, int, int *, int);
-PCRE_EXP_DECL void pcre_free_substring(const char *);
-PCRE_EXP_DECL void pcre_free_substring_list(const char **);
-PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int,
- void *);
-PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *,
- int *, int, const char *, const char **);
-PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *);
-PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *,
- char **, char **);
-PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int,
- const char **);
-PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int,
- const char ***);
-PCRE_EXP_DECL int pcre_info(const pcre *, int *, int *);
-PCRE_EXP_DECL const unsigned char *pcre_maketables(void);
-PCRE_EXP_DECL int pcre_refcount(pcre *, int);
-PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **);
-PCRE_EXP_DECL const char *pcre_version(void);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* End of pcre.h */
diff --git a/glib/pcre/pcre_chartables.c b/glib/pcre/pcre_chartables.c
deleted file mode 100644
index ae45db0ca..000000000
--- a/glib/pcre/pcre_chartables.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* This file contains character tables that are used when no external tables
-are passed to PCRE by the application that calls it. The tables are used only
-for characters whose code values are less than 256.
-
-This is a default version of the tables that assumes ASCII encoding. A program
-called dftables (which is distributed with PCRE) can be used to build
-alternative versions of this file. This is necessary if you are running in an
-EBCDIC environment, or if you want to default to a different encoding, for
-example ISO-8859-1. When dftables is run, it creates these tables in the
-current locale. If PCRE is configured with --enable-rebuild-chartables, this
-happens automatically.
-
-The following #includes are present because without the gcc 4.x may remove the
-array definition from the final binary if PCRE is built into a static library
-and dead code stripping is activated. This leads to link errors. Pulling in the
-header ensures that the array gets flagged as "someone outside this compilation
-unit might reference this" and so it will always be supplied to the linker. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-const unsigned char _pcre_default_tables[] = {
-
-/* This table is a lower casing table. */
-
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 97, 98, 99,100,101,102,103,
- 104,105,106,107,108,109,110,111,
- 112,113,114,115,116,117,118,119,
- 120,121,122, 91, 92, 93, 94, 95,
- 96, 97, 98, 99,100,101,102,103,
- 104,105,106,107,108,109,110,111,
- 112,113,114,115,116,117,118,119,
- 120,121,122,123,124,125,126,127,
- 128,129,130,131,132,133,134,135,
- 136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,
- 152,153,154,155,156,157,158,159,
- 160,161,162,163,164,165,166,167,
- 168,169,170,171,172,173,174,175,
- 176,177,178,179,180,181,182,183,
- 184,185,186,187,188,189,190,191,
- 192,193,194,195,196,197,198,199,
- 200,201,202,203,204,205,206,207,
- 208,209,210,211,212,213,214,215,
- 216,217,218,219,220,221,222,223,
- 224,225,226,227,228,229,230,231,
- 232,233,234,235,236,237,238,239,
- 240,241,242,243,244,245,246,247,
- 248,249,250,251,252,253,254,255,
-
-/* This table is a case flipping table. */
-
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 97, 98, 99,100,101,102,103,
- 104,105,106,107,108,109,110,111,
- 112,113,114,115,116,117,118,119,
- 120,121,122, 91, 92, 93, 94, 95,
- 96, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90,123,124,125,126,127,
- 128,129,130,131,132,133,134,135,
- 136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,
- 152,153,154,155,156,157,158,159,
- 160,161,162,163,164,165,166,167,
- 168,169,170,171,172,173,174,175,
- 176,177,178,179,180,181,182,183,
- 184,185,186,187,188,189,190,191,
- 192,193,194,195,196,197,198,199,
- 200,201,202,203,204,205,206,207,
- 208,209,210,211,212,213,214,215,
- 216,217,218,219,220,221,222,223,
- 224,225,226,227,228,229,230,231,
- 232,233,234,235,236,237,238,239,
- 240,241,242,243,244,245,246,247,
- 248,249,250,251,252,253,254,255,
-
-/* This table contains bit maps for various character classes. Each map is 32
-bytes long and the bits run from the least significant end of each byte. The
-classes that have their own maps are: space, xdigit, digit, upper, lower, word,
-graph, print, punct, and cntrl. Other classes are built from combinations. */
-
- 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
- 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
- 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,
- 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-/* This table identifies various classes of character by individual bits:
- 0x01 white space character
- 0x02 letter
- 0x04 decimal digit
- 0x08 hexadecimal digit
- 0x10 alphanumeric or '_'
- 0x80 regular expression metacharacter or binary zero
-*/
-
- 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
- 0x00,0x01,0x01,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
- 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */
- 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */
- 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */
- 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */
- 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */
- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */
- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */
- 0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */
- 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */
- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */
- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */
- 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */
-
-/* End of pcre_chartables.c */
diff --git a/glib/pcre/pcre_compile.c b/glib/pcre/pcre_compile.c
deleted file mode 100644
index ae68fb566..000000000
--- a/glib/pcre/pcre_compile.c
+++ /dev/null
@@ -1,6258 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains the external function pcre_compile(), along with
-supporting internal functions that are not used by other modules. */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define NLBLOCK cd /* Block containing newline information */
-#define PSSTART start_pattern /* Field containing processed string start */
-#define PSEND end_pattern /* Field containing processed string end */
-
-#include "pcre_internal.h"
-
-
-/* When DEBUG is defined, we need the pcre_printint() function, which is also
-used by pcretest. DEBUG is not defined when building a production library. */
-
-#ifdef DEBUG
-#include "pcre_printint.src"
-#endif
-
-
-/* Macro for setting individual bits in class bitmaps. */
-
-#define SETBIT(a,b) a[b/8] |= (1 << (b%8))
-
-/* Maximum length value to check against when making sure that the integer that
-holds the compiled pattern length does not overflow. We make it a bit less than
-INT_MAX to allow for adding in group terminating bytes, so that we don't have
-to check them every time. */
-
-#define OFLOW_MAX (INT_MAX - 20)
-
-
-/*************************************************
-* Code parameters and static tables *
-*************************************************/
-
-/* This value specifies the size of stack workspace that is used during the
-first pre-compile phase that determines how much memory is required. The regex
-is partly compiled into this space, but the compiled parts are discarded as
-soon as they can be, so that hopefully there will never be an overrun. The code
-does, however, check for an overrun. The largest amount I've seen used is 218,
-so this number is very generous.
-
-The same workspace is used during the second, actual compile phase for
-remembering forward references to groups so that they can be filled in at the
-end. Each entry in this list occupies LINK_SIZE bytes, so even when LINK_SIZE
-is 4 there is plenty of room. */
-
-#define COMPILE_WORK_SIZE (4096)
-
-
-/* Table for handling escaped characters in the range '0'-'z'. Positive returns
-are simple data values; negative values are for special things like \d and so
-on. Zero means further processing is needed (for things like \x), or the escape
-is invalid. */
-
-#ifndef EBCDIC /* This is the "normal" table for ASCII systems */
-static const short int escapes[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */
- 0, 0, ':', ';', '<', '=', '>', '?', /* 8 - ? */
- '@', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G, /* @ - G */
--ESC_H, 0, 0, -ESC_K, 0, 0, 0, 0, /* H - O */
--ESC_P, -ESC_Q, -ESC_R, -ESC_S, 0, 0, -ESC_V, -ESC_W, /* P - W */
--ESC_X, 0, -ESC_Z, '[', '\\', ']', '^', '_', /* X - _ */
- '`', 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* ` - g */
--ESC_h, 0, 0, -ESC_k, 0, 0, ESC_n, 0, /* h - o */
--ESC_p, 0, ESC_r, -ESC_s, ESC_tee, 0, -ESC_v, -ESC_w, /* p - w */
- 0, 0, -ESC_z /* x - z */
-};
-
-#else /* This is the "abnormal" table for EBCDIC systems */
-static const short int escapes[] = {
-/* 48 */ 0, 0, 0, '.', '<', '(', '+', '|',
-/* 50 */ '&', 0, 0, 0, 0, 0, 0, 0,
-/* 58 */ 0, 0, '!', '$', '*', ')', ';', '~',
-/* 60 */ '-', '/', 0, 0, 0, 0, 0, 0,
-/* 68 */ 0, 0, '|', ',', '%', '_', '>', '?',
-/* 70 */ 0, 0, 0, 0, 0, 0, 0, 0,
-/* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"',
-/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0,
-/* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0,
-/* 90 */ 0, 0, -ESC_k, 'l', 0, ESC_n, 0, -ESC_p,
-/* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0,
-/* A0 */ 0, '~', -ESC_s, ESC_tee, 0,-ESC_v, -ESC_w, 0,
-/* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0,
-/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0,
-/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-',
-/* C0 */ '{',-ESC_A, -ESC_B, -ESC_C, -ESC_D,-ESC_E, 0, -ESC_G,
-/* C8 */-ESC_H, 0, 0, 0, 0, 0, 0, 0,
-/* D0 */ '}', 0, -ESC_K, 0, 0, 0, 0, -ESC_P,
-/* D8 */-ESC_Q,-ESC_R, 0, 0, 0, 0, 0, 0,
-/* E0 */ '\\', 0, -ESC_S, 0, 0,-ESC_V, -ESC_W, -ESC_X,
-/* E8 */ 0,-ESC_Z, 0, 0, 0, 0, 0, 0,
-/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0,
-/* F8 */ 0, 0, 0, 0, 0, 0, 0, 0
-};
-#endif
-
-
-/* Table of special "verbs" like (*PRUNE). This is a short table, so it is
-searched linearly. Put all the names into a single string, in order to reduce
-the number of relocations when a shared library is dynamically linked. */
-
-typedef struct verbitem {
- int len;
- int op;
-} verbitem;
-
-static const char verbnames[] =
- "ACCEPT\0"
- "COMMIT\0"
- "F\0"
- "FAIL\0"
- "PRUNE\0"
- "SKIP\0"
- "THEN";
-
-static const verbitem verbs[] = {
- { 6, OP_ACCEPT },
- { 6, OP_COMMIT },
- { 1, OP_FAIL },
- { 4, OP_FAIL },
- { 5, OP_PRUNE },
- { 4, OP_SKIP },
- { 4, OP_THEN }
-};
-
-static const int verbcount = sizeof(verbs)/sizeof(verbitem);
-
-
-/* Tables of names of POSIX character classes and their lengths. The names are
-now all in a single string, to reduce the number of relocations when a shared
-library is dynamically loaded. The list of lengths is terminated by a zero
-length entry. The first three must be alpha, lower, upper, as this is assumed
-for handling case independence. */
-
-static const char posix_names[] =
- "alpha\0" "lower\0" "upper\0" "alnum\0" "ascii\0" "blank\0"
- "cntrl\0" "digit\0" "graph\0" "print\0" "punct\0" "space\0"
- "word\0" "xdigit";
-
-static const uschar posix_name_lengths[] = {
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };
-
-/* Table of class bit maps for each POSIX class. Each class is formed from a
-base map, with an optional addition or removal of another map. Then, for some
-classes, there is some additional tweaking: for [:blank:] the vertical space
-characters are removed, and for [:alpha:] and [:alnum:] the underscore
-character is removed. The triples in the table consist of the base map offset,
-second map offset or -1 if no second map, and a non-negative value for map
-addition or a negative value for map subtraction (if there are two maps). The
-absolute value of the third field has these meanings: 0 => no tweaking, 1 =>
-remove vertical space characters, 2 => remove underscore. */
-
-static const int posix_class_maps[] = {
- cbit_word, cbit_digit, -2, /* alpha */
- cbit_lower, -1, 0, /* lower */
- cbit_upper, -1, 0, /* upper */
- cbit_word, -1, 2, /* alnum - word without underscore */
- cbit_print, cbit_cntrl, 0, /* ascii */
- cbit_space, -1, 1, /* blank - a GNU extension */
- cbit_cntrl, -1, 0, /* cntrl */
- cbit_digit, -1, 0, /* digit */
- cbit_graph, -1, 0, /* graph */
- cbit_print, -1, 0, /* print */
- cbit_punct, -1, 0, /* punct */
- cbit_space, -1, 0, /* space */
- cbit_word, -1, 0, /* word - a Perl extension */
- cbit_xdigit,-1, 0 /* xdigit */
-};
-
-
-#define STRING(a) # a
-#define XSTRING(s) STRING(s)
-
-/* The texts of compile-time error messages. These are "char *" because they
-are passed to the outside world. Do not ever re-use any error number, because
-they are documented. Always add a new error instead. Messages marked DEAD below
-are no longer used. This used to be a table of strings, but in order to reduce
-the number of relocations needed when a shared library is loaded dynamically,
-it is now one long string. We cannot use a table of offsets, because the
-lengths of inserts such as XSTRING(MAX_NAME_SIZE) are not known. Instead, we
-simply count through to the one we want - this isn't a performance issue
-because these strings are used only when there is a compilation error. */
-
-static const char error_texts[] =
- "no error\0"
- "\\ at end of pattern\0"
- "\\c at end of pattern\0"
- "unrecognized character follows \\\0"
- "numbers out of order in {} quantifier\0"
- /* 5 */
- "number too big in {} quantifier\0"
- "missing terminating ] for character class\0"
- "invalid escape sequence in character class\0"
- "range out of order in character class\0"
- "nothing to repeat\0"
- /* 10 */
- "operand of unlimited repeat could match the empty string\0" /** DEAD **/
- "internal error: unexpected repeat\0"
- "unrecognized character after (? or (?-\0"
- "POSIX named classes are supported only within a class\0"
- "missing )\0"
- /* 15 */
- "reference to non-existent subpattern\0"
- "erroffset passed as NULL\0"
- "unknown option bit(s) set\0"
- "missing ) after comment\0"
- "parentheses nested too deeply\0" /** DEAD **/
- /* 20 */
- "regular expression is too large\0"
- "failed to get memory\0"
- "unmatched parentheses\0"
- "internal error: code overflow\0"
- "unrecognized character after (?<\0"
- /* 25 */
- "lookbehind assertion is not fixed length\0"
- "malformed number or name after (?(\0"
- "conditional group contains more than two branches\0"
- "assertion expected after (?(\0"
- "(?R or (?[+-]digits must be followed by )\0"
- /* 30 */
- "unknown POSIX class name\0"
- "POSIX collating elements are not supported\0"
- "this version of PCRE is not compiled with PCRE_UTF8 support\0"
- "spare error\0" /** DEAD **/
- "character value in \\x{...} sequence is too large\0"
- /* 35 */
- "invalid condition (?(0)\0"
- "\\C not allowed in lookbehind assertion\0"
- "PCRE does not support \\L, \\l, \\N, \\U, or \\u\0"
- "number after (?C is > 255\0"
- "closing ) for (?C expected\0"
- /* 40 */
- "recursive call could loop indefinitely\0"
- "unrecognized character after (?P\0"
- "syntax error in subpattern name (missing terminator)\0"
- "two named subpatterns have the same name\0"
- "invalid UTF-8 string\0"
- /* 45 */
- "support for \\P, \\p, and \\X has not been compiled\0"
- "malformed \\P or \\p sequence\0"
- "unknown property name after \\P or \\p\0"
- "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " characters)\0"
- "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0"
- /* 50 */
- "repeated subpattern is too long\0" /** DEAD **/
- "octal value is greater than \\377 (not in UTF-8 mode)\0"
- "internal error: overran compiling workspace\0"
- "internal error: previously-checked referenced subpattern not found\0"
- "DEFINE group contains more than one branch\0"
- /* 55 */
- "repeating a DEFINE group is not allowed\0"
- "inconsistent NEWLINE options\0"
- "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number\0"
- "a numbered reference must not be zero\0"
- "(*VERB) with an argument is not supported\0"
- /* 60 */
- "(*VERB) not recognized\0"
- "number is too big\0"
- "subpattern name expected\0"
- "digit expected after (?+\0"
- "] is an invalid data character in JavaScript compatibility mode";
-
-
-/* Definition to allow mutual recursion */
-
-static BOOL
- compile_regex(int, int, uschar **, const uschar **, int *, BOOL, BOOL, int,
- int *, int *, branch_chain *, compile_data *, int *);
-
-
-
-/*************************************************
-* Find an error text *
-*************************************************/
-
-/* The error texts are now all in one long string, to save on relocations. As
-some of the text is of unknown length, we can't use a table of offsets.
-Instead, just count through the strings. This is not a performance issue
-because it happens only when there has been a compilation error.
-
-Argument: the error number
-Returns: pointer to the error string
-*/
-
-static const char *
-find_error_text(int n)
-{
-const char *s = error_texts;
-for (; n > 0; n--) while (*s++ != 0) {};
-return s;
-}
-
-
-/*************************************************
-* Handle escapes *
-*************************************************/
-
-/* This function is called when a \ has been encountered. It either returns a
-positive value for a simple escape such as \n, or a negative value which
-encodes one of the more complicated things such as \d. A backreference to group
-n is returned as -(ESC_REF + n); ESC_REF is the highest ESC_xxx macro. When
-UTF-8 is enabled, a positive value greater than 255 may be returned. On entry,
-ptr is pointing at the \. On exit, it is on the final character of the escape
-sequence.
-
-Arguments:
- ptrptr points to the pattern position pointer
- errorcodeptr points to the errorcode variable
- bracount number of previous extracting brackets
- options the options bits
- isclass TRUE if inside a character class
-
-Returns: zero or positive => a data character
- negative => a special escape sequence
- on error, errorcodeptr is set
-*/
-
-static int
-check_escape(const uschar **ptrptr, int *errorcodeptr, int bracount,
- int options, BOOL isclass)
-{
-BOOL utf8 = (options & PCRE_UTF8) != 0;
-const uschar *ptr = *ptrptr + 1;
-int c, i;
-
-GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */
-ptr--; /* Set pointer back to the last byte */
-
-/* If backslash is at the end of the pattern, it's an error. */
-
-if (c == 0) *errorcodeptr = ERR1;
-
-/* Non-alphanumerics are literals. For digits or letters, do an initial lookup
-in a table. A non-zero result is something that can be returned immediately.
-Otherwise further processing may be required. */
-
-#ifndef EBCDIC /* ASCII coding */
-else if (c < '0' || c > 'z') {} /* Not alphanumeric */
-else if ((i = escapes[c - '0']) != 0) c = i;
-
-#else /* EBCDIC coding */
-else if (c < 'a' || (ebcdic_chartab[c] & 0x0E) == 0) {} /* Not alphanumeric */
-else if ((i = escapes[c - 0x48]) != 0) c = i;
-#endif
-
-/* Escapes that need further processing, or are illegal. */
-
-else
- {
- const uschar *oldptr;
- BOOL braced, negated;
-
- switch (c)
- {
- /* A number of Perl escapes are not handled by PCRE. We give an explicit
- error. */
-
- case 'l':
- case 'L':
- case 'N':
- case 'u':
- case 'U':
- *errorcodeptr = ERR37;
- break;
-
- /* \g must be followed by one of a number of specific things:
-
- (1) A number, either plain or braced. If positive, it is an absolute
- backreference. If negative, it is a relative backreference. This is a Perl
- 5.10 feature.
-
- (2) Perl 5.10 also supports \g{name} as a reference to a named group. This
- is part of Perl's movement towards a unified syntax for back references. As
- this is synonymous with \k{name}, we fudge it up by pretending it really
- was \k.
-
- (3) For Oniguruma compatibility we also support \g followed by a name or a
- number either in angle brackets or in single quotes. However, these are
- (possibly recursive) subroutine calls, _not_ backreferences. Just return
- the -ESC_g code (cf \k). */
-
- case 'g':
- if (ptr[1] == '<' || ptr[1] == '\'')
- {
- c = -ESC_g;
- break;
- }
-
- /* Handle the Perl-compatible cases */
-
- if (ptr[1] == '{')
- {
- const uschar *p;
- for (p = ptr+2; *p != 0 && *p != '}'; p++)
- if (*p != '-' && g_ascii_isdigit (*p) == 0) break;
- if (*p != 0 && *p != '}')
- {
- c = -ESC_k;
- break;
- }
- braced = TRUE;
- ptr++;
- }
- else braced = FALSE;
-
- if (ptr[1] == '-')
- {
- negated = TRUE;
- ptr++;
- }
- else negated = FALSE;
-
- c = 0;
- while (g_ascii_isdigit (ptr[1]) != 0)
- c = c * 10 + *(++ptr) - '0';
-
- if (c < 0) /* Integer overflow */
- {
- *errorcodeptr = ERR61;
- break;
- }
-
- if (braced && *(++ptr) != '}')
- {
- *errorcodeptr = ERR57;
- break;
- }
-
- if (c == 0)
- {
- *errorcodeptr = ERR58;
- break;
- }
-
- if (negated)
- {
- if (c > bracount)
- {
- *errorcodeptr = ERR15;
- break;
- }
- c = bracount - (c - 1);
- }
-
- c = -(ESC_REF + c);
- break;
-
- /* The handling of escape sequences consisting of a string of digits
- starting with one that is not zero is not straightforward. By experiment,
- the way Perl works seems to be as follows:
-
- Outside a character class, the digits are read as a decimal number. If the
- number is less than 10, or if there are that many previous extracting
- left brackets, then it is a back reference. Otherwise, up to three octal
- digits are read to form an escaped byte. Thus \123 is likely to be octal
- 123 (cf \0123, which is octal 012 followed by the literal 3). If the octal
- value is greater than 377, the least significant 8 bits are taken. Inside a
- character class, \ followed by a digit is always an octal number. */
-
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
-
- if (!isclass)
- {
- oldptr = ptr;
- c -= '0';
- while (g_ascii_isdigit (ptr[1]))
- c = c * 10 + *(++ptr) - '0';
- if (c < 0) /* Integer overflow */
- {
- *errorcodeptr = ERR61;
- break;
- }
- if (c < 10 || c <= bracount)
- {
- c = -(ESC_REF + c);
- break;
- }
- ptr = oldptr; /* Put the pointer back and fall through */
- }
-
- /* Handle an octal number following \. If the first digit is 8 or 9, Perl
- generates a binary zero byte and treats the digit as a following literal.
- Thus we have to pull back the pointer by one. */
-
- if ((c = *ptr) >= '8')
- {
- ptr--;
- c = 0;
- break;
- }
-
- /* \0 always starts an octal number, but we may drop through to here with a
- larger first octal digit. The original code used just to take the least
- significant 8 bits of octal numbers (I think this is what early Perls used
- to do). Nowadays we allow for larger numbers in UTF-8 mode, but no more
- than 3 octal digits. */
-
- case '0':
- c -= '0';
- while(i++ < 2 && ptr[1] >= '0' && ptr[1] <= '7')
- c = c * 8 + *(++ptr) - '0';
- if (!utf8 && c > 255) *errorcodeptr = ERR51;
- break;
-
- /* \x is complicated. \x{ddd} is a character number which can be greater
- than 0xff in utf8 mode, but only if the ddd are hex digits. If not, { is
- treated as a data character. */
-
- case 'x':
- if (ptr[1] == '{')
- {
- const uschar *pt = ptr + 2;
- int count = 0;
-
- c = 0;
- while (g_ascii_isxdigit (*pt) != 0)
- {
- register int cc = *pt++;
- if (c == 0 && cc == '0') continue; /* Leading zeroes */
- count++;
-
-#ifndef EBCDIC /* ASCII coding */
- if (cc >= 'a') cc -= 32; /* Convert to upper case */
- c = (c << 4) + cc - ((cc < 'A')? '0' : ('A' - 10));
-#else /* EBCDIC coding */
- if (cc >= 'a' && cc <= 'z') cc += 64; /* Convert to upper case */
- c = (c << 4) + cc - ((cc >= '0')? '0' : ('A' - 10));
-#endif
- }
-
- if (*pt == '}')
- {
- if (c < 0 || count > (utf8? 8 : 2)) *errorcodeptr = ERR34;
- ptr = pt;
- break;
- }
-
- /* If the sequence of hex digits does not end with '}', then we don't
- recognize this construct; fall through to the normal \x handling. */
- }
-
- /* Read just a single-byte hex-defined char */
-
- c = 0;
- while (i++ < 2 && g_ascii_isxdigit (ptr[1]) != 0)
- {
- int cc; /* Some compilers don't like ++ */
- cc = *(++ptr); /* in initializers */
-#ifndef EBCDIC /* ASCII coding */
- if (cc >= 'a') cc -= 32; /* Convert to upper case */
- c = c * 16 + cc - ((cc < 'A')? '0' : ('A' - 10));
-#else /* EBCDIC coding */
- if (cc <= 'z') cc += 64; /* Convert to upper case */
- c = c * 16 + cc - ((cc >= '0')? '0' : ('A' - 10));
-#endif
- }
- break;
-
- /* For \c, a following letter is upper-cased; then the 0x40 bit is flipped.
- This coding is ASCII-specific, but then the whole concept of \cx is
- ASCII-specific. (However, an EBCDIC equivalent has now been added.) */
-
- case 'c':
- c = *(++ptr);
- if (c == 0)
- {
- *errorcodeptr = ERR2;
- break;
- }
-
-#ifndef EBCDIC /* ASCII coding */
- if (c >= 'a' && c <= 'z') c -= 32;
- c ^= 0x40;
-#else /* EBCDIC coding */
- if (c >= 'a' && c <= 'z') c += 64;
- c ^= 0xC0;
-#endif
- break;
-
- /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any
- other alphanumeric following \ is an error if PCRE_EXTRA was set;
- otherwise, for Perl compatibility, it is a literal. This code looks a bit
- odd, but there used to be some cases other than the default, and there may
- be again in future, so I haven't "optimized" it. */
-
- default:
- if ((options & PCRE_EXTRA) != 0) switch(c)
- {
- default:
- *errorcodeptr = ERR3;
- break;
- }
- break;
- }
- }
-
-*ptrptr = ptr;
-return c;
-}
-
-
-
-#ifdef SUPPORT_UCP
-/*************************************************
-* Handle \P and \p *
-*************************************************/
-
-/* This function is called after \P or \p has been encountered, provided that
-PCRE is compiled with support for Unicode properties. On entry, ptrptr is
-pointing at the P or p. On exit, it is pointing at the final character of the
-escape sequence.
-
-Argument:
- ptrptr points to the pattern position pointer
- negptr points to a boolean that is set TRUE for negation else FALSE
- dptr points to an int that is set to the detailed property value
- errorcodeptr points to the error code variable
-
-Returns: type value from ucp_type_table, or -1 for an invalid type
-*/
-
-static int
-get_ucp(const uschar **ptrptr, BOOL *negptr, int *dptr, int *errorcodeptr)
-{
-int c, i, bot, top;
-const uschar *ptr = *ptrptr;
-char name[32];
-
-c = *(++ptr);
-if (c == 0) goto ERROR_RETURN;
-
-*negptr = FALSE;
-
-/* \P or \p can be followed by a name in {}, optionally preceded by ^ for
-negation. */
-
-if (c == '{')
- {
- if (ptr[1] == '^')
- {
- *negptr = TRUE;
- ptr++;
- }
- for (i = 0; i < (int)sizeof(name) - 1; i++)
- {
- c = *(++ptr);
- if (c == 0) goto ERROR_RETURN;
- if (c == '}') break;
- name[i] = c;
- }
- if (c !='}') goto ERROR_RETURN;
- name[i] = 0;
- }
-
-/* Otherwise there is just one following character */
-
-else
- {
- name[0] = c;
- name[1] = 0;
- }
-
-*ptrptr = ptr;
-
-/* Search for a recognized property name using binary chop */
-
-bot = 0;
-top = _pcre_utt_size;
-
-while (bot < top)
- {
- i = (bot + top) >> 1;
- c = strcmp(name, _pcre_utt_names + _pcre_utt[i].name_offset);
- if (c == 0)
- {
- *dptr = _pcre_utt[i].value;
- return _pcre_utt[i].type;
- }
- if (c > 0) bot = i + 1; else top = i;
- }
-
-*errorcodeptr = ERR47;
-*ptrptr = ptr;
-return -1;
-
-ERROR_RETURN:
-*errorcodeptr = ERR46;
-*ptrptr = ptr;
-return -1;
-}
-#endif
-
-
-
-
-/*************************************************
-* Check for counted repeat *
-*************************************************/
-
-/* This function is called when a '{' is encountered in a place where it might
-start a quantifier. It looks ahead to see if it really is a quantifier or not.
-It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd}
-where the ddds are digits.
-
-Arguments:
- p pointer to the first char after '{'
-
-Returns: TRUE or FALSE
-*/
-
-static BOOL
-is_counted_repeat(const uschar *p)
-{
-if (g_ascii_isdigit (*p++) == 0) return FALSE;
-while (g_ascii_isdigit (*p) != 0) p++;
-if (*p == '}') return TRUE;
-
-if (*p++ != ',') return FALSE;
-if (*p == '}') return TRUE;
-
-if (g_ascii_isdigit (*p++) == 0) return FALSE;
-while (g_ascii_isdigit (*p) != 0) p++;
-
-return (*p == '}');
-}
-
-
-
-/*************************************************
-* Read repeat counts *
-*************************************************/
-
-/* Read an item of the form {n,m} and return the values. This is called only
-after is_counted_repeat() has confirmed that a repeat-count quantifier exists,
-so the syntax is guaranteed to be correct, but we need to check the values.
-
-Arguments:
- p pointer to first char after '{'
- minp pointer to int for min
- maxp pointer to int for max
- returned as -1 if no max
- errorcodeptr points to error code variable
-
-Returns: pointer to '}' on success;
- current ptr on error, with errorcodeptr set non-zero
-*/
-
-static const uschar *
-read_repeat_counts(const uschar *p, int *minp, int *maxp, int *errorcodeptr)
-{
-int min = 0;
-int max = -1;
-
-/* Read the minimum value and do a paranoid check: a negative value indicates
-an integer overflow. */
-
-while (g_ascii_isdigit (*p) != 0) min = min * 10 + *p++ - '0';
-if (min < 0 || min > 65535)
- {
- *errorcodeptr = ERR5;
- return p;
- }
-
-/* Read the maximum value if there is one, and again do a paranoid on its size.
-Also, max must not be less than min. */
-
-if (*p == '}') max = min; else
- {
- if (*(++p) != '}')
- {
- max = 0;
- while(g_ascii_isdigit (*p) != 0) max = max * 10 + *p++ - '0';
- if (max < 0 || max > 65535)
- {
- *errorcodeptr = ERR5;
- return p;
- }
- if (max < min)
- {
- *errorcodeptr = ERR4;
- return p;
- }
- }
- }
-
-/* Fill in the required variables, and pass back the pointer to the terminating
-'}'. */
-
-*minp = min;
-*maxp = max;
-return p;
-}
-
-
-
-/*************************************************
-* Find forward referenced subpattern *
-*************************************************/
-
-/* This function scans along a pattern's text looking for capturing
-subpatterns, and counting them. If it finds a named pattern that matches the
-name it is given, it returns its number. Alternatively, if the name is NULL, it
-returns when it reaches a given numbered subpattern. This is used for forward
-references to subpatterns. We know that if (?P< is encountered, the name will
-be terminated by '>' because that is checked in the first pass.
-
-Arguments:
- ptr current position in the pattern
- cd compile background data
- name name to seek, or NULL if seeking a numbered subpattern
- lorn name length, or subpattern number if name is NULL
- xmode TRUE if we are in /x mode
-
-Returns: the number of the named subpattern, or -1 if not found
-*/
-
-static int
-find_parens(const uschar *ptr, compile_data *cd, const uschar *name, int lorn,
- BOOL xmode)
-{
-const uschar *thisname;
-int count = cd->bracount;
-
-for (; *ptr != 0; ptr++)
- {
- int term;
-
- /* Skip over backslashed characters and also entire \Q...\E */
-
- if (*ptr == '\\')
- {
- if (*(++ptr) == 0) return -1;
- if (*ptr == 'Q') for (;;)
- {
- while (*(++ptr) != 0 && *ptr != '\\') {};
- if (*ptr == 0) return -1;
- if (*(++ptr) == 'E') break;
- }
- continue;
- }
-
- /* Skip over character classes; this logic must be similar to the way they
- are handled for real. If the first character is '^', skip it. Also, if the
- first few characters (either before or after ^) are \Q\E or \E we skip them
- too. This makes for compatibility with Perl. */
-
- if (*ptr == '[')
- {
- BOOL negate_class = FALSE;
- for (;;)
- {
- int c = *(++ptr);
- if (c == '\\')
- {
- if (ptr[1] == 'E') ptr++;
- else if (strncmp((const char *)ptr+1, "Q\\E", 3) == 0) ptr += 3;
- else break;
- }
- else if (!negate_class && c == '^')
- negate_class = TRUE;
- else break;
- }
-
- /* If the next character is ']', it is a data character that must be
- skipped, except in JavaScript compatibility mode. */
-
- if (ptr[1] == ']' && (cd->external_options & PCRE_JAVASCRIPT_COMPAT) == 0)
- ptr++;
-
- while (*(++ptr) != ']')
- {
- if (*ptr == 0) return -1;
- if (*ptr == '\\')
- {
- if (*(++ptr) == 0) return -1;
- if (*ptr == 'Q') for (;;)
- {
- while (*(++ptr) != 0 && *ptr != '\\') {};
- if (*ptr == 0) return -1;
- if (*(++ptr) == 'E') break;
- }
- continue;
- }
- }
- continue;
- }
-
- /* Skip comments in /x mode */
-
- if (xmode && *ptr == '#')
- {
- while (*(++ptr) != 0 && *ptr != '\n') {};
- if (*ptr == 0) return -1;
- continue;
- }
-
- /* An opening parens must now be a real metacharacter */
-
- if (*ptr != '(') continue;
- if (ptr[1] != '?' && ptr[1] != '*')
- {
- count++;
- if (name == NULL && count == lorn) return count;
- continue;
- }
-
- ptr += 2;
- if (*ptr == 'P') ptr++; /* Allow optional P */
-
- /* We have to disambiguate (?<! and (?<= from (?<name> */
-
- if ((*ptr != '<' || ptr[1] == '!' || ptr[1] == '=') &&
- *ptr != '\'')
- continue;
-
- count++;
-
- if (name == NULL && count == lorn) return count;
- term = *ptr++;
- if (term == '<') term = '>';
- thisname = ptr;
- while (*ptr != term) ptr++;
- if (name != NULL && lorn == ptr - thisname &&
- strncmp((const char *)name, (const char *)thisname, lorn) == 0)
- return count;
- }
-
-return -1;
-}
-
-
-
-/*************************************************
-* Find first significant op code *
-*************************************************/
-
-/* This is called by several functions that scan a compiled expression looking
-for a fixed first character, or an anchoring op code etc. It skips over things
-that do not influence this. For some calls, a change of option is important.
-For some calls, it makes sense to skip negative forward and all backward
-assertions, and also the \b assertion; for others it does not.
-
-Arguments:
- code pointer to the start of the group
- options pointer to external options
- optbit the option bit whose changing is significant, or
- zero if none are
- skipassert TRUE if certain assertions are to be skipped
-
-Returns: pointer to the first significant opcode
-*/
-
-static const uschar*
-first_significant_code(const uschar *code, int *options, int optbit,
- BOOL skipassert)
-{
-for (;;)
- {
- switch ((int)*code)
- {
- case OP_OPT:
- if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit))
- *options = (int)code[1];
- code += 2;
- break;
-
- case OP_ASSERT_NOT:
- case OP_ASSERTBACK:
- case OP_ASSERTBACK_NOT:
- if (!skipassert) return code;
- do code += GET(code, 1); while (*code == OP_ALT);
- code += _pcre_OP_lengths[*code];
- break;
-
- case OP_WORD_BOUNDARY:
- case OP_NOT_WORD_BOUNDARY:
- if (!skipassert) return code;
- /* Fall through */
-
- case OP_CALLOUT:
- case OP_CREF:
- case OP_RREF:
- case OP_DEF:
- code += _pcre_OP_lengths[*code];
- break;
-
- default:
- return code;
- }
- }
-/* Control never reaches here */
-}
-
-
-
-
-/*************************************************
-* Find the fixed length of a pattern *
-*************************************************/
-
-/* Scan a pattern and compute the fixed length of subject that will match it,
-if the length is fixed. This is needed for dealing with backward assertions.
-In UTF8 mode, the result is in characters rather than bytes.
-
-Arguments:
- code points to the start of the pattern (the bracket)
- options the compiling options
-
-Returns: the fixed length, or -1 if there is no fixed length,
- or -2 if \C was encountered
-*/
-
-static int
-find_fixedlength(uschar *code, int options)
-{
-int length = -1;
-
-register int branchlength = 0;
-register uschar *cc = code + 1 + LINK_SIZE;
-
-/* Scan along the opcodes for this branch. If we get to the end of the
-branch, check the length against that of the other branches. */
-
-for (;;)
- {
- int d;
- register int op = *cc;
- switch (op)
- {
- case OP_CBRA:
- case OP_BRA:
- case OP_ONCE:
- case OP_COND:
- d = find_fixedlength(cc + ((op == OP_CBRA)? 2:0), options);
- if (d < 0) return d;
- branchlength += d;
- do cc += GET(cc, 1); while (*cc == OP_ALT);
- cc += 1 + LINK_SIZE;
- break;
-
- /* Reached end of a branch; if it's a ket it is the end of a nested
- call. If it's ALT it is an alternation in a nested call. If it is
- END it's the end of the outer call. All can be handled by the same code. */
-
- case OP_ALT:
- case OP_KET:
- case OP_KETRMAX:
- case OP_KETRMIN:
- case OP_END:
- if (length < 0) length = branchlength;
- else if (length != branchlength) return -1;
- if (*cc != OP_ALT) return length;
- cc += 1 + LINK_SIZE;
- branchlength = 0;
- break;
-
- /* Skip over assertive subpatterns */
-
- case OP_ASSERT:
- case OP_ASSERT_NOT:
- case OP_ASSERTBACK:
- case OP_ASSERTBACK_NOT:
- do cc += GET(cc, 1); while (*cc == OP_ALT);
- /* Fall through */
-
- /* Skip over things that don't match chars */
-
- case OP_REVERSE:
- case OP_CREF:
- case OP_RREF:
- case OP_DEF:
- case OP_OPT:
- case OP_CALLOUT:
- case OP_SOD:
- case OP_SOM:
- case OP_EOD:
- case OP_EODN:
- case OP_CIRC:
- case OP_DOLL:
- case OP_NOT_WORD_BOUNDARY:
- case OP_WORD_BOUNDARY:
- cc += _pcre_OP_lengths[*cc];
- break;
-
- /* Handle literal characters */
-
- case OP_CHAR:
- case OP_CHARNC:
- case OP_NOT:
- branchlength++;
- cc += 2;
-#ifdef SUPPORT_UTF8
- if ((options & PCRE_UTF8) != 0)
- {
- while ((*cc & 0xc0) == 0x80) cc++;
- }
-#endif
- break;
-
- /* Handle exact repetitions. The count is already in characters, but we
- need to skip over a multibyte character in UTF8 mode. */
-
- case OP_EXACT:
- branchlength += GET2(cc,1);
- cc += 4;
-#ifdef SUPPORT_UTF8
- if ((options & PCRE_UTF8) != 0)
- {
- while((*cc & 0x80) == 0x80) cc++;
- }
-#endif
- break;
-
- case OP_TYPEEXACT:
- branchlength += GET2(cc,1);
- if (cc[3] == OP_PROP || cc[3] == OP_NOTPROP) cc += 2;
- cc += 4;
- break;
-
- /* Handle single-char matchers */
-
- case OP_PROP:
- case OP_NOTPROP:
- cc += 2;
- /* Fall through */
-
- case OP_NOT_DIGIT:
- case OP_DIGIT:
- case OP_NOT_WHITESPACE:
- case OP_WHITESPACE:
- case OP_NOT_WORDCHAR:
- case OP_WORDCHAR:
- case OP_ANY:
- case OP_ALLANY:
- branchlength++;
- cc++;
- break;
-
- /* The single-byte matcher isn't allowed */
-
- case OP_ANYBYTE:
- return -2;
-
- /* Check a class for variable quantification */
-
-#ifdef SUPPORT_UTF8
- case OP_XCLASS:
- cc += GET(cc, 1) - 33;
- /* Fall through */
-#endif
-
- case OP_CLASS:
- case OP_NCLASS:
- cc += 33;
-
- switch (*cc)
- {
- case OP_CRSTAR:
- case OP_CRMINSTAR:
- case OP_CRQUERY:
- case OP_CRMINQUERY:
- return -1;
-
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- if (GET2(cc,1) != GET2(cc,3)) return -1;
- branchlength += GET2(cc,1);
- cc += 5;
- break;
-
- default:
- branchlength++;
- }
- break;
-
- /* Anything else is variable length */
-
- default:
- return -1;
- }
- }
-/* Control never gets here */
-}
-
-
-
-
-/*************************************************
-* Scan compiled regex for numbered bracket *
-*************************************************/
-
-/* This little function scans through a compiled pattern until it finds a
-capturing bracket with the given number.
-
-Arguments:
- code points to start of expression
- utf8 TRUE in UTF-8 mode
- number the required bracket number
-
-Returns: pointer to the opcode for the bracket, or NULL if not found
-*/
-
-static const uschar *
-find_bracket(const uschar *code, BOOL utf8, int number)
-{
-for (;;)
- {
- register int c = *code;
- if (c == OP_END) return NULL;
-
- /* XCLASS is used for classes that cannot be represented just by a bit
- map. This includes negated single high-valued characters. The length in
- the table is zero; the actual length is stored in the compiled code. */
-
- if (c == OP_XCLASS) code += GET(code, 1);
-
- /* Handle capturing bracket */
-
- else if (c == OP_CBRA)
- {
- int n = GET2(code, 1+LINK_SIZE);
- if (n == number) return (uschar *)code;
- code += _pcre_OP_lengths[c];
- }
-
- /* Otherwise, we can get the item's length from the table, except that for
- repeated character types, we have to test for \p and \P, which have an extra
- two bytes of parameters. */
-
- else
- {
- switch(c)
- {
- case OP_TYPESTAR:
- case OP_TYPEMINSTAR:
- case OP_TYPEPLUS:
- case OP_TYPEMINPLUS:
- case OP_TYPEQUERY:
- case OP_TYPEMINQUERY:
- case OP_TYPEPOSSTAR:
- case OP_TYPEPOSPLUS:
- case OP_TYPEPOSQUERY:
- if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
- break;
-
- case OP_TYPEUPTO:
- case OP_TYPEMINUPTO:
- case OP_TYPEEXACT:
- case OP_TYPEPOSUPTO:
- if (code[3] == OP_PROP || code[3] == OP_NOTPROP) code += 2;
- break;
- }
-
- /* Add in the fixed length from the table */
-
- code += _pcre_OP_lengths[c];
-
- /* In UTF-8 mode, opcodes that are followed by a character may be followed by
- a multi-byte character. The length in the table is a minimum, so we have to
- arrange to skip the extra bytes. */
-
-#ifdef SUPPORT_UTF8
- if (utf8) switch(c)
- {
- case OP_CHAR:
- case OP_CHARNC:
- case OP_EXACT:
- case OP_UPTO:
- case OP_MINUPTO:
- case OP_POSUPTO:
- case OP_STAR:
- case OP_MINSTAR:
- case OP_POSSTAR:
- case OP_PLUS:
- case OP_MINPLUS:
- case OP_POSPLUS:
- case OP_QUERY:
- case OP_MINQUERY:
- case OP_POSQUERY:
- if (code[-1] >= 0xc0) code += _pcre_utf8_table4[code[-1] & 0x3f];
- break;
- }
-#else
- (void)(utf8); /* Keep compiler happy by referencing function argument */
-#endif
- }
- }
-}
-
-
-
-/*************************************************
-* Scan compiled regex for recursion reference *
-*************************************************/
-
-/* This little function scans through a compiled pattern until it finds an
-instance of OP_RECURSE.
-
-Arguments:
- code points to start of expression
- utf8 TRUE in UTF-8 mode
-
-Returns: pointer to the opcode for OP_RECURSE, or NULL if not found
-*/
-
-static const uschar *
-find_recurse(const uschar *code, BOOL utf8)
-{
-for (;;)
- {
- register int c = *code;
- if (c == OP_END) return NULL;
- if (c == OP_RECURSE) return code;
-
- /* XCLASS is used for classes that cannot be represented just by a bit
- map. This includes negated single high-valued characters. The length in
- the table is zero; the actual length is stored in the compiled code. */
-
- if (c == OP_XCLASS) code += GET(code, 1);
-
- /* Otherwise, we can get the item's length from the table, except that for
- repeated character types, we have to test for \p and \P, which have an extra
- two bytes of parameters. */
-
- else
- {
- switch(c)
- {
- case OP_TYPESTAR:
- case OP_TYPEMINSTAR:
- case OP_TYPEPLUS:
- case OP_TYPEMINPLUS:
- case OP_TYPEQUERY:
- case OP_TYPEMINQUERY:
- case OP_TYPEPOSSTAR:
- case OP_TYPEPOSPLUS:
- case OP_TYPEPOSQUERY:
- if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
- break;
-
- case OP_TYPEPOSUPTO:
- case OP_TYPEUPTO:
- case OP_TYPEMINUPTO:
- case OP_TYPEEXACT:
- if (code[3] == OP_PROP || code[3] == OP_NOTPROP) code += 2;
- break;
- }
-
- /* Add in the fixed length from the table */
-
- code += _pcre_OP_lengths[c];
-
- /* In UTF-8 mode, opcodes that are followed by a character may be followed
- by a multi-byte character. The length in the table is a minimum, so we have
- to arrange to skip the extra bytes. */
-
-#ifdef SUPPORT_UTF8
- if (utf8) switch(c)
- {
- case OP_CHAR:
- case OP_CHARNC:
- case OP_EXACT:
- case OP_UPTO:
- case OP_MINUPTO:
- case OP_POSUPTO:
- case OP_STAR:
- case OP_MINSTAR:
- case OP_POSSTAR:
- case OP_PLUS:
- case OP_MINPLUS:
- case OP_POSPLUS:
- case OP_QUERY:
- case OP_MINQUERY:
- case OP_POSQUERY:
- if (code[-1] >= 0xc0) code += _pcre_utf8_table4[code[-1] & 0x3f];
- break;
- }
-#else
- (void)(utf8); /* Keep compiler happy by referencing function argument */
-#endif
- }
- }
-}
-
-
-
-/*************************************************
-* Scan compiled branch for non-emptiness *
-*************************************************/
-
-/* This function scans through a branch of a compiled pattern to see whether it
-can match the empty string or not. It is called from could_be_empty()
-below and from compile_branch() when checking for an unlimited repeat of a
-group that can match nothing. Note that first_significant_code() skips over
-backward and negative forward assertions when its final argument is TRUE. If we
-hit an unclosed bracket, we return "empty" - this means we've struck an inner
-bracket whose current branch will already have been scanned.
-
-Arguments:
- code points to start of search
- endcode points to where to stop
- utf8 TRUE if in UTF8 mode
-
-Returns: TRUE if what is matched could be empty
-*/
-
-static BOOL
-could_be_empty_branch(const uschar *code, const uschar *endcode, BOOL utf8)
-{
-register int c;
-for (code = first_significant_code(code + _pcre_OP_lengths[*code], NULL, 0, TRUE);
- code < endcode;
- code = first_significant_code(code + _pcre_OP_lengths[c], NULL, 0, TRUE))
- {
- const uschar *ccode;
-
- c = *code;
-
- /* Skip over forward assertions; the other assertions are skipped by
- first_significant_code() with a TRUE final argument. */
-
- if (c == OP_ASSERT)
- {
- do code += GET(code, 1); while (*code == OP_ALT);
- c = *code;
- continue;
- }
-
- /* Groups with zero repeats can of course be empty; skip them. */
-
- if (c == OP_BRAZERO || c == OP_BRAMINZERO || c == OP_SKIPZERO)
- {
- code += _pcre_OP_lengths[c];
- do code += GET(code, 1); while (*code == OP_ALT);
- c = *code;
- continue;
- }
-
- /* For other groups, scan the branches. */
-
- if (c == OP_BRA || c == OP_CBRA || c == OP_ONCE || c == OP_COND)
- {
- BOOL empty_branch;
- if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */
-
- /* Scan a closed bracket */
-
- empty_branch = FALSE;
- do
- {
- if (!empty_branch && could_be_empty_branch(code, endcode, utf8))
- empty_branch = TRUE;
- code += GET(code, 1);
- }
- while (*code == OP_ALT);
- if (!empty_branch) return FALSE; /* All branches are non-empty */
- c = *code;
- continue;
- }
-
- /* Handle the other opcodes */
-
- switch (c)
- {
- /* Check for quantifiers after a class. XCLASS is used for classes that
- cannot be represented just by a bit map. This includes negated single
- high-valued characters. The length in _pcre_OP_lengths[] is zero; the
- actual length is stored in the compiled code, so we must update "code"
- here. */
-
-#ifdef SUPPORT_UTF8
- case OP_XCLASS:
- ccode = code += GET(code, 1);
- goto CHECK_CLASS_REPEAT;
-#endif
-
- case OP_CLASS:
- case OP_NCLASS:
- ccode = code + 33;
-
-#ifdef SUPPORT_UTF8
- CHECK_CLASS_REPEAT:
-#endif
-
- switch (*ccode)
- {
- case OP_CRSTAR: /* These could be empty; continue */
- case OP_CRMINSTAR:
- case OP_CRQUERY:
- case OP_CRMINQUERY:
- break;
-
- default: /* Non-repeat => class must match */
- case OP_CRPLUS: /* These repeats aren't empty */
- case OP_CRMINPLUS:
- return FALSE;
-
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- if (GET2(ccode, 1) > 0) return FALSE; /* Minimum > 0 */
- break;
- }
- break;
-
- /* Opcodes that must match a character */
-
- case OP_PROP:
- case OP_NOTPROP:
- case OP_EXTUNI:
- case OP_NOT_DIGIT:
- case OP_DIGIT:
- case OP_NOT_WHITESPACE:
- case OP_WHITESPACE:
- case OP_NOT_WORDCHAR:
- case OP_WORDCHAR:
- case OP_ANY:
- case OP_ALLANY:
- case OP_ANYBYTE:
- case OP_CHAR:
- case OP_CHARNC:
- case OP_NOT:
- case OP_PLUS:
- case OP_MINPLUS:
- case OP_POSPLUS:
- case OP_EXACT:
- case OP_NOTPLUS:
- case OP_NOTMINPLUS:
- case OP_NOTPOSPLUS:
- case OP_NOTEXACT:
- case OP_TYPEPLUS:
- case OP_TYPEMINPLUS:
- case OP_TYPEPOSPLUS:
- case OP_TYPEEXACT:
- return FALSE;
-
- /* These are going to continue, as they may be empty, but we have to
- fudge the length for the \p and \P cases. */
-
- case OP_TYPESTAR:
- case OP_TYPEMINSTAR:
- case OP_TYPEPOSSTAR:
- case OP_TYPEQUERY:
- case OP_TYPEMINQUERY:
- case OP_TYPEPOSQUERY:
- if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
- break;
-
- /* Same for these */
-
- case OP_TYPEUPTO:
- case OP_TYPEMINUPTO:
- case OP_TYPEPOSUPTO:
- if (code[3] == OP_PROP || code[3] == OP_NOTPROP) code += 2;
- break;
-
- /* End of branch */
-
- case OP_KET:
- case OP_KETRMAX:
- case OP_KETRMIN:
- case OP_ALT:
- return TRUE;
-
- /* In UTF-8 mode, STAR, MINSTAR, POSSTAR, QUERY, MINQUERY, POSQUERY, UPTO,
- MINUPTO, and POSUPTO may be followed by a multibyte character */
-
-#ifdef SUPPORT_UTF8
- case OP_STAR:
- case OP_MINSTAR:
- case OP_POSSTAR:
- case OP_QUERY:
- case OP_MINQUERY:
- case OP_POSQUERY:
- case OP_UPTO:
- case OP_MINUPTO:
- case OP_POSUPTO:
- if (utf8) while ((code[2] & 0xc0) == 0x80) code++;
- break;
-#endif
- }
- }
-
-return TRUE;
-}
-
-
-
-/*************************************************
-* Scan compiled regex for non-emptiness *
-*************************************************/
-
-/* This function is called to check for left recursive calls. We want to check
-the current branch of the current pattern to see if it could match the empty
-string. If it could, we must look outwards for branches at other levels,
-stopping when we pass beyond the bracket which is the subject of the recursion.
-
-Arguments:
- code points to start of the recursion
- endcode points to where to stop (current RECURSE item)
- bcptr points to the chain of current (unclosed) branch starts
- utf8 TRUE if in UTF-8 mode
-
-Returns: TRUE if what is matched could be empty
-*/
-
-static BOOL
-could_be_empty(const uschar *code, const uschar *endcode, branch_chain *bcptr,
- BOOL utf8)
-{
-while (bcptr != NULL && bcptr->current >= code)
- {
- if (!could_be_empty_branch(bcptr->current, endcode, utf8)) return FALSE;
- bcptr = bcptr->outer;
- }
-return TRUE;
-}
-
-
-
-/*************************************************
-* Check for POSIX class syntax *
-*************************************************/
-
-/* This function is called when the sequence "[:" or "[." or "[=" is
-encountered in a character class. It checks whether this is followed by a
-sequence of characters terminated by a matching ":]" or ".]" or "=]". If we
-reach an unescaped ']' without the special preceding character, return FALSE.
-
-Originally, this function only recognized a sequence of letters between the
-terminators, but it seems that Perl recognizes any sequence of characters,
-though of course unknown POSIX names are subsequently rejected. Perl gives an
-"Unknown POSIX class" error for [:f\oo:] for example, where previously PCRE
-didn't consider this to be a POSIX class. Likewise for [:1234:].
-
-The problem in trying to be exactly like Perl is in the handling of escapes. We
-have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX
-class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code
-below handles the special case of \], but does not try to do any other escape
-processing. This makes it different from Perl for cases such as [:l\ower:]
-where Perl recognizes it as the POSIX class "lower" but PCRE does not recognize
-"l\ower". This is a lesser evil that not diagnosing bad classes when Perl does,
-I think.
-
-Arguments:
- ptr pointer to the initial [
- endptr where to return the end pointer
-
-Returns: TRUE or FALSE
-*/
-
-static BOOL
-check_posix_syntax(const uschar *ptr, const uschar **endptr)
-{
-int terminator; /* Don't combine these lines; the Solaris cc */
-terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */
-for (++ptr; *ptr != 0; ptr++)
- {
- if (*ptr == '\\' && ptr[1] == ']') ptr++; else
- {
- if (*ptr == ']') return FALSE;
- if (*ptr == terminator && ptr[1] == ']')
- {
- *endptr = ptr;
- return TRUE;
- }
- }
- }
-return FALSE;
-}
-
-
-
-
-/*************************************************
-* Check POSIX class name *
-*************************************************/
-
-/* This function is called to check the name given in a POSIX-style class entry
-such as [:alnum:].
-
-Arguments:
- ptr points to the first letter
- len the length of the name
-
-Returns: a value representing the name, or -1 if unknown
-*/
-
-static int
-check_posix_name(const uschar *ptr, int len)
-{
-const char *pn = posix_names;
-register int yield = 0;
-while (posix_name_lengths[yield] != 0)
- {
- if (len == posix_name_lengths[yield] &&
- strncmp((const char *)ptr, pn, len) == 0) return yield;
- pn += posix_name_lengths[yield] + 1;
- yield++;
- }
-return -1;
-}
-
-
-/*************************************************
-* Adjust OP_RECURSE items in repeated group *
-*************************************************/
-
-/* OP_RECURSE items contain an offset from the start of the regex to the group
-that is referenced. This means that groups can be replicated for fixed
-repetition simply by copying (because the recursion is allowed to refer to
-earlier groups that are outside the current group). However, when a group is
-optional (i.e. the minimum quantifier is zero), OP_BRAZERO or OP_SKIPZERO is
-inserted before it, after it has been compiled. This means that any OP_RECURSE
-items within it that refer to the group itself or any contained groups have to
-have their offsets adjusted. That one of the jobs of this function. Before it
-is called, the partially compiled regex must be temporarily terminated with
-OP_END.
-
-This function has been extended with the possibility of forward references for
-recursions and subroutine calls. It must also check the list of such references
-for the group we are dealing with. If it finds that one of the recursions in
-the current group is on this list, it adjusts the offset in the list, not the
-value in the reference (which is a group number).
-
-Arguments:
- group points to the start of the group
- adjust the amount by which the group is to be moved
- utf8 TRUE in UTF-8 mode
- cd contains pointers to tables etc.
- save_hwm the hwm forward reference pointer at the start of the group
-
-Returns: nothing
-*/
-
-static void
-adjust_recurse(uschar *group, int adjust, BOOL utf8, compile_data *cd,
- uschar *save_hwm)
-{
-uschar *ptr = group;
-
-while ((ptr = (uschar *)find_recurse(ptr, utf8)) != NULL)
- {
- int offset;
- uschar *hc;
-
- /* See if this recursion is on the forward reference list. If so, adjust the
- reference. */
-
- for (hc = save_hwm; hc < cd->hwm; hc += LINK_SIZE)
- {
- offset = GET(hc, 0);
- if (cd->start_code + offset == ptr + 1)
- {
- PUT(hc, 0, offset + adjust);
- break;
- }
- }
-
- /* Otherwise, adjust the recursion offset if it's after the start of this
- group. */
-
- if (hc >= cd->hwm)
- {
- offset = GET(ptr, 1);
- if (cd->start_code + offset >= group) PUT(ptr, 1, offset + adjust);
- }
-
- ptr += 1 + LINK_SIZE;
- }
-}
-
-
-
-/*************************************************
-* Insert an automatic callout point *
-*************************************************/
-
-/* This function is called when the PCRE_AUTO_CALLOUT option is set, to insert
-callout points before each pattern item.
-
-Arguments:
- code current code pointer
- ptr current pattern pointer
- cd pointers to tables etc
-
-Returns: new code pointer
-*/
-
-static uschar *
-auto_callout(uschar *code, const uschar *ptr, compile_data *cd)
-{
-*code++ = OP_CALLOUT;
-*code++ = 255;
-PUT(code, 0, ptr - cd->start_pattern); /* Pattern offset */
-PUT(code, LINK_SIZE, 0); /* Default length */
-return code + 2*LINK_SIZE;
-}
-
-
-
-/*************************************************
-* Complete a callout item *
-*************************************************/
-
-/* A callout item contains the length of the next item in the pattern, which
-we can't fill in till after we have reached the relevant point. This is used
-for both automatic and manual callouts.
-
-Arguments:
- previous_callout points to previous callout item
- ptr current pattern pointer
- cd pointers to tables etc
-
-Returns: nothing
-*/
-
-static void
-complete_callout(uschar *previous_callout, const uschar *ptr, compile_data *cd)
-{
-int length = ptr - cd->start_pattern - GET(previous_callout, 2);
-PUT(previous_callout, 2 + LINK_SIZE, length);
-}
-
-
-
-#ifdef SUPPORT_UCP
-/*************************************************
-* Get othercase range *
-*************************************************/
-
-/* This function is passed the start and end of a class range, in UTF-8 mode
-with UCP support. It searches up the characters, looking for internal ranges of
-characters in the "other" case. Each call returns the next one, updating the
-start address.
-
-Arguments:
- cptr points to starting character value; updated
- d end value
- ocptr where to put start of othercase range
- odptr where to put end of othercase range
-
-Yield: TRUE when range returned; FALSE when no more
-*/
-
-static BOOL
-get_othercase_range(unsigned int *cptr, unsigned int d, unsigned int *ocptr,
- unsigned int *odptr)
-{
-unsigned int c, othercase, next;
-
-for (c = *cptr; c <= d; c++)
- { if ((othercase = UCD_OTHERCASE(c)) != c) break; }
-
-if (c > d) return FALSE;
-
-*ocptr = othercase;
-next = othercase + 1;
-
-for (++c; c <= d; c++)
- {
- if (UCD_OTHERCASE(c) != next) break;
- next++;
- }
-
-*odptr = next - 1;
-*cptr = c;
-
-return TRUE;
-}
-#endif /* SUPPORT_UCP */
-
-
-
-/*************************************************
-* Check if auto-possessifying is possible *
-*************************************************/
-
-/* This function is called for unlimited repeats of certain items, to see
-whether the next thing could possibly match the repeated item. If not, it makes
-sense to automatically possessify the repeated item.
-
-Arguments:
- op_code the repeated op code
- this data for this item, depends on the opcode
- utf8 TRUE in UTF-8 mode
- utf8_char used for utf8 character bytes, NULL if not relevant
- ptr next character in pattern
- options options bits
- cd contains pointers to tables etc.
-
-Returns: TRUE if possessifying is wanted
-*/
-
-static BOOL
-check_auto_possessive(int op_code, int item, BOOL utf8, uschar *utf8_char,
- const uschar *ptr, int options, compile_data *cd)
-{
-int next;
-
-/* Skip whitespace and comments in extended mode */
-
-if ((options & PCRE_EXTENDED) != 0)
- {
- for (;;)
- {
- while ((cd->ctypes[*ptr] & ctype_space) != 0) ptr++;
- if (*ptr == '#')
- {
- while (*(++ptr) != 0)
- if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; }
- }
- else break;
- }
- }
-
-/* If the next item is one that we can handle, get its value. A non-negative
-value is a character, a negative value is an escape value. */
-
-if (*ptr == '\\')
- {
- int temperrorcode = 0;
- next = check_escape(&ptr, &temperrorcode, cd->bracount, options, FALSE);
- if (temperrorcode != 0) return FALSE;
- ptr++; /* Point after the escape sequence */
- }
-
-else if ((cd->ctypes[*ptr] & ctype_meta) == 0)
- {
-#ifdef SUPPORT_UTF8
- if (utf8) { GETCHARINC(next, ptr); } else
-#endif
- next = *ptr++;
- }
-
-else return FALSE;
-
-/* Skip whitespace and comments in extended mode */
-
-if ((options & PCRE_EXTENDED) != 0)
- {
- for (;;)
- {
- while ((cd->ctypes[*ptr] & ctype_space) != 0) ptr++;
- if (*ptr == '#')
- {
- while (*(++ptr) != 0)
- if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; }
- }
- else break;
- }
- }
-
-/* If the next thing is itself optional, we have to give up. */
-
-if (*ptr == '*' || *ptr == '?' || strncmp((char *)ptr, "{0,", 3) == 0)
- return FALSE;
-
-/* Now compare the next item with the previous opcode. If the previous is a
-positive single character match, "item" either contains the character or, if
-"item" is greater than 127 in utf8 mode, the character's bytes are in
-utf8_char. */
-
-
-/* Handle cases when the next item is a character. */
-
-if (next >= 0) switch(op_code)
- {
- case OP_CHAR:
-#ifdef SUPPORT_UTF8
- if (utf8 && item > 127) { GETCHAR(item, utf8_char); }
-#else
- (void)(utf8_char); /* Keep compiler happy by referencing function argument */
-#endif
- return item != next;
-
- /* For CHARNC (caseless character) we must check the other case. If we have
- Unicode property support, we can use it to test the other case of
- high-valued characters. */
-
- case OP_CHARNC:
-#ifdef SUPPORT_UTF8
- if (utf8 && item > 127) { GETCHAR(item, utf8_char); }
-#endif
- if (item == next) return FALSE;
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- unsigned int othercase;
- if (next < 128) othercase = cd->fcc[next]; else
-#ifdef SUPPORT_UCP
- othercase = UCD_OTHERCASE((unsigned int)next);
-#else
- othercase = NOTACHAR;
-#endif
- return (unsigned int)item != othercase;
- }
- else
-#endif /* SUPPORT_UTF8 */
- return (item != cd->fcc[next]); /* Non-UTF-8 mode */
-
- /* For OP_NOT, "item" must be a single-byte character. */
-
- case OP_NOT:
- if (item == next) return TRUE;
- if ((options & PCRE_CASELESS) == 0) return FALSE;
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- unsigned int othercase;
- if (next < 128) othercase = cd->fcc[next]; else
-#ifdef SUPPORT_UCP
- othercase = UCD_OTHERCASE(next);
-#else
- othercase = NOTACHAR;
-#endif
- return (unsigned int)item == othercase;
- }
- else
-#endif /* SUPPORT_UTF8 */
- return (item == cd->fcc[next]); /* Non-UTF-8 mode */
-
- case OP_DIGIT:
- return next > 127 || (cd->ctypes[next] & ctype_digit) == 0;
-
- case OP_NOT_DIGIT:
- return next <= 127 && (cd->ctypes[next] & ctype_digit) != 0;
-
- case OP_WHITESPACE:
- return next > 127 || (cd->ctypes[next] & ctype_space) == 0;
-
- case OP_NOT_WHITESPACE:
- return next <= 127 && (cd->ctypes[next] & ctype_space) != 0;
-
- case OP_WORDCHAR:
- return next > 127 || (cd->ctypes[next] & ctype_word) == 0;
-
- case OP_NOT_WORDCHAR:
- return next <= 127 && (cd->ctypes[next] & ctype_word) != 0;
-
- case OP_HSPACE:
- case OP_NOT_HSPACE:
- switch(next)
- {
- case 0x09:
- case 0x20:
- case 0xa0:
- case 0x1680:
- case 0x180e:
- case 0x2000:
- case 0x2001:
- case 0x2002:
- case 0x2003:
- case 0x2004:
- case 0x2005:
- case 0x2006:
- case 0x2007:
- case 0x2008:
- case 0x2009:
- case 0x200A:
- case 0x202f:
- case 0x205f:
- case 0x3000:
- return op_code != OP_HSPACE;
- default:
- return op_code == OP_HSPACE;
- }
-
- case OP_VSPACE:
- case OP_NOT_VSPACE:
- switch(next)
- {
- case 0x0a:
- case 0x0b:
- case 0x0c:
- case 0x0d:
- case 0x85:
- case 0x2028:
- case 0x2029:
- return op_code != OP_VSPACE;
- default:
- return op_code == OP_VSPACE;
- }
-
- default:
- return FALSE;
- }
-
-
-/* Handle the case when the next item is \d, \s, etc. */
-
-switch(op_code)
- {
- case OP_CHAR:
- case OP_CHARNC:
-#ifdef SUPPORT_UTF8
- if (utf8 && item > 127) { GETCHAR(item, utf8_char); }
-#endif
- switch(-next)
- {
- case ESC_d:
- return item > 127 || (cd->ctypes[item] & ctype_digit) == 0;
-
- case ESC_D:
- return item <= 127 && (cd->ctypes[item] & ctype_digit) != 0;
-
- case ESC_s:
- return item > 127 || (cd->ctypes[item] & ctype_space) == 0;
-
- case ESC_S:
- return item <= 127 && (cd->ctypes[item] & ctype_space) != 0;
-
- case ESC_w:
- return item > 127 || (cd->ctypes[item] & ctype_word) == 0;
-
- case ESC_W:
- return item <= 127 && (cd->ctypes[item] & ctype_word) != 0;
-
- case ESC_h:
- case ESC_H:
- switch(item)
- {
- case 0x09:
- case 0x20:
- case 0xa0:
- case 0x1680:
- case 0x180e:
- case 0x2000:
- case 0x2001:
- case 0x2002:
- case 0x2003:
- case 0x2004:
- case 0x2005:
- case 0x2006:
- case 0x2007:
- case 0x2008:
- case 0x2009:
- case 0x200A:
- case 0x202f:
- case 0x205f:
- case 0x3000:
- return -next != ESC_h;
- default:
- return -next == ESC_h;
- }
-
- case ESC_v:
- case ESC_V:
- switch(item)
- {
- case 0x0a:
- case 0x0b:
- case 0x0c:
- case 0x0d:
- case 0x85:
- case 0x2028:
- case 0x2029:
- return -next != ESC_v;
- default:
- return -next == ESC_v;
- }
-
- default:
- return FALSE;
- }
-
- case OP_DIGIT:
- return next == -ESC_D || next == -ESC_s || next == -ESC_W ||
- next == -ESC_h || next == -ESC_v;
-
- case OP_NOT_DIGIT:
- return next == -ESC_d;
-
- case OP_WHITESPACE:
- return next == -ESC_S || next == -ESC_d || next == -ESC_w;
-
- case OP_NOT_WHITESPACE:
- return next == -ESC_s || next == -ESC_h || next == -ESC_v;
-
- case OP_HSPACE:
- return next == -ESC_S || next == -ESC_H || next == -ESC_d || next == -ESC_w;
-
- case OP_NOT_HSPACE:
- return next == -ESC_h;
-
- /* Can't have \S in here because VT matches \S (Perl anomaly) */
- case OP_VSPACE:
- return next == -ESC_V || next == -ESC_d || next == -ESC_w;
-
- case OP_NOT_VSPACE:
- return next == -ESC_v;
-
- case OP_WORDCHAR:
- return next == -ESC_W || next == -ESC_s || next == -ESC_h || next == -ESC_v;
-
- case OP_NOT_WORDCHAR:
- return next == -ESC_w || next == -ESC_d;
-
- default:
- return FALSE;
- }
-
-/* Control does not reach here */
-}
-
-
-
-/*************************************************
-* Compile one branch *
-*************************************************/
-
-/* Scan the pattern, compiling it into the a vector. If the options are
-changed during the branch, the pointer is used to change the external options
-bits. This function is used during the pre-compile phase when we are trying
-to find out the amount of memory needed, as well as during the real compile
-phase. The value of lengthptr distinguishes the two phases.
-
-Arguments:
- optionsptr pointer to the option bits
- codeptr points to the pointer to the current code point
- ptrptr points to the current pattern pointer
- errorcodeptr points to error code variable
- firstbyteptr set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE)
- reqbyteptr set to the last literal character required, else < 0
- bcptr points to current branch chain
- cd contains pointers to tables etc.
- lengthptr NULL during the real compile phase
- points to length accumulator during pre-compile phase
-
-Returns: TRUE on success
- FALSE, with *errorcodeptr set non-zero on error
-*/
-
-static BOOL
-compile_branch(int *optionsptr, uschar **codeptr, const uschar **ptrptr,
- int *errorcodeptr, int *firstbyteptr, int *reqbyteptr, branch_chain *bcptr,
- compile_data *cd, int *lengthptr)
-{
-int repeat_type, op_type;
-int repeat_min = 0, repeat_max = 0; /* To please picky compilers */
-int bravalue = 0;
-int greedy_default, greedy_non_default;
-int firstbyte, reqbyte;
-int zeroreqbyte, zerofirstbyte;
-int req_caseopt, reqvary, tempreqvary;
-int options = *optionsptr;
-int after_manual_callout = 0;
-int length_prevgroup = 0;
-register int c;
-register uschar *code = *codeptr;
-uschar *last_code = code;
-uschar *orig_code = code;
-uschar *tempcode;
-BOOL inescq = FALSE;
-BOOL groupsetfirstbyte = FALSE;
-const uschar *ptr = *ptrptr;
-const uschar *tempptr;
-uschar *previous = NULL;
-uschar *previous_callout = NULL;
-uschar *save_hwm = NULL;
-uschar classbits[32];
-
-#ifdef SUPPORT_UTF8
-BOOL class_utf8;
-BOOL utf8 = (options & PCRE_UTF8) != 0;
-uschar *class_utf8data;
-uschar *class_utf8data_base;
-uschar utf8_char[6];
-#else
-BOOL utf8 = FALSE;
-uschar *utf8_char = NULL;
-#endif
-
-#ifdef DEBUG
-if (lengthptr != NULL) DPRINTF((">> start branch\n"));
-#endif
-
-/* Set up the default and non-default settings for greediness */
-
-greedy_default = ((options & PCRE_UNGREEDY) != 0);
-greedy_non_default = greedy_default ^ 1;
-
-/* Initialize no first byte, no required byte. REQ_UNSET means "no char
-matching encountered yet". It gets changed to REQ_NONE if we hit something that
-matches a non-fixed char first char; reqbyte just remains unset if we never
-find one.
-
-When we hit a repeat whose minimum is zero, we may have to adjust these values
-to take the zero repeat into account. This is implemented by setting them to
-zerofirstbyte and zeroreqbyte when such a repeat is encountered. The individual
-item types that can be repeated set these backoff variables appropriately. */
-
-firstbyte = reqbyte = zerofirstbyte = zeroreqbyte = REQ_UNSET;
-
-/* The variable req_caseopt contains either the REQ_CASELESS value or zero,
-according to the current setting of the caseless flag. REQ_CASELESS is a bit
-value > 255. It is added into the firstbyte or reqbyte variables to record the
-case status of the value. This is used only for ASCII characters. */
-
-req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS : 0;
-
-/* Switch on next character until the end of the branch */
-
-for (;; ptr++)
- {
- BOOL negate_class;
- BOOL should_flip_negation;
- BOOL possessive_quantifier;
- BOOL is_quantifier;
- BOOL is_recurse;
- BOOL reset_bracount;
- int class_charcount;
- int class_lastchar;
- int newoptions;
- int recno;
- int refsign;
- int skipbytes;
- int subreqbyte;
- int subfirstbyte;
- int terminator;
- int mclength;
- uschar mcbuffer[8];
-
- /* Get next byte in the pattern */
-
- c = *ptr;
-
- /* If we are in the pre-compile phase, accumulate the length used for the
- previous cycle of this loop. */
-
- if (lengthptr != NULL)
- {
-#ifdef DEBUG
- if (code > cd->hwm) cd->hwm = code; /* High water info */
-#endif
- if (code > cd->start_workspace + COMPILE_WORK_SIZE) /* Check for overrun */
- {
- *errorcodeptr = ERR52;
- goto FAILED;
- }
-
- /* There is at least one situation where code goes backwards: this is the
- case of a zero quantifier after a class (e.g. [ab]{0}). At compile time,
- the class is simply eliminated. However, it is created first, so we have to
- allow memory for it. Therefore, don't ever reduce the length at this point.
- */
-
- if (code < last_code) code = last_code;
-
- /* Paranoid check for integer overflow */
-
- if (OFLOW_MAX - *lengthptr < code - last_code)
- {
- *errorcodeptr = ERR20;
- goto FAILED;
- }
-
- *lengthptr += code - last_code;
- DPRINTF(("length=%d added %d c=%c\n", *lengthptr, code - last_code, c));
-
- /* If "previous" is set and it is not at the start of the work space, move
- it back to there, in order to avoid filling up the work space. Otherwise,
- if "previous" is NULL, reset the current code pointer to the start. */
-
- if (previous != NULL)
- {
- if (previous > orig_code)
- {
- memmove(orig_code, previous, code - previous);
- code -= previous - orig_code;
- previous = orig_code;
- }
- }
- else code = orig_code;
-
- /* Remember where this code item starts so we can pick up the length
- next time round. */
-
- last_code = code;
- }
-
- /* In the real compile phase, just check the workspace used by the forward
- reference list. */
-
- else if (cd->hwm > cd->start_workspace + COMPILE_WORK_SIZE)
- {
- *errorcodeptr = ERR52;
- goto FAILED;
- }
-
- /* If in \Q...\E, check for the end; if not, we have a literal */
-
- if (inescq && c != 0)
- {
- if (c == '\\' && ptr[1] == 'E')
- {
- inescq = FALSE;
- ptr++;
- continue;
- }
- else
- {
- if (previous_callout != NULL)
- {
- if (lengthptr == NULL) /* Don't attempt in pre-compile phase */
- complete_callout(previous_callout, ptr, cd);
- previous_callout = NULL;
- }
- if ((options & PCRE_AUTO_CALLOUT) != 0)
- {
- previous_callout = code;
- code = auto_callout(code, ptr, cd);
- }
- goto NORMAL_CHAR;
- }
- }
-
- /* Fill in length of a previous callout, except when the next thing is
- a quantifier. */
-
- is_quantifier = c == '*' || c == '+' || c == '?' ||
- (c == '{' && is_counted_repeat(ptr+1));
-
- if (!is_quantifier && previous_callout != NULL &&
- after_manual_callout-- <= 0)
- {
- if (lengthptr == NULL) /* Don't attempt in pre-compile phase */
- complete_callout(previous_callout, ptr, cd);
- previous_callout = NULL;
- }
-
- /* In extended mode, skip white space and comments */
-
- if ((options & PCRE_EXTENDED) != 0)
- {
- if ((cd->ctypes[c] & ctype_space) != 0) continue;
- if (c == '#')
- {
- while (*(++ptr) != 0)
- {
- if (IS_NEWLINE(ptr)) { ptr += cd->nllen - 1; break; }
- }
- if (*ptr != 0) continue;
-
- /* Else fall through to handle end of string */
- c = 0;
- }
- }
-
- /* No auto callout for quantifiers. */
-
- if ((options & PCRE_AUTO_CALLOUT) != 0 && !is_quantifier)
- {
- previous_callout = code;
- code = auto_callout(code, ptr, cd);
- }
-
- switch(c)
- {
- /* ===================================================================*/
- case 0: /* The branch terminates at string end */
- case '|': /* or | or ) */
- case ')':
- *firstbyteptr = firstbyte;
- *reqbyteptr = reqbyte;
- *codeptr = code;
- *ptrptr = ptr;
- if (lengthptr != NULL)
- {
- if (OFLOW_MAX - *lengthptr < code - last_code)
- {
- *errorcodeptr = ERR20;
- goto FAILED;
- }
- *lengthptr += code - last_code; /* To include callout length */
- DPRINTF((">> end branch\n"));
- }
- return TRUE;
-
-
- /* ===================================================================*/
- /* Handle single-character metacharacters. In multiline mode, ^ disables
- the setting of any following char as a first character. */
-
- case '^':
- if ((options & PCRE_MULTILINE) != 0)
- {
- if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
- }
- previous = NULL;
- *code++ = OP_CIRC;
- break;
-
- case '$':
- previous = NULL;
- *code++ = OP_DOLL;
- break;
-
- /* There can never be a first char if '.' is first, whatever happens about
- repeats. The value of reqbyte doesn't change either. */
-
- case '.':
- if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
- zerofirstbyte = firstbyte;
- zeroreqbyte = reqbyte;
- previous = code;
- *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY;
- break;
-
-
- /* ===================================================================*/
- /* Character classes. If the included characters are all < 256, we build a
- 32-byte bitmap of the permitted characters, except in the special case
- where there is only one such character. For negated classes, we build the
- map as usual, then invert it at the end. However, we use a different opcode
- so that data characters > 255 can be handled correctly.
-
- If the class contains characters outside the 0-255 range, a different
- opcode is compiled. It may optionally have a bit map for characters < 256,
- but those above are are explicitly listed afterwards. A flag byte tells
- whether the bitmap is present, and whether this is a negated class or not.
-
- In JavaScript compatibility mode, an isolated ']' causes an error. In
- default (Perl) mode, it is treated as a data character. */
-
- case ']':
- if ((cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0)
- {
- *errorcodeptr = ERR64;
- goto FAILED;
- }
- goto NORMAL_CHAR;
-
- case '[':
- previous = code;
-
- /* PCRE supports POSIX class stuff inside a class. Perl gives an error if
- they are encountered at the top level, so we'll do that too. */
-
- if ((ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') &&
- check_posix_syntax(ptr, &tempptr))
- {
- *errorcodeptr = (ptr[1] == ':')? ERR13 : ERR31;
- goto FAILED;
- }
-
- /* If the first character is '^', set the negation flag and skip it. Also,
- if the first few characters (either before or after ^) are \Q\E or \E we
- skip them too. This makes for compatibility with Perl. */
-
- negate_class = FALSE;
- for (;;)
- {
- c = *(++ptr);
- if (c == '\\')
- {
- if (ptr[1] == 'E') ptr++;
- else if (strncmp((const char *)ptr+1, "Q\\E", 3) == 0) ptr += 3;
- else break;
- }
- else if (!negate_class && c == '^')
- negate_class = TRUE;
- else break;
- }
-
- /* Empty classes are allowed in JavaScript compatibility mode. Otherwise,
- an initial ']' is taken as a data character -- the code below handles
- that. In JS mode, [] must always fail, so generate OP_FAIL, whereas
- [^] must match any character, so generate OP_ALLANY. */
-
- if (c ==']' && (cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0)
- {
- *code++ = negate_class? OP_ALLANY : OP_FAIL;
- if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
- zerofirstbyte = firstbyte;
- break;
- }
-
- /* If a class contains a negative special such as \S, we need to flip the
- negation flag at the end, so that support for characters > 255 works
- correctly (they are all included in the class). */
-
- should_flip_negation = FALSE;
-
- /* Keep a count of chars with values < 256 so that we can optimize the case
- of just a single character (as long as it's < 256). However, For higher
- valued UTF-8 characters, we don't yet do any optimization. */
-
- class_charcount = 0;
- class_lastchar = -1;
-
- /* Initialize the 32-char bit map to all zeros. We build the map in a
- temporary bit of memory, in case the class contains only 1 character (less
- than 256), because in that case the compiled code doesn't use the bit map.
- */
-
- memset(classbits, 0, 32 * sizeof(uschar));
-
-#ifdef SUPPORT_UTF8
- class_utf8 = FALSE; /* No chars >= 256 */
- class_utf8data = code + LINK_SIZE + 2; /* For UTF-8 items */
- class_utf8data_base = class_utf8data; /* For resetting in pass 1 */
-#endif
-
- /* Process characters until ] is reached. By writing this as a "do" it
- means that an initial ] is taken as a data character. At the start of the
- loop, c contains the first byte of the character. */
-
- if (c != 0) do
- {
- const uschar *oldptr;
-
-#ifdef SUPPORT_UTF8
- if (utf8 && c > 127)
- { /* Braces are required because the */
- GETCHARLEN(c, ptr, ptr); /* macro generates multiple statements */
- }
-
- /* In the pre-compile phase, accumulate the length of any UTF-8 extra
- data and reset the pointer. This is so that very large classes that
- contain a zillion UTF-8 characters no longer overwrite the work space
- (which is on the stack). */
-
- if (lengthptr != NULL)
- {
- *lengthptr += class_utf8data - class_utf8data_base;
- class_utf8data = class_utf8data_base;
- }
-
-#endif
-
- /* Inside \Q...\E everything is literal except \E */
-
- if (inescq)
- {
- if (c == '\\' && ptr[1] == 'E') /* If we are at \E */
- {
- inescq = FALSE; /* Reset literal state */
- ptr++; /* Skip the 'E' */
- continue; /* Carry on with next */
- }
- goto CHECK_RANGE; /* Could be range if \E follows */
- }
-
- /* Handle POSIX class names. Perl allows a negation extension of the
- form [:^name:]. A square bracket that doesn't match the syntax is
- treated as a literal. We also recognize the POSIX constructions
- [.ch.] and [=ch=] ("collating elements") and fault them, as Perl
- 5.6 and 5.8 do. */
-
- if (c == '[' &&
- (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') &&
- check_posix_syntax(ptr, &tempptr))
- {
- BOOL local_negate = FALSE;
- int posix_class, taboffset, tabopt;
- register const uschar *cbits = cd->cbits;
- uschar pbits[32];
-
- if (ptr[1] != ':')
- {
- *errorcodeptr = ERR31;
- goto FAILED;
- }
-
- ptr += 2;
- if (*ptr == '^')
- {
- local_negate = TRUE;
- should_flip_negation = TRUE; /* Note negative special */
- ptr++;
- }
-
- posix_class = check_posix_name(ptr, tempptr - ptr);
- if (posix_class < 0)
- {
- *errorcodeptr = ERR30;
- goto FAILED;
- }
-
- /* If matching is caseless, upper and lower are converted to
- alpha. This relies on the fact that the class table starts with
- alpha, lower, upper as the first 3 entries. */
-
- if ((options & PCRE_CASELESS) != 0 && posix_class <= 2)
- posix_class = 0;
-
- /* We build the bit map for the POSIX class in a chunk of local store
- because we may be adding and subtracting from it, and we don't want to
- subtract bits that may be in the main map already. At the end we or the
- result into the bit map that is being built. */
-
- posix_class *= 3;
-
- /* Copy in the first table (always present) */
-
- memcpy(pbits, cbits + posix_class_maps[posix_class],
- 32 * sizeof(uschar));
-
- /* If there is a second table, add or remove it as required. */
-
- taboffset = posix_class_maps[posix_class + 1];
- tabopt = posix_class_maps[posix_class + 2];
-
- if (taboffset >= 0)
- {
- if (tabopt >= 0)
- for (c = 0; c < 32; c++) pbits[c] |= cbits[c + taboffset];
- else
- for (c = 0; c < 32; c++) pbits[c] &= ~cbits[c + taboffset];
- }
-
- /* Not see if we need to remove any special characters. An option
- value of 1 removes vertical space and 2 removes underscore. */
-
- if (tabopt < 0) tabopt = -tabopt;
- if (tabopt == 1) pbits[1] &= ~0x3c;
- else if (tabopt == 2) pbits[11] &= 0x7f;
-
- /* Add the POSIX table or its complement into the main table that is
- being built and we are done. */
-
- if (local_negate)
- for (c = 0; c < 32; c++) classbits[c] |= ~pbits[c];
- else
- for (c = 0; c < 32; c++) classbits[c] |= pbits[c];
-
- ptr = tempptr + 1;
- class_charcount = 10; /* Set > 1; assumes more than 1 per class */
- continue; /* End of POSIX syntax handling */
- }
-
- /* Backslash may introduce a single character, or it may introduce one
- of the specials, which just set a flag. The sequence \b is a special
- case. Inside a class (and only there) it is treated as backspace.
- Elsewhere it marks a word boundary. Other escapes have preset maps ready
- to 'or' into the one we are building. We assume they have more than one
- character in them, so set class_charcount bigger than one. */
-
- if (c == '\\')
- {
- c = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE);
- if (*errorcodeptr != 0) goto FAILED;
-
- if (-c == ESC_b) c = '\b'; /* \b is backspace in a class */
- else if (-c == ESC_X) c = 'X'; /* \X is literal X in a class */
- else if (-c == ESC_R) c = 'R'; /* \R is literal R in a class */
- else if (-c == ESC_Q) /* Handle start of quoted string */
- {
- if (ptr[1] == '\\' && ptr[2] == 'E')
- {
- ptr += 2; /* avoid empty string */
- }
- else inescq = TRUE;
- continue;
- }
- else if (-c == ESC_E) continue; /* Ignore orphan \E */
-
- if (c < 0)
- {
- register const uschar *cbits = cd->cbits;
- class_charcount += 2; /* Greater than 1 is what matters */
-
- /* Save time by not doing this in the pre-compile phase. */
-
- if (lengthptr == NULL) switch (-c)
- {
- case ESC_d:
- for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit];
- continue;
-
- case ESC_D:
- should_flip_negation = TRUE;
- for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_digit];
- continue;
-
- case ESC_w:
- for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_word];
- continue;
-
- case ESC_W:
- should_flip_negation = TRUE;
- for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_word];
- continue;
-
- case ESC_s:
- for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_space];
- classbits[1] &= ~0x08; /* Perl 5.004 onwards omits VT from \s */
- continue;
-
- case ESC_S:
- should_flip_negation = TRUE;
- for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_space];
- classbits[1] |= 0x08; /* Perl 5.004 onwards omits VT from \s */
- continue;
-
- default: /* Not recognized; fall through */
- break; /* Need "default" setting to stop compiler warning. */
- }
-
- /* In the pre-compile phase, just do the recognition. */
-
- else if (c == -ESC_d || c == -ESC_D || c == -ESC_w ||
- c == -ESC_W || c == -ESC_s || c == -ESC_S) continue;
-
- /* We need to deal with \H, \h, \V, and \v in both phases because
- they use extra memory. */
-
- if (-c == ESC_h)
- {
- SETBIT(classbits, 0x09); /* VT */
- SETBIT(classbits, 0x20); /* SPACE */
- SETBIT(classbits, 0xa0); /* NSBP */
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- class_utf8 = TRUE;
- *class_utf8data++ = XCL_SINGLE;
- class_utf8data += _pcre_ord2utf8(0x1680, class_utf8data);
- *class_utf8data++ = XCL_SINGLE;
- class_utf8data += _pcre_ord2utf8(0x180e, class_utf8data);
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(0x2000, class_utf8data);
- class_utf8data += _pcre_ord2utf8(0x200A, class_utf8data);
- *class_utf8data++ = XCL_SINGLE;
- class_utf8data += _pcre_ord2utf8(0x202f, class_utf8data);
- *class_utf8data++ = XCL_SINGLE;
- class_utf8data += _pcre_ord2utf8(0x205f, class_utf8data);
- *class_utf8data++ = XCL_SINGLE;
- class_utf8data += _pcre_ord2utf8(0x3000, class_utf8data);
- }
-#endif
- continue;
- }
-
- if (-c == ESC_H)
- {
- for (c = 0; c < 32; c++)
- {
- int x = 0xff;
- switch (c)
- {
- case 0x09/8: x ^= 1 << (0x09%8); break;
- case 0x20/8: x ^= 1 << (0x20%8); break;
- case 0xa0/8: x ^= 1 << (0xa0%8); break;
- default: break;
- }
- classbits[c] |= x;
- }
-
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- class_utf8 = TRUE;
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(0x0100, class_utf8data);
- class_utf8data += _pcre_ord2utf8(0x167f, class_utf8data);
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(0x1681, class_utf8data);
- class_utf8data += _pcre_ord2utf8(0x180d, class_utf8data);
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(0x180f, class_utf8data);
- class_utf8data += _pcre_ord2utf8(0x1fff, class_utf8data);
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(0x200B, class_utf8data);
- class_utf8data += _pcre_ord2utf8(0x202e, class_utf8data);
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(0x2030, class_utf8data);
- class_utf8data += _pcre_ord2utf8(0x205e, class_utf8data);
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(0x2060, class_utf8data);
- class_utf8data += _pcre_ord2utf8(0x2fff, class_utf8data);
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(0x3001, class_utf8data);
- class_utf8data += _pcre_ord2utf8(0x7fffffff, class_utf8data);
- }
-#endif
- continue;
- }
-
- if (-c == ESC_v)
- {
- SETBIT(classbits, 0x0a); /* LF */
- SETBIT(classbits, 0x0b); /* VT */
- SETBIT(classbits, 0x0c); /* FF */
- SETBIT(classbits, 0x0d); /* CR */
- SETBIT(classbits, 0x85); /* NEL */
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- class_utf8 = TRUE;
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(0x2028, class_utf8data);
- class_utf8data += _pcre_ord2utf8(0x2029, class_utf8data);
- }
-#endif
- continue;
- }
-
- if (-c == ESC_V)
- {
- for (c = 0; c < 32; c++)
- {
- int x = 0xff;
- switch (c)
- {
- case 0x0a/8: x ^= 1 << (0x0a%8);
- x ^= 1 << (0x0b%8);
- x ^= 1 << (0x0c%8);
- x ^= 1 << (0x0d%8);
- break;
- case 0x85/8: x ^= 1 << (0x85%8); break;
- default: break;
- }
- classbits[c] |= x;
- }
-
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- class_utf8 = TRUE;
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(0x0100, class_utf8data);
- class_utf8data += _pcre_ord2utf8(0x2027, class_utf8data);
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(0x2029, class_utf8data);
- class_utf8data += _pcre_ord2utf8(0x7fffffff, class_utf8data);
- }
-#endif
- continue;
- }
-
- /* We need to deal with \P and \p in both phases. */
-
-#ifdef SUPPORT_UCP
- if (-c == ESC_p || -c == ESC_P)
- {
- BOOL negated;
- int pdata;
- int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr);
- if (ptype < 0) goto FAILED;
- class_utf8 = TRUE;
- *class_utf8data++ = ((-c == ESC_p) != negated)?
- XCL_PROP : XCL_NOTPROP;
- *class_utf8data++ = ptype;
- *class_utf8data++ = pdata;
- class_charcount -= 2; /* Not a < 256 character */
- continue;
- }
-#endif
- /* Unrecognized escapes are faulted if PCRE is running in its
- strict mode. By default, for compatibility with Perl, they are
- treated as literals. */
-
- if ((options & PCRE_EXTRA) != 0)
- {
- *errorcodeptr = ERR7;
- goto FAILED;
- }
-
- class_charcount -= 2; /* Undo the default count from above */
- c = *ptr; /* Get the final character and fall through */
- }
-
- /* Fall through if we have a single character (c >= 0). This may be
- greater than 256 in UTF-8 mode. */
-
- } /* End of backslash handling */
-
- /* A single character may be followed by '-' to form a range. However,
- Perl does not permit ']' to be the end of the range. A '-' character
- at the end is treated as a literal. Perl ignores orphaned \E sequences
- entirely. The code for handling \Q and \E is messy. */
-
- CHECK_RANGE:
- while (ptr[1] == '\\' && ptr[2] == 'E')
- {
- inescq = FALSE;
- ptr += 2;
- }
-
- oldptr = ptr;
-
- /* Remember \r or \n */
-
- if (c == '\r' || c == '\n') cd->external_flags |= PCRE_HASCRORLF;
-
- /* Check for range */
-
- if (!inescq && ptr[1] == '-')
- {
- int d;
- ptr += 2;
- while (*ptr == '\\' && ptr[1] == 'E') ptr += 2;
-
- /* If we hit \Q (not followed by \E) at this point, go into escaped
- mode. */
-
- while (*ptr == '\\' && ptr[1] == 'Q')
- {
- ptr += 2;
- if (*ptr == '\\' && ptr[1] == 'E') { ptr += 2; continue; }
- inescq = TRUE;
- break;
- }
-
- if (*ptr == 0 || (!inescq && *ptr == ']'))
- {
- ptr = oldptr;
- goto LONE_SINGLE_CHARACTER;
- }
-
-#ifdef SUPPORT_UTF8
- if (utf8)
- { /* Braces are required because the */
- GETCHARLEN(d, ptr, ptr); /* macro generates multiple statements */
- }
- else
-#endif
- d = *ptr; /* Not UTF-8 mode */
-
- /* The second part of a range can be a single-character escape, but
- not any of the other escapes. Perl 5.6 treats a hyphen as a literal
- in such circumstances. */
-
- if (!inescq && d == '\\')
- {
- d = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE);
- if (*errorcodeptr != 0) goto FAILED;
-
- /* \b is backspace; \X is literal X; \R is literal R; any other
- special means the '-' was literal */
-
- if (d < 0)
- {
- if (d == -ESC_b) d = '\b';
- else if (d == -ESC_X) d = 'X';
- else if (d == -ESC_R) d = 'R'; else
- {
- ptr = oldptr;
- goto LONE_SINGLE_CHARACTER; /* A few lines below */
- }
- }
- }
-
- /* Check that the two values are in the correct order. Optimize
- one-character ranges */
-
- if (d < c)
- {
- *errorcodeptr = ERR8;
- goto FAILED;
- }
-
- if (d == c) goto LONE_SINGLE_CHARACTER; /* A few lines below */
-
- /* Remember \r or \n */
-
- if (d == '\r' || d == '\n') cd->external_flags |= PCRE_HASCRORLF;
-
- /* In UTF-8 mode, if the upper limit is > 255, or > 127 for caseless
- matching, we have to use an XCLASS with extra data items. Caseless
- matching for characters > 127 is available only if UCP support is
- available. */
-
-#ifdef SUPPORT_UTF8
- if (utf8 && (d > 255 || ((options & PCRE_CASELESS) != 0 && d > 127)))
- {
- class_utf8 = TRUE;
-
- /* With UCP support, we can find the other case equivalents of
- the relevant characters. There may be several ranges. Optimize how
- they fit with the basic range. */
-
-#ifdef SUPPORT_UCP
- if ((options & PCRE_CASELESS) != 0)
- {
- unsigned int occ, ocd;
- unsigned int cc = c;
- unsigned int origd = d;
- while (get_othercase_range(&cc, origd, &occ, &ocd))
- {
- if (occ >= (unsigned int)c &&
- ocd <= (unsigned int)d)
- continue; /* Skip embedded ranges */
-
- if (occ < (unsigned int)c &&
- ocd >= (unsigned int)c - 1) /* Extend the basic range */
- { /* if there is overlap, */
- c = occ; /* noting that if occ < c */
- continue; /* we can't have ocd > d */
- } /* because a subrange is */
- if (ocd > (unsigned int)d &&
- occ <= (unsigned int)d + 1) /* always shorter than */
- { /* the basic range. */
- d = ocd;
- continue;
- }
-
- if (occ == ocd)
- {
- *class_utf8data++ = XCL_SINGLE;
- }
- else
- {
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(occ, class_utf8data);
- }
- class_utf8data += _pcre_ord2utf8(ocd, class_utf8data);
- }
- }
-#endif /* SUPPORT_UCP */
-
- /* Now record the original range, possibly modified for UCP caseless
- overlapping ranges. */
-
- *class_utf8data++ = XCL_RANGE;
- class_utf8data += _pcre_ord2utf8(c, class_utf8data);
- class_utf8data += _pcre_ord2utf8(d, class_utf8data);
-
- /* With UCP support, we are done. Without UCP support, there is no
- caseless matching for UTF-8 characters > 127; we can use the bit map
- for the smaller ones. */
-
-#ifdef SUPPORT_UCP
- continue; /* With next character in the class */
-#else
- if ((options & PCRE_CASELESS) == 0 || c > 127) continue;
-
- /* Adjust upper limit and fall through to set up the map */
-
- d = 127;
-
-#endif /* SUPPORT_UCP */
- }
-#endif /* SUPPORT_UTF8 */
-
- /* We use the bit map for all cases when not in UTF-8 mode; else
- ranges that lie entirely within 0-127 when there is UCP support; else
- for partial ranges without UCP support. */
-
- class_charcount += d - c + 1;
- class_lastchar = d;
-
- /* We can save a bit of time by skipping this in the pre-compile. */
-
- if (lengthptr == NULL) for (; c <= d; c++)
- {
- classbits[c/8] |= (1 << (c&7));
- if ((options & PCRE_CASELESS) != 0)
- {
- int uc = cd->fcc[c]; /* flip case */
- classbits[uc/8] |= (1 << (uc&7));
- }
- }
-
- continue; /* Go get the next char in the class */
- }
-
- /* Handle a lone single character - we can get here for a normal
- non-escape char, or after \ that introduces a single character or for an
- apparent range that isn't. */
-
- LONE_SINGLE_CHARACTER:
-
- /* Handle a character that cannot go in the bit map */
-
-#ifdef SUPPORT_UTF8
- if (utf8 && (c > 255 || ((options & PCRE_CASELESS) != 0 && c > 127)))
- {
- class_utf8 = TRUE;
- *class_utf8data++ = XCL_SINGLE;
- class_utf8data += _pcre_ord2utf8(c, class_utf8data);
-
-#ifdef SUPPORT_UCP
- if ((options & PCRE_CASELESS) != 0)
- {
- unsigned int othercase;
- if ((othercase = UCD_OTHERCASE(c)) != c)
- {
- *class_utf8data++ = XCL_SINGLE;
- class_utf8data += _pcre_ord2utf8(othercase, class_utf8data);
- }
- }
-#endif /* SUPPORT_UCP */
-
- }
- else
-#endif /* SUPPORT_UTF8 */
-
- /* Handle a single-byte character */
- {
- classbits[c/8] |= (1 << (c&7));
- if ((options & PCRE_CASELESS) != 0)
- {
- c = cd->fcc[c]; /* flip case */
- classbits[c/8] |= (1 << (c&7));
- }
- class_charcount++;
- class_lastchar = c;
- }
- }
-
- /* Loop until ']' reached. This "while" is the end of the "do" above. */
-
- while ((c = *(++ptr)) != 0 && (c != ']' || inescq));
-
- if (c == 0) /* Missing terminating ']' */
- {
- *errorcodeptr = ERR6;
- goto FAILED;
- }
-
-
-/* This code has been disabled because it would mean that \s counts as
-an explicit \r or \n reference, and that's not really what is wanted. Now
-we set the flag only if there is a literal "\r" or "\n" in the class. */
-
-#if 0
- /* Remember whether \r or \n are in this class */
-
- if (negate_class)
- {
- if ((classbits[1] & 0x24) != 0x24) cd->external_flags |= PCRE_HASCRORLF;
- }
- else
- {
- if ((classbits[1] & 0x24) != 0) cd->external_flags |= PCRE_HASCRORLF;
- }
-#endif
-
-
- /* If class_charcount is 1, we saw precisely one character whose value is
- less than 256. As long as there were no characters >= 128 and there was no
- use of \p or \P, in other words, no use of any XCLASS features, we can
- optimize.
-
- In UTF-8 mode, we can optimize the negative case only if there were no
- characters >= 128 because OP_NOT and the related opcodes like OP_NOTSTAR
- operate on single-bytes only. This is an historical hangover. Maybe one day
- we can tidy these opcodes to handle multi-byte characters.
-
- The optimization throws away the bit map. We turn the item into a
- 1-character OP_CHAR[NC] if it's positive, or OP_NOT if it's negative. Note
- that OP_NOT does not support multibyte characters. In the positive case, it
- can cause firstbyte to be set. Otherwise, there can be no first char if
- this item is first, whatever repeat count may follow. In the case of
- reqbyte, save the previous value for reinstating. */
-
-#ifdef SUPPORT_UTF8
- if (class_charcount == 1 && !class_utf8 &&
- (!utf8 || !negate_class || class_lastchar < 128))
-#else
- if (class_charcount == 1)
-#endif
- {
- zeroreqbyte = reqbyte;
-
- /* The OP_NOT opcode works on one-byte characters only. */
-
- if (negate_class)
- {
- if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
- zerofirstbyte = firstbyte;
- *code++ = OP_NOT;
- *code++ = class_lastchar;
- break;
- }
-
- /* For a single, positive character, get the value into mcbuffer, and
- then we can handle this with the normal one-character code. */
-
-#ifdef SUPPORT_UTF8
- if (utf8 && class_lastchar > 127)
- mclength = _pcre_ord2utf8(class_lastchar, mcbuffer);
- else
-#endif
- {
- mcbuffer[0] = class_lastchar;
- mclength = 1;
- }
- goto ONE_CHAR;
- } /* End of 1-char optimization */
-
- /* The general case - not the one-char optimization. If this is the first
- thing in the branch, there can be no first char setting, whatever the
- repeat count. Any reqbyte setting must remain unchanged after any kind of
- repeat. */
-
- if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
- zerofirstbyte = firstbyte;
- zeroreqbyte = reqbyte;
-
- /* If there are characters with values > 255, we have to compile an
- extended class, with its own opcode, unless there was a negated special
- such as \S in the class, because in that case all characters > 255 are in
- the class, so any that were explicitly given as well can be ignored. If
- (when there are explicit characters > 255 that must be listed) there are no
- characters < 256, we can omit the bitmap in the actual compiled code. */
-
-#ifdef SUPPORT_UTF8
- if (class_utf8 && !should_flip_negation)
- {
- *class_utf8data++ = XCL_END; /* Marks the end of extra data */
- *code++ = OP_XCLASS;
- code += LINK_SIZE;
- *code = negate_class? XCL_NOT : 0;
-
- /* If the map is required, move up the extra data to make room for it;
- otherwise just move the code pointer to the end of the extra data. */
-
- if (class_charcount > 0)
- {
- *code++ |= XCL_MAP;
- memmove(code + 32, code, class_utf8data - code);
- memcpy(code, classbits, 32);
- code = class_utf8data + 32;
- }
- else code = class_utf8data;
-
- /* Now fill in the complete length of the item */
-
- PUT(previous, 1, code - previous);
- break; /* End of class handling */
- }
-#endif
-
- /* If there are no characters > 255, set the opcode to OP_CLASS or
- OP_NCLASS, depending on whether the whole class was negated and whether
- there were negative specials such as \S in the class. Then copy the 32-byte
- map into the code vector, negating it if necessary. */
-
- *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS;
- if (negate_class)
- {
- if (lengthptr == NULL) /* Save time in the pre-compile phase */
- for (c = 0; c < 32; c++) code[c] = ~classbits[c];
- }
- else
- {
- memcpy(code, classbits, 32);
- }
- code += 32;
- break;
-
-
- /* ===================================================================*/
- /* Various kinds of repeat; '{' is not necessarily a quantifier, but this
- has been tested above. */
-
- case '{':
- if (!is_quantifier) goto NORMAL_CHAR;
- ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorcodeptr);
- if (*errorcodeptr != 0) goto FAILED;
- goto REPEAT;
-
- case '*':
- repeat_min = 0;
- repeat_max = -1;
- goto REPEAT;
-
- case '+':
- repeat_min = 1;
- repeat_max = -1;
- goto REPEAT;
-
- case '?':
- repeat_min = 0;
- repeat_max = 1;
-
- REPEAT:
- if (previous == NULL)
- {
- *errorcodeptr = ERR9;
- goto FAILED;
- }
-
- if (repeat_min == 0)
- {
- firstbyte = zerofirstbyte; /* Adjust for zero repeat */
- reqbyte = zeroreqbyte; /* Ditto */
- }
-
- /* Remember whether this is a variable length repeat */
-
- reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY;
-
- op_type = 0; /* Default single-char op codes */
- possessive_quantifier = FALSE; /* Default not possessive quantifier */
-
- /* Save start of previous item, in case we have to move it up to make space
- for an inserted OP_ONCE for the additional '+' extension. */
-
- tempcode = previous;
-
- /* If the next character is '+', we have a possessive quantifier. This
- implies greediness, whatever the setting of the PCRE_UNGREEDY option.
- If the next character is '?' this is a minimizing repeat, by default,
- but if PCRE_UNGREEDY is set, it works the other way round. We change the
- repeat type to the non-default. */
-
- if (ptr[1] == '+')
- {
- repeat_type = 0; /* Force greedy */
- possessive_quantifier = TRUE;
- ptr++;
- }
- else if (ptr[1] == '?')
- {
- repeat_type = greedy_non_default;
- ptr++;
- }
- else repeat_type = greedy_default;
-
- /* If previous was a character match, abolish the item and generate a
- repeat item instead. If a char item has a minumum of more than one, ensure
- that it is set in reqbyte - it might not be if a sequence such as x{3} is
- the first thing in a branch because the x will have gone into firstbyte
- instead. */
-
- if (*previous == OP_CHAR || *previous == OP_CHARNC)
- {
- /* Deal with UTF-8 characters that take up more than one byte. It's
- easier to write this out separately than try to macrify it. Use c to
- hold the length of the character in bytes, plus 0x80 to flag that it's a
- length rather than a small character. */
-
-#ifdef SUPPORT_UTF8
- if (utf8 && (code[-1] & 0x80) != 0)
- {
- uschar *lastchar = code - 1;
- while((*lastchar & 0xc0) == 0x80) lastchar--;
- c = code - lastchar; /* Length of UTF-8 character */
- memcpy(utf8_char, lastchar, c); /* Save the char */
- c |= 0x80; /* Flag c as a length */
- }
- else
-#endif
-
- /* Handle the case of a single byte - either with no UTF8 support, or
- with UTF-8 disabled, or for a UTF-8 character < 128. */
-
- {
- c = code[-1];
- if (repeat_min > 1) reqbyte = c | req_caseopt | cd->req_varyopt;
- }
-
- /* If the repetition is unlimited, it pays to see if the next thing on
- the line is something that cannot possibly match this character. If so,
- automatically possessifying this item gains some performance in the case
- where the match fails. */
-
- if (!possessive_quantifier &&
- repeat_max < 0 &&
- check_auto_possessive(*previous, c, utf8, utf8_char, ptr + 1,
- options, cd))
- {
- repeat_type = 0; /* Force greedy */
- possessive_quantifier = TRUE;
- }
-
- goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */
- }
-
- /* If previous was a single negated character ([^a] or similar), we use
- one of the special opcodes, replacing it. The code is shared with single-
- character repeats by setting opt_type to add a suitable offset into
- repeat_type. We can also test for auto-possessification. OP_NOT is
- currently used only for single-byte chars. */
-
- else if (*previous == OP_NOT)
- {
- op_type = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */
- c = previous[1];
- if (!possessive_quantifier &&
- repeat_max < 0 &&
- check_auto_possessive(OP_NOT, c, utf8, NULL, ptr + 1, options, cd))
- {
- repeat_type = 0; /* Force greedy */
- possessive_quantifier = TRUE;
- }
- goto OUTPUT_SINGLE_REPEAT;
- }
-
- /* If previous was a character type match (\d or similar), abolish it and
- create a suitable repeat item. The code is shared with single-character
- repeats by setting op_type to add a suitable offset into repeat_type. Note
- the the Unicode property types will be present only when SUPPORT_UCP is
- defined, but we don't wrap the little bits of code here because it just
- makes it horribly messy. */
-
- else if (*previous < OP_EODN)
- {
- uschar *oldcode;
- int prop_type, prop_value;
- op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */
- c = *previous;
-
- if (!possessive_quantifier &&
- repeat_max < 0 &&
- check_auto_possessive(c, 0, utf8, NULL, ptr + 1, options, cd))
- {
- repeat_type = 0; /* Force greedy */
- possessive_quantifier = TRUE;
- }
-
- OUTPUT_SINGLE_REPEAT:
- if (*previous == OP_PROP || *previous == OP_NOTPROP)
- {
- prop_type = previous[1];
- prop_value = previous[2];
- }
- else prop_type = prop_value = -1;
-
- oldcode = code;
- code = previous; /* Usually overwrite previous item */
-
- /* If the maximum is zero then the minimum must also be zero; Perl allows
- this case, so we do too - by simply omitting the item altogether. */
-
- if (repeat_max == 0) goto END_REPEAT;
-
- /* All real repeats make it impossible to handle partial matching (maybe
- one day we will be able to remove this restriction). */
-
- if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL;
-
- /* Combine the op_type with the repeat_type */
-
- repeat_type += op_type;
-
- /* A minimum of zero is handled either as the special case * or ?, or as
- an UPTO, with the maximum given. */
-
- if (repeat_min == 0)
- {
- if (repeat_max == -1) *code++ = OP_STAR + repeat_type;
- else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;
- else
- {
- *code++ = OP_UPTO + repeat_type;
- PUT2INC(code, 0, repeat_max);
- }
- }
-
- /* A repeat minimum of 1 is optimized into some special cases. If the
- maximum is unlimited, we use OP_PLUS. Otherwise, the original item is
- left in place and, if the maximum is greater than 1, we use OP_UPTO with
- one less than the maximum. */
-
- else if (repeat_min == 1)
- {
- if (repeat_max == -1)
- *code++ = OP_PLUS + repeat_type;
- else
- {
- code = oldcode; /* leave previous item in place */
- if (repeat_max == 1) goto END_REPEAT;
- *code++ = OP_UPTO + repeat_type;
- PUT2INC(code, 0, repeat_max - 1);
- }
- }
-
- /* The case {n,n} is just an EXACT, while the general case {n,m} is
- handled as an EXACT followed by an UPTO. */
-
- else
- {
- *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */
- PUT2INC(code, 0, repeat_min);
-
- /* If the maximum is unlimited, insert an OP_STAR. Before doing so,
- we have to insert the character for the previous code. For a repeated
- Unicode property match, there are two extra bytes that define the
- required property. In UTF-8 mode, long characters have their length in
- c, with the 0x80 bit as a flag. */
-
- if (repeat_max < 0)
- {
-#ifdef SUPPORT_UTF8
- if (utf8 && c >= 128)
- {
- memcpy(code, utf8_char, c & 7);
- code += c & 7;
- }
- else
-#endif
- {
- *code++ = c;
- if (prop_type >= 0)
- {
- *code++ = prop_type;
- *code++ = prop_value;
- }
- }
- *code++ = OP_STAR + repeat_type;
- }
-
- /* Else insert an UPTO if the max is greater than the min, again
- preceded by the character, for the previously inserted code. If the
- UPTO is just for 1 instance, we can use QUERY instead. */
-
- else if (repeat_max != repeat_min)
- {
-#ifdef SUPPORT_UTF8
- if (utf8 && c >= 128)
- {
- memcpy(code, utf8_char, c & 7);
- code += c & 7;
- }
- else
-#endif
- *code++ = c;
- if (prop_type >= 0)
- {
- *code++ = prop_type;
- *code++ = prop_value;
- }
- repeat_max -= repeat_min;
-
- if (repeat_max == 1)
- {
- *code++ = OP_QUERY + repeat_type;
- }
- else
- {
- *code++ = OP_UPTO + repeat_type;
- PUT2INC(code, 0, repeat_max);
- }
- }
- }
-
- /* The character or character type itself comes last in all cases. */
-
-#ifdef SUPPORT_UTF8
- if (utf8 && c >= 128)
- {
- memcpy(code, utf8_char, c & 7);
- code += c & 7;
- }
- else
-#endif
- *code++ = c;
-
- /* For a repeated Unicode property match, there are two extra bytes that
- define the required property. */
-
-#ifdef SUPPORT_UCP
- if (prop_type >= 0)
- {
- *code++ = prop_type;
- *code++ = prop_value;
- }
-#endif
- }
-
- /* If previous was a character class or a back reference, we put the repeat
- stuff after it, but just skip the item if the repeat was {0,0}. */
-
- else if (*previous == OP_CLASS ||
- *previous == OP_NCLASS ||
-#ifdef SUPPORT_UTF8
- *previous == OP_XCLASS ||
-#endif
- *previous == OP_REF)
- {
- if (repeat_max == 0)
- {
- code = previous;
- goto END_REPEAT;
- }
-
- /* All real repeats make it impossible to handle partial matching (maybe
- one day we will be able to remove this restriction). */
-
- if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL;
-
- if (repeat_min == 0 && repeat_max == -1)
- *code++ = OP_CRSTAR + repeat_type;
- else if (repeat_min == 1 && repeat_max == -1)
- *code++ = OP_CRPLUS + repeat_type;
- else if (repeat_min == 0 && repeat_max == 1)
- *code++ = OP_CRQUERY + repeat_type;
- else
- {
- *code++ = OP_CRRANGE + repeat_type;
- PUT2INC(code, 0, repeat_min);
- if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */
- PUT2INC(code, 0, repeat_max);
- }
- }
-
- /* If previous was a bracket group, we may have to replicate it in certain
- cases. */
-
- else if (*previous == OP_BRA || *previous == OP_CBRA ||
- *previous == OP_ONCE || *previous == OP_COND)
- {
- register int i;
- int ketoffset = 0;
- int len = code - previous;
- uschar *bralink = NULL;
-
- /* Repeating a DEFINE group is pointless */
-
- if (*previous == OP_COND && previous[LINK_SIZE+1] == OP_DEF)
- {
- *errorcodeptr = ERR55;
- goto FAILED;
- }
-
- /* If the maximum repeat count is unlimited, find the end of the bracket
- by scanning through from the start, and compute the offset back to it
- from the current code pointer. There may be an OP_OPT setting following
- the final KET, so we can't find the end just by going back from the code
- pointer. */
-
- if (repeat_max == -1)
- {
- register uschar *ket = previous;
- do ket += GET(ket, 1); while (*ket != OP_KET);
- ketoffset = code - ket;
- }
-
- /* The case of a zero minimum is special because of the need to stick
- OP_BRAZERO in front of it, and because the group appears once in the
- data, whereas in other cases it appears the minimum number of times. For
- this reason, it is simplest to treat this case separately, as otherwise
- the code gets far too messy. There are several special subcases when the
- minimum is zero. */
-
- if (repeat_min == 0)
- {
- /* If the maximum is also zero, we used to just omit the group from the
- output altogether, like this:
-
- ** if (repeat_max == 0)
- ** {
- ** code = previous;
- ** goto END_REPEAT;
- ** }
-
- However, that fails when a group is referenced as a subroutine from
- elsewhere in the pattern, so now we stick in OP_SKIPZERO in front of it
- so that it is skipped on execution. As we don't have a list of which
- groups are referenced, we cannot do this selectively.
-
- If the maximum is 1 or unlimited, we just have to stick in the BRAZERO
- and do no more at this point. However, we do need to adjust any
- OP_RECURSE calls inside the group that refer to the group itself or any
- internal or forward referenced group, because the offset is from the
- start of the whole regex. Temporarily terminate the pattern while doing
- this. */
-
- if (repeat_max <= 1) /* Covers 0, 1, and unlimited */
- {
- *code = OP_END;
- adjust_recurse(previous, 1, utf8, cd, save_hwm);
- memmove(previous+1, previous, len);
- code++;
- if (repeat_max == 0)
- {
- *previous++ = OP_SKIPZERO;
- goto END_REPEAT;
- }
- *previous++ = OP_BRAZERO + repeat_type;
- }
-
- /* If the maximum is greater than 1 and limited, we have to replicate
- in a nested fashion, sticking OP_BRAZERO before each set of brackets.
- The first one has to be handled carefully because it's the original
- copy, which has to be moved up. The remainder can be handled by code
- that is common with the non-zero minimum case below. We have to
- adjust the value or repeat_max, since one less copy is required. Once
- again, we may have to adjust any OP_RECURSE calls inside the group. */
-
- else
- {
- int offset;
- *code = OP_END;
- adjust_recurse(previous, 2 + LINK_SIZE, utf8, cd, save_hwm);
- memmove(previous + 2 + LINK_SIZE, previous, len);
- code += 2 + LINK_SIZE;
- *previous++ = OP_BRAZERO + repeat_type;
- *previous++ = OP_BRA;
-
- /* We chain together the bracket offset fields that have to be
- filled in later when the ends of the brackets are reached. */
-
- offset = (bralink == NULL)? 0 : previous - bralink;
- bralink = previous;
- PUTINC(previous, 0, offset);
- }
-
- repeat_max--;
- }
-
- /* If the minimum is greater than zero, replicate the group as many
- times as necessary, and adjust the maximum to the number of subsequent
- copies that we need. If we set a first char from the group, and didn't
- set a required char, copy the latter from the former. If there are any
- forward reference subroutine calls in the group, there will be entries on
- the workspace list; replicate these with an appropriate increment. */
-
- else
- {
- if (repeat_min > 1)
- {
- /* In the pre-compile phase, we don't actually do the replication. We
- just adjust the length as if we had. Do some paranoid checks for
- potential integer overflow. */
-
- if (lengthptr != NULL)
- {
- int delta = (repeat_min - 1)*length_prevgroup;
- if ((double)(repeat_min - 1)*(double)length_prevgroup >
- (double)INT_MAX ||
- OFLOW_MAX - *lengthptr < delta)
- {
- *errorcodeptr = ERR20;
- goto FAILED;
- }
- *lengthptr += delta;
- }
-
- /* This is compiling for real */
-
- else
- {
- if (groupsetfirstbyte && reqbyte < 0) reqbyte = firstbyte;
- for (i = 1; i < repeat_min; i++)
- {
- uschar *hc;
- uschar *this_hwm = cd->hwm;
- memcpy(code, previous, len);
- for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE)
- {
- PUT(cd->hwm, 0, GET(hc, 0) + len);
- cd->hwm += LINK_SIZE;
- }
- save_hwm = this_hwm;
- code += len;
- }
- }
- }
-
- if (repeat_max > 0) repeat_max -= repeat_min;
- }
-
- /* This code is common to both the zero and non-zero minimum cases. If
- the maximum is limited, it replicates the group in a nested fashion,
- remembering the bracket starts on a stack. In the case of a zero minimum,
- the first one was set up above. In all cases the repeat_max now specifies
- the number of additional copies needed. Again, we must remember to
- replicate entries on the forward reference list. */
-
- if (repeat_max >= 0)
- {
- /* In the pre-compile phase, we don't actually do the replication. We
- just adjust the length as if we had. For each repetition we must add 1
- to the length for BRAZERO and for all but the last repetition we must
- add 2 + 2*LINKSIZE to allow for the nesting that occurs. Do some
- paranoid checks to avoid integer overflow. */
-
- if (lengthptr != NULL && repeat_max > 0)
- {
- int delta = repeat_max * (length_prevgroup + 1 + 2 + 2*LINK_SIZE) -
- 2 - 2*LINK_SIZE; /* Last one doesn't nest */
- if ((double)repeat_max *
- (double)(length_prevgroup + 1 + 2 + 2*LINK_SIZE)
- > (double)INT_MAX ||
- OFLOW_MAX - *lengthptr < delta)
- {
- *errorcodeptr = ERR20;
- goto FAILED;
- }
- *lengthptr += delta;
- }
-
- /* This is compiling for real */
-
- else for (i = repeat_max - 1; i >= 0; i--)
- {
- uschar *hc;
- uschar *this_hwm = cd->hwm;
-
- *code++ = OP_BRAZERO + repeat_type;
-
- /* All but the final copy start a new nesting, maintaining the
- chain of brackets outstanding. */
-
- if (i != 0)
- {
- int offset;
- *code++ = OP_BRA;
- offset = (bralink == NULL)? 0 : code - bralink;
- bralink = code;
- PUTINC(code, 0, offset);
- }
-
- memcpy(code, previous, len);
- for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE)
- {
- PUT(cd->hwm, 0, GET(hc, 0) + len + ((i != 0)? 2+LINK_SIZE : 1));
- cd->hwm += LINK_SIZE;
- }
- save_hwm = this_hwm;
- code += len;
- }
-
- /* Now chain through the pending brackets, and fill in their length
- fields (which are holding the chain links pro tem). */
-
- while (bralink != NULL)
- {
- int oldlinkoffset;
- int offset = code - bralink + 1;
- uschar *bra = code - offset;
- oldlinkoffset = GET(bra, 1);
- bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;
- *code++ = OP_KET;
- PUTINC(code, 0, offset);
- PUT(bra, 1, offset);
- }
- }
-
- /* If the maximum is unlimited, set a repeater in the final copy. We
- can't just offset backwards from the current code point, because we
- don't know if there's been an options resetting after the ket. The
- correct offset was computed above.
-
- Then, when we are doing the actual compile phase, check to see whether
- this group is a non-atomic one that could match an empty string. If so,
- convert the initial operator to the S form (e.g. OP_BRA -> OP_SBRA) so
- that runtime checking can be done. [This check is also applied to
- atomic groups at runtime, but in a different way.] */
-
- else
- {
- uschar *ketcode = code - ketoffset;
- uschar *bracode = ketcode - GET(ketcode, 1);
- *ketcode = OP_KETRMAX + repeat_type;
- if (lengthptr == NULL && *bracode != OP_ONCE)
- {
- uschar *scode = bracode;
- do
- {
- if (could_be_empty_branch(scode, ketcode, utf8))
- {
- *bracode += OP_SBRA - OP_BRA;
- break;
- }
- scode += GET(scode, 1);
- }
- while (*scode == OP_ALT);
- }
- }
- }
-
- /* If previous is OP_FAIL, it was generated by an empty class [] in
- JavaScript mode. The other ways in which OP_FAIL can be generated, that is
- by (*FAIL) or (?!) set previous to NULL, which gives a "nothing to repeat"
- error above. We can just ignore the repeat in JS case. */
-
- else if (*previous == OP_FAIL) goto END_REPEAT;
-
- /* Else there's some kind of shambles */
-
- else
- {
- *errorcodeptr = ERR11;
- goto FAILED;
- }
-
- /* If the character following a repeat is '+', or if certain optimization
- tests above succeeded, possessive_quantifier is TRUE. For some of the
- simpler opcodes, there is an special alternative opcode for this. For
- anything else, we wrap the entire repeated item inside OP_ONCE brackets.
- The '+' notation is just syntactic sugar, taken from Sun's Java package,
- but the special opcodes can optimize it a bit. The repeated item starts at
- tempcode, not at previous, which might be the first part of a string whose
- (former) last char we repeated.
-
- Possessifying an 'exact' quantifier has no effect, so we can ignore it. But
- an 'upto' may follow. We skip over an 'exact' item, and then test the
- length of what remains before proceeding. */
-
- if (possessive_quantifier)
- {
- int len;
- if (*tempcode == OP_EXACT || *tempcode == OP_TYPEEXACT ||
- *tempcode == OP_NOTEXACT)
- tempcode += _pcre_OP_lengths[*tempcode] +
- ((*tempcode == OP_TYPEEXACT &&
- (tempcode[3] == OP_PROP || tempcode[3] == OP_NOTPROP))? 2:0);
- len = code - tempcode;
- if (len > 0) switch (*tempcode)
- {
- case OP_STAR: *tempcode = OP_POSSTAR; break;
- case OP_PLUS: *tempcode = OP_POSPLUS; break;
- case OP_QUERY: *tempcode = OP_POSQUERY; break;
- case OP_UPTO: *tempcode = OP_POSUPTO; break;
-
- case OP_TYPESTAR: *tempcode = OP_TYPEPOSSTAR; break;
- case OP_TYPEPLUS: *tempcode = OP_TYPEPOSPLUS; break;
- case OP_TYPEQUERY: *tempcode = OP_TYPEPOSQUERY; break;
- case OP_TYPEUPTO: *tempcode = OP_TYPEPOSUPTO; break;
-
- case OP_NOTSTAR: *tempcode = OP_NOTPOSSTAR; break;
- case OP_NOTPLUS: *tempcode = OP_NOTPOSPLUS; break;
- case OP_NOTQUERY: *tempcode = OP_NOTPOSQUERY; break;
- case OP_NOTUPTO: *tempcode = OP_NOTPOSUPTO; break;
-
- default:
- memmove(tempcode + 1+LINK_SIZE, tempcode, len);
- code += 1 + LINK_SIZE;
- len += 1 + LINK_SIZE;
- tempcode[0] = OP_ONCE;
- *code++ = OP_KET;
- PUTINC(code, 0, len);
- PUT(tempcode, 1, len);
- break;
- }
- }
-
- /* In all case we no longer have a previous item. We also set the
- "follows varying string" flag for subsequently encountered reqbytes if
- it isn't already set and we have just passed a varying length item. */
-
- END_REPEAT:
- previous = NULL;
- cd->req_varyopt |= reqvary;
- break;
-
-
- /* ===================================================================*/
- /* Start of nested parenthesized sub-expression, or comment or lookahead or
- lookbehind or option setting or condition or all the other extended
- parenthesis forms. */
-
- case '(':
- newoptions = options;
- skipbytes = 0;
- bravalue = OP_CBRA;
- save_hwm = cd->hwm;
- reset_bracount = FALSE;
-
- /* First deal with various "verbs" that can be introduced by '*'. */
-
- if (*(++ptr) == '*' && (cd->ctypes[ptr[1]] & ctype_letter) != 0)
- {
- int i, namelen;
- const char *vn = verbnames;
- const uschar *name = ++ptr;
- previous = NULL;
- while ((cd->ctypes[*++ptr] & ctype_letter) != 0) {};
- if (*ptr == ':')
- {
- *errorcodeptr = ERR59; /* Not supported */
- goto FAILED;
- }
- if (*ptr != ')')
- {
- *errorcodeptr = ERR60;
- goto FAILED;
- }
- namelen = ptr - name;
- for (i = 0; i < verbcount; i++)
- {
- if (namelen == verbs[i].len &&
- strncmp((char *)name, vn, namelen) == 0)
- {
- *code = verbs[i].op;
- if (*code++ == OP_ACCEPT) cd->had_accept = TRUE;
- break;
- }
- vn += verbs[i].len + 1;
- }
- if (i < verbcount) continue;
- *errorcodeptr = ERR60;
- goto FAILED;
- }
-
- /* Deal with the extended parentheses; all are introduced by '?', and the
- appearance of any of them means that this is not a capturing group. */
-
- else if (*ptr == '?')
- {
- int i, set, unset, namelen;
- int *optset;
- const uschar *name;
- uschar *slot;
-
- switch (*(++ptr))
- {
- case '#': /* Comment; skip to ket */
- ptr++;
- while (*ptr != 0 && *ptr != ')') ptr++;
- if (*ptr == 0)
- {
- *errorcodeptr = ERR18;
- goto FAILED;
- }
- continue;
-
-
- /* ------------------------------------------------------------ */
- case '|': /* Reset capture count for each branch */
- reset_bracount = TRUE;
- /* Fall through */
-
- /* ------------------------------------------------------------ */
- case ':': /* Non-capturing bracket */
- bravalue = OP_BRA;
- ptr++;
- break;
-
-
- /* ------------------------------------------------------------ */
- case '(':
- bravalue = OP_COND; /* Conditional group */
-
- /* A condition can be an assertion, a number (referring to a numbered
- group), a name (referring to a named group), or 'R', referring to
- recursion. R<digits> and R&name are also permitted for recursion tests.
-
- There are several syntaxes for testing a named group: (?(name)) is used
- by Python; Perl 5.10 onwards uses (?(<name>) or (?('name')).
-
- There are two unfortunate ambiguities, caused by history. (a) 'R' can
- be the recursive thing or the name 'R' (and similarly for 'R' followed
- by digits), and (b) a number could be a name that consists of digits.
- In both cases, we look for a name first; if not found, we try the other
- cases. */
-
- /* For conditions that are assertions, check the syntax, and then exit
- the switch. This will take control down to where bracketed groups,
- including assertions, are processed. */
-
- if (ptr[1] == '?' && (ptr[2] == '=' || ptr[2] == '!' || ptr[2] == '<'))
- break;
-
- /* Most other conditions use OP_CREF (a couple change to OP_RREF
- below), and all need to skip 3 bytes at the start of the group. */
-
- code[1+LINK_SIZE] = OP_CREF;
- skipbytes = 3;
- refsign = -1;
-
- /* Check for a test for recursion in a named group. */
-
- if (ptr[1] == 'R' && ptr[2] == '&')
- {
- terminator = -1;
- ptr += 2;
- code[1+LINK_SIZE] = OP_RREF; /* Change the type of test */
- }
-
- /* Check for a test for a named group's having been set, using the Perl
- syntax (?(<name>) or (?('name') */
-
- else if (ptr[1] == '<')
- {
- terminator = '>';
- ptr++;
- }
- else if (ptr[1] == '\'')
- {
- terminator = '\'';
- ptr++;
- }
- else
- {
- terminator = 0;
- if (ptr[1] == '-' || ptr[1] == '+') refsign = *(++ptr);
- }
-
- /* We now expect to read a name; any thing else is an error */
-
- if ((cd->ctypes[ptr[1]] & ctype_word) == 0)
- {
- ptr += 1; /* To get the right offset */
- *errorcodeptr = ERR28;
- goto FAILED;
- }
-
- /* Read the name, but also get it as a number if it's all digits */
-
- recno = 0;
- name = ++ptr;
- while ((cd->ctypes[*ptr] & ctype_word) != 0)
- {
- if (recno >= 0)
- recno = (g_ascii_isdigit (*ptr) != 0)?
- recno * 10 + *ptr - '0' : -1;
- ptr++;
- }
- namelen = ptr - name;
-
- if ((terminator > 0 && *ptr++ != terminator) || *ptr++ != ')')
- {
- ptr--; /* Error offset */
- *errorcodeptr = ERR26;
- goto FAILED;
- }
-
- /* Do no further checking in the pre-compile phase. */
-
- if (lengthptr != NULL) break;
-
- /* In the real compile we do the work of looking for the actual
- reference. If the string started with "+" or "-" we require the rest to
- be digits, in which case recno will be set. */
-
- if (refsign > 0)
- {
- if (recno <= 0)
- {
- *errorcodeptr = ERR58;
- goto FAILED;
- }
- recno = (refsign == '-')?
- cd->bracount - recno + 1 : recno +cd->bracount;
- if (recno <= 0 || recno > cd->final_bracount)
- {
- *errorcodeptr = ERR15;
- goto FAILED;
- }
- PUT2(code, 2+LINK_SIZE, recno);
- break;
- }
-
- /* Otherwise (did not start with "+" or "-"), start by looking for the
- name. */
-
- slot = cd->name_table;
- for (i = 0; i < cd->names_found; i++)
- {
- if (strncmp((char *)name, (char *)slot+2, namelen) == 0) break;
- slot += cd->name_entry_size;
- }
-
- /* Found a previous named subpattern */
-
- if (i < cd->names_found)
- {
- recno = GET2(slot, 0);
- PUT2(code, 2+LINK_SIZE, recno);
- }
-
- /* Search the pattern for a forward reference */
-
- else if ((i = find_parens(ptr, cd, name, namelen,
- (options & PCRE_EXTENDED) != 0)) > 0)
- {
- PUT2(code, 2+LINK_SIZE, i);
- }
-
- /* If terminator == 0 it means that the name followed directly after
- the opening parenthesis [e.g. (?(abc)...] and in this case there are
- some further alternatives to try. For the cases where terminator != 0
- [things like (?(<name>... or (?('name')... or (?(R&name)... ] we have
- now checked all the possibilities, so give an error. */
-
- else if (terminator != 0)
- {
- *errorcodeptr = ERR15;
- goto FAILED;
- }
-
- /* Check for (?(R) for recursion. Allow digits after R to specify a
- specific group number. */
-
- else if (*name == 'R')
- {
- recno = 0;
- for (i = 1; i < namelen; i++)
- {
- if (g_ascii_isdigit (name[i]) == 0)
- {
- *errorcodeptr = ERR15;
- goto FAILED;
- }
- recno = recno * 10 + name[i] - '0';
- }
- if (recno == 0) recno = RREF_ANY;
- code[1+LINK_SIZE] = OP_RREF; /* Change test type */
- PUT2(code, 2+LINK_SIZE, recno);
- }
-
- /* Similarly, check for the (?(DEFINE) "condition", which is always
- false. */
-
- else if (namelen == 6 && strncmp((char *)name, "DEFINE", 6) == 0)
- {
- code[1+LINK_SIZE] = OP_DEF;
- skipbytes = 1;
- }
-
- /* Check for the "name" actually being a subpattern number. We are
- in the second pass here, so final_bracount is set. */
-
- else if (recno > 0 && recno <= cd->final_bracount)
- {
- PUT2(code, 2+LINK_SIZE, recno);
- }
-
- /* Either an unidentified subpattern, or a reference to (?(0) */
-
- else
- {
- *errorcodeptr = (recno == 0)? ERR35: ERR15;
- goto FAILED;
- }
- break;
-
-
- /* ------------------------------------------------------------ */
- case '=': /* Positive lookahead */
- bravalue = OP_ASSERT;
- ptr++;
- break;
-
-
- /* ------------------------------------------------------------ */
- case '!': /* Negative lookahead */
- ptr++;
- if (*ptr == ')') /* Optimize (?!) */
- {
- *code++ = OP_FAIL;
- previous = NULL;
- continue;
- }
- bravalue = OP_ASSERT_NOT;
- break;
-
-
- /* ------------------------------------------------------------ */
- case '<': /* Lookbehind or named define */
- switch (ptr[1])
- {
- case '=': /* Positive lookbehind */
- bravalue = OP_ASSERTBACK;
- ptr += 2;
- break;
-
- case '!': /* Negative lookbehind */
- bravalue = OP_ASSERTBACK_NOT;
- ptr += 2;
- break;
-
- default: /* Could be name define, else bad */
- if ((cd->ctypes[ptr[1]] & ctype_word) != 0) goto DEFINE_NAME;
- ptr++; /* Correct offset for error */
- *errorcodeptr = ERR24;
- goto FAILED;
- }
- break;
-
-
- /* ------------------------------------------------------------ */
- case '>': /* One-time brackets */
- bravalue = OP_ONCE;
- ptr++;
- break;
-
-
- /* ------------------------------------------------------------ */
- case 'C': /* Callout - may be followed by digits; */
- previous_callout = code; /* Save for later completion */
- after_manual_callout = 1; /* Skip one item before completing */
- *code++ = OP_CALLOUT;
- {
- int n = 0;
- while (g_ascii_isdigit (*(++ptr)) != 0)
- n = n * 10 + *ptr - '0';
- if (*ptr != ')')
- {
- *errorcodeptr = ERR39;
- goto FAILED;
- }
- if (n > 255)
- {
- *errorcodeptr = ERR38;
- goto FAILED;
- }
- *code++ = n;
- PUT(code, 0, ptr - cd->start_pattern + 1); /* Pattern offset */
- PUT(code, LINK_SIZE, 0); /* Default length */
- code += 2 * LINK_SIZE;
- }
- previous = NULL;
- continue;
-
-
- /* ------------------------------------------------------------ */
- case 'P': /* Python-style named subpattern handling */
- if (*(++ptr) == '=' || *ptr == '>') /* Reference or recursion */
- {
- is_recurse = *ptr == '>';
- terminator = ')';
- goto NAMED_REF_OR_RECURSE;
- }
- else if (*ptr != '<') /* Test for Python-style definition */
- {
- *errorcodeptr = ERR41;
- goto FAILED;
- }
- /* Fall through to handle (?P< as (?< is handled */
-
-
- /* ------------------------------------------------------------ */
- DEFINE_NAME: /* Come here from (?< handling */
- case '\'':
- {
- terminator = (*ptr == '<')? '>' : '\'';
- name = ++ptr;
-
- while ((cd->ctypes[*ptr] & ctype_word) != 0) ptr++;
- namelen = ptr - name;
-
- /* In the pre-compile phase, just do a syntax check. */
-
- if (lengthptr != NULL)
- {
- if (*ptr != terminator)
- {
- *errorcodeptr = ERR42;
- goto FAILED;
- }
- if (cd->names_found >= MAX_NAME_COUNT)
- {
- *errorcodeptr = ERR49;
- goto FAILED;
- }
- if (namelen + 3 > cd->name_entry_size)
- {
- cd->name_entry_size = namelen + 3;
- if (namelen > MAX_NAME_SIZE)
- {
- *errorcodeptr = ERR48;
- goto FAILED;
- }
- }
- }
-
- /* In the real compile, create the entry in the table */
-
- else
- {
- slot = cd->name_table;
- for (i = 0; i < cd->names_found; i++)
- {
- int crc = memcmp(name, slot+2, namelen);
- if (crc == 0)
- {
- if (slot[2+namelen] == 0)
- {
- if ((options & PCRE_DUPNAMES) == 0)
- {
- *errorcodeptr = ERR43;
- goto FAILED;
- }
- }
- else crc = -1; /* Current name is substring */
- }
- if (crc < 0)
- {
- memmove(slot + cd->name_entry_size, slot,
- (cd->names_found - i) * cd->name_entry_size);
- break;
- }
- slot += cd->name_entry_size;
- }
-
- PUT2(slot, 0, cd->bracount + 1);
- memcpy(slot + 2, name, namelen);
- slot[2+namelen] = 0;
- }
- }
-
- /* In both cases, count the number of names we've encountered. */
-
- ptr++; /* Move past > or ' */
- cd->names_found++;
- goto NUMBERED_GROUP;
-
-
- /* ------------------------------------------------------------ */
- case '&': /* Perl recursion/subroutine syntax */
- terminator = ')';
- is_recurse = TRUE;
- /* Fall through */
-
- /* We come here from the Python syntax above that handles both
- references (?P=name) and recursion (?P>name), as well as falling
- through from the Perl recursion syntax (?&name). We also come here from
- the Perl \k<name> or \k'name' back reference syntax and the \k{name}
- .NET syntax, and the Oniguruma \g<...> and \g'...' subroutine syntax. */
-
- NAMED_REF_OR_RECURSE:
- name = ++ptr;
- while ((cd->ctypes[*ptr] & ctype_word) != 0) ptr++;
- namelen = ptr - name;
-
- /* In the pre-compile phase, do a syntax check and set a dummy
- reference number. */
-
- if (lengthptr != NULL)
- {
- if (namelen == 0)
- {
- *errorcodeptr = ERR62;
- goto FAILED;
- }
- if (*ptr != terminator)
- {
- *errorcodeptr = ERR42;
- goto FAILED;
- }
- if (namelen > MAX_NAME_SIZE)
- {
- *errorcodeptr = ERR48;
- goto FAILED;
- }
- recno = 0;
- }
-
- /* In the real compile, seek the name in the table. We check the name
- first, and then check that we have reached the end of the name in the
- table. That way, if the name that is longer than any in the table,
- the comparison will fail without reading beyond the table entry. */
-
- else
- {
- slot = cd->name_table;
- for (i = 0; i < cd->names_found; i++)
- {
- if (strncmp((char *)name, (char *)slot+2, namelen) == 0 &&
- slot[2+namelen] == 0)
- break;
- slot += cd->name_entry_size;
- }
-
- if (i < cd->names_found) /* Back reference */
- {
- recno = GET2(slot, 0);
- }
- else if ((recno = /* Forward back reference */
- find_parens(ptr, cd, name, namelen,
- (options & PCRE_EXTENDED) != 0)) <= 0)
- {
- *errorcodeptr = ERR15;
- goto FAILED;
- }
- }
-
- /* In both phases, we can now go to the code than handles numerical
- recursion or backreferences. */
-
- if (is_recurse) goto HANDLE_RECURSION;
- else goto HANDLE_REFERENCE;
-
-
- /* ------------------------------------------------------------ */
- case 'R': /* Recursion */
- ptr++; /* Same as (?0) */
- /* Fall through */
-
-
- /* ------------------------------------------------------------ */
- case '-': case '+':
- case '0': case '1': case '2': case '3': case '4': /* Recursion or */
- case '5': case '6': case '7': case '8': case '9': /* subroutine */
- {
- const uschar *called;
- terminator = ')';
-
- /* Come here from the \g<...> and \g'...' code (Oniguruma
- compatibility). However, the syntax has been checked to ensure that
- the ... are a (signed) number, so that neither ERR63 nor ERR29 will
- be called on this path, nor with the jump to OTHER_CHAR_AFTER_QUERY
- ever be taken. */
-
- HANDLE_NUMERICAL_RECURSION:
-
- if ((refsign = *ptr) == '+')
- {
- ptr++;
- if (g_ascii_isdigit (*ptr) == 0)
- {
- *errorcodeptr = ERR63;
- goto FAILED;
- }
- }
- else if (refsign == '-')
- {
- if (g_ascii_isdigit (ptr[1]) == 0)
- goto OTHER_CHAR_AFTER_QUERY;
- ptr++;
- }
-
- recno = 0;
- while(g_ascii_isdigit (*ptr) != 0)
- recno = recno * 10 + *ptr++ - '0';
-
- if (*ptr != terminator)
- {
- *errorcodeptr = ERR29;
- goto FAILED;
- }
-
- if (refsign == '-')
- {
- if (recno == 0)
- {
- *errorcodeptr = ERR58;
- goto FAILED;
- }
- recno = cd->bracount - recno + 1;
- if (recno <= 0)
- {
- *errorcodeptr = ERR15;
- goto FAILED;
- }
- }
- else if (refsign == '+')
- {
- if (recno == 0)
- {
- *errorcodeptr = ERR58;
- goto FAILED;
- }
- recno += cd->bracount;
- }
-
- /* Come here from code above that handles a named recursion */
-
- HANDLE_RECURSION:
-
- previous = code;
- called = cd->start_code;
-
- /* When we are actually compiling, find the bracket that is being
- referenced. Temporarily end the regex in case it doesn't exist before
- this point. If we end up with a forward reference, first check that
- the bracket does occur later so we can give the error (and position)
- now. Then remember this forward reference in the workspace so it can
- be filled in at the end. */
-
- if (lengthptr == NULL)
- {
- *code = OP_END;
- if (recno != 0) called = find_bracket(cd->start_code, utf8, recno);
-
- /* Forward reference */
-
- if (called == NULL)
- {
- if (find_parens(ptr, cd, NULL, recno,
- (options & PCRE_EXTENDED) != 0) < 0)
- {
- *errorcodeptr = ERR15;
- goto FAILED;
- }
- called = cd->start_code + recno;
- PUTINC(cd->hwm, 0, code + 2 + LINK_SIZE - cd->start_code);
- }
-
- /* If not a forward reference, and the subpattern is still open,
- this is a recursive call. We check to see if this is a left
- recursion that could loop for ever, and diagnose that case. */
-
- else if (GET(called, 1) == 0 &&
- could_be_empty(called, code, bcptr, utf8))
- {
- *errorcodeptr = ERR40;
- goto FAILED;
- }
- }
-
- /* Insert the recursion/subroutine item, automatically wrapped inside
- "once" brackets. Set up a "previous group" length so that a
- subsequent quantifier will work. */
-
- *code = OP_ONCE;
- PUT(code, 1, 2 + 2*LINK_SIZE);
- code += 1 + LINK_SIZE;
-
- *code = OP_RECURSE;
- PUT(code, 1, called - cd->start_code);
- code += 1 + LINK_SIZE;
-
- *code = OP_KET;
- PUT(code, 1, 2 + 2*LINK_SIZE);
- code += 1 + LINK_SIZE;
-
- length_prevgroup = 3 + 3*LINK_SIZE;
- }
-
- /* Can't determine a first byte now */
-
- if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
- continue;
-
-
- /* ------------------------------------------------------------ */
- default: /* Other characters: check option setting */
- OTHER_CHAR_AFTER_QUERY:
- set = unset = 0;
- optset = &set;
-
- while (*ptr != ')' && *ptr != ':')
- {
- switch (*ptr++)
- {
- case '-': optset = &unset; break;
-
- case 'J': /* Record that it changed in the external options */
- *optset |= PCRE_DUPNAMES;
- cd->external_flags |= PCRE_JCHANGED;
- break;
-
- case 'i': *optset |= PCRE_CASELESS; break;
- case 'm': *optset |= PCRE_MULTILINE; break;
- case 's': *optset |= PCRE_DOTALL; break;
- case 'x': *optset |= PCRE_EXTENDED; break;
- case 'U': *optset |= PCRE_UNGREEDY; break;
- case 'X': *optset |= PCRE_EXTRA; break;
-
- default: *errorcodeptr = ERR12;
- ptr--; /* Correct the offset */
- goto FAILED;
- }
- }
-
- /* Set up the changed option bits, but don't change anything yet. */
-
- newoptions = (options | set) & (~unset);
-
- /* If the options ended with ')' this is not the start of a nested
- group with option changes, so the options change at this level. If this
- item is right at the start of the pattern, the options can be
- abstracted and made external in the pre-compile phase, and ignored in
- the compile phase. This can be helpful when matching -- for instance in
- caseless checking of required bytes.
-
- If the code pointer is not (cd->start_code + 1 + LINK_SIZE), we are
- definitely *not* at the start of the pattern because something has been
- compiled. In the pre-compile phase, however, the code pointer can have
- that value after the start, because it gets reset as code is discarded
- during the pre-compile. However, this can happen only at top level - if
- we are within parentheses, the starting BRA will still be present. At
- any parenthesis level, the length value can be used to test if anything
- has been compiled at that level. Thus, a test for both these conditions
- is necessary to ensure we correctly detect the start of the pattern in
- both phases.
-
- If we are not at the pattern start, compile code to change the ims
- options if this setting actually changes any of them, and reset the
- greedy defaults and the case value for firstbyte and reqbyte. */
-
- if (*ptr == ')')
- {
- if (code == cd->start_code + 1 + LINK_SIZE &&
- (lengthptr == NULL || *lengthptr == 2 + 2*LINK_SIZE))
- {
- cd->external_options = newoptions;
- }
- else
- {
- if ((options & PCRE_IMS) != (newoptions & PCRE_IMS))
- {
- *code++ = OP_OPT;
- *code++ = newoptions & PCRE_IMS;
- }
- greedy_default = ((newoptions & PCRE_UNGREEDY) != 0);
- greedy_non_default = greedy_default ^ 1;
- req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS : 0;
- }
-
- /* Change options at this level, and pass them back for use
- in subsequent branches. When not at the start of the pattern, this
- information is also necessary so that a resetting item can be
- compiled at the end of a group (if we are in a group). */
-
- *optionsptr = options = newoptions;
- previous = NULL; /* This item can't be repeated */
- continue; /* It is complete */
- }
-
- /* If the options ended with ':' we are heading into a nested group
- with possible change of options. Such groups are non-capturing and are
- not assertions of any kind. All we need to do is skip over the ':';
- the newoptions value is handled below. */
-
- bravalue = OP_BRA;
- ptr++;
- } /* End of switch for character following (? */
- } /* End of (? handling */
-
- /* Opening parenthesis not followed by '?'. If PCRE_NO_AUTO_CAPTURE is set,
- all unadorned brackets become non-capturing and behave like (?:...)
- brackets. */
-
- else if ((options & PCRE_NO_AUTO_CAPTURE) != 0)
- {
- bravalue = OP_BRA;
- }
-
- /* Else we have a capturing group. */
-
- else
- {
- NUMBERED_GROUP:
- cd->bracount += 1;
- PUT2(code, 1+LINK_SIZE, cd->bracount);
- skipbytes = 2;
- }
-
- /* Process nested bracketed regex. Assertions may not be repeated, but
- other kinds can be. All their opcodes are >= OP_ONCE. We copy code into a
- non-register variable in order to be able to pass its address because some
- compilers complain otherwise. Pass in a new setting for the ims options if
- they have changed. */
-
- previous = (bravalue >= OP_ONCE)? code : NULL;
- *code = bravalue;
- tempcode = code;
- tempreqvary = cd->req_varyopt; /* Save value before bracket */
- length_prevgroup = 0; /* Initialize for pre-compile phase */
-
- if (!compile_regex(
- newoptions, /* The complete new option state */
- options & PCRE_IMS, /* The previous ims option state */
- &tempcode, /* Where to put code (updated) */
- &ptr, /* Input pointer (updated) */
- errorcodeptr, /* Where to put an error message */
- (bravalue == OP_ASSERTBACK ||
- bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */
- reset_bracount, /* True if (?| group */
- skipbytes, /* Skip over bracket number */
- &subfirstbyte, /* For possible first char */
- &subreqbyte, /* For possible last char */
- bcptr, /* Current branch chain */
- cd, /* Tables block */
- (lengthptr == NULL)? NULL : /* Actual compile phase */
- &length_prevgroup /* Pre-compile phase */
- ))
- goto FAILED;
-
- /* At the end of compiling, code is still pointing to the start of the
- group, while tempcode has been updated to point past the end of the group
- and any option resetting that may follow it. The pattern pointer (ptr)
- is on the bracket. */
-
- /* If this is a conditional bracket, check that there are no more than
- two branches in the group, or just one if it's a DEFINE group. We do this
- in the real compile phase, not in the pre-pass, where the whole group may
- not be available. */
-
- if (bravalue == OP_COND && lengthptr == NULL)
- {
- uschar *tc = code;
- int condcount = 0;
-
- do {
- condcount++;
- tc += GET(tc,1);
- }
- while (*tc != OP_KET);
-
- /* A DEFINE group is never obeyed inline (the "condition" is always
- false). It must have only one branch. */
-
- if (code[LINK_SIZE+1] == OP_DEF)
- {
- if (condcount > 1)
- {
- *errorcodeptr = ERR54;
- goto FAILED;
- }
- bravalue = OP_DEF; /* Just a flag to suppress char handling below */
- }
-
- /* A "normal" conditional group. If there is just one branch, we must not
- make use of its firstbyte or reqbyte, because this is equivalent to an
- empty second branch. */
-
- else
- {
- if (condcount > 2)
- {
- *errorcodeptr = ERR27;
- goto FAILED;
- }
- if (condcount == 1) subfirstbyte = subreqbyte = REQ_NONE;
- }
- }
-
- /* Error if hit end of pattern */
-
- if (*ptr != ')')
- {
- *errorcodeptr = ERR14;
- goto FAILED;
- }
-
- /* In the pre-compile phase, update the length by the length of the group,
- less the brackets at either end. Then reduce the compiled code to just a
- set of non-capturing brackets so that it doesn't use much memory if it is
- duplicated by a quantifier.*/
-
- if (lengthptr != NULL)
- {
- if (OFLOW_MAX - *lengthptr < length_prevgroup - 2 - 2*LINK_SIZE)
- {
- *errorcodeptr = ERR20;
- goto FAILED;
- }
- *lengthptr += length_prevgroup - 2 - 2*LINK_SIZE;
- *code++ = OP_BRA;
- PUTINC(code, 0, 1 + LINK_SIZE);
- *code++ = OP_KET;
- PUTINC(code, 0, 1 + LINK_SIZE);
- break; /* No need to waste time with special character handling */
- }
-
- /* Otherwise update the main code pointer to the end of the group. */
-
- code = tempcode;
-
- /* For a DEFINE group, required and first character settings are not
- relevant. */
-
- if (bravalue == OP_DEF) break;
-
- /* Handle updating of the required and first characters for other types of
- group. Update for normal brackets of all kinds, and conditions with two
- branches (see code above). If the bracket is followed by a quantifier with
- zero repeat, we have to back off. Hence the definition of zeroreqbyte and
- zerofirstbyte outside the main loop so that they can be accessed for the
- back off. */
-
- zeroreqbyte = reqbyte;
- zerofirstbyte = firstbyte;
- groupsetfirstbyte = FALSE;
-
- if (bravalue >= OP_ONCE)
- {
- /* If we have not yet set a firstbyte in this branch, take it from the
- subpattern, remembering that it was set here so that a repeat of more
- than one can replicate it as reqbyte if necessary. If the subpattern has
- no firstbyte, set "none" for the whole branch. In both cases, a zero
- repeat forces firstbyte to "none". */
-
- if (firstbyte == REQ_UNSET)
- {
- if (subfirstbyte >= 0)
- {
- firstbyte = subfirstbyte;
- groupsetfirstbyte = TRUE;
- }
- else firstbyte = REQ_NONE;
- zerofirstbyte = REQ_NONE;
- }
-
- /* If firstbyte was previously set, convert the subpattern's firstbyte
- into reqbyte if there wasn't one, using the vary flag that was in
- existence beforehand. */
-
- else if (subfirstbyte >= 0 && subreqbyte < 0)
- subreqbyte = subfirstbyte | tempreqvary;
-
- /* If the subpattern set a required byte (or set a first byte that isn't
- really the first byte - see above), set it. */
-
- if (subreqbyte >= 0) reqbyte = subreqbyte;
- }
-
- /* For a forward assertion, we take the reqbyte, if set. This can be
- helpful if the pattern that follows the assertion doesn't set a different
- char. For example, it's useful for /(?=abcde).+/. We can't set firstbyte
- for an assertion, however because it leads to incorrect effect for patterns
- such as /(?=a)a.+/ when the "real" "a" would then become a reqbyte instead
- of a firstbyte. This is overcome by a scan at the end if there's no
- firstbyte, looking for an asserted first char. */
-
- else if (bravalue == OP_ASSERT && subreqbyte >= 0) reqbyte = subreqbyte;
- break; /* End of processing '(' */
-
-
- /* ===================================================================*/
- /* Handle metasequences introduced by \. For ones like \d, the ESC_ values
- are arranged to be the negation of the corresponding OP_values. For the
- back references, the values are ESC_REF plus the reference number. Only
- back references and those types that consume a character may be repeated.
- We can test for values between ESC_b and ESC_Z for the latter; this may
- have to change if any new ones are ever created. */
-
- case '\\':
- tempptr = ptr;
- c = check_escape(&ptr, errorcodeptr, cd->bracount, options, FALSE);
- if (*errorcodeptr != 0) goto FAILED;
-
- if (c < 0)
- {
- if (-c == ESC_Q) /* Handle start of quoted string */
- {
- if (ptr[1] == '\\' && ptr[2] == 'E') ptr += 2; /* avoid empty string */
- else inescq = TRUE;
- continue;
- }
-
- if (-c == ESC_E) continue; /* Perl ignores an orphan \E */
-
- /* For metasequences that actually match a character, we disable the
- setting of a first character if it hasn't already been set. */
-
- if (firstbyte == REQ_UNSET && -c > ESC_b && -c < ESC_Z)
- firstbyte = REQ_NONE;
-
- /* Set values to reset to if this is followed by a zero repeat. */
-
- zerofirstbyte = firstbyte;
- zeroreqbyte = reqbyte;
-
- /* \g<name> or \g'name' is a subroutine call by name and \g<n> or \g'n'
- is a subroutine call by number (Oniguruma syntax). In fact, the value
- -ESC_g is returned only for these cases. So we don't need to check for <
- or ' if the value is -ESC_g. For the Perl syntax \g{n} the value is
- -ESC_REF+n, and for the Perl syntax \g{name} the result is -ESC_k (as
- that is a synonym for a named back reference). */
-
- if (-c == ESC_g)
- {
- const uschar *p;
- save_hwm = cd->hwm; /* Normally this is set when '(' is read */
- terminator = (*(++ptr) == '<')? '>' : '\'';
-
- /* These two statements stop the compiler for warning about possibly
- unset variables caused by the jump to HANDLE_NUMERICAL_RECURSION. In
- fact, because we actually check for a number below, the paths that
- would actually be in error are never taken. */
-
- skipbytes = 0;
- reset_bracount = FALSE;
-
- /* Test for a name */
-
- if (ptr[1] != '+' && ptr[1] != '-')
- {
- BOOL isnumber = TRUE;
- for (p = ptr + 1; *p != 0 && *p != terminator; p++)
- {
- if ((cd->ctypes[*p] & ctype_digit) == 0) isnumber = FALSE;
- if ((cd->ctypes[*p] & ctype_word) == 0) break;
- }
- if (*p != terminator)
- {
- *errorcodeptr = ERR57;
- break;
- }
- if (isnumber)
- {
- ptr++;
- goto HANDLE_NUMERICAL_RECURSION;
- }
- is_recurse = TRUE;
- goto NAMED_REF_OR_RECURSE;
- }
-
- /* Test a signed number in angle brackets or quotes. */
-
- p = ptr + 2;
- while (g_ascii_isdigit (*p) != 0) p++;
- if (*p != terminator)
- {
- *errorcodeptr = ERR57;
- break;
- }
- ptr++;
- goto HANDLE_NUMERICAL_RECURSION;
- }
-
- /* \k<name> or \k'name' is a back reference by name (Perl syntax).
- We also support \k{name} (.NET syntax) */
-
- if (-c == ESC_k && (ptr[1] == '<' || ptr[1] == '\'' || ptr[1] == '{'))
- {
- is_recurse = FALSE;
- terminator = (*(++ptr) == '<')? '>' : (*ptr == '\'')? '\'' : '}';
- goto NAMED_REF_OR_RECURSE;
- }
-
- /* Back references are handled specially; must disable firstbyte if
- not set to cope with cases like (?=(\w+))\1: which would otherwise set
- ':' later. */
-
- if (-c >= ESC_REF)
- {
- recno = -c - ESC_REF;
-
- HANDLE_REFERENCE: /* Come here from named backref handling */
- if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
- previous = code;
- *code++ = OP_REF;
- PUT2INC(code, 0, recno);
- cd->backref_map |= (recno < 32)? (1 << recno) : 1;
- if (recno > cd->top_backref) cd->top_backref = recno;
- }
-
- /* So are Unicode property matches, if supported. */
-
-#ifdef SUPPORT_UCP
- else if (-c == ESC_P || -c == ESC_p)
- {
- BOOL negated;
- int pdata;
- int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr);
- if (ptype < 0) goto FAILED;
- previous = code;
- *code++ = ((-c == ESC_p) != negated)? OP_PROP : OP_NOTPROP;
- *code++ = ptype;
- *code++ = pdata;
- }
-#else
-
- /* If Unicode properties are not supported, \X, \P, and \p are not
- allowed. */
-
- else if (-c == ESC_X || -c == ESC_P || -c == ESC_p)
- {
- *errorcodeptr = ERR45;
- goto FAILED;
- }
-#endif
-
- /* For the rest (including \X when Unicode properties are supported), we
- can obtain the OP value by negating the escape value. */
-
- else
- {
- previous = (-c > ESC_b && -c < ESC_Z)? code : NULL;
- *code++ = -c;
- }
- continue;
- }
-
- /* We have a data character whose value is in c. In UTF-8 mode it may have
- a value > 127. We set its representation in the length/buffer, and then
- handle it as a data character. */
-
-#ifdef SUPPORT_UTF8
- if (utf8 && c > 127)
- mclength = _pcre_ord2utf8(c, mcbuffer);
- else
-#endif
-
- {
- mcbuffer[0] = c;
- mclength = 1;
- }
- goto ONE_CHAR;
-
-
- /* ===================================================================*/
- /* Handle a literal character. It is guaranteed not to be whitespace or #
- when the extended flag is set. If we are in UTF-8 mode, it may be a
- multi-byte literal character. */
-
- default:
- NORMAL_CHAR:
- mclength = 1;
- mcbuffer[0] = c;
-
-#ifdef SUPPORT_UTF8
- if (utf8 && c >= 0xc0)
- {
- while ((ptr[1] & 0xc0) == 0x80)
- mcbuffer[mclength++] = *(++ptr);
- }
-#endif
-
- /* At this point we have the character's bytes in mcbuffer, and the length
- in mclength. When not in UTF-8 mode, the length is always 1. */
-
- ONE_CHAR:
- previous = code;
- *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARNC : OP_CHAR;
- for (c = 0; c < mclength; c++) *code++ = mcbuffer[c];
-
- /* Remember if \r or \n were seen */
-
- if (mcbuffer[0] == '\r' || mcbuffer[0] == '\n')
- cd->external_flags |= PCRE_HASCRORLF;
-
- /* Set the first and required bytes appropriately. If no previous first
- byte, set it from this character, but revert to none on a zero repeat.
- Otherwise, leave the firstbyte value alone, and don't change it on a zero
- repeat. */
-
- if (firstbyte == REQ_UNSET)
- {
- zerofirstbyte = REQ_NONE;
- zeroreqbyte = reqbyte;
-
- /* If the character is more than one byte long, we can set firstbyte
- only if it is not to be matched caselessly. */
-
- if (mclength == 1 || req_caseopt == 0)
- {
- firstbyte = mcbuffer[0] | req_caseopt;
- if (mclength != 1) reqbyte = code[-1] | cd->req_varyopt;
- }
- else firstbyte = reqbyte = REQ_NONE;
- }
-
- /* firstbyte was previously set; we can set reqbyte only the length is
- 1 or the matching is caseful. */
-
- else
- {
- zerofirstbyte = firstbyte;
- zeroreqbyte = reqbyte;
- if (mclength == 1 || req_caseopt == 0)
- reqbyte = code[-1] | req_caseopt | cd->req_varyopt;
- }
-
- break; /* End of literal character handling */
- }
- } /* end of big loop */
-
-
-/* Control never reaches here by falling through, only by a goto for all the
-error states. Pass back the position in the pattern so that it can be displayed
-to the user for diagnosing the error. */
-
-FAILED:
-*ptrptr = ptr;
-return FALSE;
-}
-
-
-
-
-/*************************************************
-* Compile sequence of alternatives *
-*************************************************/
-
-/* On entry, ptr is pointing past the bracket character, but on return it
-points to the closing bracket, or vertical bar, or end of string. The code
-variable is pointing at the byte into which the BRA operator has been stored.
-If the ims options are changed at the start (for a (?ims: group) or during any
-branch, we need to insert an OP_OPT item at the start of every following branch
-to ensure they get set correctly at run time, and also pass the new options
-into every subsequent branch compile.
-
-This function is used during the pre-compile phase when we are trying to find
-out the amount of memory needed, as well as during the real compile phase. The
-value of lengthptr distinguishes the two phases.
-
-Arguments:
- options option bits, including any changes for this subpattern
- oldims previous settings of ims option bits
- codeptr -> the address of the current code pointer
- ptrptr -> the address of the current pattern pointer
- errorcodeptr -> pointer to error code variable
- lookbehind TRUE if this is a lookbehind assertion
- reset_bracount TRUE to reset the count for each branch
- skipbytes skip this many bytes at start (for brackets and OP_COND)
- firstbyteptr place to put the first required character, or a negative number
- reqbyteptr place to put the last required character, or a negative number
- bcptr pointer to the chain of currently open branches
- cd points to the data block with tables pointers etc.
- lengthptr NULL during the real compile phase
- points to length accumulator during pre-compile phase
-
-Returns: TRUE on success
-*/
-
-static BOOL
-compile_regex(int options, int oldims, uschar **codeptr, const uschar **ptrptr,
- int *errorcodeptr, BOOL lookbehind, BOOL reset_bracount, int skipbytes,
- int *firstbyteptr, int *reqbyteptr, branch_chain *bcptr, compile_data *cd,
- int *lengthptr)
-{
-const uschar *ptr = *ptrptr;
-uschar *code = *codeptr;
-uschar *last_branch = code;
-uschar *start_bracket = code;
-uschar *reverse_count = NULL;
-int firstbyte, reqbyte;
-int branchfirstbyte, branchreqbyte;
-int length;
-int orig_bracount;
-int max_bracount;
-branch_chain bc;
-
-bc.outer = bcptr;
-bc.current = code;
-
-firstbyte = reqbyte = REQ_UNSET;
-
-/* Accumulate the length for use in the pre-compile phase. Start with the
-length of the BRA and KET and any extra bytes that are required at the
-beginning. We accumulate in a local variable to save frequent testing of
-lenthptr for NULL. We cannot do this by looking at the value of code at the
-start and end of each alternative, because compiled items are discarded during
-the pre-compile phase so that the work space is not exceeded. */
-
-length = 2 + 2*LINK_SIZE + skipbytes;
-
-/* WARNING: If the above line is changed for any reason, you must also change
-the code that abstracts option settings at the start of the pattern and makes
-them global. It tests the value of length for (2 + 2*LINK_SIZE) in the
-pre-compile phase to find out whether anything has yet been compiled or not. */
-
-/* Offset is set zero to mark that this bracket is still open */
-
-PUT(code, 1, 0);
-code += 1 + LINK_SIZE + skipbytes;
-
-/* Loop for each alternative branch */
-
-orig_bracount = max_bracount = cd->bracount;
-for (;;)
- {
- /* For a (?| group, reset the capturing bracket count so that each branch
- uses the same numbers. */
-
- if (reset_bracount) cd->bracount = orig_bracount;
-
- /* Handle a change of ims options at the start of the branch */
-
- if ((options & PCRE_IMS) != oldims)
- {
- *code++ = OP_OPT;
- *code++ = options & PCRE_IMS;
- length += 2;
- }
-
- /* Set up dummy OP_REVERSE if lookbehind assertion */
-
- if (lookbehind)
- {
- *code++ = OP_REVERSE;
- reverse_count = code;
- PUTINC(code, 0, 0);
- length += 1 + LINK_SIZE;
- }
-
- /* Now compile the branch; in the pre-compile phase its length gets added
- into the length. */
-
- if (!compile_branch(&options, &code, &ptr, errorcodeptr, &branchfirstbyte,
- &branchreqbyte, &bc, cd, (lengthptr == NULL)? NULL : &length))
- {
- *ptrptr = ptr;
- return FALSE;
- }
-
- /* Keep the highest bracket count in case (?| was used and some branch
- has fewer than the rest. */
-
- if (cd->bracount > max_bracount) max_bracount = cd->bracount;
-
- /* In the real compile phase, there is some post-processing to be done. */
-
- if (lengthptr == NULL)
- {
- /* If this is the first branch, the firstbyte and reqbyte values for the
- branch become the values for the regex. */
-
- if (*last_branch != OP_ALT)
- {
- firstbyte = branchfirstbyte;
- reqbyte = branchreqbyte;
- }
-
- /* If this is not the first branch, the first char and reqbyte have to
- match the values from all the previous branches, except that if the
- previous value for reqbyte didn't have REQ_VARY set, it can still match,
- and we set REQ_VARY for the regex. */
-
- else
- {
- /* If we previously had a firstbyte, but it doesn't match the new branch,
- we have to abandon the firstbyte for the regex, but if there was
- previously no reqbyte, it takes on the value of the old firstbyte. */
-
- if (firstbyte >= 0 && firstbyte != branchfirstbyte)
- {
- if (reqbyte < 0) reqbyte = firstbyte;
- firstbyte = REQ_NONE;
- }
-
- /* If we (now or from before) have no firstbyte, a firstbyte from the
- branch becomes a reqbyte if there isn't a branch reqbyte. */
-
- if (firstbyte < 0 && branchfirstbyte >= 0 && branchreqbyte < 0)
- branchreqbyte = branchfirstbyte;
-
- /* Now ensure that the reqbytes match */
-
- if ((reqbyte & ~REQ_VARY) != (branchreqbyte & ~REQ_VARY))
- reqbyte = REQ_NONE;
- else reqbyte |= branchreqbyte; /* To "or" REQ_VARY */
- }
-
- /* If lookbehind, check that this branch matches a fixed-length string, and
- put the length into the OP_REVERSE item. Temporarily mark the end of the
- branch with OP_END. */
-
- if (lookbehind)
- {
- int fixed_length;
- *code = OP_END;
- fixed_length = find_fixedlength(last_branch, options);
- DPRINTF(("fixed length = %d\n", fixed_length));
- if (fixed_length < 0)
- {
- *errorcodeptr = (fixed_length == -2)? ERR36 : ERR25;
- *ptrptr = ptr;
- return FALSE;
- }
- PUT(reverse_count, 0, fixed_length);
- }
- }
-
- /* Reached end of expression, either ')' or end of pattern. In the real
- compile phase, go back through the alternative branches and reverse the chain
- of offsets, with the field in the BRA item now becoming an offset to the
- first alternative. If there are no alternatives, it points to the end of the
- group. The length in the terminating ket is always the length of the whole
- bracketed item. If any of the ims options were changed inside the group,
- compile a resetting op-code following, except at the very end of the pattern.
- Return leaving the pointer at the terminating char. */
-
- if (*ptr != '|')
- {
- if (lengthptr == NULL)
- {
- int branch_length = code - last_branch;
- do
- {
- int prev_length = GET(last_branch, 1);
- PUT(last_branch, 1, branch_length);
- branch_length = prev_length;
- last_branch -= branch_length;
- }
- while (branch_length > 0);
- }
-
- /* Fill in the ket */
-
- *code = OP_KET;
- PUT(code, 1, code - start_bracket);
- code += 1 + LINK_SIZE;
-
- /* Resetting option if needed */
-
- if ((options & PCRE_IMS) != oldims && *ptr == ')')
- {
- *code++ = OP_OPT;
- *code++ = oldims;
- length += 2;
- }
-
- /* Retain the highest bracket number, in case resetting was used. */
-
- cd->bracount = max_bracount;
-
- /* Set values to pass back */
-
- *codeptr = code;
- *ptrptr = ptr;
- *firstbyteptr = firstbyte;
- *reqbyteptr = reqbyte;
- if (lengthptr != NULL)
- {
- if (OFLOW_MAX - *lengthptr < length)
- {
- *errorcodeptr = ERR20;
- return FALSE;
- }
- *lengthptr += length;
- }
- return TRUE;
- }
-
- /* Another branch follows. In the pre-compile phase, we can move the code
- pointer back to where it was for the start of the first branch. (That is,
- pretend that each branch is the only one.)
-
- In the real compile phase, insert an ALT node. Its length field points back
- to the previous branch while the bracket remains open. At the end the chain
- is reversed. It's done like this so that the start of the bracket has a
- zero offset until it is closed, making it possible to detect recursion. */
-
- if (lengthptr != NULL)
- {
- code = *codeptr + 1 + LINK_SIZE + skipbytes;
- length += 1 + LINK_SIZE;
- }
- else
- {
- *code = OP_ALT;
- PUT(code, 1, code - last_branch);
- bc.current = last_branch = code;
- code += 1 + LINK_SIZE;
- }
-
- ptr++;
- }
-/* Control never reaches here */
-}
-
-
-
-
-/*************************************************
-* Check for anchored expression *
-*************************************************/
-
-/* Try to find out if this is an anchored regular expression. Consider each
-alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket
-all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then
-it's anchored. However, if this is a multiline pattern, then only OP_SOD
-counts, since OP_CIRC can match in the middle.
-
-We can also consider a regex to be anchored if OP_SOM starts all its branches.
-This is the code for \G, which means "match at start of match position, taking
-into account the match offset".
-
-A branch is also implicitly anchored if it starts with .* and DOTALL is set,
-because that will try the rest of the pattern at all possible matching points,
-so there is no point trying again.... er ....
-
-.... except when the .* appears inside capturing parentheses, and there is a
-subsequent back reference to those parentheses. We haven't enough information
-to catch that case precisely.
-
-At first, the best we could do was to detect when .* was in capturing brackets
-and the highest back reference was greater than or equal to that level.
-However, by keeping a bitmap of the first 31 back references, we can catch some
-of the more common cases more precisely.
-
-Arguments:
- code points to start of expression (the bracket)
- options points to the options setting
- bracket_map a bitmap of which brackets we are inside while testing; this
- handles up to substring 31; after that we just have to take
- the less precise approach
- backref_map the back reference bitmap
-
-Returns: TRUE or FALSE
-*/
-
-static BOOL
-is_anchored(register const uschar *code, int *options, unsigned int bracket_map,
- unsigned int backref_map)
-{
-do {
- const uschar *scode = first_significant_code(code + _pcre_OP_lengths[*code],
- options, PCRE_MULTILINE, FALSE);
- register int op = *scode;
-
- /* Non-capturing brackets */
-
- if (op == OP_BRA)
- {
- if (!is_anchored(scode, options, bracket_map, backref_map)) return FALSE;
- }
-
- /* Capturing brackets */
-
- else if (op == OP_CBRA)
- {
- int n = GET2(scode, 1+LINK_SIZE);
- int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
- if (!is_anchored(scode, options, new_map, backref_map)) return FALSE;
- }
-
- /* Other brackets */
-
- else if (op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
- {
- if (!is_anchored(scode, options, bracket_map, backref_map)) return FALSE;
- }
-
- /* .* is not anchored unless DOTALL is set (which generates OP_ALLANY) and
- it isn't in brackets that are or may be referenced. */
-
- else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR ||
- op == OP_TYPEPOSSTAR))
- {
- if (scode[1] != OP_ALLANY || (bracket_map & backref_map) != 0)
- return FALSE;
- }
-
- /* Check for explicit anchoring */
-
- else if (op != OP_SOD && op != OP_SOM &&
- ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC))
- return FALSE;
- code += GET(code, 1);
- }
-while (*code == OP_ALT); /* Loop for each alternative */
-return TRUE;
-}
-
-
-
-/*************************************************
-* Check for starting with ^ or .* *
-*************************************************/
-
-/* This is called to find out if every branch starts with ^ or .* so that
-"first char" processing can be done to speed things up in multiline
-matching and for non-DOTALL patterns that start with .* (which must start at
-the beginning or after \n). As in the case of is_anchored() (see above), we
-have to take account of back references to capturing brackets that contain .*
-because in that case we can't make the assumption.
-
-Arguments:
- code points to start of expression (the bracket)
- bracket_map a bitmap of which brackets we are inside while testing; this
- handles up to substring 31; after that we just have to take
- the less precise approach
- backref_map the back reference bitmap
-
-Returns: TRUE or FALSE
-*/
-
-static BOOL
-is_startline(const uschar *code, unsigned int bracket_map,
- unsigned int backref_map)
-{
-do {
- const uschar *scode = first_significant_code(code + _pcre_OP_lengths[*code],
- NULL, 0, FALSE);
- register int op = *scode;
-
- /* Non-capturing brackets */
-
- if (op == OP_BRA)
- {
- if (!is_startline(scode, bracket_map, backref_map)) return FALSE;
- }
-
- /* Capturing brackets */
-
- else if (op == OP_CBRA)
- {
- int n = GET2(scode, 1+LINK_SIZE);
- int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
- if (!is_startline(scode, new_map, backref_map)) return FALSE;
- }
-
- /* Other brackets */
-
- else if (op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
- { if (!is_startline(scode, bracket_map, backref_map)) return FALSE; }
-
- /* .* means "start at start or after \n" if it isn't in brackets that
- may be referenced. */
-
- else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR)
- {
- if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE;
- }
-
- /* Check for explicit circumflex */
-
- else if (op != OP_CIRC) return FALSE;
-
- /* Move on to the next alternative */
-
- code += GET(code, 1);
- }
-while (*code == OP_ALT); /* Loop for each alternative */
-return TRUE;
-}
-
-
-
-/*************************************************
-* Check for asserted fixed first char *
-*************************************************/
-
-/* During compilation, the "first char" settings from forward assertions are
-discarded, because they can cause conflicts with actual literals that follow.
-However, if we end up without a first char setting for an unanchored pattern,
-it is worth scanning the regex to see if there is an initial asserted first
-char. If all branches start with the same asserted char, or with a bracket all
-of whose alternatives start with the same asserted char (recurse ad lib), then
-we return that char, otherwise -1.
-
-Arguments:
- code points to start of expression (the bracket)
- options pointer to the options (used to check casing changes)
- inassert TRUE if in an assertion
-
-Returns: -1 or the fixed first char
-*/
-
-static int
-find_firstassertedchar(const uschar *code, int *options, BOOL inassert)
-{
-register int c = -1;
-do {
- int d;
- const uschar *scode =
- first_significant_code(code + 1+LINK_SIZE, options, PCRE_CASELESS, TRUE);
- register int op = *scode;
-
- switch(op)
- {
- default:
- return -1;
-
- case OP_BRA:
- case OP_CBRA:
- case OP_ASSERT:
- case OP_ONCE:
- case OP_COND:
- if ((d = find_firstassertedchar(scode, options, op == OP_ASSERT)) < 0)
- return -1;
- if (c < 0) c = d; else if (c != d) return -1;
- break;
-
- case OP_EXACT: /* Fall through */
- scode += 2;
-
- case OP_CHAR:
- case OP_CHARNC:
- case OP_PLUS:
- case OP_MINPLUS:
- case OP_POSPLUS:
- if (!inassert) return -1;
- if (c < 0)
- {
- c = scode[1];
- if ((*options & PCRE_CASELESS) != 0) c |= REQ_CASELESS;
- }
- else if (c != scode[1]) return -1;
- break;
- }
-
- code += GET(code, 1);
- }
-while (*code == OP_ALT);
-return c;
-}
-
-
-
-/*************************************************
-* Compile a Regular Expression *
-*************************************************/
-
-/* This function takes a string and returns a pointer to a block of store
-holding a compiled version of the expression. The original API for this
-function had no error code return variable; it is retained for backwards
-compatibility. The new function is given a new name.
-
-Arguments:
- pattern the regular expression
- options various option bits
- errorcodeptr pointer to error code variable (pcre_compile2() only)
- can be NULL if you don't want a code value
- errorptr pointer to pointer to error text
- erroroffset ptr offset in pattern where error was detected
- tables pointer to character tables or NULL
-
-Returns: pointer to compiled data block, or NULL on error,
- with errorptr and erroroffset set
-*/
-
-PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION
-pcre_compile(const char *pattern, int options, const char **errorptr,
- int *erroroffset, const unsigned char *tables)
-{
-return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
-}
-
-
-PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION
-pcre_compile2(const char *pattern, int options, int *errorcodeptr,
- const char **errorptr, int *erroroffset, const unsigned char *tables)
-{
-real_pcre *re;
-int length = 1; /* For final END opcode */
-int firstbyte, reqbyte, newline;
-int errorcode = 0;
-int skipatstart = 0;
-#ifdef SUPPORT_UTF8
-BOOL utf8;
-#endif
-size_t size;
-uschar *code;
-const uschar *codestart;
-const uschar *ptr;
-compile_data compile_block;
-compile_data *cd = &compile_block;
-
-/* This space is used for "compiling" into during the first phase, when we are
-computing the amount of memory that is needed. Compiled items are thrown away
-as soon as possible, so that a fairly large buffer should be sufficient for
-this purpose. The same space is used in the second phase for remembering where
-to fill in forward references to subpatterns. */
-
-uschar cworkspace[COMPILE_WORK_SIZE];
-
-/* Set this early so that early errors get offset 0. */
-
-ptr = (const uschar *)pattern;
-
-/* We can't pass back an error message if errorptr is NULL; I guess the best we
-can do is just return NULL, but we can set a code value if there is a code
-pointer. */
-
-if (errorptr == NULL)
- {
- if (errorcodeptr != NULL) *errorcodeptr = 99;
- return NULL;
- }
-
-*errorptr = NULL;
-if (errorcodeptr != NULL) *errorcodeptr = ERR0;
-
-/* However, we can give a message for this error */
-
-if (erroroffset == NULL)
- {
- errorcode = ERR16;
- goto PCRE_EARLY_ERROR_RETURN2;
- }
-
-*erroroffset = 0;
-
-/* Can't support UTF8 unless PCRE has been compiled to include the code. */
-
-#ifdef SUPPORT_UTF8
-utf8 = (options & PCRE_UTF8) != 0;
-if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0 &&
- (*erroroffset = _pcre_valid_utf8((uschar *)pattern, -1)) >= 0)
- {
- errorcode = ERR44;
- goto PCRE_EARLY_ERROR_RETURN2;
- }
-#else
-if ((options & PCRE_UTF8) != 0)
- {
- errorcode = ERR32;
- goto PCRE_EARLY_ERROR_RETURN;
- }
-#endif
-
-if ((options & ~PUBLIC_OPTIONS) != 0)
- {
- errorcode = ERR17;
- goto PCRE_EARLY_ERROR_RETURN;
- }
-
-/* Set up pointers to the individual character tables */
-
-if (tables == NULL) tables = _pcre_default_tables;
-cd->lcc = tables + lcc_offset;
-cd->fcc = tables + fcc_offset;
-cd->cbits = tables + cbits_offset;
-cd->ctypes = tables + ctypes_offset;
-
-/* Check for global one-time settings at the start of the pattern, and remember
-the offset for later. */
-
-while (ptr[skipatstart] == '(' && ptr[skipatstart+1] == '*')
- {
- int newnl = 0;
- int newbsr = 0;
-
- if (strncmp((char *)(ptr+skipatstart+2), "CR)", 3) == 0)
- { skipatstart += 5; newnl = PCRE_NEWLINE_CR; }
- else if (strncmp((char *)(ptr+skipatstart+2), "LF)", 3) == 0)
- { skipatstart += 5; newnl = PCRE_NEWLINE_LF; }
- else if (strncmp((char *)(ptr+skipatstart+2), "CRLF)", 5) == 0)
- { skipatstart += 7; newnl = PCRE_NEWLINE_CR + PCRE_NEWLINE_LF; }
- else if (strncmp((char *)(ptr+skipatstart+2), "ANY)", 4) == 0)
- { skipatstart += 6; newnl = PCRE_NEWLINE_ANY; }
- else if (strncmp((char *)(ptr+skipatstart+2), "ANYCRLF)", 8) == 0)
- { skipatstart += 10; newnl = PCRE_NEWLINE_ANYCRLF; }
-
- else if (strncmp((char *)(ptr+skipatstart+2), "BSR_ANYCRLF)", 12) == 0)
- { skipatstart += 14; newbsr = PCRE_BSR_ANYCRLF; }
- else if (strncmp((char *)(ptr+skipatstart+2), "BSR_UNICODE)", 12) == 0)
- { skipatstart += 14; newbsr = PCRE_BSR_UNICODE; }
-
- if (newnl != 0)
- options = (options & ~PCRE_NEWLINE_BITS) | newnl;
- else if (newbsr != 0)
- options = (options & ~(PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) | newbsr;
- else break;
- }
-
-/* Check validity of \R options. */
-
-switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE))
- {
- case 0:
- case PCRE_BSR_ANYCRLF:
- case PCRE_BSR_UNICODE:
- break;
- default: errorcode = ERR56; goto PCRE_EARLY_ERROR_RETURN;
- }
-
-/* Handle different types of newline. The three bits give seven cases. The
-current code allows for fixed one- or two-byte sequences, plus "any" and
-"anycrlf". */
-
-switch (options & PCRE_NEWLINE_BITS)
- {
- case 0: newline = NEWLINE; break; /* Build-time default */
- case PCRE_NEWLINE_CR: newline = '\r'; break;
- case PCRE_NEWLINE_LF: newline = '\n'; break;
- case PCRE_NEWLINE_CR+
- PCRE_NEWLINE_LF: newline = ('\r' << 8) | '\n'; break;
- case PCRE_NEWLINE_ANY: newline = -1; break;
- case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
- default: errorcode = ERR56; goto PCRE_EARLY_ERROR_RETURN;
- }
-
-if (newline == -2)
- {
- cd->nltype = NLTYPE_ANYCRLF;
- }
-else if (newline < 0)
- {
- cd->nltype = NLTYPE_ANY;
- }
-else
- {
- cd->nltype = NLTYPE_FIXED;
- if (newline > 255)
- {
- cd->nllen = 2;
- cd->nl[0] = (newline >> 8) & 255;
- cd->nl[1] = newline & 255;
- }
- else
- {
- cd->nllen = 1;
- cd->nl[0] = newline;
- }
- }
-
-/* Maximum back reference and backref bitmap. The bitmap records up to 31 back
-references to help in deciding whether (.*) can be treated as anchored or not.
-*/
-
-cd->top_backref = 0;
-cd->backref_map = 0;
-
-/* Reflect pattern for debugging output */
-
-DPRINTF(("------------------------------------------------------------------\n"));
-DPRINTF(("%s\n", pattern));
-
-/* Pretend to compile the pattern while actually just accumulating the length
-of memory required. This behaviour is triggered by passing a non-NULL final
-argument to compile_regex(). We pass a block of workspace (cworkspace) for it
-to compile parts of the pattern into; the compiled code is discarded when it is
-no longer needed, so hopefully this workspace will never overflow, though there
-is a test for its doing so. */
-
-cd->bracount = cd->final_bracount = 0;
-cd->names_found = 0;
-cd->name_entry_size = 0;
-cd->name_table = NULL;
-cd->start_workspace = cworkspace;
-cd->start_code = cworkspace;
-cd->hwm = cworkspace;
-cd->start_pattern = (const uschar *)pattern;
-cd->end_pattern = (const uschar *)(pattern + strlen(pattern));
-cd->req_varyopt = 0;
-cd->external_options = options;
-cd->external_flags = 0;
-
-/* Now do the pre-compile. On error, errorcode will be set non-zero, so we
-don't need to look at the result of the function here. The initial options have
-been put into the cd block so that they can be changed if an option setting is
-found within the regex right at the beginning. Bringing initial option settings
-outside can help speed up starting point checks. */
-
-ptr += skipatstart;
-code = cworkspace;
-*code = OP_BRA;
-(void)compile_regex(cd->external_options, cd->external_options & PCRE_IMS,
- &code, &ptr, &errorcode, FALSE, FALSE, 0, &firstbyte, &reqbyte, NULL, cd,
- &length);
-if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN;
-
-DPRINTF(("end pre-compile: length=%d workspace=%d\n", length,
- cd->hwm - cworkspace));
-
-if (length > MAX_PATTERN_SIZE)
- {
- errorcode = ERR20;
- goto PCRE_EARLY_ERROR_RETURN;
- }
-
-/* Compute the size of data block needed and get it, either from malloc or
-externally provided function. Integer overflow should no longer be possible
-because nowadays we limit the maximum value of cd->names_found and
-cd->name_entry_size. */
-
-size = length + sizeof(real_pcre) + cd->names_found * (cd->name_entry_size + 3);
-re = (real_pcre *)(pcre_malloc)(size);
-
-if (re == NULL)
- {
- errorcode = ERR21;
- goto PCRE_EARLY_ERROR_RETURN;
- }
-
-/* Put in the magic number, and save the sizes, initial options, internal
-flags, and character table pointer. NULL is used for the default character
-tables. The nullpad field is at the end; it's there to help in the case when a
-regex compiled on a system with 4-byte pointers is run on another with 8-byte
-pointers. */
-
-re->magic_number = MAGIC_NUMBER;
-re->size = size;
-re->options = cd->external_options;
-re->flags = cd->external_flags;
-re->dummy1 = 0;
-re->first_byte = 0;
-re->req_byte = 0;
-re->name_table_offset = sizeof(real_pcre);
-re->name_entry_size = cd->name_entry_size;
-re->name_count = cd->names_found;
-re->ref_count = 0;
-re->tables = (tables == _pcre_default_tables)? NULL : tables;
-re->nullpad = NULL;
-
-/* The starting points of the name/number translation table and of the code are
-passed around in the compile data block. The start/end pattern and initial
-options are already set from the pre-compile phase, as is the name_entry_size
-field. Reset the bracket count and the names_found field. Also reset the hwm
-field; this time it's used for remembering forward references to subpatterns.
-*/
-
-cd->final_bracount = cd->bracount; /* Save for checking forward references */
-cd->bracount = 0;
-cd->names_found = 0;
-cd->name_table = (uschar *)re + re->name_table_offset;
-codestart = cd->name_table + re->name_entry_size * re->name_count;
-cd->start_code = codestart;
-cd->hwm = cworkspace;
-cd->req_varyopt = 0;
-cd->had_accept = FALSE;
-
-/* Set up a starting, non-extracting bracket, then compile the expression. On
-error, errorcode will be set non-zero, so we don't need to look at the result
-of the function here. */
-
-ptr = (const uschar *)pattern + skipatstart;
-code = (uschar *)codestart;
-*code = OP_BRA;
-(void)compile_regex(re->options, re->options & PCRE_IMS, &code, &ptr,
- &errorcode, FALSE, FALSE, 0, &firstbyte, &reqbyte, NULL, cd, NULL);
-re->top_bracket = cd->bracount;
-re->top_backref = cd->top_backref;
-re->flags = cd->external_flags;
-
-if (cd->had_accept) reqbyte = -1; /* Must disable after (*ACCEPT) */
-
-/* If not reached end of pattern on success, there's an excess bracket. */
-
-if (errorcode == 0 && *ptr != 0) errorcode = ERR22;
-
-/* Fill in the terminating state and check for disastrous overflow, but
-if debugging, leave the test till after things are printed out. */
-
-*code++ = OP_END;
-
-#ifndef DEBUG
-if (code - codestart > length) errorcode = ERR23;
-#endif
-
-/* Fill in any forward references that are required. */
-
-while (errorcode == 0 && cd->hwm > cworkspace)
- {
- int offset, recno;
- const uschar *groupptr;
- cd->hwm -= LINK_SIZE;
- offset = GET(cd->hwm, 0);
- recno = GET(codestart, offset);
- groupptr = find_bracket(codestart, (re->options & PCRE_UTF8) != 0, recno);
- if (groupptr == NULL) errorcode = ERR53;
- else PUT(((uschar *)codestart), offset, groupptr - codestart);
- }
-
-/* Give an error if there's back reference to a non-existent capturing
-subpattern. */
-
-if (errorcode == 0 && re->top_backref > re->top_bracket) errorcode = ERR15;
-
-/* Failed to compile, or error while post-processing */
-
-if (errorcode != 0)
- {
- (pcre_free)(re);
- PCRE_EARLY_ERROR_RETURN:
- *erroroffset = ptr - (const uschar *)pattern;
- PCRE_EARLY_ERROR_RETURN2:
- *errorptr = find_error_text(errorcode);
- if (errorcodeptr != NULL) *errorcodeptr = errorcode;
- return NULL;
- }
-
-/* If the anchored option was not passed, set the flag if we can determine that
-the pattern is anchored by virtue of ^ characters or \A or anything else (such
-as starting with .* when DOTALL is set).
-
-Otherwise, if we know what the first byte has to be, save it, because that
-speeds up unanchored matches no end. If not, see if we can set the
-PCRE_STARTLINE flag. This is helpful for multiline matches when all branches
-start with ^. and also when all branches start with .* for non-DOTALL matches.
-*/
-
-if ((re->options & PCRE_ANCHORED) == 0)
- {
- int temp_options = re->options; /* May get changed during these scans */
- if (is_anchored(codestart, &temp_options, 0, cd->backref_map))
- re->options |= PCRE_ANCHORED;
- else
- {
- if (firstbyte < 0)
- firstbyte = find_firstassertedchar(codestart, &temp_options, FALSE);
- if (firstbyte >= 0) /* Remove caseless flag for non-caseable chars */
- {
- int ch = firstbyte & 255;
- re->first_byte = ((firstbyte & REQ_CASELESS) != 0 &&
- cd->fcc[ch] == ch)? ch : firstbyte;
- re->flags |= PCRE_FIRSTSET;
- }
- else if (is_startline(codestart, 0, cd->backref_map))
- re->flags |= PCRE_STARTLINE;
- }
- }
-
-/* For an anchored pattern, we use the "required byte" only if it follows a
-variable length item in the regex. Remove the caseless flag for non-caseable
-bytes. */
-
-if (reqbyte >= 0 &&
- ((re->options & PCRE_ANCHORED) == 0 || (reqbyte & REQ_VARY) != 0))
- {
- int ch = reqbyte & 255;
- re->req_byte = ((reqbyte & REQ_CASELESS) != 0 &&
- cd->fcc[ch] == ch)? (reqbyte & ~REQ_CASELESS) : reqbyte;
- re->flags |= PCRE_REQCHSET;
- }
-
-/* Print out the compiled data if debugging is enabled. This is never the
-case when building a production library. */
-
-#ifdef DEBUG
-
-printf("Length = %d top_bracket = %d top_backref = %d\n",
- length, re->top_bracket, re->top_backref);
-
-printf("Options=%08x\n", re->options);
-
-if ((re->flags & PCRE_FIRSTSET) != 0)
- {
- int ch = re->first_byte & 255;
- const char *caseless = ((re->first_byte & REQ_CASELESS) == 0)?
- "" : " (caseless)";
- if (isprint(ch)) printf("First char = %c%s\n", ch, caseless);
- else printf("First char = \\x%02x%s\n", ch, caseless);
- }
-
-if ((re->flags & PCRE_REQCHSET) != 0)
- {
- int ch = re->req_byte & 255;
- const char *caseless = ((re->req_byte & REQ_CASELESS) == 0)?
- "" : " (caseless)";
- if (isprint(ch)) printf("Req char = %c%s\n", ch, caseless);
- else printf("Req char = \\x%02x%s\n", ch, caseless);
- }
-
-pcre_printint(re, stdout, TRUE);
-
-/* This check is done here in the debugging case so that the code that
-was compiled can be seen. */
-
-if (code - codestart > length)
- {
- (pcre_free)(re);
- *errorptr = find_error_text(ERR23);
- *erroroffset = ptr - (uschar *)pattern;
- if (errorcodeptr != NULL) *errorcodeptr = ERR23;
- return NULL;
- }
-#endif /* DEBUG */
-
-return (pcre *)re;
-}
-
-/* End of pcre_compile.c */
diff --git a/glib/pcre/pcre_config.c b/glib/pcre/pcre_config.c
deleted file mode 100644
index 114f0fb7a..000000000
--- a/glib/pcre/pcre_config.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains the external function pcre_config(). */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-/*************************************************
-* Return info about what features are configured *
-*************************************************/
-
-/* This function has an extensible interface so that additional items can be
-added compatibly.
-
-Arguments:
- what what information is required
- where where to put the information
-
-Returns: 0 if data returned, negative on error
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_config(int what, void *where)
-{
-switch (what)
- {
- case PCRE_CONFIG_UTF8:
-#ifdef SUPPORT_UTF8
- *((int *)where) = 1;
-#else
- *((int *)where) = 0;
-#endif
- break;
-
- case PCRE_CONFIG_UNICODE_PROPERTIES:
-#ifdef SUPPORT_UCP
- *((int *)where) = 1;
-#else
- *((int *)where) = 0;
-#endif
- break;
-
- case PCRE_CONFIG_NEWLINE:
- *((int *)where) = NEWLINE;
- break;
-
- case PCRE_CONFIG_BSR:
-#ifdef BSR_ANYCRLF
- *((int *)where) = 1;
-#else
- *((int *)where) = 0;
-#endif
- break;
-
- case PCRE_CONFIG_LINK_SIZE:
- *((int *)where) = LINK_SIZE;
- break;
-
- case PCRE_CONFIG_POSIX_MALLOC_THRESHOLD:
- *((int *)where) = POSIX_MALLOC_THRESHOLD;
- break;
-
- case PCRE_CONFIG_MATCH_LIMIT:
- *((unsigned int *)where) = MATCH_LIMIT;
- break;
-
- case PCRE_CONFIG_MATCH_LIMIT_RECURSION:
- *((unsigned int *)where) = MATCH_LIMIT_RECURSION;
- break;
-
- case PCRE_CONFIG_STACKRECURSE:
-#ifdef NO_RECURSE
- *((int *)where) = 0;
-#else
- *((int *)where) = 1;
-#endif
- break;
-
- default: return PCRE_ERROR_BADOPTION;
- }
-
-return 0;
-}
-
-/* End of pcre_config.c */
diff --git a/glib/pcre/pcre_dfa_exec.c b/glib/pcre/pcre_dfa_exec.c
deleted file mode 100644
index 9a73a5209..000000000
--- a/glib/pcre/pcre_dfa_exec.c
+++ /dev/null
@@ -1,2920 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains the external function pcre_dfa_exec(), which is an
-alternative matching function that uses a sort of DFA algorithm (not a true
-FSM). This is NOT Perl- compatible, but it has advantages in certain
-applications. */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define NLBLOCK md /* Block containing newline information */
-#define PSSTART start_subject /* Field containing processed string start */
-#define PSEND end_subject /* Field containing processed string end */
-
-#include "pcre_internal.h"
-
-
-/* For use to indent debugging output */
-
-#define SP " "
-
-
-
-/*************************************************
-* Code parameters and static tables *
-*************************************************/
-
-/* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes
-into others, under special conditions. A gap of 20 between the blocks should be
-enough. The resulting opcodes don't have to be less than 256 because they are
-never stored, so we push them well clear of the normal opcodes. */
-
-#define OP_PROP_EXTRA 300
-#define OP_EXTUNI_EXTRA 320
-#define OP_ANYNL_EXTRA 340
-#define OP_HSPACE_EXTRA 360
-#define OP_VSPACE_EXTRA 380
-
-
-/* This table identifies those opcodes that are followed immediately by a
-character that is to be tested in some way. This makes is possible to
-centralize the loading of these characters. In the case of Type * etc, the
-"character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a
-small value. ***NOTE*** If the start of this table is modified, the two tables
-that follow must also be modified. */
-
-static const uschar coptable[] = {
- 0, /* End */
- 0, 0, 0, 0, 0, /* \A, \G, \K, \B, \b */
- 0, 0, 0, 0, 0, 0, /* \D, \d, \S, \s, \W, \w */
- 0, 0, 0, /* Any, AllAny, Anybyte */
- 0, 0, 0, /* NOTPROP, PROP, EXTUNI */
- 0, 0, 0, 0, 0, /* \R, \H, \h, \V, \v */
- 0, 0, 0, 0, 0, /* \Z, \z, Opt, ^, $ */
- 1, /* Char */
- 1, /* Charnc */
- 1, /* not */
- /* Positive single-char repeats */
- 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */
- 3, 3, 3, /* upto, minupto, exact */
- 1, 1, 1, 3, /* *+, ++, ?+, upto+ */
- /* Negative single-char repeats - only for chars < 256 */
- 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */
- 3, 3, 3, /* NOT upto, minupto, exact */
- 1, 1, 1, 3, /* NOT *+, ++, ?+, updo+ */
- /* Positive type repeats */
- 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */
- 3, 3, 3, /* Type upto, minupto, exact */
- 1, 1, 1, 3, /* Type *+, ++, ?+, upto+ */
- /* Character class & ref repeats */
- 0, 0, 0, 0, 0, 0, /* *, *?, +, +?, ?, ?? */
- 0, 0, /* CRRANGE, CRMINRANGE */
- 0, /* CLASS */
- 0, /* NCLASS */
- 0, /* XCLASS - variable length */
- 0, /* REF */
- 0, /* RECURSE */
- 0, /* CALLOUT */
- 0, /* Alt */
- 0, /* Ket */
- 0, /* KetRmax */
- 0, /* KetRmin */
- 0, /* Assert */
- 0, /* Assert not */
- 0, /* Assert behind */
- 0, /* Assert behind not */
- 0, /* Reverse */
- 0, 0, 0, 0, /* ONCE, BRA, CBRA, COND */
- 0, 0, 0, /* SBRA, SCBRA, SCOND */
- 0, /* CREF */
- 0, /* RREF */
- 0, /* DEF */
- 0, 0, /* BRAZERO, BRAMINZERO */
- 0, 0, 0, 0, /* PRUNE, SKIP, THEN, COMMIT */
- 0, 0, 0 /* FAIL, ACCEPT, SKIPZERO */
-};
-
-/* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,
-and \w */
-
-static const uschar toptable1[] = {
- 0, 0, 0, 0, 0, 0,
- ctype_digit, ctype_digit,
- ctype_space, ctype_space,
- ctype_word, ctype_word,
- 0, 0 /* OP_ANY, OP_ALLANY */
-};
-
-static const uschar toptable2[] = {
- 0, 0, 0, 0, 0, 0,
- ctype_digit, 0,
- ctype_space, 0,
- ctype_word, 0,
- 1, 1 /* OP_ANY, OP_ALLANY */
-};
-
-
-/* Structure for holding data about a particular state, which is in effect the
-current data for an active path through the match tree. It must consist
-entirely of ints because the working vector we are passed, and which we put
-these structures in, is a vector of ints. */
-
-typedef struct stateblock {
- int offset; /* Offset to opcode */
- int count; /* Count for repeats */
- int ims; /* ims flag bits */
- int data; /* Some use extra data */
-} stateblock;
-
-#define INTS_PER_STATEBLOCK (sizeof(stateblock)/sizeof(int))
-
-
-#ifdef DEBUG
-/*************************************************
-* Print character string *
-*************************************************/
-
-/* Character string printing function for debugging.
-
-Arguments:
- p points to string
- length number of bytes
- f where to print
-
-Returns: nothing
-*/
-
-static void
-pchars(unsigned char *p, int length, FILE *f)
-{
-int c;
-while (length-- > 0)
- {
- if (isprint(c = *(p++)))
- fprintf(f, "%c", c);
- else
- fprintf(f, "\\x%02x", c);
- }
-}
-#endif
-
-
-
-/*************************************************
-* Execute a Regular Expression - DFA engine *
-*************************************************/
-
-/* This internal function applies a compiled pattern to a subject string,
-starting at a given point, using a DFA engine. This function is called from the
-external one, possibly multiple times if the pattern is not anchored. The
-function calls itself recursively for some kinds of subpattern.
-
-Arguments:
- md the match_data block with fixed information
- this_start_code the opening bracket of this subexpression's code
- current_subject where we currently are in the subject string
- start_offset start offset in the subject string
- offsets vector to contain the matching string offsets
- offsetcount size of same
- workspace vector of workspace
- wscount size of same
- ims the current ims flags
- rlevel function call recursion level
- recursing regex recursive call level
-
-Returns: > 0 => number of match offset pairs placed in offsets
- = 0 => offsets overflowed; longest matches are present
- -1 => failed to match
- < -1 => some kind of unexpected problem
-
-The following macros are used for adding states to the two state vectors (one
-for the current character, one for the following character). */
-
-#define ADD_ACTIVE(x,y) \
- if (active_count++ < wscount) \
- { \
- next_active_state->offset = (x); \
- next_active_state->count = (y); \
- next_active_state->ims = ims; \
- next_active_state++; \
- DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
- } \
- else return PCRE_ERROR_DFA_WSSIZE
-
-#define ADD_ACTIVE_DATA(x,y,z) \
- if (active_count++ < wscount) \
- { \
- next_active_state->offset = (x); \
- next_active_state->count = (y); \
- next_active_state->ims = ims; \
- next_active_state->data = (z); \
- next_active_state++; \
- DPRINTF(("%.*sADD_ACTIVE_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \
- } \
- else return PCRE_ERROR_DFA_WSSIZE
-
-#define ADD_NEW(x,y) \
- if (new_count++ < wscount) \
- { \
- next_new_state->offset = (x); \
- next_new_state->count = (y); \
- next_new_state->ims = ims; \
- next_new_state++; \
- DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \
- } \
- else return PCRE_ERROR_DFA_WSSIZE
-
-#define ADD_NEW_DATA(x,y,z) \
- if (new_count++ < wscount) \
- { \
- next_new_state->offset = (x); \
- next_new_state->count = (y); \
- next_new_state->ims = ims; \
- next_new_state->data = (z); \
- next_new_state++; \
- DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \
- } \
- else return PCRE_ERROR_DFA_WSSIZE
-
-/* And now, here is the code */
-
-static int
-internal_dfa_exec(
- dfa_match_data *md,
- const uschar *this_start_code,
- const uschar *current_subject,
- int start_offset,
- int *offsets,
- int offsetcount,
- int *workspace,
- int wscount,
- int ims,
- int rlevel,
- int recursing)
-{
-stateblock *active_states, *new_states, *temp_states;
-stateblock *next_active_state, *next_new_state;
-
-const uschar *ctypes, *lcc, *fcc;
-const uschar *ptr;
-const uschar *end_code, *first_op;
-
-int active_count, new_count, match_count;
-
-/* Some fields in the md block are frequently referenced, so we load them into
-independent variables in the hope that this will perform better. */
-
-const uschar *start_subject = md->start_subject;
-const uschar *end_subject = md->end_subject;
-const uschar *start_code = md->start_code;
-
-#ifdef SUPPORT_UTF8
-BOOL utf8 = (md->poptions & PCRE_UTF8) != 0;
-#else
-BOOL utf8 = FALSE;
-#endif
-
-rlevel++;
-offsetcount &= (-2);
-
-wscount -= 2;
-wscount = (wscount - (wscount % (INTS_PER_STATEBLOCK * 2))) /
- (2 * INTS_PER_STATEBLOCK);
-
-DPRINTF(("\n%.*s---------------------\n"
- "%.*sCall to internal_dfa_exec f=%d r=%d\n",
- rlevel*2-2, SP, rlevel*2-2, SP, rlevel, recursing));
-
-ctypes = md->tables + ctypes_offset;
-lcc = md->tables + lcc_offset;
-fcc = md->tables + fcc_offset;
-
-match_count = PCRE_ERROR_NOMATCH; /* A negative number */
-
-active_states = (stateblock *)(workspace + 2);
-next_new_state = new_states = active_states + wscount;
-new_count = 0;
-
-first_op = this_start_code + 1 + LINK_SIZE +
- ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA)? 2:0);
-
-/* The first thing in any (sub) pattern is a bracket of some sort. Push all
-the alternative states onto the list, and find out where the end is. This
-makes is possible to use this function recursively, when we want to stop at a
-matching internal ket rather than at the end.
-
-If the first opcode in the first alternative is OP_REVERSE, we are dealing with
-a backward assertion. In that case, we have to find out the maximum amount to
-move back, and set up each alternative appropriately. */
-
-if (*first_op == OP_REVERSE)
- {
- int max_back = 0;
- int gone_back;
-
- end_code = this_start_code;
- do
- {
- int back = GET(end_code, 2+LINK_SIZE);
- if (back > max_back) max_back = back;
- end_code += GET(end_code, 1);
- }
- while (*end_code == OP_ALT);
-
- /* If we can't go back the amount required for the longest lookbehind
- pattern, go back as far as we can; some alternatives may still be viable. */
-
-#ifdef SUPPORT_UTF8
- /* In character mode we have to step back character by character */
-
- if (utf8)
- {
- for (gone_back = 0; gone_back < max_back; gone_back++)
- {
- if (current_subject <= start_subject) break;
- current_subject--;
- while (current_subject > start_subject &&
- (*current_subject & 0xc0) == 0x80)
- current_subject--;
- }
- }
- else
-#endif
-
- /* In byte-mode we can do this quickly. */
-
- {
- gone_back = (current_subject - max_back < start_subject)?
- current_subject - start_subject : max_back;
- current_subject -= gone_back;
- }
-
- /* Now we can process the individual branches. */
-
- end_code = this_start_code;
- do
- {
- int back = GET(end_code, 2+LINK_SIZE);
- if (back <= gone_back)
- {
- int bstate = end_code - start_code + 2 + 2*LINK_SIZE;
- ADD_NEW_DATA(-bstate, 0, gone_back - back);
- }
- end_code += GET(end_code, 1);
- }
- while (*end_code == OP_ALT);
- }
-
-/* This is the code for a "normal" subpattern (not a backward assertion). The
-start of a whole pattern is always one of these. If we are at the top level,
-we may be asked to restart matching from the same point that we reached for a
-previous partial match. We still have to scan through the top-level branches to
-find the end state. */
-
-else
- {
- end_code = this_start_code;
-
- /* Restarting */
-
- if (rlevel == 1 && (md->moptions & PCRE_DFA_RESTART) != 0)
- {
- do { end_code += GET(end_code, 1); } while (*end_code == OP_ALT);
- new_count = workspace[1];
- if (!workspace[0])
- memcpy(new_states, active_states, new_count * sizeof(stateblock));
- }
-
- /* Not restarting */
-
- else
- {
- int length = 1 + LINK_SIZE +
- ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA)? 2:0);
- do
- {
- ADD_NEW(end_code - start_code + length, 0);
- end_code += GET(end_code, 1);
- length = 1 + LINK_SIZE;
- }
- while (*end_code == OP_ALT);
- }
- }
-
-workspace[0] = 0; /* Bit indicating which vector is current */
-
-DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, end_code - start_code));
-
-/* Loop for scanning the subject */
-
-ptr = current_subject;
-for (;;)
- {
- int i, j;
- int clen, dlen;
- unsigned int c, d;
-
- /* Make the new state list into the active state list and empty the
- new state list. */
-
- temp_states = active_states;
- active_states = new_states;
- new_states = temp_states;
- active_count = new_count;
- new_count = 0;
-
- workspace[0] ^= 1; /* Remember for the restarting feature */
- workspace[1] = active_count;
-
-#ifdef DEBUG
- printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP);
- pchars((uschar *)ptr, strlen((char *)ptr), stdout);
- printf("\"\n");
-
- printf("%.*sActive states: ", rlevel*2-2, SP);
- for (i = 0; i < active_count; i++)
- printf("%d/%d ", active_states[i].offset, active_states[i].count);
- printf("\n");
-#endif
-
- /* Set the pointers for adding new states */
-
- next_active_state = active_states + active_count;
- next_new_state = new_states;
-
- /* Load the current character from the subject outside the loop, as many
- different states may want to look at it, and we assume that at least one
- will. */
-
- if (ptr < end_subject)
- {
- clen = 1; /* Number of bytes in the character */
-#ifdef SUPPORT_UTF8
- if (utf8) { GETCHARLEN(c, ptr, clen); } else
-#endif /* SUPPORT_UTF8 */
- c = *ptr;
- }
- else
- {
- clen = 0; /* This indicates the end of the subject */
- c = NOTACHAR; /* This value should never actually be used */
- }
-
- /* Scan up the active states and act on each one. The result of an action
- may be to add more states to the currently active list (e.g. on hitting a
- parenthesis) or it may be to put states on the new list, for considering
- when we move the character pointer on. */
-
- for (i = 0; i < active_count; i++)
- {
- stateblock *current_state = active_states + i;
- const uschar *code;
- int state_offset = current_state->offset;
- int count, codevalue;
-
-#ifdef DEBUG
- printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset);
- if (clen == 0) printf("EOL\n");
- else if (c > 32 && c < 127) printf("'%c'\n", c);
- else printf("0x%02x\n", c);
-#endif
-
- /* This variable is referred to implicity in the ADD_xxx macros. */
-
- ims = current_state->ims;
-
- /* A negative offset is a special case meaning "hold off going to this
- (negated) state until the number of characters in the data field have
- been skipped". */
-
- if (state_offset < 0)
- {
- if (current_state->data > 0)
- {
- DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP));
- ADD_NEW_DATA(state_offset, current_state->count,
- current_state->data - 1);
- continue;
- }
- else
- {
- current_state->offset = state_offset = -state_offset;
- }
- }
-
- /* Check for a duplicate state with the same count, and skip if found. */
-
- for (j = 0; j < i; j++)
- {
- if (active_states[j].offset == state_offset &&
- active_states[j].count == current_state->count)
- {
- DPRINTF(("%.*sDuplicate state: skipped\n", rlevel*2-2, SP));
- goto NEXT_ACTIVE_STATE;
- }
- }
-
- /* The state offset is the offset to the opcode */
-
- code = start_code + state_offset;
- codevalue = *code;
-
- /* If this opcode is followed by an inline character, load it. It is
- tempting to test for the presence of a subject character here, but that
- is wrong, because sometimes zero repetitions of the subject are
- permitted.
-
- We also use this mechanism for opcodes such as OP_TYPEPLUS that take an
- argument that is not a data character - but is always one byte long. We
- have to take special action to deal with \P, \p, \H, \h, \V, \v and \X in
- this case. To keep the other cases fast, convert these ones to new opcodes.
- */
-
- if (coptable[codevalue] > 0)
- {
- dlen = 1;
-#ifdef SUPPORT_UTF8
- if (utf8) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else
-#endif /* SUPPORT_UTF8 */
- d = code[coptable[codevalue]];
- if (codevalue >= OP_TYPESTAR)
- {
- switch(d)
- {
- case OP_ANYBYTE: return PCRE_ERROR_DFA_UITEM;
- case OP_NOTPROP:
- case OP_PROP: codevalue += OP_PROP_EXTRA; break;
- case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break;
- case OP_EXTUNI: codevalue += OP_EXTUNI_EXTRA; break;
- case OP_NOT_HSPACE:
- case OP_HSPACE: codevalue += OP_HSPACE_EXTRA; break;
- case OP_NOT_VSPACE:
- case OP_VSPACE: codevalue += OP_VSPACE_EXTRA; break;
- default: break;
- }
- }
- }
- else
- {
- dlen = 0; /* Not strictly necessary, but compilers moan */
- d = NOTACHAR; /* if these variables are not set. */
- }
-
-
- /* Now process the individual opcodes */
-
- switch (codevalue)
- {
-
-/* ========================================================================== */
- /* Reached a closing bracket. If not at the end of the pattern, carry
- on with the next opcode. Otherwise, unless we have an empty string and
- PCRE_NOTEMPTY is set, save the match data, shifting up all previous
- matches so we always have the longest first. */
-
- case OP_KET:
- case OP_KETRMIN:
- case OP_KETRMAX:
- if (code != end_code)
- {
- ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0);
- if (codevalue != OP_KET)
- {
- ADD_ACTIVE(state_offset - GET(code, 1), 0);
- }
- }
- else if (ptr > current_subject || (md->moptions & PCRE_NOTEMPTY) == 0)
- {
- if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;
- else if (match_count > 0 && ++match_count * 2 >= offsetcount)
- match_count = 0;
- count = ((match_count == 0)? offsetcount : match_count * 2) - 2;
- if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));
- if (offsetcount >= 2)
- {
- offsets[0] = current_subject - start_subject;
- offsets[1] = ptr - start_subject;
- DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP,
- offsets[1] - offsets[0], current_subject));
- }
- if ((md->moptions & PCRE_DFA_SHORTEST) != 0)
- {
- DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"
- "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel,
- match_count, rlevel*2-2, SP));
- return match_count;
- }
- }
- break;
-
-/* ========================================================================== */
- /* These opcodes add to the current list of states without looking
- at the current character. */
-
- /*-----------------------------------------------------------------*/
- case OP_ALT:
- do { code += GET(code, 1); } while (*code == OP_ALT);
- ADD_ACTIVE(code - start_code, 0);
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_BRA:
- case OP_SBRA:
- do
- {
- ADD_ACTIVE(code - start_code + 1 + LINK_SIZE, 0);
- code += GET(code, 1);
- }
- while (*code == OP_ALT);
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_CBRA:
- case OP_SCBRA:
- ADD_ACTIVE(code - start_code + 3 + LINK_SIZE, 0);
- code += GET(code, 1);
- while (*code == OP_ALT)
- {
- ADD_ACTIVE(code - start_code + 1 + LINK_SIZE, 0);
- code += GET(code, 1);
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_BRAZERO:
- case OP_BRAMINZERO:
- ADD_ACTIVE(state_offset + 1, 0);
- code += 1 + GET(code, 2);
- while (*code == OP_ALT) code += GET(code, 1);
- ADD_ACTIVE(code - start_code + 1 + LINK_SIZE, 0);
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_SKIPZERO:
- code += 1 + GET(code, 2);
- while (*code == OP_ALT) code += GET(code, 1);
- ADD_ACTIVE(code - start_code + 1 + LINK_SIZE, 0);
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_CIRC:
- if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) ||
- ((ims & PCRE_MULTILINE) != 0 &&
- ptr != end_subject &&
- WAS_NEWLINE(ptr)))
- { ADD_ACTIVE(state_offset + 1, 0); }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_EOD:
- if (ptr >= end_subject) { ADD_ACTIVE(state_offset + 1, 0); }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_OPT:
- ims = code[1];
- ADD_ACTIVE(state_offset + 2, 0);
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_SOD:
- if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_SOM:
- if (ptr == start_subject + start_offset) { ADD_ACTIVE(state_offset + 1, 0); }
- break;
-
-
-/* ========================================================================== */
- /* These opcodes inspect the next subject character, and sometimes
- the previous one as well, but do not have an argument. The variable
- clen contains the length of the current character and is zero if we are
- at the end of the subject. */
-
- /*-----------------------------------------------------------------*/
- case OP_ANY:
- if (clen > 0 && !IS_NEWLINE(ptr))
- { ADD_NEW(state_offset + 1, 0); }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_ALLANY:
- if (clen > 0)
- { ADD_NEW(state_offset + 1, 0); }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_EODN:
- if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - md->nllen))
- { ADD_ACTIVE(state_offset + 1, 0); }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_DOLL:
- if ((md->moptions & PCRE_NOTEOL) == 0)
- {
- if (clen == 0 ||
- (IS_NEWLINE(ptr) &&
- ((ims & PCRE_MULTILINE) != 0 || ptr == end_subject - md->nllen)
- ))
- { ADD_ACTIVE(state_offset + 1, 0); }
- }
- else if ((ims & PCRE_MULTILINE) != 0 && IS_NEWLINE(ptr))
- { ADD_ACTIVE(state_offset + 1, 0); }
- break;
-
- /*-----------------------------------------------------------------*/
-
- case OP_DIGIT:
- case OP_WHITESPACE:
- case OP_WORDCHAR:
- if (clen > 0 && c < 256 &&
- ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0)
- { ADD_NEW(state_offset + 1, 0); }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_NOT_DIGIT:
- case OP_NOT_WHITESPACE:
- case OP_NOT_WORDCHAR:
- if (clen > 0 && (c >= 256 ||
- ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0))
- { ADD_NEW(state_offset + 1, 0); }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_WORD_BOUNDARY:
- case OP_NOT_WORD_BOUNDARY:
- {
- int left_word, right_word;
-
- if (ptr > start_subject)
- {
- const uschar *temp = ptr - 1;
-#ifdef SUPPORT_UTF8
- if (utf8) BACKCHAR(temp);
-#endif
- GETCHARTEST(d, temp);
- left_word = d < 256 && (ctypes[d] & ctype_word) != 0;
- }
- else left_word = 0;
-
- if (clen > 0) right_word = c < 256 && (ctypes[c] & ctype_word) != 0;
- else right_word = 0;
-
- if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))
- { ADD_ACTIVE(state_offset + 1, 0); }
- }
- break;
-
-
- /*-----------------------------------------------------------------*/
- /* Check the next character by Unicode property. We will get here only
- if the support is in the binary; otherwise a compile-time error occurs.
- */
-
-#ifdef SUPPORT_UCP
- case OP_PROP:
- case OP_NOTPROP:
- if (clen > 0)
- {
- BOOL OK;
- int chartype = UCD_CHARTYPE(c);
- switch(code[1])
- {
- case PT_ANY:
- OK = TRUE;
- break;
-
- case PT_LAMP:
- OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;
- break;
-
- case PT_GC:
- OK = _pcre_ucp_gentype[chartype] == code[2];
- break;
-
- case PT_PC:
- OK = chartype == code[2];
- break;
-
- case PT_SC:
- OK = UCD_SCRIPT(c) == code[2];
- break;
-
- /* Should never occur, but keep compilers from grumbling. */
-
- default:
- OK = codevalue != OP_PROP;
- break;
- }
-
- if (OK == (codevalue == OP_PROP)) { ADD_NEW(state_offset + 3, 0); }
- }
- break;
-#endif
-
-
-
-/* ========================================================================== */
- /* These opcodes likewise inspect the subject character, but have an
- argument that is not a data character. It is one of these opcodes:
- OP_ANY, OP_ALLANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE,
- OP_WORDCHAR, OP_NOT_WORDCHAR. The value is loaded into d. */
-
- case OP_TYPEPLUS:
- case OP_TYPEMINPLUS:
- case OP_TYPEPOSPLUS:
- count = current_state->count; /* Already matched */
- if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
- if (clen > 0)
- {
- if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
- (c < 256 &&
- (d != OP_ANY || !IS_NEWLINE(ptr)) &&
- ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
- {
- if (count > 0 && codevalue == OP_TYPEPOSPLUS)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- count++;
- ADD_NEW(state_offset, count);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_TYPEQUERY:
- case OP_TYPEMINQUERY:
- case OP_TYPEPOSQUERY:
- ADD_ACTIVE(state_offset + 2, 0);
- if (clen > 0)
- {
- if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
- (c < 256 &&
- (d != OP_ANY || !IS_NEWLINE(ptr)) &&
- ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
- {
- if (codevalue == OP_TYPEPOSQUERY)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- ADD_NEW(state_offset + 2, 0);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_TYPESTAR:
- case OP_TYPEMINSTAR:
- case OP_TYPEPOSSTAR:
- ADD_ACTIVE(state_offset + 2, 0);
- if (clen > 0)
- {
- if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
- (c < 256 &&
- (d != OP_ANY || !IS_NEWLINE(ptr)) &&
- ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
- {
- if (codevalue == OP_TYPEPOSSTAR)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- ADD_NEW(state_offset, 0);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_TYPEEXACT:
- count = current_state->count; /* Number already matched */
- if (clen > 0)
- {
- if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
- (c < 256 &&
- (d != OP_ANY || !IS_NEWLINE(ptr)) &&
- ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
- {
- if (++count >= GET2(code, 1))
- { ADD_NEW(state_offset + 4, 0); }
- else
- { ADD_NEW(state_offset, count); }
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_TYPEUPTO:
- case OP_TYPEMINUPTO:
- case OP_TYPEPOSUPTO:
- ADD_ACTIVE(state_offset + 4, 0);
- count = current_state->count; /* Number already matched */
- if (clen > 0)
- {
- if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) ||
- (c < 256 &&
- (d != OP_ANY || !IS_NEWLINE(ptr)) &&
- ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0))
- {
- if (codevalue == OP_TYPEPOSUPTO)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- if (++count >= GET2(code, 1))
- { ADD_NEW(state_offset + 4, 0); }
- else
- { ADD_NEW(state_offset, count); }
- }
- }
- break;
-
-/* ========================================================================== */
- /* These are virtual opcodes that are used when something like
- OP_TYPEPLUS has OP_PROP, OP_NOTPROP, OP_ANYNL, or OP_EXTUNI as its
- argument. It keeps the code above fast for the other cases. The argument
- is in the d variable. */
-
-#ifdef SUPPORT_UCP
- case OP_PROP_EXTRA + OP_TYPEPLUS:
- case OP_PROP_EXTRA + OP_TYPEMINPLUS:
- case OP_PROP_EXTRA + OP_TYPEPOSPLUS:
- count = current_state->count; /* Already matched */
- if (count > 0) { ADD_ACTIVE(state_offset + 4, 0); }
- if (clen > 0)
- {
- BOOL OK;
- int chartype = UCD_CHARTYPE(c);
- switch(code[2])
- {
- case PT_ANY:
- OK = TRUE;
- break;
-
- case PT_LAMP:
- OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;
- break;
-
- case PT_GC:
- OK = _pcre_ucp_gentype[chartype] == code[3];
- break;
-
- case PT_PC:
- OK = chartype == code[3];
- break;
-
- case PT_SC:
- OK = UCD_SCRIPT(c) == code[3];
- break;
-
- /* Should never occur, but keep compilers from grumbling. */
-
- default:
- OK = codevalue != OP_PROP;
- break;
- }
-
- if (OK == (d == OP_PROP))
- {
- if (count > 0 && codevalue == OP_PROP_EXTRA + OP_TYPEPOSPLUS)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- count++;
- ADD_NEW(state_offset, count);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_EXTUNI_EXTRA + OP_TYPEPLUS:
- case OP_EXTUNI_EXTRA + OP_TYPEMINPLUS:
- case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS:
- count = current_state->count; /* Already matched */
- if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
- if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
- {
- const uschar *nptr = ptr + clen;
- int ncount = 0;
- if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- while (nptr < end_subject)
- {
- int nd;
- int ndlen = 1;
- GETCHARLEN(nd, nptr, ndlen);
- if (UCD_CATEGORY(nd) != ucp_M) break;
- ncount++;
- nptr += ndlen;
- }
- count++;
- ADD_NEW_DATA(-state_offset, count, ncount);
- }
- break;
-#endif
-
- /*-----------------------------------------------------------------*/
- case OP_ANYNL_EXTRA + OP_TYPEPLUS:
- case OP_ANYNL_EXTRA + OP_TYPEMINPLUS:
- case OP_ANYNL_EXTRA + OP_TYPEPOSPLUS:
- count = current_state->count; /* Already matched */
- if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
- if (clen > 0)
- {
- int ncount = 0;
- switch (c)
- {
- case 0x000b:
- case 0x000c:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
- goto ANYNL01;
-
- case 0x000d:
- if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
- /* Fall through */
-
- ANYNL01:
- case 0x000a:
- if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- count++;
- ADD_NEW_DATA(-state_offset, count, ncount);
- break;
-
- default:
- break;
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_VSPACE_EXTRA + OP_TYPEPLUS:
- case OP_VSPACE_EXTRA + OP_TYPEMINPLUS:
- case OP_VSPACE_EXTRA + OP_TYPEPOSPLUS:
- count = current_state->count; /* Already matched */
- if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
- if (clen > 0)
- {
- BOOL OK;
- switch (c)
- {
- case 0x000a:
- case 0x000b:
- case 0x000c:
- case 0x000d:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- OK = TRUE;
- break;
-
- default:
- OK = FALSE;
- break;
- }
-
- if (OK == (d == OP_VSPACE))
- {
- if (count > 0 && codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSPLUS)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- count++;
- ADD_NEW_DATA(-state_offset, count, 0);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_HSPACE_EXTRA + OP_TYPEPLUS:
- case OP_HSPACE_EXTRA + OP_TYPEMINPLUS:
- case OP_HSPACE_EXTRA + OP_TYPEPOSPLUS:
- count = current_state->count; /* Already matched */
- if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
- if (clen > 0)
- {
- BOOL OK;
- switch (c)
- {
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- OK = TRUE;
- break;
-
- default:
- OK = FALSE;
- break;
- }
-
- if (OK == (d == OP_HSPACE))
- {
- if (count > 0 && codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSPLUS)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- count++;
- ADD_NEW_DATA(-state_offset, count, 0);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
-#ifdef SUPPORT_UCP
- case OP_PROP_EXTRA + OP_TYPEQUERY:
- case OP_PROP_EXTRA + OP_TYPEMINQUERY:
- case OP_PROP_EXTRA + OP_TYPEPOSQUERY:
- count = 4;
- goto QS1;
-
- case OP_PROP_EXTRA + OP_TYPESTAR:
- case OP_PROP_EXTRA + OP_TYPEMINSTAR:
- case OP_PROP_EXTRA + OP_TYPEPOSSTAR:
- count = 0;
-
- QS1:
-
- ADD_ACTIVE(state_offset + 4, 0);
- if (clen > 0)
- {
- BOOL OK;
- int chartype = UCD_CHARTYPE(c);
- switch(code[2])
- {
- case PT_ANY:
- OK = TRUE;
- break;
-
- case PT_LAMP:
- OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;
- break;
-
- case PT_GC:
- OK = _pcre_ucp_gentype[chartype] == code[3];
- break;
-
- case PT_PC:
- OK = chartype == code[3];
- break;
-
- case PT_SC:
- OK = UCD_SCRIPT(c) == code[3];
- break;
-
- /* Should never occur, but keep compilers from grumbling. */
-
- default:
- OK = codevalue != OP_PROP;
- break;
- }
-
- if (OK == (d == OP_PROP))
- {
- if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSSTAR ||
- codevalue == OP_PROP_EXTRA + OP_TYPEPOSQUERY)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- ADD_NEW(state_offset + count, 0);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_EXTUNI_EXTRA + OP_TYPEQUERY:
- case OP_EXTUNI_EXTRA + OP_TYPEMINQUERY:
- case OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY:
- count = 2;
- goto QS2;
-
- case OP_EXTUNI_EXTRA + OP_TYPESTAR:
- case OP_EXTUNI_EXTRA + OP_TYPEMINSTAR:
- case OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR:
- count = 0;
-
- QS2:
-
- ADD_ACTIVE(state_offset + 2, 0);
- if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
- {
- const uschar *nptr = ptr + clen;
- int ncount = 0;
- if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||
- codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- while (nptr < end_subject)
- {
- int nd;
- int ndlen = 1;
- GETCHARLEN(nd, nptr, ndlen);
- if (UCD_CATEGORY(nd) != ucp_M) break;
- ncount++;
- nptr += ndlen;
- }
- ADD_NEW_DATA(-(state_offset + count), 0, ncount);
- }
- break;
-#endif
-
- /*-----------------------------------------------------------------*/
- case OP_ANYNL_EXTRA + OP_TYPEQUERY:
- case OP_ANYNL_EXTRA + OP_TYPEMINQUERY:
- case OP_ANYNL_EXTRA + OP_TYPEPOSQUERY:
- count = 2;
- goto QS3;
-
- case OP_ANYNL_EXTRA + OP_TYPESTAR:
- case OP_ANYNL_EXTRA + OP_TYPEMINSTAR:
- case OP_ANYNL_EXTRA + OP_TYPEPOSSTAR:
- count = 0;
-
- QS3:
- ADD_ACTIVE(state_offset + 2, 0);
- if (clen > 0)
- {
- int ncount = 0;
- switch (c)
- {
- case 0x000b:
- case 0x000c:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
- goto ANYNL02;
-
- case 0x000d:
- if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
- /* Fall through */
-
- ANYNL02:
- case 0x000a:
- if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR ||
- codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- ADD_NEW_DATA(-(state_offset + count), 0, ncount);
- break;
-
- default:
- break;
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_VSPACE_EXTRA + OP_TYPEQUERY:
- case OP_VSPACE_EXTRA + OP_TYPEMINQUERY:
- case OP_VSPACE_EXTRA + OP_TYPEPOSQUERY:
- count = 2;
- goto QS4;
-
- case OP_VSPACE_EXTRA + OP_TYPESTAR:
- case OP_VSPACE_EXTRA + OP_TYPEMINSTAR:
- case OP_VSPACE_EXTRA + OP_TYPEPOSSTAR:
- count = 0;
-
- QS4:
- ADD_ACTIVE(state_offset + 2, 0);
- if (clen > 0)
- {
- BOOL OK;
- switch (c)
- {
- case 0x000a:
- case 0x000b:
- case 0x000c:
- case 0x000d:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- OK = TRUE;
- break;
-
- default:
- OK = FALSE;
- break;
- }
- if (OK == (d == OP_VSPACE))
- {
- if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSSTAR ||
- codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSQUERY)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- ADD_NEW_DATA(-(state_offset + count), 0, 0);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_HSPACE_EXTRA + OP_TYPEQUERY:
- case OP_HSPACE_EXTRA + OP_TYPEMINQUERY:
- case OP_HSPACE_EXTRA + OP_TYPEPOSQUERY:
- count = 2;
- goto QS5;
-
- case OP_HSPACE_EXTRA + OP_TYPESTAR:
- case OP_HSPACE_EXTRA + OP_TYPEMINSTAR:
- case OP_HSPACE_EXTRA + OP_TYPEPOSSTAR:
- count = 0;
-
- QS5:
- ADD_ACTIVE(state_offset + 2, 0);
- if (clen > 0)
- {
- BOOL OK;
- switch (c)
- {
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- OK = TRUE;
- break;
-
- default:
- OK = FALSE;
- break;
- }
-
- if (OK == (d == OP_HSPACE))
- {
- if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSSTAR ||
- codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSQUERY)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- ADD_NEW_DATA(-(state_offset + count), 0, 0);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
-#ifdef SUPPORT_UCP
- case OP_PROP_EXTRA + OP_TYPEEXACT:
- case OP_PROP_EXTRA + OP_TYPEUPTO:
- case OP_PROP_EXTRA + OP_TYPEMINUPTO:
- case OP_PROP_EXTRA + OP_TYPEPOSUPTO:
- if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT)
- { ADD_ACTIVE(state_offset + 6, 0); }
- count = current_state->count; /* Number already matched */
- if (clen > 0)
- {
- BOOL OK;
- int chartype = UCD_CHARTYPE(c);
- switch(code[4])
- {
- case PT_ANY:
- OK = TRUE;
- break;
-
- case PT_LAMP:
- OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;
- break;
-
- case PT_GC:
- OK = _pcre_ucp_gentype[chartype] == code[5];
- break;
-
- case PT_PC:
- OK = chartype == code[5];
- break;
-
- case PT_SC:
- OK = UCD_SCRIPT(c) == code[5];
- break;
-
- /* Should never occur, but keep compilers from grumbling. */
-
- default:
- OK = codevalue != OP_PROP;
- break;
- }
-
- if (OK == (d == OP_PROP))
- {
- if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSUPTO)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- if (++count >= GET2(code, 1))
- { ADD_NEW(state_offset + 6, 0); }
- else
- { ADD_NEW(state_offset, count); }
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_EXTUNI_EXTRA + OP_TYPEEXACT:
- case OP_EXTUNI_EXTRA + OP_TYPEUPTO:
- case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO:
- case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO:
- if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT)
- { ADD_ACTIVE(state_offset + 4, 0); }
- count = current_state->count; /* Number already matched */
- if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
- {
- const uschar *nptr = ptr + clen;
- int ncount = 0;
- if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- while (nptr < end_subject)
- {
- int nd;
- int ndlen = 1;
- GETCHARLEN(nd, nptr, ndlen);
- if (UCD_CATEGORY(nd) != ucp_M) break;
- ncount++;
- nptr += ndlen;
- }
- if (++count >= GET2(code, 1))
- { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }
- else
- { ADD_NEW_DATA(-state_offset, count, ncount); }
- }
- break;
-#endif
-
- /*-----------------------------------------------------------------*/
- case OP_ANYNL_EXTRA + OP_TYPEEXACT:
- case OP_ANYNL_EXTRA + OP_TYPEUPTO:
- case OP_ANYNL_EXTRA + OP_TYPEMINUPTO:
- case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO:
- if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT)
- { ADD_ACTIVE(state_offset + 4, 0); }
- count = current_state->count; /* Number already matched */
- if (clen > 0)
- {
- int ncount = 0;
- switch (c)
- {
- case 0x000b:
- case 0x000c:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
- goto ANYNL03;
-
- case 0x000d:
- if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1;
- /* Fall through */
-
- ANYNL03:
- case 0x000a:
- if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- if (++count >= GET2(code, 1))
- { ADD_NEW_DATA(-(state_offset + 4), 0, ncount); }
- else
- { ADD_NEW_DATA(-state_offset, count, ncount); }
- break;
-
- default:
- break;
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_VSPACE_EXTRA + OP_TYPEEXACT:
- case OP_VSPACE_EXTRA + OP_TYPEUPTO:
- case OP_VSPACE_EXTRA + OP_TYPEMINUPTO:
- case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO:
- if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT)
- { ADD_ACTIVE(state_offset + 4, 0); }
- count = current_state->count; /* Number already matched */
- if (clen > 0)
- {
- BOOL OK;
- switch (c)
- {
- case 0x000a:
- case 0x000b:
- case 0x000c:
- case 0x000d:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- OK = TRUE;
- break;
-
- default:
- OK = FALSE;
- }
-
- if (OK == (d == OP_VSPACE))
- {
- if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSUPTO)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- if (++count >= GET2(code, 1))
- { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }
- else
- { ADD_NEW_DATA(-state_offset, count, 0); }
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_HSPACE_EXTRA + OP_TYPEEXACT:
- case OP_HSPACE_EXTRA + OP_TYPEUPTO:
- case OP_HSPACE_EXTRA + OP_TYPEMINUPTO:
- case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO:
- if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT)
- { ADD_ACTIVE(state_offset + 4, 0); }
- count = current_state->count; /* Number already matched */
- if (clen > 0)
- {
- BOOL OK;
- switch (c)
- {
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- OK = TRUE;
- break;
-
- default:
- OK = FALSE;
- break;
- }
-
- if (OK == (d == OP_HSPACE))
- {
- if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSUPTO)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- if (++count >= GET2(code, 1))
- { ADD_NEW_DATA(-(state_offset + 4), 0, 0); }
- else
- { ADD_NEW_DATA(-state_offset, count, 0); }
- }
- }
- break;
-
-/* ========================================================================== */
- /* These opcodes are followed by a character that is usually compared
- to the current subject character; it is loaded into d. We still get
- here even if there is no subject character, because in some cases zero
- repetitions are permitted. */
-
- /*-----------------------------------------------------------------*/
- case OP_CHAR:
- if (clen > 0 && c == d) { ADD_NEW(state_offset + dlen + 1, 0); }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_CHARNC:
- if (clen == 0) break;
-
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else
- {
- unsigned int othercase;
- if (c < 128) othercase = fcc[c]; else
-
- /* If we have Unicode property support, we can use it to test the
- other case of the character. */
-
-#ifdef SUPPORT_UCP
- othercase = UCD_OTHERCASE(c);
-#else
- othercase = NOTACHAR;
-#endif
-
- if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); }
- }
- }
- else
-#endif /* SUPPORT_UTF8 */
-
- /* Non-UTF-8 mode */
- {
- if (lcc[c] == lcc[d]) { ADD_NEW(state_offset + 2, 0); }
- }
- break;
-
-
-#ifdef SUPPORT_UCP
- /*-----------------------------------------------------------------*/
- /* This is a tricky one because it can match more than one character.
- Find out how many characters to skip, and then set up a negative state
- to wait for them to pass before continuing. */
-
- case OP_EXTUNI:
- if (clen > 0 && UCD_CATEGORY(c) != ucp_M)
- {
- const uschar *nptr = ptr + clen;
- int ncount = 0;
- while (nptr < end_subject)
- {
- int nclen = 1;
- GETCHARLEN(c, nptr, nclen);
- if (UCD_CATEGORY(c) != ucp_M) break;
- ncount++;
- nptr += nclen;
- }
- ADD_NEW_DATA(-(state_offset + 1), 0, ncount);
- }
- break;
-#endif
-
- /*-----------------------------------------------------------------*/
- /* This is a tricky like EXTUNI because it too can match more than one
- character (when CR is followed by LF). In this case, set up a negative
- state to wait for one character to pass before continuing. */
-
- case OP_ANYNL:
- if (clen > 0) switch(c)
- {
- case 0x000b:
- case 0x000c:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
-
- case 0x000a:
- ADD_NEW(state_offset + 1, 0);
- break;
-
- case 0x000d:
- if (ptr + 1 < end_subject && ptr[1] == 0x0a)
- {
- ADD_NEW_DATA(-(state_offset + 1), 0, 1);
- }
- else
- {
- ADD_NEW(state_offset + 1, 0);
- }
- break;
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_NOT_VSPACE:
- if (clen > 0) switch(c)
- {
- case 0x000a:
- case 0x000b:
- case 0x000c:
- case 0x000d:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- break;
-
- default:
- ADD_NEW(state_offset + 1, 0);
- break;
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_VSPACE:
- if (clen > 0) switch(c)
- {
- case 0x000a:
- case 0x000b:
- case 0x000c:
- case 0x000d:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- ADD_NEW(state_offset + 1, 0);
- break;
-
- default: break;
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_NOT_HSPACE:
- if (clen > 0) switch(c)
- {
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- break;
-
- default:
- ADD_NEW(state_offset + 1, 0);
- break;
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_HSPACE:
- if (clen > 0) switch(c)
- {
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- ADD_NEW(state_offset + 1, 0);
- break;
- }
- break;
-
- /*-----------------------------------------------------------------*/
- /* Match a negated single character. This is only used for one-byte
- characters, that is, we know that d < 256. The character we are
- checking (c) can be multibyte. */
-
- case OP_NOT:
- if (clen > 0)
- {
- unsigned int otherd = ((ims & PCRE_CASELESS) != 0)? fcc[d] : d;
- if (c != d && c != otherd) { ADD_NEW(state_offset + dlen + 1, 0); }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_PLUS:
- case OP_MINPLUS:
- case OP_POSPLUS:
- case OP_NOTPLUS:
- case OP_NOTMINPLUS:
- case OP_NOTPOSPLUS:
- count = current_state->count; /* Already matched */
- if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }
- if (clen > 0)
- {
- unsigned int otherd = NOTACHAR;
- if ((ims & PCRE_CASELESS) != 0)
- {
-#ifdef SUPPORT_UTF8
- if (utf8 && d >= 128)
- {
-#ifdef SUPPORT_UCP
- otherd = UCD_OTHERCASE(d);
-#endif /* SUPPORT_UCP */
- }
- else
-#endif /* SUPPORT_UTF8 */
- otherd = fcc[d];
- }
- if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
- {
- if (count > 0 &&
- (codevalue == OP_POSPLUS || codevalue == OP_NOTPOSPLUS))
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- count++;
- ADD_NEW(state_offset, count);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_QUERY:
- case OP_MINQUERY:
- case OP_POSQUERY:
- case OP_NOTQUERY:
- case OP_NOTMINQUERY:
- case OP_NOTPOSQUERY:
- ADD_ACTIVE(state_offset + dlen + 1, 0);
- if (clen > 0)
- {
- unsigned int otherd = NOTACHAR;
- if ((ims & PCRE_CASELESS) != 0)
- {
-#ifdef SUPPORT_UTF8
- if (utf8 && d >= 128)
- {
-#ifdef SUPPORT_UCP
- otherd = UCD_OTHERCASE(d);
-#endif /* SUPPORT_UCP */
- }
- else
-#endif /* SUPPORT_UTF8 */
- otherd = fcc[d];
- }
- if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
- {
- if (codevalue == OP_POSQUERY || codevalue == OP_NOTPOSQUERY)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- ADD_NEW(state_offset + dlen + 1, 0);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_STAR:
- case OP_MINSTAR:
- case OP_POSSTAR:
- case OP_NOTSTAR:
- case OP_NOTMINSTAR:
- case OP_NOTPOSSTAR:
- ADD_ACTIVE(state_offset + dlen + 1, 0);
- if (clen > 0)
- {
- unsigned int otherd = NOTACHAR;
- if ((ims & PCRE_CASELESS) != 0)
- {
-#ifdef SUPPORT_UTF8
- if (utf8 && d >= 128)
- {
-#ifdef SUPPORT_UCP
- otherd = UCD_OTHERCASE(d);
-#endif /* SUPPORT_UCP */
- }
- else
-#endif /* SUPPORT_UTF8 */
- otherd = fcc[d];
- }
- if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
- {
- if (codevalue == OP_POSSTAR || codevalue == OP_NOTPOSSTAR)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- ADD_NEW(state_offset, 0);
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_EXACT:
- case OP_NOTEXACT:
- count = current_state->count; /* Number already matched */
- if (clen > 0)
- {
- unsigned int otherd = NOTACHAR;
- if ((ims & PCRE_CASELESS) != 0)
- {
-#ifdef SUPPORT_UTF8
- if (utf8 && d >= 128)
- {
-#ifdef SUPPORT_UCP
- otherd = UCD_OTHERCASE(d);
-#endif /* SUPPORT_UCP */
- }
- else
-#endif /* SUPPORT_UTF8 */
- otherd = fcc[d];
- }
- if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
- {
- if (++count >= GET2(code, 1))
- { ADD_NEW(state_offset + dlen + 3, 0); }
- else
- { ADD_NEW(state_offset, count); }
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_UPTO:
- case OP_MINUPTO:
- case OP_POSUPTO:
- case OP_NOTUPTO:
- case OP_NOTMINUPTO:
- case OP_NOTPOSUPTO:
- ADD_ACTIVE(state_offset + dlen + 3, 0);
- count = current_state->count; /* Number already matched */
- if (clen > 0)
- {
- unsigned int otherd = NOTACHAR;
- if ((ims & PCRE_CASELESS) != 0)
- {
-#ifdef SUPPORT_UTF8
- if (utf8 && d >= 128)
- {
-#ifdef SUPPORT_UCP
- otherd = UCD_OTHERCASE(d);
-#endif /* SUPPORT_UCP */
- }
- else
-#endif /* SUPPORT_UTF8 */
- otherd = fcc[d];
- }
- if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
- {
- if (codevalue == OP_POSUPTO || codevalue == OP_NOTPOSUPTO)
- {
- active_count--; /* Remove non-match possibility */
- next_active_state--;
- }
- if (++count >= GET2(code, 1))
- { ADD_NEW(state_offset + dlen + 3, 0); }
- else
- { ADD_NEW(state_offset, count); }
- }
- }
- break;
-
-
-/* ========================================================================== */
- /* These are the class-handling opcodes */
-
- case OP_CLASS:
- case OP_NCLASS:
- case OP_XCLASS:
- {
- BOOL isinclass = FALSE;
- int next_state_offset;
- const uschar *ecode;
-
- /* For a simple class, there is always just a 32-byte table, and we
- can set isinclass from it. */
-
- if (codevalue != OP_XCLASS)
- {
- ecode = code + 33;
- if (clen > 0)
- {
- isinclass = (c > 255)? (codevalue == OP_NCLASS) :
- ((code[1 + c/8] & (1 << (c&7))) != 0);
- }
- }
-
- /* An extended class may have a table or a list of single characters,
- ranges, or both, and it may be positive or negative. There's a
- function that sorts all this out. */
-
- else
- {
- ecode = code + GET(code, 1);
- if (clen > 0) isinclass = _pcre_xclass(c, code + 1 + LINK_SIZE);
- }
-
- /* At this point, isinclass is set for all kinds of class, and ecode
- points to the byte after the end of the class. If there is a
- quantifier, this is where it will be. */
-
- next_state_offset = ecode - start_code;
-
- switch (*ecode)
- {
- case OP_CRSTAR:
- case OP_CRMINSTAR:
- ADD_ACTIVE(next_state_offset + 1, 0);
- if (isinclass) { ADD_NEW(state_offset, 0); }
- break;
-
- case OP_CRPLUS:
- case OP_CRMINPLUS:
- count = current_state->count; /* Already matched */
- if (count > 0) { ADD_ACTIVE(next_state_offset + 1, 0); }
- if (isinclass) { count++; ADD_NEW(state_offset, count); }
- break;
-
- case OP_CRQUERY:
- case OP_CRMINQUERY:
- ADD_ACTIVE(next_state_offset + 1, 0);
- if (isinclass) { ADD_NEW(next_state_offset + 1, 0); }
- break;
-
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- count = current_state->count; /* Already matched */
- if (count >= GET2(ecode, 1))
- { ADD_ACTIVE(next_state_offset + 5, 0); }
- if (isinclass)
- {
- int max = GET2(ecode, 3);
- if (++count >= max && max != 0) /* Max 0 => no limit */
- { ADD_NEW(next_state_offset + 5, 0); }
- else
- { ADD_NEW(state_offset, count); }
- }
- break;
-
- default:
- if (isinclass) { ADD_NEW(next_state_offset, 0); }
- break;
- }
- }
- break;
-
-/* ========================================================================== */
- /* These are the opcodes for fancy brackets of various kinds. We have
- to use recursion in order to handle them. The "always failing" assersion
- (?!) is optimised when compiling to OP_FAIL, so we have to support that,
- though the other "backtracking verbs" are not supported. */
-
- case OP_FAIL:
- break;
-
- case OP_ASSERT:
- case OP_ASSERT_NOT:
- case OP_ASSERTBACK:
- case OP_ASSERTBACK_NOT:
- {
- int rc;
- int local_offsets[2];
- int local_workspace[1000];
- const uschar *endasscode = code + GET(code, 1);
-
- while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
-
- rc = internal_dfa_exec(
- md, /* static match data */
- code, /* this subexpression's code */
- ptr, /* where we currently are */
- ptr - start_subject, /* start offset */
- local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(int), /* size of same */
- local_workspace, /* workspace vector */
- sizeof(local_workspace)/sizeof(int), /* size of same */
- ims, /* the current ims flags */
- rlevel, /* function recursion level */
- recursing); /* pass on regex recursion */
-
- if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK))
- { ADD_ACTIVE(endasscode + LINK_SIZE + 1 - start_code, 0); }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_COND:
- case OP_SCOND:
- {
- int local_offsets[1000];
- int local_workspace[1000];
- int condcode = code[LINK_SIZE+1];
-
- /* Back reference conditions are not supported */
-
- if (condcode == OP_CREF) return PCRE_ERROR_DFA_UCOND;
-
- /* The DEFINE condition is always false */
-
- if (condcode == OP_DEF)
- {
- ADD_ACTIVE(state_offset + GET(code, 1) + LINK_SIZE + 1, 0);
- }
-
- /* The only supported version of OP_RREF is for the value RREF_ANY,
- which means "test if in any recursion". We can't test for specifically
- recursed groups. */
-
- else if (condcode == OP_RREF)
- {
- int value = GET2(code, LINK_SIZE+2);
- if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;
- if (recursing > 0) { ADD_ACTIVE(state_offset + LINK_SIZE + 4, 0); }
- else { ADD_ACTIVE(state_offset + GET(code, 1) + LINK_SIZE + 1, 0); }
- }
-
- /* Otherwise, the condition is an assertion */
-
- else
- {
- int rc;
- const uschar *asscode = code + LINK_SIZE + 1;
- const uschar *endasscode = asscode + GET(asscode, 1);
-
- while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
-
- rc = internal_dfa_exec(
- md, /* fixed match data */
- asscode, /* this subexpression's code */
- ptr, /* where we currently are */
- ptr - start_subject, /* start offset */
- local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(int), /* size of same */
- local_workspace, /* workspace vector */
- sizeof(local_workspace)/sizeof(int), /* size of same */
- ims, /* the current ims flags */
- rlevel, /* function recursion level */
- recursing); /* pass on regex recursion */
-
- if ((rc >= 0) ==
- (condcode == OP_ASSERT || condcode == OP_ASSERTBACK))
- { ADD_ACTIVE(endasscode + LINK_SIZE + 1 - start_code, 0); }
- else
- { ADD_ACTIVE(state_offset + GET(code, 1) + LINK_SIZE + 1, 0); }
- }
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_RECURSE:
- {
- int local_offsets[1000];
- int local_workspace[1000];
- int rc;
-
- DPRINTF(("%.*sStarting regex recursion %d\n", rlevel*2-2, SP,
- recursing + 1));
-
- rc = internal_dfa_exec(
- md, /* fixed match data */
- start_code + GET(code, 1), /* this subexpression's code */
- ptr, /* where we currently are */
- ptr - start_subject, /* start offset */
- local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(int), /* size of same */
- local_workspace, /* workspace vector */
- sizeof(local_workspace)/sizeof(int), /* size of same */
- ims, /* the current ims flags */
- rlevel, /* function recursion level */
- recursing + 1); /* regex recurse level */
-
- DPRINTF(("%.*sReturn from regex recursion %d: rc=%d\n", rlevel*2-2, SP,
- recursing + 1, rc));
-
- /* Ran out of internal offsets */
-
- if (rc == 0) return PCRE_ERROR_DFA_RECURSE;
-
- /* For each successful matched substring, set up the next state with a
- count of characters to skip before trying it. Note that the count is in
- characters, not bytes. */
-
- if (rc > 0)
- {
- for (rc = rc*2 - 2; rc >= 0; rc -= 2)
- {
- const uschar *p = start_subject + local_offsets[rc];
- const uschar *pp = start_subject + local_offsets[rc+1];
- int charcount = local_offsets[rc+1] - local_offsets[rc];
- while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;
- if (charcount > 0)
- {
- ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0, (charcount - 1));
- }
- else
- {
- ADD_ACTIVE(state_offset + LINK_SIZE + 1, 0);
- }
- }
- }
- else if (rc != PCRE_ERROR_NOMATCH) return rc;
- }
- break;
-
- /*-----------------------------------------------------------------*/
- case OP_ONCE:
- {
- int local_offsets[2];
- int local_workspace[1000];
-
- int rc = internal_dfa_exec(
- md, /* fixed match data */
- code, /* this subexpression's code */
- ptr, /* where we currently are */
- ptr - start_subject, /* start offset */
- local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(int), /* size of same */
- local_workspace, /* workspace vector */
- sizeof(local_workspace)/sizeof(int), /* size of same */
- ims, /* the current ims flags */
- rlevel, /* function recursion level */
- recursing); /* pass on regex recursion */
-
- if (rc >= 0)
- {
- const uschar *end_subpattern = code;
- int charcount = local_offsets[1] - local_offsets[0];
- int next_state_offset, repeat_state_offset;
-
- do { end_subpattern += GET(end_subpattern, 1); }
- while (*end_subpattern == OP_ALT);
- next_state_offset = end_subpattern - start_code + LINK_SIZE + 1;
-
- /* If the end of this subpattern is KETRMAX or KETRMIN, we must
- arrange for the repeat state also to be added to the relevant list.
- Calculate the offset, or set -1 for no repeat. */
-
- repeat_state_offset = (*end_subpattern == OP_KETRMAX ||
- *end_subpattern == OP_KETRMIN)?
- end_subpattern - start_code - GET(end_subpattern, 1) : -1;
-
- /* If we have matched an empty string, add the next state at the
- current character pointer. This is important so that the duplicate
- checking kicks in, which is what breaks infinite loops that match an
- empty string. */
-
- if (charcount == 0)
- {
- ADD_ACTIVE(next_state_offset, 0);
- }
-
- /* Optimization: if there are no more active states, and there
- are no new states yet set up, then skip over the subject string
- right here, to save looping. Otherwise, set up the new state to swing
- into action when the end of the substring is reached. */
-
- else if (i + 1 >= active_count && new_count == 0)
- {
- ptr += charcount;
- clen = 0;
- ADD_NEW(next_state_offset, 0);
-
- /* If we are adding a repeat state at the new character position,
- we must fudge things so that it is the only current state.
- Otherwise, it might be a duplicate of one we processed before, and
- that would cause it to be skipped. */
-
- if (repeat_state_offset >= 0)
- {
- next_active_state = active_states;
- active_count = 0;
- i = -1;
- ADD_ACTIVE(repeat_state_offset, 0);
- }
- }
- else
- {
- const uschar *p = start_subject + local_offsets[0];
- const uschar *pp = start_subject + local_offsets[1];
- while (p < pp) if ((*p++ & 0xc0) == 0x80) charcount--;
- ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
- if (repeat_state_offset >= 0)
- { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }
- }
-
- }
- else if (rc != PCRE_ERROR_NOMATCH) return rc;
- }
- break;
-
-
-/* ========================================================================== */
- /* Handle callouts */
-
- case OP_CALLOUT:
- if (pcre_callout != NULL)
- {
- int rrc;
- pcre_callout_block cb;
- cb.version = 1; /* Version 1 of the callout block */
- cb.callout_number = code[1];
- cb.offset_vector = offsets;
- cb.subject = (PCRE_SPTR)start_subject;
- cb.subject_length = end_subject - start_subject;
- cb.start_match = current_subject - start_subject;
- cb.current_position = ptr - start_subject;
- cb.pattern_position = GET(code, 2);
- cb.next_item_length = GET(code, 2 + LINK_SIZE);
- cb.capture_top = 1;
- cb.capture_last = -1;
- cb.callout_data = md->callout_data;
- if ((rrc = (*pcre_callout)(&cb)) < 0) return rrc; /* Abandon */
- if (rrc == 0) { ADD_ACTIVE(state_offset + 2 + 2*LINK_SIZE, 0); }
- }
- break;
-
-
-/* ========================================================================== */
- default: /* Unsupported opcode */
- return PCRE_ERROR_DFA_UITEM;
- }
-
- NEXT_ACTIVE_STATE: continue;
-
- } /* End of loop scanning active states */
-
- /* We have finished the processing at the current subject character. If no
- new states have been set for the next character, we have found all the
- matches that we are going to find. If we are at the top level and partial
- matching has been requested, check for appropriate conditions. */
-
- if (new_count <= 0)
- {
- if (match_count < 0 && /* No matches found */
- rlevel == 1 && /* Top level match function */
- (md->moptions & PCRE_PARTIAL) != 0 && /* Want partial matching */
- ptr >= end_subject && /* Reached end of subject */
- ptr > current_subject) /* Matched non-empty string */
- {
- if (offsetcount >= 2)
- {
- offsets[0] = current_subject - start_subject;
- offsets[1] = end_subject - start_subject;
- }
- match_count = PCRE_ERROR_PARTIAL;
- }
-
- DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n"
- "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, match_count,
- rlevel*2-2, SP));
- break; /* In effect, "return", but see the comment below */
- }
-
- /* One or more states are active for the next character. */
-
- ptr += clen; /* Advance to next subject character */
- } /* Loop to move along the subject string */
-
-/* Control gets here from "break" a few lines above. We do it this way because
-if we use "return" above, we have compiler trouble. Some compilers warn if
-there's nothing here because they think the function doesn't return a value. On
-the other hand, if we put a dummy statement here, some more clever compilers
-complain that it can't be reached. Sigh. */
-
-return match_count;
-}
-
-
-
-
-/*************************************************
-* Execute a Regular Expression - DFA engine *
-*************************************************/
-
-/* This external function applies a compiled re to a subject string using a DFA
-engine. This function calls the internal function multiple times if the pattern
-is not anchored.
-
-Arguments:
- argument_re points to the compiled expression
- extra_data points to extra data or is NULL
- subject points to the subject string
- length length of subject string (may contain binary zeros)
- start_offset where to start in the subject string
- options option bits
- offsets vector of match offsets
- offsetcount size of same
- workspace workspace vector
- wscount size of same
-
-Returns: > 0 => number of match offset pairs placed in offsets
- = 0 => offsets overflowed; longest matches are present
- -1 => failed to match
- < -1 => some kind of unexpected problem
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data,
- const char *subject, int length, int start_offset, int options, int *offsets,
- int offsetcount, int *workspace, int wscount)
-{
-real_pcre *re = (real_pcre *)argument_re;
-dfa_match_data match_block;
-dfa_match_data *md = &match_block;
-BOOL utf8, anchored, startline, firstline;
-const uschar *current_subject, *end_subject, *lcc;
-
-pcre_study_data internal_study;
-const pcre_study_data *study = NULL;
-real_pcre internal_re;
-
-const uschar *req_byte_ptr;
-const uschar *start_bits = NULL;
-BOOL first_byte_caseless = FALSE;
-BOOL req_byte_caseless = FALSE;
-int first_byte = -1;
-int req_byte = -1;
-int req_byte2 = -1;
-int newline;
-
-/* Plausibility checks */
-
-if ((options & ~PUBLIC_DFA_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
-if (re == NULL || subject == NULL || workspace == NULL ||
- (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
-if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;
-if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE;
-
-/* We need to find the pointer to any study data before we test for byte
-flipping, so we scan the extra_data block first. This may set two fields in the
-match block, so we must initialize them beforehand. However, the other fields
-in the match block must not be set until after the byte flipping. */
-
-md->tables = re->tables;
-md->callout_data = NULL;
-
-if (extra_data != NULL)
- {
- unsigned int flags = extra_data->flags;
- if ((flags & PCRE_EXTRA_STUDY_DATA) != 0)
- study = (const pcre_study_data *)extra_data->study_data;
- if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) return PCRE_ERROR_DFA_UMLIMIT;
- if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0)
- return PCRE_ERROR_DFA_UMLIMIT;
- if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0)
- md->callout_data = extra_data->callout_data;
- if ((flags & PCRE_EXTRA_TABLES) != 0)
- md->tables = extra_data->tables;
- }
-
-/* Check that the first field in the block is the magic number. If it is not,
-test for a regex that was compiled on a host of opposite endianness. If this is
-the case, flipped values are put in internal_re and internal_study if there was
-study data too. */
-
-if (re->magic_number != MAGIC_NUMBER)
- {
- re = _pcre_try_flipped(re, &internal_re, study, &internal_study);
- if (re == NULL) return PCRE_ERROR_BADMAGIC;
- if (study != NULL) study = &internal_study;
- }
-
-/* Set some local values */
-
-current_subject = (const unsigned char *)subject + start_offset;
-end_subject = (const unsigned char *)subject + length;
-req_byte_ptr = current_subject - 1;
-
-#ifdef SUPPORT_UTF8
-utf8 = (re->options & PCRE_UTF8) != 0;
-#else
-utf8 = FALSE;
-#endif
-
-anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 ||
- (re->options & PCRE_ANCHORED) != 0;
-
-/* The remaining fixed data for passing around. */
-
-md->start_code = (const uschar *)argument_re +
- re->name_table_offset + re->name_count * re->name_entry_size;
-md->start_subject = (const unsigned char *)subject;
-md->end_subject = end_subject;
-md->moptions = options;
-md->poptions = re->options;
-
-/* If the BSR option is not set at match time, copy what was set
-at compile time. */
-
-if ((md->moptions & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == 0)
- {
- if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0)
- md->moptions |= re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE);
-#ifdef BSR_ANYCRLF
- else md->moptions |= PCRE_BSR_ANYCRLF;
-#endif
- }
-
-/* Handle different types of newline. The three bits give eight cases. If
-nothing is set at run time, whatever was used at compile time applies. */
-
-switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) &
- PCRE_NEWLINE_BITS)
- {
- case 0: newline = NEWLINE; break; /* Compile-time default */
- case PCRE_NEWLINE_CR: newline = '\r'; break;
- case PCRE_NEWLINE_LF: newline = '\n'; break;
- case PCRE_NEWLINE_CR+
- PCRE_NEWLINE_LF: newline = ('\r' << 8) | '\n'; break;
- case PCRE_NEWLINE_ANY: newline = -1; break;
- case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
- default: return PCRE_ERROR_BADNEWLINE;
- }
-
-if (newline == -2)
- {
- md->nltype = NLTYPE_ANYCRLF;
- }
-else if (newline < 0)
- {
- md->nltype = NLTYPE_ANY;
- }
-else
- {
- md->nltype = NLTYPE_FIXED;
- if (newline > 255)
- {
- md->nllen = 2;
- md->nl[0] = (newline >> 8) & 255;
- md->nl[1] = newline & 255;
- }
- else
- {
- md->nllen = 1;
- md->nl[0] = newline;
- }
- }
-
-/* Check a UTF-8 string if required. Unfortunately there's no way of passing
-back the character offset. */
-
-#ifdef SUPPORT_UTF8
-if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)
- {
- if (_pcre_valid_utf8((uschar *)subject, length) >= 0)
- return PCRE_ERROR_BADUTF8;
- if (start_offset > 0 && start_offset < length)
- {
- int tb = ((uschar *)subject)[start_offset];
- if (tb > 127)
- {
- tb &= 0xc0;
- if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET;
- }
- }
- }
-#endif
-
-/* If the exec call supplied NULL for tables, use the inbuilt ones. This
-is a feature that makes it possible to save compiled regex and re-use them
-in other programs later. */
-
-if (md->tables == NULL) md->tables = _pcre_default_tables;
-
-/* The lower casing table and the "must be at the start of a line" flag are
-used in a loop when finding where to start. */
-
-lcc = md->tables + lcc_offset;
-startline = (re->flags & PCRE_STARTLINE) != 0;
-firstline = (re->options & PCRE_FIRSTLINE) != 0;
-
-/* Set up the first character to match, if available. The first_byte value is
-never set for an anchored regular expression, but the anchoring may be forced
-at run time, so we have to test for anchoring. The first char may be unset for
-an unanchored pattern, of course. If there's no first char and the pattern was
-studied, there may be a bitmap of possible first characters. */
-
-if (!anchored)
- {
- if ((re->flags & PCRE_FIRSTSET) != 0)
- {
- first_byte = re->first_byte & 255;
- if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE)
- first_byte = lcc[first_byte];
- }
- else
- {
- if (startline && study != NULL &&
- (study->options & PCRE_STUDY_MAPPED) != 0)
- start_bits = study->start_bits;
- }
- }
-
-/* For anchored or unanchored matches, there may be a "last known required
-character" set. */
-
-if ((re->flags & PCRE_REQCHSET) != 0)
- {
- req_byte = re->req_byte & 255;
- req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0;
- req_byte2 = (md->tables + fcc_offset)[req_byte]; /* case flipped */
- }
-
-/* Call the main matching function, looping for a non-anchored regex after a
-failed match. Unless restarting, optimize by moving to the first match
-character if possible, when not anchored. Then unless wanting a partial match,
-check for a required later character. */
-
-for (;;)
- {
- int rc;
-
- if ((options & PCRE_DFA_RESTART) == 0)
- {
- const uschar *save_end_subject = end_subject;
-
- /* Advance to a unique first char if possible. If firstline is TRUE, the
- start of the match is constrained to the first line of a multiline string.
- Implement this by temporarily adjusting end_subject so that we stop
- scanning at a newline. If the match fails at the newline, later code breaks
- this loop. */
-
- if (firstline)
- {
- USPTR t = current_subject;
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- while (t < md->end_subject && !IS_NEWLINE(t))
- {
- t++;
- while (t < end_subject && (*t & 0xc0) == 0x80) t++;
- }
- }
- else
-#endif
- while (t < md->end_subject && !IS_NEWLINE(t)) t++;
- end_subject = t;
- }
-
- if (first_byte >= 0)
- {
- if (first_byte_caseless)
- while (current_subject < end_subject &&
- lcc[*current_subject] != first_byte)
- current_subject++;
- else
- while (current_subject < end_subject && *current_subject != first_byte)
- current_subject++;
- }
-
- /* Or to just after a linebreak for a multiline match if possible */
-
- else if (startline)
- {
- if (current_subject > md->start_subject + start_offset)
- {
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- while (current_subject < end_subject && !WAS_NEWLINE(current_subject))
- {
- current_subject++;
- while(current_subject < end_subject &&
- (*current_subject & 0xc0) == 0x80)
- current_subject++;
- }
- }
- else
-#endif
- while (current_subject < end_subject && !WAS_NEWLINE(current_subject))
- current_subject++;
-
- /* If we have just passed a CR and the newline option is ANY or
- ANYCRLF, and we are now at a LF, advance the match position by one more
- character. */
-
- if (current_subject[-1] == '\r' &&
- (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
- current_subject < end_subject &&
- *current_subject == '\n')
- current_subject++;
- }
- }
-
- /* Or to a non-unique first char after study */
-
- else if (start_bits != NULL)
- {
- while (current_subject < end_subject)
- {
- register unsigned int c = *current_subject;
- if ((start_bits[c/8] & (1 << (c&7))) == 0) current_subject++;
- else break;
- }
- }
-
- /* Restore fudged end_subject */
-
- end_subject = save_end_subject;
- }
-
- /* If req_byte is set, we know that that character must appear in the subject
- for the match to succeed. If the first character is set, req_byte must be
- later in the subject; otherwise the test starts at the match point. This
- optimization can save a huge amount of work in patterns with nested unlimited
- repeats that aren't going to match. Writing separate code for cased/caseless
- versions makes it go faster, as does using an autoincrement and backing off
- on a match.
-
- HOWEVER: when the subject string is very, very long, searching to its end can
- take a long time, and give bad performance on quite ordinary patterns. This
- showed up when somebody was matching /^C/ on a 32-megabyte string... so we
- don't do this when the string is sufficiently long.
-
- ALSO: this processing is disabled when partial matching is requested.
- */
-
- if (req_byte >= 0 &&
- end_subject - current_subject < REQ_BYTE_MAX &&
- (options & PCRE_PARTIAL) == 0)
- {
- register const uschar *p = current_subject + ((first_byte >= 0)? 1 : 0);
-
- /* We don't need to repeat the search if we haven't yet reached the
- place we found it at last time. */
-
- if (p > req_byte_ptr)
- {
- if (req_byte_caseless)
- {
- while (p < end_subject)
- {
- register int pp = *p++;
- if (pp == req_byte || pp == req_byte2) { p--; break; }
- }
- }
- else
- {
- while (p < end_subject)
- {
- if (*p++ == req_byte) { p--; break; }
- }
- }
-
- /* If we can't find the required character, break the matching loop,
- which will cause a return or PCRE_ERROR_NOMATCH. */
-
- if (p >= end_subject) break;
-
- /* If we have found the required character, save the point where we
- found it, so that we don't search again next time round the loop if
- the start hasn't passed this character yet. */
-
- req_byte_ptr = p;
- }
- }
-
- /* OK, now we can do the business */
-
- rc = internal_dfa_exec(
- md, /* fixed match data */
- md->start_code, /* this subexpression's code */
- current_subject, /* where we currently are */
- start_offset, /* start offset in subject */
- offsets, /* offset vector */
- offsetcount, /* size of same */
- workspace, /* workspace vector */
- wscount, /* size of same */
- re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL), /* ims flags */
- 0, /* function recurse level */
- 0); /* regex recurse level */
-
- /* Anything other than "no match" means we are done, always; otherwise, carry
- on only if not anchored. */
-
- if (rc != PCRE_ERROR_NOMATCH || anchored) return rc;
-
- /* Advance to the next subject character unless we are at the end of a line
- and firstline is set. */
-
- if (firstline && IS_NEWLINE(current_subject)) break;
- current_subject++;
- if (utf8)
- {
- while (current_subject < end_subject && (*current_subject & 0xc0) == 0x80)
- current_subject++;
- }
- if (current_subject > end_subject) break;
-
- /* If we have just passed a CR and we are now at a LF, and the pattern does
- not contain any explicit matches for \r or \n, and the newline option is CRLF
- or ANY or ANYCRLF, advance the match position by one more character. */
-
- if (current_subject[-1] == '\r' &&
- current_subject < end_subject &&
- *current_subject == '\n' &&
- (re->flags & PCRE_HASCRORLF) == 0 &&
- (md->nltype == NLTYPE_ANY ||
- md->nltype == NLTYPE_ANYCRLF ||
- md->nllen == 2))
- current_subject++;
-
- } /* "Bumpalong" loop */
-
-return PCRE_ERROR_NOMATCH;
-}
-
-/* End of pcre_dfa_exec.c */
diff --git a/glib/pcre/pcre_exec.c b/glib/pcre/pcre_exec.c
deleted file mode 100644
index 06ce8f70e..000000000
--- a/glib/pcre/pcre_exec.c
+++ /dev/null
@@ -1,4998 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains pcre_exec(), the externally visible function that does
-pattern matching using an NFA algorithm, trying to mimic Perl as closely as
-possible. There are also some static supporting functions. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define NLBLOCK md /* Block containing newline information */
-#define PSSTART start_subject /* Field containing processed string start */
-#define PSEND end_subject /* Field containing processed string end */
-
-#include "pcre_internal.h"
-
-/* Undefine some potentially clashing cpp symbols */
-
-#undef min
-#undef max
-
-/* Flag bits for the match() function */
-
-#define match_condassert 0x01 /* Called to check a condition assertion */
-#define match_cbegroup 0x02 /* Could-be-empty unlimited repeat group */
-
-/* Non-error returns from the match() function. Error returns are externally
-defined PCRE_ERROR_xxx codes, which are all negative. */
-
-#define MATCH_MATCH 1
-#define MATCH_NOMATCH 0
-
-/* Special internal returns from the match() function. Make them sufficiently
-negative to avoid the external error codes. */
-
-#define MATCH_COMMIT (-999)
-#define MATCH_PRUNE (-998)
-#define MATCH_SKIP (-997)
-#define MATCH_THEN (-996)
-
-/* Maximum number of ints of offset to save on the stack for recursive calls.
-If the offset vector is bigger, malloc is used. This should be a multiple of 3,
-because the offset vector is always a multiple of 3 long. */
-
-#define REC_STACK_SAVE_MAX 30
-
-/* Min and max values for the common repeats; for the maxima, 0 => infinity */
-
-static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
-static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
-
-
-
-#ifdef DEBUG
-/*************************************************
-* Debugging function to print chars *
-*************************************************/
-
-/* Print a sequence of chars in printable format, stopping at the end of the
-subject if the requested.
-
-Arguments:
- p points to characters
- length number to print
- is_subject TRUE if printing from within md->start_subject
- md pointer to matching data block, if is_subject is TRUE
-
-Returns: nothing
-*/
-
-static void
-pchars(const uschar *p, int length, BOOL is_subject, match_data *md)
-{
-unsigned int c;
-if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
-while (length-- > 0)
- if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c);
-}
-#endif
-
-
-
-/*************************************************
-* Match a back-reference *
-*************************************************/
-
-/* If a back reference hasn't been set, the length that is passed is greater
-than the number of characters left in the string, so the match fails.
-
-Arguments:
- offset index into the offset vector
- eptr points into the subject
- length length to be matched
- md points to match data block
- ims the ims flags
-
-Returns: TRUE if matched
-*/
-
-static BOOL
-match_ref(int offset, register USPTR eptr, int length, match_data *md,
- unsigned long int ims)
-{
-USPTR p = md->start_subject + md->offset_vector[offset];
-
-#ifdef DEBUG
-if (eptr >= md->end_subject)
- printf("matching subject <null>");
-else
- {
- printf("matching subject ");
- pchars(eptr, length, TRUE, md);
- }
-printf(" against backref ");
-pchars(p, length, FALSE, md);
-printf("\n");
-#endif
-
-/* Always fail if not enough characters left */
-
-if (length > md->end_subject - eptr) return FALSE;
-
-/* Separate the caseless case for speed. In UTF-8 mode we can only do this
-properly if Unicode properties are supported. Otherwise, we can check only
-ASCII characters. */
-
-if ((ims & PCRE_CASELESS) != 0)
- {
-#ifdef SUPPORT_UTF8
-#ifdef SUPPORT_UCP
- if (md->utf8)
- {
- USPTR endptr = eptr + length;
- while (eptr < endptr)
- {
- int c, d;
- GETCHARINC(c, eptr);
- GETCHARINC(d, p);
- if (c != d && c != UCD_OTHERCASE(d)) return FALSE;
- }
- }
- else
-#endif
-#endif
-
- /* The same code works when not in UTF-8 mode and in UTF-8 mode when there
- is no UCP support. */
-
- while (length-- > 0)
- { if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE; }
- }
-
-/* In the caseful case, we can just compare the bytes, whether or not we
-are in UTF-8 mode. */
-
-else
- { while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
-
-return TRUE;
-}
-
-
-
-/***************************************************************************
-****************************************************************************
- RECURSION IN THE match() FUNCTION
-
-The match() function is highly recursive, though not every recursive call
-increases the recursive depth. Nevertheless, some regular expressions can cause
-it to recurse to a great depth. I was writing for Unix, so I just let it call
-itself recursively. This uses the stack for saving everything that has to be
-saved for a recursive call. On Unix, the stack can be large, and this works
-fine.
-
-It turns out that on some non-Unix-like systems there are problems with
-programs that use a lot of stack. (This despite the fact that every last chip
-has oodles of memory these days, and techniques for extending the stack have
-been known for decades.) So....
-
-There is a fudge, triggered by defining NO_RECURSE, which avoids recursive
-calls by keeping local variables that need to be preserved in blocks of memory
-obtained from malloc() instead instead of on the stack. Macros are used to
-achieve this so that the actual code doesn't look very different to what it
-always used to.
-
-The original heap-recursive code used longjmp(). However, it seems that this
-can be very slow on some operating systems. Following a suggestion from Stan
-Switzer, the use of longjmp() has been abolished, at the cost of having to
-provide a unique number for each call to RMATCH. There is no way of generating
-a sequence of numbers at compile time in C. I have given them names, to make
-them stand out more clearly.
-
-Crude tests on x86 Linux show a small speedup of around 5-8%. However, on
-FreeBSD, avoiding longjmp() more than halves the time taken to run the standard
-tests. Furthermore, not using longjmp() means that local dynamic variables
-don't have indeterminate values; this has meant that the frame size can be
-reduced because the result can be "passed back" by straight setting of the
-variable instead of being passed in the frame.
-****************************************************************************
-***************************************************************************/
-
-/* Numbers for RMATCH calls. When this list is changed, the code at HEAP_RETURN
-below must be updated in sync. */
-
-enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10,
- RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20,
- RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30,
- RM31, RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40,
- RM41, RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50,
- RM51, RM52, RM53, RM54 };
-
-/* These versions of the macros use the stack, as normal. There are debugging
-versions and production versions. Note that the "rw" argument of RMATCH isn't
-actuall used in this definition. */
-
-#ifndef NO_RECURSE
-#define REGISTER register
-
-#ifdef DEBUG
-#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \
- { \
- printf("match() called in line %d\n", __LINE__); \
- rrc = match(ra,rb,mstart,rc,rd,re,rf,rg,rdepth+1); \
- printf("to line %d\n", __LINE__); \
- }
-#define RRETURN(ra) \
- { \
- printf("match() returned %d from line %d ", ra, __LINE__); \
- return ra; \
- }
-#else
-#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw) \
- rrc = match(ra,rb,mstart,rc,rd,re,rf,rg,rdepth+1)
-#define RRETURN(ra) return ra
-#endif
-
-#else
-
-
-/* These versions of the macros manage a private stack on the heap. Note that
-the "rd" argument of RMATCH isn't actually used in this definition. It's the md
-argument of match(), which never changes. */
-
-#define REGISTER
-
-#define RMATCH(ra,rb,rc,rd,re,rf,rg,rw)\
- {\
- heapframe *newframe = (pcre_stack_malloc)(sizeof(heapframe));\
- frame->Xwhere = rw; \
- newframe->Xeptr = ra;\
- newframe->Xecode = rb;\
- newframe->Xmstart = mstart;\
- newframe->Xoffset_top = rc;\
- newframe->Xims = re;\
- newframe->Xeptrb = rf;\
- newframe->Xflags = rg;\
- newframe->Xrdepth = frame->Xrdepth + 1;\
- newframe->Xprevframe = frame;\
- frame = newframe;\
- DPRINTF(("restarting from line %d\n", __LINE__));\
- goto HEAP_RECURSE;\
- L_##rw:\
- DPRINTF(("jumped back to line %d\n", __LINE__));\
- }
-
-#define RRETURN(ra)\
- {\
- heapframe *newframe = frame;\
- frame = newframe->Xprevframe;\
- (pcre_stack_free)(newframe);\
- if (frame != NULL)\
- {\
- rrc = ra;\
- goto HEAP_RETURN;\
- }\
- return ra;\
- }
-
-
-/* Structure for remembering the local variables in a private frame */
-
-typedef struct heapframe {
- struct heapframe *Xprevframe;
-
- /* Function arguments that may change */
-
- const uschar *Xeptr;
- const uschar *Xecode;
- const uschar *Xmstart;
- int Xoffset_top;
- long int Xims;
- eptrblock *Xeptrb;
- int Xflags;
- unsigned int Xrdepth;
-
- /* Function local variables */
-
- const uschar *Xcallpat;
- const uschar *Xcharptr;
- const uschar *Xdata;
- const uschar *Xnext;
- const uschar *Xpp;
- const uschar *Xprev;
- const uschar *Xsaved_eptr;
-
- recursion_info Xnew_recursive;
-
- BOOL Xcur_is_word;
- BOOL Xcondition;
- BOOL Xprev_is_word;
-
- unsigned long int Xoriginal_ims;
-
-#ifdef SUPPORT_UCP
- int Xprop_type;
- int Xprop_value;
- int Xprop_fail_result;
- int Xprop_category;
- int Xprop_chartype;
- int Xprop_script;
- int Xoclength;
- uschar Xocchars[8];
-#endif
-
- int Xctype;
- unsigned int Xfc;
- int Xfi;
- int Xlength;
- int Xmax;
- int Xmin;
- int Xnumber;
- int Xoffset;
- int Xop;
- int Xsave_capture_last;
- int Xsave_offset1, Xsave_offset2, Xsave_offset3;
- int Xstacksave[REC_STACK_SAVE_MAX];
-
- eptrblock Xnewptrb;
-
- /* Where to jump back to */
-
- int Xwhere;
-
-} heapframe;
-
-#endif
-
-
-/***************************************************************************
-***************************************************************************/
-
-
-
-/*************************************************
-* Match from current position *
-*************************************************/
-
-/* This function is called recursively in many circumstances. Whenever it
-returns a negative (error) response, the outer incarnation must also return the
-same response.
-
-Performance note: It might be tempting to extract commonly used fields from the
-md structure (e.g. utf8, end_subject) into individual variables to improve
-performance. Tests using gcc on a SPARC disproved this; in the first case, it
-made performance worse.
-
-Arguments:
- eptr pointer to current character in subject
- ecode pointer to current position in compiled code
- mstart pointer to the current match start position (can be modified
- by encountering \K)
- offset_top current top pointer
- md pointer to "static" info for the match
- ims current /i, /m, and /s options
- eptrb pointer to chain of blocks containing eptr at start of
- brackets - for testing for empty matches
- flags can contain
- match_condassert - this is an assertion condition
- match_cbegroup - this is the start of an unlimited repeat
- group that can match an empty string
- rdepth the recursion depth
-
-Returns: MATCH_MATCH if matched ) these values are >= 0
- MATCH_NOMATCH if failed to match )
- a negative PCRE_ERROR_xxx value if aborted by an error condition
- (e.g. stopped by repeated call or recursion limit)
-*/
-
-static int
-match(REGISTER USPTR eptr, REGISTER const uschar *ecode, const uschar *mstart,
- int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
- int flags, unsigned int rdepth)
-{
-/* These variables do not need to be preserved over recursion in this function,
-so they can be ordinary variables in all cases. Mark some of them with
-"register" because they are used a lot in loops. */
-
-register int rrc; /* Returns from recursive calls */
-register int i; /* Used for loops not involving calls to RMATCH() */
-register unsigned int c; /* Character values not kept over RMATCH() calls */
-register BOOL utf8; /* Local copy of UTF-8 flag for speed */
-
-BOOL minimize, possessive; /* Quantifier options */
-
-/* When recursion is not being used, all "local" variables that have to be
-preserved over calls to RMATCH() are part of a "frame" which is obtained from
-heap storage. Set up the top-level frame here; others are obtained from the
-heap whenever RMATCH() does a "recursion". See the macro definitions above. */
-
-#ifdef NO_RECURSE
-heapframe *frame = (pcre_stack_malloc)(sizeof(heapframe));
-frame->Xprevframe = NULL; /* Marks the top level */
-
-/* Copy in the original argument variables */
-
-frame->Xeptr = eptr;
-frame->Xecode = ecode;
-frame->Xmstart = mstart;
-frame->Xoffset_top = offset_top;
-frame->Xims = ims;
-frame->Xeptrb = eptrb;
-frame->Xflags = flags;
-frame->Xrdepth = rdepth;
-
-/* This is where control jumps back to to effect "recursion" */
-
-HEAP_RECURSE:
-
-/* Macros make the argument variables come from the current frame */
-
-#define eptr frame->Xeptr
-#define ecode frame->Xecode
-#define mstart frame->Xmstart
-#define offset_top frame->Xoffset_top
-#define ims frame->Xims
-#define eptrb frame->Xeptrb
-#define flags frame->Xflags
-#define rdepth frame->Xrdepth
-
-/* Ditto for the local variables */
-
-#ifdef SUPPORT_UTF8
-#define charptr frame->Xcharptr
-#endif
-#define callpat frame->Xcallpat
-#define data frame->Xdata
-#define next frame->Xnext
-#define pp frame->Xpp
-#define prev frame->Xprev
-#define saved_eptr frame->Xsaved_eptr
-
-#define new_recursive frame->Xnew_recursive
-
-#define cur_is_word frame->Xcur_is_word
-#define condition frame->Xcondition
-#define prev_is_word frame->Xprev_is_word
-
-#define original_ims frame->Xoriginal_ims
-
-#ifdef SUPPORT_UCP
-#define prop_type frame->Xprop_type
-#define prop_value frame->Xprop_value
-#define prop_fail_result frame->Xprop_fail_result
-#define prop_category frame->Xprop_category
-#define prop_chartype frame->Xprop_chartype
-#define prop_script frame->Xprop_script
-#define oclength frame->Xoclength
-#define occhars frame->Xocchars
-#endif
-
-#define ctype frame->Xctype
-#define fc frame->Xfc
-#define fi frame->Xfi
-#define length frame->Xlength
-#define max frame->Xmax
-#define min frame->Xmin
-#define number frame->Xnumber
-#define offset frame->Xoffset
-#define op frame->Xop
-#define save_capture_last frame->Xsave_capture_last
-#define save_offset1 frame->Xsave_offset1
-#define save_offset2 frame->Xsave_offset2
-#define save_offset3 frame->Xsave_offset3
-#define stacksave frame->Xstacksave
-
-#define newptrb frame->Xnewptrb
-
-/* When recursion is being used, local variables are allocated on the stack and
-get preserved during recursion in the normal way. In this environment, fi and
-i, and fc and c, can be the same variables. */
-
-#else /* NO_RECURSE not defined */
-#define fi i
-#define fc c
-
-
-#ifdef SUPPORT_UTF8 /* Many of these variables are used only */
-const uschar *charptr; /* in small blocks of the code. My normal */
-#endif /* style of coding would have declared */
-const uschar *callpat; /* them within each of those blocks. */
-const uschar *data; /* However, in order to accommodate the */
-const uschar *next; /* version of this code that uses an */
-USPTR pp; /* external "stack" implemented on the */
-const uschar *prev; /* heap, it is easier to declare them all */
-USPTR saved_eptr; /* here, so the declarations can be cut */
- /* out in a block. The only declarations */
-recursion_info new_recursive; /* within blocks below are for variables */
- /* that do not have to be preserved over */
-BOOL cur_is_word; /* a recursive call to RMATCH(). */
-BOOL condition;
-BOOL prev_is_word;
-
-unsigned long int original_ims;
-
-#ifdef SUPPORT_UCP
-int prop_type;
-int prop_value;
-int prop_fail_result;
-int prop_category;
-int prop_chartype;
-int prop_script;
-int oclength;
-uschar occhars[8];
-#endif
-
-int ctype;
-int length;
-int max;
-int min;
-int number;
-int offset;
-int op;
-int save_capture_last;
-int save_offset1, save_offset2, save_offset3;
-int stacksave[REC_STACK_SAVE_MAX];
-
-eptrblock newptrb;
-#endif /* NO_RECURSE */
-
-/* These statements are here to stop the compiler complaining about unitialized
-variables. */
-
-#ifdef SUPPORT_UCP
-prop_value = 0;
-prop_fail_result = 0;
-#endif
-
-
-/* This label is used for tail recursion, which is used in a few cases even
-when NO_RECURSE is not defined, in order to reduce the amount of stack that is
-used. Thanks to Ian Taylor for noticing this possibility and sending the
-original patch. */
-
-TAIL_RECURSE:
-
-/* OK, now we can get on with the real code of the function. Recursive calls
-are specified by the macro RMATCH and RRETURN is used to return. When
-NO_RECURSE is *not* defined, these just turn into a recursive call to match()
-and a "return", respectively (possibly with some debugging if DEBUG is
-defined). However, RMATCH isn't like a function call because it's quite a
-complicated macro. It has to be used in one particular way. This shouldn't,
-however, impact performance when true recursion is being used. */
-
-#ifdef SUPPORT_UTF8
-utf8 = md->utf8; /* Local copy of the flag */
-#else
-utf8 = FALSE;
-#endif
-
-/* First check that we haven't called match() too many times, or that we
-haven't exceeded the recursive call limit. */
-
-if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT);
-if (rdepth >= md->match_limit_recursion) RRETURN(PCRE_ERROR_RECURSIONLIMIT);
-
-original_ims = ims; /* Save for resetting on ')' */
-
-/* At the start of a group with an unlimited repeat that may match an empty
-string, the match_cbegroup flag is set. When this is the case, add the current
-subject pointer to the chain of such remembered pointers, to be checked when we
-hit the closing ket, in order to break infinite loops that match no characters.
-When match() is called in other circumstances, don't add to the chain. The
-match_cbegroup flag must NOT be used with tail recursion, because the memory
-block that is used is on the stack, so a new one may be required for each
-match(). */
-
-if ((flags & match_cbegroup) != 0)
- {
- newptrb.epb_saved_eptr = eptr;
- newptrb.epb_prev = eptrb;
- eptrb = &newptrb;
- }
-
-/* Now start processing the opcodes. */
-
-for (;;)
- {
- minimize = possessive = FALSE;
- op = *ecode;
-
- /* For partial matching, remember if we ever hit the end of the subject after
- matching at least one subject character. */
-
- if (md->partial &&
- eptr >= md->end_subject &&
- eptr > mstart)
- md->hitend = TRUE;
-
- switch(op)
- {
- case OP_FAIL:
- RRETURN(MATCH_NOMATCH);
-
- case OP_PRUNE:
- RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
- ims, eptrb, flags, RM51);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- RRETURN(MATCH_PRUNE);
-
- case OP_COMMIT:
- RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
- ims, eptrb, flags, RM52);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- RRETURN(MATCH_COMMIT);
-
- case OP_SKIP:
- RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
- ims, eptrb, flags, RM53);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- md->start_match_ptr = eptr; /* Pass back current position */
- RRETURN(MATCH_SKIP);
-
- case OP_THEN:
- RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
- ims, eptrb, flags, RM54);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- RRETURN(MATCH_THEN);
-
- /* Handle a capturing bracket. If there is space in the offset vector, save
- the current subject position in the working slot at the top of the vector.
- We mustn't change the current values of the data slot, because they may be
- set from a previous iteration of this group, and be referred to by a
- reference inside the group.
-
- If the bracket fails to match, we need to restore this value and also the
- values of the final offsets, in case they were set by a previous iteration
- of the same bracket.
-
- If there isn't enough space in the offset vector, treat this as if it were
- a non-capturing bracket. Don't worry about setting the flag for the error
- case here; that is handled in the code for KET. */
-
- case OP_CBRA:
- case OP_SCBRA:
- number = GET2(ecode, 1+LINK_SIZE);
- offset = number << 1;
-
-#ifdef DEBUG
- printf("start bracket %d\n", number);
- printf("subject=");
- pchars(eptr, 16, TRUE, md);
- printf("\n");
-#endif
-
- if (offset < md->offset_max)
- {
- save_offset1 = md->offset_vector[offset];
- save_offset2 = md->offset_vector[offset+1];
- save_offset3 = md->offset_vector[md->offset_end - number];
- save_capture_last = md->capture_last;
-
- DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
- md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
-
- flags = (op == OP_SCBRA)? match_cbegroup : 0;
- do
- {
- RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
- ims, eptrb, flags, RM1);
- if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
- md->capture_last = save_capture_last;
- ecode += GET(ecode, 1);
- }
- while (*ecode == OP_ALT);
-
- DPRINTF(("bracket %d failed\n", number));
-
- md->offset_vector[offset] = save_offset1;
- md->offset_vector[offset+1] = save_offset2;
- md->offset_vector[md->offset_end - number] = save_offset3;
-
- RRETURN(MATCH_NOMATCH);
- }
-
- /* FALL THROUGH ... Insufficient room for saving captured contents. Treat
- as a non-capturing bracket. */
-
- /* VVVVVVVVVVVVVVVVVVVVVVVVV */
- /* VVVVVVVVVVVVVVVVVVVVVVVVV */
-
- DPRINTF(("insufficient capture room: treat as non-capturing\n"));
-
- /* VVVVVVVVVVVVVVVVVVVVVVVVV */
- /* VVVVVVVVVVVVVVVVVVVVVVVVV */
-
- /* Non-capturing bracket. Loop for all the alternatives. When we get to the
- final alternative within the brackets, we would return the result of a
- recursive call to match() whatever happened. We can reduce stack usage by
- turning this into a tail recursion, except in the case when match_cbegroup
- is set.*/
-
- case OP_BRA:
- case OP_SBRA:
- DPRINTF(("start non-capturing bracket\n"));
- flags = (op >= OP_SBRA)? match_cbegroup : 0;
- for (;;)
- {
- if (ecode[GET(ecode, 1)] != OP_ALT) /* Final alternative */
- {
- if (flags == 0) /* Not a possibly empty group */
- {
- ecode += _pcre_OP_lengths[*ecode];
- DPRINTF(("bracket 0 tail recursion\n"));
- goto TAIL_RECURSE;
- }
-
- /* Possibly empty group; can't use tail recursion. */
-
- RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims,
- eptrb, flags, RM48);
- RRETURN(rrc);
- }
-
- /* For non-final alternatives, continue the loop for a NOMATCH result;
- otherwise return. */
-
- RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md, ims,
- eptrb, flags, RM2);
- if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
- ecode += GET(ecode, 1);
- }
- /* Control never reaches here. */
-
- /* Conditional group: compilation checked that there are no more than
- two branches. If the condition is false, skipping the first branch takes us
- past the end if there is only one branch, but that's OK because that is
- exactly what going to the ket would do. As there is only one branch to be
- obeyed, we can use tail recursion to avoid using another stack frame. */
-
- case OP_COND:
- case OP_SCOND:
- if (ecode[LINK_SIZE+1] == OP_RREF) /* Recursion test */
- {
- offset = GET2(ecode, LINK_SIZE + 2); /* Recursion group number*/
- condition = md->recursive != NULL &&
- (offset == RREF_ANY || offset == md->recursive->group_num);
- ecode += condition? 3 : GET(ecode, 1);
- }
-
- else if (ecode[LINK_SIZE+1] == OP_CREF) /* Group used test */
- {
- offset = GET2(ecode, LINK_SIZE+2) << 1; /* Doubled ref number */
- condition = offset < offset_top && md->offset_vector[offset] >= 0;
- ecode += condition? 3 : GET(ecode, 1);
- }
-
- else if (ecode[LINK_SIZE+1] == OP_DEF) /* DEFINE - always false */
- {
- condition = FALSE;
- ecode += GET(ecode, 1);
- }
-
- /* The condition is an assertion. Call match() to evaluate it - setting
- the final argument match_condassert causes it to stop at the end of an
- assertion. */
-
- else
- {
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL,
- match_condassert, RM3);
- if (rrc == MATCH_MATCH)
- {
- condition = TRUE;
- ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE + 2);
- while (*ecode == OP_ALT) ecode += GET(ecode, 1);
- }
- else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)
- {
- RRETURN(rrc); /* Need braces because of following else */
- }
- else
- {
- condition = FALSE;
- ecode += GET(ecode, 1);
- }
- }
-
- /* We are now at the branch that is to be obeyed. As there is only one,
- we can use tail recursion to avoid using another stack frame, except when
- match_cbegroup is required for an unlimited repeat of a possibly empty
- group. If the second alternative doesn't exist, we can just plough on. */
-
- if (condition || *ecode == OP_ALT)
- {
- ecode += 1 + LINK_SIZE;
- if (op == OP_SCOND) /* Possibly empty group */
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, match_cbegroup, RM49);
- RRETURN(rrc);
- }
- else /* Group must match something */
- {
- flags = 0;
- goto TAIL_RECURSE;
- }
- }
- else /* Condition false & no 2nd alternative */
- {
- ecode += 1 + LINK_SIZE;
- }
- break;
-
-
- /* End of the pattern, either real or forced. If we are in a top-level
- recursion, we should restore the offsets appropriately and continue from
- after the call. */
-
- case OP_ACCEPT:
- case OP_END:
- if (md->recursive != NULL && md->recursive->group_num == 0)
- {
- recursion_info *rec = md->recursive;
- DPRINTF(("End of pattern in a (?0) recursion\n"));
- md->recursive = rec->prevrec;
- memmove(md->offset_vector, rec->offset_save,
- rec->saved_max * sizeof(int));
- mstart = rec->save_start;
- ims = original_ims;
- ecode = rec->after_call;
- break;
- }
-
- /* Otherwise, if PCRE_NOTEMPTY is set, fail if we have matched an empty
- string - backtracking will then try other alternatives, if any. */
-
- if (md->notempty && eptr == mstart) RRETURN(MATCH_NOMATCH);
- md->end_match_ptr = eptr; /* Record where we ended */
- md->end_offset_top = offset_top; /* and how many extracts were taken */
- md->start_match_ptr = mstart; /* and the start (\K can modify) */
- RRETURN(MATCH_MATCH);
-
- /* Change option settings */
-
- case OP_OPT:
- ims = ecode[1];
- ecode += 2;
- DPRINTF(("ims set to %02lx\n", ims));
- break;
-
- /* Assertion brackets. Check the alternative branches in turn - the
- matching won't pass the KET for an assertion. If any one branch matches,
- the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
- start of each branch to move the current point backwards, so the code at
- this level is identical to the lookahead case. */
-
- case OP_ASSERT:
- case OP_ASSERTBACK:
- do
- {
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,
- RM4);
- if (rrc == MATCH_MATCH) break;
- if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
- ecode += GET(ecode, 1);
- }
- while (*ecode == OP_ALT);
- if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH);
-
- /* If checking an assertion for a condition, return MATCH_MATCH. */
-
- if ((flags & match_condassert) != 0) RRETURN(MATCH_MATCH);
-
- /* Continue from after the assertion, updating the offsets high water
- mark, since extracts may have been taken during the assertion. */
-
- do ecode += GET(ecode,1); while (*ecode == OP_ALT);
- ecode += 1 + LINK_SIZE;
- offset_top = md->end_offset_top;
- continue;
-
- /* Negative assertion: all branches must fail to match */
-
- case OP_ASSERT_NOT:
- case OP_ASSERTBACK_NOT:
- do
- {
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, NULL, 0,
- RM5);
- if (rrc == MATCH_MATCH) RRETURN(MATCH_NOMATCH);
- if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
- ecode += GET(ecode,1);
- }
- while (*ecode == OP_ALT);
-
- if ((flags & match_condassert) != 0) RRETURN(MATCH_MATCH);
-
- ecode += 1 + LINK_SIZE;
- continue;
-
- /* Move the subject pointer back. This occurs only at the start of
- each branch of a lookbehind assertion. If we are too close to the start to
- move back, this match function fails. When working with UTF-8 we move
- back a number of characters, not bytes. */
-
- case OP_REVERSE:
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- i = GET(ecode, 1);
- while (i-- > 0)
- {
- eptr--;
- if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
- BACKCHAR(eptr);
- }
- }
- else
-#endif
-
- /* No UTF-8 support, or not in UTF-8 mode: count is byte count */
-
- {
- eptr -= GET(ecode, 1);
- if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
- }
-
- /* Skip to next op code */
-
- ecode += 1 + LINK_SIZE;
- break;
-
- /* The callout item calls an external function, if one is provided, passing
- details of the match so far. This is mainly for debugging, though the
- function is able to force a failure. */
-
- case OP_CALLOUT:
- if (pcre_callout != NULL)
- {
- pcre_callout_block cb;
- cb.version = 1; /* Version 1 of the callout block */
- cb.callout_number = ecode[1];
- cb.offset_vector = md->offset_vector;
- cb.subject = (PCRE_SPTR)md->start_subject;
- cb.subject_length = md->end_subject - md->start_subject;
- cb.start_match = mstart - md->start_subject;
- cb.current_position = eptr - md->start_subject;
- cb.pattern_position = GET(ecode, 2);
- cb.next_item_length = GET(ecode, 2 + LINK_SIZE);
- cb.capture_top = offset_top/2;
- cb.capture_last = md->capture_last;
- cb.callout_data = md->callout_data;
- if ((rrc = (*pcre_callout)(&cb)) > 0) RRETURN(MATCH_NOMATCH);
- if (rrc < 0) RRETURN(rrc);
- }
- ecode += 2 + 2*LINK_SIZE;
- break;
-
- /* Recursion either matches the current regex, or some subexpression. The
- offset data is the offset to the starting bracket from the start of the
- whole pattern. (This is so that it works from duplicated subpatterns.)
-
- If there are any capturing brackets started but not finished, we have to
- save their starting points and reinstate them after the recursion. However,
- we don't know how many such there are (offset_top records the completed
- total) so we just have to save all the potential data. There may be up to
- 65535 such values, which is too large to put on the stack, but using malloc
- for small numbers seems expensive. As a compromise, the stack is used when
- there are no more than REC_STACK_SAVE_MAX values to store; otherwise malloc
- is used. A problem is what to do if the malloc fails ... there is no way of
- returning to the top level with an error. Save the top REC_STACK_SAVE_MAX
- values on the stack, and accept that the rest may be wrong.
-
- There are also other values that have to be saved. We use a chained
- sequence of blocks that actually live on the stack. Thanks to Robin Houston
- for the original version of this logic. */
-
- case OP_RECURSE:
- {
- callpat = md->start_code + GET(ecode, 1);
- new_recursive.group_num = (callpat == md->start_code)? 0 :
- GET2(callpat, 1 + LINK_SIZE);
-
- /* Add to "recursing stack" */
-
- new_recursive.prevrec = md->recursive;
- md->recursive = &new_recursive;
-
- /* Find where to continue from afterwards */
-
- ecode += 1 + LINK_SIZE;
- new_recursive.after_call = ecode;
-
- /* Now save the offset data. */
-
- new_recursive.saved_max = md->offset_end;
- if (new_recursive.saved_max <= REC_STACK_SAVE_MAX)
- new_recursive.offset_save = stacksave;
- else
- {
- new_recursive.offset_save =
- (int *)(pcre_malloc)(new_recursive.saved_max * sizeof(int));
- if (new_recursive.offset_save == NULL) RRETURN(PCRE_ERROR_NOMEMORY);
- }
-
- memcpy(new_recursive.offset_save, md->offset_vector,
- new_recursive.saved_max * sizeof(int));
- new_recursive.save_start = mstart;
- mstart = eptr;
-
- /* OK, now we can do the recursion. For each top-level alternative we
- restore the offset and recursion data. */
-
- DPRINTF(("Recursing into group %d\n", new_recursive.group_num));
- flags = (*callpat >= OP_SBRA)? match_cbegroup : 0;
- do
- {
- RMATCH(eptr, callpat + _pcre_OP_lengths[*callpat], offset_top,
- md, ims, eptrb, flags, RM6);
- if (rrc == MATCH_MATCH)
- {
- DPRINTF(("Recursion matched\n"));
- md->recursive = new_recursive.prevrec;
- if (new_recursive.offset_save != stacksave)
- (pcre_free)(new_recursive.offset_save);
- RRETURN(MATCH_MATCH);
- }
- else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN)
- {
- DPRINTF(("Recursion gave error %d\n", rrc));
- RRETURN(rrc);
- }
-
- md->recursive = &new_recursive;
- memcpy(md->offset_vector, new_recursive.offset_save,
- new_recursive.saved_max * sizeof(int));
- callpat += GET(callpat, 1);
- }
- while (*callpat == OP_ALT);
-
- DPRINTF(("Recursion didn't match\n"));
- md->recursive = new_recursive.prevrec;
- if (new_recursive.offset_save != stacksave)
- (pcre_free)(new_recursive.offset_save);
- RRETURN(MATCH_NOMATCH);
- }
- /* Control never reaches here */
-
- /* "Once" brackets are like assertion brackets except that after a match,
- the point in the subject string is not moved back. Thus there can never be
- a move back into the brackets. Friedl calls these "atomic" subpatterns.
- Check the alternative branches in turn - the matching won't pass the KET
- for this kind of subpattern. If any one branch matches, we carry on as at
- the end of a normal bracket, leaving the subject pointer. */
-
- case OP_ONCE:
- prev = ecode;
- saved_eptr = eptr;
-
- do
- {
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM7);
- if (rrc == MATCH_MATCH) break;
- if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
- ecode += GET(ecode,1);
- }
- while (*ecode == OP_ALT);
-
- /* If hit the end of the group (which could be repeated), fail */
-
- if (*ecode != OP_ONCE && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH);
-
- /* Continue as from after the assertion, updating the offsets high water
- mark, since extracts may have been taken. */
-
- do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
-
- offset_top = md->end_offset_top;
- eptr = md->end_match_ptr;
-
- /* For a non-repeating ket, just continue at this level. This also
- happens for a repeating ket if no characters were matched in the group.
- This is the forcible breaking of infinite loops as implemented in Perl
- 5.005. If there is an options reset, it will get obeyed in the normal
- course of events. */
-
- if (*ecode == OP_KET || eptr == saved_eptr)
- {
- ecode += 1+LINK_SIZE;
- break;
- }
-
- /* The repeating kets try the rest of the pattern or restart from the
- preceding bracket, in the appropriate order. The second "call" of match()
- uses tail recursion, to avoid using another stack frame. We need to reset
- any options that changed within the bracket before re-running it, so
- check the next opcode. */
-
- if (ecode[1+LINK_SIZE] == OP_OPT)
- {
- ims = (ims & ~PCRE_IMS) | ecode[4];
- DPRINTF(("ims set to %02lx at group repeat\n", ims));
- }
-
- if (*ecode == OP_KETRMIN)
- {
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM8);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- ecode = prev;
- flags = 0;
- goto TAIL_RECURSE;
- }
- else /* OP_KETRMAX */
- {
- RMATCH(eptr, prev, offset_top, md, ims, eptrb, match_cbegroup, RM9);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- ecode += 1 + LINK_SIZE;
- flags = 0;
- goto TAIL_RECURSE;
- }
- /* Control never gets here */
-
- /* An alternation is the end of a branch; scan along to find the end of the
- bracketed group and go to there. */
-
- case OP_ALT:
- do ecode += GET(ecode,1); while (*ecode == OP_ALT);
- break;
-
- /* BRAZERO, BRAMINZERO and SKIPZERO occur just before a bracket group,
- indicating that it may occur zero times. It may repeat infinitely, or not
- at all - i.e. it could be ()* or ()? or even (){0} in the pattern. Brackets
- with fixed upper repeat limits are compiled as a number of copies, with the
- optional ones preceded by BRAZERO or BRAMINZERO. */
-
- case OP_BRAZERO:
- {
- next = ecode+1;
- RMATCH(eptr, next, offset_top, md, ims, eptrb, 0, RM10);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- do next += GET(next,1); while (*next == OP_ALT);
- ecode = next + 1 + LINK_SIZE;
- }
- break;
-
- case OP_BRAMINZERO:
- {
- next = ecode+1;
- do next += GET(next, 1); while (*next == OP_ALT);
- RMATCH(eptr, next + 1+LINK_SIZE, offset_top, md, ims, eptrb, 0, RM11);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- ecode++;
- }
- break;
-
- case OP_SKIPZERO:
- {
- next = ecode+1;
- do next += GET(next,1); while (*next == OP_ALT);
- ecode = next + 1 + LINK_SIZE;
- }
- break;
-
- /* End of a group, repeated or non-repeating. */
-
- case OP_KET:
- case OP_KETRMIN:
- case OP_KETRMAX:
- prev = ecode - GET(ecode, 1);
-
- /* If this was a group that remembered the subject start, in order to break
- infinite repeats of empty string matches, retrieve the subject start from
- the chain. Otherwise, set it NULL. */
-
- if (*prev >= OP_SBRA)
- {
- saved_eptr = eptrb->epb_saved_eptr; /* Value at start of group */
- eptrb = eptrb->epb_prev; /* Backup to previous group */
- }
- else saved_eptr = NULL;
-
- /* If we are at the end of an assertion group, stop matching and return
- MATCH_MATCH, but record the current high water mark for use by positive
- assertions. Do this also for the "once" (atomic) groups. */
-
- if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
- *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
- *prev == OP_ONCE)
- {
- md->end_match_ptr = eptr; /* For ONCE */
- md->end_offset_top = offset_top;
- RRETURN(MATCH_MATCH);
- }
-
- /* For capturing groups we have to check the group number back at the start
- and if necessary complete handling an extraction by setting the offsets and
- bumping the high water mark. Note that whole-pattern recursion is coded as
- a recurse into group 0, so it won't be picked up here. Instead, we catch it
- when the OP_END is reached. Other recursion is handled here. */
-
- if (*prev == OP_CBRA || *prev == OP_SCBRA)
- {
- number = GET2(prev, 1+LINK_SIZE);
- offset = number << 1;
-
-#ifdef DEBUG
- printf("end bracket %d", number);
- printf("\n");
-#endif
-
- md->capture_last = number;
- if (offset >= md->offset_max) md->offset_overflow = TRUE; else
- {
- md->offset_vector[offset] =
- md->offset_vector[md->offset_end - number];
- md->offset_vector[offset+1] = eptr - md->start_subject;
- if (offset_top <= offset) offset_top = offset + 2;
- }
-
- /* Handle a recursively called group. Restore the offsets
- appropriately and continue from after the call. */
-
- if (md->recursive != NULL && md->recursive->group_num == number)
- {
- recursion_info *rec = md->recursive;
- DPRINTF(("Recursion (%d) succeeded - continuing\n", number));
- md->recursive = rec->prevrec;
- mstart = rec->save_start;
- memcpy(md->offset_vector, rec->offset_save,
- rec->saved_max * sizeof(int));
- ecode = rec->after_call;
- ims = original_ims;
- break;
- }
- }
-
- /* For both capturing and non-capturing groups, reset the value of the ims
- flags, in case they got changed during the group. */
-
- ims = original_ims;
- DPRINTF(("ims reset to %02lx\n", ims));
-
- /* For a non-repeating ket, just continue at this level. This also
- happens for a repeating ket if no characters were matched in the group.
- This is the forcible breaking of infinite loops as implemented in Perl
- 5.005. If there is an options reset, it will get obeyed in the normal
- course of events. */
-
- if (*ecode == OP_KET || eptr == saved_eptr)
- {
- ecode += 1 + LINK_SIZE;
- break;
- }
-
- /* The repeating kets try the rest of the pattern or restart from the
- preceding bracket, in the appropriate order. In the second case, we can use
- tail recursion to avoid using another stack frame, unless we have an
- unlimited repeat of a group that can match an empty string. */
-
- flags = (*prev >= OP_SBRA)? match_cbegroup : 0;
-
- if (*ecode == OP_KETRMIN)
- {
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, ims, eptrb, 0, RM12);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (flags != 0) /* Could match an empty string */
- {
- RMATCH(eptr, prev, offset_top, md, ims, eptrb, flags, RM50);
- RRETURN(rrc);
- }
- ecode = prev;
- goto TAIL_RECURSE;
- }
- else /* OP_KETRMAX */
- {
- RMATCH(eptr, prev, offset_top, md, ims, eptrb, flags, RM13);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- ecode += 1 + LINK_SIZE;
- flags = 0;
- goto TAIL_RECURSE;
- }
- /* Control never gets here */
-
- /* Start of subject unless notbol, or after internal newline if multiline */
-
- case OP_CIRC:
- if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);
- if ((ims & PCRE_MULTILINE) != 0)
- {
- if (eptr != md->start_subject &&
- (eptr == md->end_subject || !WAS_NEWLINE(eptr)))
- RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
- }
- /* ... else fall through */
-
- /* Start of subject assertion */
-
- case OP_SOD:
- if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
-
- /* Start of match assertion */
-
- case OP_SOM:
- if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
-
- /* Reset the start of match point */
-
- case OP_SET_SOM:
- mstart = eptr;
- ecode++;
- break;
-
- /* Assert before internal newline if multiline, or before a terminating
- newline unless endonly is set, else end of subject unless noteol is set. */
-
- case OP_DOLL:
- if ((ims & PCRE_MULTILINE) != 0)
- {
- if (eptr < md->end_subject)
- { if (!IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); }
- else
- { if (md->noteol) RRETURN(MATCH_NOMATCH); }
- ecode++;
- break;
- }
- else
- {
- if (md->noteol) RRETURN(MATCH_NOMATCH);
- if (!md->endonly)
- {
- if (eptr != md->end_subject &&
- (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen))
- RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
- }
- }
- /* ... else fall through for endonly */
-
- /* End of subject assertion (\z) */
-
- case OP_EOD:
- if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
-
- /* End of subject or ending \n assertion (\Z) */
-
- case OP_EODN:
- if (eptr != md->end_subject &&
- (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen))
- RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
-
- /* Word boundary assertions */
-
- case OP_NOT_WORD_BOUNDARY:
- case OP_WORD_BOUNDARY:
- {
-
- /* Find out if the previous and current characters are "word" characters.
- It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to
- be "non-word" characters. */
-
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- if (eptr == md->start_subject) prev_is_word = FALSE; else
- {
- const uschar *lastptr = eptr - 1;
- while((*lastptr & 0xc0) == 0x80) lastptr--;
- GETCHAR(c, lastptr);
- prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
- }
- if (eptr >= md->end_subject) cur_is_word = FALSE; else
- {
- GETCHAR(c, eptr);
- cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
- }
- }
- else
-#endif
-
- /* More streamlined when not in UTF-8 mode */
-
- {
- prev_is_word = (eptr != md->start_subject) &&
- ((md->ctypes[eptr[-1]] & ctype_word) != 0);
- cur_is_word = (eptr < md->end_subject) &&
- ((md->ctypes[*eptr] & ctype_word) != 0);
- }
-
- /* Now see if the situation is what we want */
-
- if ((*ecode++ == OP_WORD_BOUNDARY)?
- cur_is_word == prev_is_word : cur_is_word != prev_is_word)
- RRETURN(MATCH_NOMATCH);
- }
- break;
-
- /* Match a single character type; inline for speed */
-
- case OP_ANY:
- if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
- /* Fall through */
-
- case OP_ALLANY:
- if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH);
- if (utf8) while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
- ecode++;
- break;
-
- /* Match a single byte, even in UTF-8 mode. This opcode really does match
- any byte, even newline, independent of the setting of PCRE_DOTALL. */
-
- case OP_ANYBYTE:
- if (eptr++ >= md->end_subject) RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
-
- case OP_NOT_DIGIT:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- if (
-#ifdef SUPPORT_UTF8
- c < 256 &&
-#endif
- (md->ctypes[c] & ctype_digit) != 0
- )
- RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
-
- case OP_DIGIT:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- if (
-#ifdef SUPPORT_UTF8
- c >= 256 ||
-#endif
- (md->ctypes[c] & ctype_digit) == 0
- )
- RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
-
- case OP_NOT_WHITESPACE:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- if (
-#ifdef SUPPORT_UTF8
- c < 256 &&
-#endif
- (md->ctypes[c] & ctype_space) != 0
- )
- RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
-
- case OP_WHITESPACE:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- if (
-#ifdef SUPPORT_UTF8
- c >= 256 ||
-#endif
- (md->ctypes[c] & ctype_space) == 0
- )
- RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
-
- case OP_NOT_WORDCHAR:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- if (
-#ifdef SUPPORT_UTF8
- c < 256 &&
-#endif
- (md->ctypes[c] & ctype_word) != 0
- )
- RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
-
- case OP_WORDCHAR:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- if (
-#ifdef SUPPORT_UTF8
- c >= 256 ||
-#endif
- (md->ctypes[c] & ctype_word) == 0
- )
- RRETURN(MATCH_NOMATCH);
- ecode++;
- break;
-
- case OP_ANYNL:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x000d:
- if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
- break;
-
- case 0x000a:
- break;
-
- case 0x000b:
- case 0x000c:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
- break;
- }
- ecode++;
- break;
-
- case OP_NOT_HSPACE:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- switch(c)
- {
- default: break;
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- RRETURN(MATCH_NOMATCH);
- }
- ecode++;
- break;
-
- case OP_HSPACE:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- break;
- }
- ecode++;
- break;
-
- case OP_NOT_VSPACE:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- switch(c)
- {
- default: break;
- case 0x0a: /* LF */
- case 0x0b: /* VT */
- case 0x0c: /* FF */
- case 0x0d: /* CR */
- case 0x85: /* NEL */
- case 0x2028: /* LINE SEPARATOR */
- case 0x2029: /* PARAGRAPH SEPARATOR */
- RRETURN(MATCH_NOMATCH);
- }
- ecode++;
- break;
-
- case OP_VSPACE:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x0a: /* LF */
- case 0x0b: /* VT */
- case 0x0c: /* FF */
- case 0x0d: /* CR */
- case 0x85: /* NEL */
- case 0x2028: /* LINE SEPARATOR */
- case 0x2029: /* PARAGRAPH SEPARATOR */
- break;
- }
- ecode++;
- break;
-
-#ifdef SUPPORT_UCP
- /* Check the next character by Unicode property. We will get here only
- if the support is in the binary; otherwise a compile-time error occurs. */
-
- case OP_PROP:
- case OP_NOTPROP:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- {
- int chartype = UCD_CHARTYPE(c);
- switch(ecode[1])
- {
- case PT_ANY:
- if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
- break;
-
- case PT_LAMP:
- if ((chartype == ucp_Lu ||
- chartype == ucp_Ll ||
- chartype == ucp_Lt) == (op == OP_NOTPROP))
- RRETURN(MATCH_NOMATCH);
- break;
-
- case PT_GC:
- if ((ecode[2] != _pcre_ucp_gentype[chartype]) == (op == OP_PROP))
- RRETURN(MATCH_NOMATCH);
- break;
-
- case PT_PC:
- if ((ecode[2] != chartype) == (op == OP_PROP))
- RRETURN(MATCH_NOMATCH);
- break;
-
- case PT_SC:
- if ((ecode[2] != UCD_SCRIPT(c)) == (op == OP_PROP))
- RRETURN(MATCH_NOMATCH);
- break;
-
- default:
- RRETURN(PCRE_ERROR_INTERNAL);
- }
-
- ecode += 3;
- }
- break;
-
- /* Match an extended Unicode sequence. We will get here only if the support
- is in the binary; otherwise a compile-time error occurs. */
-
- case OP_EXTUNI:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- {
- int category = UCD_CATEGORY(c);
- if (category == ucp_M) RRETURN(MATCH_NOMATCH);
- while (eptr < md->end_subject)
- {
- int len = 1;
- if (!utf8) c = *eptr; else
- {
- GETCHARLEN(c, eptr, len);
- }
- category = UCD_CATEGORY(c);
- if (category != ucp_M) break;
- eptr += len;
- }
- }
- ecode++;
- break;
-#endif
-
-
- /* Match a back reference, possibly repeatedly. Look past the end of the
- item to see if there is repeat information following. The code is similar
- to that for character classes, but repeated for efficiency. Then obey
- similar code to character type repeats - written out again for speed.
- However, if the referenced string is the empty string, always treat
- it as matched, any number of times (otherwise there could be infinite
- loops). */
-
- case OP_REF:
- {
- offset = GET2(ecode, 1) << 1; /* Doubled ref number */
- ecode += 3;
-
- /* If the reference is unset, there are two possibilities:
-
- (a) In the default, Perl-compatible state, set the length to be longer
- than the amount of subject left; this ensures that every attempt at a
- match fails. We can't just fail here, because of the possibility of
- quantifiers with zero minima.
-
- (b) If the JavaScript compatibility flag is set, set the length to zero
- so that the back reference matches an empty string.
-
- Otherwise, set the length to the length of what was matched by the
- referenced subpattern. */
-
- if (offset >= offset_top || md->offset_vector[offset] < 0)
- length = (md->jscript_compat)? 0 : md->end_subject - eptr + 1;
- else
- length = md->offset_vector[offset+1] - md->offset_vector[offset];
-
- /* Set up for repetition, or handle the non-repeated case */
-
- switch (*ecode)
- {
- case OP_CRSTAR:
- case OP_CRMINSTAR:
- case OP_CRPLUS:
- case OP_CRMINPLUS:
- case OP_CRQUERY:
- case OP_CRMINQUERY:
- c = *ecode++ - OP_CRSTAR;
- minimize = (c & 1) != 0;
- min = rep_min[c]; /* Pick up values from tables; */
- max = rep_max[c]; /* zero for max => infinity */
- if (max == 0) max = INT_MAX;
- break;
-
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- minimize = (*ecode == OP_CRMINRANGE);
- min = GET2(ecode, 1);
- max = GET2(ecode, 3);
- if (max == 0) max = INT_MAX;
- ecode += 5;
- break;
-
- default: /* No repeat follows */
- if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH);
- eptr += length;
- continue; /* With the main loop */
- }
-
- /* If the length of the reference is zero, just continue with the
- main loop. */
-
- if (length == 0) continue;
-
- /* First, ensure the minimum number of matches are present. We get back
- the length of the reference string explicitly rather than passing the
- address of eptr, so that eptr can be a register variable. */
-
- for (i = 1; i <= min; i++)
- {
- if (!match_ref(offset, eptr, length, md, ims)) RRETURN(MATCH_NOMATCH);
- eptr += length;
- }
-
- /* If min = max, continue at the same level without recursion.
- They are not both allowed to be zero. */
-
- if (min == max) continue;
-
- /* If minimizing, keep trying and advancing the pointer */
-
- if (minimize)
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM14);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || !match_ref(offset, eptr, length, md, ims))
- RRETURN(MATCH_NOMATCH);
- eptr += length;
- }
- /* Control never gets here */
- }
-
- /* If maximizing, find the longest string and work backwards */
-
- else
- {
- pp = eptr;
- for (i = min; i < max; i++)
- {
- if (!match_ref(offset, eptr, length, md, ims)) break;
- eptr += length;
- }
- while (eptr >= pp)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM15);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- eptr -= length;
- }
- RRETURN(MATCH_NOMATCH);
- }
- }
- /* Control never gets here */
-
-
-
- /* Match a bit-mapped character class, possibly repeatedly. This op code is
- used when all the characters in the class have values in the range 0-255,
- and either the matching is caseful, or the characters are in the range
- 0-127 when UTF-8 processing is enabled. The only difference between
- OP_CLASS and OP_NCLASS occurs when a data character outside the range is
- encountered.
-
- First, look past the end of the item to see if there is repeat information
- following. Then obey similar code to character type repeats - written out
- again for speed. */
-
- case OP_NCLASS:
- case OP_CLASS:
- {
- data = ecode + 1; /* Save for matching */
- ecode += 33; /* Advance past the item */
-
- switch (*ecode)
- {
- case OP_CRSTAR:
- case OP_CRMINSTAR:
- case OP_CRPLUS:
- case OP_CRMINPLUS:
- case OP_CRQUERY:
- case OP_CRMINQUERY:
- c = *ecode++ - OP_CRSTAR;
- minimize = (c & 1) != 0;
- min = rep_min[c]; /* Pick up values from tables; */
- max = rep_max[c]; /* zero for max => infinity */
- if (max == 0) max = INT_MAX;
- break;
-
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- minimize = (*ecode == OP_CRMINRANGE);
- min = GET2(ecode, 1);
- max = GET2(ecode, 3);
- if (max == 0) max = INT_MAX;
- ecode += 5;
- break;
-
- default: /* No repeat follows */
- min = max = 1;
- break;
- }
-
- /* First, ensure the minimum number of matches are present. */
-
-#ifdef SUPPORT_UTF8
- /* UTF-8 mode */
- if (utf8)
- {
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- if (c > 255)
- {
- if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
- }
- else
- {
- if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
- }
- }
- }
- else
-#endif
- /* Not UTF-8 mode */
- {
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- c = *eptr++;
- if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
- }
- }
-
- /* If max == min we can continue with the main loop without the
- need to recurse. */
-
- if (min == max) continue;
-
- /* If minimizing, keep testing the rest of the expression and advancing
- the pointer while it matches the class. */
-
- if (minimize)
- {
-#ifdef SUPPORT_UTF8
- /* UTF-8 mode */
- if (utf8)
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM16);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- if (c > 255)
- {
- if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
- }
- else
- {
- if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
- }
- }
- }
- else
-#endif
- /* Not UTF-8 mode */
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM17);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- c = *eptr++;
- if ((data[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH);
- }
- }
- /* Control never gets here */
- }
-
- /* If maximizing, find the longest possible run, then work backwards. */
-
- else
- {
- pp = eptr;
-
-#ifdef SUPPORT_UTF8
- /* UTF-8 mode */
- if (utf8)
- {
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- if (c > 255)
- {
- if (op == OP_CLASS) break;
- }
- else
- {
- if ((data[c/8] & (1 << (c&7))) == 0) break;
- }
- eptr += len;
- }
- for (;;)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM18);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (eptr-- == pp) break; /* Stop if tried at original pos */
- BACKCHAR(eptr);
- }
- }
- else
-#endif
- /* Not UTF-8 mode */
- {
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject) break;
- c = *eptr;
- if ((data[c/8] & (1 << (c&7))) == 0) break;
- eptr++;
- }
- while (eptr >= pp)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM19);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- eptr--;
- }
- }
-
- RRETURN(MATCH_NOMATCH);
- }
- }
- /* Control never gets here */
-
-
- /* Match an extended character class. This opcode is encountered only
- in UTF-8 mode, because that's the only time it is compiled. */
-
-#ifdef SUPPORT_UTF8
- case OP_XCLASS:
- {
- data = ecode + 1 + LINK_SIZE; /* Save for matching */
- ecode += GET(ecode, 1); /* Advance past the item */
-
- switch (*ecode)
- {
- case OP_CRSTAR:
- case OP_CRMINSTAR:
- case OP_CRPLUS:
- case OP_CRMINPLUS:
- case OP_CRQUERY:
- case OP_CRMINQUERY:
- c = *ecode++ - OP_CRSTAR;
- minimize = (c & 1) != 0;
- min = rep_min[c]; /* Pick up values from tables; */
- max = rep_max[c]; /* zero for max => infinity */
- if (max == 0) max = INT_MAX;
- break;
-
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- minimize = (*ecode == OP_CRMINRANGE);
- min = GET2(ecode, 1);
- max = GET2(ecode, 3);
- if (max == 0) max = INT_MAX;
- ecode += 5;
- break;
-
- default: /* No repeat follows */
- min = max = 1;
- break;
- }
-
- /* First, ensure the minimum number of matches are present. */
-
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);
- }
-
- /* If max == min we can continue with the main loop without the
- need to recurse. */
-
- if (min == max) continue;
-
- /* If minimizing, keep testing the rest of the expression and advancing
- the pointer while it matches the class. */
-
- if (minimize)
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM20);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- if (!_pcre_xclass(c, data)) RRETURN(MATCH_NOMATCH);
- }
- /* Control never gets here */
- }
-
- /* If maximizing, find the longest possible run, then work backwards. */
-
- else
- {
- pp = eptr;
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- if (!_pcre_xclass(c, data)) break;
- eptr += len;
- }
- for(;;)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM21);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (eptr-- == pp) break; /* Stop if tried at original pos */
- if (utf8) BACKCHAR(eptr);
- }
- RRETURN(MATCH_NOMATCH);
- }
-
- /* Control never gets here */
- }
-#endif /* End of XCLASS */
-
- /* Match a single character, casefully */
-
- case OP_CHAR:
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- length = 1;
- ecode++;
- GETCHARLEN(fc, ecode, length);
- if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
- while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH);
- }
- else
-#endif
-
- /* Non-UTF-8 mode */
- {
- if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH);
- if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH);
- ecode += 2;
- }
- break;
-
- /* Match a single character, caselessly */
-
- case OP_CHARNC:
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- length = 1;
- ecode++;
- GETCHARLEN(fc, ecode, length);
-
- if (length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
-
- /* If the pattern character's value is < 128, we have only one byte, and
- can use the fast lookup table. */
-
- if (fc < 128)
- {
- if (md->lcc[*ecode++] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
- }
-
- /* Otherwise we must pick up the subject character */
-
- else
- {
- unsigned int dc;
- GETCHARINC(dc, eptr);
- ecode += length;
-
- /* If we have Unicode property support, we can use it to test the other
- case of the character, if there is one. */
-
- if (fc != dc)
- {
-#ifdef SUPPORT_UCP
- if (dc != UCD_OTHERCASE(fc))
-#endif
- RRETURN(MATCH_NOMATCH);
- }
- }
- }
- else
-#endif /* SUPPORT_UTF8 */
-
- /* Non-UTF-8 mode */
- {
- if (md->end_subject - eptr < 1) RRETURN(MATCH_NOMATCH);
- if (md->lcc[ecode[1]] != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
- ecode += 2;
- }
- break;
-
- /* Match a single character repeatedly. */
-
- case OP_EXACT:
- min = max = GET2(ecode, 1);
- ecode += 3;
- goto REPEATCHAR;
-
- case OP_POSUPTO:
- possessive = TRUE;
- /* Fall through */
-
- case OP_UPTO:
- case OP_MINUPTO:
- min = 0;
- max = GET2(ecode, 1);
- minimize = *ecode == OP_MINUPTO;
- ecode += 3;
- goto REPEATCHAR;
-
- case OP_POSSTAR:
- possessive = TRUE;
- min = 0;
- max = INT_MAX;
- ecode++;
- goto REPEATCHAR;
-
- case OP_POSPLUS:
- possessive = TRUE;
- min = 1;
- max = INT_MAX;
- ecode++;
- goto REPEATCHAR;
-
- case OP_POSQUERY:
- possessive = TRUE;
- min = 0;
- max = 1;
- ecode++;
- goto REPEATCHAR;
-
- case OP_STAR:
- case OP_MINSTAR:
- case OP_PLUS:
- case OP_MINPLUS:
- case OP_QUERY:
- case OP_MINQUERY:
- c = *ecode++ - OP_STAR;
- minimize = (c & 1) != 0;
- min = rep_min[c]; /* Pick up values from tables; */
- max = rep_max[c]; /* zero for max => infinity */
- if (max == 0) max = INT_MAX;
-
- /* Common code for all repeated single-character matches. We can give
- up quickly if there are fewer than the minimum number of characters left in
- the subject. */
-
- REPEATCHAR:
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- length = 1;
- charptr = ecode;
- GETCHARLEN(fc, ecode, length);
- if (min * length > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
- ecode += length;
-
- /* Handle multibyte character matching specially here. There is
- support for caseless matching if UCP support is present. */
-
- if (length > 1)
- {
-#ifdef SUPPORT_UCP
- unsigned int othercase;
- if ((ims & PCRE_CASELESS) != 0 &&
- (othercase = UCD_OTHERCASE(fc)) != fc)
- oclength = _pcre_ord2utf8(othercase, occhars);
- else oclength = 0;
-#endif /* SUPPORT_UCP */
-
- for (i = 1; i <= min; i++)
- {
- if (memcmp(eptr, charptr, length) == 0) eptr += length;
-#ifdef SUPPORT_UCP
- /* Need braces because of following else */
- else if (oclength == 0) { RRETURN(MATCH_NOMATCH); }
- else
- {
- if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH);
- eptr += oclength;
- }
-#else /* without SUPPORT_UCP */
- else { RRETURN(MATCH_NOMATCH); }
-#endif /* SUPPORT_UCP */
- }
-
- if (min == max) continue;
-
- if (minimize)
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM22);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- if (memcmp(eptr, charptr, length) == 0) eptr += length;
-#ifdef SUPPORT_UCP
- /* Need braces because of following else */
- else if (oclength == 0) { RRETURN(MATCH_NOMATCH); }
- else
- {
- if (memcmp(eptr, occhars, oclength) != 0) RRETURN(MATCH_NOMATCH);
- eptr += oclength;
- }
-#else /* without SUPPORT_UCP */
- else { RRETURN (MATCH_NOMATCH); }
-#endif /* SUPPORT_UCP */
- }
- /* Control never gets here */
- }
-
- else /* Maximize */
- {
- pp = eptr;
- for (i = min; i < max; i++)
- {
- if (eptr > md->end_subject - length) break;
- if (memcmp(eptr, charptr, length) == 0) eptr += length;
-#ifdef SUPPORT_UCP
- else if (oclength == 0) break;
- else
- {
- if (memcmp(eptr, occhars, oclength) != 0) break;
- eptr += oclength;
- }
-#else /* without SUPPORT_UCP */
- else break;
-#endif /* SUPPORT_UCP */
- }
-
- if (possessive) continue;
- for(;;)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM23);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (eptr == pp) RRETURN(MATCH_NOMATCH);
-#ifdef SUPPORT_UCP
- eptr--;
- BACKCHAR(eptr);
-#else /* without SUPPORT_UCP */
- eptr -= length;
-#endif /* SUPPORT_UCP */
- }
- }
- /* Control never gets here */
- }
-
- /* If the length of a UTF-8 character is 1, we fall through here, and
- obey the code as for non-UTF-8 characters below, though in this case the
- value of fc will always be < 128. */
- }
- else
-#endif /* SUPPORT_UTF8 */
-
- /* When not in UTF-8 mode, load a single-byte character. */
- {
- if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
- fc = *ecode++;
- }
-
- /* The value of fc at this point is always less than 256, though we may or
- may not be in UTF-8 mode. The code is duplicated for the caseless and
- caseful cases, for speed, since matching characters is likely to be quite
- common. First, ensure the minimum number of matches are present. If min =
- max, continue at the same level without recursing. Otherwise, if
- minimizing, keep trying the rest of the expression and advancing one
- matching character if failing, up to the maximum. Alternatively, if
- maximizing, find the maximum number of characters and work backwards. */
-
- DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max,
- max, eptr));
-
- if ((ims & PCRE_CASELESS) != 0)
- {
- fc = md->lcc[fc];
- for (i = 1; i <= min; i++)
- if (fc != md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
- if (min == max) continue;
- if (minimize)
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM24);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject ||
- fc != md->lcc[*eptr++])
- RRETURN(MATCH_NOMATCH);
- }
- /* Control never gets here */
- }
- else /* Maximize */
- {
- pp = eptr;
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || fc != md->lcc[*eptr]) break;
- eptr++;
- }
- if (possessive) continue;
- while (eptr >= pp)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM25);
- eptr--;
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- }
- RRETURN(MATCH_NOMATCH);
- }
- /* Control never gets here */
- }
-
- /* Caseful comparisons (includes all multi-byte characters) */
-
- else
- {
- for (i = 1; i <= min; i++) if (fc != *eptr++) RRETURN(MATCH_NOMATCH);
- if (min == max) continue;
- if (minimize)
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM26);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject || fc != *eptr++)
- RRETURN(MATCH_NOMATCH);
- }
- /* Control never gets here */
- }
- else /* Maximize */
- {
- pp = eptr;
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || fc != *eptr) break;
- eptr++;
- }
- if (possessive) continue;
- while (eptr >= pp)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM27);
- eptr--;
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- }
- RRETURN(MATCH_NOMATCH);
- }
- }
- /* Control never gets here */
-
- /* Match a negated single one-byte character. The character we are
- checking can be multibyte. */
-
- case OP_NOT:
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- ecode++;
- GETCHARINCTEST(c, eptr);
- if ((ims & PCRE_CASELESS) != 0)
- {
-#ifdef SUPPORT_UTF8
- if (c < 256)
-#endif
- c = md->lcc[c];
- if (md->lcc[*ecode++] == c) RRETURN(MATCH_NOMATCH);
- }
- else
- {
- if (*ecode++ == c) RRETURN(MATCH_NOMATCH);
- }
- break;
-
- /* Match a negated single one-byte character repeatedly. This is almost a
- repeat of the code for a repeated single character, but I haven't found a
- nice way of commoning these up that doesn't require a test of the
- positive/negative option for each character match. Maybe that wouldn't add
- very much to the time taken, but character matching *is* what this is all
- about... */
-
- case OP_NOTEXACT:
- min = max = GET2(ecode, 1);
- ecode += 3;
- goto REPEATNOTCHAR;
-
- case OP_NOTUPTO:
- case OP_NOTMINUPTO:
- min = 0;
- max = GET2(ecode, 1);
- minimize = *ecode == OP_NOTMINUPTO;
- ecode += 3;
- goto REPEATNOTCHAR;
-
- case OP_NOTPOSSTAR:
- possessive = TRUE;
- min = 0;
- max = INT_MAX;
- ecode++;
- goto REPEATNOTCHAR;
-
- case OP_NOTPOSPLUS:
- possessive = TRUE;
- min = 1;
- max = INT_MAX;
- ecode++;
- goto REPEATNOTCHAR;
-
- case OP_NOTPOSQUERY:
- possessive = TRUE;
- min = 0;
- max = 1;
- ecode++;
- goto REPEATNOTCHAR;
-
- case OP_NOTPOSUPTO:
- possessive = TRUE;
- min = 0;
- max = GET2(ecode, 1);
- ecode += 3;
- goto REPEATNOTCHAR;
-
- case OP_NOTSTAR:
- case OP_NOTMINSTAR:
- case OP_NOTPLUS:
- case OP_NOTMINPLUS:
- case OP_NOTQUERY:
- case OP_NOTMINQUERY:
- c = *ecode++ - OP_NOTSTAR;
- minimize = (c & 1) != 0;
- min = rep_min[c]; /* Pick up values from tables; */
- max = rep_max[c]; /* zero for max => infinity */
- if (max == 0) max = INT_MAX;
-
- /* Common code for all repeated single-byte matches. We can give up quickly
- if there are fewer than the minimum number of bytes left in the
- subject. */
-
- REPEATNOTCHAR:
- if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
- fc = *ecode++;
-
- /* The code is duplicated for the caseless and caseful cases, for speed,
- since matching characters is likely to be quite common. First, ensure the
- minimum number of matches are present. If min = max, continue at the same
- level without recursing. Otherwise, if minimizing, keep trying the rest of
- the expression and advancing one matching character if failing, up to the
- maximum. Alternatively, if maximizing, find the maximum number of
- characters and work backwards. */
-
- DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max,
- max, eptr));
-
- if ((ims & PCRE_CASELESS) != 0)
- {
- fc = md->lcc[fc];
-
-#ifdef SUPPORT_UTF8
- /* UTF-8 mode */
- if (utf8)
- {
- register unsigned int d;
- for (i = 1; i <= min; i++)
- {
- GETCHARINC(d, eptr);
- if (d < 256) d = md->lcc[d];
- if (fc == d) RRETURN(MATCH_NOMATCH);
- }
- }
- else
-#endif
-
- /* Not UTF-8 mode */
- {
- for (i = 1; i <= min; i++)
- if (fc == md->lcc[*eptr++]) RRETURN(MATCH_NOMATCH);
- }
-
- if (min == max) continue;
-
- if (minimize)
- {
-#ifdef SUPPORT_UTF8
- /* UTF-8 mode */
- if (utf8)
- {
- register unsigned int d;
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM28);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(d, eptr);
- if (d < 256) d = md->lcc[d];
- if (fc == d) RRETURN(MATCH_NOMATCH);
-
- }
- }
- else
-#endif
- /* Not UTF-8 mode */
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM29);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject || fc == md->lcc[*eptr++])
- RRETURN(MATCH_NOMATCH);
- }
- }
- /* Control never gets here */
- }
-
- /* Maximize case */
-
- else
- {
- pp = eptr;
-
-#ifdef SUPPORT_UTF8
- /* UTF-8 mode */
- if (utf8)
- {
- register unsigned int d;
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(d, eptr, len);
- if (d < 256) d = md->lcc[d];
- if (fc == d) break;
- eptr += len;
- }
- if (possessive) continue;
- for(;;)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM30);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (eptr-- == pp) break; /* Stop if tried at original pos */
- BACKCHAR(eptr);
- }
- }
- else
-#endif
- /* Not UTF-8 mode */
- {
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || fc == md->lcc[*eptr]) break;
- eptr++;
- }
- if (possessive) continue;
- while (eptr >= pp)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM31);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- eptr--;
- }
- }
-
- RRETURN(MATCH_NOMATCH);
- }
- /* Control never gets here */
- }
-
- /* Caseful comparisons */
-
- else
- {
-#ifdef SUPPORT_UTF8
- /* UTF-8 mode */
- if (utf8)
- {
- register unsigned int d;
- for (i = 1; i <= min; i++)
- {
- GETCHARINC(d, eptr);
- if (fc == d) RRETURN(MATCH_NOMATCH);
- }
- }
- else
-#endif
- /* Not UTF-8 mode */
- {
- for (i = 1; i <= min; i++)
- if (fc == *eptr++) RRETURN(MATCH_NOMATCH);
- }
-
- if (min == max) continue;
-
- if (minimize)
- {
-#ifdef SUPPORT_UTF8
- /* UTF-8 mode */
- if (utf8)
- {
- register unsigned int d;
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM32);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(d, eptr);
- if (fc == d) RRETURN(MATCH_NOMATCH);
- }
- }
- else
-#endif
- /* Not UTF-8 mode */
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM33);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject || fc == *eptr++)
- RRETURN(MATCH_NOMATCH);
- }
- }
- /* Control never gets here */
- }
-
- /* Maximize case */
-
- else
- {
- pp = eptr;
-
-#ifdef SUPPORT_UTF8
- /* UTF-8 mode */
- if (utf8)
- {
- register unsigned int d;
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(d, eptr, len);
- if (fc == d) break;
- eptr += len;
- }
- if (possessive) continue;
- for(;;)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM34);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (eptr-- == pp) break; /* Stop if tried at original pos */
- BACKCHAR(eptr);
- }
- }
- else
-#endif
- /* Not UTF-8 mode */
- {
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || fc == *eptr) break;
- eptr++;
- }
- if (possessive) continue;
- while (eptr >= pp)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM35);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- eptr--;
- }
- }
-
- RRETURN(MATCH_NOMATCH);
- }
- }
- /* Control never gets here */
-
- /* Match a single character type repeatedly; several different opcodes
- share code. This is very similar to the code for single characters, but we
- repeat it in the interests of efficiency. */
-
- case OP_TYPEEXACT:
- min = max = GET2(ecode, 1);
- minimize = TRUE;
- ecode += 3;
- goto REPEATTYPE;
-
- case OP_TYPEUPTO:
- case OP_TYPEMINUPTO:
- min = 0;
- max = GET2(ecode, 1);
- minimize = *ecode == OP_TYPEMINUPTO;
- ecode += 3;
- goto REPEATTYPE;
-
- case OP_TYPEPOSSTAR:
- possessive = TRUE;
- min = 0;
- max = INT_MAX;
- ecode++;
- goto REPEATTYPE;
-
- case OP_TYPEPOSPLUS:
- possessive = TRUE;
- min = 1;
- max = INT_MAX;
- ecode++;
- goto REPEATTYPE;
-
- case OP_TYPEPOSQUERY:
- possessive = TRUE;
- min = 0;
- max = 1;
- ecode++;
- goto REPEATTYPE;
-
- case OP_TYPEPOSUPTO:
- possessive = TRUE;
- min = 0;
- max = GET2(ecode, 1);
- ecode += 3;
- goto REPEATTYPE;
-
- case OP_TYPESTAR:
- case OP_TYPEMINSTAR:
- case OP_TYPEPLUS:
- case OP_TYPEMINPLUS:
- case OP_TYPEQUERY:
- case OP_TYPEMINQUERY:
- c = *ecode++ - OP_TYPESTAR;
- minimize = (c & 1) != 0;
- min = rep_min[c]; /* Pick up values from tables; */
- max = rep_max[c]; /* zero for max => infinity */
- if (max == 0) max = INT_MAX;
-
- /* Common code for all repeated single character type matches. Note that
- in UTF-8 mode, '.' matches a character of any length, but for the other
- character types, the valid characters are all one-byte long. */
-
- REPEATTYPE:
- ctype = *ecode++; /* Code for the character type */
-
-#ifdef SUPPORT_UCP
- if (ctype == OP_PROP || ctype == OP_NOTPROP)
- {
- prop_fail_result = ctype == OP_NOTPROP;
- prop_type = *ecode++;
- prop_value = *ecode++;
- }
- else prop_type = -1;
-#endif
-
- /* First, ensure the minimum number of matches are present. Use inline
- code for maximizing the speed, and do the type test once at the start
- (i.e. keep it out of the loop). Also we can test that there are at least
- the minimum number of bytes before we start. This isn't as effective in
- UTF-8 mode, but it does no harm. Separate the UTF-8 code completely as that
- is tidier. Also separate the UCP code, which can be the same for both UTF-8
- and single-bytes. */
-
- if (min > md->end_subject - eptr) RRETURN(MATCH_NOMATCH);
- if (min > 0)
- {
-#ifdef SUPPORT_UCP
- if (prop_type >= 0)
- {
- switch(prop_type)
- {
- case PT_ANY:
- if (prop_fail_result) RRETURN(MATCH_NOMATCH);
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- }
- break;
-
- case PT_LAMP:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- prop_chartype = UCD_CHARTYPE(c);
- if ((prop_chartype == ucp_Lu ||
- prop_chartype == ucp_Ll ||
- prop_chartype == ucp_Lt) == prop_fail_result)
- RRETURN(MATCH_NOMATCH);
- }
- break;
-
- case PT_GC:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- prop_category = UCD_CATEGORY(c);
- if ((prop_category == prop_value) == prop_fail_result)
- RRETURN(MATCH_NOMATCH);
- }
- break;
-
- case PT_PC:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- prop_chartype = UCD_CHARTYPE(c);
- if ((prop_chartype == prop_value) == prop_fail_result)
- RRETURN(MATCH_NOMATCH);
- }
- break;
-
- case PT_SC:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- prop_script = UCD_SCRIPT(c);
- if ((prop_script == prop_value) == prop_fail_result)
- RRETURN(MATCH_NOMATCH);
- }
- break;
-
- default:
- RRETURN(PCRE_ERROR_INTERNAL);
- }
- }
-
- /* Match extended Unicode sequences. We will get here only if the
- support is in the binary; otherwise a compile-time error occurs. */
-
- else if (ctype == OP_EXTUNI)
- {
- for (i = 1; i <= min; i++)
- {
- GETCHARINCTEST(c, eptr);
- prop_category = UCD_CATEGORY(c);
- if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);
- while (eptr < md->end_subject)
- {
- int len = 1;
- if (!utf8) c = *eptr; else
- {
- GETCHARLEN(c, eptr, len);
- }
- prop_category = UCD_CATEGORY(c);
- if (prop_category != ucp_M) break;
- eptr += len;
- }
- }
- }
-
- else
-#endif /* SUPPORT_UCP */
-
-/* Handle all other cases when the coding is UTF-8 */
-
-#ifdef SUPPORT_UTF8
- if (utf8) switch(ctype)
- {
- case OP_ANY:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject || IS_NEWLINE(eptr))
- RRETURN(MATCH_NOMATCH);
- eptr++;
- while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
- }
- break;
-
- case OP_ALLANY:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- eptr++;
- while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
- }
- break;
-
- case OP_ANYBYTE:
- eptr += min;
- break;
-
- case OP_ANYNL:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x000d:
- if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
- break;
-
- case 0x000a:
- break;
-
- case 0x000b:
- case 0x000c:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
- break;
- }
- }
- break;
-
- case OP_NOT_HSPACE:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- switch(c)
- {
- default: break;
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- RRETURN(MATCH_NOMATCH);
- }
- }
- break;
-
- case OP_HSPACE:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- break;
- }
- }
- break;
-
- case OP_NOT_VSPACE:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- switch(c)
- {
- default: break;
- case 0x0a: /* LF */
- case 0x0b: /* VT */
- case 0x0c: /* FF */
- case 0x0d: /* CR */
- case 0x85: /* NEL */
- case 0x2028: /* LINE SEPARATOR */
- case 0x2029: /* PARAGRAPH SEPARATOR */
- RRETURN(MATCH_NOMATCH);
- }
- }
- break;
-
- case OP_VSPACE:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x0a: /* LF */
- case 0x0b: /* VT */
- case 0x0c: /* FF */
- case 0x0d: /* CR */
- case 0x85: /* NEL */
- case 0x2028: /* LINE SEPARATOR */
- case 0x2029: /* PARAGRAPH SEPARATOR */
- break;
- }
- }
- break;
-
- case OP_NOT_DIGIT:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- if (c < 128 && (md->ctypes[c] & ctype_digit) != 0)
- RRETURN(MATCH_NOMATCH);
- }
- break;
-
- case OP_DIGIT:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject ||
- *eptr >= 128 || (md->ctypes[*eptr++] & ctype_digit) == 0)
- RRETURN(MATCH_NOMATCH);
- /* No need to skip more bytes - we know it's a 1-byte character */
- }
- break;
-
- case OP_NOT_WHITESPACE:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject ||
- (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0))
- RRETURN(MATCH_NOMATCH);
- while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80);
- }
- break;
-
- case OP_WHITESPACE:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject ||
- *eptr >= 128 || (md->ctypes[*eptr++] & ctype_space) == 0)
- RRETURN(MATCH_NOMATCH);
- /* No need to skip more bytes - we know it's a 1-byte character */
- }
- break;
-
- case OP_NOT_WORDCHAR:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject ||
- (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0))
- RRETURN(MATCH_NOMATCH);
- while (++eptr < md->end_subject && (*eptr & 0xc0) == 0x80);
- }
- break;
-
- case OP_WORDCHAR:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject ||
- *eptr >= 128 || (md->ctypes[*eptr++] & ctype_word) == 0)
- RRETURN(MATCH_NOMATCH);
- /* No need to skip more bytes - we know it's a 1-byte character */
- }
- break;
-
- default:
- RRETURN(PCRE_ERROR_INTERNAL);
- } /* End switch(ctype) */
-
- else
-#endif /* SUPPORT_UTF8 */
-
- /* Code for the non-UTF-8 case for minimum matching of operators other
- than OP_PROP and OP_NOTPROP. We can assume that there are the minimum
- number of bytes present, as this was tested above. */
-
- switch(ctype)
- {
- case OP_ANY:
- for (i = 1; i <= min; i++)
- {
- if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
- eptr++;
- }
- break;
-
- case OP_ALLANY:
- eptr += min;
- break;
-
- case OP_ANYBYTE:
- eptr += min;
- break;
-
- /* Because of the CRLF case, we can't assume the minimum number of
- bytes are present in this case. */
-
- case OP_ANYNL:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- switch(*eptr++)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x000d:
- if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
- break;
- case 0x000a:
- break;
-
- case 0x000b:
- case 0x000c:
- case 0x0085:
- if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
- break;
- }
- }
- break;
-
- case OP_NOT_HSPACE:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- switch(*eptr++)
- {
- default: break;
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- RRETURN(MATCH_NOMATCH);
- }
- }
- break;
-
- case OP_HSPACE:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- switch(*eptr++)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- break;
- }
- }
- break;
-
- case OP_NOT_VSPACE:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- switch(*eptr++)
- {
- default: break;
- case 0x0a: /* LF */
- case 0x0b: /* VT */
- case 0x0c: /* FF */
- case 0x0d: /* CR */
- case 0x85: /* NEL */
- RRETURN(MATCH_NOMATCH);
- }
- }
- break;
-
- case OP_VSPACE:
- for (i = 1; i <= min; i++)
- {
- if (eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- switch(*eptr++)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x0a: /* LF */
- case 0x0b: /* VT */
- case 0x0c: /* FF */
- case 0x0d: /* CR */
- case 0x85: /* NEL */
- break;
- }
- }
- break;
-
- case OP_NOT_DIGIT:
- for (i = 1; i <= min; i++)
- if ((md->ctypes[*eptr++] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_DIGIT:
- for (i = 1; i <= min; i++)
- if ((md->ctypes[*eptr++] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_NOT_WHITESPACE:
- for (i = 1; i <= min; i++)
- if ((md->ctypes[*eptr++] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_WHITESPACE:
- for (i = 1; i <= min; i++)
- if ((md->ctypes[*eptr++] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_NOT_WORDCHAR:
- for (i = 1; i <= min; i++)
- if ((md->ctypes[*eptr++] & ctype_word) != 0)
- RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_WORDCHAR:
- for (i = 1; i <= min; i++)
- if ((md->ctypes[*eptr++] & ctype_word) == 0)
- RRETURN(MATCH_NOMATCH);
- break;
-
- default:
- RRETURN(PCRE_ERROR_INTERNAL);
- }
- }
-
- /* If min = max, continue at the same level without recursing */
-
- if (min == max) continue;
-
- /* If minimizing, we have to test the rest of the pattern before each
- subsequent match. Again, separate the UTF-8 case for speed, and also
- separate the UCP cases. */
-
- if (minimize)
- {
-#ifdef SUPPORT_UCP
- if (prop_type >= 0)
- {
- switch(prop_type)
- {
- case PT_ANY:
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM36);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- if (prop_fail_result) RRETURN(MATCH_NOMATCH);
- }
- /* Control never gets here */
-
- case PT_LAMP:
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM37);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- prop_chartype = UCD_CHARTYPE(c);
- if ((prop_chartype == ucp_Lu ||
- prop_chartype == ucp_Ll ||
- prop_chartype == ucp_Lt) == prop_fail_result)
- RRETURN(MATCH_NOMATCH);
- }
- /* Control never gets here */
-
- case PT_GC:
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM38);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- prop_category = UCD_CATEGORY(c);
- if ((prop_category == prop_value) == prop_fail_result)
- RRETURN(MATCH_NOMATCH);
- }
- /* Control never gets here */
-
- case PT_PC:
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM39);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- prop_chartype = UCD_CHARTYPE(c);
- if ((prop_chartype == prop_value) == prop_fail_result)
- RRETURN(MATCH_NOMATCH);
- }
- /* Control never gets here */
-
- case PT_SC:
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM40);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINC(c, eptr);
- prop_script = UCD_SCRIPT(c);
- if ((prop_script == prop_value) == prop_fail_result)
- RRETURN(MATCH_NOMATCH);
- }
- /* Control never gets here */
-
- default:
- RRETURN(PCRE_ERROR_INTERNAL);
- }
- }
-
- /* Match extended Unicode sequences. We will get here only if the
- support is in the binary; otherwise a compile-time error occurs. */
-
- else if (ctype == OP_EXTUNI)
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM41);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject) RRETURN(MATCH_NOMATCH);
- GETCHARINCTEST(c, eptr);
- prop_category = UCD_CATEGORY(c);
- if (prop_category == ucp_M) RRETURN(MATCH_NOMATCH);
- while (eptr < md->end_subject)
- {
- int len = 1;
- if (!utf8) c = *eptr; else
- {
- GETCHARLEN(c, eptr, len);
- }
- prop_category = UCD_CATEGORY(c);
- if (prop_category != ucp_M) break;
- eptr += len;
- }
- }
- }
-
- else
-#endif /* SUPPORT_UCP */
-
-#ifdef SUPPORT_UTF8
- /* UTF-8 mode */
- if (utf8)
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM42);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject ||
- (ctype == OP_ANY && IS_NEWLINE(eptr)))
- RRETURN(MATCH_NOMATCH);
-
- GETCHARINC(c, eptr);
- switch(ctype)
- {
- case OP_ANY: /* This is the non-NL case */
- case OP_ALLANY:
- case OP_ANYBYTE:
- break;
-
- case OP_ANYNL:
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x000d:
- if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
- break;
- case 0x000a:
- break;
-
- case 0x000b:
- case 0x000c:
- case 0x0085:
- case 0x2028:
- case 0x2029:
- if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
- break;
- }
- break;
-
- case OP_NOT_HSPACE:
- switch(c)
- {
- default: break;
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- RRETURN(MATCH_NOMATCH);
- }
- break;
-
- case OP_HSPACE:
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- break;
- }
- break;
-
- case OP_NOT_VSPACE:
- switch(c)
- {
- default: break;
- case 0x0a: /* LF */
- case 0x0b: /* VT */
- case 0x0c: /* FF */
- case 0x0d: /* CR */
- case 0x85: /* NEL */
- case 0x2028: /* LINE SEPARATOR */
- case 0x2029: /* PARAGRAPH SEPARATOR */
- RRETURN(MATCH_NOMATCH);
- }
- break;
-
- case OP_VSPACE:
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x0a: /* LF */
- case 0x0b: /* VT */
- case 0x0c: /* FF */
- case 0x0d: /* CR */
- case 0x85: /* NEL */
- case 0x2028: /* LINE SEPARATOR */
- case 0x2029: /* PARAGRAPH SEPARATOR */
- break;
- }
- break;
-
- case OP_NOT_DIGIT:
- if (c < 256 && (md->ctypes[c] & ctype_digit) != 0)
- RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_DIGIT:
- if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0)
- RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_NOT_WHITESPACE:
- if (c < 256 && (md->ctypes[c] & ctype_space) != 0)
- RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_WHITESPACE:
- if (c >= 256 || (md->ctypes[c] & ctype_space) == 0)
- RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_NOT_WORDCHAR:
- if (c < 256 && (md->ctypes[c] & ctype_word) != 0)
- RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_WORDCHAR:
- if (c >= 256 || (md->ctypes[c] & ctype_word) == 0)
- RRETURN(MATCH_NOMATCH);
- break;
-
- default:
- RRETURN(PCRE_ERROR_INTERNAL);
- }
- }
- }
- else
-#endif
- /* Not UTF-8 mode */
- {
- for (fi = min;; fi++)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM43);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (fi >= max || eptr >= md->end_subject ||
- (ctype == OP_ANY && IS_NEWLINE(eptr)))
- RRETURN(MATCH_NOMATCH);
-
- c = *eptr++;
- switch(ctype)
- {
- case OP_ANY: /* This is the non-NL case */
- case OP_ALLANY:
- case OP_ANYBYTE:
- break;
-
- case OP_ANYNL:
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x000d:
- if (eptr < md->end_subject && *eptr == 0x0a) eptr++;
- break;
-
- case 0x000a:
- break;
-
- case 0x000b:
- case 0x000c:
- case 0x0085:
- if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
- break;
- }
- break;
-
- case OP_NOT_HSPACE:
- switch(c)
- {
- default: break;
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- RRETURN(MATCH_NOMATCH);
- }
- break;
-
- case OP_HSPACE:
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- break;
- }
- break;
-
- case OP_NOT_VSPACE:
- switch(c)
- {
- default: break;
- case 0x0a: /* LF */
- case 0x0b: /* VT */
- case 0x0c: /* FF */
- case 0x0d: /* CR */
- case 0x85: /* NEL */
- RRETURN(MATCH_NOMATCH);
- }
- break;
-
- case OP_VSPACE:
- switch(c)
- {
- default: RRETURN(MATCH_NOMATCH);
- case 0x0a: /* LF */
- case 0x0b: /* VT */
- case 0x0c: /* FF */
- case 0x0d: /* CR */
- case 0x85: /* NEL */
- break;
- }
- break;
-
- case OP_NOT_DIGIT:
- if ((md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_DIGIT:
- if ((md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_NOT_WHITESPACE:
- if ((md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_WHITESPACE:
- if ((md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_NOT_WORDCHAR:
- if ((md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH);
- break;
-
- case OP_WORDCHAR:
- if ((md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH);
- break;
-
- default:
- RRETURN(PCRE_ERROR_INTERNAL);
- }
- }
- }
- /* Control never gets here */
- }
-
- /* If maximizing, it is worth using inline code for speed, doing the type
- test once at the start (i.e. keep it out of the loop). Again, keep the
- UTF-8 and UCP stuff separate. */
-
- else
- {
- pp = eptr; /* Remember where we started */
-
-#ifdef SUPPORT_UCP
- if (prop_type >= 0)
- {
- switch(prop_type)
- {
- case PT_ANY:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- if (prop_fail_result) break;
- eptr+= len;
- }
- break;
-
- case PT_LAMP:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- prop_chartype = UCD_CHARTYPE(c);
- if ((prop_chartype == ucp_Lu ||
- prop_chartype == ucp_Ll ||
- prop_chartype == ucp_Lt) == prop_fail_result)
- break;
- eptr+= len;
- }
- break;
-
- case PT_GC:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- prop_category = UCD_CATEGORY(c);
- if ((prop_category == prop_value) == prop_fail_result)
- break;
- eptr+= len;
- }
- break;
-
- case PT_PC:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- prop_chartype = UCD_CHARTYPE(c);
- if ((prop_chartype == prop_value) == prop_fail_result)
- break;
- eptr+= len;
- }
- break;
-
- case PT_SC:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- prop_script = UCD_SCRIPT(c);
- if ((prop_script == prop_value) == prop_fail_result)
- break;
- eptr+= len;
- }
- break;
- }
-
- /* eptr is now past the end of the maximum run */
-
- if (possessive) continue;
- for(;;)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM44);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (eptr-- == pp) break; /* Stop if tried at original pos */
- if (utf8) BACKCHAR(eptr);
- }
- }
-
- /* Match extended Unicode sequences. We will get here only if the
- support is in the binary; otherwise a compile-time error occurs. */
-
- else if (ctype == OP_EXTUNI)
- {
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject) break;
- GETCHARINCTEST(c, eptr);
- prop_category = UCD_CATEGORY(c);
- if (prop_category == ucp_M) break;
- while (eptr < md->end_subject)
- {
- int len = 1;
- if (!utf8) c = *eptr; else
- {
- GETCHARLEN(c, eptr, len);
- }
- prop_category = UCD_CATEGORY(c);
- if (prop_category != ucp_M) break;
- eptr += len;
- }
- }
-
- /* eptr is now past the end of the maximum run */
-
- if (possessive) continue;
- for(;;)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM45);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (eptr-- == pp) break; /* Stop if tried at original pos */
- for (;;) /* Move back over one extended */
- {
- int len = 1;
- if (!utf8) c = *eptr; else
- {
- BACKCHAR(eptr);
- GETCHARLEN(c, eptr, len);
- }
- prop_category = UCD_CATEGORY(c);
- if (prop_category != ucp_M) break;
- eptr--;
- }
- }
- }
-
- else
-#endif /* SUPPORT_UCP */
-
-#ifdef SUPPORT_UTF8
- /* UTF-8 mode */
-
- if (utf8)
- {
- switch(ctype)
- {
- case OP_ANY:
- if (max < INT_MAX)
- {
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || IS_NEWLINE(eptr)) break;
- eptr++;
- while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
- }
- }
-
- /* Handle unlimited UTF-8 repeat */
-
- else
- {
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || IS_NEWLINE(eptr)) break;
- eptr++;
- while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
- }
- }
- break;
-
- case OP_ALLANY:
- if (max < INT_MAX)
- {
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject) break;
- eptr++;
- while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
- }
- }
- else eptr = md->end_subject; /* Unlimited UTF-8 repeat */
- break;
-
- /* The byte case is the same as non-UTF8 */
-
- case OP_ANYBYTE:
- c = max - min;
- if (c > (unsigned int)(md->end_subject - eptr))
- c = md->end_subject - eptr;
- eptr += c;
- break;
-
- case OP_ANYNL:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- if (c == 0x000d)
- {
- if (++eptr >= md->end_subject) break;
- if (*eptr == 0x000a) eptr++;
- }
- else
- {
- if (c != 0x000a &&
- (md->bsr_anycrlf ||
- (c != 0x000b && c != 0x000c &&
- c != 0x0085 && c != 0x2028 && c != 0x2029)))
- break;
- eptr += len;
- }
- }
- break;
-
- case OP_NOT_HSPACE:
- case OP_HSPACE:
- for (i = min; i < max; i++)
- {
- BOOL gotspace;
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- switch(c)
- {
- default: gotspace = FALSE; break;
- case 0x09: /* HT */
- case 0x20: /* SPACE */
- case 0xa0: /* NBSP */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x202f: /* NARROW NO-BREAK SPACE */
- case 0x205f: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- gotspace = TRUE;
- break;
- }
- if (gotspace == (ctype == OP_NOT_HSPACE)) break;
- eptr += len;
- }
- break;
-
- case OP_NOT_VSPACE:
- case OP_VSPACE:
- for (i = min; i < max; i++)
- {
- BOOL gotspace;
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- switch(c)
- {
- default: gotspace = FALSE; break;
- case 0x0a: /* LF */
- case 0x0b: /* VT */
- case 0x0c: /* FF */
- case 0x0d: /* CR */
- case 0x85: /* NEL */
- case 0x2028: /* LINE SEPARATOR */
- case 0x2029: /* PARAGRAPH SEPARATOR */
- gotspace = TRUE;
- break;
- }
- if (gotspace == (ctype == OP_NOT_VSPACE)) break;
- eptr += len;
- }
- break;
-
- case OP_NOT_DIGIT:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break;
- eptr+= len;
- }
- break;
-
- case OP_DIGIT:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break;
- eptr+= len;
- }
- break;
-
- case OP_NOT_WHITESPACE:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break;
- eptr+= len;
- }
- break;
-
- case OP_WHITESPACE:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break;
- eptr+= len;
- }
- break;
-
- case OP_NOT_WORDCHAR:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break;
- eptr+= len;
- }
- break;
-
- case OP_WORDCHAR:
- for (i = min; i < max; i++)
- {
- int len = 1;
- if (eptr >= md->end_subject) break;
- GETCHARLEN(c, eptr, len);
- if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break;
- eptr+= len;
- }
- break;
-
- default:
- RRETURN(PCRE_ERROR_INTERNAL);
- }
-
- /* eptr is now past the end of the maximum run */
-
- if (possessive) continue;
- for(;;)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM46);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- if (eptr-- == pp) break; /* Stop if tried at original pos */
- BACKCHAR(eptr);
- }
- }
- else
-#endif /* SUPPORT_UTF8 */
-
- /* Not UTF-8 mode */
- {
- switch(ctype)
- {
- case OP_ANY:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || IS_NEWLINE(eptr)) break;
- eptr++;
- }
- break;
-
- case OP_ALLANY:
- case OP_ANYBYTE:
- c = max - min;
- if (c > (unsigned int)(md->end_subject - eptr))
- c = md->end_subject - eptr;
- eptr += c;
- break;
-
- case OP_ANYNL:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject) break;
- c = *eptr;
- if (c == 0x000d)
- {
- if (++eptr >= md->end_subject) break;
- if (*eptr == 0x000a) eptr++;
- }
- else
- {
- if (c != 0x000a &&
- (md->bsr_anycrlf ||
- (c != 0x000b && c != 0x000c && c != 0x0085)))
- break;
- eptr++;
- }
- }
- break;
-
- case OP_NOT_HSPACE:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject) break;
- c = *eptr;
- if (c == 0x09 || c == 0x20 || c == 0xa0) break;
- eptr++;
- }
- break;
-
- case OP_HSPACE:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject) break;
- c = *eptr;
- if (c != 0x09 && c != 0x20 && c != 0xa0) break;
- eptr++;
- }
- break;
-
- case OP_NOT_VSPACE:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject) break;
- c = *eptr;
- if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85)
- break;
- eptr++;
- }
- break;
-
- case OP_VSPACE:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject) break;
- c = *eptr;
- if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85)
- break;
- eptr++;
- }
- break;
-
- case OP_NOT_DIGIT:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
- break;
- eptr++;
- }
- break;
-
- case OP_DIGIT:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
- break;
- eptr++;
- }
- break;
-
- case OP_NOT_WHITESPACE:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
- break;
- eptr++;
- }
- break;
-
- case OP_WHITESPACE:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
- break;
- eptr++;
- }
- break;
-
- case OP_NOT_WORDCHAR:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
- break;
- eptr++;
- }
- break;
-
- case OP_WORDCHAR:
- for (i = min; i < max; i++)
- {
- if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
- break;
- eptr++;
- }
- break;
-
- default:
- RRETURN(PCRE_ERROR_INTERNAL);
- }
-
- /* eptr is now past the end of the maximum run */
-
- if (possessive) continue;
- while (eptr >= pp)
- {
- RMATCH(eptr, ecode, offset_top, md, ims, eptrb, 0, RM47);
- eptr--;
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- }
- }
-
- /* Get here if we can't make it match with any permitted repetitions */
-
- RRETURN(MATCH_NOMATCH);
- }
- /* Control never gets here */
-
- /* There's been some horrible disaster. Arrival here can only mean there is
- something seriously wrong in the code above or the OP_xxx definitions. */
-
- default:
- DPRINTF(("Unknown opcode %d\n", *ecode));
- RRETURN(PCRE_ERROR_UNKNOWN_OPCODE);
- }
-
- /* Do not stick any code in here without much thought; it is assumed
- that "continue" in the code above comes out to here to repeat the main
- loop. */
-
- } /* End of main loop */
-/* Control never reaches here */
-
-
-/* When compiling to use the heap rather than the stack for recursive calls to
-match(), the RRETURN() macro jumps here. The number that is saved in
-frame->Xwhere indicates which label we actually want to return to. */
-
-#ifdef NO_RECURSE
-#define LBL(val) case val: goto L_RM##val;
-HEAP_RETURN:
-switch (frame->Xwhere)
- {
- LBL( 1) LBL( 2) LBL( 3) LBL( 4) LBL( 5) LBL( 6) LBL( 7) LBL( 8)
- LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17)
- LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33)
- LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52)
- LBL(53) LBL(54)
-#ifdef SUPPORT_UTF8
- LBL(16) LBL(18) LBL(20) LBL(21) LBL(22) LBL(23) LBL(28) LBL(30)
- LBL(32) LBL(34) LBL(42) LBL(46)
-#ifdef SUPPORT_UCP
- LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45)
-#endif /* SUPPORT_UCP */
-#endif /* SUPPORT_UTF8 */
- default:
- DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere));
- return PCRE_ERROR_INTERNAL;
- }
-#undef LBL
-#endif /* NO_RECURSE */
-}
-
-
-/***************************************************************************
-****************************************************************************
- RECURSION IN THE match() FUNCTION
-
-Undefine all the macros that were defined above to handle this. */
-
-#ifdef NO_RECURSE
-#undef eptr
-#undef ecode
-#undef mstart
-#undef offset_top
-#undef ims
-#undef eptrb
-#undef flags
-
-#undef callpat
-#undef charptr
-#undef data
-#undef next
-#undef pp
-#undef prev
-#undef saved_eptr
-
-#undef new_recursive
-
-#undef cur_is_word
-#undef condition
-#undef prev_is_word
-
-#undef original_ims
-
-#undef ctype
-#undef length
-#undef max
-#undef min
-#undef number
-#undef offset
-#undef op
-#undef save_capture_last
-#undef save_offset1
-#undef save_offset2
-#undef save_offset3
-#undef stacksave
-
-#undef newptrb
-
-#endif
-
-/* These two are defined as macros in both cases */
-
-#undef fc
-#undef fi
-
-/***************************************************************************
-***************************************************************************/
-
-
-
-/*************************************************
-* Execute a Regular Expression *
-*************************************************/
-
-/* This function applies a compiled re to a subject string and picks out
-portions of the string if it matches. Two elements in the vector are set for
-each substring: the offsets to the start and end of the substring.
-
-Arguments:
- argument_re points to the compiled expression
- extra_data points to extra data or is NULL
- subject points to the subject string
- length length of subject string (may contain binary zeros)
- start_offset where to start in the subject string
- options option bits
- offsets points to a vector of ints to be filled in with offsets
- offsetcount the number of elements in the vector
-
-Returns: > 0 => success; value is the number of elements filled in
- = 0 => success, but offsets is not big enough
- -1 => failed to match
- < -1 => some kind of unexpected problem
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_exec(const pcre *argument_re, const pcre_extra *extra_data,
- PCRE_SPTR subject, int length, int start_offset, int options, int *offsets,
- int offsetcount)
-{
-int rc, resetcount, ocount;
-int first_byte = -1;
-int req_byte = -1;
-int req_byte2 = -1;
-int newline;
-unsigned long int ims;
-BOOL using_temporary_offsets = FALSE;
-BOOL anchored;
-BOOL startline;
-BOOL firstline;
-BOOL first_byte_caseless = FALSE;
-BOOL req_byte_caseless = FALSE;
-BOOL utf8;
-match_data match_block;
-match_data *md = &match_block;
-const uschar *tables;
-const uschar *start_bits = NULL;
-USPTR start_match = (USPTR)subject + start_offset;
-USPTR end_subject;
-USPTR req_byte_ptr = start_match - 1;
-
-pcre_study_data internal_study;
-const pcre_study_data *study;
-
-real_pcre internal_re;
-const real_pcre *external_re = (const real_pcre *)argument_re;
-const real_pcre *re = external_re;
-
-/* Plausibility checks */
-
-if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
-if (re == NULL || subject == NULL ||
- (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
-if (offsetcount < 0) return PCRE_ERROR_BADCOUNT;
-
-/* Fish out the optional data from the extra_data structure, first setting
-the default values. */
-
-study = NULL;
-md->match_limit = MATCH_LIMIT;
-md->match_limit_recursion = MATCH_LIMIT_RECURSION;
-md->callout_data = NULL;
-
-/* The table pointer is always in native byte order. */
-
-tables = external_re->tables;
-
-if (extra_data != NULL)
- {
- register unsigned int flags = extra_data->flags;
- if ((flags & PCRE_EXTRA_STUDY_DATA) != 0)
- study = (const pcre_study_data *)extra_data->study_data;
- if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0)
- md->match_limit = extra_data->match_limit;
- if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0)
- md->match_limit_recursion = extra_data->match_limit_recursion;
- if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0)
- md->callout_data = extra_data->callout_data;
- if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables;
- }
-
-/* If the exec call supplied NULL for tables, use the inbuilt ones. This
-is a feature that makes it possible to save compiled regex and re-use them
-in other programs later. */
-
-if (tables == NULL) tables = _pcre_default_tables;
-
-/* Check that the first field in the block is the magic number. If it is not,
-test for a regex that was compiled on a host of opposite endianness. If this is
-the case, flipped values are put in internal_re and internal_study if there was
-study data too. */
-
-if (re->magic_number != MAGIC_NUMBER)
- {
- re = _pcre_try_flipped(re, &internal_re, study, &internal_study);
- if (re == NULL) return PCRE_ERROR_BADMAGIC;
- if (study != NULL) study = &internal_study;
- }
-
-/* Set up other data */
-
-anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
-startline = (re->flags & PCRE_STARTLINE) != 0;
-firstline = (re->options & PCRE_FIRSTLINE) != 0;
-
-/* The code starts after the real_pcre block and the capture name table. */
-
-md->start_code = (const uschar *)external_re + re->name_table_offset +
- re->name_count * re->name_entry_size;
-
-md->start_subject = (USPTR)subject;
-md->start_offset = start_offset;
-md->end_subject = md->start_subject + length;
-end_subject = md->end_subject;
-
-md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
-utf8 = md->utf8 = (re->options & PCRE_UTF8) != 0;
-md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
-
-md->notbol = (options & PCRE_NOTBOL) != 0;
-md->noteol = (options & PCRE_NOTEOL) != 0;
-md->notempty = (options & PCRE_NOTEMPTY) != 0;
-md->partial = (options & PCRE_PARTIAL) != 0;
-md->hitend = FALSE;
-
-md->recursive = NULL; /* No recursion at top level */
-
-md->lcc = tables + lcc_offset;
-md->ctypes = tables + ctypes_offset;
-
-/* Handle different \R options. */
-
-switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE))
- {
- case 0:
- if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0)
- md->bsr_anycrlf = (re->options & PCRE_BSR_ANYCRLF) != 0;
- else
-#ifdef BSR_ANYCRLF
- md->bsr_anycrlf = TRUE;
-#else
- md->bsr_anycrlf = FALSE;
-#endif
- break;
-
- case PCRE_BSR_ANYCRLF:
- md->bsr_anycrlf = TRUE;
- break;
-
- case PCRE_BSR_UNICODE:
- md->bsr_anycrlf = FALSE;
- break;
-
- default: return PCRE_ERROR_BADNEWLINE;
- }
-
-/* Handle different types of newline. The three bits give eight cases. If
-nothing is set at run time, whatever was used at compile time applies. */
-
-switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options :
- (pcre_uint32)options) & PCRE_NEWLINE_BITS)
- {
- case 0: newline = NEWLINE; break; /* Compile-time default */
- case PCRE_NEWLINE_CR: newline = '\r'; break;
- case PCRE_NEWLINE_LF: newline = '\n'; break;
- case PCRE_NEWLINE_CR+
- PCRE_NEWLINE_LF: newline = ('\r' << 8) | '\n'; break;
- case PCRE_NEWLINE_ANY: newline = -1; break;
- case PCRE_NEWLINE_ANYCRLF: newline = -2; break;
- default: return PCRE_ERROR_BADNEWLINE;
- }
-
-if (newline == -2)
- {
- md->nltype = NLTYPE_ANYCRLF;
- }
-else if (newline < 0)
- {
- md->nltype = NLTYPE_ANY;
- }
-else
- {
- md->nltype = NLTYPE_FIXED;
- if (newline > 255)
- {
- md->nllen = 2;
- md->nl[0] = (newline >> 8) & 255;
- md->nl[1] = newline & 255;
- }
- else
- {
- md->nllen = 1;
- md->nl[0] = newline;
- }
- }
-
-/* Partial matching is supported only for a restricted set of regexes at the
-moment. */
-
-if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0)
- return PCRE_ERROR_BADPARTIAL;
-
-/* Check a UTF-8 string if required. Unfortunately there's no way of passing
-back the character offset. */
-
-#ifdef SUPPORT_UTF8
-if (utf8 && (options & PCRE_NO_UTF8_CHECK) == 0)
- {
- if (_pcre_valid_utf8((uschar *)subject, length) >= 0)
- return PCRE_ERROR_BADUTF8;
- if (start_offset > 0 && start_offset < length)
- {
- int tb = ((uschar *)subject)[start_offset];
- if (tb > 127)
- {
- tb &= 0xc0;
- if (tb != 0 && tb != 0xc0) return PCRE_ERROR_BADUTF8_OFFSET;
- }
- }
- }
-#endif
-
-/* The ims options can vary during the matching as a result of the presence
-of (?ims) items in the pattern. They are kept in a local variable so that
-restoring at the exit of a group is easy. */
-
-ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
-
-/* If the expression has got more back references than the offsets supplied can
-hold, we get a temporary chunk of working store to use during the matching.
-Otherwise, we can use the vector supplied, rounding down its size to a multiple
-of 3. */
-
-ocount = offsetcount - (offsetcount % 3);
-
-if (re->top_backref > 0 && re->top_backref >= ocount/3)
- {
- ocount = re->top_backref * 3 + 3;
- md->offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int));
- if (md->offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
- using_temporary_offsets = TRUE;
- DPRINTF(("Got memory to hold back references\n"));
- }
-else md->offset_vector = offsets;
-
-md->offset_end = ocount;
-md->offset_max = (2*ocount)/3;
-md->offset_overflow = FALSE;
-md->capture_last = -1;
-
-/* Compute the minimum number of offsets that we need to reset each time. Doing
-this makes a huge difference to execution time when there aren't many brackets
-in the pattern. */
-
-resetcount = 2 + re->top_bracket * 2;
-if (resetcount > offsetcount) resetcount = ocount;
-
-/* Reset the working variable associated with each extraction. These should
-never be used unless previously set, but they get saved and restored, and so we
-initialize them to avoid reading uninitialized locations. */
-
-if (md->offset_vector != NULL)
- {
- register int *iptr = md->offset_vector + ocount;
- register int *iend = iptr - resetcount/2 + 1;
- while (--iptr >= iend) *iptr = -1;
- }
-
-/* Set up the first character to match, if available. The first_byte value is
-never set for an anchored regular expression, but the anchoring may be forced
-at run time, so we have to test for anchoring. The first char may be unset for
-an unanchored pattern, of course. If there's no first char and the pattern was
-studied, there may be a bitmap of possible first characters. */
-
-if (!anchored)
- {
- if ((re->flags & PCRE_FIRSTSET) != 0)
- {
- first_byte = re->first_byte & 255;
- if ((first_byte_caseless = ((re->first_byte & REQ_CASELESS) != 0)) == TRUE)
- first_byte = md->lcc[first_byte];
- }
- else
- if (!startline && study != NULL &&
- (study->options & PCRE_STUDY_MAPPED) != 0)
- start_bits = study->start_bits;
- }
-
-/* For anchored or unanchored matches, there may be a "last known required
-character" set. */
-
-if ((re->flags & PCRE_REQCHSET) != 0)
- {
- req_byte = re->req_byte & 255;
- req_byte_caseless = (re->req_byte & REQ_CASELESS) != 0;
- req_byte2 = (tables + fcc_offset)[req_byte]; /* case flipped */
- }
-
-
-/* ==========================================================================*/
-
-/* Loop for handling unanchored repeated matching attempts; for anchored regexs
-the loop runs just once. */
-
-for(;;)
- {
- USPTR save_end_subject = end_subject;
- USPTR new_start_match;
-
- /* Reset the maximum number of extractions we might see. */
-
- if (md->offset_vector != NULL)
- {
- register int *iptr = md->offset_vector;
- register int *iend = iptr + resetcount;
- while (iptr < iend) *iptr++ = -1;
- }
-
- /* Advance to a unique first char if possible. If firstline is TRUE, the
- start of the match is constrained to the first line of a multiline string.
- That is, the match must be before or at the first newline. Implement this by
- temporarily adjusting end_subject so that we stop scanning at a newline. If
- the match fails at the newline, later code breaks this loop. */
-
- if (firstline)
- {
- USPTR t = start_match;
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- while (t < md->end_subject && !IS_NEWLINE(t))
- {
- t++;
- while (t < end_subject && (*t & 0xc0) == 0x80) t++;
- }
- }
- else
-#endif
- while (t < md->end_subject && !IS_NEWLINE(t)) t++;
- end_subject = t;
- }
-
- /* Now advance to a unique first byte if there is one. */
-
- if (first_byte >= 0)
- {
- if (first_byte_caseless)
- while (start_match < end_subject && md->lcc[*start_match] != first_byte)
- start_match++;
- else
- while (start_match < end_subject && *start_match != first_byte)
- start_match++;
- }
-
- /* Or to just after a linebreak for a multiline match */
-
- else if (startline)
- {
- if (start_match > md->start_subject + start_offset)
- {
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- while (start_match < end_subject && !WAS_NEWLINE(start_match))
- {
- start_match++;
- while(start_match < end_subject && (*start_match & 0xc0) == 0x80)
- start_match++;
- }
- }
- else
-#endif
- while (start_match < end_subject && !WAS_NEWLINE(start_match))
- start_match++;
-
- /* If we have just passed a CR and the newline option is ANY or ANYCRLF,
- and we are now at a LF, advance the match position by one more character.
- */
-
- if (start_match[-1] == '\r' &&
- (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
- start_match < end_subject &&
- *start_match == '\n')
- start_match++;
- }
- }
-
- /* Or to a non-unique first byte after study */
-
- else if (start_bits != NULL)
- {
- while (start_match < end_subject)
- {
- register unsigned int c = *start_match;
- if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++;
- else break;
- }
- }
-
- /* Restore fudged end_subject */
-
- end_subject = save_end_subject;
-
-#ifdef DEBUG /* Sigh. Some compilers never learn. */
- printf(">>>> Match against: ");
- pchars(start_match, end_subject - start_match, TRUE, md);
- printf("\n");
-#endif
-
- /* If req_byte is set, we know that that character must appear in the subject
- for the match to succeed. If the first character is set, req_byte must be
- later in the subject; otherwise the test starts at the match point. This
- optimization can save a huge amount of backtracking in patterns with nested
- unlimited repeats that aren't going to match. Writing separate code for
- cased/caseless versions makes it go faster, as does using an autoincrement
- and backing off on a match.
-
- HOWEVER: when the subject string is very, very long, searching to its end can
- take a long time, and give bad performance on quite ordinary patterns. This
- showed up when somebody was matching something like /^\d+C/ on a 32-megabyte
- string... so we don't do this when the string is sufficiently long.
-
- ALSO: this processing is disabled when partial matching is requested.
- */
-
- if (req_byte >= 0 &&
- end_subject - start_match < REQ_BYTE_MAX &&
- !md->partial)
- {
- register USPTR p = start_match + ((first_byte >= 0)? 1 : 0);
-
- /* We don't need to repeat the search if we haven't yet reached the
- place we found it at last time. */
-
- if (p > req_byte_ptr)
- {
- if (req_byte_caseless)
- {
- while (p < end_subject)
- {
- register int pp = *p++;
- if (pp == req_byte || pp == req_byte2) { p--; break; }
- }
- }
- else
- {
- while (p < end_subject)
- {
- if (*p++ == req_byte) { p--; break; }
- }
- }
-
- /* If we can't find the required character, break the matching loop,
- forcing a match failure. */
-
- if (p >= end_subject)
- {
- rc = MATCH_NOMATCH;
- break;
- }
-
- /* If we have found the required character, save the point where we
- found it, so that we don't search again next time round the loop if
- the start hasn't passed this character yet. */
-
- req_byte_ptr = p;
- }
- }
-
- /* OK, we can now run the match. */
-
- md->start_match_ptr = start_match;
- md->match_call_count = 0;
- rc = match(start_match, md->start_code, start_match, 2, md, ims, NULL, 0, 0);
-
- switch(rc)
- {
- /* NOMATCH and PRUNE advance by one character. THEN at this level acts
- exactly like PRUNE. */
-
- case MATCH_NOMATCH:
- case MATCH_PRUNE:
- case MATCH_THEN:
- new_start_match = start_match + 1;
-#ifdef SUPPORT_UTF8
- if (utf8)
- while(new_start_match < end_subject && (*new_start_match & 0xc0) == 0x80)
- new_start_match++;
-#endif
- break;
-
- /* SKIP passes back the next starting point explicitly. */
-
- case MATCH_SKIP:
- new_start_match = md->start_match_ptr;
- break;
-
- /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */
-
- case MATCH_COMMIT:
- rc = MATCH_NOMATCH;
- goto ENDLOOP;
-
- /* Any other return is some kind of error. */
-
- default:
- goto ENDLOOP;
- }
-
- /* Control reaches here for the various types of "no match at this point"
- result. Reset the code to MATCH_NOMATCH for subsequent checking. */
-
- rc = MATCH_NOMATCH;
-
- /* If PCRE_FIRSTLINE is set, the match must happen before or at the first
- newline in the subject (though it may continue over the newline). Therefore,
- if we have just failed to match, starting at a newline, do not continue. */
-
- if (firstline && IS_NEWLINE(start_match)) break;
-
- /* Advance to new matching position */
-
- start_match = new_start_match;
-
- /* Break the loop if the pattern is anchored or if we have passed the end of
- the subject. */
-
- if (anchored || start_match > end_subject) break;
-
- /* If we have just passed a CR and we are now at a LF, and the pattern does
- not contain any explicit matches for \r or \n, and the newline option is CRLF
- or ANY or ANYCRLF, advance the match position by one more character. */
-
- if (start_match[-1] == '\r' &&
- start_match < end_subject &&
- *start_match == '\n' &&
- (re->flags & PCRE_HASCRORLF) == 0 &&
- (md->nltype == NLTYPE_ANY ||
- md->nltype == NLTYPE_ANYCRLF ||
- md->nllen == 2))
- start_match++;
-
- } /* End of for(;;) "bumpalong" loop */
-
-/* ==========================================================================*/
-
-/* We reach here when rc is not MATCH_NOMATCH, or if one of the stopping
-conditions is true:
-
-(1) The pattern is anchored or the match was failed by (*COMMIT);
-
-(2) We are past the end of the subject;
-
-(3) PCRE_FIRSTLINE is set and we have failed to match at a newline, because
- this option requests that a match occur at or before the first newline in
- the subject.
-
-When we have a match and the offset vector is big enough to deal with any
-backreferences, captured substring offsets will already be set up. In the case
-where we had to get some local store to hold offsets for backreference
-processing, copy those that we can. In this case there need not be overflow if
-certain parts of the pattern were not used, even though there are more
-capturing parentheses than vector slots. */
-
-ENDLOOP:
-
-if (rc == MATCH_MATCH)
- {
- if (using_temporary_offsets)
- {
- if (offsetcount >= 4)
- {
- memcpy(offsets + 2, md->offset_vector + 2,
- (offsetcount - 2) * sizeof(int));
- DPRINTF(("Copied offsets from temporary memory\n"));
- }
- if (md->end_offset_top > offsetcount) md->offset_overflow = TRUE;
- DPRINTF(("Freeing temporary memory\n"));
- (pcre_free)(md->offset_vector);
- }
-
- /* Set the return code to the number of captured strings, or 0 if there are
- too many to fit into the vector. */
-
- rc = md->offset_overflow? 0 : md->end_offset_top/2;
-
- /* If there is space, set up the whole thing as substring 0. The value of
- md->start_match_ptr might be modified if \K was encountered on the success
- matching path. */
-
- if (offsetcount < 2) rc = 0; else
- {
- offsets[0] = md->start_match_ptr - md->start_subject;
- offsets[1] = md->end_match_ptr - md->start_subject;
- }
-
- DPRINTF((">>>> returning %d\n", rc));
- return rc;
- }
-
-/* Control gets here if there has been an error, or if the overall match
-attempt has failed at all permitted starting positions. */
-
-if (using_temporary_offsets)
- {
- DPRINTF(("Freeing temporary memory\n"));
- (pcre_free)(md->offset_vector);
- }
-
-if (rc != MATCH_NOMATCH)
- {
- DPRINTF((">>>> error: returning %d\n", rc));
- return rc;
- }
-else if (md->partial && md->hitend)
- {
- DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));
- return PCRE_ERROR_PARTIAL;
- }
-else
- {
- DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
- return PCRE_ERROR_NOMATCH;
- }
-}
-
-/* End of pcre_exec.c */
diff --git a/glib/pcre/pcre_fullinfo.c b/glib/pcre/pcre_fullinfo.c
deleted file mode 100644
index 30566bbc0..000000000
--- a/glib/pcre/pcre_fullinfo.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains the external function pcre_fullinfo(), which returns
-information about a compiled pattern. */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-/*************************************************
-* Return info about compiled pattern *
-*************************************************/
-
-/* This is a newer "info" function which has an extensible interface so
-that additional items can be added compatibly.
-
-Arguments:
- argument_re points to compiled code
- extra_data points extra data, or NULL
- what what information is required
- where where to put the information
-
-Returns: 0 if data returned, negative on error
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data, int what,
- void *where)
-{
-real_pcre internal_re;
-pcre_study_data internal_study;
-const real_pcre *re = (const real_pcre *)argument_re;
-const pcre_study_data *study = NULL;
-
-if (re == NULL || where == NULL) return PCRE_ERROR_NULL;
-
-if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0)
- study = (const pcre_study_data *)extra_data->study_data;
-
-if (re->magic_number != MAGIC_NUMBER)
- {
- re = _pcre_try_flipped(re, &internal_re, study, &internal_study);
- if (re == NULL) return PCRE_ERROR_BADMAGIC;
- if (study != NULL) study = &internal_study;
- }
-
-switch (what)
- {
- case PCRE_INFO_OPTIONS:
- *((unsigned long int *)where) = re->options & PUBLIC_OPTIONS;
- break;
-
- case PCRE_INFO_SIZE:
- *((size_t *)where) = re->size;
- break;
-
- case PCRE_INFO_STUDYSIZE:
- *((size_t *)where) = (study == NULL)? 0 : study->size;
- break;
-
- case PCRE_INFO_CAPTURECOUNT:
- *((int *)where) = re->top_bracket;
- break;
-
- case PCRE_INFO_BACKREFMAX:
- *((int *)where) = re->top_backref;
- break;
-
- case PCRE_INFO_FIRSTBYTE:
- *((int *)where) =
- ((re->flags & PCRE_FIRSTSET) != 0)? re->first_byte :
- ((re->flags & PCRE_STARTLINE) != 0)? -1 : -2;
- break;
-
- /* Make sure we pass back the pointer to the bit vector in the external
- block, not the internal copy (with flipped integer fields). */
-
- case PCRE_INFO_FIRSTTABLE:
- *((const uschar **)where) =
- (study != NULL && (study->options & PCRE_STUDY_MAPPED) != 0)?
- ((const pcre_study_data *)extra_data->study_data)->start_bits : NULL;
- break;
-
- case PCRE_INFO_LASTLITERAL:
- *((int *)where) =
- ((re->flags & PCRE_REQCHSET) != 0)? re->req_byte : -1;
- break;
-
- case PCRE_INFO_NAMEENTRYSIZE:
- *((int *)where) = re->name_entry_size;
- break;
-
- case PCRE_INFO_NAMECOUNT:
- *((int *)where) = re->name_count;
- break;
-
- case PCRE_INFO_NAMETABLE:
- *((const uschar **)where) = (const uschar *)re + re->name_table_offset;
- break;
-
- case PCRE_INFO_DEFAULT_TABLES:
- *((const uschar **)where) = (const uschar *)(_pcre_default_tables);
- break;
-
- case PCRE_INFO_OKPARTIAL:
- *((int *)where) = (re->flags & PCRE_NOPARTIAL) == 0;
- break;
-
- case PCRE_INFO_JCHANGED:
- *((int *)where) = (re->flags & PCRE_JCHANGED) != 0;
- break;
-
- case PCRE_INFO_HASCRORLF:
- *((int *)where) = (re->flags & PCRE_HASCRORLF) != 0;
- break;
-
- default: return PCRE_ERROR_BADOPTION;
- }
-
-return 0;
-}
-
-/* End of pcre_fullinfo.c */
diff --git a/glib/pcre/pcre_get.c b/glib/pcre/pcre_get.c
deleted file mode 100644
index 611778640..000000000
--- a/glib/pcre/pcre_get.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains some convenience functions for extracting substrings
-from the subject string after a regex match has succeeded. The original idea
-for these functions came from Scott Wimer. */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-/*************************************************
-* Find number for named string *
-*************************************************/
-
-/* This function is used by the get_first_set() function below, as well
-as being generally available. It assumes that names are unique.
-
-Arguments:
- code the compiled regex
- stringname the name whose number is required
-
-Returns: the number of the named parentheses, or a negative number
- (PCRE_ERROR_NOSUBSTRING) if not found
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_get_stringnumber(const pcre *code, const char *stringname)
-{
-int rc;
-int entrysize;
-int top, bot;
-uschar *nametable;
-
-if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
- return rc;
-if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
-
-if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
- return rc;
-if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
- return rc;
-
-bot = 0;
-while (top > bot)
- {
- int mid = (top + bot) / 2;
- uschar *entry = nametable + entrysize*mid;
- int c = strcmp(stringname, (char *)(entry + 2));
- if (c == 0) return (entry[0] << 8) + entry[1];
- if (c > 0) bot = mid + 1; else top = mid;
- }
-
-return PCRE_ERROR_NOSUBSTRING;
-}
-
-
-
-/*************************************************
-* Find (multiple) entries for named string *
-*************************************************/
-
-/* This is used by the get_first_set() function below, as well as being
-generally available. It is used when duplicated names are permitted.
-
-Arguments:
- code the compiled regex
- stringname the name whose entries required
- firstptr where to put the pointer to the first entry
- lastptr where to put the pointer to the last entry
-
-Returns: the length of each entry, or a negative number
- (PCRE_ERROR_NOSUBSTRING) if not found
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_get_stringtable_entries(const pcre *code, const char *stringname,
- char **firstptr, char **lastptr)
-{
-int rc;
-int entrysize;
-int top, bot;
-uschar *nametable, *lastentry;
-
-if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
- return rc;
-if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
-
-if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
- return rc;
-if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
- return rc;
-
-lastentry = nametable + entrysize * (top - 1);
-bot = 0;
-while (top > bot)
- {
- int mid = (top + bot) / 2;
- uschar *entry = nametable + entrysize*mid;
- int c = strcmp(stringname, (char *)(entry + 2));
- if (c == 0)
- {
- uschar *first = entry;
- uschar *last = entry;
- while (first > nametable)
- {
- if (strcmp(stringname, (char *)(first - entrysize + 2)) != 0) break;
- first -= entrysize;
- }
- while (last < lastentry)
- {
- if (strcmp(stringname, (char *)(last + entrysize + 2)) != 0) break;
- last += entrysize;
- }
- *firstptr = (char *)first;
- *lastptr = (char *)last;
- return entrysize;
- }
- if (c > 0) bot = mid + 1; else top = mid;
- }
-
-return PCRE_ERROR_NOSUBSTRING;
-}
-
-
-
-/*************************************************
-* Find first set of multiple named strings *
-*************************************************/
-
-/* This function allows for duplicate names in the table of named substrings.
-It returns the number of the first one that was set in a pattern match.
-
-Arguments:
- code the compiled regex
- stringname the name of the capturing substring
- ovector the vector of matched substrings
-
-Returns: the number of the first that is set,
- or the number of the last one if none are set,
- or a negative number on error
-*/
-
-static int
-get_first_set(const pcre *code, const char *stringname, int *ovector)
-{
-const real_pcre *re = (const real_pcre *)code;
-int entrysize;
-char *first, *last;
-uschar *entry;
-if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
- return pcre_get_stringnumber(code, stringname);
-entrysize = pcre_get_stringtable_entries(code, stringname, &first, &last);
-if (entrysize <= 0) return entrysize;
-for (entry = (uschar *)first; entry <= (uschar *)last; entry += entrysize)
- {
- int n = (entry[0] << 8) + entry[1];
- if (ovector[n*2] >= 0) return n;
- }
-return (first[0] << 8) + first[1];
-}
-
-
-
-
-/*************************************************
-* Copy captured string to given buffer *
-*************************************************/
-
-/* This function copies a single captured substring into a given buffer.
-Note that we use memcpy() rather than strncpy() in case there are binary zeros
-in the string.
-
-Arguments:
- subject the subject string that was matched
- ovector pointer to the offsets table
- stringcount the number of substrings that were captured
- (i.e. the yield of the pcre_exec call, unless
- that was zero, in which case it should be 1/3
- of the offset table size)
- stringnumber the number of the required substring
- buffer where to put the substring
- size the size of the buffer
-
-Returns: if successful:
- the length of the copied string, not including the zero
- that is put on the end; can be zero
- if not successful:
- PCRE_ERROR_NOMEMORY (-6) buffer too small
- PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_copy_substring(const char *subject, int *ovector, int stringcount,
- int stringnumber, char *buffer, int size)
-{
-int yield;
-if (stringnumber < 0 || stringnumber >= stringcount)
- return PCRE_ERROR_NOSUBSTRING;
-stringnumber *= 2;
-yield = ovector[stringnumber+1] - ovector[stringnumber];
-if (size < yield + 1) return PCRE_ERROR_NOMEMORY;
-memcpy(buffer, subject + ovector[stringnumber], yield);
-buffer[yield] = 0;
-return yield;
-}
-
-
-
-/*************************************************
-* Copy named captured string to given buffer *
-*************************************************/
-
-/* This function copies a single captured substring into a given buffer,
-identifying it by name. If the regex permits duplicate names, the first
-substring that is set is chosen.
-
-Arguments:
- code the compiled regex
- subject the subject string that was matched
- ovector pointer to the offsets table
- stringcount the number of substrings that were captured
- (i.e. the yield of the pcre_exec call, unless
- that was zero, in which case it should be 1/3
- of the offset table size)
- stringname the name of the required substring
- buffer where to put the substring
- size the size of the buffer
-
-Returns: if successful:
- the length of the copied string, not including the zero
- that is put on the end; can be zero
- if not successful:
- PCRE_ERROR_NOMEMORY (-6) buffer too small
- PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector,
- int stringcount, const char *stringname, char *buffer, int size)
-{
-int n = get_first_set(code, stringname, ovector);
-if (n <= 0) return n;
-return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
-}
-
-
-
-/*************************************************
-* Copy all captured strings to new store *
-*************************************************/
-
-/* This function gets one chunk of store and builds a list of pointers and all
-of the captured substrings in it. A NULL pointer is put on the end of the list.
-
-Arguments:
- subject the subject string that was matched
- ovector pointer to the offsets table
- stringcount the number of substrings that were captured
- (i.e. the yield of the pcre_exec call, unless
- that was zero, in which case it should be 1/3
- of the offset table size)
- listptr set to point to the list of pointers
-
-Returns: if successful: 0
- if not successful:
- PCRE_ERROR_NOMEMORY (-6) failed to get store
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_get_substring_list(const char *subject, int *ovector, int stringcount,
- const char ***listptr)
-{
-int i;
-int size = sizeof(char *);
-int double_count = stringcount * 2;
-char **stringlist;
-char *p;
-
-for (i = 0; i < double_count; i += 2)
- size += sizeof(char *) + ovector[i+1] - ovector[i] + 1;
-
-stringlist = (char **)(pcre_malloc)(size);
-if (stringlist == NULL) return PCRE_ERROR_NOMEMORY;
-
-*listptr = (const char **)stringlist;
-p = (char *)(stringlist + stringcount + 1);
-
-for (i = 0; i < double_count; i += 2)
- {
- int len = ovector[i+1] - ovector[i];
- memcpy(p, subject + ovector[i], len);
- *stringlist++ = p;
- p += len;
- *p++ = 0;
- }
-
-*stringlist = NULL;
-return 0;
-}
-
-
-
-/*************************************************
-* Free store obtained by get_substring_list *
-*************************************************/
-
-/* This function exists for the benefit of people calling PCRE from non-C
-programs that can call its functions, but not free() or (pcre_free)() directly.
-
-Argument: the result of a previous pcre_get_substring_list()
-Returns: nothing
-*/
-
-PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
-pcre_free_substring_list(const char **pointer)
-{
-(pcre_free)((void *)pointer);
-}
-
-
-
-/*************************************************
-* Copy captured string to new store *
-*************************************************/
-
-/* This function copies a single captured substring into a piece of new
-store
-
-Arguments:
- subject the subject string that was matched
- ovector pointer to the offsets table
- stringcount the number of substrings that were captured
- (i.e. the yield of the pcre_exec call, unless
- that was zero, in which case it should be 1/3
- of the offset table size)
- stringnumber the number of the required substring
- stringptr where to put a pointer to the substring
-
-Returns: if successful:
- the length of the string, not including the zero that
- is put on the end; can be zero
- if not successful:
- PCRE_ERROR_NOMEMORY (-6) failed to get store
- PCRE_ERROR_NOSUBSTRING (-7) substring not present
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_get_substring(const char *subject, int *ovector, int stringcount,
- int stringnumber, const char **stringptr)
-{
-int yield;
-char *substring;
-if (stringnumber < 0 || stringnumber >= stringcount)
- return PCRE_ERROR_NOSUBSTRING;
-stringnumber *= 2;
-yield = ovector[stringnumber+1] - ovector[stringnumber];
-substring = (char *)(pcre_malloc)(yield + 1);
-if (substring == NULL) return PCRE_ERROR_NOMEMORY;
-memcpy(substring, subject + ovector[stringnumber], yield);
-substring[yield] = 0;
-*stringptr = substring;
-return yield;
-}
-
-
-
-/*************************************************
-* Copy named captured string to new store *
-*************************************************/
-
-/* This function copies a single captured substring, identified by name, into
-new store. If the regex permits duplicate names, the first substring that is
-set is chosen.
-
-Arguments:
- code the compiled regex
- subject the subject string that was matched
- ovector pointer to the offsets table
- stringcount the number of substrings that were captured
- (i.e. the yield of the pcre_exec call, unless
- that was zero, in which case it should be 1/3
- of the offset table size)
- stringname the name of the required substring
- stringptr where to put the pointer
-
-Returns: if successful:
- the length of the copied string, not including the zero
- that is put on the end; can be zero
- if not successful:
- PCRE_ERROR_NOMEMORY (-6) couldn't get memory
- PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_get_named_substring(const pcre *code, const char *subject, int *ovector,
- int stringcount, const char *stringname, const char **stringptr)
-{
-int n = get_first_set(code, stringname, ovector);
-if (n <= 0) return n;
-return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
-}
-
-
-
-
-/*************************************************
-* Free store obtained by get_substring *
-*************************************************/
-
-/* This function exists for the benefit of people calling PCRE from non-C
-programs that can call its functions, but not free() or (pcre_free)() directly.
-
-Argument: the result of a previous pcre_get_substring()
-Returns: nothing
-*/
-
-PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
-pcre_free_substring(const char *pointer)
-{
-(pcre_free)((void *)pointer);
-}
-
-/* End of pcre_get.c */
diff --git a/glib/pcre/pcre_globals.c b/glib/pcre/pcre_globals.c
deleted file mode 100644
index e759ed5ce..000000000
--- a/glib/pcre/pcre_globals.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains global variables that are exported by the PCRE library.
-PCRE is thread-clean and doesn't use any global variables in the normal sense.
-However, it calls memory allocation and freeing functions via the four
-indirections below, and it can optionally do callouts, using the fifth
-indirection. These values can be changed by the caller, but are shared between
-all threads. However, when compiling for Virtual Pascal, things are done
-differently, and global variables are not used (see pcre.in). */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-PCRE_EXP_DATA_DEFN int (*pcre_callout)(pcre_callout_block *) = NULL;
-
-/* End of pcre_globals.c */
diff --git a/glib/pcre/pcre_info.c b/glib/pcre/pcre_info.c
deleted file mode 100644
index 02cf1c91d..000000000
--- a/glib/pcre/pcre_info.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains the external function pcre_info(), which gives some
-information about a compiled pattern. However, use of this function is now
-deprecated, as it has been superseded by pcre_fullinfo(). */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-/*************************************************
-* (Obsolete) Return info about compiled pattern *
-*************************************************/
-
-/* This is the original "info" function. It picks potentially useful data out
-of the private structure, but its interface was too rigid. It remains for
-backwards compatibility. The public options are passed back in an int - though
-the re->options field has been expanded to a long int, all the public options
-at the low end of it, and so even on 16-bit systems this will still be OK.
-Therefore, I haven't changed the API for pcre_info().
-
-Arguments:
- argument_re points to compiled code
- optptr where to pass back the options
- first_byte where to pass back the first character,
- or -1 if multiline and all branches start ^,
- or -2 otherwise
-
-Returns: number of capturing subpatterns
- or negative values on error
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_info(const pcre *argument_re, int *optptr, int *first_byte)
-{
-real_pcre internal_re;
-const real_pcre *re = (const real_pcre *)argument_re;
-if (re == NULL) return PCRE_ERROR_NULL;
-if (re->magic_number != MAGIC_NUMBER)
- {
- re = _pcre_try_flipped(re, &internal_re, NULL, NULL);
- if (re == NULL) return PCRE_ERROR_BADMAGIC;
- }
-if (optptr != NULL) *optptr = (int)(re->options & PUBLIC_OPTIONS);
-if (first_byte != NULL)
- *first_byte = ((re->flags & PCRE_FIRSTSET) != 0)? re->first_byte :
- ((re->flags & PCRE_STARTLINE) != 0)? -1 : -2;
-return re->top_bracket;
-}
-
-/* End of pcre_info.c */
diff --git a/glib/pcre/pcre_internal.h b/glib/pcre/pcre_internal.h
deleted file mode 100644
index 519b8712a..000000000
--- a/glib/pcre/pcre_internal.h
+++ /dev/null
@@ -1,1157 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-/* This header contains definitions that are shared between the different
-modules, but which are not relevant to the exported API. This includes some
-functions whose names all begin with "_pcre_". */
-
-#ifndef PCRE_INTERNAL_H
-#define PCRE_INTERNAL_H
-
-/* Define DEBUG to get debugging output on stdout. */
-
-#if 0
-#define DEBUG
-#endif
-
-/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
-inline, and there are *still* stupid compilers about that don't like indented
-pre-processor statements, or at least there were when I first wrote this. After
-all, it had only been about 10 years then...
-
-It turns out that the Mac Debugging.h header also defines the macro DPRINTF, so
-be absolutely sure we get our version. */
-
-#undef DPRINTF
-#ifdef DEBUG
-#define DPRINTF(p) printf p
-#else
-#define DPRINTF(p) /* Nothing */
-#endif
-
-
-/* Standard C headers plus the external interface definition. The only time
-setjmp and stdarg are used is when NO_RECURSE is set. */
-
-#include <ctype.h>
-#include <limits.h>
-#include <setjmp.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* When compiling a DLL for Windows, the exported symbols have to be declared
-using some MS magic. I found some useful information on this web page:
-http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the
-information there, using __declspec(dllexport) without "extern" we have a
-definition; with "extern" we have a declaration. The settings here override the
-setting in pcre.h (which is included below); it defines only PCRE_EXP_DECL,
-which is all that is needed for applications (they just import the symbols). We
-use:
-
- PCRE_EXP_DECL for declarations
- PCRE_EXP_DEFN for definitions of exported functions
- PCRE_EXP_DATA_DEFN for definitions of exported variables
-
-The reason for the two DEFN macros is that in non-Windows environments, one
-does not want to have "extern" before variable definitions because it leads to
-compiler warnings. So we distinguish between functions and variables. In
-Windows, the two should always be the same.
-
-The reason for wrapping this in #ifndef PCRE_EXP_DECL is so that pcretest,
-which is an application, but needs to import this file in order to "peek" at
-internals, can #include pcre.h first to get an application's-eye view.
-
-In principle, people compiling for non-Windows, non-Unix-like (i.e. uncommon,
-special-purpose environments) might want to stick other stuff in front of
-exported symbols. That's why, in the non-Windows case, we set PCRE_EXP_DEFN and
-PCRE_EXP_DATA_DEFN only if they are not already set. */
-
-#ifndef PCRE_EXP_DECL
-# ifdef _WIN32
-# ifndef PCRE_STATIC
-# define PCRE_EXP_DECL extern __declspec(dllexport)
-# define PCRE_EXP_DEFN __declspec(dllexport)
-# define PCRE_EXP_DATA_DEFN __declspec(dllexport)
-# else
-# define PCRE_EXP_DECL extern
-# define PCRE_EXP_DEFN
-# define PCRE_EXP_DATA_DEFN
-# endif
-# else
-# ifdef __cplusplus
-# define PCRE_EXP_DECL extern "C"
-# else
-# define PCRE_EXP_DECL extern
-# endif
-# ifndef PCRE_EXP_DEFN
-# define PCRE_EXP_DEFN PCRE_EXP_DECL
-# endif
-# ifndef PCRE_EXP_DATA_DEFN
-# define PCRE_EXP_DATA_DEFN
-# endif
-# endif
-#endif
-
-/* When compiling with the MSVC compiler, it is sometimes necessary to include
-a "calling convention" before exported function names. (This is secondhand
-information; I know nothing about MSVC myself). For example, something like
-
- void __cdecl function(....)
-
-might be needed. In order so make this easy, all the exported functions have
-PCRE_CALL_CONVENTION just before their names. It is rarely needed; if not
-set, we ensure here that it has no effect. */
-
-#ifndef PCRE_CALL_CONVENTION
-#define PCRE_CALL_CONVENTION
-#endif
-
-/* We need to have types that specify unsigned 16-bit and 32-bit integers. We
-cannot determine these outside the compilation (e.g. by running a program as
-part of "configure") because PCRE is often cross-compiled for use on other
-systems. Instead we make use of the maximum sizes that are available at
-preprocessor time in standard C environments. */
-
-#if USHRT_MAX == 65535
- typedef unsigned short pcre_uint16;
- typedef short pcre_int16;
-#elif UINT_MAX == 65535
- typedef unsigned int pcre_uint16;
- typedef int pcre_int16;
-#else
- #error Cannot determine a type for 16-bit unsigned integers
-#endif
-
-#if UINT_MAX == 4294967295
- typedef unsigned int pcre_uint32;
- typedef int pcre_int32;
-#elif ULONG_MAX == 4294967295
- typedef unsigned long int pcre_uint32;
- typedef long int pcre_int32;
-#else
- #error Cannot determine a type for 32-bit unsigned integers
-#endif
-
-/* All character handling must be done as unsigned characters. Otherwise there
-are problems with top-bit-set characters and functions such as isspace().
-However, we leave the interface to the outside world as char *, because that
-should make things easier for callers. We define a short type for unsigned char
-to save lots of typing. I tried "uchar", but it causes problems on Digital
-Unix, where it is defined in sys/types, so use "uschar" instead. */
-
-typedef unsigned char uschar;
-
-/* This is an unsigned int value that no character can ever have. UTF-8
-characters only go up to 0x7fffffff (though Unicode doesn't go beyond
-0x0010ffff). */
-
-#define NOTACHAR 0xffffffff
-
-/* PCRE is able to support several different kinds of newline (CR, LF, CRLF,
-"any" and "anycrlf" at present). The following macros are used to package up
-testing for newlines. NLBLOCK, PSSTART, and PSEND are defined in the various
-modules to indicate in which datablock the parameters exist, and what the
-start/end of string field names are. */
-
-#define NLTYPE_FIXED 0 /* Newline is a fixed length string */
-#define NLTYPE_ANY 1 /* Newline is any Unicode line ending */
-#define NLTYPE_ANYCRLF 2 /* Newline is CR, LF, or CRLF */
-
-/* This macro checks for a newline at the given position */
-
-#define IS_NEWLINE(p) \
- ((NLBLOCK->nltype != NLTYPE_FIXED)? \
- ((p) < NLBLOCK->PSEND && \
- _pcre_is_newline((p), NLBLOCK->nltype, NLBLOCK->PSEND, &(NLBLOCK->nllen),\
- utf8)) \
- : \
- ((p) <= NLBLOCK->PSEND - NLBLOCK->nllen && \
- (p)[0] == NLBLOCK->nl[0] && \
- (NLBLOCK->nllen == 1 || (p)[1] == NLBLOCK->nl[1]) \
- ) \
- )
-
-/* This macro checks for a newline immediately preceding the given position */
-
-#define WAS_NEWLINE(p) \
- ((NLBLOCK->nltype != NLTYPE_FIXED)? \
- ((p) > NLBLOCK->PSSTART && \
- _pcre_was_newline((p), NLBLOCK->nltype, NLBLOCK->PSSTART, \
- &(NLBLOCK->nllen), utf8)) \
- : \
- ((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \
- (p)[-NLBLOCK->nllen] == NLBLOCK->nl[0] && \
- (NLBLOCK->nllen == 1 || (p)[-NLBLOCK->nllen+1] == NLBLOCK->nl[1]) \
- ) \
- )
-
-/* When PCRE is compiled as a C++ library, the subject pointer can be replaced
-with a custom type. This makes it possible, for example, to allow pcre_exec()
-to process subject strings that are discontinuous by using a smart pointer
-class. It must always be possible to inspect all of the subject string in
-pcre_exec() because of the way it backtracks. Two macros are required in the
-normal case, for sign-unspecified and unsigned char pointers. The former is
-used for the external interface and appears in pcre.h, which is why its name
-must begin with PCRE_. */
-
-#ifdef CUSTOM_SUBJECT_PTR
-#define PCRE_SPTR CUSTOM_SUBJECT_PTR
-#define USPTR CUSTOM_SUBJECT_PTR
-#else
-#define PCRE_SPTR const char *
-#define USPTR const unsigned char *
-#endif
-
-
-
-/* Include the public PCRE header and the definitions of UCP character property
-values. */
-
-#include "pcre.h"
-#include "ucp.h"
-
-/* When compiling for use with the Virtual Pascal compiler, these functions
-need to have their names changed. PCRE must be compiled with the -DVPCOMPAT
-option on the command line. */
-
-#ifdef VPCOMPAT
-#define strlen(s) _strlen(s)
-#define strncmp(s1,s2,m) _strncmp(s1,s2,m)
-#define memcmp(s,c,n) _memcmp(s,c,n)
-#define memcpy(d,s,n) _memcpy(d,s,n)
-#define memset(s,c,n) _memset(s,c,n)
-#else /* VPCOMPAT */
-
-/* To cope with SunOS4 and other systems that lack memmove() but have bcopy(),
-define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY
-is set. Otherwise, include an emulating function for those systems that have
-neither (there some non-Unix environments where this is the case). */
-
-#ifndef HAVE_MEMMOVE
-#undef memmove /* some systems may have a macro */
-#ifdef HAVE_BCOPY
-#define memmove(a, b, c) bcopy(b, a, c)
-#else /* HAVE_BCOPY */
-static void *
-pcre_memmove(void *d, const void *s, size_t n)
-{
-size_t i;
-unsigned char *dest = (unsigned char *)d;
-const unsigned char *src = (const unsigned char *)s;
-if (dest > src)
- {
- dest += n;
- src += n;
- for (i = 0; i < n; ++i) *(--dest) = *(--src);
- return (void *)dest;
- }
-else
- {
- for (i = 0; i < n; ++i) *dest++ = *src++;
- return (void *)(dest - n);
- }
-}
-#define memmove(a, b, c) pcre_memmove(a, b, c)
-#endif /* not HAVE_BCOPY */
-#endif /* not HAVE_MEMMOVE */
-#endif /* not VPCOMPAT */
-
-
-/* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored
-in big-endian order) by default. These are used, for example, to link from the
-start of a subpattern to its alternatives and its end. The use of 2 bytes per
-offset limits the size of the compiled regex to around 64K, which is big enough
-for almost everybody. However, I received a request for an even bigger limit.
-For this reason, and also to make the code easier to maintain, the storing and
-loading of offsets from the byte string is now handled by the macros that are
-defined here.
-
-The macros are controlled by the value of LINK_SIZE. This defaults to 2 in
-the config.h file, but can be overridden by using -D on the command line. This
-is automated on Unix systems via the "configure" command. */
-
-#if LINK_SIZE == 2
-
-#define PUT(a,n,d) \
- (a[n] = (d) >> 8), \
- (a[(n)+1] = (d) & 255)
-
-#define GET(a,n) \
- (((a)[n] << 8) | (a)[(n)+1])
-
-#define MAX_PATTERN_SIZE (1 << 16)
-
-
-#elif LINK_SIZE == 3
-
-#define PUT(a,n,d) \
- (a[n] = (d) >> 16), \
- (a[(n)+1] = (d) >> 8), \
- (a[(n)+2] = (d) & 255)
-
-#define GET(a,n) \
- (((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2])
-
-#define MAX_PATTERN_SIZE (1 << 24)
-
-
-#elif LINK_SIZE == 4
-
-#define PUT(a,n,d) \
- (a[n] = (d) >> 24), \
- (a[(n)+1] = (d) >> 16), \
- (a[(n)+2] = (d) >> 8), \
- (a[(n)+3] = (d) & 255)
-
-#define GET(a,n) \
- (((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3])
-
-#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */
-
-
-#else
-#error LINK_SIZE must be either 2, 3, or 4
-#endif
-
-
-/* Convenience macro defined in terms of the others */
-
-#define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE
-
-
-/* PCRE uses some other 2-byte quantities that do not change when the size of
-offsets changes. There are used for repeat counts and for other things such as
-capturing parenthesis numbers in back references. */
-
-#define PUT2(a,n,d) \
- a[n] = (d) >> 8; \
- a[(n)+1] = (d) & 255
-
-#define GET2(a,n) \
- (((a)[n] << 8) | (a)[(n)+1])
-
-#define PUT2INC(a,n,d) PUT2(a,n,d), a += 2
-
-
-/* When UTF-8 encoding is being used, a character is no longer just a single
-byte. The macros for character handling generate simple sequences when used in
-byte-mode, and more complicated ones for UTF-8 characters. BACKCHAR should
-never be called in byte mode. To make sure it can never even appear when UTF-8
-support is omitted, we don't even define it. */
-
-#ifndef SUPPORT_UTF8
-#define GETCHAR(c, eptr) c = *eptr;
-#define GETCHARTEST(c, eptr) c = *eptr;
-#define GETCHARINC(c, eptr) c = *eptr++;
-#define GETCHARINCTEST(c, eptr) c = *eptr++;
-#define GETCHARLEN(c, eptr, len) c = *eptr;
-/* #define BACKCHAR(eptr) */
-
-#else /* SUPPORT_UTF8 */
-
-/* Get the next UTF-8 character, not advancing the pointer. This is called when
-we know we are in UTF-8 mode. */
-
-#define GETCHAR(c, eptr) \
- c = *eptr; \
- if (c >= 0xc0) \
- { \
- int gcii; \
- int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \
- int gcss = 6*gcaa; \
- c = (c & _pcre_utf8_table3[gcaa]) << gcss; \
- for (gcii = 1; gcii <= gcaa; gcii++) \
- { \
- gcss -= 6; \
- c |= (eptr[gcii] & 0x3f) << gcss; \
- } \
- }
-
-/* Get the next UTF-8 character, testing for UTF-8 mode, and not advancing the
-pointer. */
-
-#define GETCHARTEST(c, eptr) \
- c = *eptr; \
- if (utf8 && c >= 0xc0) \
- { \
- int gcii; \
- int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \
- int gcss = 6*gcaa; \
- c = (c & _pcre_utf8_table3[gcaa]) << gcss; \
- for (gcii = 1; gcii <= gcaa; gcii++) \
- { \
- gcss -= 6; \
- c |= (eptr[gcii] & 0x3f) << gcss; \
- } \
- }
-
-/* Get the next UTF-8 character, advancing the pointer. This is called when we
-know we are in UTF-8 mode. */
-
-#define GETCHARINC(c, eptr) \
- c = *eptr++; \
- if (c >= 0xc0) \
- { \
- int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \
- int gcss = 6*gcaa; \
- c = (c & _pcre_utf8_table3[gcaa]) << gcss; \
- while (gcaa-- > 0) \
- { \
- gcss -= 6; \
- c |= (*eptr++ & 0x3f) << gcss; \
- } \
- }
-
-/* Get the next character, testing for UTF-8 mode, and advancing the pointer */
-
-#define GETCHARINCTEST(c, eptr) \
- c = *eptr++; \
- if (utf8 && c >= 0xc0) \
- { \
- int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \
- int gcss = 6*gcaa; \
- c = (c & _pcre_utf8_table3[gcaa]) << gcss; \
- while (gcaa-- > 0) \
- { \
- gcss -= 6; \
- c |= (*eptr++ & 0x3f) << gcss; \
- } \
- }
-
-/* Get the next UTF-8 character, not advancing the pointer, incrementing length
-if there are extra bytes. This is called when we know we are in UTF-8 mode. */
-
-#define GETCHARLEN(c, eptr, len) \
- c = *eptr; \
- if (c >= 0xc0) \
- { \
- int gcii; \
- int gcaa = _pcre_utf8_table4[c & 0x3f]; /* Number of additional bytes */ \
- int gcss = 6*gcaa; \
- c = (c & _pcre_utf8_table3[gcaa]) << gcss; \
- for (gcii = 1; gcii <= gcaa; gcii++) \
- { \
- gcss -= 6; \
- c |= (eptr[gcii] & 0x3f) << gcss; \
- } \
- len += gcaa; \
- }
-
-/* If the pointer is not at the start of a character, move it back until
-it is. This is called only in UTF-8 mode - we don't put a test within the macro
-because almost all calls are already within a block of UTF-8 only code. */
-
-#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--
-
-#endif
-
-
-/* In case there is no definition of offsetof() provided - though any proper
-Standard C system should have one. */
-
-#ifndef offsetof
-#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
-#endif
-
-
-/* These are the public options that can change during matching. */
-
-#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL)
-
-/* Private flags containing information about the compiled regex. They used to
-live at the top end of the options word, but that got almost full, so now they
-are in a 16-bit flags word. */
-
-#define PCRE_NOPARTIAL 0x0001 /* can't use partial with this regex */
-#define PCRE_FIRSTSET 0x0002 /* first_byte is set */
-#define PCRE_REQCHSET 0x0004 /* req_byte is set */
-#define PCRE_STARTLINE 0x0008 /* start after \n for multiline */
-#define PCRE_JCHANGED 0x0010 /* j option used in regex */
-#define PCRE_HASCRORLF 0x0020 /* explicit \r or \n in pattern */
-
-/* Options for the "extra" block produced by pcre_study(). */
-
-#define PCRE_STUDY_MAPPED 0x01 /* a map of starting chars exists */
-
-/* Masks for identifying the public options that are permitted at compile
-time, run time, or study time, respectively. */
-
-#define PCRE_NEWLINE_BITS (PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_ANY| \
- PCRE_NEWLINE_ANYCRLF)
-
-#define PUBLIC_OPTIONS \
- (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \
- PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \
- PCRE_NO_AUTO_CAPTURE|PCRE_NO_UTF8_CHECK|PCRE_AUTO_CALLOUT|PCRE_FIRSTLINE| \
- PCRE_DUPNAMES|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \
- PCRE_JAVASCRIPT_COMPAT)
-
-#define PUBLIC_EXEC_OPTIONS \
- (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NO_UTF8_CHECK| \
- PCRE_PARTIAL|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)
-
-#define PUBLIC_DFA_EXEC_OPTIONS \
- (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NO_UTF8_CHECK| \
- PCRE_PARTIAL|PCRE_DFA_SHORTEST|PCRE_DFA_RESTART|PCRE_NEWLINE_BITS| \
- PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)
-
-#define PUBLIC_STUDY_OPTIONS 0 /* None defined */
-
-/* Magic number to provide a small check against being handed junk. Also used
-to detect whether a pattern was compiled on a host of different endianness. */
-
-#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */
-
-/* Negative values for the firstchar and reqchar variables */
-
-#define REQ_UNSET (-2)
-#define REQ_NONE (-1)
-
-/* The maximum remaining length of subject we are prepared to search for a
-req_byte match. */
-
-#define REQ_BYTE_MAX 1000
-
-/* Flags added to firstbyte or reqbyte; a "non-literal" item is either a
-variable-length repeat, or a anything other than literal characters. */
-
-#define REQ_CASELESS 0x0100 /* indicates caselessness */
-#define REQ_VARY 0x0200 /* reqbyte followed non-literal item */
-
-/* Miscellaneous definitions. The #ifndef is to pacify compiler warnings in
-environments where these macros are defined elsewhere. */
-
-typedef gboolean BOOL;
-
-/* Escape items that are just an encoding of a particular data value. */
-
-#ifndef ESC_e
-#define ESC_e 27
-#endif
-
-#ifndef ESC_f
-#define ESC_f '\f'
-#endif
-
-#ifndef ESC_n
-#define ESC_n '\n'
-#endif
-
-#ifndef ESC_r
-#define ESC_r '\r'
-#endif
-
-/* We can't officially use ESC_t because it is a POSIX reserved identifier
-(presumably because of all the others like size_t). */
-
-#ifndef ESC_tee
-#define ESC_tee '\t'
-#endif
-
-/* Codes for different types of Unicode property */
-
-#define PT_ANY 0 /* Any property - matches all chars */
-#define PT_LAMP 1 /* L& - the union of Lu, Ll, Lt */
-#define PT_GC 2 /* General characteristic (e.g. L) */
-#define PT_PC 3 /* Particular characteristic (e.g. Lu) */
-#define PT_SC 4 /* Script (e.g. Han) */
-
-/* Flag bits and data types for the extended class (OP_XCLASS) for classes that
-contain UTF-8 characters with values greater than 255. */
-
-#define XCL_NOT 0x01 /* Flag: this is a negative class */
-#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */
-
-#define XCL_END 0 /* Marks end of individual items */
-#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */
-#define XCL_RANGE 2 /* A range (two multibyte chars) follows */
-#define XCL_PROP 3 /* Unicode property (2-byte property code follows) */
-#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */
-
-/* These are escaped items that aren't just an encoding of a particular data
-value such as \n. They must have non-zero values, as check_escape() returns
-their negation. Also, they must appear in the same order as in the opcode
-definitions below, up to ESC_z. There's a dummy for OP_ANY because it
-corresponds to "." rather than an escape sequence, and another for OP_ALLANY
-(which is used for [^] in JavaScript compatibility mode).
-
-The final escape must be ESC_REF as subsequent values are used for
-backreferences (\1, \2, \3, etc). There are two tests in the code for an escape
-greater than ESC_b and less than ESC_Z to detect the types that may be
-repeated. These are the types that consume characters. If any new escapes are
-put in between that don't consume a character, that code will have to change.
-*/
-
-enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s,
- ESC_W, ESC_w, ESC_dum1, ESC_dum2, ESC_C, ESC_P, ESC_p, ESC_R, ESC_H,
- ESC_h, ESC_V, ESC_v, ESC_X, ESC_Z, ESC_z, ESC_E, ESC_Q, ESC_g, ESC_k,
- ESC_REF };
-
-
-/* Opcode table: Starting from 1 (i.e. after OP_END), the values up to
-OP_EOD must correspond in order to the list of escapes immediately above.
-
-*** NOTE NOTE NOTE *** Whenever this list is updated, the two macro definitions
-that follow must also be updated to match. There is also a table called
-"coptable" in pcre_dfa_exec.c that must be updated. */
-
-enum {
- OP_END, /* 0 End of pattern */
-
- /* Values corresponding to backslashed metacharacters */
-
- OP_SOD, /* 1 Start of data: \A */
- OP_SOM, /* 2 Start of match (subject + offset): \G */
- OP_SET_SOM, /* 3 Set start of match (\K) */
- OP_NOT_WORD_BOUNDARY, /* 4 \B */
- OP_WORD_BOUNDARY, /* 5 \b */
- OP_NOT_DIGIT, /* 6 \D */
- OP_DIGIT, /* 7 \d */
- OP_NOT_WHITESPACE, /* 8 \S */
- OP_WHITESPACE, /* 9 \s */
- OP_NOT_WORDCHAR, /* 10 \W */
- OP_WORDCHAR, /* 11 \w */
- OP_ANY, /* 12 Match any character (subject to DOTALL) */
- OP_ALLANY, /* 13 Match any character (not subject to DOTALL) */
- OP_ANYBYTE, /* 14 Match any byte (\C); different to OP_ANY for UTF-8 */
- OP_NOTPROP, /* 15 \P (not Unicode property) */
- OP_PROP, /* 16 \p (Unicode property) */
- OP_ANYNL, /* 17 \R (any newline sequence) */
- OP_NOT_HSPACE, /* 18 \H (not horizontal whitespace) */
- OP_HSPACE, /* 19 \h (horizontal whitespace) */
- OP_NOT_VSPACE, /* 20 \V (not vertical whitespace) */
- OP_VSPACE, /* 21 \v (vertical whitespace) */
- OP_EXTUNI, /* 22 \X (extended Unicode sequence */
- OP_EODN, /* 23 End of data or \n at end of data: \Z. */
- OP_EOD, /* 24 End of data: \z */
-
- OP_OPT, /* 25 Set runtime options */
- OP_CIRC, /* 26 Start of line - varies with multiline switch */
- OP_DOLL, /* 27 End of line - varies with multiline switch */
- OP_CHAR, /* 28 Match one character, casefully */
- OP_CHARNC, /* 29 Match one character, caselessly */
- OP_NOT, /* 30 Match one character, not the following one */
-
- OP_STAR, /* 31 The maximizing and minimizing versions of */
- OP_MINSTAR, /* 32 these six opcodes must come in pairs, with */
- OP_PLUS, /* 33 the minimizing one second. */
- OP_MINPLUS, /* 34 This first set applies to single characters.*/
- OP_QUERY, /* 35 */
- OP_MINQUERY, /* 36 */
-
- OP_UPTO, /* 37 From 0 to n matches */
- OP_MINUPTO, /* 38 */
- OP_EXACT, /* 39 Exactly n matches */
-
- OP_POSSTAR, /* 40 Possessified star */
- OP_POSPLUS, /* 41 Possessified plus */
- OP_POSQUERY, /* 42 Posesssified query */
- OP_POSUPTO, /* 43 Possessified upto */
-
- OP_NOTSTAR, /* 44 The maximizing and minimizing versions of */
- OP_NOTMINSTAR, /* 45 these six opcodes must come in pairs, with */
- OP_NOTPLUS, /* 46 the minimizing one second. They must be in */
- OP_NOTMINPLUS, /* 47 exactly the same order as those above. */
- OP_NOTQUERY, /* 48 This set applies to "not" single characters. */
- OP_NOTMINQUERY, /* 49 */
-
- OP_NOTUPTO, /* 50 From 0 to n matches */
- OP_NOTMINUPTO, /* 51 */
- OP_NOTEXACT, /* 52 Exactly n matches */
-
- OP_NOTPOSSTAR, /* 53 Possessified versions */
- OP_NOTPOSPLUS, /* 54 */
- OP_NOTPOSQUERY, /* 55 */
- OP_NOTPOSUPTO, /* 56 */
-
- OP_TYPESTAR, /* 57 The maximizing and minimizing versions of */
- OP_TYPEMINSTAR, /* 58 these six opcodes must come in pairs, with */
- OP_TYPEPLUS, /* 59 the minimizing one second. These codes must */
- OP_TYPEMINPLUS, /* 60 be in exactly the same order as those above. */
- OP_TYPEQUERY, /* 61 This set applies to character types such as \d */
- OP_TYPEMINQUERY, /* 62 */
-
- OP_TYPEUPTO, /* 63 From 0 to n matches */
- OP_TYPEMINUPTO, /* 64 */
- OP_TYPEEXACT, /* 65 Exactly n matches */
-
- OP_TYPEPOSSTAR, /* 66 Possessified versions */
- OP_TYPEPOSPLUS, /* 67 */
- OP_TYPEPOSQUERY, /* 68 */
- OP_TYPEPOSUPTO, /* 69 */
-
- OP_CRSTAR, /* 70 The maximizing and minimizing versions of */
- OP_CRMINSTAR, /* 71 all these opcodes must come in pairs, with */
- OP_CRPLUS, /* 72 the minimizing one second. These codes must */
- OP_CRMINPLUS, /* 73 be in exactly the same order as those above. */
- OP_CRQUERY, /* 74 These are for character classes and back refs */
- OP_CRMINQUERY, /* 75 */
- OP_CRRANGE, /* 76 These are different to the three sets above. */
- OP_CRMINRANGE, /* 77 */
-
- OP_CLASS, /* 78 Match a character class, chars < 256 only */
- OP_NCLASS, /* 79 Same, but the bitmap was created from a negative
- class - the difference is relevant only when a UTF-8
- character > 255 is encountered. */
-
- OP_XCLASS, /* 80 Extended class for handling UTF-8 chars within the
- class. This does both positive and negative. */
-
- OP_REF, /* 81 Match a back reference */
- OP_RECURSE, /* 82 Match a numbered subpattern (possibly recursive) */
- OP_CALLOUT, /* 83 Call out to external function if provided */
-
- OP_ALT, /* 84 Start of alternation */
- OP_KET, /* 85 End of group that doesn't have an unbounded repeat */
- OP_KETRMAX, /* 86 These two must remain together and in this */
- OP_KETRMIN, /* 87 order. They are for groups the repeat for ever. */
-
- /* The assertions must come before BRA, CBRA, ONCE, and COND.*/
-
- OP_ASSERT, /* 88 Positive lookahead */
- OP_ASSERT_NOT, /* 89 Negative lookahead */
- OP_ASSERTBACK, /* 90 Positive lookbehind */
- OP_ASSERTBACK_NOT, /* 91 Negative lookbehind */
- OP_REVERSE, /* 92 Move pointer back - used in lookbehind assertions */
-
- /* ONCE, BRA, CBRA, and COND must come after the assertions, with ONCE first,
- as there's a test for >= ONCE for a subpattern that isn't an assertion. */
-
- OP_ONCE, /* 93 Atomic group */
- OP_BRA, /* 94 Start of non-capturing bracket */
- OP_CBRA, /* 95 Start of capturing bracket */
- OP_COND, /* 96 Conditional group */
-
- /* These three must follow the previous three, in the same order. There's a
- check for >= SBRA to distinguish the two sets. */
-
- OP_SBRA, /* 97 Start of non-capturing bracket, check empty */
- OP_SCBRA, /* 98 Start of capturing bracket, check empty */
- OP_SCOND, /* 99 Conditional group, check empty */
-
- OP_CREF, /* 100 Used to hold a capture number as condition */
- OP_RREF, /* 101 Used to hold a recursion number as condition */
- OP_DEF, /* 102 The DEFINE condition */
-
- OP_BRAZERO, /* 103 These two must remain together and in this */
- OP_BRAMINZERO, /* 104 order. */
-
- /* These are backtracking control verbs */
-
- OP_PRUNE, /* 105 */
- OP_SKIP, /* 106 */
- OP_THEN, /* 107 */
- OP_COMMIT, /* 108 */
-
- /* These are forced failure and success verbs */
-
- OP_FAIL, /* 109 */
- OP_ACCEPT, /* 110 */
-
- /* This is used to skip a subpattern with a {0} quantifier */
-
- OP_SKIPZERO /* 111 */
-};
-
-
-/* This macro defines textual names for all the opcodes. These are used only
-for debugging. The macro is referenced only in pcre_printint.c. */
-
-#define OP_NAME_LIST \
- "End", "\\A", "\\G", "\\K", "\\B", "\\b", "\\D", "\\d", \
- "\\S", "\\s", "\\W", "\\w", "Any", "AllAny", "Anybyte", \
- "notprop", "prop", "\\R", "\\H", "\\h", "\\V", "\\v", \
- "extuni", "\\Z", "\\z", \
- "Opt", "^", "$", "char", "charnc", "not", \
- "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \
- "*+","++", "?+", "{", \
- "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \
- "*+","++", "?+", "{", \
- "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \
- "*+","++", "?+", "{", \
- "*", "*?", "+", "+?", "?", "??", "{", "{", \
- "class", "nclass", "xclass", "Ref", "Recurse", "Callout", \
- "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not", \
- "AssertB", "AssertB not", "Reverse", \
- "Once", "Bra", "CBra", "Cond", "SBra", "SCBra", "SCond", \
- "Cond ref", "Cond rec", "Cond def", "Brazero", "Braminzero", \
- "*PRUNE", "*SKIP", "*THEN", "*COMMIT", "*FAIL", "*ACCEPT", \
- "Skip zero"
-
-
-/* This macro defines the length of fixed length operations in the compiled
-regex. The lengths are used when searching for specific things, and also in the
-debugging printing of a compiled regex. We use a macro so that it can be
-defined close to the definitions of the opcodes themselves.
-
-As things have been extended, some of these are no longer fixed lenths, but are
-minima instead. For example, the length of a single-character repeat may vary
-in UTF-8 mode. The code that uses this table must know about such things. */
-
-#define OP_LENGTHS \
- 1, /* End */ \
- 1, 1, 1, 1, 1, /* \A, \G, \K, \B, \b */ \
- 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */ \
- 1, 1, 1, /* Any, AllAny, Anybyte */ \
- 3, 3, 1, /* NOTPROP, PROP, EXTUNI */ \
- 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */ \
- 1, 1, 2, 1, 1, /* \Z, \z, Opt, ^, $ */ \
- 2, /* Char - the minimum length */ \
- 2, /* Charnc - the minimum length */ \
- 2, /* not */ \
- /* Positive single-char repeats ** These are */ \
- 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** minima in */ \
- 4, 4, 4, /* upto, minupto, exact ** UTF-8 mode */ \
- 2, 2, 2, 4, /* *+, ++, ?+, upto+ */ \
- /* Negative single-char repeats - only for chars < 256 */ \
- 2, 2, 2, 2, 2, 2, /* NOT *, *?, +, +?, ?, ?? */ \
- 4, 4, 4, /* NOT upto, minupto, exact */ \
- 2, 2, 2, 4, /* Possessive *, +, ?, upto */ \
- /* Positive type repeats */ \
- 2, 2, 2, 2, 2, 2, /* Type *, *?, +, +?, ?, ?? */ \
- 4, 4, 4, /* Type upto, minupto, exact */ \
- 2, 2, 2, 4, /* Possessive *+, ++, ?+, upto+ */ \
- /* Character class & ref repeats */ \
- 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \
- 5, 5, /* CRRANGE, CRMINRANGE */ \
- 33, /* CLASS */ \
- 33, /* NCLASS */ \
- 0, /* XCLASS - variable length */ \
- 3, /* REF */ \
- 1+LINK_SIZE, /* RECURSE */ \
- 2+2*LINK_SIZE, /* CALLOUT */ \
- 1+LINK_SIZE, /* Alt */ \
- 1+LINK_SIZE, /* Ket */ \
- 1+LINK_SIZE, /* KetRmax */ \
- 1+LINK_SIZE, /* KetRmin */ \
- 1+LINK_SIZE, /* Assert */ \
- 1+LINK_SIZE, /* Assert not */ \
- 1+LINK_SIZE, /* Assert behind */ \
- 1+LINK_SIZE, /* Assert behind not */ \
- 1+LINK_SIZE, /* Reverse */ \
- 1+LINK_SIZE, /* ONCE */ \
- 1+LINK_SIZE, /* BRA */ \
- 3+LINK_SIZE, /* CBRA */ \
- 1+LINK_SIZE, /* COND */ \
- 1+LINK_SIZE, /* SBRA */ \
- 3+LINK_SIZE, /* SCBRA */ \
- 1+LINK_SIZE, /* SCOND */ \
- 3, /* CREF */ \
- 3, /* RREF */ \
- 1, /* DEF */ \
- 1, 1, /* BRAZERO, BRAMINZERO */ \
- 1, 1, 1, 1, /* PRUNE, SKIP, THEN, COMMIT, */ \
- 1, 1, 1 /* FAIL, ACCEPT, SKIPZERO */
-
-
-/* A magic value for OP_RREF to indicate the "any recursion" condition. */
-
-#define RREF_ANY 0xffff
-
-/* Error code numbers. They are given names so that they can more easily be
-tracked. */
-
-enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9,
- ERR10, ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19,
- ERR20, ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29,
- ERR30, ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39,
- ERR40, ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49,
- ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59,
- ERR60, ERR61, ERR62, ERR63, ERR64 };
-
-/* The real format of the start of the pcre block; the index of names and the
-code vector run on as long as necessary after the end. We store an explicit
-offset to the name table so that if a regex is compiled on one host, saved, and
-then run on another where the size of pointers is different, all might still
-be well. For the case of compiled-on-4 and run-on-8, we include an extra
-pointer that is always NULL. For future-proofing, a few dummy fields were
-originally included - even though you can never get this planning right - but
-there is only one left now.
-
-NOTE NOTE NOTE:
-Because people can now save and re-use compiled patterns, any additions to this
-structure should be made at the end, and something earlier (e.g. a new
-flag in the options or one of the dummy fields) should indicate that the new
-fields are present. Currently PCRE always sets the dummy fields to zero.
-NOTE NOTE NOTE:
-*/
-
-typedef struct real_pcre {
- pcre_uint32 magic_number;
- pcre_uint32 size; /* Total that was malloced */
- pcre_uint32 options; /* Public options */
- pcre_uint16 flags; /* Private flags */
- pcre_uint16 dummy1; /* For future use */
- pcre_uint16 top_bracket;
- pcre_uint16 top_backref;
- pcre_uint16 first_byte;
- pcre_uint16 req_byte;
- pcre_uint16 name_table_offset; /* Offset to name table that follows */
- pcre_uint16 name_entry_size; /* Size of any name items */
- pcre_uint16 name_count; /* Number of name items */
- pcre_uint16 ref_count; /* Reference count */
-
- const unsigned char *tables; /* Pointer to tables or NULL for std */
- const unsigned char *nullpad; /* NULL padding */
-} real_pcre;
-
-/* The format of the block used to store data from pcre_study(). The same
-remark (see NOTE above) about extending this structure applies. */
-
-typedef struct pcre_study_data {
- pcre_uint32 size; /* Total that was malloced */
- pcre_uint32 options;
- uschar start_bits[32];
-} pcre_study_data;
-
-/* Structure for passing "static" information around between the functions
-doing the compiling, so that they are thread-safe. */
-
-typedef struct compile_data {
- const uschar *lcc; /* Points to lower casing table */
- const uschar *fcc; /* Points to case-flipping table */
- const uschar *cbits; /* Points to character type table */
- const uschar *ctypes; /* Points to table of type maps */
- const uschar *start_workspace;/* The start of working space */
- const uschar *start_code; /* The start of the compiled code */
- const uschar *start_pattern; /* The start of the pattern */
- const uschar *end_pattern; /* The end of the pattern */
- uschar *hwm; /* High watermark of workspace */
- uschar *name_table; /* The name/number table */
- int names_found; /* Number of entries so far */
- int name_entry_size; /* Size of each entry */
- int bracount; /* Count of capturing parens as we compile */
- int final_bracount; /* Saved value after first pass */
- int top_backref; /* Maximum back reference */
- unsigned int backref_map; /* Bitmap of low back refs */
- int external_options; /* External (initial) options */
- int external_flags; /* External flag bits to be set */
- int req_varyopt; /* "After variable item" flag for reqbyte */
- BOOL had_accept; /* (*ACCEPT) encountered */
- int nltype; /* Newline type */
- int nllen; /* Newline string length */
- uschar nl[4]; /* Newline string when fixed length */
-} compile_data;
-
-/* Structure for maintaining a chain of pointers to the currently incomplete
-branches, for testing for left recursion. */
-
-typedef struct branch_chain {
- struct branch_chain *outer;
- uschar *current;
-} branch_chain;
-
-/* Structure for items in a linked list that represents an explicit recursive
-call within the pattern. */
-
-typedef struct recursion_info {
- struct recursion_info *prevrec; /* Previous recursion record (or NULL) */
- int group_num; /* Number of group that was called */
- const uschar *after_call; /* "Return value": points after the call in the expr */
- USPTR save_start; /* Old value of mstart */
- int *offset_save; /* Pointer to start of saved offsets */
- int saved_max; /* Number of saved offsets */
-} recursion_info;
-
-/* Structure for building a chain of data for holding the values of the subject
-pointer at the start of each subpattern, so as to detect when an empty string
-has been matched by a subpattern - to break infinite loops. */
-
-typedef struct eptrblock {
- struct eptrblock *epb_prev;
- USPTR epb_saved_eptr;
-} eptrblock;
-
-
-/* Structure for passing "static" information around between the functions
-doing traditional NFA matching, so that they are thread-safe. */
-
-typedef struct match_data {
- unsigned long int match_call_count; /* As it says */
- unsigned long int match_limit; /* As it says */
- unsigned long int match_limit_recursion; /* As it says */
- int *offset_vector; /* Offset vector */
- int offset_end; /* One past the end */
- int offset_max; /* The maximum usable for return data */
- int nltype; /* Newline type */
- int nllen; /* Newline string length */
- uschar nl[4]; /* Newline string when fixed */
- const uschar *lcc; /* Points to lower casing table */
- const uschar *ctypes; /* Points to table of type maps */
- BOOL offset_overflow; /* Set if too many extractions */
- BOOL notbol; /* NOTBOL flag */
- BOOL noteol; /* NOTEOL flag */
- BOOL utf8; /* UTF8 flag */
- BOOL jscript_compat; /* JAVASCRIPT_COMPAT flag */
- BOOL endonly; /* Dollar not before final \n */
- BOOL notempty; /* Empty string match not wanted */
- BOOL partial; /* PARTIAL flag */
- BOOL hitend; /* Hit the end of the subject at some point */
- BOOL bsr_anycrlf; /* \R is just any CRLF, not full Unicode */
- const uschar *start_code; /* For use when recursing */
- USPTR start_subject; /* Start of the subject string */
- USPTR end_subject; /* End of the subject string */
- USPTR start_match_ptr; /* Start of matched string */
- USPTR end_match_ptr; /* Subject position at end match */
- int end_offset_top; /* Highwater mark at end of match */
- int capture_last; /* Most recent capture number */
- int start_offset; /* The start offset value */
- eptrblock *eptrchain; /* Chain of eptrblocks for tail recursions */
- int eptrn; /* Next free eptrblock */
- recursion_info *recursive; /* Linked list of recursion data */
- void *callout_data; /* To pass back to callouts */
-} match_data;
-
-/* A similar structure is used for the same purpose by the DFA matching
-functions. */
-
-typedef struct dfa_match_data {
- const uschar *start_code; /* Start of the compiled pattern */
- const uschar *start_subject; /* Start of the subject string */
- const uschar *end_subject; /* End of subject string */
- const uschar *tables; /* Character tables */
- int moptions; /* Match options */
- int poptions; /* Pattern options */
- int nltype; /* Newline type */
- int nllen; /* Newline string length */
- uschar nl[4]; /* Newline string when fixed */
- void *callout_data; /* To pass back to callouts */
-} dfa_match_data;
-
-/* Bit definitions for entries in the pcre_ctypes table. */
-
-#define ctype_space 0x01
-#define ctype_letter 0x02
-#define ctype_digit 0x04
-#define ctype_xdigit 0x08
-#define ctype_word 0x10 /* alphanumeric or '_' */
-#define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */
-
-/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set
-of bits for a class map. Some classes are built by combining these tables. */
-
-#define cbit_space 0 /* [:space:] or \s */
-#define cbit_xdigit 32 /* [:xdigit:] */
-#define cbit_digit 64 /* [:digit:] or \d */
-#define cbit_upper 96 /* [:upper:] */
-#define cbit_lower 128 /* [:lower:] */
-#define cbit_word 160 /* [:word:] or \w */
-#define cbit_graph 192 /* [:graph:] */
-#define cbit_print 224 /* [:print:] */
-#define cbit_punct 256 /* [:punct:] */
-#define cbit_cntrl 288 /* [:cntrl:] */
-#define cbit_length 320 /* Length of the cbits table */
-
-/* Offsets of the various tables from the base tables pointer, and
-total length. */
-
-#define lcc_offset 0
-#define fcc_offset 256
-#define cbits_offset 512
-#define ctypes_offset (cbits_offset + cbit_length)
-#define tables_length (ctypes_offset + 256)
-
-/* Layout of the UCP type table that translates property names into types and
-codes. Each entry used to point directly to a name, but to reduce the number of
-relocations in shared libraries, it now has an offset into a single string
-instead. */
-
-typedef struct {
- pcre_uint16 name_offset;
- pcre_uint16 type;
- pcre_uint16 value;
-} ucp_type_table;
-
-
-/* Internal shared data tables. These are tables that are used by more than one
-of the exported public functions. They have to be "external" in the C sense,
-but are not part of the PCRE public API. The data for these tables is in the
-pcre_tables.c module. */
-
-extern const int _pcre_utf8_table1[];
-extern const int _pcre_utf8_table2[];
-extern const int _pcre_utf8_table3[];
-extern const uschar _pcre_utf8_table4[];
-
-extern const int _pcre_utf8_table1_size;
-
-extern const char _pcre_utt_names[];
-extern const ucp_type_table _pcre_utt[];
-extern const int _pcre_utt_size;
-
-extern const uschar _pcre_default_tables[];
-
-extern const uschar _pcre_OP_lengths[];
-
-
-/* Internal shared functions. These are functions that are used by more than
-one of the exported public functions. They have to be "external" in the C
-sense, but are not part of the PCRE public API. */
-
-extern BOOL _pcre_is_newline(const uschar *, int, const uschar *,
- int *, BOOL);
-extern int _pcre_ord2utf8(int, uschar *);
-extern real_pcre *_pcre_try_flipped(const real_pcre *, real_pcre *,
- const pcre_study_data *, pcre_study_data *);
-extern int _pcre_valid_utf8(const uschar *, int);
-extern BOOL _pcre_was_newline(const uschar *, int, const uschar *,
- int *, BOOL);
-extern BOOL _pcre_xclass(int, const uschar *);
-extern unsigned int _pcre_ucp_othercase(unsigned int);
-
-
-extern const int _pcre_ucp_gentype[];
-
-
-/* UCD access macros */
-
-#include "../glib.h"
-
-#define UCD_CHARTYPE(ch) g_unichar_type(ch)
-#define UCD_SCRIPT(ch) g_unichar_get_script(ch)
-#define UCD_CATEGORY(ch) _pcre_ucp_gentype[UCD_CHARTYPE(ch)]
-#define UCD_OTHERCASE(ch) _pcre_ucp_othercase(ch)
-
-#endif
-
-/* End of pcre_internal.h */
diff --git a/glib/pcre/pcre_maketables.c b/glib/pcre/pcre_maketables.c
deleted file mode 100644
index 219973e37..000000000
--- a/glib/pcre/pcre_maketables.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains the external function pcre_maketables(), which builds
-character tables for PCRE in the current locale. The file is compiled on its
-own as part of the PCRE library. However, it is also included in the
-compilation of dftables.c, in which case the macro DFTABLES is defined. */
-
-
-#ifndef DFTABLES
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-# include "pcre_internal.h"
-#endif
-
-
-/*************************************************
-* Create PCRE character tables *
-*************************************************/
-
-/* This function builds a set of character tables for use by PCRE and returns
-a pointer to them. They are build using the ctype functions, and consequently
-their contents will depend upon the current locale setting. When compiled as
-part of the library, the store is obtained via pcre_malloc(), but when compiled
-inside dftables, use malloc().
-
-Arguments: none
-Returns: pointer to the contiguous block of data
-*/
-
-const unsigned char *
-pcre_maketables(void)
-{
-unsigned char *yield, *p;
-int i;
-
-#ifndef DFTABLES
-yield = (unsigned char*)(pcre_malloc)(tables_length);
-#else
-yield = (unsigned char*)malloc(tables_length);
-#endif
-
-if (yield == NULL) return NULL;
-p = yield;
-
-/* First comes the lower casing table */
-
-for (i = 0; i < 256; i++) *p++ = tolower(i);
-
-/* Next the case-flipping table */
-
-for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(i);
-
-/* Then the character class tables. Don't try to be clever and save effort on
-exclusive ones - in some locales things may be different. Note that the table
-for "space" includes everything "isspace" gives, including VT in the default
-locale. This makes it work for the POSIX class [:space:]. Note also that it is
-possible for a character to be alnum or alpha without being lower or upper,
-such as "male and female ordinals" (\xAA and \xBA) in the fr_FR locale (at
-least under Debian Linux's locales as of 12/2005). So we must test for alnum
-specially. */
-
-memset(p, 0, cbit_length);
-for (i = 0; i < 256; i++)
- {
- if (isdigit(i)) p[cbit_digit + i/8] |= 1 << (i&7);
- if (isupper(i)) p[cbit_upper + i/8] |= 1 << (i&7);
- if (islower(i)) p[cbit_lower + i/8] |= 1 << (i&7);
- if (isalnum(i)) p[cbit_word + i/8] |= 1 << (i&7);
- if (i == '_') p[cbit_word + i/8] |= 1 << (i&7);
- if (isspace(i)) p[cbit_space + i/8] |= 1 << (i&7);
- if (isxdigit(i))p[cbit_xdigit + i/8] |= 1 << (i&7);
- if (isgraph(i)) p[cbit_graph + i/8] |= 1 << (i&7);
- if (isprint(i)) p[cbit_print + i/8] |= 1 << (i&7);
- if (ispunct(i)) p[cbit_punct + i/8] |= 1 << (i&7);
- if (iscntrl(i)) p[cbit_cntrl + i/8] |= 1 << (i&7);
- }
-p += cbit_length;
-
-/* Finally, the character type table. In this, we exclude VT from the white
-space chars, because Perl doesn't recognize it as such for \s and for comments
-within regexes. */
-
-for (i = 0; i < 256; i++)
- {
- int x = 0;
- if (i != 0x0b && isspace(i)) x += ctype_space;
- if (isalpha(i)) x += ctype_letter;
- if (isdigit(i)) x += ctype_digit;
- if (isxdigit(i)) x += ctype_xdigit;
- if (isalnum(i) || i == '_') x += ctype_word;
-
- /* Note: strchr includes the terminating zero in the characters it considers.
- In this instance, that is ok because we want binary zero to be flagged as a
- meta-character, which in this sense is any character that terminates a run
- of data characters. */
-
- if (strchr("\\*+?{^.$|()[", i) != 0) x += ctype_meta;
- *p++ = x;
- }
-
-return yield;
-}
-
-/* End of pcre_maketables.c */
diff --git a/glib/pcre/pcre_newline.c b/glib/pcre/pcre_newline.c
deleted file mode 100644
index 58885760e..000000000
--- a/glib/pcre/pcre_newline.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains internal functions for testing newlines when more than
-one kind of newline is to be recognized. When a newline is found, its length is
-returned. In principle, we could implement several newline "types", each
-referring to a different set of newline characters. At present, PCRE supports
-only NLTYPE_FIXED, which gets handled without these functions, NLTYPE_ANYCRLF,
-and NLTYPE_ANY. The full list of Unicode newline characters is taken from
-http://unicode.org/unicode/reports/tr18/. */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-
-/*************************************************
-* Check for newline at given position *
-*************************************************/
-
-/* It is guaranteed that the initial value of ptr is less than the end of the
-string that is being processed.
-
-Arguments:
- ptr pointer to possible newline
- type the newline type
- endptr pointer to the end of the string
- lenptr where to return the length
- utf8 TRUE if in utf8 mode
-
-Returns: TRUE or FALSE
-*/
-
-BOOL
-_pcre_is_newline(const uschar *ptr, int type, const uschar *endptr,
- int *lenptr, BOOL utf8)
-{
-int c;
-if (utf8) { GETCHAR(c, ptr); } else c = *ptr;
-
-if (type == NLTYPE_ANYCRLF) switch(c)
- {
- case 0x000a: *lenptr = 1; return TRUE; /* LF */
- case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1;
- return TRUE; /* CR */
- default: return FALSE;
- }
-
-/* NLTYPE_ANY */
-
-else switch(c)
- {
- case 0x000a: /* LF */
- case 0x000b: /* VT */
- case 0x000c: *lenptr = 1; return TRUE; /* FF */
- case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1;
- return TRUE; /* CR */
- case 0x0085: *lenptr = utf8? 2 : 1; return TRUE; /* NEL */
- case 0x2028: /* LS */
- case 0x2029: *lenptr = 3; return TRUE; /* PS */
- default: return FALSE;
- }
-}
-
-
-
-/*************************************************
-* Check for newline at previous position *
-*************************************************/
-
-/* It is guaranteed that the initial value of ptr is greater than the start of
-the string that is being processed.
-
-Arguments:
- ptr pointer to possible newline
- type the newline type
- startptr pointer to the start of the string
- lenptr where to return the length
- utf8 TRUE if in utf8 mode
-
-Returns: TRUE or FALSE
-*/
-
-BOOL
-_pcre_was_newline(const uschar *ptr, int type, const uschar *startptr,
- int *lenptr, BOOL utf8)
-{
-int c;
-ptr--;
-#ifdef SUPPORT_UTF8
-if (utf8)
- {
- BACKCHAR(ptr);
- GETCHAR(c, ptr);
- }
-else c = *ptr;
-#else /* no UTF-8 support */
-c = *ptr;
-#endif /* SUPPORT_UTF8 */
-
-if (type == NLTYPE_ANYCRLF) switch(c)
- {
- case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1;
- return TRUE; /* LF */
- case 0x000d: *lenptr = 1; return TRUE; /* CR */
- default: return FALSE;
- }
-
-else switch(c)
- {
- case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1;
- return TRUE; /* LF */
- case 0x000b: /* VT */
- case 0x000c: /* FF */
- case 0x000d: *lenptr = 1; return TRUE; /* CR */
- case 0x0085: *lenptr = utf8? 2 : 1; return TRUE; /* NEL */
- case 0x2028: /* LS */
- case 0x2029: *lenptr = 3; return TRUE; /* PS */
- default: return FALSE;
- }
-}
-
-/* End of pcre_newline.c */
diff --git a/glib/pcre/pcre_ord2utf8.c b/glib/pcre/pcre_ord2utf8.c
deleted file mode 100644
index 6f4eb9ebe..000000000
--- a/glib/pcre/pcre_ord2utf8.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This file contains a private PCRE function that converts an ordinal
-character value into a UTF8 string. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-/*************************************************
-* Convert character value to UTF-8 *
-*************************************************/
-
-/* This function takes an integer value in the range 0 - 0x7fffffff
-and encodes it as a UTF-8 character in 0 to 6 bytes.
-
-Arguments:
- cvalue the character value
- buffer pointer to buffer for result - at least 6 bytes long
-
-Returns: number of characters placed in the buffer
-*/
-
-int
-_pcre_ord2utf8(int cvalue, uschar *buffer)
-{
-#ifdef SUPPORT_UTF8
-register int i, j;
-for (i = 0; i < _pcre_utf8_table1_size; i++)
- if (cvalue <= _pcre_utf8_table1[i]) break;
-buffer += i;
-for (j = i; j > 0; j--)
- {
- *buffer-- = 0x80 | (cvalue & 0x3f);
- cvalue >>= 6;
- }
-*buffer = _pcre_utf8_table2[i] | cvalue;
-return i + 1;
-#else
-(void)(cvalue); /* Keep compiler happy; this function won't ever be */
-(void)(buffer); /* called when SUPPORT_UTF8 is not defined. */
-return 0;
-#endif
-}
-
-/* End of pcre_ord2utf8.c */
diff --git a/glib/pcre/pcre_refcount.c b/glib/pcre/pcre_refcount.c
deleted file mode 100644
index 92e4b8505..000000000
--- a/glib/pcre/pcre_refcount.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains the external function pcre_refcount(), which is an
-auxiliary function that can be used to maintain a reference count in a compiled
-pattern data block. This might be helpful in applications where the block is
-shared by different users. */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-/*************************************************
-* Maintain reference count *
-*************************************************/
-
-/* The reference count is a 16-bit field, initialized to zero. It is not
-possible to transfer a non-zero count from one host to a different host that
-has a different byte order - though I can't see why anyone in their right mind
-would ever want to do that!
-
-Arguments:
- argument_re points to compiled code
- adjust value to add to the count
-
-Returns: the (possibly updated) count value (a non-negative number), or
- a negative error number
-*/
-
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_refcount(pcre *argument_re, int adjust)
-{
-real_pcre *re = (real_pcre *)argument_re;
-if (re == NULL) return PCRE_ERROR_NULL;
-re->ref_count = (-adjust > re->ref_count)? 0 :
- (adjust + re->ref_count > 65535)? 65535 :
- re->ref_count + adjust;
-return re->ref_count;
-}
-
-/* End of pcre_refcount.c */
diff --git a/glib/pcre/pcre_study.c b/glib/pcre/pcre_study.c
deleted file mode 100644
index 778851d24..000000000
--- a/glib/pcre/pcre_study.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains the external function pcre_study(), along with local
-supporting functions. */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-/* Returns from set_start_bits() */
-
-enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE };
-
-
-/*************************************************
-* Set a bit and maybe its alternate case *
-*************************************************/
-
-/* Given a character, set its bit in the table, and also the bit for the other
-version of a letter if we are caseless.
-
-Arguments:
- start_bits points to the bit map
- c is the character
- caseless the caseless flag
- cd the block with char table pointers
-
-Returns: nothing
-*/
-
-static void
-set_bit(uschar *start_bits, unsigned int c, BOOL caseless, compile_data *cd)
-{
-start_bits[c/8] |= (1 << (c&7));
-if (caseless && (cd->ctypes[c] & ctype_letter) != 0)
- start_bits[cd->fcc[c]/8] |= (1 << (cd->fcc[c]&7));
-}
-
-
-
-/*************************************************
-* Create bitmap of starting bytes *
-*************************************************/
-
-/* This function scans a compiled unanchored expression recursively and
-attempts to build a bitmap of the set of possible starting bytes. As time goes
-by, we may be able to get more clever at doing this. The SSB_CONTINUE return is
-useful for parenthesized groups in patterns such as (a*)b where the group
-provides some optional starting bytes but scanning must continue at the outer
-level to find at least one mandatory byte. At the outermost level, this
-function fails unless the result is SSB_DONE.
-
-Arguments:
- code points to an expression
- start_bits points to a 32-byte table, initialized to 0
- caseless the current state of the caseless flag
- utf8 TRUE if in UTF-8 mode
- cd the block with char table pointers
-
-Returns: SSB_FAIL => Failed to find any starting bytes
- SSB_DONE => Found mandatory starting bytes
- SSB_CONTINUE => Found optional starting bytes
-*/
-
-static int
-set_start_bits(const uschar *code, uschar *start_bits, BOOL caseless,
- BOOL utf8, compile_data *cd)
-{
-register int c;
-int yield = SSB_DONE;
-
-#if 0
-/* ========================================================================= */
-/* The following comment and code was inserted in January 1999. In May 2006,
-when it was observed to cause compiler warnings about unused values, I took it
-out again. If anybody is still using OS/2, they will have to put it back
-manually. */
-
-/* This next statement and the later reference to dummy are here in order to
-trick the optimizer of the IBM C compiler for OS/2 into generating correct
-code. Apparently IBM isn't going to fix the problem, and we would rather not
-disable optimization (in this module it actually makes a big difference, and
-the pcre module can use all the optimization it can get). */
-
-volatile int dummy;
-/* ========================================================================= */
-#endif
-
-do
- {
- const uschar *tcode = code + (((int)*code == OP_CBRA)? 3:1) + LINK_SIZE;
- BOOL try_next = TRUE;
-
- while (try_next) /* Loop for items in this branch */
- {
- int rc;
- switch(*tcode)
- {
- /* Fail if we reach something we don't understand */
-
- default:
- return SSB_FAIL;
-
- /* If we hit a bracket or a positive lookahead assertion, recurse to set
- bits from within the subpattern. If it can't find anything, we have to
- give up. If it finds some mandatory character(s), we are done for this
- branch. Otherwise, carry on scanning after the subpattern. */
-
- case OP_BRA:
- case OP_SBRA:
- case OP_CBRA:
- case OP_SCBRA:
- case OP_ONCE:
- case OP_ASSERT:
- rc = set_start_bits(tcode, start_bits, caseless, utf8, cd);
- if (rc == SSB_FAIL) return SSB_FAIL;
- if (rc == SSB_DONE) try_next = FALSE; else
- {
- do tcode += GET(tcode, 1); while (*tcode == OP_ALT);
- tcode += 1 + LINK_SIZE;
- }
- break;
-
- /* If we hit ALT or KET, it means we haven't found anything mandatory in
- this branch, though we might have found something optional. For ALT, we
- continue with the next alternative, but we have to arrange that the final
- result from subpattern is SSB_CONTINUE rather than SSB_DONE. For KET,
- return SSB_CONTINUE: if this is the top level, that indicates failure,
- but after a nested subpattern, it causes scanning to continue. */
-
- case OP_ALT:
- yield = SSB_CONTINUE;
- try_next = FALSE;
- break;
-
- case OP_KET:
- case OP_KETRMAX:
- case OP_KETRMIN:
- return SSB_CONTINUE;
-
- /* Skip over callout */
-
- case OP_CALLOUT:
- tcode += 2 + 2*LINK_SIZE;
- break;
-
- /* Skip over lookbehind and negative lookahead assertions */
-
- case OP_ASSERT_NOT:
- case OP_ASSERTBACK:
- case OP_ASSERTBACK_NOT:
- do tcode += GET(tcode, 1); while (*tcode == OP_ALT);
- tcode += 1 + LINK_SIZE;
- break;
-
- /* Skip over an option setting, changing the caseless flag */
-
- case OP_OPT:
- caseless = (tcode[1] & PCRE_CASELESS) != 0;
- tcode += 2;
- break;
-
- /* BRAZERO does the bracket, but carries on. */
-
- case OP_BRAZERO:
- case OP_BRAMINZERO:
- if (set_start_bits(++tcode, start_bits, caseless, utf8, cd) == SSB_FAIL)
- return SSB_FAIL;
-/* =========================================================================
- See the comment at the head of this function concerning the next line,
- which was an old fudge for the benefit of OS/2.
- dummy = 1;
- ========================================================================= */
- do tcode += GET(tcode,1); while (*tcode == OP_ALT);
- tcode += 1 + LINK_SIZE;
- break;
-
- /* SKIPZERO skips the bracket. */
-
- case OP_SKIPZERO:
- tcode++;
- do tcode += GET(tcode,1); while (*tcode == OP_ALT);
- tcode += 1 + LINK_SIZE;
- break;
-
- /* Single-char * or ? sets the bit and tries the next item */
-
- case OP_STAR:
- case OP_MINSTAR:
- case OP_POSSTAR:
- case OP_QUERY:
- case OP_MINQUERY:
- case OP_POSQUERY:
- set_bit(start_bits, tcode[1], caseless, cd);
- tcode += 2;
-#ifdef SUPPORT_UTF8
- if (utf8 && tcode[-1] >= 0xc0)
- tcode += _pcre_utf8_table4[tcode[-1] & 0x3f];
-#endif
- break;
-
- /* Single-char upto sets the bit and tries the next */
-
- case OP_UPTO:
- case OP_MINUPTO:
- case OP_POSUPTO:
- set_bit(start_bits, tcode[3], caseless, cd);
- tcode += 4;
-#ifdef SUPPORT_UTF8
- if (utf8 && tcode[-1] >= 0xc0)
- tcode += _pcre_utf8_table4[tcode[-1] & 0x3f];
-#endif
- break;
-
- /* At least one single char sets the bit and stops */
-
- case OP_EXACT: /* Fall through */
- tcode += 2;
-
- case OP_CHAR:
- case OP_CHARNC:
- case OP_PLUS:
- case OP_MINPLUS:
- case OP_POSPLUS:
- set_bit(start_bits, tcode[1], caseless, cd);
- try_next = FALSE;
- break;
-
- /* Single character type sets the bits and stops */
-
- case OP_NOT_DIGIT:
- for (c = 0; c < 32; c++)
- start_bits[c] |= ~cd->cbits[c+cbit_digit];
- try_next = FALSE;
- break;
-
- case OP_DIGIT:
- for (c = 0; c < 32; c++)
- start_bits[c] |= cd->cbits[c+cbit_digit];
- try_next = FALSE;
- break;
-
- /* The cbit_space table has vertical tab as whitespace; we have to
- discard it. */
-
- case OP_NOT_WHITESPACE:
- for (c = 0; c < 32; c++)
- {
- int d = cd->cbits[c+cbit_space];
- if (c == 1) d &= ~0x08;
- start_bits[c] |= ~d;
- }
- try_next = FALSE;
- break;
-
- /* The cbit_space table has vertical tab as whitespace; we have to
- discard it. */
-
- case OP_WHITESPACE:
- for (c = 0; c < 32; c++)
- {
- int d = cd->cbits[c+cbit_space];
- if (c == 1) d &= ~0x08;
- start_bits[c] |= d;
- }
- try_next = FALSE;
- break;
-
- case OP_NOT_WORDCHAR:
- for (c = 0; c < 32; c++)
- start_bits[c] |= ~cd->cbits[c+cbit_word];
- try_next = FALSE;
- break;
-
- case OP_WORDCHAR:
- for (c = 0; c < 32; c++)
- start_bits[c] |= cd->cbits[c+cbit_word];
- try_next = FALSE;
- break;
-
- /* One or more character type fudges the pointer and restarts, knowing
- it will hit a single character type and stop there. */
-
- case OP_TYPEPLUS:
- case OP_TYPEMINPLUS:
- tcode++;
- break;
-
- case OP_TYPEEXACT:
- tcode += 3;
- break;
-
- /* Zero or more repeats of character types set the bits and then
- try again. */
-
- case OP_TYPEUPTO:
- case OP_TYPEMINUPTO:
- case OP_TYPEPOSUPTO:
- tcode += 2; /* Fall through */
-
- case OP_TYPESTAR:
- case OP_TYPEMINSTAR:
- case OP_TYPEPOSSTAR:
- case OP_TYPEQUERY:
- case OP_TYPEMINQUERY:
- case OP_TYPEPOSQUERY:
- switch(tcode[1])
- {
- case OP_ANY:
- case OP_ALLANY:
- return SSB_FAIL;
-
- case OP_NOT_DIGIT:
- for (c = 0; c < 32; c++)
- start_bits[c] |= ~cd->cbits[c+cbit_digit];
- break;
-
- case OP_DIGIT:
- for (c = 0; c < 32; c++)
- start_bits[c] |= cd->cbits[c+cbit_digit];
- break;
-
- /* The cbit_space table has vertical tab as whitespace; we have to
- discard it. */
-
- case OP_NOT_WHITESPACE:
- for (c = 0; c < 32; c++)
- {
- int d = cd->cbits[c+cbit_space];
- if (c == 1) d &= ~0x08;
- start_bits[c] |= ~d;
- }
- break;
-
- /* The cbit_space table has vertical tab as whitespace; we have to
- discard it. */
-
- case OP_WHITESPACE:
- for (c = 0; c < 32; c++)
- {
- int d = cd->cbits[c+cbit_space];
- if (c == 1) d &= ~0x08;
- start_bits[c] |= d;
- }
- break;
-
- case OP_NOT_WORDCHAR:
- for (c = 0; c < 32; c++)
- start_bits[c] |= ~cd->cbits[c+cbit_word];
- break;
-
- case OP_WORDCHAR:
- for (c = 0; c < 32; c++)
- start_bits[c] |= cd->cbits[c+cbit_word];
- break;
- }
-
- tcode += 2;
- break;
-
- /* Character class where all the information is in a bit map: set the
- bits and either carry on or not, according to the repeat count. If it was
- a negative class, and we are operating with UTF-8 characters, any byte
- with a value >= 0xc4 is a potentially valid starter because it starts a
- character with a value > 255. */
-
- case OP_NCLASS:
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- start_bits[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */
- memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */
- }
-#endif
- /* Fall through */
-
- case OP_CLASS:
- {
- tcode++;
-
- /* In UTF-8 mode, the bits in a bit map correspond to character
- values, not to byte values. However, the bit map we are constructing is
- for byte values. So we have to do a conversion for characters whose
- value is > 127. In fact, there are only two possible starting bytes for
- characters in the range 128 - 255. */
-
-#ifdef SUPPORT_UTF8
- if (utf8)
- {
- for (c = 0; c < 16; c++) start_bits[c] |= tcode[c];
- for (c = 128; c < 256; c++)
- {
- if ((tcode[c/8] && (1 << (c&7))) != 0)
- {
- int d = (c >> 6) | 0xc0; /* Set bit for this starter */
- start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */
- c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */
- }
- }
- }
-
- /* In non-UTF-8 mode, the two bit maps are completely compatible. */
-
- else
-#endif
- {
- for (c = 0; c < 32; c++) start_bits[c] |= tcode[c];
- }
-
- /* Advance past the bit map, and act on what follows */
-
- tcode += 32;
- switch (*tcode)
- {
- case OP_CRSTAR:
- case OP_CRMINSTAR:
- case OP_CRQUERY:
- case OP_CRMINQUERY:
- tcode++;
- break;
-
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- if (((tcode[1] << 8) + tcode[2]) == 0) tcode += 5;
- else try_next = FALSE;
- break;
-
- default:
- try_next = FALSE;
- break;
- }
- }
- break; /* End of bitmap class handling */
-
- } /* End of switch */
- } /* End of try_next loop */
-
- code += GET(code, 1); /* Advance to next branch */
- }
-while (*code == OP_ALT);
-return yield;
-}
-
-
-
-/*************************************************
-* Study a compiled expression *
-*************************************************/
-
-/* This function is handed a compiled expression that it must study to produce
-information that will speed up the matching. It returns a pcre_extra block
-which then gets handed back to pcre_exec().
-
-Arguments:
- re points to the compiled expression
- options contains option bits
- errorptr points to where to place error messages;
- set NULL unless error
-
-Returns: pointer to a pcre_extra block, with study_data filled in and the
- appropriate flag set;
- NULL on error or if no optimization possible
-*/
-
-PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION
-pcre_study(const pcre *external_re, int options, const char **errorptr)
-{
-uschar start_bits[32];
-pcre_extra *extra;
-pcre_study_data *study;
-const uschar *tables;
-uschar *code;
-compile_data compile_block;
-const real_pcre *re = (const real_pcre *)external_re;
-
-*errorptr = NULL;
-
-if (re == NULL || re->magic_number != MAGIC_NUMBER)
- {
- *errorptr = "argument is not a compiled regular expression";
- return NULL;
- }
-
-if ((options & ~PUBLIC_STUDY_OPTIONS) != 0)
- {
- *errorptr = "unknown or incorrect option bit(s) set";
- return NULL;
- }
-
-code = (uschar *)re + re->name_table_offset +
- (re->name_count * re->name_entry_size);
-
-/* For an anchored pattern, or an unanchored pattern that has a first char, or
-a multiline pattern that matches only at "line starts", no further processing
-at present. */
-
-if ((re->options & PCRE_ANCHORED) != 0 ||
- (re->flags & (PCRE_FIRSTSET|PCRE_STARTLINE)) != 0)
- return NULL;
-
-/* Set the character tables in the block that is passed around */
-
-tables = re->tables;
-if (tables == NULL)
- (void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
- (void *)(&tables));
-
-compile_block.lcc = tables + lcc_offset;
-compile_block.fcc = tables + fcc_offset;
-compile_block.cbits = tables + cbits_offset;
-compile_block.ctypes = tables + ctypes_offset;
-
-/* See if we can find a fixed set of initial characters for the pattern. */
-
-memset(start_bits, 0, 32 * sizeof(uschar));
-if (set_start_bits(code, start_bits, (re->options & PCRE_CASELESS) != 0,
- (re->options & PCRE_UTF8) != 0, &compile_block) != SSB_DONE) return NULL;
-
-/* Get a pcre_extra block and a pcre_study_data block. The study data is put in
-the latter, which is pointed to by the former, which may also get additional
-data set later by the calling program. At the moment, the size of
-pcre_study_data is fixed. We nevertheless save it in a field for returning via
-the pcre_fullinfo() function so that if it becomes variable in the future, we
-don't have to change that code. */
-
-extra = (pcre_extra *)(pcre_malloc)
- (sizeof(pcre_extra) + sizeof(pcre_study_data));
-
-if (extra == NULL)
- {
- *errorptr = "failed to get memory";
- return NULL;
- }
-
-study = (pcre_study_data *)((char *)extra + sizeof(pcre_extra));
-extra->flags = PCRE_EXTRA_STUDY_DATA;
-extra->study_data = study;
-
-study->size = sizeof(pcre_study_data);
-study->options = PCRE_STUDY_MAPPED;
-memcpy(study->start_bits, start_bits, sizeof(start_bits));
-
-return extra;
-}
-
-/* End of pcre_study.c */
diff --git a/glib/pcre/pcre_tables.c b/glib/pcre/pcre_tables.c
deleted file mode 100644
index 160bc5d53..000000000
--- a/glib/pcre/pcre_tables.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains some fixed tables that are used by more than one of the
-PCRE code modules. The tables are also #included by the pcretest program, which
-uses macros to change their names from _pcre_xxx to xxxx, thereby avoiding name
-clashes with the library. */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that
-the definition is next to the definition of the opcodes in pcre_internal.h. */
-
-const uschar _pcre_OP_lengths[] = { OP_LENGTHS };
-
-
-
-/*************************************************
-* Tables for UTF-8 support *
-*************************************************/
-
-/* These are the breakpoints for different numbers of bytes in a UTF-8
-character. */
-
-#ifdef SUPPORT_UTF8
-
-const int _pcre_utf8_table1[] =
- { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
-
-const int _pcre_utf8_table1_size = sizeof(_pcre_utf8_table1)/sizeof(int);
-
-/* These are the indicator bits and the mask for the data bits to set in the
-first byte of a character, indexed by the number of additional bytes. */
-
-const int _pcre_utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
-const int _pcre_utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
-
-/* Table of the number of extra bytes, indexed by the first byte masked with
-0x3f. The highest number for a valid UTF-8 first byte is in fact 0x3d. */
-
-const uschar _pcre_utf8_table4[] = {
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
-
-/* Table to translate from particular type value to the general value. */
-
-const int _pcre_ucp_gentype[] = {
- ucp_C, ucp_C, ucp_C, ucp_C, ucp_C, /* Cc, Cf, Cn, Co, Cs */
- ucp_L, ucp_L, ucp_L, ucp_L, ucp_L, /* Ll, Lu, Lm, Lo, Lt */
- ucp_M, ucp_M, ucp_M, /* Mc, Me, Mn */
- ucp_N, ucp_N, ucp_N, /* Nd, Nl, No */
- ucp_P, ucp_P, ucp_P, ucp_P, ucp_P, /* Pc, Pd, Pe, Pf, Pi */
- ucp_P, ucp_P, /* Ps, Po */
- ucp_S, ucp_S, ucp_S, ucp_S, /* Sc, Sk, Sm, So */
- ucp_Z, ucp_Z, ucp_Z /* Zl, Zp, Zs */
-};
-
-/* The pcre_utt[] table below translates Unicode property names into type and
-code values. It is searched by binary chop, so must be in collating sequence of
-name. Originally, the table contained pointers to the name strings in the first
-field of each entry. However, that leads to a large number of relocations when
-a shared library is dynamically loaded. A significant reduction is made by
-putting all the names into a single, large string and then using offsets in the
-table itself. Maintenance is more error-prone, but frequent changes to this
-data are unlikely.
-
-July 2008: There is now a script called maint/GenerateUtt.py which can be used
-to generate this data instead of maintaining it entirely by hand. */
-
-const char _pcre_utt_names[] =
- "Any\0"
- "Arabic\0"
- "Armenian\0"
- "Balinese\0"
- "Bengali\0"
- "Bopomofo\0"
- "Braille\0"
- "Buginese\0"
- "Buhid\0"
- "C\0"
- "Canadian_Aboriginal\0"
- "Carian\0"
- "Cc\0"
- "Cf\0"
- "Cham\0"
- "Cherokee\0"
- "Cn\0"
- "Co\0"
- "Common\0"
- "Coptic\0"
- "Cs\0"
- "Cuneiform\0"
- "Cypriot\0"
- "Cyrillic\0"
- "Deseret\0"
- "Devanagari\0"
- "Ethiopic\0"
- "Georgian\0"
- "Glagolitic\0"
- "Gothic\0"
- "Greek\0"
- "Gujarati\0"
- "Gurmukhi\0"
- "Han\0"
- "Hangul\0"
- "Hanunoo\0"
- "Hebrew\0"
- "Hiragana\0"
- "Inherited\0"
- "Kannada\0"
- "Katakana\0"
- "Kayah_Li\0"
- "Kharoshthi\0"
- "Khmer\0"
- "L\0"
- "L&\0"
- "Lao\0"
- "Latin\0"
- "Lepcha\0"
- "Limbu\0"
- "Linear_B\0"
- "Ll\0"
- "Lm\0"
- "Lo\0"
- "Lt\0"
- "Lu\0"
- "Lycian\0"
- "Lydian\0"
- "M\0"
- "Malayalam\0"
- "Mc\0"
- "Me\0"
- "Mn\0"
- "Mongolian\0"
- "Myanmar\0"
- "N\0"
- "Nd\0"
- "New_Tai_Lue\0"
- "Nko\0"
- "Nl\0"
- "No\0"
- "Ogham\0"
- "Ol_Chiki\0"
- "Old_Italic\0"
- "Old_Persian\0"
- "Oriya\0"
- "Osmanya\0"
- "P\0"
- "Pc\0"
- "Pd\0"
- "Pe\0"
- "Pf\0"
- "Phags_Pa\0"
- "Phoenician\0"
- "Pi\0"
- "Po\0"
- "Ps\0"
- "Rejang\0"
- "Runic\0"
- "S\0"
- "Saurashtra\0"
- "Sc\0"
- "Shavian\0"
- "Sinhala\0"
- "Sk\0"
- "Sm\0"
- "So\0"
- "Sundanese\0"
- "Syloti_Nagri\0"
- "Syriac\0"
- "Tagalog\0"
- "Tagbanwa\0"
- "Tai_Le\0"
- "Tamil\0"
- "Telugu\0"
- "Thaana\0"
- "Thai\0"
- "Tibetan\0"
- "Tifinagh\0"
- "Ugaritic\0"
- "Vai\0"
- "Yi\0"
- "Z\0"
- "Zl\0"
- "Zp\0"
- "Zs\0";
-
-const ucp_type_table _pcre_utt[] = {
- { 0, PT_ANY, 0 },
- { 4, PT_SC, ucp_Arabic },
- { 11, PT_SC, ucp_Armenian },
- { 20, PT_SC, ucp_Balinese },
- { 29, PT_SC, ucp_Bengali },
- { 37, PT_SC, ucp_Bopomofo },
- { 46, PT_SC, ucp_Braille },
- { 54, PT_SC, ucp_Buginese },
- { 63, PT_SC, ucp_Buhid },
- { 69, PT_GC, ucp_C },
- { 71, PT_SC, ucp_Canadian_Aboriginal },
- { 91, PT_SC, ucp_Carian },
- { 98, PT_PC, ucp_Cc },
- { 101, PT_PC, ucp_Cf },
- { 104, PT_SC, ucp_Cham },
- { 109, PT_SC, ucp_Cherokee },
- { 118, PT_PC, ucp_Cn },
- { 121, PT_PC, ucp_Co },
- { 124, PT_SC, ucp_Common },
- { 131, PT_SC, ucp_Coptic },
- { 138, PT_PC, ucp_Cs },
- { 141, PT_SC, ucp_Cuneiform },
- { 151, PT_SC, ucp_Cypriot },
- { 159, PT_SC, ucp_Cyrillic },
- { 168, PT_SC, ucp_Deseret },
- { 176, PT_SC, ucp_Devanagari },
- { 187, PT_SC, ucp_Ethiopic },
- { 196, PT_SC, ucp_Georgian },
- { 205, PT_SC, ucp_Glagolitic },
- { 216, PT_SC, ucp_Gothic },
- { 223, PT_SC, ucp_Greek },
- { 229, PT_SC, ucp_Gujarati },
- { 238, PT_SC, ucp_Gurmukhi },
- { 247, PT_SC, ucp_Han },
- { 251, PT_SC, ucp_Hangul },
- { 258, PT_SC, ucp_Hanunoo },
- { 266, PT_SC, ucp_Hebrew },
- { 273, PT_SC, ucp_Hiragana },
- { 282, PT_SC, ucp_Inherited },
- { 292, PT_SC, ucp_Kannada },
- { 300, PT_SC, ucp_Katakana },
- { 309, PT_SC, ucp_Kayah_Li },
- { 318, PT_SC, ucp_Kharoshthi },
- { 329, PT_SC, ucp_Khmer },
- { 335, PT_GC, ucp_L },
- { 337, PT_LAMP, 0 },
- { 340, PT_SC, ucp_Lao },
- { 344, PT_SC, ucp_Latin },
- { 350, PT_SC, ucp_Lepcha },
- { 357, PT_SC, ucp_Limbu },
- { 363, PT_SC, ucp_Linear_B },
- { 372, PT_PC, ucp_Ll },
- { 375, PT_PC, ucp_Lm },
- { 378, PT_PC, ucp_Lo },
- { 381, PT_PC, ucp_Lt },
- { 384, PT_PC, ucp_Lu },
- { 387, PT_SC, ucp_Lycian },
- { 394, PT_SC, ucp_Lydian },
- { 401, PT_GC, ucp_M },
- { 403, PT_SC, ucp_Malayalam },
- { 413, PT_PC, ucp_Mc },
- { 416, PT_PC, ucp_Me },
- { 419, PT_PC, ucp_Mn },
- { 422, PT_SC, ucp_Mongolian },
- { 432, PT_SC, ucp_Myanmar },
- { 440, PT_GC, ucp_N },
- { 442, PT_PC, ucp_Nd },
- { 445, PT_SC, ucp_New_Tai_Lue },
- { 457, PT_SC, ucp_Nko },
- { 461, PT_PC, ucp_Nl },
- { 464, PT_PC, ucp_No },
- { 467, PT_SC, ucp_Ogham },
- { 473, PT_SC, ucp_Ol_Chiki },
- { 482, PT_SC, ucp_Old_Italic },
- { 493, PT_SC, ucp_Old_Persian },
- { 505, PT_SC, ucp_Oriya },
- { 511, PT_SC, ucp_Osmanya },
- { 519, PT_GC, ucp_P },
- { 521, PT_PC, ucp_Pc },
- { 524, PT_PC, ucp_Pd },
- { 527, PT_PC, ucp_Pe },
- { 530, PT_PC, ucp_Pf },
- { 533, PT_SC, ucp_Phags_Pa },
- { 542, PT_SC, ucp_Phoenician },
- { 553, PT_PC, ucp_Pi },
- { 556, PT_PC, ucp_Po },
- { 559, PT_PC, ucp_Ps },
- { 562, PT_SC, ucp_Rejang },
- { 569, PT_SC, ucp_Runic },
- { 575, PT_GC, ucp_S },
- { 577, PT_SC, ucp_Saurashtra },
- { 588, PT_PC, ucp_Sc },
- { 591, PT_SC, ucp_Shavian },
- { 599, PT_SC, ucp_Sinhala },
- { 607, PT_PC, ucp_Sk },
- { 610, PT_PC, ucp_Sm },
- { 613, PT_PC, ucp_So },
- { 616, PT_SC, ucp_Sundanese },
- { 626, PT_SC, ucp_Syloti_Nagri },
- { 639, PT_SC, ucp_Syriac },
- { 646, PT_SC, ucp_Tagalog },
- { 654, PT_SC, ucp_Tagbanwa },
- { 663, PT_SC, ucp_Tai_Le },
- { 670, PT_SC, ucp_Tamil },
- { 676, PT_SC, ucp_Telugu },
- { 683, PT_SC, ucp_Thaana },
- { 690, PT_SC, ucp_Thai },
- { 695, PT_SC, ucp_Tibetan },
- { 703, PT_SC, ucp_Tifinagh },
- { 712, PT_SC, ucp_Ugaritic },
- { 721, PT_SC, ucp_Vai },
- { 725, PT_SC, ucp_Yi },
- { 728, PT_GC, ucp_Z },
- { 730, PT_PC, ucp_Zl },
- { 733, PT_PC, ucp_Zp },
- { 736, PT_PC, ucp_Zs }
-};
-
-const int _pcre_utt_size = sizeof(_pcre_utt)/sizeof(ucp_type_table);
-
-#endif /* SUPPORT_UTF8 */
-
-/* End of pcre_tables.c */
diff --git a/glib/pcre/pcre_try_flipped.c b/glib/pcre/pcre_try_flipped.c
deleted file mode 100644
index 0d2f3a2d3..000000000
--- a/glib/pcre/pcre_try_flipped.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains an internal function that tests a compiled pattern to
-see if it was compiled with the opposite endianness. If so, it uses an
-auxiliary local function to flip the appropriate bytes. */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-/*************************************************
-* Flip bytes in an integer *
-*************************************************/
-
-/* This function is called when the magic number in a regex doesn't match, in
-order to flip its bytes to see if we are dealing with a pattern that was
-compiled on a host of different endianness. If so, this function is used to
-flip other byte values.
-
-Arguments:
- value the number to flip
- n the number of bytes to flip (assumed to be 2 or 4)
-
-Returns: the flipped value
-*/
-
-static unsigned long int
-byteflip(unsigned long int value, int n)
-{
-if (n == 2) return ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8);
-return ((value & 0x000000ff) << 24) |
- ((value & 0x0000ff00) << 8) |
- ((value & 0x00ff0000) >> 8) |
- ((value & 0xff000000) >> 24);
-}
-
-
-
-/*************************************************
-* Test for a byte-flipped compiled regex *
-*************************************************/
-
-/* This function is called from pcre_exec(), pcre_dfa_exec(), and also from
-pcre_fullinfo(). Its job is to test whether the regex is byte-flipped - that
-is, it was compiled on a system of opposite endianness. The function is called
-only when the native MAGIC_NUMBER test fails. If the regex is indeed flipped,
-we flip all the relevant values into a different data block, and return it.
-
-Arguments:
- re points to the regex
- study points to study data, or NULL
- internal_re points to a new regex block
- internal_study points to a new study block
-
-Returns: the new block if is is indeed a byte-flipped regex
- NULL if it is not
-*/
-
-real_pcre *
-_pcre_try_flipped(const real_pcre *re, real_pcre *internal_re,
- const pcre_study_data *study, pcre_study_data *internal_study)
-{
-if (byteflip(re->magic_number, sizeof(re->magic_number)) != MAGIC_NUMBER)
- return NULL;
-
-*internal_re = *re; /* To copy other fields */
-internal_re->size = byteflip(re->size, sizeof(re->size));
-internal_re->options = byteflip(re->options, sizeof(re->options));
-internal_re->flags = (pcre_uint16)byteflip(re->flags, sizeof(re->flags));
-internal_re->top_bracket =
- (pcre_uint16)byteflip(re->top_bracket, sizeof(re->top_bracket));
-internal_re->top_backref =
- (pcre_uint16)byteflip(re->top_backref, sizeof(re->top_backref));
-internal_re->first_byte =
- (pcre_uint16)byteflip(re->first_byte, sizeof(re->first_byte));
-internal_re->req_byte =
- (pcre_uint16)byteflip(re->req_byte, sizeof(re->req_byte));
-internal_re->name_table_offset =
- (pcre_uint16)byteflip(re->name_table_offset, sizeof(re->name_table_offset));
-internal_re->name_entry_size =
- (pcre_uint16)byteflip(re->name_entry_size, sizeof(re->name_entry_size));
-internal_re->name_count =
- (pcre_uint16)byteflip(re->name_count, sizeof(re->name_count));
-
-if (study != NULL)
- {
- *internal_study = *study; /* To copy other fields */
- internal_study->size = byteflip(study->size, sizeof(study->size));
- internal_study->options = byteflip(study->options, sizeof(study->options));
- }
-
-return internal_re;
-}
-
-/* End of pcre_tryflipped.c */
diff --git a/glib/pcre/pcre_ucp_searchfuncs.c b/glib/pcre/pcre_ucp_searchfuncs.c
deleted file mode 100644
index 9060fbccd..000000000
--- a/glib/pcre/pcre_ucp_searchfuncs.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2006 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-/* This file has been modified to use glib instead of the internal table
- * in ucptable.c -- Marco Barisione */
-
-/* This module contains code for searching the table of Unicode character
-properties. */
-
-#include "pcre_internal.h"
-
-#include "ucp.h" /* Category definitions */
-
-
-/*************************************************
-* Search table and return other case *
-*************************************************/
-
-/* If the given character is a letter, and there is another case for the
-letter, return the other case. Otherwise, return -1.
-
-Arguments:
- c the character value
-
-Returns: the other case or NOTACHAR if none
-*/
-
-unsigned int
-_pcre_ucp_othercase(const unsigned int c)
-{
-unsigned int other_case = NOTACHAR;
-
-if (g_unichar_islower(c))
- other_case = g_unichar_toupper(c);
-else if (g_unichar_isupper(c))
- other_case = g_unichar_tolower(c);
-
-if (other_case == c)
- other_case = NOTACHAR;
-
-return other_case;
-}
-
-
-/* End of pcre_ucp_searchfuncs.c */
diff --git a/glib/pcre/pcre_valid_utf8.c b/glib/pcre/pcre_valid_utf8.c
deleted file mode 100644
index a5766b454..000000000
--- a/glib/pcre/pcre_valid_utf8.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "pcre_internal.h"
-
-/*
- * This function is not needed by GRegex, so print an error and
- * return always -1, that is the string is a valid UTF-8 encoded
- * string.
- */
-int
-_pcre_valid_utf8(const uschar *string, int length)
-{
-g_warning ("%s: this function should not be called", G_STRLOC);
-return -1;
-}
diff --git a/glib/pcre/pcre_version.c b/glib/pcre/pcre_version.c
deleted file mode 100644
index 7067cd4ae..000000000
--- a/glib/pcre/pcre_version.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains the external function pcre_version(), which returns a
-string that identifies the PCRE version that is in use. */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-/*************************************************
-* Return version string *
-*************************************************/
-
-/* These macros are the standard way of turning unquoted text into C strings.
-They allow macros like PCRE_MAJOR to be defined without quotes, which is
-convenient for user programs that want to test its value. */
-
-#define STRING(a) # a
-#define XSTRING(s) STRING(s)
-
-/* A problem turned up with PCRE_PRERELEASE, which is defined empty for
-production releases. Originally, it was used naively in this code:
-
- return XSTRING(PCRE_MAJOR)
- "." XSTRING(PCRE_MINOR)
- XSTRING(PCRE_PRERELEASE)
- " " XSTRING(PCRE_DATE);
-
-However, when PCRE_PRERELEASE is empty, this leads to an attempted expansion of
-STRING(). The C standard states: "If (before argument substitution) any
-argument consists of no preprocessing tokens, the behavior is undefined." It
-turns out the gcc treats this case as a single empty string - which is what we
-really want - but Visual C grumbles about the lack of an argument for the
-macro. Unfortunately, both are within their rights. To cope with both ways of
-handling this, I had resort to some messy hackery that does a test at run time.
-I could find no way of detecting that a macro is defined as an empty string at
-pre-processor time. This hack uses a standard trick for avoiding calling
-the STRING macro with an empty argument when doing the test. */
-
-PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
-pcre_version(void)
-{
-return (XSTRING(Z PCRE_PRERELEASE)[1] == 0)?
- XSTRING(PCRE_MAJOR.PCRE_MINOR PCRE_DATE) :
- XSTRING(PCRE_MAJOR.PCRE_MINOR) XSTRING(PCRE_PRERELEASE PCRE_DATE);
-}
-
-/* End of pcre_version.c */
diff --git a/glib/pcre/pcre_xclass.c b/glib/pcre/pcre_xclass.c
deleted file mode 100644
index e8e7a5049..000000000
--- a/glib/pcre/pcre_xclass.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2008 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains an internal function that is used to match an extended
-class (one that contains characters whose values are > 255). It is used by both
-pcre_exec() and pcre_def_exec(). */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-
-/*************************************************
-* Match character against an XCLASS *
-*************************************************/
-
-/* This function is called to match a character against an extended class that
-might contain values > 255.
-
-Arguments:
- c the character
- data points to the flag byte of the XCLASS data
-
-Returns: TRUE if character matches, else FALSE
-*/
-
-BOOL
-_pcre_xclass(int c, const uschar *data)
-{
-int t;
-BOOL negated = (*data & XCL_NOT) != 0;
-
-/* Character values < 256 are matched against a bitmap, if one is present. If
-not, we still carry on, because there may be ranges that start below 256 in the
-additional data. */
-
-if (c < 256)
- {
- if ((*data & XCL_MAP) != 0 && (data[1 + c/8] & (1 << (c&7))) != 0)
- return !negated; /* char found */
- }
-
-/* First skip the bit map if present. Then match against the list of Unicode
-properties or large chars or ranges that end with a large char. We won't ever
-encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */
-
-if ((*data++ & XCL_MAP) != 0) data += 32;
-
-while ((t = *data++) != XCL_END)
- {
- int x, y;
- if (t == XCL_SINGLE)
- {
- GETCHARINC(x, data);
- if (c == x) return !negated;
- }
- else if (t == XCL_RANGE)
- {
- GETCHARINC(x, data);
- GETCHARINC(y, data);
- if (c >= x && c <= y) return !negated;
- }
-
-#ifdef SUPPORT_UCP
- else /* XCL_PROP & XCL_NOTPROP */
- {
- int chartype = UCD_CHARTYPE(c);
- switch(*data)
- {
- case PT_ANY:
- if (t == XCL_PROP) return !negated;
- break;
-
- case PT_LAMP:
- if ((chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt) ==
- (t == XCL_PROP)) return !negated;
- break;
-
- case PT_GC:
- if ((data[1] == _pcre_ucp_gentype[chartype]) == (t == XCL_PROP)) return !negated;
- break;
-
- case PT_PC:
- if ((data[1] == chartype) == (t == XCL_PROP)) return !negated;
- break;
-
- case PT_SC:
- if ((data[1] == UCD_SCRIPT(c)) == (t == XCL_PROP)) return !negated;
- break;
-
- /* This should never occur, but compilers may mutter if there is no
- default. */
-
- default:
- return FALSE;
- }
-
- data += 2;
- }
-#endif /* SUPPORT_UCP */
- }
-
-return negated; /* char did not match */
-}
-
-/* End of pcre_xclass.c */
diff --git a/glib/pcre/ucp.h b/glib/pcre/ucp.h
deleted file mode 100644
index fe910ce00..000000000
--- a/glib/pcre/ucp.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*************************************************
-* Unicode Property Table handler *
-*************************************************/
-
-#ifndef _UCP_H
-#define _UCP_H
-
-/* This file contains definitions of the property values that are returned by
-the function _pcre_ucp_findprop(). New values that are added for new releases
-of Unicode should always be at the end of each enum, for backwards
-compatibility. */
-
-/* These are the general character categories. */
-
-enum {
- ucp_C, /* Other */
- ucp_L, /* Letter */
- ucp_M, /* Mark */
- ucp_N, /* Number */
- ucp_P, /* Punctuation */
- ucp_S, /* Symbol */
- ucp_Z /* Separator */
-};
-
-/* These are the particular character types. */
-
-enum {
- ucp_Cc, /* Control */
- ucp_Cf, /* Format */
- ucp_Cn, /* Unassigned */
- ucp_Co, /* Private use */
- ucp_Cs, /* Surrogate */
- ucp_Ll, /* Lower case letter */
- ucp_Lm, /* Modifier letter */
- ucp_Lo, /* Other letter */
- ucp_Lt, /* Title case letter */
- ucp_Lu, /* Upper case letter */
- ucp_Mc, /* Spacing mark */
- ucp_Me, /* Enclosing mark */
- ucp_Mn, /* Non-spacing mark */
- ucp_Nd, /* Decimal number */
- ucp_Nl, /* Letter number */
- ucp_No, /* Other number */
- ucp_Pc, /* Connector punctuation */
- ucp_Pd, /* Dash punctuation */
- ucp_Pe, /* Close punctuation */
- ucp_Pf, /* Final punctuation */
- ucp_Pi, /* Initial punctuation */
- ucp_Po, /* Other punctuation */
- ucp_Ps, /* Open punctuation */
- ucp_Sc, /* Currency symbol */
- ucp_Sk, /* Modifier symbol */
- ucp_Sm, /* Mathematical symbol */
- ucp_So, /* Other symbol */
- ucp_Zl, /* Line separator */
- ucp_Zp, /* Paragraph separator */
- ucp_Zs /* Space separator */
-};
-
-/* These are the script identifications. */
-
-enum {
- ucp_Arabic = G_UNICODE_SCRIPT_ARABIC,
- ucp_Armenian = G_UNICODE_SCRIPT_ARMENIAN,
- ucp_Bengali = G_UNICODE_SCRIPT_BENGALI,
- ucp_Bopomofo = G_UNICODE_SCRIPT_BOPOMOFO,
- ucp_Braille = G_UNICODE_SCRIPT_BRAILLE,
- ucp_Buginese = G_UNICODE_SCRIPT_BUGINESE,
- ucp_Buhid = G_UNICODE_SCRIPT_BUHID,
- ucp_Canadian_Aboriginal = G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL,
- ucp_Cherokee = G_UNICODE_SCRIPT_CHEROKEE,
- ucp_Common = G_UNICODE_SCRIPT_COMMON,
- ucp_Coptic = G_UNICODE_SCRIPT_COPTIC,
- ucp_Cypriot = G_UNICODE_SCRIPT_CYPRIOT,
- ucp_Cyrillic = G_UNICODE_SCRIPT_CYRILLIC,
- ucp_Deseret = G_UNICODE_SCRIPT_DESERET,
- ucp_Devanagari = G_UNICODE_SCRIPT_DEVANAGARI,
- ucp_Ethiopic = G_UNICODE_SCRIPT_ETHIOPIC,
- ucp_Georgian = G_UNICODE_SCRIPT_GEORGIAN,
- ucp_Glagolitic = G_UNICODE_SCRIPT_GLAGOLITIC,
- ucp_Gothic = G_UNICODE_SCRIPT_GOTHIC,
- ucp_Greek = G_UNICODE_SCRIPT_GREEK,
- ucp_Gujarati = G_UNICODE_SCRIPT_GUJARATI,
- ucp_Gurmukhi = G_UNICODE_SCRIPT_GURMUKHI,
- ucp_Han = G_UNICODE_SCRIPT_HAN,
- ucp_Hangul = G_UNICODE_SCRIPT_HANGUL,
- ucp_Hanunoo = G_UNICODE_SCRIPT_HANUNOO,
- ucp_Hebrew = G_UNICODE_SCRIPT_HEBREW,
- ucp_Hiragana = G_UNICODE_SCRIPT_HIRAGANA,
- ucp_Inherited = G_UNICODE_SCRIPT_INHERITED,
- ucp_Kannada = G_UNICODE_SCRIPT_KANNADA,
- ucp_Katakana = G_UNICODE_SCRIPT_KATAKANA,
- ucp_Kharoshthi = G_UNICODE_SCRIPT_KHAROSHTHI,
- ucp_Khmer = G_UNICODE_SCRIPT_KHMER,
- ucp_Lao = G_UNICODE_SCRIPT_LAO,
- ucp_Latin = G_UNICODE_SCRIPT_LATIN,
- ucp_Limbu = G_UNICODE_SCRIPT_LIMBU,
- ucp_Linear_B = G_UNICODE_SCRIPT_LINEAR_B,
- ucp_Malayalam = G_UNICODE_SCRIPT_MALAYALAM,
- ucp_Mongolian = G_UNICODE_SCRIPT_MONGOLIAN,
- ucp_Myanmar = G_UNICODE_SCRIPT_MYANMAR,
- ucp_New_Tai_Lue = G_UNICODE_SCRIPT_NEW_TAI_LUE,
- ucp_Ogham = G_UNICODE_SCRIPT_OGHAM,
- ucp_Old_Italic = G_UNICODE_SCRIPT_OLD_ITALIC,
- ucp_Old_Persian = G_UNICODE_SCRIPT_OLD_PERSIAN,
- ucp_Oriya = G_UNICODE_SCRIPT_ORIYA,
- ucp_Osmanya = G_UNICODE_SCRIPT_OSMANYA,
- ucp_Runic = G_UNICODE_SCRIPT_RUNIC,
- ucp_Shavian = G_UNICODE_SCRIPT_SHAVIAN,
- ucp_Sinhala = G_UNICODE_SCRIPT_SINHALA,
- ucp_Syloti_Nagri = G_UNICODE_SCRIPT_SYLOTI_NAGRI,
- ucp_Syriac = G_UNICODE_SCRIPT_SYRIAC,
- ucp_Tagalog = G_UNICODE_SCRIPT_TAGALOG,
- ucp_Tagbanwa = G_UNICODE_SCRIPT_TAGBANWA,
- ucp_Tai_Le = G_UNICODE_SCRIPT_TAI_LE,
- ucp_Tamil = G_UNICODE_SCRIPT_TAMIL,
- ucp_Telugu = G_UNICODE_SCRIPT_TELUGU,
- ucp_Thaana = G_UNICODE_SCRIPT_THAANA,
- ucp_Thai = G_UNICODE_SCRIPT_THAI,
- ucp_Tibetan = G_UNICODE_SCRIPT_TIBETAN,
- ucp_Tifinagh = G_UNICODE_SCRIPT_TIFINAGH,
- ucp_Ugaritic = G_UNICODE_SCRIPT_UGARITIC,
- ucp_Yi = G_UNICODE_SCRIPT_YI,
- ucp_Balinese = G_UNICODE_SCRIPT_BALINESE, /* New for Unicode 5.0.0 */
- ucp_Cuneiform = G_UNICODE_SCRIPT_CUNEIFORM, /* New for Unicode 5.0.0 */
- ucp_Nko = G_UNICODE_SCRIPT_NKO, /* New for Unicode 5.0.0 */
- ucp_Phags_Pa = G_UNICODE_SCRIPT_PHAGS_PA, /* New for Unicode 5.0.0 */
- ucp_Phoenician = G_UNICODE_SCRIPT_PHOENICIAN, /* New for Unicode 5.0.0 */
- ucp_Carian = G_UNICODE_SCRIPT_CARIAN, /* New for Unicode 5.1 */
- ucp_Cham = G_UNICODE_SCRIPT_CHAM, /* New for Unicode 5.1 */
- ucp_Kayah_Li = G_UNICODE_SCRIPT_KAYAH_LI, /* New for Unicode 5.1 */
- ucp_Lepcha = G_UNICODE_SCRIPT_LEPCHA, /* New for Unicode 5.1 */
- ucp_Lycian = G_UNICODE_SCRIPT_LYCIAN, /* New for Unicode 5.1 */
- ucp_Lydian = G_UNICODE_SCRIPT_LYDIAN, /* New for Unicode 5.1 */
- ucp_Ol_Chiki = G_UNICODE_SCRIPT_OL_CHIKI, /* New for Unicode 5.1 */
- ucp_Rejang = G_UNICODE_SCRIPT_REJANG, /* New for Unicode 5.1 */
- ucp_Saurashtra = G_UNICODE_SCRIPT_SAURASHTRA, /* New for Unicode 5.1 */
- ucp_Sundanese = G_UNICODE_SCRIPT_SUNDANESE, /* New for Unicode 5.1 */
- ucp_Vai = G_UNICODE_SCRIPT_VAI /* New for Unicode 5.1 */
-};
-
-#endif
-
-/* End of ucp.h */
diff --git a/glib/pcre/ucpinternal.h b/glib/pcre/ucpinternal.h
deleted file mode 100644
index a96667b0a..000000000
--- a/glib/pcre/ucpinternal.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*************************************************
-* Unicode Property Table handler *
-*************************************************/
-
-#ifndef _UCPINTERNAL_H
-#define _UCPINTERNAL_H
-
-/* Internal header file defining the layout of the bits in each pair of 32-bit
-words that form a data item in the table. */
-
-typedef struct cnode {
- pcre_uint32 f0;
- pcre_uint32 f1;
-} cnode;
-
-/* Things for the f0 field */
-
-#define f0_scriptmask 0xff000000 /* Mask for script field */
-#define f0_scriptshift 24 /* Shift for script value */
-#define f0_rangeflag 0x00800000 /* Flag for a range item */
-#define f0_charmask 0x001fffff /* Mask for code point value */
-
-/* Things for the f1 field */
-
-#define f1_typemask 0xfc000000 /* Mask for char type field */
-#define f1_typeshift 26 /* Shift for the type field */
-#define f1_rangemask 0x0000ffff /* Mask for a range offset */
-#define f1_casemask 0x0000ffff /* Mask for a case offset */
-#define f1_caseneg 0xffff8000 /* Bits for negation */
-
-/* The data consists of a vector of structures of type cnode. The two unsigned
-32-bit integers are used as follows:
-
-(f0) (1) The most significant byte holds the script number. The numbers are
- defined by the enum in ucp.h.
-
- (2) The 0x00800000 bit is set if this entry defines a range of characters.
- It is not set if this entry defines a single character
-
- (3) The 0x00600000 bits are spare.
-
- (4) The 0x001fffff bits contain the code point. No Unicode code point will
- ever be greater than 0x0010ffff, so this should be OK for ever.
-
-(f1) (1) The 0xfc000000 bits contain the character type number. The numbers are
- defined by an enum in ucp.h.
-
- (2) The 0x03ff0000 bits are spare.
-
- (3) The 0x0000ffff bits contain EITHER the unsigned offset to the top of
- range if this entry defines a range, OR the *signed* offset to the
- character's "other case" partner if this entry defines a single
- character. There is no partner if the value is zero.
-
--------------------------------------------------------------------------------
-| script (8) |.|.|.| codepoint (21) || type (6) |.|.| spare (8) | offset (16) |
--------------------------------------------------------------------------------
- | | | | |
- | | |-> spare | |-> spare
- | | |
- | |-> spare |-> spare
- |
- |-> range flag
-
-The upper/lower casing information is set only for characters that come in
-pairs. The non-one-to-one mappings in the Unicode data are ignored.
-
-When searching the data, proceed as follows:
-
-(1) Set up for a binary chop search.
-
-(2) If the top is not greater than the bottom, the character is not in the
- table. Its type must therefore be "Cn" ("Undefined").
-
-(3) Find the middle vector element.
-
-(4) Extract the code point and compare. If equal, we are done.
-
-(5) If the test character is smaller, set the top to the current point, and
- goto (2).
-
-(6) If the current entry defines a range, compute the last character by adding
- the offset, and see if the test character is within the range. If it is,
- we are done.
-
-(7) Otherwise, set the bottom to one element past the current point and goto
- (2).
-*/
-
-#endif /* _UCPINTERNAL_H */
-
-/* End of ucpinternal.h */
diff --git a/glib/pltcheck.sh b/glib/pltcheck.sh
deleted file mode 100755
index 236eeb141..000000000
--- a/glib/pltcheck.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-
-LANG=C
-
-status=0
-
-if ! which readelf 2>/dev/null >/dev/null; then
- echo "'readelf' not found; skipping test"
- exit 0
-fi
-
-for so in .libs/lib*.so; do
- echo Checking $so for local PLT entries
- # g_string_insert_c is used in g_string_append_c_inline
- # unaliased. Couldn't find a way to fix it.
- # Same for g_once_init_enter
- readelf -r $so | grep 'JU\?MP_SLOT\?' | \
- grep -v '\<g_string_insert_c\>' | \
- grep -v '\<g_atomic_[a-z]*_[sg]et\>' | \
- grep -v '\<g_once_init_enter_impl\>' | \
- grep -v '\<g_bit_' | \
- grep '\<g_' && status=1
-done
-
-exit $status
diff --git a/glib/tests/.gitignore b/glib/tests/.gitignore
deleted file mode 100644
index 5e917297e..000000000
--- a/glib/tests/.gitignore
+++ /dev/null
@@ -1,11 +0,0 @@
-array-test
-fileutils
-keyfile
-markup-subparser
-option-context
-printf
-rand
-strfuncs
-string
-testing
-tmpsample.xml
diff --git a/glib/tests/4096-random-bytes b/glib/tests/4096-random-bytes
deleted file mode 100644
index 3e7a7db31..000000000
--- a/glib/tests/4096-random-bytes
+++ /dev/null
@@ -1,45 +0,0 @@
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXOxdolodx0WMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWMMMMMMMMMMMMMMMMMM0l' :NMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM0c. .:KMMMMMMMMMMMWd. ,MMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN, XMMMMMMMMMk. .MMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM' oMMMMMMMMc oMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMNklclkWMMMMMM0 lMMMMMMMc ;MMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMW: .XMMMMMk OMMMMMMx ;WMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMc 'MMMMMK .MMMMMMW. dMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMM. KMMMMM' 0MMMMMM0 ,KMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMM: OMMMMMK OMMMMMMM0 .OMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMW0kONMMMMMK KMMMMMMX, ,KMMMMMMMMW. ,kMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMWc lWMMMMO .MMMMMMMMMKxxXMMMMMMMMMMM0. .lXMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMM; 'WMMMMN: 0MMMMMMMMMMMMMMMMMMMMMMMMMNl'. ..:xXMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMM. oMMMMMMXdldNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMx .MMMMMMMMMMMMMMMMMMMMMMMWXK0OkkkkkkO0XNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMx NMMMMMMMMMMMMMMWKko:'. .;d0WMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMK, .MMMMMMMMMMW0o;. :KMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMXo;';KMMMMMMMKo' cMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMXl. xMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMk' :MMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMO. dMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMWc ,WMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMN. cWMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMW' '0MMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMd :KMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMM. 'dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMM 'oXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMM. ,xNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMM; .:kNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMO .l0MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMM, :KMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMN. oNMMMMMMMMMMMMMXkoc:,,,,:lOWMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMX. .XMMMMMMMMMMMM0:. .XMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMN. xMMMMMMMMMMMM0 OMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMWc 'NMMMMMMMMMMMO 'WMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMO. .kMMMMMMMMMMc .XMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMWl .l0WMMMW0; .KMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMNl ... ;NMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMMMWd. .OMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM0c. 'xWMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM0l. .cKMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo;. .;dKMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNKOxxdddkOXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
-MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM.
diff --git a/glib/tests/Makefile.am b/glib/tests/Makefile.am
deleted file mode 100644
index 3d497ac23..000000000
--- a/glib/tests/Makefile.am
+++ /dev/null
@@ -1,62 +0,0 @@
-include $(top_srcdir)/Makefile.decl
-
-INCLUDES = -g -I$(top_srcdir) -I$(top_srcdir)/glib $(GLIB_DEBUG_FLAGS)
-
-noinst_PROGRAMS = $(TEST_PROGS)
-progs_ldadd = $(top_builddir)/glib/libglib-2.0.la
-
-
-TEST_PROGS += testing
-testing_SOURCES = testing.c
-testing_LDADD = $(progs_ldadd)
-
-TEST_PROGS += option-context
-option_context_SOURCES = option-context.c
-option_context_LDADD = $(progs_ldadd)
-
-TEST_PROGS += keyfile
-keyfile_SOURCES = keyfile.c
-keyfile_LDADD = $(progs_ldadd)
-
-TEST_PROGS += fileutils
-fileutils_SOURCES = fileutils.c
-fileutils_LDADD = $(progs_ldadd)
-
-TEST_PROGS += printf
-printf_SOURCES = printf.c
-printf_LDADD = $(progs_ldadd) -lm
-
-TEST_PROGS += rand
-rand_SOURCES = rand.c
-rand_LDADD = $(progs_ldadd) -lm
-
-TEST_PROGS += strfuncs
-strfuncs_SOURCES = strfuncs.c
-strfuncs_LDADD = $(progs_ldadd) -lm
-
-TEST_PROGS += string
-string_SOURCES = string.c
-string_LDADD = $(progs_ldadd) -lm
-
-TEST_PROGS += markup-subparser
-markup_subparser_LDADD = $(progs_ldadd)
-
-TEST_PROGS += array-test
-array_test_LDADD = $(progs_ldadd)
-
-if OS_UNIX
-
-# some testing of gtester funcitonality
-XMLLINT=xmllint
-gtester-xmllint-check: # check testreport xml with xmllint if present
- ${GTESTER} -k --quiet -o tmpsample.xml --test-arg=--gtester-selftest ${GTESTER}
- ${XMLLINT} --version 2>/dev/null; test "$$?" != 0 || ${XMLLINT} --noout tmpsample.xml
-check-am: gtester-xmllint-check
-
-endif
-
-CLEANFILES = \
- tmpsample.xml
-
-EXTRA_DIST += \
- 4096-random-bytes
diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c
deleted file mode 100644
index 6f83a2762..000000000
--- a/glib/tests/array-test.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * 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 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
- * file for a list of people on the GLib Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-#undef G_DISABLE_ASSERT
-#undef G_LOG_DOMAIN
-
-#include <stdio.h>
-#include <string.h>
-#include "glib.h"
-
-static void
-sum_up (gpointer data,
- gpointer user_data)
-{
- gint *sum = (gint *)user_data;
-
- *sum += GPOINTER_TO_INT (data);
-}
-
-static void
-array_append (void)
-{
- GArray *garray;
- gint i;
-
- garray = g_array_new (FALSE, FALSE, sizeof (gint));
- for (i = 0; i < 10000; i++)
- g_array_append_val (garray, i);
-
- for (i = 0; i < 10000; i++)
- g_assert_cmpint (g_array_index (garray, gint, i), ==, i);
-
- g_array_free (garray, TRUE);
-}
-
-static void
-array_prepend (void)
-{
- GArray *garray;
- gint i;
-
- garray = g_array_new (FALSE, FALSE, sizeof (gint));
- for (i = 0; i < 100; i++)
- g_array_prepend_val (garray, i);
-
- for (i = 0; i < 100; i++)
- g_assert_cmpint (g_array_index (garray, gint, i), ==, (100 - i - 1));
-
- g_array_free (garray, TRUE);
-}
-
-static void
-pointer_array_add (void)
-{
- GPtrArray *gparray;
- gint i;
- gint sum = 0;
-
- gparray = g_ptr_array_new ();
- for (i = 0; i < 10000; i++)
- g_ptr_array_add (gparray, GINT_TO_POINTER (i));
-
- for (i = 0; i < 10000; i++)
- g_assert (g_ptr_array_index (gparray, i) == GINT_TO_POINTER (i));
-
- g_ptr_array_foreach (gparray, sum_up, &sum);
- g_assert (sum == 49995000);
-
- g_ptr_array_free (gparray, TRUE);
-}
-
-static void
-byte_array_append (void)
-{
- GByteArray *gbarray;
- gint i;
-
- gbarray = g_byte_array_new ();
- for (i = 0; i < 10000; i++)
- g_byte_array_append (gbarray, (guint8*) "abcd", 4);
-
- for (i = 0; i < 10000; i++)
- {
- g_assert (gbarray->data[4*i] == 'a');
- g_assert (gbarray->data[4*i+1] == 'b');
- g_assert (gbarray->data[4*i+2] == 'c');
- g_assert (gbarray->data[4*i+3] == 'd');
- }
-
- g_byte_array_free (gbarray, TRUE);
-}
-
-int
-main (int argc, char *argv[])
-{
- g_test_init (&argc, &argv, NULL);
-
- /* array tests */
- g_test_add_func ("/array/append", array_append);
- g_test_add_func ("/array/prepend", array_prepend);
-
- /* pointer arrays */
- g_test_add_func ("/pointerarray/add", pointer_array_add);
-
- /* byte arrays */
- g_test_add_func ("/bytearray/append", byte_array_append);
-
- return g_test_run ();
-}
-
diff --git a/glib/tests/fileutils.c b/glib/tests/fileutils.c
deleted file mode 100644
index 225c6ce35..000000000
--- a/glib/tests/fileutils.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/* Unit tests for gfileutils
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This work is provided "as is"; redistribution and modification
- * in whole or in part, in any medium, physical or electronic is
- * permitted without restriction.
- *
- * This work 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.
- *
- * In no event shall the authors or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even
- * if advised of the possibility of such damage.
- */
-
-#include <string.h>
-#include <errno.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#define S G_DIR_SEPARATOR_S
-
-static void
-check_string (gchar *str, gchar *expected)
-{
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, expected);
- g_free (str);
-}
-
-static void
-test_build_path (void)
-{
-/* check_string (g_build_path ("", NULL), "");*/
- check_string (g_build_path ("", "", NULL), "");
- check_string (g_build_path ("", "x", NULL), "x");
- check_string (g_build_path ("", "x", "y", NULL), "xy");
- check_string (g_build_path ("", "x", "y", "z", NULL), "xyz");
-
-/* check_string (g_build_path (":", NULL), "");*/
- check_string (g_build_path (":", ":", NULL), ":");
- check_string (g_build_path (":", ":x", NULL), ":x");
- check_string (g_build_path (":", "x:", NULL), "x:");
- check_string (g_build_path (":", "", "x", NULL), "x");
- check_string (g_build_path (":", "", ":x", NULL), ":x");
- check_string (g_build_path (":", ":", "x", NULL), ":x");
- check_string (g_build_path (":", "::", "x", NULL), "::x");
- check_string (g_build_path (":", "x", "", NULL), "x");
- check_string (g_build_path (":", "x:", "", NULL), "x:");
- check_string (g_build_path (":", "x", ":", NULL), "x:");
- check_string (g_build_path (":", "x", "::", NULL), "x::");
- check_string (g_build_path (":", "x", "y", NULL), "x:y");
- check_string (g_build_path (":", ":x", "y", NULL), ":x:y");
- check_string (g_build_path (":", "x", "y:", NULL), "x:y:");
- check_string (g_build_path (":", ":x:", ":y:", NULL), ":x:y:");
- check_string (g_build_path (":", ":x::", "::y:", NULL), ":x:y:");
- check_string (g_build_path (":", "x", "","y", NULL), "x:y");
- check_string (g_build_path (":", "x", ":", "y", NULL), "x:y");
- check_string (g_build_path (":", "x", "::", "y", NULL), "x:y");
- check_string (g_build_path (":", "x", "y", "z", NULL), "x:y:z");
- check_string (g_build_path (":", ":x:", ":y:", ":z:", NULL), ":x:y:z:");
- check_string (g_build_path (":", "::x::", "::y::", "::z::", NULL), "::x:y:z::");
-
-/* check_string (g_build_path ("::", NULL), "");*/
- check_string (g_build_path ("::", "::", NULL), "::");
- check_string (g_build_path ("::", ":::", NULL), ":::");
- check_string (g_build_path ("::", "::x", NULL), "::x");
- check_string (g_build_path ("::", "x::", NULL), "x::");
- check_string (g_build_path ("::", "", "x", NULL), "x");
- check_string (g_build_path ("::", "", "::x", NULL), "::x");
- check_string (g_build_path ("::", "::", "x", NULL), "::x");
- check_string (g_build_path ("::", "::::", "x", NULL), "::::x");
- check_string (g_build_path ("::", "x", "", NULL), "x");
- check_string (g_build_path ("::", "x::", "", NULL), "x::");
- check_string (g_build_path ("::", "x", "::", NULL), "x::");
-
- /* This following is weird, but keeps the definition simple */
- check_string (g_build_path ("::", "x", ":::", NULL), "x:::::");
- check_string (g_build_path ("::", "x", "::::", NULL), "x::::");
- check_string (g_build_path ("::", "x", "y", NULL), "x::y");
- check_string (g_build_path ("::", "::x", "y", NULL), "::x::y");
- check_string (g_build_path ("::", "x", "y::", NULL), "x::y::");
- check_string (g_build_path ("::", "::x::", "::y::", NULL), "::x::y::");
- check_string (g_build_path ("::", "::x:::", ":::y::", NULL), "::x::::y::");
- check_string (g_build_path ("::", "::x::::", "::::y::", NULL), "::x::y::");
- check_string (g_build_path ("::", "x", "", "y", NULL), "x::y");
- check_string (g_build_path ("::", "x", "::", "y", NULL), "x::y");
- check_string (g_build_path ("::", "x", "::::", "y", NULL), "x::y");
- check_string (g_build_path ("::", "x", "y", "z", NULL), "x::y::z");
- check_string (g_build_path ("::", "::x::", "::y::", "::z::", NULL), "::x::y::z::");
- check_string (g_build_path ("::", ":::x:::", ":::y:::", ":::z:::", NULL), ":::x::::y::::z:::");
- check_string (g_build_path ("::", "::::x::::", "::::y::::", "::::z::::", NULL), "::::x::y::z::::");
-}
-
-static void
-test_build_pathv (void)
-{
- gchar *args[10];
-
- args[0] = NULL;
- check_string (g_build_pathv ("", args), "");
- args[0] = ""; args[1] = NULL;
- check_string (g_build_pathv ("", args), "");
- args[0] = "x"; args[1] = NULL;
- check_string (g_build_pathv ("", args), "x");
- args[0] = "x"; args[1] = "y"; args[2] = NULL;
- check_string (g_build_pathv ("", args), "xy");
- args[0] = "x"; args[1] = "y"; args[2] = "z", args[3] = NULL;
- check_string (g_build_pathv ("", args), "xyz");
-
- args[0] = NULL;
- check_string (g_build_pathv (":", args), "");
- args[0] = ":"; args[1] = NULL;
- check_string (g_build_pathv (":", args), ":");
- args[0] = ":x"; args[1] = NULL;
- check_string (g_build_pathv (":", args), ":x");
- args[0] = "x:"; args[1] = NULL;
- check_string (g_build_pathv (":", args), "x:");
- args[0] = ""; args[1] = "x"; args[2] = NULL;
- check_string (g_build_pathv (":", args), "x");
- args[0] = ""; args[1] = ":x"; args[2] = NULL;
- check_string (g_build_pathv (":", args), ":x");
- args[0] = ":"; args[1] = "x"; args[2] = NULL;
- check_string (g_build_pathv (":", args), ":x");
- args[0] = "::"; args[1] = "x"; args[2] = NULL;
- check_string (g_build_pathv (":", args), "::x");
- args[0] = "x"; args[1] = ""; args[2] = NULL;
- check_string (g_build_pathv (":", args), "x");
- args[0] = "x:"; args[1] = ""; args[2] = NULL;
- check_string (g_build_pathv (":", args), "x:");
- args[0] = "x"; args[1] = ":"; args[2] = NULL;
- check_string (g_build_pathv (":", args), "x:");
- args[0] = "x"; args[1] = "::"; args[2] = NULL;
- check_string (g_build_pathv (":", args), "x::");
- args[0] = "x"; args[1] = "y"; args[2] = NULL;
- check_string (g_build_pathv (":", args), "x:y");
- args[0] = ":x"; args[1] = "y"; args[2] = NULL;
- check_string (g_build_pathv (":", args), ":x:y");
- args[0] = "x"; args[1] = "y:"; args[2] = NULL;
- check_string (g_build_pathv (":", args), "x:y:");
- args[0] = ":x:"; args[1] = ":y:"; args[2] = NULL;
- check_string (g_build_pathv (":", args), ":x:y:");
- args[0] = ":x::"; args[1] = "::y:"; args[2] = NULL;
- check_string (g_build_pathv (":", args), ":x:y:");
- args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
- check_string (g_build_pathv (":", args), "x:y");
- args[0] = "x"; args[1] = ":"; args[2] = "y"; args[3] = NULL;
- check_string (g_build_pathv (":", args), "x:y");
- args[0] = "x"; args[1] = "::"; args[2] = "y"; args[3] = NULL;
- check_string (g_build_pathv (":", args), "x:y");
- args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
- check_string (g_build_pathv (":", args), "x:y:z");
- args[0] = ":x:"; args[1] = ":y:"; args[2] = ":z:"; args[3] = NULL;
- check_string (g_build_pathv (":", args), ":x:y:z:");
- args[0] = "::x::"; args[1] = "::y::"; args[2] = "::z::"; args[3] = NULL;
- check_string (g_build_pathv (":", args), "::x:y:z::");
-
- args[0] = NULL;
- check_string (g_build_pathv ("::", args), "");
- args[0] = "::"; args[1] = NULL;
- check_string (g_build_pathv ("::", args), "::");
- args[0] = ":::"; args[1] = NULL;
- check_string (g_build_pathv ("::", args), ":::");
- args[0] = "::x"; args[1] = NULL;
- check_string (g_build_pathv ("::", args), "::x");
- args[0] = "x::"; args[1] = NULL;
- check_string (g_build_pathv ("::", args), "x::");
- args[0] = ""; args[1] = "x"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "x");
- args[0] = ""; args[1] = "::x"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "::x");
- args[0] = "::"; args[1] = "x"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "::x");
- args[0] = "::::"; args[1] = "x"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "::::x");
- args[0] = "x"; args[1] = ""; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "x");
- args[0] = "x::"; args[1] = ""; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "x::");
- args[0] = "x"; args[1] = "::"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "x::");
- /* This following is weird, but keeps the definition simple */
- args[0] = "x"; args[1] = ":::"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "x:::::");
- args[0] = "x"; args[1] = "::::"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "x::::");
- args[0] = "x"; args[1] = "y"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "x::y");
- args[0] = "::x"; args[1] = "y"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "::x::y");
- args[0] = "x"; args[1] = "y::"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "x::y::");
- args[0] = "::x::"; args[1] = "::y::"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "::x::y::");
- args[0] = "::x:::"; args[1] = ":::y::"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "::x::::y::");
- args[0] = "::x::::"; args[1] = "::::y::"; args[2] = NULL;
- check_string (g_build_pathv ("::", args), "::x::y::");
- args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
- check_string (g_build_pathv ("::", args), "x::y");
- args[0] = "x"; args[1] = "::"; args[2] = "y"; args[3] = NULL;
- check_string (g_build_pathv ("::", args), "x::y");
- args[0] = "x"; args[1] = "::::"; args[2] = "y"; args[3] = NULL;
- check_string (g_build_pathv ("::", args), "x::y");
- args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
- check_string (g_build_pathv ("::", args), "x::y::z");
- args[0] = "::x::"; args[1] = "::y::"; args[2] = "::z::"; args[3] = NULL;
- check_string (g_build_pathv ("::", args), "::x::y::z::");
- args[0] = ":::x:::"; args[1] = ":::y:::"; args[2] = ":::z:::"; args[3] = NULL;
- check_string (g_build_pathv ("::", args), ":::x::::y::::z:::");
- args[0] = "::::x::::"; args[1] = "::::y::::"; args[2] = "::::z::::"; args[3] = NULL;
- check_string (g_build_pathv ("::", args), "::::x::y::z::::");
-}
-
-static void
-test_build_filename (void)
-{
-/* check_string (g_build_filename (NULL), "");*/
- check_string (g_build_filename (S, NULL), S);
- check_string (g_build_filename (S"x", NULL), S"x");
- check_string (g_build_filename ("x"S, NULL), "x"S);
- check_string (g_build_filename ("", "x", NULL), "x");
- check_string (g_build_filename ("", S"x", NULL), S"x");
- check_string (g_build_filename (S, "x", NULL), S"x");
- check_string (g_build_filename (S S, "x", NULL), S S"x");
- check_string (g_build_filename ("x", "", NULL), "x");
- check_string (g_build_filename ("x"S, "", NULL), "x"S);
- check_string (g_build_filename ("x", S, NULL), "x"S);
- check_string (g_build_filename ("x", S S, NULL), "x"S S);
- check_string (g_build_filename ("x", "y", NULL), "x"S"y");
- check_string (g_build_filename (S"x", "y", NULL), S"x"S"y");
- check_string (g_build_filename ("x", "y"S, NULL), "x"S"y"S);
- check_string (g_build_filename (S"x"S, S"y"S, NULL), S"x"S"y"S);
- check_string (g_build_filename (S"x"S S, S S"y"S, NULL), S"x"S"y"S);
- check_string (g_build_filename ("x", "", "y", NULL), "x"S"y");
- check_string (g_build_filename ("x", S, "y", NULL), "x"S"y");
- check_string (g_build_filename ("x", S S, "y", NULL), "x"S"y");
- check_string (g_build_filename ("x", "y", "z", NULL), "x"S"y"S"z");
- check_string (g_build_filename (S"x"S, S"y"S, S"z"S, NULL), S"x"S"y"S"z"S);
- check_string (g_build_filename (S S"x"S S, S S"y"S S, S S"z"S S, NULL), S S"x"S"y"S"z"S S);
-
-#ifdef G_OS_WIN32
-
- /* Test also using the slash as file name separator */
-#define U "/"
- check_string (g_build_filename (NULL), "");
- check_string (g_build_filename (U, NULL), U);
- check_string (g_build_filename (U"x", NULL), U"x");
- check_string (g_build_filename ("x"U, NULL), "x"U);
- check_string (g_build_filename ("", U"x", NULL), U"x");
- check_string (g_build_filename ("", U"x", NULL), U"x");
- check_string (g_build_filename (U, "x", NULL), U"x");
- check_string (g_build_filename (U U, "x", NULL), U U"x");
- check_string (g_build_filename (U S, "x", NULL), U S"x");
- check_string (g_build_filename ("x"U, "", NULL), "x"U);
- check_string (g_build_filename ("x"S"y", "z"U"a", NULL), "x"S"y"S"z"U"a");
- check_string (g_build_filename ("x", U, NULL), "x"U);
- check_string (g_build_filename ("x", U U, NULL), "x"U U);
- check_string (g_build_filename ("x", S U, NULL), "x"S U);
- check_string (g_build_filename (U"x", "y", NULL), U"x"U"y");
- check_string (g_build_filename ("x", "y"U, NULL), "x"U"y"U);
- check_string (g_build_filename (U"x"U, U"y"U, NULL), U"x"U"y"U);
- check_string (g_build_filename (U"x"U U, U U"y"U, NULL), U"x"U"y"U);
- check_string (g_build_filename ("x", U, "y", NULL), "x"U"y");
- check_string (g_build_filename ("x", U U, "y", NULL), "x"U"y");
- check_string (g_build_filename ("x", U S, "y", NULL), "x"S"y");
- check_string (g_build_filename ("x", S U, "y", NULL), "x"U"y");
- check_string (g_build_filename ("x", U "y", "z", NULL), "x"U"y"U"z");
- check_string (g_build_filename ("x", S "y", "z", NULL), "x"S"y"S"z");
- check_string (g_build_filename ("x", S "y", "z", U, "a", "b", NULL), "x"S"y"S"z"U"a"U"b");
- check_string (g_build_filename (U"x"U, U"y"U, U"z"U, NULL), U"x"U"y"U"z"U);
- check_string (g_build_filename (U U"x"U U, U U"y"U U, U U"z"U U, NULL), U U"x"U"y"U"z"U U);
-
-#undef U
-
-#endif /* G_OS_WIN32 */
-
-}
-
-static void
-test_build_filenamev (void)
-{
- gchar *args[10];
-
- args[0] = NULL;
- check_string (g_build_filenamev (args), "");
- args[0] = S; args[1] = NULL;
- check_string (g_build_filenamev (args), S);
- args[0] = S"x"; args[1] = NULL;
- check_string (g_build_filenamev (args), S"x");
- args[0] = "x"S; args[1] = NULL;
- check_string (g_build_filenamev (args), "x"S);
- args[0] = ""; args[1] = "x"; args[2] = NULL;
- check_string (g_build_filenamev (args), "x");
- args[0] = ""; args[1] = S"x"; args[2] = NULL;
- check_string (g_build_filenamev (args), S"x");
- args[0] = S; args[1] = "x"; args[2] = NULL;
- check_string (g_build_filenamev (args), S"x");
- args[0] = S S; args[1] = "x"; args[2] = NULL;
- check_string (g_build_filenamev (args), S S"x");
- args[0] = "x"; args[1] = ""; args[2] = NULL;
- check_string (g_build_filenamev (args), "x");
- args[0] = "x"S; args[1] = ""; args[2] = NULL;
- check_string (g_build_filenamev (args), "x"S);
- args[0] = "x"; args[1] = S; args[2] = NULL;
- check_string (g_build_filenamev (args), "x"S);
- args[0] = "x"; args[1] = S S; args[2] = NULL;
- check_string (g_build_filenamev (args), "x"S S);
- args[0] = "x"; args[1] = "y"; args[2] = NULL;
- check_string (g_build_filenamev (args), "x"S"y");
- args[0] = S"x"; args[1] = "y"; args[2] = NULL;
- check_string (g_build_filenamev (args), S"x"S"y");
- args[0] = "x"; args[1] = "y"S; args[2] = NULL;
- check_string (g_build_filenamev (args), "x"S"y"S);
- args[0] = S"x"S; args[1] = S"y"S; args[2] = NULL;
- check_string (g_build_filenamev (args), S"x"S"y"S);
- args[0] = S"x"S S; args[1] = S S"y"S; args[2] = NULL;
- check_string (g_build_filenamev (args), S"x"S"y"S);
- args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
- check_string (g_build_filenamev (args), "x"S"y");
- args[0] = "x"; args[1] = S; args[2] = "y"; args[3] = NULL;
- check_string (g_build_filenamev (args), "x"S"y");
- args[0] = "x"; args[1] = S S; args[2] = "y"; args[3] = NULL;
- check_string (g_build_filenamev (args), "x"S"y");
- args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
- check_string (g_build_filenamev (args), "x"S"y"S"z");
- args[0] = S"x"S; args[1] = S"y"S; args[2] = S"z"S; args[3] = NULL;
- check_string (g_build_filenamev (args), S"x"S"y"S"z"S);
- args[0] = S S"x"S S; args[1] = S S"y"S S; args[2] = S S"z"S S; args[3] = NULL;
- check_string (g_build_filenamev (args), S S"x"S"y"S"z"S S);
-
-#ifdef G_OS_WIN32
-
- /* Test also using the slash as file name separator */
-#define U "/"
- args[0] = NULL;
- check_string (g_build_filenamev (args), "");
- args[0] = U; args[1] = NULL;
- check_string (g_build_filenamev (args), U);
- args[0] = U"x"; args[1] = NULL;
- check_string (g_build_filenamev (args), U"x");
- args[0] = "x"U; args[1] = NULL;
- check_string (g_build_filenamev (args), "x"U);
- args[0] = ""; args[1] = U"x"; args[2] = NULL;
- check_string (g_build_filenamev (args), U"x");
- args[0] = ""; args[1] = U"x"; args[2] = NULL;
- check_string (g_build_filenamev (args), U"x");
- args[0] = U; args[1] = "x"; args[2] = NULL;
- check_string (g_build_filenamev (args), U"x");
- args[0] = U U; args[1] = "x"; args[2] = NULL;
- check_string (g_build_filenamev (args), U U"x");
- args[0] = U S; args[1] = "x"; args[2] = NULL;
- check_string (g_build_filenamev (args), U S"x");
- args[0] = "x"U; args[1] = ""; args[2] = NULL;
- check_string (g_build_filenamev (args), "x"U);
- args[0] = "x"S"y"; args[1] = "z"U"a"; args[2] = NULL;
- check_string (g_build_filenamev (args), "x"S"y"S"z"U"a");
- args[0] = "x"; args[1] = U; args[2] = NULL;
- check_string (g_build_filenamev (args), "x"U);
- args[0] = "x"; args[1] = U U; args[2] = NULL;
- check_string (g_build_filenamev (args), "x"U U);
- args[0] = "x"; args[1] = S U; args[2] = NULL;
- check_string (g_build_filenamev (args), "x"S U);
- args[0] = U"x"; args[1] = "y"; args[2] = NULL;
- check_string (g_build_filenamev (args), U"x"U"y");
- args[0] = "x"; args[1] = "y"U; args[2] = NULL;
- check_string (g_build_filenamev (args), "x"U"y"U);
- args[0] = U"x"U; args[1] = U"y"U; args[2] = NULL;
- check_string (g_build_filenamev (args), U"x"U"y"U);
- args[0] = U"x"U U; args[1] = U U"y"U; args[2] = NULL;
- check_string (g_build_filenamev (args), U"x"U"y"U);
- args[0] = "x"; args[1] = U; args[2] = "y", args[3] = NULL;
- check_string (g_build_filenamev (args), "x"U"y");
- args[0] = "x"; args[1] = U U; args[2] = "y", args[3] = NULL;
- check_string (g_build_filenamev (args), "x"U"y");
- args[0] = "x"; args[1] = U S; args[2] = "y", args[3] = NULL;
- check_string (g_build_filenamev (args), "x"S"y");
- args[0] = "x"; args[1] = S U; args[2] = "y", args[3] = NULL;
- check_string (g_build_filenamev (args), "x"U"y");
- args[0] = "x"; args[1] = U "y"; args[2] = "z", args[3] = NULL;
- check_string (g_build_filenamev (args), "x"U"y"U"z");
- args[0] = "x"; args[1] = S "y"; args[2] = "z", args[3] = NULL;
- check_string (g_build_filenamev (args), "x"S"y"S"z");
- args[0] = "x"; args[1] = S "y"; args[2] = "z", args[3] = U;
- args[4] = "a"; args[5] = "b"; args[6] = NULL;
- check_string (g_build_filenamev (args), "x"S"y"S"z"U"a"U"b");
- args[0] = U"x"U; args[1] = U"y"U; args[2] = U"z"U, args[3] = NULL;
- check_string (g_build_filenamev (args), U"x"U"y"U"z"U);
- args[0] = U U"x"U U; args[1] = U U"y"U U; args[2] = U U"z"U U, args[3] = NULL;
- check_string (g_build_filenamev (args), U U"x"U"y"U"z"U U);
-
-#undef U
-
-#endif /* G_OS_WIN32 */
-}
-
-#undef S
-
-static void
-test_mkdir_with_parents_1 (const gchar *base)
-{
- char *p0 = g_build_filename (base, "fum", NULL);
- char *p1 = g_build_filename (p0, "tem", NULL);
- char *p2 = g_build_filename (p1, "zap", NULL);
- FILE *f;
-
- g_remove (p2);
- g_remove (p1);
- g_remove (p0);
-
- if (g_file_test (p0, G_FILE_TEST_EXISTS))
- g_error ("failed, %s exists, cannot test g_mkdir_with_parents\n", p0);
-
- if (g_file_test (p1, G_FILE_TEST_EXISTS))
- g_error ("failed, %s exists, cannot test g_mkdir_with_parents\n", p1);
-
- if (g_file_test (p2, G_FILE_TEST_EXISTS))
- g_error ("failed, %s exists, cannot test g_mkdir_with_parents\n", p2);
-
- if (g_mkdir_with_parents (p2, 0777) == -1)
- g_error ("failed, g_mkdir_with_parents(%s) failed: %s\n", p2, g_strerror (errno));
-
- if (!g_file_test (p2, G_FILE_TEST_IS_DIR))
- g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory\n", p2, p2);
-
- if (!g_file_test (p1, G_FILE_TEST_IS_DIR))
- g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory\n", p2, p1);
-
- if (!g_file_test (p0, G_FILE_TEST_IS_DIR))
- g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory\n", p2, p0);
-
- g_rmdir (p2);
- if (g_file_test (p2, G_FILE_TEST_EXISTS))
- g_error ("failed, did g_rmdir(%s), but %s is still there\n", p2, p2);
-
- g_rmdir (p1);
- if (g_file_test (p1, G_FILE_TEST_EXISTS))
- g_error ("failed, did g_rmdir(%s), but %s is still there\n", p1, p1);
-
- f = g_fopen (p1, "w");
- if (f == NULL)
- g_error ("failed, couldn't create file %s\n", p1);
- fclose (f);
-
- if (g_mkdir_with_parents (p1, 0666) == 0)
- g_error ("failed, g_mkdir_with_parents(%s) succeeded, even if %s is a file\n", p1, p1);
-
- if (g_mkdir_with_parents (p2, 0666) == 0)
- g_error("failed, g_mkdir_with_parents(%s) succeeded, even if %s is a file\n", p2, p1);
-
- g_remove (p2);
- g_remove (p1);
- g_remove (p0);
-}
-
-static void
-test_mkdir_with_parents (void)
-{
- gchar *cwd;
- if (g_test_verbose())
- g_print ("checking g_mkdir_with_parents() in subdir ./hum/");
- test_mkdir_with_parents_1 ("hum");
- g_remove ("hum");
- if (g_test_verbose())
- g_print ("checking g_mkdir_with_parents() in subdir ./hii///haa/hee/");
- test_mkdir_with_parents_1 ("hii///haa/hee");
- g_remove ("hii/haa/hee");
- g_remove ("hii/haa");
- g_remove ("hii");
- cwd = g_get_current_dir ();
- if (g_test_verbose())
- g_print ("checking g_mkdir_with_parents() in cwd: %s", cwd);
- test_mkdir_with_parents_1 (cwd);
- g_free (cwd);
-}
-
-static void
-test_format_size_for_display (void)
-{
- check_string (g_format_size_for_display (0), "0 bytes");
- check_string (g_format_size_for_display (1), "1 byte");
- check_string (g_format_size_for_display (2), "2 bytes");
- check_string (g_format_size_for_display (1024), "1.0 KB");
- check_string (g_format_size_for_display (1024 * 1024), "1.0 MB");
- check_string (g_format_size_for_display (1024 * 1024 * 1024), "1.0 GB");
-}
-
-int
-main (int argc,
- char *argv[])
-{
- g_test_init (&argc, &argv, NULL);
-
- g_test_add_func ("/fileutils/build-path", test_build_path);
- g_test_add_func ("/fileutils/build-pathv", test_build_pathv);
- g_test_add_func ("/fileutils/build-filename", test_build_filename);
- g_test_add_func ("/fileutils/build-filenamev", test_build_filenamev);
- g_test_add_func ("/fileutils/mkdir-with-parents", test_mkdir_with_parents);
- g_test_add_func ("/fileutils/format-size-for-display", test_format_size_for_display);
-
- return g_test_run();
-}
diff --git a/glib/tests/keyfile.c b/glib/tests/keyfile.c
deleted file mode 100644
index ba8cd1e61..000000000
--- a/glib/tests/keyfile.c
+++ /dev/null
@@ -1,1262 +0,0 @@
-#include <glib.h>
-#include <locale.h>
-#include <string.h>
-#include <stdlib.h>
-
-static GKeyFile *
-load_data (const gchar *data,
- GKeyFileFlags flags)
-{
- GKeyFile *keyfile;
- GError *error = NULL;
-
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, flags, &error);
- g_assert_no_error (error);
- return keyfile;
-}
-
-static void
-check_error (GError **error,
- GQuark domain,
- gint code)
-{
- g_assert_error (*error, domain, code);
- g_error_free (*error);
- *error = NULL;
-}
-
-static void
-check_no_error (GError **error)
-{
- g_assert_no_error (*error);
-}
-
-static void
-check_string_value (GKeyFile *keyfile,
- const gchar *group,
- const gchar *key,
- const gchar *expected)
-{
- GError *error = NULL;
- gchar *value;
-
- value = g_key_file_get_string (keyfile, group, key, &error);
- check_no_error (&error);
- g_assert (value != NULL);
- g_assert_cmpstr (value, ==, expected);
- g_free (value);
-}
-
-static void
-check_locale_string_value (GKeyFile *keyfile,
- const gchar *group,
- const gchar *key,
- const gchar *locale,
- const gchar *expected)
-{
- GError *error = NULL;
- gchar *value;
-
- value = g_key_file_get_locale_string (keyfile, group, key, locale, &error);
- check_no_error (&error);
- g_assert (value != NULL);
- g_assert_cmpstr (value, ==, expected);
- g_free (value);
-}
-
-static void
-check_string_list_value (GKeyFile *keyfile,
- const gchar *group,
- const gchar *key,
- ...)
-{
- gint i;
- gchar *v, **value;
- va_list args;
- gsize len;
- GError *error = NULL;
-
- value = g_key_file_get_string_list (keyfile, group, key, &len, &error);
- check_no_error (&error);
- g_assert (value != NULL);
-
- va_start (args, key);
- i = 0;
- v = va_arg (args, gchar*);
- while (v)
- {
- g_assert (value[i] != NULL);
- g_assert_cmpstr (v, ==, value[i]);
- i++;
- v = va_arg (args, gchar*);
- }
-
- va_end (args);
-
- g_strfreev (value);
-}
-
-static void
-check_locale_string_list_value (GKeyFile *keyfile,
- const gchar *group,
- const gchar *key,
- const gchar *locale,
- ...)
-{
- gint i;
- gchar *v, **value;
- va_list args;
- gsize len;
- GError *error = NULL;
-
- value = g_key_file_get_locale_string_list (keyfile, group, key, locale, &len, &error);
- check_no_error (&error);
- g_assert (value != NULL);
-
- va_start (args, locale);
- i = 0;
- v = va_arg (args, gchar*);
- while (v)
- {
- g_assert (value[i] != NULL);
- g_assert_cmpstr (v, ==, value[i]);
- i++;
- v = va_arg (args, gchar*);
- }
-
- va_end (args);
-
- g_strfreev (value);
-}
-
-static void
-check_integer_list_value (GKeyFile *keyfile,
- const gchar *group,
- const gchar *key,
- ...)
-{
- gint i;
- gint v, *value;
- va_list args;
- gsize len;
- GError *error = NULL;
-
- value = g_key_file_get_integer_list (keyfile, group, key, &len, &error);
- check_no_error (&error);
- g_assert (value != NULL);
-
- va_start (args, key);
- i = 0;
- v = va_arg (args, gint);
- while (v != -100)
- {
- g_assert_cmpint (i, <, len);
- g_assert_cmpint (value[i], ==, v);
- i++;
- v = va_arg (args, gint);
- }
-
- va_end (args);
-
- g_free (value);
-}
-
-static void
-check_double_list_value (GKeyFile *keyfile,
- const gchar *group,
- const gchar *key,
- ...)
-{
- gint i;
- gdouble v, *value;
- va_list args;
- gsize len;
- GError *error = NULL;
-
- value = g_key_file_get_double_list (keyfile, group, key, &len, &error);
- check_no_error (&error);
- g_assert (value != NULL);
-
- va_start (args, key);
- i = 0;
- v = va_arg (args, gdouble);
- while (v != -100)
- {
- g_assert_cmpint (i, <, len);
- g_assert_cmpfloat (value[i], ==, v);
- i++;
- v = va_arg (args, gdouble);
- }
-
- va_end (args);
-
- g_free (value);
-}
-
-static void
-check_boolean_list_value (GKeyFile *keyfile,
- const gchar *group,
- const gchar *key,
- ...)
-{
- gint i;
- gboolean v, *value;
- va_list args;
- gsize len;
- GError *error = NULL;
-
- value = g_key_file_get_boolean_list (keyfile, group, key, &len, &error);
- check_no_error (&error);
- g_assert (value != NULL);
-
- va_start (args, key);
- i = 0;
- v = va_arg (args, gboolean);
- while (v != -100)
- {
- g_assert_cmpint (i, <, len);
- g_assert_cmpint (value[i], ==, v);
- i++;
- v = va_arg (args, gboolean);
- }
-
- va_end (args);
-
- g_free (value);
-}
-
-static void
-check_boolean_value (GKeyFile *keyfile,
- const gchar *group,
- const gchar *key,
- gboolean expected)
-{
- GError *error = NULL;
- gboolean value;
-
- value = g_key_file_get_boolean (keyfile, group, key, &error);
- check_no_error (&error);
- g_assert_cmpint (value, ==, expected);
-}
-
-static void
-check_integer_value (GKeyFile *keyfile,
- const gchar *group,
- const gchar *key,
- gint expected)
-{
- GError *error = NULL;
- gint value;
-
- value = g_key_file_get_integer (keyfile, group, key, &error);
- check_no_error (&error);
- g_assert_cmpint (value, ==, expected);
-}
-
-static void
-check_double_value (GKeyFile *keyfile,
- const gchar *group,
- const gchar *key,
- gdouble expected)
-{
- GError *error = NULL;
- gdouble value;
-
- value = g_key_file_get_double (keyfile, group, key, &error);
- check_no_error (&error);
- g_assert_cmpfloat (value, ==, expected);
-}
-
-static void
-check_name (const gchar *what,
- const gchar *value,
- const gchar *expected,
- gint position)
-{
- g_assert_cmpstr (value, ==, expected);
-}
-
-static void
-check_length (const gchar *what,
- gint n_items,
- gint length,
- gint expected)
-{
- g_assert_cmpint (n_items, ==, length);
- g_assert_cmpint (n_items, ==, expected);
-}
-
-
-/* check that both \n and \r\n are accepted as line ends,
- * and that stray \r are passed through
- */
-static void
-test_line_ends (void)
-{
- GKeyFile *keyfile;
-
- const gchar *data =
- "[group1]\n"
- "key1=value1\n"
- "key2=value2\r\n"
- "[group2]\r\n"
- "key3=value3\r\r\n"
- "key4=value4\n";
-
- keyfile = load_data (data, 0);
-
- check_string_value (keyfile, "group1", "key1", "value1");
- check_string_value (keyfile, "group1", "key2", "value2");
- check_string_value (keyfile, "group2", "key3", "value3\r");
- check_string_value (keyfile, "group2", "key4", "value4");
-
- g_key_file_free (keyfile);
-}
-
-/* check handling of whitespace
- */
-static void
-test_whitespace (void)
-{
- GKeyFile *keyfile;
-
- const gchar *data =
- "[group1]\n"
- "key1 = value1\n"
- "key2\t=\tvalue2\n"
- " [ group2 ] \n"
- "key3 = value3 \n"
- "key4 = value \t4\n"
- " key5 = value5\n";
-
- keyfile = load_data (data, 0);
-
- check_string_value (keyfile, "group1", "key1", "value1");
- check_string_value (keyfile, "group1", "key2", "value2");
- check_string_value (keyfile, " group2 ", "key3", "value3 ");
- check_string_value (keyfile, " group2 ", "key4", "value \t4");
- check_string_value (keyfile, " group2 ", "key5", "value5");
-
- g_key_file_free (keyfile);
-}
-
-/* check handling of comments
- */
-static void
-test_comments (void)
-{
- GKeyFile *keyfile;
- gchar **names;
- gsize len;
- GError *error = NULL;
- gchar *comment;
-
- const gchar *data =
- "# top comment\n"
- "# top comment, continued\n"
- "[group1]\n"
- "key1 = value1\n"
- "# key comment\n"
- "# key comment, continued\n"
- "key2 = value2\n"
- "# line end check\r\n"
- "key3 = value3\n"
- "key4 = value4\n"
- "# group comment\n"
- "# group comment, continued\n"
- "[group2]\n";
-
- const gchar *top_comment= " top comment\n top comment, continued\n";
- const gchar *group_comment= " group comment\n group comment, continued\n";
- const gchar *key_comment= " key comment\n key comment, continued\n";
-
- keyfile = load_data (data, 0);
-
- check_string_value (keyfile, "group1", "key1", "value1");
- check_string_value (keyfile, "group1", "key2", "value2");
- check_string_value (keyfile, "group1", "key3", "value3");
- check_string_value (keyfile, "group1", "key4", "value4");
-
- names = g_key_file_get_keys (keyfile, "group1", &len, &error);
- check_no_error (&error);
-
- check_length ("keys", g_strv_length (names), len, 4);
- check_name ("key", names[0], "key1", 0);
- check_name ("key", names[1], "key2", 1);
- check_name ("key", names[2], "key3", 2);
- check_name ("key", names[3], "key4", 3);
-
- g_strfreev (names);
-
- g_key_file_free (keyfile);
-
- keyfile = load_data (data, G_KEY_FILE_KEEP_COMMENTS);
-
- names = g_key_file_get_keys (keyfile, "group1", &len, &error);
- check_no_error (&error);
-
- check_length ("keys", g_strv_length (names), len, 4);
- check_name ("key", names[0], "key1", 0);
- check_name ("key", names[1], "key2", 1);
- check_name ("key", names[2], "key3", 2);
- check_name ("key", names[3], "key4", 3);
-
- g_strfreev (names);
-
- comment = g_key_file_get_comment (keyfile, NULL, NULL, &error);
- check_no_error (&error);
- check_name ("top comment", comment, top_comment, 0);
- g_free (comment);
-
- comment = g_key_file_get_comment (keyfile, "group1", "key2", &error);
- check_no_error (&error);
- check_name ("key comment", comment, key_comment, 0);
- g_free (comment);
-
- comment = g_key_file_get_comment (keyfile, "group2", NULL, &error);
- check_no_error (&error);
- check_name ("group comment", comment, group_comment, 0);
- g_free (comment);
-
- comment = g_key_file_get_comment (keyfile, "group3", NULL, &error);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
- g_assert (comment == NULL);
-
- g_key_file_free (keyfile);
-}
-
-
-/* check key and group listing */
-static void
-test_listing (void)
-{
- GKeyFile *keyfile;
- gchar **names;
- gsize len;
- gchar *start;
- GError *error = NULL;
-
- const gchar *data =
- "[group1]\n"
- "key1=value1\n"
- "key2=value2\n"
- "[group2]\n"
- "key3=value3\n"
- "key4=value4\n";
-
- keyfile = load_data (data, 0);
-
- names = g_key_file_get_groups (keyfile, &len);
- g_assert (names != NULL);
-
- check_length ("groups", g_strv_length (names), len, 2);
- check_name ("group name", names[0], "group1", 0);
- check_name ("group name", names[1], "group2", 1);
-
- g_strfreev (names);
-
- names = g_key_file_get_keys (keyfile, "group1", &len, &error);
- check_no_error (&error);
-
- check_length ("keys", g_strv_length (names), len, 2);
- check_name ("key", names[0], "key1", 0);
- check_name ("key", names[1], "key2", 1);
-
- g_strfreev (names);
-
- names = g_key_file_get_keys (keyfile, "no-such-group", &len, &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
-
- g_strfreev (names);
-
- g_assert (g_key_file_has_group (keyfile, "group1"));
- g_assert (g_key_file_has_group (keyfile, "group2"));
- g_assert (!g_key_file_has_group (keyfile, "group10"));
- g_assert (!g_key_file_has_group (keyfile, "group20"));
-
- start = g_key_file_get_start_group (keyfile);
- g_assert_cmpstr (start, ==, "group1");
- g_free (start);
-
- g_assert (g_key_file_has_key (keyfile, "group1", "key1", &error));
- check_no_error (&error);
- g_assert (g_key_file_has_key (keyfile, "group2", "key3", &error));
- check_no_error (&error);
- g_assert (!g_key_file_has_key (keyfile, "group2", "no-such-key", NULL));
-
- g_key_file_has_key (keyfile, "no-such-group", "key", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
-
- g_key_file_free (keyfile);
-}
-
-/* check parsing of string values */
-static void
-test_string (void)
-{
- GKeyFile *keyfile;
- GError *error = NULL;
- gchar *value;
-
- const gchar *data =
- "[valid]\n"
- "key1=\\s\\n\\t\\r\\\\\n"
- "key2=\"quoted\"\n"
- "key3='quoted'\n"
- "key4=\xe2\x89\xa0\xe2\x89\xa0\n"
- "[invalid]\n"
- "key1=\\a\\b\\0800xff\n"
- "key2=blabla\\\n";
-
- keyfile = load_data (data, 0);
-
- check_string_value (keyfile, "valid", "key1", " \n\t\r\\");
- check_string_value (keyfile, "valid", "key2", "\"quoted\"");
- check_string_value (keyfile, "valid", "key3", "'quoted'");
- check_string_value (keyfile, "valid", "key4", "\xe2\x89\xa0\xe2\x89\xa0");
-
- value = g_key_file_get_string (keyfile, "invalid", "key1", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
- g_free (value);
-
- value = g_key_file_get_string (keyfile, "invalid", "key2", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
- g_free (value);
-
- g_key_file_free (keyfile);
-}
-
-/* check parsing of boolean values */
-static void
-test_boolean (void)
-{
- GKeyFile *keyfile;
- GError *error = NULL;
-
- const gchar *data =
- "[valid]\n"
- "key1=true\n"
- "key2=false\n"
- "key3=1\n"
- "key4=0\n"
- "[invalid]\n"
- "key1=t\n"
- "key2=f\n"
- "key3=yes\n"
- "key4=no\n";
-
- keyfile = load_data (data, 0);
-
- check_boolean_value (keyfile, "valid", "key1", TRUE);
- check_boolean_value (keyfile, "valid", "key2", FALSE);
- check_boolean_value (keyfile, "valid", "key3", TRUE);
- check_boolean_value (keyfile, "valid", "key4", FALSE);
-
- g_key_file_get_boolean (keyfile, "invalid", "key1", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_get_boolean (keyfile, "invalid", "key2", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_get_boolean (keyfile, "invalid", "key3", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_get_boolean (keyfile, "invalid", "key4", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_free (keyfile);
-}
-
-/* check parsing of integer and double values */
-static void
-test_number (void)
-{
- GKeyFile *keyfile;
- GError *error = NULL;
-
- const gchar *data =
- "[valid]\n"
- "key1=0\n"
- "key2=1\n"
- "key3=-1\n"
- "key4=2324431\n"
- "key5=-2324431\n"
- "key6=000111\n"
- "dkey1=000111\n"
- "dkey2=145.45\n"
- "dkey3=-3453.7\n"
- "[invalid]\n"
- "key1=0xffff\n"
- "key2=0.5\n"
- "key3=1e37\n"
- "key4=ten\n"
- "key5=\n"
- "key6=1.0.0\n"
- "key7=2x2\n"
- "key8=abc\n";
-
- keyfile = load_data (data, 0);
-
- check_integer_value (keyfile, "valid", "key1", 0);
- check_integer_value (keyfile, "valid", "key2", 1);
- check_integer_value (keyfile, "valid", "key3", -1);
- check_integer_value (keyfile, "valid", "key4", 2324431);
- check_integer_value (keyfile, "valid", "key5", -2324431);
- check_integer_value (keyfile, "valid", "key6", 111);
- check_double_value (keyfile, "valid", "dkey1", 111.0);
- check_double_value (keyfile, "valid", "dkey2", 145.45);
- check_double_value (keyfile, "valid", "dkey3", -3453.7);
-
- g_key_file_get_integer (keyfile, "invalid", "key1", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_get_integer (keyfile, "invalid", "key2", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_get_integer (keyfile, "invalid", "key3", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_get_integer (keyfile, "invalid", "key4", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_get_double (keyfile, "invalid", "key5", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_get_double (keyfile, "invalid", "key6", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_get_double (keyfile, "invalid", "key7", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_get_double (keyfile, "invalid", "key8", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
-
- g_key_file_free (keyfile);
-}
-
-/* check handling of translated strings */
-static void
-test_locale_string (void)
-{
- GKeyFile *keyfile;
-
- const gchar *data =
- "[valid]\n"
- "key1=v1\n"
- "key1[de]=v1-de\n"
- "key1[de_DE]=v1-de_DE\n"
- "key1[de_DE.UTF8]=v1-de_DE.UTF8\n"
- "key1[fr]=v1-fr\n"
- "key1[en] =v1-en\n"
- "key1[sr@Latn]=v1-sr\n";
-
- keyfile = load_data (data, G_KEY_FILE_KEEP_TRANSLATIONS);
-
- check_locale_string_value (keyfile, "valid", "key1", "it", "v1");
- check_locale_string_value (keyfile, "valid", "key1", "de", "v1-de");
- check_locale_string_value (keyfile, "valid", "key1", "de_DE", "v1-de_DE");
- check_locale_string_value (keyfile, "valid", "key1", "de_DE.UTF8", "v1-de_DE.UTF8");
- check_locale_string_value (keyfile, "valid", "key1", "fr", "v1-fr");
- check_locale_string_value (keyfile, "valid", "key1", "fr_FR", "v1-fr");
- check_locale_string_value (keyfile, "valid", "key1", "en", "v1-en");
- check_locale_string_value (keyfile, "valid", "key1", "sr@Latn", "v1-sr");
-
- g_key_file_free (keyfile);
-
- /* now test that translations are thrown away */
-
- g_setenv ("LANGUAGE", "de", TRUE);
- setlocale (LC_ALL, "");
-
- keyfile = load_data (data, 0);
-
- check_locale_string_value (keyfile, "valid", "key1", "it", "v1");
- check_locale_string_value (keyfile, "valid", "key1", "de", "v1-de");
- check_locale_string_value (keyfile, "valid", "key1", "de_DE", "v1-de");
- check_locale_string_value (keyfile, "valid", "key1", "de_DE.UTF8", "v1-de");
- check_locale_string_value (keyfile, "valid", "key1", "fr", "v1");
- check_locale_string_value (keyfile, "valid", "key1", "fr_FR", "v1");
- check_locale_string_value (keyfile, "valid", "key1", "en", "v1");
-
- g_key_file_free (keyfile);
-}
-
-static void
-test_lists (void)
-{
- GKeyFile *keyfile;
-
- const gchar *data =
- "[valid]\n"
- "key1=v1;v2\n"
- "key2=v1;v2;\n"
- "key3=v1,v2\n"
- "key4=v1\\;v2\n"
- "key5=true;false\n"
- "key6=1;0;-1\n"
- "key7= 1 ; 0 ; -1 \n"
- "key8=v1\\,v2\n"
- "key9=0;1.3456;-76532.456\n";
-
- keyfile = load_data (data, 0);
-
- check_string_list_value (keyfile, "valid", "key1", "v1", "v2", NULL);
- check_string_list_value (keyfile, "valid", "key2", "v1", "v2", NULL);
- check_string_list_value (keyfile, "valid", "key3", "v1,v2", NULL);
- check_string_list_value (keyfile, "valid", "key4", "v1;v2", NULL);
- check_boolean_list_value (keyfile, "valid", "key5", TRUE, FALSE, -100);
- check_integer_list_value (keyfile, "valid", "key6", 1, 0, -1, -100);
- check_double_list_value (keyfile, "valid", "key9", 0.0, 1.3456, -76532.456, -100.0);
- /* maybe these should be valid */
- /* check_integer_list_value (keyfile, "valid", "key7", 1, 0, -1, -100);*/
- /* check_string_list_value (keyfile, "valid", "key8", "v1\\,v2", NULL);*/
-
- g_key_file_free (keyfile);
-
- /* Now check an alternate separator */
-
- keyfile = load_data (data, 0);
- g_key_file_set_list_separator (keyfile, ',');
-
- check_string_list_value (keyfile, "valid", "key1", "v1;v2", NULL);
- check_string_list_value (keyfile, "valid", "key2", "v1;v2;", NULL);
- check_string_list_value (keyfile, "valid", "key3", "v1", "v2", NULL);
-
- g_key_file_free (keyfile);
-}
-
-static void
-test_lists_set_get (void)
-{
- GKeyFile *keyfile;
- static const char * const strings[] = { "v1", "v2" };
- static const char * const locale_strings[] = { "v1-l", "v2-l" };
- static int integers[] = { 1, -1, 2 };
- static gdouble doubles[] = { 3.14, 2.71 };
-
- keyfile = g_key_file_new ();
- g_key_file_set_string_list (keyfile, "group0", "key1", strings, G_N_ELEMENTS (strings));
- g_key_file_set_locale_string_list (keyfile, "group0", "key1", "de", locale_strings, G_N_ELEMENTS (locale_strings));
- g_key_file_set_integer_list (keyfile, "group0", "key2", integers, G_N_ELEMENTS (integers));
- g_key_file_set_double_list (keyfile, "group0", "key3", doubles, G_N_ELEMENTS (doubles));
-
- check_string_list_value (keyfile, "group0", "key1", strings[0], strings[1], NULL);
- check_locale_string_list_value (keyfile, "group0", "key1", "de", locale_strings[0], locale_strings[1], NULL);
- check_integer_list_value (keyfile, "group0", "key2", integers[0], integers[1], -100);
- check_double_list_value (keyfile, "group0", "key3", doubles[0], doubles[1], -100.0);
- g_key_file_free (keyfile);
-
- /* and again with a different list separator */
- keyfile = g_key_file_new ();
- g_key_file_set_list_separator (keyfile, ',');
- g_key_file_set_string_list (keyfile, "group0", "key1", strings, G_N_ELEMENTS (strings));
- g_key_file_set_locale_string_list (keyfile, "group0", "key1", "de", locale_strings, G_N_ELEMENTS (locale_strings));
- g_key_file_set_integer_list (keyfile, "group0", "key2", integers, G_N_ELEMENTS (integers));
- g_key_file_set_double_list (keyfile, "group0", "key3", doubles, G_N_ELEMENTS (doubles));
-
- check_string_list_value (keyfile, "group0", "key1", strings[0], strings[1], NULL);
- check_locale_string_list_value (keyfile, "group0", "key1", "de", locale_strings[0], locale_strings[1], NULL);
- check_integer_list_value (keyfile, "group0", "key2", integers[0], integers[1], -100);
- check_double_list_value (keyfile, "group0", "key3", doubles[0], doubles[1], -100.0);
- g_key_file_free (keyfile);
-}
-
-static void
-test_group_remove (void)
-{
- GKeyFile *keyfile;
- gchar **names;
- gsize len;
- GError *error = NULL;
-
- const gchar *data =
- "[group1]\n"
- "[group2]\n"
- "key1=bla\n"
- "key2=bla\n"
- "[group3]\n"
- "key1=bla\n"
- "key2=bla\n";
-
- g_test_bug ("165887");
-
- keyfile = load_data (data, 0);
-
- names = g_key_file_get_groups (keyfile, &len);
- g_assert (names != NULL);
-
- check_length ("groups", g_strv_length (names), len, 3);
- check_name ("group name", names[0], "group1", 0);
- check_name ("group name", names[1], "group2", 1);
- check_name ("group name", names[2], "group3", 2);
-
- g_key_file_remove_group (keyfile, "group1", &error);
- check_no_error (&error);
-
- g_strfreev (names);
-
- names = g_key_file_get_groups (keyfile, &len);
- g_assert (names != NULL);
-
- check_length ("groups", g_strv_length (names), len, 2);
- check_name ("group name", names[0], "group2", 0);
- check_name ("group name", names[1], "group3", 1);
-
- g_key_file_remove_group (keyfile, "group2", &error);
- check_no_error (&error);
-
- g_strfreev (names);
-
- names = g_key_file_get_groups (keyfile, &len);
- g_assert (names != NULL);
-
- check_length ("groups", g_strv_length (names), len, 1);
- check_name ("group name", names[0], "group3", 0);
-
- g_key_file_remove_group (keyfile, "no such group", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
-
- g_strfreev (names);
-
- g_key_file_free (keyfile);
-}
-
-static void
-test_key_remove (void)
-{
- GKeyFile *keyfile;
- gchar *value;
- GError *error = NULL;
-
- const gchar *data =
- "[group1]\n"
- "key1=bla\n"
- "key2=bla\n";
-
- g_test_bug ("165980");
-
- keyfile = load_data (data, 0);
-
- check_string_value (keyfile, "group1", "key1", "bla");
-
- g_key_file_remove_key (keyfile, "group1", "key1", &error);
- check_no_error (&error);
-
- value = g_key_file_get_string (keyfile, "group1", "key1", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
- g_free (value);
-
- g_key_file_remove_key (keyfile, "group1", "key1", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
-
- g_key_file_remove_key (keyfile, "no such group", "key1", &error);
- check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
-
- g_key_file_free (keyfile);
-}
-
-
-static void
-test_groups (void)
-{
- GKeyFile *keyfile;
-
- const gchar *data =
- "[1]\n"
- "key1=123\n"
- "[2]\n"
- "key2=123\n";
-
- g_test_bug ("316309");
-
- keyfile = load_data (data, 0);
-
- check_string_value (keyfile, "1", "key1", "123");
- check_string_value (keyfile, "2", "key2", "123");
-
- g_key_file_free (keyfile);
-}
-
-static void
-test_group_names (void)
-{
- GKeyFile *keyfile;
- GError *error = NULL;
- const gchar *data;
- gchar *value;
-
- /* [ in group name */
- data = "[a[b]\n"
- "key1=123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- g_key_file_free (keyfile);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_PARSE);
-
- /* ] in group name */
- data = "[a]b]\n"
- "key1=123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- g_key_file_free (keyfile);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_PARSE);
-
- /* control char in group name */
- data = "[a\tb]\n"
- "key1=123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- g_key_file_free (keyfile);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_PARSE);
-
- /* empty group name */
- data = "[]\n"
- "key1=123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- g_key_file_free (keyfile);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_PARSE);
-
- /* Unicode in group name */
- data = "[\xc2\xbd]\n"
- "key1=123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- g_key_file_free (keyfile);
- check_no_error (&error);
-
- keyfile = g_key_file_new ();
- /*g_key_file_set_string (keyfile, "a[b", "key1", "123");*/
- value = g_key_file_get_string (keyfile, "a[b", "key1", &error);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
- g_key_file_free (keyfile);
-
- keyfile = g_key_file_new ();
- /*g_key_file_set_string (keyfile, "a]b", "key1", "123");*/
- value = g_key_file_get_string (keyfile, "a]b", "key1", &error);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
- g_key_file_free (keyfile);
-
- keyfile = g_key_file_new ();
- /*g_key_file_set_string (keyfile, "a\tb", "key1", "123");*/
- value = g_key_file_get_string (keyfile, "a\tb", "key1", &error);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
- g_key_file_free (keyfile);
-
- keyfile = g_key_file_new ();
- g_key_file_set_string (keyfile, "\xc2\xbd", "key1", "123");
- check_string_value (keyfile, "\xc2\xbd", "key1", "123");
- g_key_file_free (keyfile);
-}
-
-static void
-test_key_names (void)
-{
- GKeyFile *keyfile;
- GError *error = NULL;
- const gchar *data;
- gchar *value;
-
- /* [ in key name */
- data = "[a]\n"
- "key[=123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- g_key_file_free (keyfile);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_PARSE);
-
- /* empty key name */
- data = "[a]\n"
- " =123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- g_key_file_free (keyfile);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_PARSE);
-
- /* empty key name */
- data = "[a]\n"
- " [de] =123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- g_key_file_free (keyfile);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_PARSE);
-
- /* bad locale suffix */
- data = "[a]\n"
- "foo[@#!&%]=123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- g_key_file_free (keyfile);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_PARSE);
-
- /* initial space */
- data = "[a]\n"
- " foo=123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- check_no_error (&error);
- check_string_value (keyfile, "a", "foo", "123");
- g_key_file_free (keyfile);
-
- /* final space */
- data = "[a]\n"
- "foo =123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- check_no_error (&error);
- check_string_value (keyfile, "a", "foo", "123");
- g_key_file_free (keyfile);
-
- /* inner space */
- data = "[a]\n"
- "foo bar=123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- check_no_error (&error);
- check_string_value (keyfile, "a", "foo bar", "123");
- g_key_file_free (keyfile);
-
- /* inner space */
- data = "[a]\n"
- "foo [de] =123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_PARSE);
- g_key_file_free (keyfile);
-
- /* control char in key name */
- data = "[a]\n"
- "key\tfoo=123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- g_key_file_free (keyfile);
- check_no_error (&error);
-
- /* Unicode in key name */
- data = "[a]\n"
- "\xc2\xbd=123\n";
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile, data, -1, 0, &error);
- g_key_file_free (keyfile);
- check_no_error (&error);
-
- keyfile = g_key_file_new ();
- g_key_file_set_string (keyfile, "a", "x", "123");
- /*g_key_file_set_string (keyfile, "a", "key=", "123");*/
- value = g_key_file_get_string (keyfile, "a", "key=", &error);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_KEY_NOT_FOUND);
- g_key_file_free (keyfile);
-
- keyfile = g_key_file_new ();
- g_key_file_set_string (keyfile, "a", "x", "123");
- /*g_key_file_set_string (keyfile, "a", "key[", "123");*/
- value = g_key_file_get_string (keyfile, "a", "key[", &error);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_KEY_NOT_FOUND);
- g_key_file_free (keyfile);
-
- keyfile = g_key_file_new ();
- g_key_file_set_string (keyfile, "a", "x", "123");
- g_key_file_set_string (keyfile, "a", "key\tfoo", "123");
- value = g_key_file_get_string (keyfile, "a", "key\tfoo", &error);
- check_no_error (&error);
- g_key_file_free (keyfile);
-
- keyfile = g_key_file_new ();
- g_key_file_set_string (keyfile, "a", "x", "123");
- /*g_key_file_set_string (keyfile, "a", " key", "123");*/
- value = g_key_file_get_string (keyfile, "a", " key", &error);
- check_error (&error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_KEY_NOT_FOUND);
- g_key_file_free (keyfile);
-
- keyfile = g_key_file_new ();
- g_key_file_set_string (keyfile, "a", "x", "123");
-
- /* Unicode key */
- g_key_file_set_string (keyfile, "a", "\xc2\xbd", "123");
- check_string_value (keyfile, "a", "\xc2\xbd", "123");
-
- /* Keys with / + . (as used by the gnome-vfs mime cache) */
- g_key_file_set_string (keyfile, "a", "foo/bar", "/");
- check_string_value (keyfile, "a", "foo/bar", "/");
- g_key_file_set_string (keyfile, "a", "foo+bar", "+");
- check_string_value (keyfile, "a", "foo+bar", "+");
- g_key_file_set_string (keyfile, "a", "foo.bar", ".");
- check_string_value (keyfile, "a", "foo.bar", ".");
-
- g_key_file_free (keyfile);
-}
-
-static void
-test_duplicate_keys (void)
-{
- GKeyFile *keyfile;
- const gchar *data =
- "[1]\n"
- "key1=123\n"
- "key1=345\n";
-
- keyfile = load_data (data, 0);
- check_string_value (keyfile, "1", "key1", "345");
-
- g_key_file_free (keyfile);
-}
-
-static void
-test_duplicate_groups (void)
-{
- GKeyFile *keyfile;
- const gchar *data =
- "[Desktop Entry]\n"
- "key1=123\n"
- "[Desktop Entry]\n"
- "key2=123\n";
-
- g_test_bug ("157877");
-
- keyfile = load_data (data, 0);
- check_string_value (keyfile, "Desktop Entry", "key1", "123");
- check_string_value (keyfile, "Desktop Entry", "key2", "123");
-
- g_key_file_free (keyfile);
-}
-
-static void
-test_duplicate_groups2 (void)
-{
- GKeyFile *keyfile;
- const gchar *data =
- "[A]\n"
- "foo=bar\n"
- "[B]\n"
- "foo=baz\n"
- "[A]\n"
- "foo=bang\n";
-
- g_test_bug ("385910");
-
- keyfile = load_data (data, 0);
- check_string_value (keyfile, "A", "foo", "bang");
- check_string_value (keyfile, "B", "foo", "baz");
-
- g_key_file_free (keyfile);
-}
-
-static void
-test_reload_idempotency (void)
-{
- static const gchar *original_data=""
- "# Top comment\n"
- "\n"
- "# First comment\n"
- "[first]\n"
- "key=value\n"
- "# A random comment in the first group\n"
- "anotherkey=anothervalue\n"
- "# Second comment - one line\n"
- "[second]\n"
- "# Third comment - two lines\n"
- "# Third comment - two lines\n"
- "[third]\n"
- "blank_line=1\n"
- "\n"
- "blank_lines=2\n"
- "\n\n"
- "[fourth]\n"
- "[fifth]\n";
- GKeyFile *keyfile;
- GError *error = NULL;
- gchar *data1, *data2;
- gsize len1, len2;
-
- g_test_bug ("420686");
-
- /* check that we only insert a single new line between groups */
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile,
- original_data, strlen(original_data),
- G_KEY_FILE_KEEP_COMMENTS,
- &error);
- check_no_error (&error);
-
- data1 = g_key_file_to_data (keyfile, &len1, &error);
- g_assert (data1 != NULL);
- g_key_file_free (keyfile);
-
- keyfile = g_key_file_new ();
- g_key_file_load_from_data (keyfile,
- data1, len1,
- G_KEY_FILE_KEEP_COMMENTS,
- &error);
- check_no_error (&error);
-
- data2 = g_key_file_to_data (keyfile, &len2, &error);
- g_assert (data2 != NULL);
- g_key_file_free (keyfile);
-
- g_assert_cmpstr (data1, ==, data2);
-
- g_free (data2);
- g_free (data1);
-}
-
-int
-main (int argc, char *argv[])
-{
- g_test_init (&argc, &argv, NULL);
- g_test_bug_base ("http://bugzilla.gnome.org/");
-
- g_test_add_func ("/keyfile/line-ends", test_line_ends);
- g_test_add_func ("/keyfile/whitespace", test_whitespace);
- g_test_add_func ("/keyfile/comments", test_comments);
- g_test_add_func ("/keyfile/listing", test_listing);
- g_test_add_func ("/keyfile/string", test_string);
- g_test_add_func ("/keyfile/boolean", test_boolean);
- g_test_add_func ("/keyfile/number", test_number);
- g_test_add_func ("/keyfile/locale-string", test_locale_string);
- g_test_add_func ("/keyfile/lists", test_lists);
- g_test_add_func ("/keyfile/lists-set-get", test_lists_set_get);
- g_test_add_func ("/keyfile/group-remove", test_group_remove);
- g_test_add_func ("/keyfile/key-remove", test_key_remove);
- g_test_add_func ("/keyfile/groups", test_groups);
- g_test_add_func ("/keyfile/duplicate-keys", test_duplicate_keys);
- g_test_add_func ("/keyfile/duplicate-groups", test_duplicate_groups);
- g_test_add_func ("/keyfile/duplicate-groups2", test_duplicate_groups2);
- g_test_add_func ("/keyfile/group-names", test_group_names);
- g_test_add_func ("/keyfile/key-names", test_key_names);
- g_test_add_func ("/keyfile/reload", test_reload_idempotency);
-
- return g_test_run ();
-}
diff --git a/glib/tests/markup-subparser.c b/glib/tests/markup-subparser.c
deleted file mode 100644
index 0b3c746d2..000000000
--- a/glib/tests/markup-subparser.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright © 2008 Ryan Lortie
- *
- * This program 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 of the
- * License, or (at your option) any later version.
- *
- * See the included COPYING file for more information.
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <glib.h>
-
-/* keep track of GString instances to make sure nothing leaks */
-static int strings_allocated;
-
-/* === the GMarkupParser functions === */
-static void
-subparser_start_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer user_data,
- GError **error)
-{
- g_string_append_printf (user_data, "{%s}", element_name);
-
- /* we don't like trouble... */
- if (strcmp (element_name, "trouble") == 0)
- g_set_error (error, 0, 0, "we don't like trouble");
-}
-
-static void
-subparser_end_element (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer user_data,
- GError **error)
-{
- g_string_append_printf (user_data, "{/%s}", element_name);
-}
-
-static void
-subparser_error (GMarkupParseContext *context,
- GError *error,
- gpointer user_data)
-{
- g_string_free (user_data, TRUE);
- strings_allocated--;
-}
-
-static GMarkupParser subparser_parser =
-{
- subparser_start_element,
- subparser_end_element,
- NULL,
- NULL,
- subparser_error
-};
-
-/* convenience functions for a parser that does not
- * replay the starting tag into the subparser...
- */
-static void
-subparser_start (GMarkupParseContext *ctx)
-{
- gpointer user_data;
-
- user_data = g_string_new (NULL);
- strings_allocated++;
- g_markup_parse_context_push (ctx, &subparser_parser, user_data);
-}
-
-static char *
-subparser_end (GMarkupParseContext *ctx,
- GError **error)
-{
- GString *string;
- char *result;
-
- string = g_markup_parse_context_pop (ctx);
- result = string->str;
-
- g_string_free (string, FALSE);
- strings_allocated--;
-
- if (result == NULL || result[0] == '\0')
- {
- g_free (result);
- g_set_error (error, 0, 0, "got no data");
-
- return NULL;
- }
-
- return result;
-}
-
-/* convenience functions for a parser that -does-
- * replay the starting tag into the subparser...
- */
-static gboolean
-replay_parser_start (GMarkupParseContext *ctx,
- const char *element_name,
- const char **attribute_names,
- const char **attribute_values,
- GError **error)
-{
- GError *tmp_error = NULL;
- gpointer user_data;
-
- user_data = g_string_new (NULL);
- strings_allocated++;
-
- subparser_parser.start_element (ctx, element_name,
- attribute_names, attribute_values,
- user_data, &tmp_error);
-
- if (tmp_error)
- {
- g_propagate_error (error, tmp_error);
- g_string_free (user_data, TRUE);
- strings_allocated--;
-
- return FALSE;
- }
-
- g_markup_parse_context_push (ctx, &subparser_parser, user_data);
-
- return TRUE;
-}
-
-static char *
-replay_parser_end (GMarkupParseContext *ctx,
- GError **error)
-{
- GError *tmp_error = NULL;
- GString *string;
- char *result;
-
- string = g_markup_parse_context_pop (ctx);
-
- subparser_parser.end_element (ctx, g_markup_parse_context_get_element (ctx),
- string, &tmp_error);
-
- if (tmp_error)
- {
- g_propagate_error (error, tmp_error);
- g_string_free (string, TRUE);
- strings_allocated--;
-
- return FALSE;
- }
-
- result = string->str;
-
- g_string_free (string, FALSE);
- strings_allocated--;
-
- if (result == NULL || result[0] == '\0')
- {
- g_free (result);
- g_set_error (error, 0, 0, "got no data");
-
- return NULL;
- }
-
- return result;
-}
-
-
-/* === start interface between subparser and calling parser === */
-static void subparser_start (GMarkupParseContext *ctx);
-static char *subparser_end (GMarkupParseContext *ctx,
- GError **error);
-/* === end interface between subparser and calling parser === */
-
-/* === start interface between replay parser and calling parser === */
-static gboolean replay_parser_start (GMarkupParseContext *ctx,
- const char *element_name,
- const char **attribute_names,
- const char **attribute_values,
- GError **error);
-static char *replay_parser_end (GMarkupParseContext *ctx,
- GError **error);
-/* === end interface between replay parser and calling parser === */
-
-
-
-/* now comes our parser for the test.
- *
- * we recognise the tags <test> and <sub>.
- * <test> is ignored.
- * <sub> invokes the subparser (no replay).
- *
- * "unknown tags" are passed to the reply subparser
- * (so the unknown tag is fed to the subparser...)
- */
-static void
-start_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer user_data,
- GError **error)
-{
- g_string_append_printf (user_data, "<%s>", element_name);
-
- if (strcmp (element_name, "test") == 0)
- {
- /* do nothing */
- }
- else if (strcmp (element_name, "sub") == 0)
- {
- /* invoke subparser */
- subparser_start (context);
- }
- else
- {
- /* unknown tag. invoke replay subparser */
- if (!replay_parser_start (context, element_name,
- attribute_names, attribute_values,
- error))
- return;
- }
-}
-
-static void
-end_element (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer user_data,
- GError **error)
-{
- if (strcmp (element_name, "test") == 0)
- {
- /* do nothing */
- }
- else if (strcmp (element_name, "sub") == 0)
- {
- char *result;
-
- if ((result = subparser_end (context, error)) == NULL)
- return;
-
- g_string_append_printf (user_data, "<<%s>>", result);
- g_free (result);
- }
- else
- {
- char *result;
-
- if ((result = replay_parser_end (context, error)) == NULL)
- return;
-
- g_string_append_printf (user_data, "[[%s]]", result);
- g_free (result);
- }
-
- g_string_append_printf (user_data, "</%s>", element_name);
-}
-
-static GMarkupParser parser =
-{
- start_element,
- end_element
-};
-
-typedef struct
-{
- const char *markup;
- const char *result;
- const char *error_message;
-} TestCase;
-
-void
-test (gconstpointer user_data)
-{
- const TestCase *tc = user_data;
- GMarkupParseContext *ctx;
- GString *string;
- gboolean result;
- GError *error;
-
- error = NULL;
- string = g_string_new (NULL);
- ctx = g_markup_parse_context_new (&parser, 0, string, NULL);
- result = g_markup_parse_context_parse (ctx, tc->markup,
- strlen (tc->markup), &error);
- if (result)
- result = g_markup_parse_context_end_parse (ctx, &error);
- g_markup_parse_context_free (ctx);
- g_assert (strings_allocated == 0);
-
- if (result)
- {
- if (tc->error_message)
- g_error ("expected failure (about '%s') passed!\n"
- " in: %s\n out: %s",
- tc->error_message, tc->markup, string->str);
- }
- else
- {
- if (!tc->error_message)
- g_error ("unexpected failure: '%s'\n"
- " in: %s\n out: %s",
- error->message, tc->markup, string->str);
-
- if (!strstr (error->message, tc->error_message))
- g_error ("failed for the wrong reason.\n"
- " expecting message about '%s'\n"
- " got message '%s'\n"
- " in: %s\n out: %s",
- tc->error_message, error->message, tc->markup, string->str);
- }
-
- if (strcmp (string->str, tc->result) != 0)
- g_error ("got the wrong result.\n"
- " expected: '%s'\n"
- " got: '%s'\n"
- " input: %s",
- tc->result, string->str, tc->markup);
-
- if (error)
- g_error_free (error);
-
- g_string_free (string, TRUE);
-}
-
-TestCase test_cases[] = /* successful runs */
-{
- /* in */ /* out */
- { "<test/>", "<test></test>" },
- { "<sub><foo/></sub>", "<sub><<{foo}{/foo}>></sub>" },
- { "<sub><foo/><bar/></sub>", "<sub><<{foo}{/foo}{bar}{/bar}>></sub>" },
- { "<foo><bar/></foo>", "<foo>[[{foo}{bar}{/bar}{/foo}]]</foo>" },
- { "<foo><x/><y/></foo>", "<foo>[[{foo}{x}{/x}{y}{/y}{/foo}]]</foo>" },
- { "<foo/>", "<foo>[[{foo}{/foo}]]</foo>" },
- { "<sub><foo/></sub><bar/>", "<sub><<{foo}{/foo}>></sub>"
- "<bar>[[{bar}{/bar}]]</bar>" }
-};
-
-TestCase error_cases[] = /* error cases */
-{
- /* in */ /* out */ /* error */
- { "<foo><>", "<foo>", ">"},
- { "", "", "empty" },
- { "<trouble/>", "<trouble>", "trouble" },
- { "<sub><trouble>", "<sub>", "trouble" },
- { "<foo><trouble>", "<foo>", "trouble" },
- { "<sub></sub>", "<sub>", "no data" },
- { "<sub/>", "<sub>", "no data" }
-};
-
-#define add_tests(func, basename, array) \
- G_STMT_START { \
- int __add_tests_i; \
- \
- for (__add_tests_i = 0; \
- __add_tests_i < G_N_ELEMENTS (array); \
- __add_tests_i++) \
- { \
- char *testname; \
- \
- testname = g_strdup_printf ("%s/%d", basename, __add_tests_i); \
- g_test_add_data_func (testname, &array[__add_tests_i], func); \
- g_free (testname); \
- } \
- } G_STMT_END
-
-int
-main (int argc, char **argv)
-{
- g_test_init (&argc, &argv, NULL);
- add_tests (test, "/glib/markup/subparser/success", test_cases);
- add_tests (test, "/glib/markup/subparser/failure", error_cases);
- return g_test_run ();
-}
diff --git a/glib/tests/option-context.c b/glib/tests/option-context.c
deleted file mode 100644
index 913ad5c84..000000000
--- a/glib/tests/option-context.c
+++ /dev/null
@@ -1,1794 +0,0 @@
-/* Unit tests for GOptionContext
- * Copyright (C) 2007 Openismus GmbH
- * Authors: Mathias Hasselmann
- *
- * This work is provided "as is"; redistribution and modification
- * in whole or in part, in any medium, physical or electronic is
- * permitted without restriction.
- *
- * This work 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.
- *
- * In no event shall the authors or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even
- * if advised of the possibility of such damage.
- */
-
-#include <glib.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <locale.h>
-
-static void
-group_captions (void)
-{
- gchar *help_variants[] = { "--help", "--help-all", "--help-test" };
-
- GOptionEntry main_entries[] = {
- { "main-switch", 0,
- G_OPTION_FLAG_NO_ARG,
- G_OPTION_ARG_NONE, NULL,
- "A switch that is in the main group", NULL },
- { NULL }
- };
-
- GOptionEntry group_entries[] = {
- { "test-switch", 0,
- G_OPTION_FLAG_NO_ARG,
- G_OPTION_ARG_NONE, NULL,
- "A switch that is in the test group", NULL },
- { NULL }
- };
-
- gint i, j;
-
- g_test_bug ("504142");
-
- for (i = 0; i < 4; ++i)
- {
- gboolean have_main_entries = (0 != (i & 1));
- gboolean have_test_entries = (0 != (i & 2));
-
- GOptionContext *options;
- GOptionGroup *group = NULL;
-
- options = g_option_context_new (NULL);
-
- if (have_main_entries)
- g_option_context_add_main_entries (options, main_entries, NULL);
- if (have_test_entries)
- {
- group = g_option_group_new ("test", "Test Options",
- "Show all test options",
- NULL, NULL);
- g_option_context_add_group (options, group);
- g_option_group_add_entries (group, group_entries);
- }
-
- for (j = 0; j < G_N_ELEMENTS (help_variants); ++j)
- {
- GTestTrapFlags trap_flags = 0;
- gchar *args[3];
-
- args[0] = __FILE__;
- args[1] = help_variants[j];
- args[2] = NULL;
-
- if (!g_test_verbose ())
- trap_flags |= G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR;
-
- g_test_message ("test setup: args='%s', main-entries=%d, test-entries=%d",
- args[1], have_main_entries, have_test_entries);
-
- if (g_test_trap_fork (0, trap_flags))
- {
- gchar **argv = args;
- gint argc = 2;
- GError *error = NULL;
-
- g_setenv ("LANG", "C", TRUE);
-
- g_option_context_parse (options, &argc, &argv, &error);
- exit(0);
- }
- else
- {
- gboolean expect_main_description = FALSE;
- gboolean expect_main_switch = FALSE;
-
- gboolean expect_test_description = FALSE;
- gboolean expect_test_switch = FALSE;
- gboolean expect_test_group = FALSE;
-
- g_test_trap_assert_passed ();
- g_test_trap_assert_stderr ("");
-
- switch (j)
- {
- case 0:
- g_assert_cmpstr ("--help", ==, args[1]);
- expect_main_switch = have_main_entries;
- expect_test_group = have_test_entries;
- break;
-
- case 1:
- g_assert_cmpstr ("--help-all", ==, args[1]);
- expect_main_switch = have_main_entries;
- expect_test_switch = have_test_entries;
- expect_test_group = have_test_entries;
- break;
-
- case 2:
- g_assert_cmpstr ("--help-test", ==, args[1]);
- expect_test_switch = have_test_entries;
- break;
-
- default:
- g_assert_not_reached ();
- break;
- }
-
- expect_main_description |= expect_main_switch;
- expect_test_description |= expect_test_switch;
-
- if (expect_main_description)
- g_test_trap_assert_stdout ("*Application Options*");
- else
- g_test_trap_assert_stdout_unmatched ("*Application Options*");
- if (expect_main_switch)
- g_test_trap_assert_stdout ("*--main-switch*");
- else
- g_test_trap_assert_stdout_unmatched ("*--main-switch*");
-
- if (expect_test_description)
- g_test_trap_assert_stdout ("*Test Options*");
- else
- g_test_trap_assert_stdout_unmatched ("*Test Options*");
- if (expect_test_switch)
- g_test_trap_assert_stdout ("*--test-switch*");
- else
- g_test_trap_assert_stdout_unmatched ("*--test-switch*");
-
- if (expect_test_group)
- g_test_trap_assert_stdout ("*--help-test*");
- else
- g_test_trap_assert_stdout_unmatched ("*--help-test*");
- }
- }
- }
-}
-
-int error_test1_int;
-char *error_test2_string;
-gboolean error_test3_boolean;
-
-int arg_test1_int;
-gchar *arg_test2_string;
-gchar *arg_test3_filename;
-gdouble arg_test4_double;
-gdouble arg_test5_double;
-gint64 arg_test6_int64;
-gint64 arg_test6_int64_2;
-
-gchar *callback_test1_string;
-int callback_test2_int;
-
-gchar *callback_test_optional_string;
-gboolean callback_test_optional_boolean;
-
-gchar **array_test1_array;
-
-gboolean ignore_test1_boolean;
-gboolean ignore_test2_boolean;
-gchar *ignore_test3_string;
-
-gchar **
-split_string (const char *str, int *argc)
-{
- gchar **argv;
- int len;
-
- argv = g_strsplit (str, " ", 0);
-
- for (len = 0; argv[len] != NULL; len++);
-
- if (argc)
- *argc = len;
-
- return argv;
-}
-
-gchar *
-join_stringv (int argc, char **argv)
-{
- int i;
- GString *str;
-
- str = g_string_new (NULL);
-
- for (i = 0; i < argc; i++)
- {
- g_string_append (str, argv[i]);
-
- if (i < argc - 1)
- g_string_append_c (str, ' ');
- }
-
- return g_string_free (str, FALSE);
-}
-
-/* Performs a shallow copy */
-char **
-copy_stringv (char **argv, int argc)
-{
- return g_memdup (argv, sizeof (char *) * (argc + 1));
-}
-
-
-static gboolean
-error_test1_pre_parse (GOptionContext *context,
- GOptionGroup *group,
- gpointer data,
- GError **error)
-{
- g_assert (error_test1_int == 0x12345678);
-
- return TRUE;
-}
-
-static gboolean
-error_test1_post_parse (GOptionContext *context,
- GOptionGroup *group,
- gpointer data,
- GError **error)
-{
- g_assert (error_test1_int == 20);
-
- /* Set an error in the post hook */
- g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
-
- return FALSE;
-}
-
-void
-error_test1 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionGroup *main_group;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_INT, &error_test1_int, NULL, NULL },
- { NULL } };
-
- error_test1_int = 0x12345678;
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Set pre and post parse hooks */
- main_group = g_option_context_get_main_group (context);
- g_option_group_set_parse_hooks (main_group,
- error_test1_pre_parse, error_test1_post_parse);
-
- /* Now try parsing */
- argv = split_string ("program --test 20", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- g_assert (retval == FALSE);
-
- /* On failure, values should be reset */
- g_assert (error_test1_int == 0x12345678);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-static gboolean
-error_test2_pre_parse (GOptionContext *context,
- GOptionGroup *group,
- gpointer data,
- GError **error)
-{
- g_assert (strcmp (error_test2_string, "foo") == 0);
-
- return TRUE;
-}
-
-static gboolean
-error_test2_post_parse (GOptionContext *context,
- GOptionGroup *group,
- gpointer data,
- GError **error)
-{
- g_assert (strcmp (error_test2_string, "bar") == 0);
-
- /* Set an error in the post hook */
- g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
-
- return FALSE;
-}
-
-void
-error_test2 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionGroup *main_group;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_STRING, &error_test2_string, NULL, NULL },
- { NULL } };
-
- error_test2_string = "foo";
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Set pre and post parse hooks */
- main_group = g_option_context_get_main_group (context);
- g_option_group_set_parse_hooks (main_group,
- error_test2_pre_parse, error_test2_post_parse);
-
- /* Now try parsing */
- argv = split_string ("program --test bar", &argc);
- retval = g_option_context_parse (context, &argc, &argv, &error);
-
- g_error_free (error);
- g_assert (retval == FALSE);
-
- g_assert (strcmp (error_test2_string, "foo") == 0);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-static gboolean
-error_test3_pre_parse (GOptionContext *context,
- GOptionGroup *group,
- gpointer data,
- GError **error)
-{
- g_assert (!error_test3_boolean);
-
- return TRUE;
-}
-
-static gboolean
-error_test3_post_parse (GOptionContext *context,
- GOptionGroup *group,
- gpointer data,
- GError **error)
-{
- g_assert (error_test3_boolean);
-
- /* Set an error in the post hook */
- g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, " ");
-
- return FALSE;
-}
-
-void
-error_test3 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionGroup *main_group;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_NONE, &error_test3_boolean, NULL, NULL },
- { NULL } };
-
- error_test3_boolean = FALSE;
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Set pre and post parse hooks */
- main_group = g_option_context_get_main_group (context);
- g_option_group_set_parse_hooks (main_group,
- error_test3_pre_parse, error_test3_post_parse);
-
- /* Now try parsing */
- argv = split_string ("program --test", &argc);
- retval = g_option_context_parse (context, &argc, &argv, &error);
-
- g_error_free (error);
- g_assert (retval == FALSE);
-
- g_assert (!error_test3_boolean);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-static void
-assert_no_error (GError *error)
-{
- if (error)
- {
- fprintf (stderr, "unexpected error: %s, %d, %s\n", g_quark_to_string (error->domain), error->code, error->message);
- exit (1);
- }
-}
-
-void
-arg_test1 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_INT, &arg_test1_int, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test 20 --test 30", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Last arg specified is the one that should be stored */
- g_assert (arg_test1_int == 30);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-arg_test2 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_STRING, &arg_test2_string, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test foo --test bar", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Last arg specified is the one that should be stored */
- g_assert (strcmp (arg_test2_string, "bar") == 0);
-
- g_free (arg_test2_string);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-arg_test3 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_FILENAME, &arg_test3_filename, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test foo.txt", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Last arg specified is the one that should be stored */
- g_assert (strcmp (arg_test3_filename, "foo.txt") == 0);
-
- g_free (arg_test3_filename);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-
-void
-arg_test4 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &arg_test4_double, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test 20.0 --test 30.03", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Last arg specified is the one that should be stored */
- g_assert (arg_test4_double == 30.03);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-arg_test5 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- char *old_locale, *current_locale;
- const char *locale = "de_DE";
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &arg_test5_double, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test 20,0 --test 30,03", &argc);
-
- /* set it to some locale that uses commas instead of decimal points */
-
- old_locale = g_strdup (setlocale (LC_NUMERIC, locale));
- current_locale = setlocale (LC_NUMERIC, NULL);
- if (strcmp (current_locale, locale) != 0)
- {
- fprintf (stderr, "Cannot set locale to %s, skipping\n", locale);
- goto cleanup;
- }
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Last arg specified is the one that should be stored */
- g_assert (arg_test5_double == 30.03);
-
- cleanup:
- setlocale (LC_NUMERIC, old_locale);
- g_free (old_locale);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-arg_test6 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_INT64, &arg_test6_int64, NULL, NULL },
- { "test2", 0, 0, G_OPTION_ARG_INT64, &arg_test6_int64_2, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test 4294967297 --test 4294967296 --test2 0xfffffffff", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Last arg specified is the one that should be stored */
- g_assert (arg_test6_int64 == G_GINT64_CONSTANT(4294967296));
- g_assert (arg_test6_int64_2 == G_GINT64_CONSTANT(0xfffffffff));
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-static gboolean
-callback_parse1 (const gchar *option_name, const gchar *value,
- gpointer data, GError **error)
-{
- callback_test1_string = g_strdup (value);
- return TRUE;
-}
-
-void
-callback_test1 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_CALLBACK, callback_parse1, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test foo.txt", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (strcmp (callback_test1_string, "foo.txt") == 0);
-
- g_free (callback_test1_string);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-static gboolean
-callback_parse2 (const gchar *option_name, const gchar *value,
- gpointer data, GError **error)
-{
- callback_test2_int++;
- return TRUE;
-}
-
-void
-callback_test2 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, callback_parse2, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test --test", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (callback_test2_int == 2);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-static gboolean
-callback_parse_optional (const gchar *option_name, const gchar *value,
- gpointer data, GError **error)
-{
- callback_test_optional_boolean = TRUE;
- if (value)
- callback_test_optional_string = g_strdup (value);
- else
- callback_test_optional_string = NULL;
- return TRUE;
-}
-
-void
-callback_test_optional_1 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
- callback_parse_optional, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test foo.txt", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (strcmp (callback_test_optional_string, "foo.txt") == 0);
-
- g_assert (callback_test_optional_boolean);
-
- g_free (callback_test_optional_string);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-callback_test_optional_2 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
- callback_parse_optional, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (callback_test_optional_string == NULL);
-
- g_assert (callback_test_optional_boolean);
-
- g_free (callback_test_optional_string);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-callback_test_optional_3 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
- callback_parse_optional, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program -t foo.txt", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (strcmp (callback_test_optional_string, "foo.txt") == 0);
-
- g_assert (callback_test_optional_boolean);
-
- g_free (callback_test_optional_string);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-
-void
-callback_test_optional_4 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
- callback_parse_optional, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program -t", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (callback_test_optional_string == NULL);
-
- g_assert (callback_test_optional_boolean);
-
- g_free (callback_test_optional_string);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-callback_test_optional_5 (void)
-{
- GOptionContext *context;
- gboolean dummy;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
- { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
- callback_parse_optional, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test --dummy", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (callback_test_optional_string == NULL);
-
- g_assert (callback_test_optional_boolean);
-
- g_free (callback_test_optional_string);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-callback_test_optional_6 (void)
-{
- GOptionContext *context;
- gboolean dummy;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
- { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
- callback_parse_optional, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program -t -d", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (callback_test_optional_string == NULL);
-
- g_assert (callback_test_optional_boolean);
-
- g_free (callback_test_optional_string);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-callback_test_optional_7 (void)
-{
- GOptionContext *context;
- gboolean dummy;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
- { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
- callback_parse_optional, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program -td", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (callback_test_optional_string == NULL);
-
- g_assert (callback_test_optional_boolean);
-
- g_free (callback_test_optional_string);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-callback_test_optional_8 (void)
-{
- GOptionContext *context;
- gboolean dummy;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL },
- { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
- callback_parse_optional, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program -dt foo.txt", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (callback_test_optional_string);
-
- g_assert (callback_test_optional_boolean);
-
- g_free (callback_test_optional_string);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-static GPtrArray *callback_remaining_args;
-static gboolean
-callback_remaining_test1_callback (const gchar *option_name, const gchar *value,
- gpointer data, GError **error)
-{
- g_ptr_array_add (callback_remaining_args, g_strdup (value));
- return TRUE;
-}
-
-void
-callback_remaining_test1 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_CALLBACK, callback_remaining_test1_callback, NULL, NULL },
- { NULL } };
-
- callback_remaining_args = g_ptr_array_new ();
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program foo.txt blah.txt", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (callback_remaining_args->len == 2);
- g_assert (strcmp (callback_remaining_args->pdata[0], "foo.txt") == 0);
- g_assert (strcmp (callback_remaining_args->pdata[1], "blah.txt") == 0);
-
- g_ptr_array_foreach (callback_remaining_args, (GFunc) g_free, NULL);
- g_ptr_array_free (callback_remaining_args, TRUE);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-static gboolean
-callback_error (const gchar *option_name, const gchar *value,
- gpointer data, GError **error)
-{
- g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "42");
- return FALSE;
-}
-
-static void
-callback_returns_false (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "error", 0, 0, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL },
- { "error-no-arg", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL },
- { "error-optional-arg", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --error value", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
- g_assert (retval == FALSE);
-
- g_option_context_free (context);
- g_clear_error (&error);
-
- /* And again, this time with a no-arg variant */
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- argv = split_string ("program --error-no-arg", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
- g_assert (retval == FALSE);
-
- g_option_context_free (context);
- g_clear_error (&error);
-
- /* And again, this time with a optional arg variant, with argument */
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- argv = split_string ("program --error-optional-arg value", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
- g_assert (retval == FALSE);
-
- g_option_context_free (context);
- g_clear_error (&error);
-
- /* And again, this time with a optional arg variant, without argument */
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- argv = split_string ("program --error-optional-arg", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- g_assert_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE);
- g_assert (retval == FALSE);
-
- g_option_context_free (context);
- g_clear_error (&error);
-}
-
-
-void
-ignore_test1 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv, **argv_copy;
- int argc;
- gchar *arg;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_set_ignore_unknown_options (context, TRUE);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test --hello", &argc);
- argv_copy = copy_stringv (argv, argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- arg = join_stringv (argc, argv);
- g_assert (strcmp (arg, "program --hello") == 0);
-
- g_free (arg);
- g_strfreev (argv_copy);
- g_free (argv);
- g_option_context_free (context);
-}
-
-void
-ignore_test2 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- gchar *arg;
- GOptionEntry entries [] =
- { { "test", 't', 0, G_OPTION_ARG_NONE, &ignore_test2_boolean, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_set_ignore_unknown_options (context, TRUE);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program -test", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- arg = join_stringv (argc, argv);
- g_assert (strcmp (arg, "program -es") == 0);
-
- g_free (arg);
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-ignore_test3 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv, **argv_copy;
- int argc;
- gchar *arg;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_STRING, &ignore_test3_string, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_set_ignore_unknown_options (context, TRUE);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test foo --hello", &argc);
- argv_copy = copy_stringv (argv, argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- arg = join_stringv (argc, argv);
- g_assert (strcmp (arg, "program --hello") == 0);
-
- g_assert (strcmp (ignore_test3_string, "foo") == 0);
- g_free (ignore_test3_string);
-
- g_free (arg);
- g_strfreev (argv_copy);
- g_free (argv);
- g_option_context_free (context);
-}
-
-void
-array_test1 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] =
- { { "test", 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test foo --test bar", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- g_assert (strcmp (array_test1_array[0], "foo") == 0);
- g_assert (strcmp (array_test1_array[1], "bar") == 0);
- g_assert (array_test1_array[2] == NULL);
-
- g_strfreev (array_test1_array);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-add_test1 (void)
-{
- GOptionContext *context;
-
- GOptionEntry entries1 [] =
- { { "test1", 0, 0, G_OPTION_ARG_STRING_ARRAY, NULL, NULL, NULL },
- { NULL } };
- GOptionEntry entries2 [] =
- { { "test2", 0, 0, G_OPTION_ARG_STRING_ARRAY, NULL, NULL, NULL },
- { NULL } };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries1, NULL);
- g_option_context_add_main_entries (context, entries2, NULL);
-
- g_option_context_free (context);
-}
-
-void
-empty_test1 (void)
-{
- GOptionContext *context;
- GOptionEntry entries [] =
- { { NULL } };
- char *prgname;
-
- g_set_prgname (NULL);
- context = g_option_context_new (NULL);
-
- g_option_context_add_main_entries (context, entries, NULL);
-
- g_option_context_parse (context, NULL, NULL, NULL);
-
- prgname = g_get_prgname ();
- g_assert (prgname && strcmp (prgname, "<unknown>") == 0);
-
- g_option_context_free (context);
-}
-
-void
-empty_test2 (void)
-{
- GOptionContext *context;
-
- context = g_option_context_new (NULL);
- g_option_context_parse (context, NULL, NULL, NULL);
-
- g_option_context_free (context);
-}
-
-void
-empty_test3 (void)
-{
- GOptionContext *context;
- gint argc;
- gchar **argv;
-
- argc = 0;
- argv = NULL;
-
- context = g_option_context_new (NULL);
- g_option_context_parse (context, &argc, &argv, NULL);
-
- g_option_context_free (context);
-}
-
-/* check that non-option arguments are left in argv by default */
-void
-rest_test1 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] = {
- { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
- { NULL }
- };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program foo --test bar", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- g_assert (ignore_test1_boolean);
- g_assert (strcmp (argv[0], "program") == 0);
- g_assert (strcmp (argv[1], "foo") == 0);
- g_assert (strcmp (argv[2], "bar") == 0);
- g_assert (argv[3] == NULL);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-/* check that -- works */
-void
-rest_test2 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] = {
- { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
- { NULL }
- };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program foo --test -- -bar", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- g_assert (ignore_test1_boolean);
- g_assert (strcmp (argv[0], "program") == 0);
- g_assert (strcmp (argv[1], "foo") == 0);
- g_assert (strcmp (argv[2], "--") == 0);
- g_assert (strcmp (argv[3], "-bar") == 0);
- g_assert (argv[4] == NULL);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-/* check that -- stripping works */
-void
-rest_test2a (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] = {
- { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
- { NULL }
- };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program foo --test -- bar", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- g_assert (ignore_test1_boolean);
- g_assert (strcmp (argv[0], "program") == 0);
- g_assert (strcmp (argv[1], "foo") == 0);
- g_assert (strcmp (argv[2], "bar") == 0);
- g_assert (argv[3] == NULL);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-rest_test2b (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] = {
- { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
- { NULL }
- };
-
- context = g_option_context_new (NULL);
- g_option_context_set_ignore_unknown_options (context, TRUE);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program foo --test -bar --", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- g_assert (ignore_test1_boolean);
- g_assert (strcmp (argv[0], "program") == 0);
- g_assert (strcmp (argv[1], "foo") == 0);
- g_assert (strcmp (argv[2], "-bar") == 0);
- g_assert (argv[3] == NULL);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-rest_test2c (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] = {
- { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
- { NULL }
- };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test foo -- bar", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- g_assert (ignore_test1_boolean);
- g_assert (strcmp (argv[0], "program") == 0);
- g_assert (strcmp (argv[1], "foo") == 0);
- g_assert (strcmp (argv[2], "bar") == 0);
- g_assert (argv[3] == NULL);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-rest_test2d (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] = {
- { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
- { NULL }
- };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test -- -bar", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- g_assert (ignore_test1_boolean);
- g_assert (strcmp (argv[0], "program") == 0);
- g_assert (strcmp (argv[1], "--") == 0);
- g_assert (strcmp (argv[2], "-bar") == 0);
- g_assert (argv[3] == NULL);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-
-/* check that G_OPTION_REMAINING collects non-option arguments */
-void
-rest_test3 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] = {
- { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
- { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL },
- { NULL }
- };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program foo --test bar", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- g_assert (ignore_test1_boolean);
- g_assert (strcmp (array_test1_array[0], "foo") == 0);
- g_assert (strcmp (array_test1_array[1], "bar") == 0);
- g_assert (array_test1_array[2] == NULL);
-
- g_strfreev (array_test1_array);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-
-/* check that G_OPTION_REMAINING and -- work together */
-void
-rest_test4 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] = {
- { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
- { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL },
- { NULL }
- };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program foo --test -- -bar", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- g_assert (ignore_test1_boolean);
- g_assert (strcmp (array_test1_array[0], "foo") == 0);
- g_assert (strcmp (array_test1_array[1], "-bar") == 0);
- g_assert (array_test1_array[2] == NULL);
-
- g_strfreev (array_test1_array);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-/* test that G_OPTION_REMAINING works with G_OPTION_ARG_FILENAME_ARRAY */
-void
-rest_test5 (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] = {
- { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL },
- { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &array_test1_array, NULL, NULL },
- { NULL }
- };
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program foo --test bar", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- /* Check array */
- g_assert (ignore_test1_boolean);
- g_assert (strcmp (array_test1_array[0], "foo") == 0);
- g_assert (strcmp (array_test1_array[1], "bar") == 0);
- g_assert (array_test1_array[2] == NULL);
-
- g_strfreev (array_test1_array);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-unknown_short_test (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- GOptionEntry entries [] = { { NULL } };
-
- g_test_bug ("166609");
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program -0", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- g_assert (!retval);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-/* test that lone dashes are treated as non-options */
-void lonely_dash_test (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
-
- g_test_bug ("168008");
-
- context = g_option_context_new (NULL);
-
- /* Now try parsing */
- argv = split_string ("program -", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- assert_no_error (error);
- g_assert (retval);
-
- g_assert (argv[1] && strcmp (argv[1], "-") == 0);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-void
-missing_arg_test (void)
-{
- GOptionContext *context;
- gboolean retval;
- GError *error = NULL;
- gchar **argv;
- int argc;
- gchar *arg = NULL;
- GOptionEntry entries [] =
- { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
- { NULL } };
-
- g_test_bug ("305576");
-
- context = g_option_context_new (NULL);
- g_option_context_add_main_entries (context, entries, NULL);
-
- /* Now try parsing */
- argv = split_string ("program --test", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- g_assert (retval == FALSE);
- g_clear_error (&error);
-
- g_strfreev (argv);
-
- /* Try parsing again */
- argv = split_string ("program --t", &argc);
-
- retval = g_option_context_parse (context, &argc, &argv, &error);
- g_assert (retval == FALSE);
-
- g_strfreev (argv);
- g_option_context_free (context);
-}
-
-int
-main (int argc,
- char *argv[])
-{
- g_test_init (&argc, &argv, NULL);
-
- g_test_bug_base ("http://bugzilla.gnome.org/");
- g_test_add_func ("/group/captions", group_captions);
-
- /* Test that restoration on failure works */
- g_test_add_func ("/restoration/int", error_test1);
- g_test_add_func ("/restoration/string", error_test2);
- g_test_add_func ("/restoration/boolean", error_test3);
-
- /* Test that special argument parsing works */
- g_test_add_func ("/arg/repetition/int", arg_test1);
- g_test_add_func ("/arg/repetition/string", arg_test2);
- g_test_add_func ("/arg/repetition/filename", arg_test3);
- g_test_add_func ("/arg/repetition/double", arg_test4);
- g_test_add_func ("/arg/repetition/locale", arg_test5);
- g_test_add_func ("/arg/repetition/int64", arg_test6);
-
- /* Test string arrays */
- g_test_add_func ("/arg/array/string", array_test1);
-
- /* Test callback args */
- g_test_add_func ("/arg/callback/string", callback_test1);
- g_test_add_func ("/arg/callback/count", callback_test2);
-
- /* Test optional arg flag for callback */
- g_test_add_func ("/arg/callback/optional1", callback_test_optional_1);
- g_test_add_func ("/arg/callback/optional2", callback_test_optional_2);
- g_test_add_func ("/arg/callback/optional3", callback_test_optional_3);
- g_test_add_func ("/arg/callback/optional4", callback_test_optional_4);
- g_test_add_func ("/arg/callback/optional5", callback_test_optional_5);
- g_test_add_func ("/arg/callback/optional6", callback_test_optional_6);
- g_test_add_func ("/arg/callback/optional7", callback_test_optional_7);
- g_test_add_func ("/arg/callback/optional8", callback_test_optional_8);
-
- /* Test callback with G_OPTION_REMAINING */
- g_test_add_func ("/arg/remaining/callback", callback_remaining_test1);
-
- /* Test callbacks which return FALSE */
- g_test_add_func ("/arg/remaining/callback-false", callback_returns_false);
-
- /* Test ignoring options */
- g_test_add_func ("/arg/ignore/long", ignore_test1);
- g_test_add_func ("/arg/ignore/short", ignore_test2);
- g_test_add_func ("/arg/ignore/arg", ignore_test3);
-
- g_test_add_func ("/context/add", add_test1);
-
- /* Test parsing empty args */
- g_test_add_func ("/context/empty1", empty_test1);
- g_test_add_func ("/context/empty2", empty_test2);
- g_test_add_func ("/context/empty3", empty_test3);
-
- /* Test handling of rest args */
- g_test_add_func ("/arg/rest/non-option", rest_test1);
- g_test_add_func ("/arg/rest/separator1", rest_test2);
- g_test_add_func ("/arg/rest/separator2", rest_test2a);
- g_test_add_func ("/arg/rest/separator3", rest_test2b);
- g_test_add_func ("/arg/rest/separator4", rest_test2c);
- g_test_add_func ("/arg/rest/separator5", rest_test2d);
- g_test_add_func ("/arg/remaining/non-option", rest_test3);
- g_test_add_func ("/arg/remaining/separator", rest_test4);
- g_test_add_func ("/arg/remaining/array", rest_test5);
-
- /* regression tests for individual bugs */
- g_test_add_func ("/bug/unknown-short", unknown_short_test);
- g_test_add_func ("/bug/lonely-dash", lonely_dash_test);
- g_test_add_func ("/bug/missing-arg", missing_arg_test);
-
- return g_test_run();
-}
diff --git a/glib/tests/printf.c b/glib/tests/printf.c
deleted file mode 100644
index ff8eee275..000000000
--- a/glib/tests/printf.c
+++ /dev/null
@@ -1,711 +0,0 @@
-/* Unit tests for gstring
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This work is provided "as is"; redistribution and modification
- * in whole or in part, in any medium, physical or electronic is
- * permitted without restriction.
- *
- * This work 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.
- *
- * In no event shall the authors or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even
- * if advised of the possibility of such damage.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "glib.h"
-
-static void
-test_retval_and_trunc (void)
-{
- gchar buf[128];
- gint res;
-
- res = g_snprintf (buf, 0, "abc");
- g_assert_cmpint (res, ==, 3);
-
- res = g_snprintf (NULL, 0, "abc");
- g_assert_cmpint (res, ==, 3);
-
- res = g_snprintf (buf, 5, "abc");
- g_assert_cmpint (res, ==, 3);
-
- res = g_snprintf (buf, 1, "abc");
- g_assert_cmpint (res, ==, 3);
- g_assert (buf[0] == '\0');
- g_assert_cmpstr (buf, ==, "");
-
- res = g_snprintf (buf, 2, "abc");
- g_assert_cmpint (res, ==, 3);
- g_assert (buf[1] == '\0');
- g_assert_cmpstr (buf, ==, "a");
-
- res = g_snprintf (buf, 3, "abc");
- g_assert_cmpint (res, ==, 3);
- g_assert (buf[2] == '\0');
- g_assert_cmpstr (buf, ==, "ab");
-
- res = g_snprintf (buf, 4, "abc");
- g_assert_cmpint (res, ==, 3);
- g_assert (buf[3] == '\0');
- g_assert_cmpstr (buf, ==, "abc");
-
- res = g_snprintf (buf, 5, "abc");
- g_assert_cmpint (res, ==, 3);
- g_assert (buf[3] == '\0');
- g_assert_cmpstr (buf, ==, "abc");
-}
-
-static void
-test_d (void)
-{
- gchar buf[128];
- gint res;
- const gchar *fmt;
-
- /* %d basic formatting */
-
- res = g_snprintf (buf, 128, "%d", 5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- res = g_snprintf (buf, 128, "%d", 0);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "0");
-
- res = g_snprintf (buf, 128, "%.0d", 0);
- g_assert_cmpint (res, ==, 0);
- g_assert_cmpstr (buf, ==, "");
-
- res = g_snprintf (buf, 128, "%.0d", 1);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "1");
-
- res = g_snprintf (buf, 128, "%.d", 2);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "2");
-
- res = g_snprintf (buf, 128, "%d", -1);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "-1");
-
- res = g_snprintf (buf, 128, "%.3d", 5);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "005");
-
- res = g_snprintf (buf, 128, "%.3d", -5);
- g_assert_cmpint (res, ==, 4);
- g_assert_cmpstr (buf, ==, "-005");
-
- res = g_snprintf (buf, 128, "%5.3d", 5);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, " 005");
-
- res = g_snprintf (buf, 128, "%-5.3d", -5);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, "-005 ");
-
- /* %d, length modifiers */
-
- res = g_snprintf (buf, 128, "%" G_GINT16_FORMAT, (gint16)-5);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "-5");
-
- res = g_snprintf (buf, 128, "%" G_GUINT16_FORMAT, (guint16)5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- res = g_snprintf (buf, 128, "%" G_GINT32_FORMAT, (gint32)-5);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "-5");
-
- res = g_snprintf (buf, 128, "%" G_GUINT32_FORMAT, (guint32)5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- res = g_snprintf (buf, 128, "%" G_GINT64_FORMAT, (gint64)-5);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "-5");
-
- res = g_snprintf (buf, 128, "%" G_GUINT64_FORMAT, (guint64)5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- res = g_snprintf (buf, 128, "%" G_GSSIZE_FORMAT, (gssize)-5);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "-5");
-
- res = g_snprintf (buf, 128, "%" G_GSIZE_FORMAT, (gsize)5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- /* %d, flags */
-
- res = g_snprintf (buf, 128, "%-d", 5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- res = g_snprintf (buf, 128, "%-+d", 5);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "+5");
-
- res = g_snprintf (buf, 128, "%+-d", 5);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "+5");
-
- res = g_snprintf (buf, 128, "%+d", -5);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "-5");
-
- res = g_snprintf (buf, 128, "% d", 5);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, " 5");
-
- res = g_snprintf (buf, 128, "% .0d", 0);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, " ");
-
- res = g_snprintf (buf, 128, "%03d", 5);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "005");
-
- res = g_snprintf (buf, 128, "%03d", -5);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "-05");
-
- /* gcc emits warnings for the following formats, since the C spec
- * says some of the flags must be ignored. (The " " in "% +d" and
- * the "0" in "%-03d".) But we need to test that our printf gets
- * those rules right. So we fool gcc into not warning.
- */
- fmt = "% +d";
- res = g_snprintf (buf, 128, fmt, 5);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "+5");
-
- fmt = "%-03d";
- res = g_snprintf (buf, 128, fmt, -5);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "-5 ");
-}
-
-static void
-test_o (void)
-{
- gchar buf[128];
- gint res;
-
- /* %o basic formatting */
-
- res = g_snprintf (buf, 128, "%o", 5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- res = g_snprintf (buf, 128, "%o", 8);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "10");
-
- res = g_snprintf (buf, 128, "%o", 0);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "0");
-
- res = g_snprintf (buf, 128, "%.0o", 0);
- g_assert_cmpint (res, ==, 0);
- g_assert_cmpstr (buf, ==, "");
-
- res = g_snprintf (buf, 128, "%.0o", 1);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "1");
-
- res = g_snprintf (buf, 128, "%.3o", 5);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "005");
-
- res = g_snprintf (buf, 128, "%.3o", 8);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "010");
-
- res = g_snprintf (buf, 128, "%5.3o", 5);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, " 005");
-}
-
-static void
-test_u (void)
-{
- gchar buf[128];
- gint res;
-
- /* %u, basic formatting */
-
- res = g_snprintf (buf, 128, "%u", 5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- res = g_snprintf (buf, 128, "%u", 0);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "0");
-
- res = g_snprintf (buf, 128, "%.0u", 0);
- g_assert_cmpint (res, ==, 0);
- g_assert_cmpstr (buf, ==, "");
-
- res = g_snprintf (buf, 128, "%.0u", 1);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "1");
-
- res = g_snprintf (buf, 128, "%.3u", 5);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "005");
-
- res = g_snprintf (buf, 128, "%5.3u", 5);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, " 005");
-}
-
-static void
-test_x (void)
-{
- gchar buf[128];
- gint res;
-
- /* %x, basic formatting */
-
- res = g_snprintf (buf, 128, "%x", 5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- res = g_snprintf (buf, 128, "%x", 31);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "1f");
-
- res = g_snprintf (buf, 128, "%x", 0);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "0");
-
- res = g_snprintf (buf, 128, "%.0x", 0);
- g_assert_cmpint (res, ==, 0);
- g_assert_cmpstr (buf, ==, "");
-
- res = g_snprintf (buf, 128, "%.0x", 1);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "1");
-
- res = g_snprintf (buf, 128, "%.3x", 5);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "005");
-
- res = g_snprintf (buf, 128, "%.3x", 31);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "01f");
-
- res = g_snprintf (buf, 128, "%5.3x", 5);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, " 005");
-
- /* %x, flags */
-
- res = g_snprintf (buf, 128, "%-x", 5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- res = g_snprintf (buf, 128, "%03x", 5);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "005");
-
- res = g_snprintf (buf, 128, "%#x", 31);
- g_assert_cmpint (res, ==, 4);
- g_assert_cmpstr (buf, ==, "0x1f");
-
- res = g_snprintf (buf, 128, "%#x", 0);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "0");
-}
-
-static void
-test_X (void)
-{
- gchar buf[128];
- gint res;
-
- /* %X, basic formatting */
-
- res = g_snprintf (buf, 128, "%X", 5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- res = g_snprintf (buf, 128, "%X", 31);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "1F");
-
- res = g_snprintf (buf, 128, "%X", 0);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "0");
-
- res = g_snprintf (buf, 128, "%.0X", 0);
- g_assert_cmpint (res, ==, 0);
- g_assert_cmpstr (buf, ==, "");
-
- res = g_snprintf (buf, 128, "%.0X", 1);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "1");
-
- res = g_snprintf (buf, 128, "%.3X", 5);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "005");
-
- res = g_snprintf (buf, 128, "%.3X", 31);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "01F");
-
- res = g_snprintf (buf, 128, "%5.3X", 5);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, " 005");
-
- /* %X, flags */
-
- res = g_snprintf (buf, 128, "%-X", 5);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "5");
-
- res = g_snprintf (buf, 128, "%03X", 5);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "005");
-
- res = g_snprintf (buf, 128, "%#X", 31);
- g_assert_cmpint (res, ==, 4);
- g_assert_cmpstr (buf, ==, "0X1F");
-
- res = g_snprintf (buf, 128, "%#X", 0);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "0");
-}
-
-static void
-test_f (void)
-{
- gchar buf[128];
- gint res;
-
- /* %f, basic formattting */
-
- res = g_snprintf (buf, 128, "%f", G_PI);
- g_assert_cmpint (res, ==, 8);
- g_assert (0 == strncmp (buf, "3.14159", 7));
-
- res = g_snprintf (buf, 128, "%.8f", G_PI);
- g_assert_cmpint (res, ==, 10);
- g_assert (0 == strncmp (buf, "3.1415926", 9));
-
- res = g_snprintf (buf, 128, "%.0f", G_PI);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "3");
-
- res = g_snprintf (buf, 128, "%1.f", G_PI);
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "3");
-
- res = g_snprintf (buf, 128, "%3.f", G_PI);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, " 3");
-
- /* %f, flags */
-
- res = g_snprintf (buf, 128, "%+f", G_PI);
- g_assert_cmpint (res, ==, 9);
- g_assert (0 == strncmp (buf, "+3.14159", 8));
-
- res = g_snprintf (buf, 128, "% f", G_PI);
- g_assert_cmpint (res, ==, 9);
- g_assert (0 == strncmp (buf, " 3.14159", 8));
-
- res = g_snprintf (buf, 128, "%#.0f", G_PI);
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "3.");
-
- res = g_snprintf (buf, 128, "%05.2f", G_PI);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, "03.14");
-}
-
-static gboolean
-same_value (const gchar *actual,
- const gchar *expected)
-{
- gdouble actual_value, expected_value;
-
- actual_value = g_ascii_strtod (actual, NULL);
- expected_value = g_ascii_strtod (expected, NULL);
-
- return actual_value == expected_value;
-}
-
-static void
-test_e (void)
-{
- gchar buf[128];
- gint res;
-
- /* %e, basic formatting */
- /* for %e we can't expect to reproduce exact strings and lengths, since SUS
- * only guarantees that the exponent shall always contain at least two
- * digits. On Windows, it seems to be at least three digits long.
- * Therefore, we compare the results of parsing the expected result and the
- * actual result.
- */
-
- res = g_snprintf (buf, 128, "%e", G_PI);
- g_assert_cmpint (res, >=, 12);
- g_assert (same_value (buf, "3.141593e+00"));
-
- res = g_snprintf (buf, 128, "%.8e", G_PI);
- g_assert_cmpint (res, >=, 14);
- g_assert (same_value (buf, "3.14159265e+00"));
-
- res = g_snprintf (buf, 128, "%.0e", G_PI);
- g_assert_cmpint (res, >=, 5);
- g_assert (same_value (buf, "3e+00"));
-
- res = g_snprintf (buf, 128, "%.1e", 0.0);
- g_assert_cmpint (res, >=, 7);
- g_assert (same_value (buf, "0.0e+00"));
-
- res = g_snprintf (buf, 128, "%.1e", 0.00001);
- g_assert_cmpint (res, >=, 7);
- g_assert (same_value (buf, "1.0e-05"));
-
- res = g_snprintf (buf, 128, "%.1e", 10000.0);
- g_assert_cmpint (res, >=, 7);
- g_assert (same_value (buf, "1.0e+04"));
-
- /* %e, flags */
-
- res = g_snprintf (buf, 128, "%+e", G_PI);
- g_assert_cmpint (res, >=, 13);
- g_assert (same_value (buf, "+3.141593e+00"));
-
- res = g_snprintf (buf, 128, "% e", G_PI);
- g_assert_cmpint (res, >=, 13);
- g_assert (same_value (buf, " 3.141593e+00"));
-
- res = g_snprintf (buf, 128, "%#.0e", G_PI);
- g_assert_cmpint (res, >=, 6);
- g_assert (same_value (buf, "3.e+00"));
-
- res = g_snprintf (buf, 128, "%09.2e", G_PI);
- g_assert_cmpint (res, >=, 9);
- g_assert (same_value (buf, "03.14e+00"));
-}
-
-static void
-test_c (void)
-{
- gchar buf[128];
- gint res;
-
- res = g_snprintf (buf, 128, "%c", 'a');
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "a");
-}
-
-static void
-test_s (void)
-{
- gchar buf[128];
- gint res;
-
- res = g_snprintf (buf, 128, "%.2s", "abc");
- g_assert_cmpint (res, ==, 2);
- g_assert_cmpstr (buf, ==, "ab");
-
- res = g_snprintf (buf, 128, "%.6s", "abc");
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "abc");
-
- res = g_snprintf (buf, 128, "%5s", "abc");
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, " abc");
-
- res = g_snprintf (buf, 128, "%-5s", "abc");
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, "abc ");
-
- res = g_snprintf (buf, 128, "%5.2s", "abc");
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, " ab");
-
- res = g_snprintf (buf, 128, "%*s", 5, "abc");
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, " abc");
-
-#if 0 /* HP-UX doesn't get this right */
- res = g_snprintf (buf, 128, "%*s", -5, "abc");
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, "abc ");
-#endif
-
- res = g_snprintf (buf, 128, "%*.*s", 5, 2, "abc");
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, " ab");
-}
-
-static void
-test_n (void)
-{
- gchar buf[128];
- gint res;
- gint i;
- glong l;
-
- res = g_snprintf (buf, 128, "abc%n", &i);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "abc");
- g_assert_cmpint (i, ==, 3);
-
- res = g_snprintf (buf, 128, "abc%ln", &l);
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "abc");
- g_assert_cmpint (l, ==, 3);
-}
-
-static void
-test_percent (void)
-{
- gchar buf[128];
- gint res;
-
- res = g_snprintf (buf, 128, "%%");
- g_assert_cmpint (res, ==, 1);
- g_assert_cmpstr (buf, ==, "%");
-}
-
-static void
-test_positional_params (void)
-{
- gchar buf[128];
- gint res;
-
- res = g_snprintf (buf, 128, "%2$c %1$c", 'b', 'a');
- g_assert_cmpint (res, ==, 3);
- g_assert_cmpstr (buf, ==, "a b");
-
- res = g_snprintf (buf, 128, "%1$*2$.*3$s", "abc", 5, 2);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, " ab");
-
- res = g_snprintf (buf, 128, "%1$s%1$s", "abc");
- g_assert_cmpint (res, ==, 6);
- g_assert_cmpstr (buf, ==, "abcabc");
-}
-
-static void
-test_64bit (void)
-{
- gchar buf[128];
- gint res;
-
- res = g_snprintf (buf, 128, "%" G_GINT64_FORMAT, (gint64)123456);
- g_assert_cmpint (res, ==, 6);
- g_assert_cmpstr (buf, ==, "123456");
-
- res = g_snprintf (buf, 128, "%" G_GINT64_FORMAT, (gint64)-123456);
- g_assert_cmpint (res, ==, 7);
- g_assert_cmpstr (buf, ==, "-123456");
-
- res = g_snprintf (buf, 128, "%" G_GUINT64_FORMAT, (guint64)123456);
- g_assert_cmpint (res, ==, 6);
- g_assert_cmpstr (buf, ==, "123456");
-
- res = g_snprintf (buf, 128, "%" G_GINT64_MODIFIER "o", (gint64)123456);
- g_assert_cmpint (res, ==, 6);
- g_assert_cmpstr (buf, ==, "361100");
-
- res = g_snprintf (buf, 128, "%#" G_GINT64_MODIFIER "o", (gint64)123456);
- g_assert_cmpint (res, ==, 7);
- g_assert_cmpstr (buf, ==, "0361100");
-
- res = g_snprintf (buf, 128, "%" G_GINT64_MODIFIER "x", (gint64)123456);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, "1e240");
-
- res = g_snprintf (buf, 128, "%#" G_GINT64_MODIFIER "x", (gint64)123456);
- g_assert_cmpint (res, ==, 7);
- g_assert_cmpstr (buf, ==, "0x1e240");
-
- res = g_snprintf (buf, 128, "%" G_GINT64_MODIFIER "X", (gint64)123456);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, "1E240");
-
-#ifdef G_OS_WIN32
- /* On Win32, test that the "ll" modifier also works, for backward
- * compatibility. One really should use the G_GINT64_MODIFIER (which
- * on Win32 is the "I64" that the (msvcrt) C library's printf uses),
- * but "ll" used to work with the "trio" g_printf implementation in
- * GLib 2.2, so it's best if it continues to work.
- */
-
- res = g_snprintf (buf, 128, "%" "lli", (gint64)123456);
- g_assert_cmpint (res, ==, 6);
- g_assert_cmpstr (buf, ==, "123456");
-
- res = g_snprintf (buf, 128, "%" "lli", (gint64)-123456);
- g_assert_cmpint (res, ==, 7);
- g_assert_cmpstr (buf, ==, "-123456");
-
- res = g_snprintf (buf, 128, "%" "llu", (guint64)123456);
- g_assert_cmpint (res, ==, 6);
- g_assert_cmpstr (buf, ==, "123456");
-
- res = g_snprintf (buf, 128, "%" "ll" "o", (gint64)123456);
- g_assert_cmpint (res, ==, 6);
- g_assert_cmpstr (buf, ==, "361100");
-
- res = g_snprintf (buf, 128, "%#" "ll" "o", (gint64)123456);
- g_assert_cmpint (res, ==, 7);
- g_assert_cmpstr (buf, ==, "0361100");
-
- res = g_snprintf (buf, 128, "%" "ll" "x", (gint64)123456);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, "1e240");
-
- res = g_snprintf (buf, 128, "%#" "ll" "x", (gint64)123456);
- g_assert_cmpint (res, ==, 7);
- g_assert_cmpstr (buf, ==, "0x1e240");
-
- res = g_snprintf (buf, 128, "%" "ll" "X", (gint64)123456);
- g_assert_cmpint (res, ==, 5);
- g_assert_cmpstr (buf, ==, "1E240");
-#endif
-}
-
-int
-main (int argc,
- char *argv[])
-{
- g_test_init (&argc, &argv, NULL);
-
- g_test_add_func ("/printf/test-retval-and-trunc", test_retval_and_trunc);
- g_test_add_func ("/printf/test-d", test_d);
- g_test_add_func ("/printf/test-o", test_o);
- g_test_add_func ("/printf/test-u", test_u);
- g_test_add_func ("/printf/test-x", test_x);
- g_test_add_func ("/printf/test-X", test_X);
- g_test_add_func ("/printf/test-f", test_f);
- g_test_add_func ("/printf/test-e", test_e);
- g_test_add_func ("/printf/test-c", test_c);
- g_test_add_func ("/printf/test-s", test_s);
- g_test_add_func ("/printf/test-n", test_n);
- g_test_add_func ("/printf/test-percent", test_percent);
- g_test_add_func ("/printf/test-positional-params", test_positional_params);
- g_test_add_func ("/printf/test-64bit", test_64bit);
-
- return g_test_run();
-}
diff --git a/glib/tests/rand.c b/glib/tests/rand.c
deleted file mode 100644
index 0bddfbf4d..000000000
--- a/glib/tests/rand.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/* Unit tests for gstring
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This work is provided "as is"; redistribution and modification
- * in whole or in part, in any medium, physical or electronic is
- * permitted without restriction.
- *
- * This work 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.
- *
- * In no event shall the authors or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even
- * if advised of the possibility of such damage.
- */
-
-#include "glib.h"
-
-/* Outputs tested against the reference implementation mt19937ar.c from
- http://www.math.keio.ac.jp/~matumoto/MT2002/emt19937ar.html */
-
-/* Tests for a simple seed, first number is the seed */
-const guint32 first_numbers[] =
-{
- 0x7a7a7a7a,
- 0xfdcc2d54,
- 0x3a279ceb,
- 0xc4d39c33,
- 0xf31895cd,
- 0x46ca0afc,
- 0x3f5484ff,
- 0x54bc9557,
- 0xed2c24b1,
- 0x84062503,
- 0x8f6404b3,
- 0x599a94b3,
- 0xe46d03d5,
- 0x310beb78,
- 0x7bee5d08,
- 0x760d09be,
- 0x59b6e163,
- 0xbf6d16ec,
- 0xcca5fb54,
- 0x5de7259b,
- 0x1696330c,
-};
-
-/* array seed */
-const guint32 seed_array[] =
-{
- 0x6553375f,
- 0xd6b8d43b,
- 0xa1e7667f,
- 0x2b10117c
-};
-
-/* tests for the array seed */
-const guint32 array_outputs[] =
-{
- 0xc22b7dc3,
- 0xfdecb8ae,
- 0xb4af0738,
- 0x516bc6e1,
- 0x7e372e91,
- 0x2d38ff80,
- 0x6096494a,
- 0xd162d5a8,
- 0x3c0aaa0d,
- 0x10e736ae
-};
-
-static void
-test_rand (void)
-{
- guint n;
- guint ones;
- double proportion;
- GRand *rand;
- GRand *copy;
-
- rand = g_rand_new_with_seed (first_numbers[0]);
-
- for (n = 1; n < G_N_ELEMENTS (first_numbers); n++)
- g_assert (first_numbers[n] == g_rand_int (rand));
-
- g_rand_set_seed (rand, 2);
- g_rand_set_seed_array (rand, seed_array, G_N_ELEMENTS (seed_array));
-
- for (n = 0; n < G_N_ELEMENTS (array_outputs); n++)
- g_assert (array_outputs[n] == g_rand_int (rand));
-
- copy = g_rand_copy (rand);
- for (n = 0; n < 100; n++)
- g_assert (g_rand_int (copy) == g_rand_int (rand));
-
- for (n = 1; n < 100000; n++)
- {
- gint32 i;
- gdouble d;
- gboolean b;
-
- i = g_rand_int_range (rand, 8,16);
- g_assert (i >= 8 && i < 16);
-
- i = g_random_int_range (8,16);
- g_assert (i >= 8 && i < 16);
-
- d = g_rand_double (rand);
- g_assert (d >= 0 && d < 1);
-
- d = g_random_double ();
- g_assert (d >= 0 && d < 1);
-
- d = g_rand_double_range (rand, -8, 32);
- g_assert (d >= -8 && d < 32);
-
- d = g_random_double_range (-8, 32);
- g_assert (d >= -8 && d < 32);
-
- b = g_random_boolean ();
- g_assert (b == TRUE || b == FALSE);
-
- b = g_rand_boolean (rand);
- g_assert (b == TRUE || b == FALSE);
- }
-
- /* Statistical sanity check, count the number of ones
- * when getting random numbers in range [0,3) and see
- * that it must be semi-close to 0.25 with a VERY large
- * probability */
- ones = 0;
- for (n = 1; n < 100000; n++)
- {
- if (g_random_int_range (0, 4) == 1)
- ones ++;
- }
-
- proportion = (double)ones / (double)100000;
- /* 0.025 is overkill, but should suffice to test for some unreasonability */
- g_assert (ABS (proportion - 0.25) < 0.025);
-
- g_rand_free (rand);
- g_rand_free (copy);
-}
-
-int
-main (int argc,
- char *argv[])
-{
- g_test_init (&argc, &argv, NULL);
-
- g_test_add_func ("/rand/test-rand", test_rand);
-
- return g_test_run();
-}
diff --git a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c
deleted file mode 100644
index 8928ae658..000000000
--- a/glib/tests/strfuncs.c
+++ /dev/null
@@ -1,1241 +0,0 @@
-/* Unit tests for gstrfuncs
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This work is provided "as is"; redistribution and modification
- * in whole or in part, in any medium, physical or electronic is
- * permitted without restriction.
- *
- * This work 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.
- *
- * In no event shall the authors or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even
- * if advised of the possibility of such damage.
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <locale.h>
-#include <math.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "glib.h"
-
-#define GLIB_TEST_STRING "el dorado "
-
-#define FOR_ALL_CTYPE(macro) \
- macro(isalnum) \
- macro(isalpha) \
- macro(iscntrl) \
- macro(isdigit) \
- macro(isgraph) \
- macro(islower) \
- macro(isprint) \
- macro(ispunct) \
- macro(isspace) \
- macro(isupper) \
- macro(isxdigit)
-
-#define DEFINE_CALL_CTYPE(function) \
- static int \
- call_##function (int c) \
- { \
- return function (c); \
- }
-
-#define DEFINE_CALL_G_ASCII_CTYPE(function) \
- static gboolean \
- call_g_ascii_##function (gchar c) \
- { \
- return g_ascii_##function (c); \
- }
-
-FOR_ALL_CTYPE (DEFINE_CALL_CTYPE)
-FOR_ALL_CTYPE (DEFINE_CALL_G_ASCII_CTYPE)
-
-static void
-test_is_function (const char *name,
- gboolean (* ascii_function) (gchar),
- int (* c_library_function) (int),
- gboolean (* unicode_function) (gunichar))
-{
- int c;
-
- for (c = 0; c <= 0x7F; c++)
- {
- gboolean ascii_result = ascii_function ((gchar)c);
- gboolean c_library_result = c_library_function (c) != 0;
- gboolean unicode_result = unicode_function ((gunichar) c);
- if (ascii_result != c_library_result && c != '\v')
- {
- g_error ("g_ascii_%s returned %d and %s returned %d for 0x%X",
- name, ascii_result, name, c_library_result, c);
- }
- if (ascii_result != unicode_result)
- {
- g_error ("g_ascii_%s returned %d and g_unichar_%s returned %d for 0x%X",
- name, ascii_result, name, unicode_result, c);
- }
- }
- for (c = 0x80; c <= 0xFF; c++)
- {
- gboolean ascii_result = ascii_function ((gchar)c);
- if (ascii_result)
- {
- g_error ("g_ascii_%s returned TRUE for 0x%X", name, c);
- }
- }
-}
-
-static void
-test_to_function (const char *name,
- gchar (* ascii_function) (gchar),
- int (* c_library_function) (int),
- gunichar (* unicode_function) (gunichar))
-{
- int c;
-
- for (c = 0; c <= 0x7F; c++)
- {
- int ascii_result = (guchar) ascii_function ((gchar) c);
- int c_library_result = c_library_function (c);
- int unicode_result = unicode_function ((gunichar) c);
- if (ascii_result != c_library_result)
- {
- g_error ("g_ascii_%s returned 0x%X and %s returned 0x%X for 0x%X",
- name, ascii_result, name, c_library_result, c);
- }
- if (ascii_result != unicode_result)
- {
- g_error ("g_ascii_%s returned 0x%X and g_unichar_%s returned 0x%X for 0x%X",
- name, ascii_result, name, unicode_result, c);
- }
- }
- for (c = 0x80; c <= 0xFF; c++)
- {
- int ascii_result = (guchar) ascii_function ((gchar) c);
- if (ascii_result != c)
- {
- g_error ("g_ascii_%s returned 0x%X for 0x%X",
- name, ascii_result, c);
- }
- }
-}
-
-static void
-test_digit_function (const char *name,
- int (* ascii_function) (gchar),
- int (* unicode_function) (gunichar))
-{
- int c;
-
- for (c = 0; c <= 0x7F; c++)
- {
- int ascii_result = ascii_function ((gchar) c);
- int unicode_result = unicode_function ((gunichar) c);
- if (ascii_result != unicode_result)
- {
- g_error ("g_ascii_%s_value returned %d and g_unichar_%s_value returned %d for 0x%X",
- name, ascii_result, name, unicode_result, c);
- }
- }
- for (c = 0x80; c <= 0xFF; c++)
- {
- int ascii_result = ascii_function ((gchar) c);
- if (ascii_result != -1)
- {
- g_error ("g_ascii_%s_value returned %d for 0x%X",
- name, ascii_result, c);
- }
- }
-}
-
-static void
-test_is_to_digit (void)
-{
- #define TEST_IS(name) test_is_function (#name, call_g_ascii_##name, call_##name, g_unichar_##name);
-
- FOR_ALL_CTYPE(TEST_IS)
-
- #undef TEST_IS
-
- #define TEST_TO(name) test_to_function (#name, g_ascii_##name, name, g_unichar_##name)
-
- TEST_TO (tolower);
- TEST_TO (toupper);
-
- #undef TEST_TO
-
- #define TEST_DIGIT(name) test_digit_function (#name, g_ascii_##name##_value, g_unichar_##name##_value)
-
- TEST_DIGIT (digit);
- TEST_DIGIT (xdigit);
-
- #undef TEST_DIGIT
-}
-
-static void
-test_strdup (void)
-{
- gchar *str;
-
- str = g_strdup (NULL);
- g_assert (str == NULL);
-
- str = g_strdup (GLIB_TEST_STRING);
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, GLIB_TEST_STRING);
- g_free (str);
-}
-
-static void
-test_strndup (void)
-{
- gchar *str;
-
- str = g_strndup (NULL, 3);
- g_assert (str == NULL);
-
- str = g_strndup ("aaaa", 5);
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, "aaaa");
- g_free (str);
-
- str = g_strndup ("aaaa", 2);
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, "aa");
- g_free (str);
-}
-
-static void
-test_strdup_printf (void)
-{
- gchar *str;
-
- str = g_strdup_printf ("%05d %-5s", 21, "test");
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, "00021 test ");
- g_free (str);
-}
-
-static void
-test_strdupv (void)
-{
- gchar *vec[] = { "Foo", "Bar", NULL };
- gchar **copy;
-
- copy = g_strdupv (NULL);
- g_assert (copy == NULL);
-
- copy = g_strdupv (vec);
- g_assert (copy != NULL);
- g_assert_cmpstr (copy[0], ==, "Foo");
- g_assert_cmpstr (copy[1], ==, "Bar");
- g_assert (copy[2] == NULL);
- g_strfreev (copy);
-}
-
-static void
-test_strnfill (void)
-{
- gchar *str;
-
- str = g_strnfill (0, 'a');
- g_assert (str != NULL);
- g_assert (*str == '\0');
- g_free (str);
-
- str = g_strnfill (5, 'a');
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, "aaaaa");
- g_free (str);
-}
-
-static void
-test_strconcat (void)
-{
- gchar *str;
-
- str = g_strconcat (GLIB_TEST_STRING, NULL);
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, GLIB_TEST_STRING);
- g_free (str);
-
- str = g_strconcat (GLIB_TEST_STRING,
- GLIB_TEST_STRING,
- GLIB_TEST_STRING,
- NULL);
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, GLIB_TEST_STRING GLIB_TEST_STRING GLIB_TEST_STRING);
- g_free (str);
-}
-
-static void
-test_strjoin (void)
-{
- gchar *str;
-
- str = g_strjoin (NULL, NULL);
- g_assert (str != NULL);
- g_assert (*str == '\0');
- g_free (str);
-
- str = g_strjoin (":", NULL);
- g_assert (str != NULL);
- g_assert (*str == '\0');
- g_free (str);
-
- str = g_strjoin (NULL, GLIB_TEST_STRING, NULL);
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, GLIB_TEST_STRING);
- g_free (str);
-
- str = g_strjoin (NULL,
- GLIB_TEST_STRING,
- GLIB_TEST_STRING,
- GLIB_TEST_STRING,
- NULL);
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, GLIB_TEST_STRING GLIB_TEST_STRING GLIB_TEST_STRING);
- g_free (str);
-
- str = g_strjoin (":",
- GLIB_TEST_STRING,
- GLIB_TEST_STRING,
- GLIB_TEST_STRING,
- NULL);
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, GLIB_TEST_STRING ":" GLIB_TEST_STRING ":" GLIB_TEST_STRING);
- g_free (str);
-}
-
-static void
-test_strcanon (void)
-{
- gchar *str;
-
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- str = g_strcanon (NULL, "ab", 'y');
- }
- g_test_trap_assert_failed ();
-
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- str = g_strdup ("abxabxab");
- str = g_strcanon (str, NULL, 'y');
- g_free (str);
- }
- g_test_trap_assert_failed ();
-
- str = g_strdup ("abxabxab");
- str = g_strcanon (str, "ab", 'y');
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, "abyabyab");
- g_free (str);
-}
-
-static void
-test_strcompress_strescape (void)
-{
- gchar *str;
- gchar *tmp;
-
- /* test compress */
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- str = g_strcompress (NULL);
- }
- g_test_trap_assert_failed ();
-
- /* trailing slashes are not allowed */
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- str = g_strcompress ("abc\\");
- }
- g_test_trap_assert_failed ();
-
- str = g_strcompress ("abc\\\\\\\"\\b\\f\\n\\r\\t\\003\\177\\234\\313\\12345z");
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, "abc\\\"\b\f\n\r\t\003\177\234\313\12345z");
- g_free (str);
-
- /* test escape */
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- str = g_strescape (NULL, NULL);
- }
- g_test_trap_assert_failed ();
-
- str = g_strescape ("abc\\\"\b\f\n\r\t\003\177\234\313", NULL);
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, "abc\\\\\\\"\\b\\f\\n\\r\\t\\003\\177\\234\\313");
- g_free (str);
-
- str = g_strescape ("abc\\\"\b\f\n\r\t\003\177\234\313",
- "\b\f\001\002\003\004");
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, "abc\\\\\\\"\b\f\\n\\r\\t\003\\177\\234\\313");
- g_free (str);
-
- /* round trip */
- tmp = g_strescape ("abc\\\"\b\f\n\r\t\003\177\234\313", NULL);
- str = g_strcompress (tmp);
- g_assert (str != NULL);
- g_assert_cmpstr (str, ==, "abc\\\"\b\f\n\r\t\003\177\234\313");
- g_free (str);
- g_free (tmp);
-}
-
-static void
-test_ascii_strcasecmp (void)
-{
- gboolean res;
-
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- res = g_ascii_strcasecmp ("foo", NULL);
- }
- g_test_trap_assert_failed ();
-
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- res = g_ascii_strcasecmp (NULL, "foo");
- }
- g_test_trap_assert_failed ();
-
- res = g_ascii_strcasecmp ("FroboZZ", "frobozz");
- g_assert_cmpint (res, ==, 0);
-
- res = g_ascii_strcasecmp ("frobozz", "frobozz");
- g_assert_cmpint (res, ==, 0);
-
- res = g_ascii_strcasecmp ("frobozz", "FROBOZZ");
- g_assert_cmpint (res, ==, 0);
-
- res = g_ascii_strcasecmp ("FROBOZZ", "froboz");
- g_assert_cmpint (res, !=, 0);
-
- res = g_ascii_strcasecmp ("", "");
- g_assert_cmpint (res, ==, 0);
-
- res = g_ascii_strcasecmp ("!#%&/()", "!#%&/()");
- g_assert_cmpint (res, ==, 0);
-
- res = g_ascii_strcasecmp ("a", "b");
- g_assert_cmpint (res, <, 0);
-
- res = g_ascii_strcasecmp ("a", "B");
- g_assert_cmpint (res, <, 0);
-
- res = g_ascii_strcasecmp ("A", "b");
- g_assert_cmpint (res, <, 0);
-
- res = g_ascii_strcasecmp ("A", "B");
- g_assert_cmpint (res, <, 0);
-
- res = g_ascii_strcasecmp ("b", "a");
- g_assert_cmpint (res, >, 0);
-
- res = g_ascii_strcasecmp ("b", "A");
- g_assert_cmpint (res, >, 0);
-
- res = g_ascii_strcasecmp ("B", "a");
- g_assert_cmpint (res, >, 0);
-
- res = g_ascii_strcasecmp ("B", "A");
- g_assert_cmpint (res, >, 0);
-}
-
-static void
-do_test_strchug (const gchar *str, const gchar *expected)
-{
- gchar *tmp;
- gboolean res;
-
- tmp = g_strdup (str);
-
- g_strchug (tmp);
- res = (strcmp (tmp, expected) == 0);
- g_free (tmp);
-
- g_assert_cmpint (res, ==, TRUE);
-}
-
-static void
-test_strchug (void)
-{
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- g_strchug (NULL);
- }
- g_test_trap_assert_failed ();
-
- do_test_strchug ("", "");
- do_test_strchug (" ", "");
- do_test_strchug ("\t\r\n ", "");
- do_test_strchug (" a", "a");
- do_test_strchug (" a", "a");
- do_test_strchug ("a a", "a a");
- do_test_strchug (" a a", "a a");
-}
-
-static void
-do_test_strchomp (const gchar *str, const gchar *expected)
-{
- gchar *tmp;
- gboolean res;
-
- tmp = g_strdup (str);
-
- g_strchomp (tmp);
- res = (strcmp (tmp, expected) == 0);
- g_free (tmp);
-
- g_assert_cmpint (res, ==, TRUE);
-}
-
-static void
-test_strchomp (void)
-{
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- g_strchomp (NULL);
- }
- g_test_trap_assert_failed ();
-
- do_test_strchomp ("", "");
- do_test_strchomp (" ", "");
- do_test_strchomp (" \t\r\n", "");
- do_test_strchomp ("a ", "a");
- do_test_strchomp ("a ", "a");
- do_test_strchomp ("a a", "a a");
- do_test_strchomp ("a a ", "a a");
-}
-
-static void
-test_strreverse (void)
-{
- gchar *str;
- gchar *p;
-
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- str = g_strreverse (NULL);
- }
- g_test_trap_assert_failed ();
-
- str = p = g_strdup ("abcde");
- str = g_strreverse (str);
- g_assert (str != NULL);
- g_assert (p == str);
- g_assert_cmpstr (str, ==, "edcba");
- g_free (str);
-}
-
-static void
-test_strstr (void)
-{
- gchar *haystack;
- gchar *res;
-
- haystack = g_strdup ("FooBarFooBarFoo");
-
- /* strstr_len */
- res = g_strstr_len (haystack, 6, "xxx");
- g_assert (res == NULL);
-
- res = g_strstr_len (haystack, 6, "FooBarFooBarFooBar");
- g_assert (res == NULL);
-
- res = g_strstr_len (haystack, 3, "Bar");
- g_assert (res == NULL);
-
- res = g_strstr_len (haystack, 6, "");
- g_assert (res == haystack);
- g_assert_cmpstr (res, ==, "FooBarFooBarFoo");
-
- res = g_strstr_len (haystack, 6, "Bar");
- g_assert (res == haystack + 3);
- g_assert_cmpstr (res, ==, "BarFooBarFoo");
-
- res = g_strstr_len (haystack, -1, "Bar");
- g_assert (res == haystack + 3);
- g_assert_cmpstr (res, ==, "BarFooBarFoo");
-
- /* strrstr */
- res = g_strrstr (haystack, "xxx");
- g_assert (res == NULL);
-
- res = g_strrstr (haystack, "FooBarFooBarFooBar");
- g_assert (res == NULL);
-
- res = g_strrstr (haystack, "");
- g_assert (res == haystack);
- g_assert_cmpstr (res, ==, "FooBarFooBarFoo");
-
- res = g_strrstr (haystack, "Bar");
- g_assert (res == haystack + 9);
- g_assert_cmpstr (res, ==, "BarFoo");
-
- /* strrstr_len */
- res = g_strrstr_len (haystack, 14, "xxx");
- g_assert (res == NULL);
-
- res = g_strrstr_len (haystack, 14, "FooBarFooBarFooBar");
- g_assert (res == NULL);
-
- res = g_strrstr_len (haystack, 3, "Bar");
- g_assert (res == NULL);
-
- res = g_strrstr_len (haystack, 14, "BarFoo");
- g_assert (res == haystack + 3);
- g_assert_cmpstr (res, ==, "BarFooBarFoo");
-
- res = g_strrstr_len (haystack, 15, "BarFoo");
- g_assert (res == haystack + 9);
- g_assert_cmpstr (res, ==, "BarFoo");
-
- res = g_strrstr_len (haystack, -1, "BarFoo");
- g_assert (res == haystack + 9);
- g_assert_cmpstr (res, ==, "BarFoo");
-
- /* test case for strings with \0 in the middle */
- *(haystack + 7) = '\0';
- res = g_strstr_len (haystack, 15, "BarFoo");
- g_assert (res == NULL);
-
- g_free (haystack);
-}
-
-static void
-test_has_prefix (void)
-{
- gboolean res;
-
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- res = g_str_has_prefix ("foo", NULL);
- }
- g_test_trap_assert_failed ();
-
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- res = g_str_has_prefix (NULL, "foo");
- }
- g_test_trap_assert_failed ();
-
- res = g_str_has_prefix ("foo", "bar");
- g_assert_cmpint (res, ==, FALSE);
-
- res = g_str_has_prefix ("foo", "foobar");
- g_assert_cmpint (res, ==, FALSE);
-
- res = g_str_has_prefix ("foobar", "bar");
- g_assert_cmpint (res, ==, FALSE);
-
- res = g_str_has_prefix ("foobar", "foo");
- g_assert_cmpint (res, ==, TRUE);
-
- res = g_str_has_prefix ("foo", "");
- g_assert_cmpint (res, ==, TRUE);
-
- res = g_str_has_prefix ("foo", "foo");
- g_assert_cmpint (res, ==, TRUE);
-
- res = g_str_has_prefix ("", "");
- g_assert_cmpint (res, ==, TRUE);
-}
-
-static void
-test_has_suffix (void)
-{
- gboolean res;
-
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- res = g_str_has_suffix ("foo", NULL);
- }
- g_test_trap_assert_failed ();
-
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- res = g_str_has_suffix (NULL, "foo");
- }
- g_test_trap_assert_failed ();
-
- res = g_str_has_suffix ("foo", "bar");
- g_assert_cmpint (res, ==, FALSE);
-
- res = g_str_has_suffix ("bar", "foobar");
- g_assert_cmpint (res, ==, FALSE);
-
- res = g_str_has_suffix ("foobar", "foo");
- g_assert_cmpint (res, ==, FALSE);
-
- res = g_str_has_suffix ("foobar", "bar");
- g_assert_cmpint (res, ==, TRUE);
-
- res = g_str_has_suffix ("foo", "");
- g_assert_cmpint (res, ==, TRUE);
-
- res = g_str_has_suffix ("foo", "foo");
- g_assert_cmpint (res, ==, TRUE);
-
- res = g_str_has_suffix ("", "");
- g_assert_cmpint (res, ==, TRUE);
-}
-
-static void
-strv_check (gchar **strv, ...)
-{
- gboolean ok = TRUE;
- gint i = 0;
- va_list list;
-
- va_start (list, strv);
- while (ok)
- {
- const gchar *str = va_arg (list, const char *);
- if (strv[i] == NULL)
- {
- g_assert (str == NULL);
- break;
- }
- if (str == NULL)
- {
- ok = FALSE;
- }
- else
- {
- g_assert_cmpstr (strv[i], ==, str);
- }
- i++;
- }
- va_end (list);
-
- g_strfreev (strv);
-}
-
-static void
-test_strsplit (void)
-{
- strv_check (g_strsplit ("", ",", 0), NULL);
- strv_check (g_strsplit ("x", ",", 0), "x", NULL);
- strv_check (g_strsplit ("x,y", ",", 0), "x", "y", NULL);
- strv_check (g_strsplit ("x,y,", ",", 0), "x", "y", "", NULL);
- strv_check (g_strsplit (",x,y", ",", 0), "", "x", "y", NULL);
- strv_check (g_strsplit (",x,y,", ",", 0), "", "x", "y", "", NULL);
- strv_check (g_strsplit ("x,y,z", ",", 0), "x", "y", "z", NULL);
- strv_check (g_strsplit ("x,y,z,", ",", 0), "x", "y", "z", "", NULL);
- strv_check (g_strsplit (",x,y,z", ",", 0), "", "x", "y", "z", NULL);
- strv_check (g_strsplit (",x,y,z,", ",", 0), "", "x", "y", "z", "", NULL);
- strv_check (g_strsplit (",,x,,y,,z,,", ",", 0), "", "", "x", "", "y", "", "z", "", "", NULL);
- strv_check (g_strsplit (",,x,,y,,z,,", ",,", 0), "", "x", "y", "z", "", NULL);
-
- strv_check (g_strsplit ("", ",", 1), NULL);
- strv_check (g_strsplit ("x", ",", 1), "x", NULL);
- strv_check (g_strsplit ("x,y", ",", 1), "x,y", NULL);
- strv_check (g_strsplit ("x,y,", ",", 1), "x,y,", NULL);
- strv_check (g_strsplit (",x,y", ",", 1), ",x,y", NULL);
- strv_check (g_strsplit (",x,y,", ",", 1), ",x,y,", NULL);
- strv_check (g_strsplit ("x,y,z", ",", 1), "x,y,z", NULL);
- strv_check (g_strsplit ("x,y,z,", ",", 1), "x,y,z,", NULL);
- strv_check (g_strsplit (",x,y,z", ",", 1), ",x,y,z", NULL);
- strv_check (g_strsplit (",x,y,z,", ",", 1), ",x,y,z,", NULL);
- strv_check (g_strsplit (",,x,,y,,z,,", ",", 1), ",,x,,y,,z,,", NULL);
- strv_check (g_strsplit (",,x,,y,,z,,", ",,", 1), ",,x,,y,,z,,", NULL);
-
- strv_check (g_strsplit ("", ",", 2), NULL);
- strv_check (g_strsplit ("x", ",", 2), "x", NULL);
- strv_check (g_strsplit ("x,y", ",", 2), "x", "y", NULL);
- strv_check (g_strsplit ("x,y,", ",", 2), "x", "y,", NULL);
- strv_check (g_strsplit (",x,y", ",", 2), "", "x,y", NULL);
- strv_check (g_strsplit (",x,y,", ",", 2), "", "x,y,", NULL);
- strv_check (g_strsplit ("x,y,z", ",", 2), "x", "y,z", NULL);
- strv_check (g_strsplit ("x,y,z,", ",", 2), "x", "y,z,", NULL);
- strv_check (g_strsplit (",x,y,z", ",", 2), "", "x,y,z", NULL);
- strv_check (g_strsplit (",x,y,z,", ",", 2), "", "x,y,z,", NULL);
- strv_check (g_strsplit (",,x,,y,,z,,", ",", 2), "", ",x,,y,,z,,", NULL);
- strv_check (g_strsplit (",,x,,y,,z,,", ",,", 2), "", "x,,y,,z,,", NULL);
-}
-
-static void
-test_strsplit_set (void)
-{
- strv_check (g_strsplit_set ("", ",/", 0), NULL);
- strv_check (g_strsplit_set (":def/ghi:", ":/", -1), "", "def", "ghi", "", NULL);
- strv_check (g_strsplit_set ("abc:def/ghi", ":/", -1), "abc", "def", "ghi", NULL);
- strv_check (g_strsplit_set (",;,;,;,;", ",;", -1), "", "", "", "", "", "", "", "", "", NULL);
- strv_check (g_strsplit_set (",,abc.def", ".,", -1), "", "", "abc", "def", NULL);
-
- strv_check (g_strsplit_set (",x.y", ",.", 0), "", "x", "y", NULL);
- strv_check (g_strsplit_set (".x,y,", ",.", 0), "", "x", "y", "", NULL);
- strv_check (g_strsplit_set ("x,y.z", ",.", 0), "x", "y", "z", NULL);
- strv_check (g_strsplit_set ("x.y,z,", ",.", 0), "x", "y", "z", "", NULL);
- strv_check (g_strsplit_set (",x.y,z", ",.", 0), "", "x", "y", "z", NULL);
- strv_check (g_strsplit_set (",x,y,z,", ",.", 0), "", "x", "y", "z", "", NULL);
- strv_check (g_strsplit_set (",.x,,y,;z..", ".,;", 0), "", "", "x", "", "y", "", "z", "", "", NULL);
- strv_check (g_strsplit_set (",,x,,y,,z,,", ",,", 0), "", "", "x", "", "y", "", "z", "", "", NULL);
-
- strv_check (g_strsplit_set ("x,y.z", ",.", 1), "x,y.z", NULL);
- strv_check (g_strsplit_set ("x.y,z,", ",.", 1), "x.y,z,", NULL);
- strv_check (g_strsplit_set (",x,y,z", ",.", 1), ",x,y,z", NULL);
- strv_check (g_strsplit_set (",x,y.z,", ",.", 1), ",x,y.z,", NULL);
- strv_check (g_strsplit_set (",,x,.y,,z,,", ",.", 1), ",,x,.y,,z,,", NULL);
- strv_check (g_strsplit_set (",.x,,y,,z,,", ",,..", 1), ",.x,,y,,z,,", NULL);
-
- strv_check (g_strsplit_set ("", ",", 0), NULL);
- strv_check (g_strsplit_set ("x", ",", 0), "x", NULL);
- strv_check (g_strsplit_set ("x,y", ",", 0), "x", "y", NULL);
- strv_check (g_strsplit_set ("x,y,", ",", 0), "x", "y", "", NULL);
- strv_check (g_strsplit_set (",x,y", ",", 0), "", "x", "y", NULL);
- strv_check (g_strsplit_set (",x,y,", ",", 0), "", "x", "y", "", NULL);
- strv_check (g_strsplit_set ("x,y,z", ",", 0), "x", "y", "z", NULL);
- strv_check (g_strsplit_set ("x,y,z,", ",", 0), "x", "y", "z", "", NULL);
- strv_check (g_strsplit_set (",x,y,z", ",", 0), "", "x", "y", "z", NULL);
- strv_check (g_strsplit_set (",x,y,z,", ",", 0), "", "x", "y", "z", "", NULL);
- strv_check (g_strsplit_set (",,x,,y,,z,,", ",", 0), "", "", "x", "", "y", "", "z", "", "", NULL);
-
- strv_check (g_strsplit_set ("", ",", 1), NULL);
- strv_check (g_strsplit_set ("x", ",", 1), "x", NULL);
- strv_check (g_strsplit_set ("x,y", ",", 1), "x,y", NULL);
- strv_check (g_strsplit_set ("x,y,", ",", 1), "x,y,", NULL);
- strv_check (g_strsplit_set (",x,y", ",", 1), ",x,y", NULL);
- strv_check (g_strsplit_set (",x,y,", ",", 1), ",x,y,", NULL);
- strv_check (g_strsplit_set ("x,y,z", ",", 1), "x,y,z", NULL);
- strv_check (g_strsplit_set ("x,y,z,", ",", 1), "x,y,z,", NULL);
- strv_check (g_strsplit_set (",x,y,z", ",", 1), ",x,y,z", NULL);
- strv_check (g_strsplit_set (",x,y,z,", ",", 1), ",x,y,z,", NULL);
- strv_check (g_strsplit_set (",,x,,y,,z,,", ",", 1), ",,x,,y,,z,,", NULL);
- strv_check (g_strsplit_set (",,x,,y,,z,,", ",,", 1), ",,x,,y,,z,,", NULL);
-
- strv_check (g_strsplit_set ("", ",", 2), NULL);
- strv_check (g_strsplit_set ("x", ",", 2), "x", NULL);
- strv_check (g_strsplit_set ("x,y", ",", 2), "x", "y", NULL);
- strv_check (g_strsplit_set ("x,y,", ",", 2), "x", "y,", NULL);
- strv_check (g_strsplit_set (",x,y", ",", 2), "", "x,y", NULL);
- strv_check (g_strsplit_set (",x,y,", ",", 2), "", "x,y,", NULL);
- strv_check (g_strsplit_set ("x,y,z", ",", 2), "x", "y,z", NULL);
- strv_check (g_strsplit_set ("x,y,z,", ",", 2), "x", "y,z,", NULL);
- strv_check (g_strsplit_set (",x,y,z", ",", 2), "", "x,y,z", NULL);
- strv_check (g_strsplit_set (",x,y,z,", ",", 2), "", "x,y,z,", NULL);
- strv_check (g_strsplit_set (",,x,,y,,z,,", ",", 2), "", ",x,,y,,z,,", NULL);
-
- strv_check (g_strsplit_set (",,x,.y,..z,,", ",.", 3), "", "", "x,.y,..z,,", NULL);
-}
-
-static void
-test_strv_length (void)
-{
- guint l;
-
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- l = g_strv_length (NULL);
- }
- g_test_trap_assert_failed ();
-
- l = g_strv_length (g_strsplit ("1,2,3,4", ",", -1));
- g_assert_cmpuint (l, ==, 4);
-}
-
-static char *locales[] = {"sv_SE", "en_US", "fa_IR", "C", "ru_RU"};
-
-void
-check_strtod_string (gchar *number,
- double res,
- gboolean check_end,
- gint correct_len)
-{
- double d;
- gint l;
- gchar *dummy;
-
- /* we try a copy of number, with some free space for malloc before that.
- * This is supposed to smash the some wrong pointer calculations. */
-
- dummy = g_malloc (100000);
- number = g_strdup (number);
- g_free (dummy);
-
- for (l = 0; l < G_N_ELEMENTS (locales); l++)
- {
- gboolean ok;
- gchar *end = "(unset)";
-
- setlocale (LC_NUMERIC, locales[l]);
- d = g_ascii_strtod (number, &end);
- ok = isnan (res) ? isnan (d) : (d == res);
- if (!ok)
- {
- g_error ("g_ascii_strtod on \"%s\" for locale %s failed\n" \
- "expected %f (nan %d) actual %f (nan %d)\n",
- number, locales[l],
- res, isnan (res),
- d, isnan (d));
- }
-
- ok = (end - number) == (check_end ? correct_len : strlen (number));
- if (!ok) {
- if (end == NULL)
- g_error ("g_ascii_strtod on \"%s\" for locale %s endptr was NULL\n",
- number, locales[l]);
- else if (end >= number && end <= number + strlen (number))
- g_error ("g_ascii_strtod on \"%s\" for locale %s endptr was wrong, leftover: \"%s\"\n",
- number, locales[l], end);
- else
- g_error ("g_ascii_strtod on \"%s\" for locale %s endptr was REALLY wrong (number=%p, end=%p)\n",
- number, locales[l], number, end);
- }
- }
-
- g_free (number);
-}
-
-static void
-check_strtod_number (gdouble num, gchar *fmt, gchar *str)
-{
- int l;
- gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
-
- for (l = 0; l < G_N_ELEMENTS (locales); l++)
- {
- g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, fmt, num);
- g_assert_cmpstr (buf, ==, str);
- }
-}
-
-static void
-test_strtod (void)
-{
- gdouble d, our_nan, our_inf;
- char buffer[G_ASCII_DTOSTR_BUF_SIZE];
-
-#ifdef NAN
- our_nan = NAN;
-#else
- /* Do this before any call to setlocale. */
- our_nan = atof ("NaN");
-#endif
- g_assert (isnan (our_nan));
-
-#ifdef INFINITY
- our_inf = INFINITY;
-#else
- our_inf = atof ("Infinity");
-#endif
- g_assert (our_inf > 1 && our_inf == our_inf / 2);
-
- check_strtod_string ("123.123", 123.123, FALSE, 0);
- check_strtod_string ("123.123e2", 123.123e2, FALSE, 0);
- check_strtod_string ("123.123e-2", 123.123e-2, FALSE, 0);
- check_strtod_string ("-123.123", -123.123, FALSE, 0);
- check_strtod_string ("-123.123e2", -123.123e2, FALSE, 0);
- check_strtod_string ("-123.123e-2", -123.123e-2, FALSE, 0);
- check_strtod_string ("5.4", 5.4, TRUE, 3);
- check_strtod_string ("5.4,5.5", 5.4, TRUE, 3);
- check_strtod_string ("5,4", 5.0, TRUE, 1);
- /* the following are for #156421 */
- check_strtod_string ("1e1", 1e1, FALSE, 0);
- check_strtod_string ("NAN", our_nan, FALSE, 0);
- check_strtod_string ("-nan", -our_nan, FALSE, 0);
- check_strtod_string ("INF", our_inf, FALSE, 0);
- check_strtod_string ("-infinity", -our_inf, FALSE, 0);
- check_strtod_string ("-.75,0", -0.75, TRUE, 4);
-
- d = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0;
- g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
-
- d = -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0;
- g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
-
- d = pow (2.0, -1024.1);
- g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
-
- d = -pow (2.0, -1024.1);
- g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
-
- /* for #343899 */
- check_strtod_string (" 0.75", 0.75, FALSE, 0);
- check_strtod_string (" +0.75", 0.75, FALSE, 0);
- check_strtod_string (" -0.75", -0.75, FALSE, 0);
- check_strtod_string ("\f0.75", 0.75, FALSE, 0);
- check_strtod_string ("\n0.75", 0.75, FALSE, 0);
- check_strtod_string ("\r0.75", 0.75, FALSE, 0);
- check_strtod_string ("\t0.75", 0.75, FALSE, 0);
-
-#if 0
- /* g_ascii_isspace() returns FALSE for vertical tab, see #59388 */
- check_strtod_string ("\v0.75", 0.75, FALSE, 0);
-#endif
-
- /* for #343899 */
- check_strtod_number (0.75, "%0.2f", "0.75");
- check_strtod_number (0.75, "%5.2f", " 0.75");
- check_strtod_number (-0.75, "%0.2f", "-0.75");
- check_strtod_number (-0.75, "%5.2f", "-0.75");
- check_strtod_number (1e99, "%.0e", "1e+99");
-}
-
-static void
-check_uint64 (const gchar *str,
- const gchar *end,
- gint base,
- guint64 result,
- gint error)
-{
- guint64 actual;
- gchar *endptr = NULL;
- gint err;
-
- errno = 0;
- actual = g_ascii_strtoull (str, &endptr, base);
- err = errno;
-
- g_assert (actual == result);
- g_assert_cmpstr (end, ==, endptr);
- g_assert (err == error);
-}
-
-static void
-check_int64 (const gchar *str,
- const gchar *end,
- gint base,
- gint64 result,
- gint error)
-{
- gint64 actual;
- gchar *endptr = NULL;
- gint err;
-
- errno = 0;
- actual = g_ascii_strtoll (str, &endptr, base);
- err = errno;
-
- g_assert (actual == result);
- g_assert_cmpstr (end, ==, endptr);
- g_assert (err == error);
-}
-
-static void
-test_strtoll (void)
-{
- check_uint64 ("0", "", 10, 0, 0);
- check_uint64 ("+0", "", 10, 0, 0);
- check_uint64 ("-0", "", 10, 0, 0);
- check_uint64 ("18446744073709551615", "", 10, G_MAXUINT64, 0);
- check_uint64 ("18446744073709551616", "", 10, G_MAXUINT64, ERANGE);
- check_uint64 ("20xyz", "xyz", 10, 20, 0);
- check_uint64 ("-1", "", 10, G_MAXUINT64, 0);
-
- check_int64 ("0", "", 10, 0, 0);
- check_int64 ("9223372036854775807", "", 10, G_MAXINT64, 0);
- check_int64 ("9223372036854775808", "", 10, G_MAXINT64, ERANGE);
- check_int64 ("-9223372036854775808", "", 10, G_MININT64, 0);
- check_int64 ("-9223372036854775809", "", 10, G_MININT64, ERANGE);
- check_int64 ("32768", "", 10, 32768, 0);
- check_int64 ("-32768", "", 10, -32768, 0);
- check_int64 ("001", "", 10, 1, 0);
- check_int64 ("-001", "", 10, -1, 0);
-}
-
-static void
-test_bounds (void)
-{
- GMappedFile *file, *before, *after;
- char buffer[4097];
- char *tmp, *tmp2;
- char **array;
- char *string;
-
- /* if we allocate the file between two others and then free those
- * other two, then hopefully we end up with unmapped memory on either
- * side.
- */
- before = g_mapped_file_new ("4096-random-bytes", TRUE, NULL);
-
- /* quick workaround until #549783 can be fixed */
- if (before == NULL)
- return;
-
- file = g_mapped_file_new ("4096-random-bytes", TRUE, NULL);
- after = g_mapped_file_new ("4096-random-bytes", TRUE, NULL);
- g_mapped_file_free (before);
- g_mapped_file_free (after);
-
- g_assert (file != NULL);
- g_assert_cmpint (g_mapped_file_get_length (file), ==, 4096);
- string = g_mapped_file_get_contents (file);
-
- /* ensure they're all non-nul */
- g_assert (memchr (string, '\0', 4096) == NULL);
-
- /* test set 1: ensure that nothing goes past its maximum length, even in
- * light of a missing nul terminator.
- *
- * we try to test all of the 'n' functions here.
- */
- tmp = g_strndup (string, 4096);
- g_assert_cmpint (strlen (tmp), ==, 4096);
- g_free (tmp);
-
- /* found no bugs in gnome, i hope :) */
- g_assert (g_strstr_len (string, 4096, "BUGS") == NULL);
- g_strstr_len (string, 4096, "B");
- g_strstr_len (string, 4096, ".");
- g_strstr_len (string, 4096, "");
-
- g_strrstr_len (string, 4096, "BUGS");
- g_strrstr_len (string, 4096, "B");
- g_strrstr_len (string, 4096, ".");
- g_strrstr_len (string, 4096, "");
-
- g_ascii_strdown (string, 4096);
- g_ascii_strdown (string, 4096);
- g_ascii_strup (string, 4096);
- g_ascii_strup (string, 4096);
-
- g_ascii_strncasecmp (string, string, 4096);
-
- tmp = g_markup_escape_text (string, 4096);
- g_free (tmp);
-
- /* test set 2: ensure that nothing reads even one byte past a '\0'.
- */
- g_assert_cmpint (string[4095], ==, '\n');
- string[4095] = '\0';
-
- tmp = g_strdup (string);
- g_assert_cmpint (strlen (tmp), ==, 4095);
- g_free (tmp);
-
- tmp = g_strndup (string, 10000);
- g_assert_cmpint (strlen (tmp), ==, 4095);
- g_free (tmp);
-
- g_stpcpy (buffer, string);
- g_assert_cmpint (strlen (buffer), ==, 4095);
-
- g_strstr_len (string, 10000, "BUGS");
- g_strstr_len (string, 10000, "B");
- g_strstr_len (string, 10000, ".");
- g_strstr_len (string, 10000, "");
-
- g_strrstr (string, "BUGS");
- g_strrstr (string, "B");
- g_strrstr (string, ".");
- g_strrstr (string, "");
-
- g_strrstr_len (string, 10000, "BUGS");
- g_strrstr_len (string, 10000, "B");
- g_strrstr_len (string, 10000, ".");
- g_strrstr_len (string, 10000, "");
-
- g_str_has_prefix (string, "this won't do very much...");
- g_str_has_suffix (string, "but maybe this will...");
- g_str_has_suffix (string, "HMMMM.");
- g_str_has_suffix (string, "MMMM.");
- g_str_has_suffix (string, "M.");
-
- g_strlcpy (buffer, string, sizeof buffer);
- g_assert_cmpint (strlen (buffer), ==, 4095);
- g_strlcpy (buffer, string, sizeof buffer);
- buffer[0] = '\0';
- g_strlcat (buffer, string, sizeof buffer);
- g_assert_cmpint (strlen (buffer), ==, 4095);
-
- tmp = g_strdup_printf ("<%s>", string);
- g_assert_cmpint (strlen (tmp), ==, 4095 + 2);
- g_free (tmp);
-
- g_ascii_strdown (string, -1);
- g_ascii_strdown (string, -1);
- g_ascii_strup (string, -1);
- g_ascii_strup (string, -1);
-
- g_ascii_strcasecmp (string, string);
- g_ascii_strncasecmp (string, string, 10000);
-
- g_strreverse (string);
- g_strreverse (string);
- g_strchug (string);
- g_strchomp (string);
- g_strstrip (string);
- g_assert_cmpint (strlen (string), ==, 4095);
-
- g_strdelimit (string, "M", 'N');
- g_strcanon (string, " N.", ':');
- g_assert_cmpint (strlen (string), ==, 4095);
-
- array = g_strsplit (string, ".", -1);
- tmp = g_strjoinv (".", array);
- g_strfreev (array);
-
- g_assert_cmpint (strlen (tmp), ==, 4095);
- g_assert (memcmp (tmp, string, 4095) == 0);
- g_free (tmp);
-
- tmp = g_strconcat (string, string, string, NULL);
- g_assert_cmpint (strlen (tmp), ==, 4095 * 3);
- g_free (tmp);
-
- tmp = g_strjoin ("!", string, string, NULL);
- g_assert_cmpint (strlen (tmp), ==, 4095 + 1 + 4095);
- g_free (tmp);
-
- tmp = g_markup_escape_text (string, -1);
- g_free (tmp);
-
- tmp = g_markup_printf_escaped ("%s", string);
- g_free (tmp);
-
- tmp = g_strescape (string, NULL);
- tmp2 = g_strcompress (tmp);
- g_assert_cmpstr (string, ==, tmp2);
- g_free (tmp2);
- g_free (tmp);
-
- g_mapped_file_free (file);
-}
-
-int
-main (int argc,
- char *argv[])
-{
- g_test_init (&argc, &argv, NULL);
-
- g_test_add_func ("/strfuncs/test-is-to-digit", test_is_to_digit);
- g_test_add_func ("/strfuncs/strdup", test_strdup);
- g_test_add_func ("/strfuncs/strndup", test_strndup);
- g_test_add_func ("/strfuncs/strdup-printf", test_strdup_printf);
- g_test_add_func ("/strfuncs/strdupv", test_strdupv);
- g_test_add_func ("/strfuncs/strnfill", test_strnfill);
- g_test_add_func ("/strfuncs/strconcat", test_strconcat);
- g_test_add_func ("/strfuncs/strjoin", test_strjoin);
- g_test_add_func ("/strfuncs/strcanon", test_strcanon);
- g_test_add_func ("/strfuncs/strcompress-strescape", test_strcompress_strescape);
- g_test_add_func ("/strfuncs/ascii-strcasecmp", test_ascii_strcasecmp);
- g_test_add_func ("/strfuncs/strchug", test_strchug);
- g_test_add_func ("/strfuncs/strchomp", test_strchomp);
- g_test_add_func ("/strfuncs/strreverse", test_strreverse);
- g_test_add_func ("/strfuncs/strstr", test_strstr);
- g_test_add_func ("/strfuncs/has-prefix", test_has_prefix);
- g_test_add_func ("/strfuncs/has-suffix", test_has_suffix);
- g_test_add_func ("/strfuncs/strsplit", test_strsplit);
- g_test_add_func ("/strfuncs/strsplit-set", test_strsplit_set);
- g_test_add_func ("/strfuncs/strv-length", test_strv_length);
- g_test_add_func ("/strfuncs/strtod", test_strtod);
- g_test_add_func ("/strfuncs/strtoull-strtoll", test_strtoll);
- g_test_add_func ("/strfuncs/bounds-check", test_bounds);
-
- return g_test_run();
-}
diff --git a/glib/tests/string.c b/glib/tests/string.c
deleted file mode 100644
index 3ee03c6d7..000000000
--- a/glib/tests/string.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/* Unit tests for gstring
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This work is provided "as is"; redistribution and modification
- * in whole or in part, in any medium, physical or electronic is
- * permitted without restriction.
- *
- * This work 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.
- *
- * In no event shall the authors or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even
- * if advised of the possibility of such damage.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "glib.h"
-
-
-static void
-test_string_chunks (void)
-{
- GStringChunk *string_chunk;
- gchar *tmp_string, *tmp_string_2;
- gint i;
-
- string_chunk = g_string_chunk_new (1024);
-
- for (i = 0; i < 100000; i ++)
- {
- tmp_string = g_string_chunk_insert (string_chunk, "hi pete");
- g_assert_cmpstr ("hi pete", ==, tmp_string);
- }
-
- tmp_string_2 = g_string_chunk_insert_const (string_chunk, tmp_string);
- g_assert (tmp_string_2 != tmp_string);
- g_assert_cmpstr (tmp_string_2, ==, tmp_string);
-
- tmp_string = g_string_chunk_insert_const (string_chunk, tmp_string);
- g_assert_cmpstr (tmp_string_2, ==, tmp_string);
-
- g_string_chunk_free (string_chunk);
-}
-
-static void
-test_string_new (void)
-{
- GString *string1, *string2;
-
- string1 = g_string_new ("hi pete!");
- string2 = g_string_new (NULL);
-
- g_assert (string1 != NULL);
- g_assert (string2 != NULL);
- g_assert (strlen (string1->str) == string1->len);
- g_assert (strlen (string2->str) == string2->len);
- g_assert (string2->len == 0);
- g_assert_cmpstr ("hi pete!", ==, string1->str);
- g_assert_cmpstr ("", ==, string2->str);
-
- g_string_free (string1, TRUE);
- g_string_free (string2, TRUE);
-}
-
-static void
-test_string_printf (void)
-{
- GString *string;
-
- string = g_string_new (NULL);
-
-#ifndef G_OS_WIN32
- /* MSVC and mingw32 use the same run-time C library, which doesn't like
- the %10000.10000f format... */
- g_string_printf (string, "%s|%0100d|%s|%0*d|%*.*f|%10000.10000f",
- "this pete guy sure is a wuss, like he's the number ",
- 1,
- " wuss. everyone agrees.\n",
- 10, 666, 15, 15, 666.666666666, 666.666666666);
-#else
- g_string_printf (string, "%s|%0100d|%s|%0*d|%*.*f|%100.100f",
- "this pete guy sure is a wuss, like he's the number ",
- 1,
- " wuss. everyone agrees.\n",
- 10, 666, 15, 15, 666.666666666, 666.666666666);
-#endif
-
- g_string_free (string, TRUE);
-}
-
-static void
-test_string_assign (void)
-{
- GString *string;
-
- string = g_string_new (NULL);
- g_string_assign (string, "boring text");
- g_assert_cmpstr (string->str, ==, "boring text");
- g_string_free (string, TRUE);
-
- /* assign with string overlap */
- string = g_string_new ("textbeforetextafter");
- g_string_assign (string, string->str + 10);
- g_assert_cmpstr (string->str, ==, "textafter");
- g_string_free (string, TRUE);
-
- string = g_string_new ("boring text");
- g_string_assign (string, string->str);
- g_assert_cmpstr (string->str, ==, "boring text");
- g_string_free (string, TRUE);
-}
-
-static void
-test_string_append_c (void)
-{
- GString *string;
- gint i;
-
- string = g_string_new ("hi pete!");
-
- for (i = 0; i < 10000; i++)
- g_string_append_c (string, 'a'+(i%26));
-
- g_assert((strlen("hi pete!") + 10000) == string->len);
- g_assert((strlen("hi pete!") + 10000) == strlen(string->str));
-
- g_string_free (string, TRUE);
-}
-
-static void
-test_string_append (void)
-{
- GString *string;
-
- /* append */
- string = g_string_new ("firsthalf");
- g_string_append (string, "lasthalf");
- g_assert_cmpstr (string->str, ==, "firsthalflasthalf");
- g_string_free (string, TRUE);
-
- /* append_len */
- string = g_string_new ("firsthalf");
- g_string_append_len (string, "lasthalfjunkjunk", strlen ("lasthalf"));
- g_assert_cmpstr (string->str, ==, "firsthalflasthalf");
- g_string_free (string, TRUE);
-}
-
-static void
-test_string_prepend_c (void)
-{
- GString *string;
- gint i;
-
- string = g_string_new ("hi pete!");
-
- for (i = 0; i < 10000; i++)
- g_string_prepend_c (string, 'a'+(i%26));
-
- g_assert((strlen("hi pete!") + 10000) == string->len);
- g_assert((strlen("hi pete!") + 10000) == strlen(string->str));
-
- g_string_free (string, TRUE);
-}
-
-static void
-test_string_prepend (void)
-{
- GString *string;
-
- /* prepend */
- string = g_string_new ("lasthalf");
- g_string_prepend (string, "firsthalf");
- g_assert_cmpstr (string->str, ==, "firsthalflasthalf");
- g_string_free (string, TRUE);
-
- /* prepend_len */
- string = g_string_new ("lasthalf");
- g_string_prepend_len (string, "firsthalfjunkjunk", strlen ("firsthalf"));
- g_assert_cmpstr (string->str, ==, "firsthalflasthalf");
- g_string_free (string, TRUE);
-}
-
-static void
-test_string_insert (void)
-{
- GString *string;
-
- /* insert */
- string = g_string_new ("firstlast");
- g_string_insert (string, 5, "middle");
- g_assert_cmpstr (string->str, ==, "firstmiddlelast");
- g_string_free (string, TRUE);
-
- /* insert with pos == end of the string */
- string = g_string_new ("firstmiddle");
- g_string_insert (string, strlen ("firstmiddle"), "last");
- g_assert_cmpstr (string->str, ==, "firstmiddlelast");
- g_string_free (string, TRUE);
-
- /* insert_len */
- string = g_string_new ("firstlast");
- g_string_insert_len (string, 5, "middlejunkjunk", strlen ("middle"));
- g_assert_cmpstr (string->str, ==, "firstmiddlelast");
- g_string_free (string, TRUE);
-
- /* insert_len with magic -1 pos for append */
- string = g_string_new ("first");
- g_string_insert_len (string, -1, "lastjunkjunk", strlen ("last"));
- g_assert_cmpstr (string->str, ==, "firstlast");
- g_string_free (string, TRUE);
-
- /* insert_len with magic -1 len for strlen-the-string */
- string = g_string_new ("first");
- g_string_insert_len (string, 5, "last", -1);
- g_assert_cmpstr (string->str, ==, "firstlast");
- g_string_free (string, TRUE);
-
- /* insert_len with string overlap */
- string = g_string_new ("textbeforetextafter");
- g_string_insert_len (string, 10, string->str + 8, 5);
- g_assert_cmpstr (string->str, ==, "textbeforeretextextafter");
- g_string_free (string, TRUE);
-}
-
-static void
-test_string_insert_unichar (void)
-{
- GString *string;
-
- /* insert_unichar with insertion in middle */
- string = g_string_new ("firsthalf");
- g_string_insert_unichar (string, 5, 0x0041);
- g_assert_cmpstr (string->str, ==, "first\x41half");
- g_string_free (string, TRUE);
-
- string = g_string_new ("firsthalf");
- g_string_insert_unichar (string, 5, 0x0298);
- g_assert_cmpstr (string->str, ==, "first\xCA\x98half");
- g_string_free (string, TRUE);
-
- string = g_string_new ("firsthalf");
- g_string_insert_unichar (string, 5, 0xFFFD);
- g_assert_cmpstr (string->str, ==, "first\xEF\xBF\xBDhalf");
- g_string_free (string, TRUE);
-
- string = g_string_new ("firsthalf");
- g_string_insert_unichar (string, 5, 0x1D100);
- g_assert_cmpstr (string->str, ==, "first\xF0\x9D\x84\x80half");
- g_string_free (string, TRUE);
-
- /* insert_unichar with insertion at end */
- string = g_string_new ("start");
- g_string_insert_unichar (string, -1, 0x0041);
- g_assert_cmpstr (string->str, ==, "start\x41");
- g_string_free (string, TRUE);
-
- string = g_string_new ("start");
- g_string_insert_unichar (string, -1, 0x0298);
- g_assert_cmpstr (string->str, ==, "start\xCA\x98");
- g_string_free (string, TRUE);
-
- string = g_string_new ("start");
- g_string_insert_unichar (string, -1, 0xFFFD);
- g_assert_cmpstr (string->str, ==, "start\xEF\xBF\xBD");
- g_string_free (string, TRUE);
-
- string = g_string_new ("start");
- g_string_insert_unichar (string, -1, 0x1D100);
- g_assert_cmpstr (string->str, ==, "start\xF0\x9D\x84\x80");
- g_string_free (string, TRUE);
-}
-
-static void
-test_string_equal (void)
-{
- GString *string1, *string2;
-
- string1 = g_string_new ("test");
- string2 = g_string_new ("te");
- g_assert (!g_string_equal(string1, string2));
- g_string_append (string2, "st");
- g_assert (g_string_equal(string1, string2));
- g_string_free (string1, TRUE);
- g_string_free (string2, TRUE);
-}
-
-static void
-test_string_truncate (void)
-{
- GString *string;
-
- string = g_string_new ("testing");
-
- g_string_truncate (string, 1000);
- g_assert (string->len == strlen("testing"));
- g_assert_cmpstr (string->str, ==, "testing");
-
- g_string_truncate (string, 4);
- g_assert (string->len == 4);
- g_assert_cmpstr (string->str, ==, "test");
-
- g_string_truncate (string, 0);
- g_assert (string->len == 0);
- g_assert_cmpstr (string->str, ==, "");
-
- g_string_free (string, TRUE);
-}
-
-static void
-test_string_overwrite (void)
-{
- GString *string;
-
- /* overwriting functions */
- string = g_string_new ("testing");
-
- g_string_overwrite (string, 4, " and expand");
- g_assert (15 == string->len);
- g_assert ('\0' == string->str[15]);
- g_assert (g_str_equal ("test and expand", string->str));
-
- g_string_overwrite (string, 5, "NOT-");
- g_assert (15 == string->len);
- g_assert ('\0' == string->str[15]);
- g_assert (g_str_equal ("test NOT-expand", string->str));
-
- g_string_overwrite_len (string, 9, "blablabla", 6);
- g_assert (15 == string->len);
- g_assert ('\0' == string->str[15]);
- g_assert (g_str_equal ("test NOT-blabla", string->str));
-
- g_string_free (string, TRUE);
-}
-
-static void
-test_string_nul_handling (void)
-{
- GString *string1, *string2;
-
- /* Check handling of embedded ASCII 0 (NUL) characters in GString. */
- string1 = g_string_new ("fiddle");
- string2 = g_string_new ("fiddle");
- g_assert (g_string_equal (string1, string2));
- g_string_append_c (string1, '\0');
- g_assert (!g_string_equal (string1, string2));
- g_string_append_c (string2, '\0');
- g_assert (g_string_equal (string1, string2));
- g_string_append_c (string1, 'x');
- g_string_append_c (string2, 'y');
- g_assert (!g_string_equal (string1, string2));
- g_assert (string1->len == 8);
- g_string_append (string1, "yzzy");
- g_assert (string1->len == 12);
- g_assert (memcmp (string1->str, "fiddle\0xyzzy", 13) == 0);
- g_string_insert (string1, 1, "QED");
- g_assert (memcmp (string1->str, "fQEDiddle\0xyzzy", 16) == 0);
- g_string_printf (string1, "fiddle%cxyzzy", '\0');
- g_assert (string1->len == 12);
- g_assert (memcmp (string1->str, "fiddle\0xyzzy", 13) == 0);
-
- g_string_free (string1, TRUE);
- g_string_free (string2, TRUE);
-}
-
-int
-main (int argc,
- char *argv[])
-{
- g_test_init (&argc, &argv, NULL);
-
- g_test_add_func ("/string/test-string-chunks", test_string_chunks);
- g_test_add_func ("/string/test-string-new", test_string_new);
- g_test_add_func ("/string/test-string-printf", test_string_printf);
- g_test_add_func ("/string/test-string-assign", test_string_assign);
- g_test_add_func ("/string/test-string-append-c", test_string_append_c);
- g_test_add_func ("/string/test-string-append", test_string_append);
- g_test_add_func ("/string/test-string-prepend-c", test_string_prepend_c);
- g_test_add_func ("/string/test-string-prepend", test_string_prepend);
- g_test_add_func ("/string/test-string-insert", test_string_insert);
- g_test_add_func ("/string/test-string-insert-unichar", test_string_insert_unichar);
- g_test_add_func ("/string/test-string-equal", test_string_equal);
- g_test_add_func ("/string/test-string-truncate", test_string_truncate);
- g_test_add_func ("/string/test-string-overwrite", test_string_overwrite);
- g_test_add_func ("/string/test-string-nul-handling", test_string_nul_handling);
-
- return g_test_run();
-}
diff --git a/glib/tests/testing.c b/glib/tests/testing.c
deleted file mode 100644
index cfbf8d4d2..000000000
--- a/glib/tests/testing.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/* GLib testing framework examples and tests
- * Copyright (C) 2007 Imendio AB
- * Authors: Tim Janik
- *
- * This work is provided "as is"; redistribution and modification
- * in whole or in part, in any medium, physical or electronic is
- * permitted without restriction.
- *
- * This work 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.
- *
- * In no event shall the authors or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even
- * if advised of the possibility of such damage.
- */
-
-#include <glib.h>
-
-#include <stdlib.h>
-
-/* test assertion variants */
-static void
-test_assertions (void)
-{
- gchar *fuu;
- g_assert_cmpint (1, >, 0);
- g_assert_cmphex (2, ==, 2);
- g_assert_cmpfloat (3.3, !=, 7);
- g_assert_cmpfloat (7, <=, 3 + 4);
- g_assert (TRUE);
- g_assert_cmpstr ("foo", !=, "faa");
- fuu = g_strdup_printf ("f%s", "uu");
- g_test_queue_free (fuu);
- g_assert_cmpstr ("foo", !=, fuu);
- g_assert_cmpstr ("fuu", ==, fuu);
- g_assert_cmpstr (NULL, <, "");
- g_assert_cmpstr (NULL, ==, NULL);
- g_assert_cmpstr ("", >, NULL);
- g_assert_cmpstr ("foo", <, "fzz");
- g_assert_cmpstr ("fzz", >, "faa");
- g_assert_cmpstr ("fzz", ==, "fzz");
-}
-
-/* test g_test_timer* API */
-static void
-test_timer (void)
-{
- double ttime;
- g_test_timer_start();
- g_assert_cmpfloat (g_test_timer_last(), ==, 0);
- g_usleep (25 * 1000);
- ttime = g_test_timer_elapsed();
- g_assert_cmpfloat (ttime, >, 0);
- g_assert_cmpfloat (g_test_timer_last(), ==, ttime);
- g_test_minimized_result (ttime, "timer-test-time: %fsec", ttime);
- g_test_maximized_result (5, "bogus-quantity: %ddummies", 5); /* simple API test */
-}
-
-/* fork out for a failing test */
-static void
-test_fork_fail (void)
-{
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
- {
- g_assert_not_reached();
- }
- g_test_trap_assert_failed();
- g_test_trap_assert_stderr ("*ERROR*test_fork_fail*should not be reached*");
-}
-
-/* fork out to assert stdout and stderr patterns */
-static void
-test_fork_patterns (void)
-{
- if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
- {
- g_print ("some stdout text: somagic17\n");
- g_printerr ("some stderr text: semagic43\n");
- exit (0);
- }
- g_test_trap_assert_passed();
- g_test_trap_assert_stdout ("*somagic17*");
- g_test_trap_assert_stderr ("*semagic43*");
-}
-
-/* fork out for a timeout test */
-static void
-test_fork_timeout (void)
-{
- /* allow child to run for only a fraction of a second */
- if (g_test_trap_fork (0.11 * 1000000, 0))
- {
- /* loop and sleep forever */
- while (TRUE)
- g_usleep (1000 * 1000);
- }
- g_test_trap_assert_failed();
- g_assert (g_test_trap_reached_timeout());
-}
-
-/* run a test with fixture setup and teardown */
-typedef struct {
- guint seed;
- guint prime;
- gchar *msg;
-} Fixturetest;
-static void
-fixturetest_setup (Fixturetest *fix,
- gconstpointer test_data)
-{
- g_assert (test_data == (void*) 0xc0cac01a);
- fix->seed = 18;
- fix->prime = 19;
- fix->msg = g_strdup_printf ("%d", fix->prime);
-}
-static void
-fixturetest_test (Fixturetest *fix,
- gconstpointer test_data)
-{
- guint prime = g_spaced_primes_closest (fix->seed);
- g_assert_cmpint (prime, ==, fix->prime);
- prime = g_ascii_strtoull (fix->msg, NULL, 0);
- g_assert_cmpint (prime, ==, fix->prime);
- g_assert (test_data == (void*) 0xc0cac01a);
-}
-static void
-fixturetest_teardown (Fixturetest *fix,
- gconstpointer test_data)
-{
- g_assert (test_data == (void*) 0xc0cac01a);
- g_free (fix->msg);
-}
-
-static struct {
- int bit, vint1, vint2, irange;
- long double vdouble, drange;
-} shared_rand_state;
-
-static void
-test_rand1 (void)
-{
- shared_rand_state.bit = g_test_rand_bit();
- shared_rand_state.vint1 = g_test_rand_int();
- shared_rand_state.vint2 = g_test_rand_int();
- g_assert_cmpint (shared_rand_state.vint1, !=, shared_rand_state.vint2);
- shared_rand_state.irange = g_test_rand_int_range (17, 35);
- g_assert_cmpint (shared_rand_state.irange, >=, 17);
- g_assert_cmpint (shared_rand_state.irange, <=, 35);
- shared_rand_state.vdouble = g_test_rand_double();
- shared_rand_state.drange = g_test_rand_double_range (-999, +17);
- g_assert_cmpfloat (shared_rand_state.drange, >=, -999);
- g_assert_cmpfloat (shared_rand_state.drange, <=, +17);
-}
-
-static void
-test_rand2 (void)
-{
- /* this test only works if run after test1.
- * we do this to check that random number generators
- * are reseeded upon fixture setup.
- */
- g_assert_cmpint (shared_rand_state.bit, ==, g_test_rand_bit());
- g_assert_cmpint (shared_rand_state.vint1, ==, g_test_rand_int());
- g_assert_cmpint (shared_rand_state.vint2, ==, g_test_rand_int());
- g_assert_cmpint (shared_rand_state.irange, ==, g_test_rand_int_range (17, 35));
- g_assert_cmpfloat (shared_rand_state.vdouble, ==, g_test_rand_double());
- g_assert_cmpfloat (shared_rand_state.drange, ==, g_test_rand_double_range (-999, +17));
-}
-
-static void
-test_data_test (gconstpointer test_data)
-{
- g_assert (test_data == (void*) 0xc0c0baba);
-}
-
-static void
-test_random_conversions (void)
-{
- /* very simple conversion test using random numbers */
- int vint = g_test_rand_int();
- char *err, *str = g_strdup_printf ("%d", vint);
- gint64 vint64 = g_ascii_strtoll (str, &err, 10);
- g_assert_cmphex (vint, ==, vint64);
- g_assert (!err || *err == 0);
- g_free (str);
-}
-
-int
-main (int argc,
- char *argv[])
-{
- g_test_init (&argc, &argv, NULL);
-
- g_test_add_func ("/random-generator/rand-1", test_rand1);
- g_test_add_func ("/random-generator/rand-2", test_rand2);
- g_test_add_func ("/random-generator/random-conversions", test_random_conversions);
- g_test_add_func ("/misc/assertions", test_assertions);
- g_test_add_data_func ("/misc/test-data", (void*) 0xc0c0baba, test_data_test);
- g_test_add ("/misc/primetoul", Fixturetest, (void*) 0xc0cac01a, fixturetest_setup, fixturetest_test, fixturetest_teardown);
- if (g_test_perf())
- g_test_add_func ("/misc/timer", test_timer);
- g_test_add_func ("/forking/fail assertion", test_fork_fail);
- g_test_add_func ("/forking/patterns", test_fork_patterns);
- if (g_test_slow())
- g_test_add_func ("/forking/timeout", test_fork_timeout);
-
- return g_test_run();
-}
diff --git a/glib/update-pcre/Makefile.am b/glib/update-pcre/Makefile.am
deleted file mode 100644
index b7f80c61f..000000000
--- a/glib/update-pcre/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-include $(top_srcdir)/Makefile.decl
-
-EXTRA_DIST += \
- update.sh \
- Makefile.am-1 \
- Makefile.am-2 \
- digitab.patch \
- memory.patch \
- pcre_ucp_searchfuncs.c \
- pcre_valid_utf8.c
diff --git a/glib/update-pcre/Makefile.am-1 b/glib/update-pcre/Makefile.am-1
deleted file mode 100644
index d4255b754..000000000
--- a/glib/update-pcre/Makefile.am-1
+++ /dev/null
@@ -1,30 +0,0 @@
-INCLUDES = \
- -DG_LOG_DOMAIN=\"GLib-GRegex\" \
- -DSUPPORT_UCP \
- -DSUPPORT_UTF8 \
- -DNEWLINE=-1 \
- -DMATCH_LIMIT=10000000 \
- -DMATCH_LIMIT_RECURSION=10000000 \
- -DMAX_NAME_SIZE=32 \
- -DMAX_NAME_COUNT=10000 \
- -DMAX_DUPLENGTH=30000 \
- -DLINK_SIZE=2 \
- -DEBCDIC=0 \
- -DPOSIX_MALLOC_THRESHOLD=10 \
- -DPCRE_STATIC \
- -I$(top_srcdir) \
- -I$(srcdir) \
- -I$(top_srcdir)/glib \
- @GLIB_DEBUG_FLAGS@ \
- -DG_DISABLE_DEPRECATED \
- -DGLIB_COMPILATION \
- $(DEPRECATED_FLAGS)\
- $(WARN_CFLAGS) \
- $(PCRE_WARN_CFLAGS) \
- $(DEP_CFLAGS)
-
-noinst_LTLIBRARIES = libpcre.la
-
-libpcre_headers =
-
-libpcre_la_SOURCES = \
diff --git a/glib/update-pcre/Makefile.am-2 b/glib/update-pcre/Makefile.am-2
deleted file mode 100644
index 94d4d3c66..000000000
--- a/glib/update-pcre/Makefile.am-2
+++ /dev/null
@@ -1,10 +0,0 @@
- $(libpcre_headers)
-
-libpcre_la_LIBADD = $(DEP_LIBS)
-
-libpcre_la_LDFLAGS = -no-undefined
-
-EXTRA_DIST = \
- COPYING \
- makefile.msc
-
diff --git a/glib/update-pcre/digitab.patch b/glib/update-pcre/digitab.patch
deleted file mode 100644
index a745fbb42..000000000
--- a/glib/update-pcre/digitab.patch
+++ /dev/null
@@ -1,133 +0,0 @@
---- pcre_compile.c 2006-10-10 12:00:00.000000000 +0200
-+++ pcre_compile.c 2006-10-10 12:00:00.000000000 +0200
-@@ -246,130 +246,6 @@ static const char *error_texts[] = {
- };
-
-
--/* Table to identify digits and hex digits. This is used when compiling
--patterns. Note that the tables in chartables are dependent on the locale, and
--may mark arbitrary characters as digits - but the PCRE compiling code expects
--to handle only 0-9, a-z, and A-Z as digits when compiling. That is why we have
--a private table here. It costs 256 bytes, but it is a lot faster than doing
--character value tests (at least in some simple cases I timed), and in some
--applications one wants PCRE to compile efficiently as well as match
--efficiently.
--
--For convenience, we use the same bit definitions as in chartables:
--
-- 0x04 decimal digit
-- 0x08 hexadecimal digit
--
--Then we can use ctype_digit and ctype_xdigit in the code. */
--
--#if !EBCDIC /* This is the "normal" case, for ASCII systems */
--static const unsigned char digitab[] =
-- {
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */
-- 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 */
-- 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */
-- 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* @ - G */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H - O */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* P - W */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* X - _ */
-- 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* ` - g */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h - o */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p - w */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x -127 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */
--
--#else /* This is the "abnormal" case, for EBCDIC systems */
--static const unsigned char digitab[] =
-- {
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 0 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 10 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32- 39 20 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 30 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 40 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 72- | */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 50 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 88- ¬ */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 60 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 104- ? */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 70 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */
-- 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* 128- g 80 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144- p 90 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160- x A0 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 B0 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
-- 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* { - G C0 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* } - P D0 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* \ - X E0 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */
-- 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 F0 */
-- 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */
--
--static const unsigned char ebcdic_chartab[] = { /* chartable partial dup */
-- 0x80,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 0- 7 */
-- 0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */
-- 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 16- 23 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
-- 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 32- 39 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */
-- 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 */
-- 0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80, /* 72- | */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 */
-- 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, /* 88- ¬ */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 */
-- 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x80, /* 104- ? */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 */
-- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */
-- 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* 128- g */
-- 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */
-- 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* 144- p */
-- 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */
-- 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* 160- x */
-- 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */
-- 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 */
-- 0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
-- 0x80,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* { - G */
-- 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */
-- 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* } - P */
-- 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */
-- 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* \ - X */
-- 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */
-- 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */
-- 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */
--#endif
--
--
- /* Definition to allow mutual recursion */
-
- static BOOL
diff --git a/glib/update-pcre/make_utt.py b/glib/update-pcre/make_utt.py
deleted file mode 100644
index 20c720e08..000000000
--- a/glib/update-pcre/make_utt.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#! /usr/bin/env python
-
-# Reduce the number of relocations using a single string for the
-# keys in the _pcre_utt table.
-
-import re
-
-fin = open('pcre_tables.c')
-data = fin.read()
-fin.close()
-
-mo = re.search(r'const ucp_type_table _pcre_utt\[] = {', data)
-assert mo, '_pcre_utt not found'
-before = data[:mo.start()]
-table_decl = data[mo.start():mo.end()]
-table_start = mo.end()
-
-mo = re.compile('};').search(data, table_start)
-assert mo, 'end of _pcre_utt not found'
-after = data[mo.end():]
-table_end = mo.start()
-
-table = data[table_start:table_end].strip()
-
-rs = '\s*\{\s*"(?P<name>[^"]*)",\s*(?P<type>PT_[A-Z]*),\s*(?P<value>(?:0|ucp_[A-Za-z_]*))\s*},?\s*$'
-r = re.compile(rs)
-
-lines = []
-names = []
-pos = 0
-for line in table.split('\n'):
- mo = r.match(line)
- assert mo, 'line not recognized'
- name, type, value = mo.groups()
- lines.append(' { %d, %s, %s }' % (pos, type, value))
- names.append(name)
- # +1 for the '\0'
- pos += len(name) + 1
-
-table = ',\n'.join(lines)
-
-names = [' "%s\\0"' % n for n in names]
-names_string = ' \n'.join(names) + ';'
-
-data = before + \
- 'const char _pcre_ucp_names[] =\n' + \
- names_string + \
- '\n\n' + \
- table_decl + \
- '\n' + \
- table + \
- '\n};' + \
- after
-
-fout = open('pcre_tables.c', 'w')
-fout.write(data)
-fout.close()
diff --git a/glib/update-pcre/memory.patch b/glib/update-pcre/memory.patch
deleted file mode 100644
index 65b7b9790..000000000
--- a/glib/update-pcre/memory.patch
+++ /dev/null
@@ -1,87 +0,0 @@
-diff -r 0f4042339eb5 pcre/pcre.h
---- pcre/pcre.h Tue Jul 25 22:39:16 2006 +0200
-+++ pcre/pcre.h Tue Jul 25 22:52:10 2006 +0200
-@@ -233,25 +233,14 @@ typedef struct pcre_callout_block {
- /* ------------------------------------------------------------------ */
- } pcre_callout_block;
-
--/* Indirection for store get and free functions. These can be set to
--alternative malloc/free functions if required. Special ones are used in the
--non-recursive case for "frames". There is also an optional callout function
--that is triggered by the (?) regex item. For Virtual Pascal, these definitions
--have to take another form. */
--
--#ifndef VPCOMPAT
--PCRE_DATA_SCOPE void *(*pcre_malloc)(size_t);
--PCRE_DATA_SCOPE void (*pcre_free)(void *);
--PCRE_DATA_SCOPE void *(*pcre_stack_malloc)(size_t);
--PCRE_DATA_SCOPE void (*pcre_stack_free)(void *);
-+#include "glib.h"
-+#include "galias.h"
-+
-+#define pcre_malloc g_try_malloc
-+#define pcre_free g_free
-+#define pcre_stack_malloc g_try_malloc
-+
- PCRE_DATA_SCOPE int (*pcre_callout)(pcre_callout_block *);
--#else /* VPCOMPAT */
--PCRE_DATA_SCOPE void *pcre_malloc(size_t);
--PCRE_DATA_SCOPE void pcre_free(void *);
--PCRE_DATA_SCOPE void *pcre_stack_malloc(size_t);
--PCRE_DATA_SCOPE void pcre_stack_free(void *);
--PCRE_DATA_SCOPE int pcre_callout(pcre_callout_block *);
--#endif /* VPCOMPAT */
-
- /* Exported PCRE functions */
-
-diff -r 0f4042339eb5 pcre/pcre_globals.c
---- pcre/pcre_globals.c Tue Jul 25 22:39:16 2006 +0200
-+++ pcre/pcre_globals.c Tue Jul 25 22:52:10 2006 +0200
-@@ -50,32 +50,9 @@ differently, and global variables are no
- #include "pcre_internal.h"
-
-
--#ifndef VPCOMPAT
--
--/**************************************************************************
--This code used to be here for use when compiling as a C++ library. However,
--according to Dair Grant it is not needed: "
--
-- Including 'extern "C"' in the declaration generates an "initialized and
-- declared `extern'" warning from gcc 4.0.1. Since we include pcre_internal.h,
-- which includes pcre.h, which declares these prototypes within an extern "C" {}
-- block, we shouldn't need the prefix here.
--
--So, from Release 7.0 I have cut this out.
--
- #ifdef __cplusplus
--extern "C" void *(*pcre_malloc)(size_t) = malloc;
--extern "C" void (*pcre_free)(void *) = free;
--extern "C" void *(*pcre_stack_malloc)(size_t) = malloc;
--extern "C" void (*pcre_stack_free)(void *) = free;
- extern "C" int (*pcre_callout)(pcre_callout_block *) = NULL;
- #else
--**************************************************************************/
--
--void *(*pcre_malloc)(size_t) = malloc;
--void (*pcre_free)(void *) = free;
--void *(*pcre_stack_malloc)(size_t) = malloc;
--void (*pcre_stack_free)(void *) = free;
- int (*pcre_callout)(pcre_callout_block *) = NULL;
- #endif
-
-diff -r 0f4042339eb5 pcre/pcre_internal.h
---- pcre/pcre_internal.h Tue Jul 25 22:39:16 2006 +0200
-+++ pcre/pcre_internal.h Tue Jul 25 22:52:10 2006 +0200
-@@ -480,10 +480,7 @@ variable-length repeat, or a anything ot
-
- /* Miscellaneous definitions */
-
--typedef int BOOL;
--
--#define FALSE 0
--#define TRUE 1
-+typedef gboolean BOOL;
-
- /* Escape items that are just an encoding of a particular data value. */
-
diff --git a/glib/update-pcre/pcre_ucp_searchfuncs.c b/glib/update-pcre/pcre_ucp_searchfuncs.c
deleted file mode 100644
index b95d2794c..000000000
--- a/glib/update-pcre/pcre_ucp_searchfuncs.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- Copyright (c) 1997-2006 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-/* This file has been modified to use glib instead of the internal table
- * in ucptable.c -- Marco Barisione */
-
-/* This module contains code for searching the table of Unicode character
-properties. */
-
-#include "pcre_internal.h"
-
-#include "ucp.h" /* Category definitions */
-#include "ucpinternal.h" /* Internal table details */
-
-
-/* Table to translate from particular type value to the general value. */
-
-static int ucp_gentype[] = {
- ucp_C, ucp_C, ucp_C, ucp_C, ucp_C, /* Cc, Cf, Cn, Co, Cs */
- ucp_L, ucp_L, ucp_L, ucp_L, ucp_L, /* Ll, Lu, Lm, Lo, Lt */
- ucp_M, ucp_M, ucp_M, /* Mc, Me, Mn */
- ucp_N, ucp_N, ucp_N, /* Nd, Nl, No */
- ucp_P, ucp_P, ucp_P, ucp_P, ucp_P, /* Pc, Pd, Pe, Pf, Pi */
- ucp_P, ucp_P, /* Ps, Po */
- ucp_S, ucp_S, ucp_S, ucp_S, /* Sc, Sk, Sm, So */
- ucp_Z, ucp_Z, ucp_Z /* Zl, Zp, Zs */
-};
-
-
-
-/*************************************************
-* Search table and return type *
-*************************************************/
-
-/* Three values are returned: the category is ucp_C, ucp_L, etc. The detailed
-character type is ucp_Lu, ucp_Nd, etc. The script is ucp_Latin, etc.
-
-Arguments:
- c the character value
- type_ptr the detailed character type is returned here
- script_ptr the script is returned here
-
-Returns: the character type category
-*/
-
-int
-_pcre_ucp_findprop(const unsigned int c, int *type_ptr, int *script_ptr)
-{
-/* Note that the Unicode types have the same values in glib and in
- * PCRE, so ucp_Ll == G_UNICODE_LOWERCASE_LETTER,
- * ucp_Zs == G_UNICODE_SPACE_SEPARATOR, and so on. */
-*type_ptr = g_unichar_type(c);
-*script_ptr = g_unichar_get_script(c);
-return ucp_gentype[*type_ptr];
-}
-
-
-
-
-/*************************************************
-* Search table and return other case *
-*************************************************/
-
-/* If the given character is a letter, and there is another case for the
-letter, return the other case. Otherwise, return -1.
-
-Arguments:
- c the character value
-
-Returns: the other case or NOTACHAR if none
-*/
-
-unsigned int
-_pcre_ucp_othercase(const unsigned int c)
-{
-int other_case = NOTACHAR;
-
-if (g_unichar_islower(c))
- other_case = g_unichar_toupper(c);
-else if (g_unichar_isupper(c))
- other_case = g_unichar_tolower(c);
-
-if (other_case == c)
- other_case = NOTACHAR;
-
-return other_case;
-}
-
-
-/* End of pcre_ucp_searchfuncs.c */
diff --git a/glib/update-pcre/pcre_valid_utf8.c b/glib/update-pcre/pcre_valid_utf8.c
deleted file mode 100644
index a5766b454..000000000
--- a/glib/update-pcre/pcre_valid_utf8.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "pcre_internal.h"
-
-/*
- * This function is not needed by GRegex, so print an error and
- * return always -1, that is the string is a valid UTF-8 encoded
- * string.
- */
-int
-_pcre_valid_utf8(const uschar *string, int length)
-{
-g_warning ("%s: this function should not be called", G_STRLOC);
-return -1;
-}
diff --git a/glib/update-pcre/table-reduction.patch b/glib/update-pcre/table-reduction.patch
deleted file mode 100644
index 7cc78192b..000000000
--- a/glib/update-pcre/table-reduction.patch
+++ /dev/null
@@ -1,269 +0,0 @@
---- pcre_compile.c 2006-10-10 12:00:00.000000000 +0200
-+++ pcre_compile.c 2006-10-10 12:00:00.000000000 +0200
-@@ -129,10 +129,21 @@
- terminated by a zero length entry. The first three must be alpha, lower, upper,
- as this is assumed for handling case independence. */
-
--static const char *const posix_names[] = {
-- "alpha", "lower", "upper",
-- "alnum", "ascii", "blank", "cntrl", "digit", "graph",
-- "print", "punct", "space", "word", "xdigit" };
-+static const char posix_names[] =
-+ "alpha\0"
-+ "lower\0"
-+ "upper\0"
-+ "alnum\0"
-+ "ascii\0"
-+ "blank\0"
-+ "cntrl\0"
-+ "digit\0"
-+ "graph\0"
-+ "print\0"
-+ "punct\0"
-+ "space\0"
-+ "word\0"
-+ "xdigit";
-
- static const uschar posix_name_lengths[] = {
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };
-@@ -173,76 +184,138 @@
- they are documented. Always add a new error instead. Messages marked DEAD below
- are no longer used. */
-
--static const char *error_texts[] = {
-- "no error",
-- "\\ at end of pattern",
-- "\\c at end of pattern",
-- "unrecognized character follows \\",
-- "numbers out of order in {} quantifier",
-+#define DEAD(s) "\0"
-+
-+static const char error_texts[] =
-+ "no error\0"
-+ "\\ at end of pattern\0"
-+ "\\c at end of pattern\0"
-+ "unrecognized character follows \\\0"
-+ "numbers out of order in {} quantifier\0"
- /* 5 */
-- "number too big in {} quantifier",
-- "missing terminating ] for character class",
-- "invalid escape sequence in character class",
-- "range out of order in character class",
-- "nothing to repeat",
-+ "number too big in {} quantifier\0"
-+ "missing terminating ] for character class\0"
-+ "invalid escape sequence in character class\0"
-+ "range out of order in character class\0"
-+ "nothing to repeat\0"
- /* 10 */
-- "operand of unlimited repeat could match the empty string", /** DEAD **/
-- "internal error: unexpected repeat",
-- "unrecognized character after (?",
-- "POSIX named classes are supported only within a class",
-- "missing )",
-+ DEAD("operand of unlimited repeat could match the empty string")
-+ "internal error: unexpected repeat\0"
-+ "unrecognized character after (?\0"
-+ "POSIX named classes are supported only within a class\0"
-+ "missing )\0"
- /* 15 */
-- "reference to non-existent subpattern",
-- "erroffset passed as NULL",
-- "unknown option bit(s) set",
-- "missing ) after comment",
-- "parentheses nested too deeply", /** DEAD **/
-+ "reference to non-existent subpattern\0"
-+ "erroffset passed as NULL\0"
-+ "unknown option bit(s) set\0"
-+ "missing ) after comment\0"
-+ DEAD("parentheses nested too deeply")
- /* 20 */
-- "regular expression too large",
-- "failed to get memory",
-- "unmatched parentheses",
-- "internal error: code overflow",
-- "unrecognized character after (?<",
-+ "regular expression too large\0"
-+ "failed to get memory\0"
-+ "unmatched parentheses\0"
-+ "internal error: code overflow\0"
-+ "unrecognized character after (?<\0"
- /* 25 */
-- "lookbehind assertion is not fixed length",
-- "malformed number or name after (?(",
-- "conditional group contains more than two branches",
-- "assertion expected after (?(",
-- "(?R or (?digits must be followed by )",
-+ "lookbehind assertion is not fixed length\0"
-+ "malformed number or name after (?(\0"
-+ "conditional group contains more than two branches\0"
-+ "assertion expected after (?(\0"
-+ "(?R or (?digits must be followed by )\0"
- /* 30 */
-- "unknown POSIX class name",
-- "POSIX collating elements are not supported",
-- "this version of PCRE is not compiled with PCRE_UTF8 support",
-- "spare error", /** DEAD **/
-- "character value in \\x{...} sequence is too large",
-+ "unknown POSIX class name\0"
-+ "POSIX collating elements are not supported\0"
-+ "this version of PCRE is not compiled with PCRE_UTF8 support\0"
-+ DEAD("spare error")
-+ "character value in \\x{...} sequence is too large\0"
- /* 35 */
-- "invalid condition (?(0)",
-- "\\C not allowed in lookbehind assertion",
-- "PCRE does not support \\L, \\l, \\N, \\U, or \\u",
-- "number after (?C is > 255",
-- "closing ) for (?C expected",
-+ "invalid condition (?(0)\0"
-+ "\\C not allowed in lookbehind assertion\0"
-+ "PCRE does not support \\L, \\l, \\N, \\U, or \\u\0"
-+ "number after (?C is > 255\0"
-+ "closing ) for (?C expected\0"
- /* 40 */
-- "recursive call could loop indefinitely",
-- "unrecognized character after (?P",
-- "syntax error in subpattern name (missing terminator)",
-- "two named subpatterns have the same name",
-- "invalid UTF-8 string",
-+ "recursive call could loop indefinitely\0"
-+ "unrecognized character after (?P\0"
-+ "syntax error in subpattern name (missing terminator)\0"
-+ "two named subpatterns have the same name\0"
-+ "invalid UTF-8 string\0"
- /* 45 */
-- "support for \\P, \\p, and \\X has not been compiled",
-- "malformed \\P or \\p sequence",
-- "unknown property name after \\P or \\p",
-- "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " characters)",
-- "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")",
-+ "support for \\P, \\p, and \\X has not been compiled\0"
-+ "malformed \\P or \\p sequence\0"
-+ "unknown property name after \\P or \\p\0"
-+ "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " characters)\0"
-+ "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0"
- /* 50 */
-- "repeated subpattern is too long",
-- "octal value is greater than \\377 (not in UTF-8 mode)",
-- "internal error: overran compiling workspace",
-- "internal error: previously-checked referenced subpattern not found",
-- "DEFINE group contains more than one branch",
-+ "repeated subpattern is too long\0"
-+ "octal value is greater than \\377 (not in UTF-8 mode)\0"
-+ "internal error: overran compiling workspace\0"
-+ "internal error: previously-checked referenced subpattern not found\0"
-+ "DEFINE group contains more than one branch\0"
- /* 55 */
-- "repeating a DEFINE group is not allowed",
-- "inconsistent NEWLINE options",
-- "\\g is not followed by an (optionally braced) non-zero number"
-+ "repeating a DEFINE group is not allowed\0"
-+ "inconsistent NEWLINE options\0"
-+ "\\g is not followed by an (optionally braced) non-zero number";
-+
-+static const int error_texts_offsets[] = {
-+ 0,
-+ 9,
-+ 29,
-+ 50,
-+ 83,
-+ 121,
-+ 153,
-+ 195,
-+ 238,
-+ 276,
-+ 294,
-+ 295,
-+ 329,
-+ 361,
-+ 415,
-+ 425,
-+ 462,
-+ 487,
-+ 513,
-+ 537,
-+ 538,
-+ 567,
-+ 588,
-+ 610,
-+ 640,
-+ 673,
-+ 714,
-+ 749,
-+ 799,
-+ 828,
-+ 866,
-+ 891,
-+ 934,
-+ 994,
-+ 995,
-+ 1044,
-+ 1068,
-+ 1107,
-+ 1151,
-+ 1177,
-+ 1204,
-+ 1243,
-+ 1276,
-+ 1329,
-+ 1370,
-+ 1391,
-+ 1440,
-+ 1468,
-+ 1505,
-+ 1557,
-+ 1600,
-+ 1632,
-+ 1685,
-+ 1729,
-+ 1796,
-+ 1839,
-+ 1879,
-+ 1908
- };
-
-
-@@ -1453,14 +1526,16 @@
- static int
- check_posix_name(const uschar *ptr, int len)
- {
--register int yield = 0;
--while (posix_name_lengths[yield] != 0)
-- {
-- if (len == posix_name_lengths[yield] &&
-- strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield;
-- yield++;
-- }
--return -1;
-+ int offset = 0;
-+ int yield = 0;
-+ while (posix_name_lengths[yield] != 0)
-+ {
-+ if (len == posix_name_lengths[yield] &&
-+ strcmp((const char *)ptr, posix_names + offset) == 0) return yield;
-+ offset += posix_name_lengths[yield] + 1;
-+ yield++;
-+ }
-+ return -1;
- }
-
-
-@@ -5200,7 +5275,7 @@
- #ifdef SUPPORT_UTF8
- PCRE_UTF8_ERROR_RETURN:
- #endif
-- *errorptr = error_texts[errorcode];
-+ *errorptr = error_texts + error_texts_offsets[errorcode];
- if (errorcodeptr != NULL) *errorcodeptr = errorcode;
- return NULL;
- }
-@@ -5297,7 +5372,7 @@
- if (code - codestart > length)
- {
- (pcre_free)(re);
-- *errorptr = error_texts[ERR23];
-+ *errorptr = error_texts + error_texts_offsets[ERR23];
- *erroroffset = ptr - (uschar *)pattern;
- if (errorcodeptr != NULL) *errorcodeptr = ERR23;
- return NULL;
diff --git a/glib/update-pcre/ucp.patch b/glib/update-pcre/ucp.patch
deleted file mode 100644
index 8abd812e5..000000000
--- a/glib/update-pcre/ucp.patch
+++ /dev/null
@@ -1,141 +0,0 @@
---- pcre/ucp.h 2006-07-05 13:28:01.000000000 +0200
-+++ pcre/ucp.h 2006-10-09 16:27:19.000000000 +0200
-@@ -60,72 +60,72 @@ enum {
- /* These are the script identifications. */
-
- enum {
-- ucp_Arabic,
-- ucp_Armenian,
-- ucp_Bengali,
-- ucp_Bopomofo,
-- ucp_Braille,
-- ucp_Buginese,
-- ucp_Buhid,
-- ucp_Canadian_Aboriginal,
-- ucp_Cherokee,
-- ucp_Common,
-- ucp_Coptic,
-- ucp_Cypriot,
-- ucp_Cyrillic,
-- ucp_Deseret,
-- ucp_Devanagari,
-- ucp_Ethiopic,
-- ucp_Georgian,
-- ucp_Glagolitic,
-- ucp_Gothic,
-- ucp_Greek,
-- ucp_Gujarati,
-- ucp_Gurmukhi,
-- ucp_Han,
-- ucp_Hangul,
-- ucp_Hanunoo,
-- ucp_Hebrew,
-- ucp_Hiragana,
-- ucp_Inherited,
-- ucp_Kannada,
-- ucp_Katakana,
-- ucp_Kharoshthi,
-- ucp_Khmer,
-- ucp_Lao,
-- ucp_Latin,
-- ucp_Limbu,
-- ucp_Linear_B,
-- ucp_Malayalam,
-- ucp_Mongolian,
-- ucp_Myanmar,
-- ucp_New_Tai_Lue,
-- ucp_Ogham,
-- ucp_Old_Italic,
-- ucp_Old_Persian,
-- ucp_Oriya,
-- ucp_Osmanya,
-- ucp_Runic,
-- ucp_Shavian,
-- ucp_Sinhala,
-- ucp_Syloti_Nagri,
-- ucp_Syriac,
-- ucp_Tagalog,
-- ucp_Tagbanwa,
-- ucp_Tai_Le,
-- ucp_Tamil,
-- ucp_Telugu,
-- ucp_Thaana,
-- ucp_Thai,
-- ucp_Tibetan,
-- ucp_Tifinagh,
-- ucp_Ugaritic,
-- ucp_Yi,
-- ucp_Balinese, /* New for Unicode 5.0.0 */
-- ucp_Cuneiform, /* New for Unicode 5.0.0 */
-- ucp_Nko, /* New for Unicode 5.0.0 */
-- ucp_Phags_Pa, /* New for Unicode 5.0.0 */
-- ucp_Phoenician /* New for Unicode 5.0.0 */
-+ ucp_Arabic = G_UNICODE_SCRIPT_ARABIC,
-+ ucp_Armenian = G_UNICODE_SCRIPT_ARMENIAN,
-+ ucp_Bengali = G_UNICODE_SCRIPT_BENGALI,
-+ ucp_Bopomofo = G_UNICODE_SCRIPT_BOPOMOFO,
-+ ucp_Braille = G_UNICODE_SCRIPT_BRAILLE,
-+ ucp_Buginese = G_UNICODE_SCRIPT_BUGINESE,
-+ ucp_Buhid = G_UNICODE_SCRIPT_BUHID,
-+ ucp_Canadian_Aboriginal = G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL,
-+ ucp_Cherokee = G_UNICODE_SCRIPT_CHEROKEE,
-+ ucp_Common = G_UNICODE_SCRIPT_COMMON,
-+ ucp_Coptic = G_UNICODE_SCRIPT_COPTIC,
-+ ucp_Cypriot = G_UNICODE_SCRIPT_CYPRIOT,
-+ ucp_Cyrillic = G_UNICODE_SCRIPT_CYRILLIC,
-+ ucp_Deseret = G_UNICODE_SCRIPT_DESERET,
-+ ucp_Devanagari = G_UNICODE_SCRIPT_DEVANAGARI,
-+ ucp_Ethiopic = G_UNICODE_SCRIPT_ETHIOPIC,
-+ ucp_Georgian = G_UNICODE_SCRIPT_GEORGIAN,
-+ ucp_Glagolitic = G_UNICODE_SCRIPT_GLAGOLITIC,
-+ ucp_Gothic = G_UNICODE_SCRIPT_GOTHIC,
-+ ucp_Greek = G_UNICODE_SCRIPT_GREEK,
-+ ucp_Gujarati = G_UNICODE_SCRIPT_GUJARATI,
-+ ucp_Gurmukhi = G_UNICODE_SCRIPT_GURMUKHI,
-+ ucp_Han = G_UNICODE_SCRIPT_HAN,
-+ ucp_Hangul = G_UNICODE_SCRIPT_HANGUL,
-+ ucp_Hanunoo = G_UNICODE_SCRIPT_HANUNOO,
-+ ucp_Hebrew = G_UNICODE_SCRIPT_HEBREW,
-+ ucp_Hiragana = G_UNICODE_SCRIPT_HIRAGANA,
-+ ucp_Inherited = G_UNICODE_SCRIPT_INHERITED,
-+ ucp_Kannada = G_UNICODE_SCRIPT_KANNADA,
-+ ucp_Katakana = G_UNICODE_SCRIPT_KATAKANA,
-+ ucp_Kharoshthi = G_UNICODE_SCRIPT_KHAROSHTHI,
-+ ucp_Khmer = G_UNICODE_SCRIPT_KHMER,
-+ ucp_Lao = G_UNICODE_SCRIPT_LAO,
-+ ucp_Latin = G_UNICODE_SCRIPT_LATIN,
-+ ucp_Limbu = G_UNICODE_SCRIPT_LIMBU,
-+ ucp_Linear_B = G_UNICODE_SCRIPT_LINEAR_B,
-+ ucp_Malayalam = G_UNICODE_SCRIPT_MALAYALAM,
-+ ucp_Mongolian = G_UNICODE_SCRIPT_MONGOLIAN,
-+ ucp_Myanmar = G_UNICODE_SCRIPT_MYANMAR,
-+ ucp_New_Tai_Lue = G_UNICODE_SCRIPT_NEW_TAI_LUE,
-+ ucp_Ogham = G_UNICODE_SCRIPT_OGHAM,
-+ ucp_Old_Italic = G_UNICODE_SCRIPT_OLD_ITALIC,
-+ ucp_Old_Persian = G_UNICODE_SCRIPT_OLD_PERSIAN,
-+ ucp_Oriya = G_UNICODE_SCRIPT_ORIYA,
-+ ucp_Osmanya = G_UNICODE_SCRIPT_OSMANYA,
-+ ucp_Runic = G_UNICODE_SCRIPT_RUNIC,
-+ ucp_Shavian = G_UNICODE_SCRIPT_SHAVIAN,
-+ ucp_Sinhala = G_UNICODE_SCRIPT_SINHALA,
-+ ucp_Syloti_Nagri = G_UNICODE_SCRIPT_SYLOTI_NAGRI,
-+ ucp_Syriac = G_UNICODE_SCRIPT_SYRIAC,
-+ ucp_Tagalog = G_UNICODE_SCRIPT_TAGALOG,
-+ ucp_Tagbanwa = G_UNICODE_SCRIPT_TAGBANWA,
-+ ucp_Tai_Le = G_UNICODE_SCRIPT_TAI_LE,
-+ ucp_Tamil = G_UNICODE_SCRIPT_TAMIL,
-+ ucp_Telugu = G_UNICODE_SCRIPT_TELUGU,
-+ ucp_Thaana = G_UNICODE_SCRIPT_THAANA,
-+ ucp_Thai = G_UNICODE_SCRIPT_THAI,
-+ ucp_Tibetan = G_UNICODE_SCRIPT_TIBETAN,
-+ ucp_Tifinagh = G_UNICODE_SCRIPT_TIFINAGH,
-+ ucp_Ugaritic = G_UNICODE_SCRIPT_UGARITIC,
-+ ucp_Yi = G_UNICODE_SCRIPT_YI,
-+ ucp_Balinese = G_UNICODE_SCRIPT_BALINESE, /* New for Unicode 5.0.0 */
-+ ucp_Cuneiform = G_UNICODE_SCRIPT_CUNEIFORM, /* New for Unicode 5.0.0 */
-+ ucp_Nko = G_UNICODE_SCRIPT_NKO, /* New for Unicode 5.0.0 */
-+ ucp_Phags_Pa = G_UNICODE_SCRIPT_PHAGS_PA, /* New for Unicode 5.0.0 */
-+ ucp_Phoenician = G_UNICODE_SCRIPT_PHOENICIAN /* New for Unicode 5.0.0 */
- };
-
- #endif
diff --git a/glib/update-pcre/update.sh b/glib/update-pcre/update.sh
deleted file mode 100644
index 960b4d21d..000000000
--- a/glib/update-pcre/update.sh
+++ /dev/null
@@ -1,159 +0,0 @@
-#! /bin/sh
-
-IN="../update-pcre"
-PCRE=$1
-
-if [ "x$PCRE" = x -o "x$PCRE" = x--help -o "x$PCRE" = x-h ]; then
- cat >&2 << EOF
-
-$0 PCRE-DIR
-
- Updates the local PCRE copy with a different version of the library,
- contained in the directory PCRE-DIR.
-
- This will delete the content of the local pcre directory, copy the
- necessary files from PCRE-DIR, and generate other needed files, such
- as Makefile.am
-EOF
- exit
-fi
-
-if [ ! -f gregex.h ]; then
- echo "This script should be executed from the directory containing gregex.c." 2> /dev/null
- exit 1
-fi
-
-if [ ! -f $PCRE/Makefile.in -o ! -f $PCRE/pcre_compile.c ]; then
- echo "'$PCRE' does not contain a valid PCRE version." 2> /dev/null
- exit 1
-fi
-
-
-echo "Deleting old PCRE library"
-mv pcre/.svn tmp-pcre-svn
-rm -R pcre 2> /dev/null
-mkdir pcre
-cd pcre
-
-# pcre_chartables.c is generated by dfatables.
-# We do not want to compile and execute dfatables.c every time, because
-# this could be a problem (e.g. when cross-compiling), so now generate
-# the file and then distribuite it with GRegex.
-echo "Generating pcre_chartables.c"
-cp -R $PCRE tmp-build
-cd tmp-build
-./configure --enable-utf8 --enable-unicode-properties --disable-cpp > /dev/null
-make pcre_chartables.c > /dev/null
-cat > ../pcre_chartables.c << \EOF
-/* This file is autogenerated by ../update-pcre/update.sh during
- * the update of the local copy of PCRE.
- */
-EOF
-cat pcre_chartables.c >> ../pcre_chartables.c
-cd ..
-rm -R tmp-build
-
-# Compiled C files.
-echo "Generating makefiles"
-all_files=`awk '/^OBJ = /, /^\\s*$/ \
- { \
- sub("^OBJ = ", ""); \
- sub(".@OBJEXT@[[:blank:]]*\\\\\\\\", ""); \
- sub("\\\\$\\\\(POSIX_OBJ\\\\)", ""); \
- print; \
- }' \
- $PCRE/Makefile.in`
-
-# Headers.
-included_files="pcre.h pcre_internal.h ucp.h ucpinternal.h"
-
-# Generate Makefile.am.
-cat $IN/Makefile.am-1 > Makefile.am
-for name in $all_files; do
- echo " $name.c \\" >> Makefile.am
- if [ $name != pcre_chartables ]; then
- # pcre_chartables.c is a generated file.
- cp $PCRE/$name.c .
- fi
-done
-for f in $included_files; do
- echo " $f \\" >> Makefile.am
- cp $PCRE/$f .
-done
-cat $IN/Makefile.am-2 >> Makefile.am
-
-# Generate makefile.msc
-cat > makefile.msc << EOF
-TOP = ..\..\..
-!INCLUDE ..\..\build\win32\make.msc
-
-INCLUDES = \\
- -I ..\.. \\
- -I ..
-
-DEFINES = \\
- -DPCRE_STATIC \\
- -DHAVE_CONFIG_H \\
- -DHAVE_LONG_LONG_FORMAT \\
- -DSUPPORT_UCP \\
- -DSUPPORT_UTF8 \\
- -DNEWLINE=-1 \\
- -DMATCH_LIMIT=10000000 \\
- -DMATCH_LIMIT_RECURSION=10000000 \\
- -DMAX_NAME_SIZE=32 \\
- -DMAX_NAME_COUNT=10000 \\
- -DMAX_DUPLENGTH=30000 \\
- -DLINK_SIZE=2 \\
- -DEBCDIC=0 \\
- -DPOSIX_MALLOC_THRESHOLD=10
-
-OBJECTS = \\
-`
-for f in $all_files; do
- echo " $f.obj \\\\"
-done
-`
-
-all : pcre.lib
-
-pcre.lib : \$(OBJECTS)
- lib -out:pcre.lib \$(OBJECTS)
-EOF
-
-echo "Patching PCRE"
-
-# Copy the license.
-cp $PCRE/COPYING .
-
-# Use glib for memory allocation.
-patch > /dev/null < $IN/memory.patch
-
-# Copy the modified version of pcre_valid_utf8.c.
-cp $IN/pcre_valid_utf8.c .
-
-# Copy the modified version of pcre_ucp_searchfuncs.c that uses glib
-# for Unicode properties.
-cp $IN/pcre_ucp_searchfuncs.c .
-patch > /dev/null < $IN/ucp.patch
-
-# Remove the digitab array in pcre_compile.c.
-patch > /dev/null < $IN/digitab.patch
-sed -i -e 's/(digitab\[\(.*\)\] & ctype_digit)/g_ascii_isdigit(\1)/' pcre_compile.c
-sed -i -e 's/(digitab\[\(.*\)\] & ctype_xdigit)/g_ascii_isxdigit(\1)/' pcre_compile.c
-
-# Reduce the number of relocations.
-python $IN/make_utt.py
-patch > /dev/null < $IN/utt.patch
-patch > /dev/null < $IN/table-reduction.patch
-
-# Copy back the old SVN directory.
-mv ../tmp-pcre-svn .svn
-
-
-cat << EOF
-
-Update completed. You now should check that everything is working.
-Remember to update the regex syntax doc with the new features
-(docs/reference/glib/regex-syntax.sgml) and to run the tests.
-EOF
-
diff --git a/glib/update-pcre/utt.patch b/glib/update-pcre/utt.patch
deleted file mode 100644
index 171445f71..000000000
--- a/glib/update-pcre/utt.patch
+++ /dev/null
@@ -1,30 +0,0 @@
---- pcre_compile.c 2006-10-10 12:00:00.000000000 +0200
-+++ pcre_compile.c 2006-10-10 12:00:00.000000000 +0200
-@@ -589,7 +589,7 @@ while (bot < top)
- while (bot < top)
- {
- i = (bot + top) >> 1;
-- c = strcmp(name, _pcre_utt[i].name);
-+ c = strcmp(name, &_pcre_ucp_names[_pcre_utt[i].offset]);
- if (c == 0)
- {
- *dptr = _pcre_utt[i].value;
---- pcre_internal.h 2006-10-10 12:00:00.000000000 +0200
-+++ pcre_internal.h 2006-10-10 12:00:00.000000000 +0200
-@@ -993,7 +993,7 @@ codes. */
- codes. */
-
- typedef struct {
-- const char *name;
-+ pcre_uint16 offset;
- pcre_uint16 type;
- pcre_uint16 value;
- } ucp_type_table;
-@@ -1011,6 +1011,7 @@ extern const uschar _pcre_utf8_table4[];
-
- extern const int _pcre_utf8_table1_size;
-
-+extern const char _pcre_ucp_names[];
- extern const ucp_type_table _pcre_utt[];
- extern const int _pcre_utt_size;
-
diff --git a/glib/win_iconv.c b/glib/win_iconv.c
deleted file mode 100644
index ea1924024..000000000
--- a/glib/win_iconv.c
+++ /dev/null
@@ -1,1956 +0,0 @@
-/*
- * iconv library implemented with Win32 API.
- *
- * This file is placed in the public domain.
- *
- * Maintainer: Yukihiro Nakadaira <yukihiro.nakadaira@gmail.com>
- *
- * If $WINICONV_LIBICONV_DLL environment variable was defined, win_iconv
- * loads the specified DLL dynamically and uses it. If loading the DLL
- * or iconv_open() failed, falls back to internal conversion.
- * $WINICONV_LIBICONV_DLL is a comma separated list. The first loadable
- * DLL is used. The specified DLL should have iconv_open(),
- * iconv_close() and iconv() functions. Or these functions can be
- * libiconv_open(), libiconv_close() and libiconv().
- *
- * Win32 API does not support strict encoding conversion for some
- * codepage. And MLang function drop or replace invalid bytes and does
- * not return useful error status as iconv. This implementation cannot
- * be used for encoding validation purpose.
- */
-
-/* for WC_NO_BEST_FIT_CHARS */
-#ifndef WINVER
-# define WINVER 0x0500
-#endif
-
-#define STRICT
-#include <windows.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-#if 0
-# define MAKE_EXE
-# define MAKE_DLL
-# define USE_LIBICONV_DLL
-#endif
-
-#if !defined(DEFAULT_LIBICONV_DLL)
-# define DEFAULT_LIBICONV_DLL ""
-#endif
-
-#define MB_CHAR_MAX 16
-
-#define UNICODE_MODE_BOM_DONE 1
-#define UNICODE_MODE_SWAPPED 2
-
-#define FLAG_USE_BOM_ENDIAN 1
-#define FLAG_TRANSLIT 2 /* //TRANSLIT */
-#define FLAG_IGNORE 4 /* //IGNORE (not implemented) */
-
-#define return_error(code) \
- do { \
- errno = code; \
- return -1; \
- } while (0)
-
-#define xstrlcpy(dst, src, size) \
- do { \
- strncpy(dst, src, size); \
- dst[size - 1] = 0; \
- } while (0)
-
-#define xstrlcpyn(dst, src, srclen, size) \
- xstrlcpy(dst, src, xmin((srclen) + 1, size))
-
-#define xmin(a, b) ((a) < (b) ? (a) : (b))
-#define xmax(a, b) ((a) > (b) ? (a) : (b))
-
-#define STATIC_STRLEN(arr) (sizeof(arr) - 1)
-
-typedef unsigned char uchar;
-typedef unsigned short ushort;
-typedef unsigned int uint;
-
-typedef void* iconv_t;
-
-iconv_t iconv_open(const char *tocode, const char *fromcode);
-int iconv_close(iconv_t cd);
-size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
-
-/* libiconv interface for vim */
-#if defined(MAKE_DLL)
-int
-iconvctl (iconv_t cd, int request, void* argument)
-{
- /* not supported */
- return 0;
-}
-#endif
-
-typedef struct compat_t compat_t;
-typedef struct csconv_t csconv_t;
-typedef struct rec_iconv_t rec_iconv_t;
-
-typedef iconv_t (*f_iconv_open)(const char *tocode, const char *fromcode);
-typedef int (*f_iconv_close)(iconv_t cd);
-typedef size_t (*f_iconv)(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
-typedef int* (*f_errno)(void);
-typedef int (*f_mbtowc)(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
-typedef int (*f_wctomb)(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
-typedef int (*f_mblen)(csconv_t *cv, const uchar *buf, int bufsize);
-typedef int (*f_flush)(csconv_t *cv, uchar *buf, int bufsize);
-
-#define COMPAT_IN 1
-#define COMPAT_OUT 2
-
-/* unicode mapping for compatibility with other conversion table. */
-struct compat_t {
- uint in;
- uint out;
- uint flag;
-};
-
-struct csconv_t {
- int codepage;
- int flags;
- f_mbtowc mbtowc;
- f_wctomb wctomb;
- f_mblen mblen;
- f_flush flush;
- DWORD mode;
- compat_t *compat;
-};
-
-struct rec_iconv_t {
- iconv_t cd;
- f_iconv_close iconv_close;
- f_iconv iconv;
- f_errno _errno;
- csconv_t from;
- csconv_t to;
-#if defined(USE_LIBICONV_DLL)
- HMODULE hlibiconv;
-#endif
-};
-
-static int win_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode);
-static int win_iconv_close(iconv_t cd);
-static size_t win_iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
-
-static int load_mlang();
-static csconv_t make_csconv(const char *name);
-static int name_to_codepage(const char *name);
-static uint utf16_to_ucs4(const ushort *wbuf);
-static void ucs4_to_utf16(uint wc, ushort *wbuf, int *wbufsize);
-static int is_unicode(int codepage);
-static int mbtowc_flags(int codepage);
-static int must_use_null_useddefaultchar(int codepage);
-static void check_utf_bom(rec_iconv_t *cd, ushort *wbuf, int *wbufsize);
-static char *strrstr(const char *str, const char *token);
-
-#if defined(USE_LIBICONV_DLL)
-static int libiconv_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode);
-static PVOID MyImageDirectoryEntryToData(LPVOID Base, BOOLEAN MappedAsImage, USHORT DirectoryEntry, PULONG Size);
-static HMODULE find_imported_module_by_funcname(HMODULE hModule, const char *funcname);
-
-static HMODULE hwiniconv;
-static HMODULE hlastdll; /* keep dll loaded for efficiency (unnecessary?) */
-#endif
-
-static int sbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize);
-static int dbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize);
-static int mbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize);
-static int utf8_mblen(csconv_t *cv, const uchar *buf, int bufsize);
-static int eucjp_mblen(csconv_t *cv, const uchar *buf, int bufsize);
-
-static int kernel_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
-static int kernel_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
-static int mlang_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
-static int mlang_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
-static int utf16_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
-static int utf16_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
-static int utf32_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
-static int utf32_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
-static int iso2022jp_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
-static int iso2022jp_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
-static int iso2022jp_flush(csconv_t *cv, uchar *buf, int bufsize);
-
-static struct {
- int codepage;
- const char *name;
-} codepage_alias[] = {
- {65001, "CP65001"},
- {65001, "UTF8"},
- {65001, "UTF-8"},
-
- {1200, "CP1200"},
- {1200, "UTF16LE"},
- {1200, "UTF-16LE"},
- {1200, "UCS2LE"},
- {1200, "UCS-2LE"},
-
- {1201, "CP1201"},
- {1201, "UTF16BE"},
- {1201, "UTF-16BE"},
- {1201, "UCS2BE"},
- {1201, "UCS-2BE"},
- {1201, "unicodeFFFE"},
-
- {12000, "CP12000"},
- {12000, "UTF32LE"},
- {12000, "UTF-32LE"},
- {12000, "UCS4LE"},
- {12000, "UCS-4LE"},
-
- {12001, "CP12001"},
- {12001, "UTF32BE"},
- {12001, "UTF-32BE"},
- {12001, "UCS4BE"},
- {12001, "UCS-4BE"},
-
-#ifndef GLIB_COMPILATION
- /*
- * Default is big endian.
- * See rfc2781 4.3 Interpreting text labelled as UTF-16.
- */
- {1201, "UTF16"},
- {1201, "UTF-16"},
- {12001, "UTF32"},
- {12001, "UTF-32"},
- {12001, "UCS-4"},
- {12001, "UCS4"},
-#else
- /* Default is little endian, because the platform is */
- {1200, "UTF16"},
- {1200, "UTF-16"},
- {1200, "UCS2"},
- {1200, "UCS-2"},
- {12000, "UTF32"},
- {12000, "UTF-32"},
- {12000, "UCS4"},
- {12000, "UCS-4"},
-#endif
-
- /* copy from libiconv `iconv -l` */
- /* !IsValidCodePage(367) */
- {20127, "ANSI_X3.4-1968"},
- {20127, "ANSI_X3.4-1986"},
- {20127, "ASCII"},
- {20127, "CP367"},
- {20127, "IBM367"},
- {20127, "ISO-IR-6"},
- {20127, "ISO646-US"},
- {20127, "ISO_646.IRV:1991"},
- {20127, "US"},
- {20127, "US-ASCII"},
- {20127, "CSASCII"},
-
- /* !IsValidCodePage(819) */
- {1252, "CP819"},
- {1252, "IBM819"},
- {28591, "ISO-8859-1"},
- {28591, "ISO-IR-100"},
- {28591, "ISO8859-1"},
- {28591, "ISO_8859-1"},
- {28591, "ISO_8859-1:1987"},
- {28591, "L1"},
- {28591, "LATIN1"},
- {28591, "CSISOLATIN1"},
-
- {1250, "CP1250"},
- {1250, "MS-EE"},
- {1250, "WINDOWS-1250"},
-
- {1251, "CP1251"},
- {1251, "MS-CYRL"},
- {1251, "WINDOWS-1251"},
-
- {1252, "CP1252"},
- {1252, "MS-ANSI"},
- {1252, "WINDOWS-1252"},
-
- {1253, "CP1253"},
- {1253, "MS-GREEK"},
- {1253, "WINDOWS-1253"},
-
- {1254, "CP1254"},
- {1254, "MS-TURK"},
- {1254, "WINDOWS-1254"},
-
- {1255, "CP1255"},
- {1255, "MS-HEBR"},
- {1255, "WINDOWS-1255"},
-
- {1256, "CP1256"},
- {1256, "MS-ARAB"},
- {1256, "WINDOWS-1256"},
-
- {1257, "CP1257"},
- {1257, "WINBALTRIM"},
- {1257, "WINDOWS-1257"},
-
- {1258, "CP1258"},
- {1258, "WINDOWS-1258"},
-
- {850, "850"},
- {850, "CP850"},
- {850, "IBM850"},
- {850, "CSPC850MULTILINGUAL"},
-
- /* !IsValidCodePage(862) */
- {862, "862"},
- {862, "CP862"},
- {862, "IBM862"},
- {862, "CSPC862LATINHEBREW"},
-
- {866, "866"},
- {866, "CP866"},
- {866, "IBM866"},
- {866, "CSIBM866"},
-
- /* !IsValidCodePage(154) */
- {154, "CP154"},
- {154, "CYRILLIC-ASIAN"},
- {154, "PT154"},
- {154, "PTCP154"},
- {154, "CSPTCP154"},
-
- /* !IsValidCodePage(1133) */
- {1133, "CP1133"},
- {1133, "IBM-CP1133"},
-
- {874, "CP874"},
- {874, "WINDOWS-874"},
-
- /* !IsValidCodePage(51932) */
- {51932, "CP51932"},
- {51932, "MS51932"},
- {51932, "WINDOWS-51932"},
- {51932, "EUC-JP"},
-
- {932, "CP932"},
- {932, "MS932"},
- {932, "SHIFFT_JIS"},
- {932, "SHIFFT_JIS-MS"},
- {932, "SJIS"},
- {932, "SJIS-MS"},
- {932, "SJIS-OPEN"},
- {932, "SJIS-WIN"},
- {932, "WINDOWS-31J"},
- {932, "WINDOWS-932"},
- {932, "CSWINDOWS31J"},
-
- {50221, "CP50221"},
- {50221, "ISO-2022-JP"},
- {50221, "ISO-2022-JP-MS"},
- {50221, "ISO2022-JP"},
- {50221, "ISO2022-JP-MS"},
- {50221, "MS50221"},
- {50221, "WINDOWS-50221"},
-
- {936, "CP936"},
- {936, "GBK"},
- {936, "MS936"},
- {936, "WINDOWS-936"},
-
- {950, "CP950"},
- {950, "BIG5"},
-
- {949, "CP949"},
- {949, "UHC"},
- {949, "EUC-KR"},
-
- {1361, "CP1361"},
- {1361, "JOHAB"},
-
- {437, "437"},
- {437, "CP437"},
- {437, "IBM437"},
- {437, "CSPC8CODEPAGE437"},
-
- {737, "CP737"},
-
- {775, "CP775"},
- {775, "IBM775"},
- {775, "CSPC775BALTIC"},
-
- {852, "852"},
- {852, "CP852"},
- {852, "IBM852"},
- {852, "CSPCP852"},
-
- /* !IsValidCodePage(853) */
- {853, "CP853"},
-
- {855, "855"},
- {855, "CP855"},
- {855, "IBM855"},
- {855, "CSIBM855"},
-
- {857, "857"},
- {857, "CP857"},
- {857, "IBM857"},
- {857, "CSIBM857"},
-
- /* !IsValidCodePage(858) */
- {858, "CP858"},
-
- {860, "860"},
- {860, "CP860"},
- {860, "IBM860"},
- {860, "CSIBM860"},
-
- {861, "861"},
- {861, "CP-IS"},
- {861, "CP861"},
- {861, "IBM861"},
- {861, "CSIBM861"},
-
- {863, "863"},
- {863, "CP863"},
- {863, "IBM863"},
- {863, "CSIBM863"},
-
- {864, "CP864"},
- {864, "IBM864"},
- {864, "CSIBM864"},
-
- {865, "865"},
- {865, "CP865"},
- {865, "IBM865"},
- {865, "CSIBM865"},
-
- {869, "869"},
- {869, "CP-GR"},
- {869, "CP869"},
- {869, "IBM869"},
- {869, "CSIBM869"},
-
- /* !IsValidCodePage(1152) */
- {1125, "CP1125"},
-
- /*
- * Code Page Identifiers
- * http://msdn2.microsoft.com/en-us/library/ms776446.aspx
- */
- {37, "IBM037"}, /* IBM EBCDIC US-Canada */
- {437, "IBM437"}, /* OEM United States */
- {500, "IBM500"}, /* IBM EBCDIC International */
- {708, "ASMO-708"}, /* Arabic (ASMO 708) */
- /* 709 Arabic (ASMO-449+, BCON V4) */
- /* 710 Arabic - Transparent Arabic */
- {720, "DOS-720"}, /* Arabic (Transparent ASMO); Arabic (DOS) */
- {737, "ibm737"}, /* OEM Greek (formerly 437G); Greek (DOS) */
- {775, "ibm775"}, /* OEM Baltic; Baltic (DOS) */
- {850, "ibm850"}, /* OEM Multilingual Latin 1; Western European (DOS) */
- {852, "ibm852"}, /* OEM Latin 2; Central European (DOS) */
- {855, "IBM855"}, /* OEM Cyrillic (primarily Russian) */
- {857, "ibm857"}, /* OEM Turkish; Turkish (DOS) */
- {858, "IBM00858"}, /* OEM Multilingual Latin 1 + Euro symbol */
- {860, "IBM860"}, /* OEM Portuguese; Portuguese (DOS) */
- {861, "ibm861"}, /* OEM Icelandic; Icelandic (DOS) */
- {862, "DOS-862"}, /* OEM Hebrew; Hebrew (DOS) */
- {863, "IBM863"}, /* OEM French Canadian; French Canadian (DOS) */
- {864, "IBM864"}, /* OEM Arabic; Arabic (864) */
- {865, "IBM865"}, /* OEM Nordic; Nordic (DOS) */
- {866, "cp866"}, /* OEM Russian; Cyrillic (DOS) */
- {869, "ibm869"}, /* OEM Modern Greek; Greek, Modern (DOS) */
- {870, "IBM870"}, /* IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2 */
- {874, "windows-874"}, /* ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows) */
- {875, "cp875"}, /* IBM EBCDIC Greek Modern */
- {932, "shift_jis"}, /* ANSI/OEM Japanese; Japanese (Shift-JIS) */
- {932, "shift-jis"}, /* alternative name for it */
- {936, "gb2312"}, /* ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) */
- {949, "ks_c_5601-1987"}, /* ANSI/OEM Korean (Unified Hangul Code) */
- {950, "big5"}, /* ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5) */
- {1026, "IBM1026"}, /* IBM EBCDIC Turkish (Latin 5) */
- {1047, "IBM01047"}, /* IBM EBCDIC Latin 1/Open System */
- {1140, "IBM01140"}, /* IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro) */
- {1141, "IBM01141"}, /* IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro) */
- {1142, "IBM01142"}, /* IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro) */
- {1143, "IBM01143"}, /* IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro) */
- {1144, "IBM01144"}, /* IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro) */
- {1145, "IBM01145"}, /* IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro) */
- {1146, "IBM01146"}, /* IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro) */
- {1147, "IBM01147"}, /* IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro) */
- {1148, "IBM01148"}, /* IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro) */
- {1149, "IBM01149"}, /* IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro) */
- {1250, "windows-1250"}, /* ANSI Central European; Central European (Windows) */
- {1251, "windows-1251"}, /* ANSI Cyrillic; Cyrillic (Windows) */
- {1252, "windows-1252"}, /* ANSI Latin 1; Western European (Windows) */
- {1253, "windows-1253"}, /* ANSI Greek; Greek (Windows) */
- {1254, "windows-1254"}, /* ANSI Turkish; Turkish (Windows) */
- {1255, "windows-1255"}, /* ANSI Hebrew; Hebrew (Windows) */
- {1256, "windows-1256"}, /* ANSI Arabic; Arabic (Windows) */
- {1257, "windows-1257"}, /* ANSI Baltic; Baltic (Windows) */
- {1258, "windows-1258"}, /* ANSI/OEM Vietnamese; Vietnamese (Windows) */
- {1361, "Johab"}, /* Korean (Johab) */
- {10000, "macintosh"}, /* MAC Roman; Western European (Mac) */
- {10001, "x-mac-japanese"}, /* Japanese (Mac) */
- {10002, "x-mac-chinesetrad"}, /* MAC Traditional Chinese (Big5); Chinese Traditional (Mac) */
- {10003, "x-mac-korean"}, /* Korean (Mac) */
- {10004, "x-mac-arabic"}, /* Arabic (Mac) */
- {10005, "x-mac-hebrew"}, /* Hebrew (Mac) */
- {10006, "x-mac-greek"}, /* Greek (Mac) */
- {10007, "x-mac-cyrillic"}, /* Cyrillic (Mac) */
- {10008, "x-mac-chinesesimp"}, /* MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac) */
- {10010, "x-mac-romanian"}, /* Romanian (Mac) */
- {10017, "x-mac-ukrainian"}, /* Ukrainian (Mac) */
- {10021, "x-mac-thai"}, /* Thai (Mac) */
- {10029, "x-mac-ce"}, /* MAC Latin 2; Central European (Mac) */
- {10079, "x-mac-icelandic"}, /* Icelandic (Mac) */
- {10081, "x-mac-turkish"}, /* Turkish (Mac) */
- {10082, "x-mac-croatian"}, /* Croatian (Mac) */
- {20000, "x-Chinese_CNS"}, /* CNS Taiwan; Chinese Traditional (CNS) */
- {20001, "x-cp20001"}, /* TCA Taiwan */
- {20002, "x_Chinese-Eten"}, /* Eten Taiwan; Chinese Traditional (Eten) */
- {20003, "x-cp20003"}, /* IBM5550 Taiwan */
- {20004, "x-cp20004"}, /* TeleText Taiwan */
- {20005, "x-cp20005"}, /* Wang Taiwan */
- {20105, "x-IA5"}, /* IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5) */
- {20106, "x-IA5-German"}, /* IA5 German (7-bit) */
- {20107, "x-IA5-Swedish"}, /* IA5 Swedish (7-bit) */
- {20108, "x-IA5-Norwegian"}, /* IA5 Norwegian (7-bit) */
- {20127, "us-ascii"}, /* US-ASCII (7-bit) */
- {20261, "x-cp20261"}, /* T.61 */
- {20269, "x-cp20269"}, /* ISO 6937 Non-Spacing Accent */
- {20273, "IBM273"}, /* IBM EBCDIC Germany */
- {20277, "IBM277"}, /* IBM EBCDIC Denmark-Norway */
- {20278, "IBM278"}, /* IBM EBCDIC Finland-Sweden */
- {20280, "IBM280"}, /* IBM EBCDIC Italy */
- {20284, "IBM284"}, /* IBM EBCDIC Latin America-Spain */
- {20285, "IBM285"}, /* IBM EBCDIC United Kingdom */
- {20290, "IBM290"}, /* IBM EBCDIC Japanese Katakana Extended */
- {20297, "IBM297"}, /* IBM EBCDIC France */
- {20420, "IBM420"}, /* IBM EBCDIC Arabic */
- {20423, "IBM423"}, /* IBM EBCDIC Greek */
- {20424, "IBM424"}, /* IBM EBCDIC Hebrew */
- {20833, "x-EBCDIC-KoreanExtended"}, /* IBM EBCDIC Korean Extended */
- {20838, "IBM-Thai"}, /* IBM EBCDIC Thai */
- {20866, "koi8-r"}, /* Russian (KOI8-R); Cyrillic (KOI8-R) */
- {20871, "IBM871"}, /* IBM EBCDIC Icelandic */
- {20880, "IBM880"}, /* IBM EBCDIC Cyrillic Russian */
- {20905, "IBM905"}, /* IBM EBCDIC Turkish */
- {20924, "IBM00924"}, /* IBM EBCDIC Latin 1/Open System (1047 + Euro symbol) */
- {20932, "EUC-JP"}, /* Japanese (JIS 0208-1990 and 0121-1990) */
- {20936, "x-cp20936"}, /* Simplified Chinese (GB2312); Chinese Simplified (GB2312-80) */
- {20949, "x-cp20949"}, /* Korean Wansung */
- {21025, "cp1025"}, /* IBM EBCDIC Cyrillic Serbian-Bulgarian */
- /* 21027 (deprecated) */
- {21866, "koi8-u"}, /* Ukrainian (KOI8-U); Cyrillic (KOI8-U) */
- {28591, "iso-8859-1"}, /* ISO 8859-1 Latin 1; Western European (ISO) */
- {28591, "iso8859-1"}, /* ISO 8859-1 Latin 1; Western European (ISO) */
- {28592, "iso-8859-2"}, /* ISO 8859-2 Central European; Central European (ISO) */
- {28592, "iso8859-2"}, /* ISO 8859-2 Central European; Central European (ISO) */
- {28593, "iso-8859-3"}, /* ISO 8859-3 Latin 3 */
- {28593, "iso8859-3"}, /* ISO 8859-3 Latin 3 */
- {28594, "iso-8859-4"}, /* ISO 8859-4 Baltic */
- {28594, "iso8859-4"}, /* ISO 8859-4 Baltic */
- {28595, "iso-8859-5"}, /* ISO 8859-5 Cyrillic */
- {28595, "iso8859-5"}, /* ISO 8859-5 Cyrillic */
- {28596, "iso-8859-6"}, /* ISO 8859-6 Arabic */
- {28596, "iso8859-6"}, /* ISO 8859-6 Arabic */
- {28597, "iso-8859-7"}, /* ISO 8859-7 Greek */
- {28597, "iso8859-7"}, /* ISO 8859-7 Greek */
- {28598, "iso-8859-8"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Visual) */
- {28598, "iso8859-8"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Visual) */
- {28599, "iso-8859-9"}, /* ISO 8859-9 Turkish */
- {28599, "iso8859-9"}, /* ISO 8859-9 Turkish */
- {28603, "iso-8859-13"}, /* ISO 8859-13 Estonian */
- {28603, "iso8859-13"}, /* ISO 8859-13 Estonian */
- {28605, "iso-8859-15"}, /* ISO 8859-15 Latin 9 */
- {28605, "iso8859-15"}, /* ISO 8859-15 Latin 9 */
- {29001, "x-Europa"}, /* Europa 3 */
- {38598, "iso-8859-8-i"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Logical) */
- {38598, "iso8859-8-i"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Logical) */
- {50220, "iso-2022-jp"}, /* ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS) */
- {50221, "csISO2022JP"}, /* ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana) */
- {50222, "iso-2022-jp"}, /* ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI) */
- {50225, "iso-2022-kr"}, /* ISO 2022 Korean */
- {50225, "iso2022-kr"}, /* ISO 2022 Korean */
- {50227, "x-cp50227"}, /* ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022) */
- /* 50229 ISO 2022 Traditional Chinese */
- /* 50930 EBCDIC Japanese (Katakana) Extended */
- /* 50931 EBCDIC US-Canada and Japanese */
- /* 50933 EBCDIC Korean Extended and Korean */
- /* 50935 EBCDIC Simplified Chinese Extended and Simplified Chinese */
- /* 50936 EBCDIC Simplified Chinese */
- /* 50937 EBCDIC US-Canada and Traditional Chinese */
- /* 50939 EBCDIC Japanese (Latin) Extended and Japanese */
- {51932, "euc-jp"}, /* EUC Japanese */
- {51936, "EUC-CN"}, /* EUC Simplified Chinese; Chinese Simplified (EUC) */
- {51949, "euc-kr"}, /* EUC Korean */
- /* 51950 EUC Traditional Chinese */
- {52936, "hz-gb-2312"}, /* HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ) */
- {54936, "GB18030"}, /* Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030) */
- {57002, "x-iscii-de"}, /* ISCII Devanagari */
- {57003, "x-iscii-be"}, /* ISCII Bengali */
- {57004, "x-iscii-ta"}, /* ISCII Tamil */
- {57005, "x-iscii-te"}, /* ISCII Telugu */
- {57006, "x-iscii-as"}, /* ISCII Assamese */
- {57007, "x-iscii-or"}, /* ISCII Oriya */
- {57008, "x-iscii-ka"}, /* ISCII Kannada */
- {57009, "x-iscii-ma"}, /* ISCII Malayalam */
- {57010, "x-iscii-gu"}, /* ISCII Gujarati */
- {57011, "x-iscii-pa"}, /* ISCII Punjabi */
-
- {0, NULL}
-};
-
-/*
- * SJIS SHIFTJIS table CP932 table
- * ---- --------------------------- --------------------------------
- * 5C U+00A5 YEN SIGN U+005C REVERSE SOLIDUS
- * 7E U+203E OVERLINE U+007E TILDE
- * 815C U+2014 EM DASH U+2015 HORIZONTAL BAR
- * 815F U+005C REVERSE SOLIDUS U+FF3C FULLWIDTH REVERSE SOLIDUS
- * 8160 U+301C WAVE DASH U+FF5E FULLWIDTH TILDE
- * 8161 U+2016 DOUBLE VERTICAL LINE U+2225 PARALLEL TO
- * 817C U+2212 MINUS SIGN U+FF0D FULLWIDTH HYPHEN-MINUS
- * 8191 U+00A2 CENT SIGN U+FFE0 FULLWIDTH CENT SIGN
- * 8192 U+00A3 POUND SIGN U+FFE1 FULLWIDTH POUND SIGN
- * 81CA U+00AC NOT SIGN U+FFE2 FULLWIDTH NOT SIGN
- *
- * EUC-JP and ISO-2022-JP should be compatible with CP932.
- *
- * Kernel and MLang have different Unicode mapping table. Make sure
- * which API is used.
- */
-static compat_t cp932_compat[] = {
- {0x00A5, 0x005C, COMPAT_OUT},
- {0x203E, 0x007E, COMPAT_OUT},
- {0x2014, 0x2015, COMPAT_OUT},
- {0x301C, 0xFF5E, COMPAT_OUT},
- {0x2016, 0x2225, COMPAT_OUT},
- {0x2212, 0xFF0D, COMPAT_OUT},
- {0x00A2, 0xFFE0, COMPAT_OUT},
- {0x00A3, 0xFFE1, COMPAT_OUT},
- {0x00AC, 0xFFE2, COMPAT_OUT},
- {0, 0, 0}
-};
-
-static compat_t cp20932_compat[] = {
- {0x00A5, 0x005C, COMPAT_OUT},
- {0x203E, 0x007E, COMPAT_OUT},
- {0x2014, 0x2015, COMPAT_OUT},
- {0xFF5E, 0x301C, COMPAT_OUT|COMPAT_IN},
- {0x2225, 0x2016, COMPAT_OUT|COMPAT_IN},
- {0xFF0D, 0x2212, COMPAT_OUT|COMPAT_IN},
- {0xFFE0, 0x00A2, COMPAT_OUT|COMPAT_IN},
- {0xFFE1, 0x00A3, COMPAT_OUT|COMPAT_IN},
- {0xFFE2, 0x00AC, COMPAT_OUT|COMPAT_IN},
- {0, 0, 0}
-};
-
-static compat_t *cp51932_compat = cp932_compat;
-
-/* cp20932_compat for kernel. cp932_compat for mlang. */
-static compat_t *cp5022x_compat = cp932_compat;
-
-typedef HRESULT (WINAPI *CONVERTINETSTRING)(
- LPDWORD lpdwMode,
- DWORD dwSrcEncoding,
- DWORD dwDstEncoding,
- LPCSTR lpSrcStr,
- LPINT lpnSrcSize,
- LPBYTE lpDstStr,
- LPINT lpnDstSize
-);
-typedef HRESULT (WINAPI *CONVERTINETMULTIBYTETOUNICODE)(
- LPDWORD lpdwMode,
- DWORD dwSrcEncoding,
- LPCSTR lpSrcStr,
- LPINT lpnMultiCharCount,
- LPWSTR lpDstStr,
- LPINT lpnWideCharCount
-);
-typedef HRESULT (WINAPI *CONVERTINETUNICODETOMULTIBYTE)(
- LPDWORD lpdwMode,
- DWORD dwEncoding,
- LPCWSTR lpSrcStr,
- LPINT lpnWideCharCount,
- LPSTR lpDstStr,
- LPINT lpnMultiCharCount
-);
-typedef HRESULT (WINAPI *ISCONVERTINETSTRINGAVAILABLE)(
- DWORD dwSrcEncoding,
- DWORD dwDstEncoding
-);
-typedef HRESULT (WINAPI *LCIDTORFC1766A)(
- LCID Locale,
- LPSTR pszRfc1766,
- int nChar
-);
-typedef HRESULT (WINAPI *LCIDTORFC1766W)(
- LCID Locale,
- LPWSTR pszRfc1766,
- int nChar
-);
-typedef HRESULT (WINAPI *RFC1766TOLCIDA)(
- LCID *pLocale,
- LPSTR pszRfc1766
-);
-typedef HRESULT (WINAPI *RFC1766TOLCIDW)(
- LCID *pLocale,
- LPWSTR pszRfc1766
-);
-static CONVERTINETSTRING ConvertINetString;
-static CONVERTINETMULTIBYTETOUNICODE ConvertINetMultiByteToUnicode;
-static CONVERTINETUNICODETOMULTIBYTE ConvertINetUnicodeToMultiByte;
-static ISCONVERTINETSTRINGAVAILABLE IsConvertINetStringAvailable;
-static LCIDTORFC1766A LcidToRfc1766A;
-static RFC1766TOLCIDA Rfc1766ToLcidA;
-
-static int
-load_mlang()
-{
- HMODULE h;
- if (ConvertINetString != NULL)
- return TRUE;
- h = LoadLibrary("mlang.dll");
- if (!h)
- return FALSE;
- ConvertINetString = (CONVERTINETSTRING)GetProcAddress(h, "ConvertINetString");
- ConvertINetMultiByteToUnicode = (CONVERTINETMULTIBYTETOUNICODE)GetProcAddress(h, "ConvertINetMultiByteToUnicode");
- ConvertINetUnicodeToMultiByte = (CONVERTINETUNICODETOMULTIBYTE)GetProcAddress(h, "ConvertINetUnicodeToMultiByte");
- IsConvertINetStringAvailable = (ISCONVERTINETSTRINGAVAILABLE)GetProcAddress(h, "IsConvertINetStringAvailable");
- LcidToRfc1766A = (LCIDTORFC1766A)GetProcAddress(h, "LcidToRfc1766A");
- Rfc1766ToLcidA = (RFC1766TOLCIDA)GetProcAddress(h, "Rfc1766ToLcidA");
- return TRUE;
-}
-
-iconv_t
-iconv_open(const char *tocode, const char *fromcode)
-{
- rec_iconv_t *cd;
-
- cd = (rec_iconv_t *)calloc(1, sizeof(rec_iconv_t));
- if (cd == NULL)
- {
- errno = ENOMEM;
- return (iconv_t)(-1);
- }
-
-#if defined(USE_LIBICONV_DLL)
- if (libiconv_iconv_open(cd, tocode, fromcode))
- return (iconv_t)cd;
-#endif
-
- if (win_iconv_open(cd, tocode, fromcode))
- return (iconv_t)cd;
-
- free(cd);
- errno = EINVAL;
- return (iconv_t)(-1);
-}
-
-int
-iconv_close(iconv_t _cd)
-{
- rec_iconv_t *cd = (rec_iconv_t *)_cd;
- int r = cd->iconv_close(cd->cd);
- int e = *(cd->_errno());
-#if defined(USE_LIBICONV_DLL)
- if (cd->hlibiconv != NULL)
- FreeLibrary(cd->hlibiconv);
-#endif
- free(cd);
- errno = e;
- return r;
-}
-
-size_t
-iconv(iconv_t _cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
-{
- rec_iconv_t *cd = (rec_iconv_t *)_cd;
- size_t r = cd->iconv(cd->cd, inbuf, inbytesleft, outbuf, outbytesleft);
- errno = *(cd->_errno());
- return r;
-}
-
-static int
-win_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode)
-{
- cd->from = make_csconv(fromcode);
- cd->to = make_csconv(tocode);
- if (cd->from.codepage == -1 || cd->to.codepage == -1)
- return FALSE;
- cd->iconv_close = win_iconv_close;
- cd->iconv = win_iconv;
- cd->_errno = _errno;
- cd->cd = (iconv_t)cd;
- return TRUE;
-}
-
-static int
-win_iconv_close(iconv_t cd)
-{
- return 0;
-}
-
-static size_t
-win_iconv(iconv_t _cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
-{
- rec_iconv_t *cd = (rec_iconv_t *)_cd;
- ushort wbuf[MB_CHAR_MAX]; /* enough room for one character */
- int insize;
- int outsize;
- int wsize;
- DWORD mode;
- uint wc;
- compat_t *cp;
- int i;
-
- if (inbuf == NULL || *inbuf == NULL)
- {
- if (outbuf != NULL && *outbuf != NULL && cd->to.flush != NULL)
- {
- outsize = cd->to.flush(&cd->to, (uchar *)*outbuf, *outbytesleft);
- if (outsize == -1)
- return (size_t)(-1);
- *outbuf += outsize;
- *outbytesleft -= outsize;
- }
- if (is_unicode(cd->from.codepage) && (cd->from.mode & UNICODE_MODE_SWAPPED))
- cd->from.codepage ^= 1;
- cd->from.mode = 0;
- cd->to.mode = 0;
- return 0;
- }
-
- while (*inbytesleft != 0)
- {
- mode = cd->from.mode;
- wsize = MB_CHAR_MAX;
-
- insize = cd->from.mbtowc(&cd->from, (const uchar *)*inbuf, *inbytesleft, wbuf, &wsize);
- if (insize == -1)
- return (size_t)(-1);
-
- if (is_unicode(cd->from.codepage) && !(cd->from.mode & UNICODE_MODE_BOM_DONE))
- {
- check_utf_bom(cd, wbuf, &wsize);
- cd->from.mode |= UNICODE_MODE_BOM_DONE;
- }
-
- if (wsize == 0)
- {
- *inbuf += insize;
- *inbytesleft -= insize;
- continue;
- }
-
- if (cd->from.compat != NULL)
- {
- wc = utf16_to_ucs4(wbuf);
- cp = cd->from.compat;
- for (i = 0; cp[i].in != 0; ++i)
- {
- if ((cp[i].flag & COMPAT_IN) && cp[i].out == wc)
- {
- ucs4_to_utf16(cp[i].in, wbuf, &wsize);
- break;
- }
- }
- }
-
- if (cd->to.compat != NULL)
- {
- wc = utf16_to_ucs4(wbuf);
- cp = cd->to.compat;
- for (i = 0; cp[i].in != 0; ++i)
- {
- if ((cp[i].flag & COMPAT_OUT) && cp[i].in == wc)
- {
- ucs4_to_utf16(cp[i].out, wbuf, &wsize);
- break;
- }
- }
- }
-
- outsize = cd->to.wctomb(&cd->to, wbuf, wsize, (uchar *)*outbuf, *outbytesleft);
- if (outsize == -1)
- {
- cd->from.mode = mode;
- return (size_t)(-1);
- }
-
- *inbuf += insize;
- *outbuf += outsize;
- *inbytesleft -= insize;
- *outbytesleft -= outsize;
- }
-
- return 0;
-}
-
-static csconv_t
-make_csconv(const char *_name)
-{
- CPINFOEX cpinfoex;
- csconv_t cv;
- int use_compat = TRUE;
- int flag = 0;
- char name[128];
- char *p;
-
- xstrlcpy(name, _name, sizeof(name));
-
- /* check for option "enc_name//opt1//opt2" */
- while ((p = strrstr(name, "//")) != NULL)
- {
- if (_stricmp(p + 2, "nocompat") == 0)
- use_compat = FALSE;
- else if (_stricmp(p + 2, "translit") == 0)
- flag |= FLAG_TRANSLIT;
- else if (_stricmp(p + 2, "ignore") == 0)
- flag |= FLAG_IGNORE;
- *p = 0;
- }
-
- cv.mode = 0;
- cv.flags = flag;
- cv.mblen = NULL;
- cv.flush = NULL;
- cv.compat = NULL;
- cv.codepage = name_to_codepage(name);
- if (cv.codepage == 1200 || cv.codepage == 1201)
- {
- cv.mbtowc = utf16_mbtowc;
- cv.wctomb = utf16_wctomb;
- if (_stricmp(name, "UTF-16") == 0 ||
- _stricmp(name, "UTF16") == 0 ||
- _stricmp(name, "UCS-2") == 0 ||
- _stricmp(name, "UCS2") == 0)
- cv.flags |= FLAG_USE_BOM_ENDIAN;
- }
- else if (cv.codepage == 12000 || cv.codepage == 12001)
- {
- cv.mbtowc = utf32_mbtowc;
- cv.wctomb = utf32_wctomb;
- if (_stricmp(name, "UTF-32") == 0 ||
- _stricmp(name, "UTF32") == 0 ||
- _stricmp(name, "UCS-4") == 0 ||
- _stricmp(name, "UCS4") == 0)
- cv.flags |= FLAG_USE_BOM_ENDIAN;
- }
- else if (cv.codepage == 65001)
- {
- cv.mbtowc = kernel_mbtowc;
- cv.wctomb = kernel_wctomb;
- cv.mblen = utf8_mblen;
- }
- else if ((cv.codepage == 50220 || cv.codepage == 50221 || cv.codepage == 50222) && load_mlang())
- {
- cv.mbtowc = iso2022jp_mbtowc;
- cv.wctomb = iso2022jp_wctomb;
- cv.flush = iso2022jp_flush;
- }
- else if (cv.codepage == 51932 && load_mlang())
- {
- cv.mbtowc = mlang_mbtowc;
- cv.wctomb = mlang_wctomb;
- cv.mblen = eucjp_mblen;
- }
- else if (IsValidCodePage(cv.codepage)
- && GetCPInfoEx(cv.codepage, 0, &cpinfoex) != 0)
- {
- cv.mbtowc = kernel_mbtowc;
- cv.wctomb = kernel_wctomb;
- if (cpinfoex.MaxCharSize == 1)
- cv.mblen = sbcs_mblen;
- else if (cpinfoex.MaxCharSize == 2)
- cv.mblen = dbcs_mblen;
- else
- cv.mblen = mbcs_mblen;
- }
- else
- {
- /* not supported */
- cv.codepage = -1;
- }
- if (use_compat)
- {
- switch (cv.codepage)
- {
- case 932: cv.compat = cp932_compat; break;
- case 20932: cv.compat = cp20932_compat; break;
- case 51932: cv.compat = cp51932_compat; break;
- case 50220: case 50221: case 50222: cv.compat = cp5022x_compat; break;
- }
- }
- return cv;
-}
-
-static int
-name_to_codepage(const char *name)
-{
- int i;
-
- if (*name == '\0' ||
- strcmp(name, "char") == 0)
- return GetACP();
- else if (strcmp(name, "wchar_t") == 0)
- return 1200;
- else if (_strnicmp(name, "cp", 2) == 0)
- return atoi(name + 2); /* CP123 */
- else if ('0' <= name[0] && name[0] <= '9')
- return atoi(name); /* 123 */
- else if (_strnicmp(name, "xx", 2) == 0)
- return atoi(name + 2); /* XX123 for debug */
-
- for (i = 0; codepage_alias[i].name != NULL; ++i)
- if (_stricmp(name, codepage_alias[i].name) == 0)
- return codepage_alias[i].codepage;
- return -1;
-}
-
-/*
- * http://www.faqs.org/rfcs/rfc2781.html
- */
-static uint
-utf16_to_ucs4(const ushort *wbuf)
-{
- uint wc = wbuf[0];
- if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF)
- wc = ((wbuf[0] & 0x3FF) << 10) + (wbuf[1] & 0x3FF) + 0x10000;
- return wc;
-}
-
-static void
-ucs4_to_utf16(uint wc, ushort *wbuf, int *wbufsize)
-{
- if (wc < 0x10000)
- {
- wbuf[0] = wc;
- *wbufsize = 1;
- }
- else
- {
- wc -= 0x10000;
- wbuf[0] = 0xD800 | ((wc >> 10) & 0x3FF);
- wbuf[1] = 0xDC00 | (wc & 0x3FF);
- *wbufsize = 2;
- }
-}
-
-static int
-is_unicode(int codepage)
-{
- return (codepage == 1200 || codepage == 1201 ||
- codepage == 12000 || codepage == 12001 ||
- codepage == 65000 || codepage == 65001);
-}
-
-/*
- * Check if codepage is one of those for which the dwFlags parameter
- * to MultiByteToWideChar() must be zero. Return zero or
- * MB_ERR_INVALID_CHARS. The docs in Platform SDK for for Windows
- * Server 2003 R2 claims that also codepage 65001 is one of these, but
- * that doesn't seem to be the case. The MSDN docs for MSVS2008 leave
- * out 65001 (UTF-8), and that indeed seems to be the case on XP, it
- * works fine to pass MB_ERR_INVALID_CHARS in dwFlags when converting
- * from UTF-8.
- */
-static int
-mbtowc_flags(int codepage)
-{
- return (codepage == 50220 || codepage == 50221 ||
- codepage == 50222 || codepage == 50225 ||
- codepage == 50227 || codepage == 50229 ||
- codepage == 52936 || codepage == 54936 ||
- (codepage >= 57002 && codepage <= 57011) ||
- codepage == 65000 || codepage == 42) ? 0 : MB_ERR_INVALID_CHARS;
-}
-
-/*
- * Check if codepage is one those for which the lpUsedDefaultChar
- * parameter to WideCharToMultiByte() must be NULL. The docs in
- * Platform SDK for for Windows Server 2003 R2 claims that this is the
- * list below, while the MSDN docs for MSVS2008 claim that it is only
- * for 65000 (UTF-7) and 65001 (UTF-8). This time the earlier Platform
- * SDK seems to be correct, at least for XP.
- */
-static int
-must_use_null_useddefaultchar(int codepage)
-{
- return (codepage == 65000 || codepage == 65001 ||
- codepage == 50220 || codepage == 50221 ||
- codepage == 50222 || codepage == 50225 ||
- codepage == 50227 || codepage == 50229 ||
- codepage == 52936 || codepage == 54936 ||
- (codepage >= 57002 && codepage <= 57011) ||
- codepage == 42);
-}
-
-static void
-check_utf_bom(rec_iconv_t *cd, ushort *wbuf, int *wbufsize)
-{
- /* If we have a BOM, trust it, despite what the caller said */
- if (wbuf[0] == 0xFFFE && (cd->from.flags & FLAG_USE_BOM_ENDIAN))
- {
- /* swap endian: 1200 <-> 1201 or 12000 <-> 12001 */
- cd->from.codepage ^= 1;
- cd->from.mode |= UNICODE_MODE_SWAPPED;
- wbuf[0] = 0xFEFF;
- }
-
- /*
- * Remove BOM.
- * Don't do this if "to" is Unicode,
- * except if "to" is UTF-8.
- */
- if (wbuf[0] == 0xFEFF && (!is_unicode(cd->to.codepage) || cd->to.codepage == 65001))
- *wbufsize = 0;
-}
-
-static char *
-strrstr(const char *str, const char *token)
-{
- int len = strlen(token);
- const char *p = str + strlen(str);
-
- while (str <= --p)
- if (p[0] == token[0] && strncmp(p, token, len) == 0)
- return (char *)p;
- return NULL;
-}
-
-#if defined(USE_LIBICONV_DLL)
-static int
-libiconv_iconv_open(rec_iconv_t *cd, const char *fromcode, const char *tocode)
-{
- HMODULE hlibiconv = NULL;
- HMODULE hmsvcrt = NULL;
- char dllname[_MAX_PATH];
- const char *p;
- const char *e;
- f_iconv_open _iconv_open;
-
- /*
- * always try to load dll, so that we can switch dll in runtime.
- */
-
- /* XXX: getenv() can't get variable set by SetEnvironmentVariable() */
- p = getenv("WINICONV_LIBICONV_DLL");
- if (p == NULL)
- p = DEFAULT_LIBICONV_DLL;
- /* parse comma separated value */
- for ( ; *p != 0; p = (*e == ',') ? e + 1 : e)
- {
- e = strchr(p, ',');
- if (p == e)
- continue;
- else if (e == NULL)
- e = p + strlen(p);
- xstrlcpyn(dllname, p, e - p, sizeof(dllname));
- hlibiconv = LoadLibrary(dllname);
- if (hlibiconv != NULL)
- {
- if (hlibiconv == hwiniconv)
- {
- FreeLibrary(hlibiconv);
- hlibiconv = NULL;
- continue;
- }
- break;
- }
- }
-
- if (hlastdll != NULL)
- {
- /* decrement reference count */
- FreeLibrary(hlastdll);
- hlastdll = NULL;
- }
-
- if (hlibiconv == NULL)
- goto failed;
-
- hmsvcrt = find_imported_module_by_funcname(hlibiconv, "_errno");
- if (hmsvcrt == NULL)
- goto failed;
-
- _iconv_open = (f_iconv_open)GetProcAddress(hlibiconv, "libiconv_open");
- if (_iconv_open == NULL)
- _iconv_open = (f_iconv_open)GetProcAddress(hlibiconv, "iconv_open");
- cd->iconv_close = (f_iconv_close)GetProcAddress(hlibiconv, "libiconv_close");
- if (cd->iconv_close == NULL)
- cd->iconv_close = (f_iconv_close)GetProcAddress(hlibiconv, "iconv_close");
- cd->iconv = (f_iconv)GetProcAddress(hlibiconv, "libiconv");
- if (cd->iconv == NULL)
- cd->iconv = (f_iconv)GetProcAddress(hlibiconv, "iconv");
- cd->_errno = (f_errno)GetProcAddress(hmsvcrt, "_errno");
- if (_iconv_open == NULL || cd->iconv_close == NULL
- || cd->iconv == NULL || cd->_errno == NULL)
- goto failed;
-
- /* increment reference count */
- hlastdll = LoadLibrary(dllname);
-
- cd->cd = _iconv_open(tocode, fromcode);
- if (cd->cd == (iconv_t)(-1))
- goto failed;
-
- cd->hlibiconv = hlibiconv;
- return TRUE;
-
-failed:
- if (hlibiconv != NULL)
- FreeLibrary(hlibiconv);
- /* do not free hmsvcrt which is obtained by GetModuleHandle() */
- return FALSE;
-}
-
-/*
- * Reference:
- * http://forums.belution.com/ja/vc/000/234/78s.shtml
- * http://nienie.com/~masapico/api_ImageDirectoryEntryToData.html
- *
- * The formal way is
- * imagehlp.h or dbghelp.h
- * imagehlp.lib or dbghelp.lib
- * ImageDirectoryEntryToData()
- */
-#define TO_DOS_HEADER(base) ((PIMAGE_DOS_HEADER)(base))
-#define TO_NT_HEADERS(base) ((PIMAGE_NT_HEADERS)((LPBYTE)(base) + TO_DOS_HEADER(base)->e_lfanew))
-static PVOID
-MyImageDirectoryEntryToData(LPVOID Base, BOOLEAN MappedAsImage, USHORT DirectoryEntry, PULONG Size)
-{
- /* TODO: MappedAsImage? */
- PIMAGE_DATA_DIRECTORY p;
- p = TO_NT_HEADERS(Base)->OptionalHeader.DataDirectory + DirectoryEntry;
- if (p->VirtualAddress == 0) {
- *Size = 0;
- return NULL;
- }
- *Size = p->Size;
- return (PVOID)((LPBYTE)Base + p->VirtualAddress);
-}
-
-static HMODULE
-find_imported_module_by_funcname(HMODULE hModule, const char *funcname)
-{
- DWORD Base;
- ULONG Size;
- PIMAGE_IMPORT_DESCRIPTOR Imp;
- PIMAGE_THUNK_DATA Name; /* Import Name Table */
- PIMAGE_IMPORT_BY_NAME ImpName;
-
- Base = (DWORD)hModule;
- Imp = MyImageDirectoryEntryToData(
- (LPVOID)Base,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_IMPORT,
- &Size);
- if (Imp == NULL)
- return NULL;
- for ( ; Imp->OriginalFirstThunk != 0; ++Imp)
- {
- Name = (PIMAGE_THUNK_DATA)(Base + Imp->OriginalFirstThunk);
- for ( ; Name->u1.Ordinal != 0; ++Name)
- {
- if (!IMAGE_SNAP_BY_ORDINAL(Name->u1.Ordinal))
- {
- ImpName = (PIMAGE_IMPORT_BY_NAME)
- (Base + (DWORD)Name->u1.AddressOfData);
- if (strcmp((char *)ImpName->Name, funcname) == 0)
- return GetModuleHandle((char *)(Base + Imp->Name));
- }
- }
- }
- return NULL;
-}
-#endif
-
-static int
-sbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize)
-{
- return 1;
-}
-
-static int
-dbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize)
-{
- int len = IsDBCSLeadByteEx(cv->codepage, buf[0]) ? 2 : 1;
- if (bufsize < len)
- return_error(EINVAL);
- return len;
-}
-
-static int
-mbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize)
-{
- int len = 0;
-
- if (cv->codepage == 54936) {
- if (buf[0] <= 0x7F) len = 1;
- else if (buf[0] >= 0x81 && buf[0] <= 0xFE &&
- bufsize >= 2 &&
- ((buf[1] >= 0x40 && buf[1] <= 0x7E) ||
- (buf[1] >= 0x80 && buf[1] <= 0xFE))) len = 2;
- else if (buf[0] >= 0x81 && buf[0] <= 0xFE &&
- bufsize >= 4 &&
- buf[1] >= 0x30 && buf[1] <= 0x39) len = 4;
- else
- return_error(EINVAL);
- return len;
- }
- else
- return_error(EINVAL);
-}
-
-static int
-utf8_mblen(csconv_t *cv, const uchar *buf, int bufsize)
-{
- int len = 0;
-
- if (buf[0] < 0x80) len = 1;
- else if ((buf[0] & 0xE0) == 0xC0) len = 2;
- else if ((buf[0] & 0xF0) == 0xE0) len = 3;
- else if ((buf[0] & 0xF8) == 0xF0) len = 4;
- else if ((buf[0] & 0xFC) == 0xF8) len = 5;
- else if ((buf[0] & 0xFE) == 0xFC) len = 6;
-
- if (len == 0)
- return_error(EILSEQ);
- else if (bufsize < len)
- return_error(EINVAL);
- return len;
-}
-
-static int
-eucjp_mblen(csconv_t *cv, const uchar *buf, int bufsize)
-{
- if (buf[0] < 0x80) /* ASCII */
- return 1;
- else if (buf[0] == 0x8E) /* JIS X 0201 */
- {
- if (bufsize < 2)
- return_error(EINVAL);
- else if (!(0xA1 <= buf[1] && buf[1] <= 0xDF))
- return_error(EILSEQ);
- return 2;
- }
- else if (buf[0] == 0x8F) /* JIS X 0212 */
- {
- if (bufsize < 3)
- return_error(EINVAL);
- else if (!(0xA1 <= buf[1] && buf[1] <= 0xFE)
- || !(0xA1 <= buf[2] && buf[2] <= 0xFE))
- return_error(EILSEQ);
- return 3;
- }
- else /* JIS X 0208 */
- {
- if (bufsize < 2)
- return_error(EINVAL);
- else if (!(0xA1 <= buf[0] && buf[0] <= 0xFE)
- || !(0xA1 <= buf[1] && buf[1] <= 0xFE))
- return_error(EILSEQ);
- return 2;
- }
-}
-
-static int
-kernel_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize)
-{
- int len;
-
- len = cv->mblen(cv, buf, bufsize);
- if (len == -1)
- return -1;
- /* If converting from ASCII, reject 8bit
- * chars. MultiByteToWideChar() doesn't. Note that for ASCII we
- * know that the mblen function is sbcs_mblen() so len is 1.
- */
- if (cv->codepage == 20127 && buf[0] >= 0x80)
- return_error(EILSEQ);
- *wbufsize = MultiByteToWideChar(cv->codepage, mbtowc_flags (cv->codepage),
- (const char *)buf, len, (wchar_t *)wbuf, *wbufsize);
- if (*wbufsize == 0)
- return_error(EILSEQ);
- return len;
-}
-
-static int
-kernel_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize)
-{
- BOOL usedDefaultChar = 0;
- BOOL *p = NULL;
- int flags = 0;
- int len;
-
- if (bufsize == 0)
- return_error(E2BIG);
- if (!must_use_null_useddefaultchar(cv->codepage))
- {
- p = &usedDefaultChar;
-#ifdef WC_NO_BEST_FIT_CHARS
- if (!(cv->flags & FLAG_TRANSLIT))
- flags |= WC_NO_BEST_FIT_CHARS;
-#endif
- }
- len = WideCharToMultiByte(cv->codepage, flags,
- (const wchar_t *)wbuf, wbufsize, (char *)buf, bufsize, NULL, p);
- if (len == 0)
- {
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- return_error(E2BIG);
- return_error(EILSEQ);
- }
- else if (usedDefaultChar)
- return_error(EILSEQ);
- else if (cv->mblen(cv, buf, len) != len) /* validate result */
- return_error(EILSEQ);
- return len;
-}
-
-/*
- * It seems that the mode (cv->mode) is fixnum.
- * For example, when converting iso-2022-jp(cp50221) to unicode:
- * in ascii sequence: mode=0xC42C0000
- * in jisx0208 sequence: mode=0xC42C0001
- * "C42C" is same for each convert session.
- * It should be: ((codepage-1)<<16)|state
- */
-static int
-mlang_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize)
-{
- int len;
- int insize;
- HRESULT hr;
-
- len = cv->mblen(cv, buf, bufsize);
- if (len == -1)
- return -1;
- insize = len;
- hr = ConvertINetMultiByteToUnicode(&cv->mode, cv->codepage,
- (const char *)buf, &insize, (wchar_t *)wbuf, wbufsize);
- if (hr != S_OK || insize != len)
- return_error(EILSEQ);
- return len;
-}
-
-static int
-mlang_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize)
-{
- char tmpbuf[MB_CHAR_MAX]; /* enough room for one character */
- int tmpsize = MB_CHAR_MAX;
- int insize = wbufsize;
- HRESULT hr;
-
- hr = ConvertINetUnicodeToMultiByte(&cv->mode, cv->codepage,
- (const wchar_t *)wbuf, &wbufsize, tmpbuf, &tmpsize);
- if (hr != S_OK || insize != wbufsize)
- return_error(EILSEQ);
- else if (bufsize < tmpsize)
- return_error(E2BIG);
- else if (cv->mblen(cv, (uchar *)tmpbuf, tmpsize) != tmpsize)
- return_error(EILSEQ);
- memcpy(buf, tmpbuf, tmpsize);
- return tmpsize;
-}
-
-static int
-utf16_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize)
-{
- if (bufsize < 2)
- return_error(EINVAL);
- if (cv->codepage == 1200) /* little endian */
- wbuf[0] = (buf[1] << 8) | buf[0];
- else if (cv->codepage == 1201) /* big endian */
- wbuf[0] = (buf[0] << 8) | buf[1];
- if (0xDC00 <= wbuf[0] && wbuf[0] <= 0xDFFF)
- return_error(EILSEQ);
- if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF)
- {
- if (bufsize < 4)
- return_error(EINVAL);
- if (cv->codepage == 1200) /* little endian */
- wbuf[1] = (buf[3] << 8) | buf[2];
- else if (cv->codepage == 1201) /* big endian */
- wbuf[1] = (buf[2] << 8) | buf[3];
- if (!(0xDC00 <= wbuf[1] && wbuf[1] <= 0xDFFF))
- return_error(EILSEQ);
- *wbufsize = 2;
- return 4;
- }
- *wbufsize = 1;
- return 2;
-}
-
-static int
-utf16_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize)
-{
- if (bufsize < 2)
- return_error(E2BIG);
- if (cv->codepage == 1200) /* little endian */
- {
- buf[0] = (wbuf[0] & 0x00FF);
- buf[1] = (wbuf[0] & 0xFF00) >> 8;
- }
- else if (cv->codepage == 1201) /* big endian */
- {
- buf[0] = (wbuf[0] & 0xFF00) >> 8;
- buf[1] = (wbuf[0] & 0x00FF);
- }
- if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF)
- {
- if (bufsize < 4)
- return_error(E2BIG);
- if (cv->codepage == 1200) /* little endian */
- {
- buf[2] = (wbuf[1] & 0x00FF);
- buf[3] = (wbuf[1] & 0xFF00) >> 8;
- }
- else if (cv->codepage == 1201) /* big endian */
- {
- buf[2] = (wbuf[1] & 0xFF00) >> 8;
- buf[3] = (wbuf[1] & 0x00FF);
- }
- return 4;
- }
- return 2;
-}
-
-static int
-utf32_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize)
-{
- uint wc;
-
- if (bufsize < 4)
- return_error(EINVAL);
- if (cv->codepage == 12000) /* little endian */
- wc = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
- else if (cv->codepage == 12001) /* big endian */
- wc = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
- if ((0xD800 <= wc && wc <= 0xDFFF) || 0x10FFFF < wc)
- return_error(EILSEQ);
- ucs4_to_utf16(wc, wbuf, wbufsize);
- return 4;
-}
-
-static int
-utf32_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize)
-{
- uint wc;
-
- if (bufsize < 4)
- return_error(E2BIG);
- wc = utf16_to_ucs4(wbuf);
- if (cv->codepage == 12000) /* little endian */
- {
- buf[0] = wc & 0x000000FF;
- buf[1] = (wc & 0x0000FF00) >> 8;
- buf[2] = (wc & 0x00FF0000) >> 16;
- buf[3] = (wc & 0xFF000000) >> 24;
- }
- else if (cv->codepage == 12001) /* big endian */
- {
- buf[0] = (wc & 0xFF000000) >> 24;
- buf[1] = (wc & 0x00FF0000) >> 16;
- buf[2] = (wc & 0x0000FF00) >> 8;
- buf[3] = wc & 0x000000FF;
- }
- return 4;
-}
-
-/*
- * 50220: ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS)
- * 50221: ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow
- * 1 byte Kana)
- * 50222: ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte
- * Kana - SO/SI)
- *
- * MultiByteToWideChar() and WideCharToMultiByte() behave differently
- * depending on Windows version. On XP, WideCharToMultiByte() doesn't
- * terminate result sequence with ascii escape. But Vista does.
- * Use MLang instead.
- */
-
-#define ISO2022_MODE(cs, shift) (((cs) << 8) | (shift))
-#define ISO2022_MODE_CS(mode) (((mode) >> 8) & 0xFF)
-#define ISO2022_MODE_SHIFT(mode) ((mode) & 0xFF)
-
-#define ISO2022_SI 0
-#define ISO2022_SO 1
-
-/* shift in */
-static const char iso2022_SI_seq[] = "\x0F";
-/* shift out */
-static const char iso2022_SO_seq[] = "\x0E";
-
-typedef struct iso2022_esc_t iso2022_esc_t;
-struct iso2022_esc_t {
- const char *esc;
- int esc_len;
- int len;
- int cs;
-};
-
-#define ISO2022JP_CS_ASCII 0
-#define ISO2022JP_CS_JISX0201_ROMAN 1
-#define ISO2022JP_CS_JISX0201_KANA 2
-#define ISO2022JP_CS_JISX0208_1978 3
-#define ISO2022JP_CS_JISX0208_1983 4
-#define ISO2022JP_CS_JISX0212 5
-
-static iso2022_esc_t iso2022jp_esc[] = {
- {"\x1B\x28\x42", 3, 1, ISO2022JP_CS_ASCII},
- {"\x1B\x28\x4A", 3, 1, ISO2022JP_CS_JISX0201_ROMAN},
- {"\x1B\x28\x49", 3, 1, ISO2022JP_CS_JISX0201_KANA},
- {"\x1B\x24\x40", 3, 2, ISO2022JP_CS_JISX0208_1983}, /* unify 1978 with 1983 */
- {"\x1B\x24\x42", 3, 2, ISO2022JP_CS_JISX0208_1983},
- {"\x1B\x24\x28\x44", 4, 2, ISO2022JP_CS_JISX0212},
- {NULL, 0, 0, 0}
-};
-
-static int
-iso2022jp_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize)
-{
- iso2022_esc_t *iesc = iso2022jp_esc;
- char tmp[MB_CHAR_MAX];
- int insize;
- HRESULT hr;
- DWORD dummy = 0;
- int len;
- int esc_len;
- int cs;
- int shift;
- int i;
-
- if (buf[0] == 0x1B)
- {
- for (i = 0; iesc[i].esc != NULL; ++i)
- {
- esc_len = iesc[i].esc_len;
- if (bufsize < esc_len)
- {
- if (strncmp((char *)buf, iesc[i].esc, bufsize) == 0)
- return_error(EINVAL);
- }
- else
- {
- if (strncmp((char *)buf, iesc[i].esc, esc_len) == 0)
- {
- cv->mode = ISO2022_MODE(iesc[i].cs, ISO2022_SI);
- *wbufsize = 0;
- return esc_len;
- }
- }
- }
- /* not supported escape sequence */
- return_error(EILSEQ);
- }
- else if (buf[0] == iso2022_SO_seq[0])
- {
- cv->mode = ISO2022_MODE(ISO2022_MODE_CS(cv->mode), ISO2022_SO);
- *wbufsize = 0;
- return 1;
- }
- else if (buf[0] == iso2022_SI_seq[0])
- {
- cv->mode = ISO2022_MODE(ISO2022_MODE_CS(cv->mode), ISO2022_SI);
- *wbufsize = 0;
- return 1;
- }
-
- cs = ISO2022_MODE_CS(cv->mode);
- shift = ISO2022_MODE_SHIFT(cv->mode);
-
- /* reset the mode for informal sequence */
- if (buf[0] < 0x20)
- {
- cs = ISO2022JP_CS_ASCII;
- shift = ISO2022_SI;
- }
-
- len = iesc[cs].len;
- if (bufsize < len)
- return_error(EINVAL);
- for (i = 0; i < len; ++i)
- if (!(buf[i] < 0x80))
- return_error(EILSEQ);
- esc_len = iesc[cs].esc_len;
- memcpy(tmp, iesc[cs].esc, esc_len);
- if (shift == ISO2022_SO)
- {
- memcpy(tmp + esc_len, iso2022_SO_seq, 1);
- esc_len += 1;
- }
- memcpy(tmp + esc_len, buf, len);
-
- if ((cv->codepage == 50220 || cv->codepage == 50221
- || cv->codepage == 50222) && shift == ISO2022_SO)
- {
- /* XXX: shift-out cannot be used for mbtowc (both kernel and
- * mlang) */
- esc_len = iesc[ISO2022JP_CS_JISX0201_KANA].esc_len;
- memcpy(tmp, iesc[ISO2022JP_CS_JISX0201_KANA].esc, esc_len);
- memcpy(tmp + esc_len, buf, len);
- }
-
- insize = len + esc_len;
- hr = ConvertINetMultiByteToUnicode(&dummy, cv->codepage,
- (const char *)tmp, &insize, (wchar_t *)wbuf, wbufsize);
- if (hr != S_OK || insize != len + esc_len)
- return_error(EILSEQ);
-
- /* Check for conversion error. Assuming defaultChar is 0x3F. */
- /* ascii should be converted from ascii */
- if (wbuf[0] == buf[0]
- && cv->mode != ISO2022_MODE(ISO2022JP_CS_ASCII, ISO2022_SI))
- return_error(EILSEQ);
-
- /* reset the mode for informal sequence */
- if (cv->mode != ISO2022_MODE(cs, shift))
- cv->mode = ISO2022_MODE(cs, shift);
-
- return len;
-}
-
-static int
-iso2022jp_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize)
-{
- iso2022_esc_t *iesc = iso2022jp_esc;
- char tmp[MB_CHAR_MAX];
- int tmpsize = MB_CHAR_MAX;
- int insize = wbufsize;
- HRESULT hr;
- DWORD dummy = 0;
- int len;
- int esc_len;
- int cs;
- int shift;
- int i;
-
- /*
- * MultiByte = [escape sequence] + character + [escape sequence]
- *
- * Whether trailing escape sequence is added depends on which API is
- * used (kernel or MLang, and its version).
- */
- hr = ConvertINetUnicodeToMultiByte(&dummy, cv->codepage,
- (const wchar_t *)wbuf, &wbufsize, tmp, &tmpsize);
- if (hr != S_OK || insize != wbufsize)
- return_error(EILSEQ);
- else if (bufsize < tmpsize)
- return_error(E2BIG);
-
- if (tmpsize == 1)
- {
- cs = ISO2022JP_CS_ASCII;
- esc_len = 0;
- }
- else
- {
- for (i = 1; iesc[i].esc != NULL; ++i)
- {
- esc_len = iesc[i].esc_len;
- if (strncmp(tmp, iesc[i].esc, esc_len) == 0)
- {
- cs = iesc[i].cs;
- break;
- }
- }
- if (iesc[i].esc == NULL)
- /* not supported escape sequence */
- return_error(EILSEQ);
- }
-
- shift = ISO2022_SI;
- if (tmp[esc_len] == iso2022_SO_seq[0])
- {
- shift = ISO2022_SO;
- esc_len += 1;
- }
-
- len = iesc[cs].len;
-
- /* Check for converting error. Assuming defaultChar is 0x3F. */
- /* ascii should be converted from ascii */
- if (cs == ISO2022JP_CS_ASCII && !(wbuf[0] < 0x80))
- return_error(EILSEQ);
- else if (tmpsize < esc_len + len)
- return_error(EILSEQ);
-
- if (cv->mode == ISO2022_MODE(cs, shift))
- {
- /* remove escape sequence */
- if (esc_len != 0)
- memmove(tmp, tmp + esc_len, len);
- esc_len = 0;
- }
- else
- {
- if (cs == ISO2022JP_CS_ASCII)
- {
- esc_len = iesc[ISO2022JP_CS_ASCII].esc_len;
- memmove(tmp + esc_len, tmp, len);
- memcpy(tmp, iesc[ISO2022JP_CS_ASCII].esc, esc_len);
- }
- if (ISO2022_MODE_SHIFT(cv->mode) == ISO2022_SO)
- {
- /* shift-in before changing to other mode */
- memmove(tmp + 1, tmp, len + esc_len);
- memcpy(tmp, iso2022_SI_seq, 1);
- esc_len += 1;
- }
- }
-
- if (bufsize < len + esc_len)
- return_error(E2BIG);
- memcpy(buf, tmp, len + esc_len);
- cv->mode = ISO2022_MODE(cs, shift);
- return len + esc_len;
-}
-
-static int
-iso2022jp_flush(csconv_t *cv, uchar *buf, int bufsize)
-{
- iso2022_esc_t *iesc = iso2022jp_esc;
- int esc_len;
-
- if (cv->mode != ISO2022_MODE(ISO2022JP_CS_ASCII, ISO2022_SI))
- {
- esc_len = 0;
- if (ISO2022_MODE_SHIFT(cv->mode) != ISO2022_SI)
- esc_len += 1;
- if (ISO2022_MODE_CS(cv->mode) != ISO2022JP_CS_ASCII)
- esc_len += iesc[ISO2022JP_CS_ASCII].esc_len;
- if (bufsize < esc_len)
- return_error(E2BIG);
-
- esc_len = 0;
- if (ISO2022_MODE_SHIFT(cv->mode) != ISO2022_SI)
- {
- memcpy(buf, iso2022_SI_seq, 1);
- esc_len += 1;
- }
- if (ISO2022_MODE_CS(cv->mode) != ISO2022JP_CS_ASCII)
- {
- memcpy(buf + esc_len, iesc[ISO2022JP_CS_ASCII].esc,
- iesc[ISO2022JP_CS_ASCII].esc_len);
- esc_len += iesc[ISO2022JP_CS_ASCII].esc_len;
- }
- return esc_len;
- }
- return 0;
-}
-
-#if defined(MAKE_DLL) && defined(USE_LIBICONV_DLL)
-BOOL WINAPI
-DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
-{
- switch( fdwReason )
- {
- case DLL_PROCESS_ATTACH:
- hwiniconv = (HMODULE)hinstDLL;
- break;
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
-}
-#endif
-
-#if defined(MAKE_EXE)
-#include <stdio.h>
-#include <fcntl.h>
-#include <io.h>
-int
-main(int argc, char **argv)
-{
- char *fromcode = NULL;
- char *tocode = NULL;
- int i;
- char inbuf[BUFSIZ];
- char outbuf[BUFSIZ];
- const char *pin;
- char *pout;
- size_t inbytesleft;
- size_t outbytesleft;
- size_t rest = 0;
- iconv_t cd;
- size_t r;
- FILE *in = stdin;
-
- _setmode(_fileno(stdin), _O_BINARY);
- _setmode(_fileno(stdout), _O_BINARY);
-
- for (i = 1; i < argc; ++i)
- {
- if (strcmp(argv[i], "-l") == 0)
- {
- for (i = 0; codepage_alias[i].name != NULL; ++i)
- printf("%s\n", codepage_alias[i].name);
- return 0;
- }
-
- if (strcmp(argv[i], "-f") == 0)
- fromcode = argv[++i];
- else if (strcmp(argv[i], "-t") == 0)
- tocode = argv[++i];
- else
- {
- in = fopen(argv[i], "rb");
- if (in == NULL)
- {
- fprintf(stderr, "cannot open %s\n", argv[i]);
- return 1;
- }
- break;
- }
- }
-
- if (fromcode == NULL || tocode == NULL)
- {
- printf("usage: %s -f from-enc -t to-enc [file]\n", argv[0]);
- return 0;
- }
-
- cd = iconv_open(tocode, fromcode);
- if (cd == (iconv_t)(-1))
- {
- perror("iconv_open error");
- return 1;
- }
-
- while ((inbytesleft = fread(inbuf + rest, 1, sizeof(inbuf) - rest, in)) != 0
- || rest != 0)
- {
- inbytesleft += rest;
- pin = inbuf;
- pout = outbuf;
- outbytesleft = sizeof(outbuf);
- r = iconv(cd, &pin, &inbytesleft, &pout, &outbytesleft);
- fwrite(outbuf, 1, sizeof(outbuf) - outbytesleft, stdout);
- if (r == (size_t)(-1) && errno != EINVAL && errno != E2BIG)
- {
- perror("conversion error");
- return 1;
- }
- memmove(inbuf, pin, inbytesleft);
- rest = inbytesleft;
- }
- pout = outbuf;
- outbytesleft = sizeof(outbuf);
- r = iconv(cd, NULL, NULL, &pout, &outbytesleft);
- fwrite(outbuf, 1, sizeof(outbuf) - outbytesleft, stdout);
- if (r == (size_t)(-1))
- {
- perror("conversion error");
- return 1;
- }
-
- iconv_close(cd);
-
- return 0;
-}
-#endif
-