aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortheuni <theuni@svn>2010-11-27 17:47:16 +0000
committertheuni <theuni@svn>2010-11-27 17:47:16 +0000
commit3f19345ca330029b775395f28a5f476e26e19b6a (patch)
treed1e8983f52c0c8a5e1495419864df67ef11a39a8
parentb3b440aa7cce402cf73be601d57ef22293648e08 (diff)
delete libshout - now unused
Fixed up backport of r35469. git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/branches/Dharma@35488 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
-rw-r--r--xbmc/lib/libshout/Makefile.in13
-rw-r--r--xbmc/lib/libshout/argv.c358
-rw-r--r--xbmc/lib/libshout/cbuf2.c847
-rw-r--r--xbmc/lib/libshout/cbuf2.h118
-rw-r--r--xbmc/lib/libshout/charmaps.h57
-rw-r--r--xbmc/lib/libshout/charset.c521
-rwxr-xr-xxbmc/lib/libshout/charset.h72
-rw-r--r--xbmc/lib/libshout/compat.h117
-rw-r--r--xbmc/lib/libshout/config.h181
-rw-r--r--xbmc/lib/libshout/config.h.in172
-rw-r--r--xbmc/lib/libshout/confw32.h167
-rw-r--r--xbmc/lib/libshout/debug.c203
-rw-r--r--xbmc/lib/libshout/debug.h37
-rw-r--r--xbmc/lib/libshout/external.c364
-rw-r--r--xbmc/lib/libshout/external.h47
-rw-r--r--xbmc/lib/libshout/filelib.c1247
-rw-r--r--xbmc/lib/libshout/filelib.h100
-rw-r--r--xbmc/lib/libshout/findsep.c531
-rw-r--r--xbmc/lib/libshout/findsep.h37
-rw-r--r--xbmc/lib/libshout/http.c800
-rw-r--r--xbmc/lib/libshout/http.h43
-rw-r--r--xbmc/lib/libshout/iconvert.c243
-rw-r--r--xbmc/lib/libshout/ictest.c19
-rw-r--r--xbmc/lib/libshout/libshout/libshout.sln21
-rw-r--r--xbmc/lib/libshout/libshout/libshout.vcproj336
-rw-r--r--xbmc/lib/libshout/libshout/libshout.vcxproj130
-rw-r--r--xbmc/lib/libshout/libshout/libshout.vcxproj.filters134
-rw-r--r--xbmc/lib/libshout/libshout/regex/regcomp.c3801
-rw-r--r--xbmc/lib/libshout/libshout/regex/regex.c74
-rw-r--r--xbmc/lib/libshout/libshout/regex/regex.h556
-rw-r--r--xbmc/lib/libshout/libshout/regex/regex_internal.c1717
-rw-r--r--xbmc/lib/libshout/libshout/regex/regex_internal.h767
-rw-r--r--xbmc/lib/libshout/libshout/regex/regexec.c4333
-rw-r--r--xbmc/lib/libshout/libshout/stdafx.cpp8
-rw-r--r--xbmc/lib/libshout/libshout/stdafx.h11
-rw-r--r--xbmc/lib/libshout/list.h281
-rw-r--r--xbmc/lib/libshout/mchar.c601
-rw-r--r--xbmc/lib/libshout/mchar.h53
-rw-r--r--xbmc/lib/libshout/mpeg.c259
-rw-r--r--xbmc/lib/libshout/mpeg.h28
-rw-r--r--xbmc/lib/libshout/parse.c559
-rw-r--r--xbmc/lib/libshout/parse.h9
-rw-r--r--xbmc/lib/libshout/relaylib.c670
-rw-r--r--xbmc/lib/libshout/relaylib.h68
-rw-r--r--xbmc/lib/libshout/rip_manager.c765
-rw-r--r--xbmc/lib/libshout/rip_manager.h200
-rw-r--r--xbmc/lib/libshout/ripaac.c260
-rw-r--r--xbmc/lib/libshout/ripogg.c834
-rw-r--r--xbmc/lib/libshout/ripogg.h27
-rw-r--r--xbmc/lib/libshout/ripstream.c1105
-rw-r--r--xbmc/lib/libshout/ripstream.h25
-rw-r--r--xbmc/lib/libshout/socklib.c351
-rw-r--r--xbmc/lib/libshout/socklib.h20
-rw-r--r--xbmc/lib/libshout/srconfig.h16
-rw-r--r--xbmc/lib/libshout/srtypes.h286
-rw-r--r--xbmc/lib/libshout/threadlib.c91
-rw-r--r--xbmc/lib/libshout/threadlib.h28
-rw-r--r--xbmc/lib/libshout/uce_dirent.h681
-rw-r--r--xbmc/lib/libshout/utf8.c320
-rw-r--r--xbmc/lib/libshout/utf8.h36
60 files changed, 0 insertions, 25755 deletions
diff --git a/xbmc/lib/libshout/Makefile.in b/xbmc/lib/libshout/Makefile.in
deleted file mode 100644
index 4eeaaa37ba..0000000000
--- a/xbmc/lib/libshout/Makefile.in
+++ /dev/null
@@ -1,13 +0,0 @@
-OBJS=argv.o cbuf2.o charset.o debug.o external.o filelib.o findsep.o http.o iconvert.o mchar.o mpeg.o parse.o relaylib.o ripaac.o rip_manager.o ripogg.o ripstream.o socklib.o threadlib.o utf8.o
-
-CFLAGS += -D__UNIX__ -DXBMC
-
-LIB=libshout-@ARCH@.a
-
-include ../../../Makefile.include
-# Don't use -DHAVE_CONFIG_H for osx
-ifeq (osx,$(findstring osx, @ARCH@))
- DEFINES := $(filter-out -DHAVE_CONFIG_H,$(DEFINES))
-endif
-
-
diff --git a/xbmc/lib/libshout/argv.c b/xbmc/lib/libshout/argv.c
deleted file mode 100644
index 69619964e4..0000000000
--- a/xbmc/lib/libshout/argv.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/* Create and destroy argument vectors (argv's)
- Copyright (C) 1992, 2001 Free Software Foundation, Inc.
- Written by Fred Fish @ Cygnus Support
-
-This file is part of the libiberty library.
-Libiberty 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.
-
-Libiberty 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 libiberty; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-
-/* Create and destroy argument vectors. An argument vector is simply an
- array of string pointers, terminated by a NULL pointer. */
-
-#if defined (commentout)
-#include "ansidecl.h"
-#include "libiberty.h"
-#endif
-void freeargv (char **vector);
-
-#ifdef _MSC_VER
-#define alloca _alloca
-#endif
-
-#define ISBLANK(ch) ((ch) == ' ' || (ch) == '\t')
-
-/* Routines imported from standard C runtime libraries. */
-
-#ifdef ANSI_PROTOTYPES
-
-#include <stddef.h>
-#include <string.h>
-#include <stdlib.h>
-
-#else /* !ANSI_PROTOTYPES */
-
-#if !defined _WIN32 || defined __GNUC__
-#include <stdlib.h>
-#include <string.h>
-#endif
-
-#endif /* ANSI_PROTOTYPES */
-
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef EOS
-#define EOS '\0'
-#endif
-
-#define INITIAL_MAXARGC 8 /* Number of args + NULL in initial argv */
-
-
-/*
-
-@deftypefn Extension char** dupargv (char **@var{vector})
-
-Duplicate an argument vector. Simply scans through @var{vector},
-duplicating each argument until the terminating @code{NULL} is found.
-Returns a pointer to the argument vector if successful. Returns
-@code{NULL} if there is insufficient memory to complete building the
-argument vector.
-
-@end deftypefn
-
-*/
-
-char **
-dupargv (argv)
- char **argv;
-{
- int argc;
- char **copy;
-
- if (argv == NULL)
- return NULL;
-
- /* the vector */
- for (argc = 0; argv[argc] != NULL; argc++);
- copy = (char **) malloc ((argc + 1) * sizeof (char *));
- if (copy == NULL)
- return NULL;
-
- /* the strings */
- for (argc = 0; argv[argc] != NULL; argc++)
- {
- int len = strlen (argv[argc]);
- copy[argc] = malloc (sizeof (char *) * (len + 1));
- if (copy[argc] == NULL)
- {
- freeargv (copy);
- return NULL;
- }
- strcpy (copy[argc], argv[argc]);
- }
- copy[argc] = NULL;
- return copy;
-}
-
-/*
-
-@deftypefn Extension void freeargv (char **@var{vector})
-
-Free an argument vector that was built using @code{buildargv}. Simply
-scans through @var{vector}, freeing the memory for each argument until
-the terminating @code{NULL} is found, and then frees @var{vector}
-itself.
-
-@end deftypefn
-
-*/
-
-void freeargv (vector)
-char **vector;
-{
- register char **scan;
-
- if (vector != NULL)
- {
- for (scan = vector; *scan != NULL; scan++)
- {
- free (*scan);
- }
- free (vector);
- }
-}
-
-/*
-
-@deftypefn Extension char** buildargv (char *@var{sp})
-
-Given a pointer to a string, parse the string extracting fields
-separated by whitespace and optionally enclosed within either single
-or double quotes (which are stripped off), and build a vector of
-pointers to copies of the string for each field. The input string
-remains unchanged. The last element of the vector is followed by a
-@code{NULL} element.
-
-All of the memory for the pointer array and copies of the string
-is obtained from @code{malloc}. All of the memory can be returned to the
-system with the single function call @code{freeargv}, which takes the
-returned result of @code{buildargv}, as it's argument.
-
-Returns a pointer to the argument vector if successful. Returns
-@code{NULL} if @var{sp} is @code{NULL} or if there is insufficient
-memory to complete building the argument vector.
-
-If the input is a null string (as opposed to a @code{NULL} pointer),
-then buildarg returns an argument vector that has one arg, a null
-string.
-
-@end deftypefn
-
-The memory for the argv array is dynamically expanded as necessary.
-
-In order to provide a working buffer for extracting arguments into,
-with appropriate stripping of quotes and translation of backslash
-sequences, we allocate a working buffer at least as long as the input
-string. This ensures that we always have enough space in which to
-work, since the extracted arg is never larger than the input string.
-
-The argument vector is always kept terminated with a @code{NULL} arg
-pointer, so it can be passed to @code{freeargv} at any time, or
-returned, as appropriate.
-
-*/
-
-char **buildargv (input)
- const char *input;
-{
- char *arg;
- char *copybuf;
- int squote = 0;
- int dquote = 0;
- int bsquote = 0;
- int argc = 0;
- int maxargc = 0;
- char **argv = NULL;
- char **nargv;
-
- if (input != NULL)
- {
- copybuf = (char *) alloca (strlen (input) + 1);
- /* Is a do{}while to always execute the loop once. Always return an
- argv, even for null strings. See NOTES above, test case below. */
- do
- {
- /* Pick off argv[argc] */
- while (ISBLANK (*input))
- {
- input++;
- }
- if ((maxargc == 0) || (argc >= (maxargc - 1)))
- {
- /* argv needs initialization, or expansion */
- if (argv == NULL)
- {
- maxargc = INITIAL_MAXARGC;
- nargv = (char **) malloc (maxargc * sizeof (char *));
- }
- else
- {
- maxargc *= 2;
- nargv = (char **) realloc (argv, maxargc * sizeof (char *));
- }
- if (nargv == NULL)
- {
- if (argv != NULL)
- {
- freeargv (argv);
- argv = NULL;
- }
- break;
- }
- argv = nargv;
- argv[argc] = NULL;
- }
- /* Begin scanning arg */
- arg = copybuf;
- while (*input != EOS)
- {
- if (ISBLANK (*input) && !squote && !dquote && !bsquote)
- {
- break;
- }
- else
- {
- if (bsquote)
- {
- bsquote = 0;
- *arg++ = *input;
- }
- else if (*input == '\\')
- {
- bsquote = 1;
- }
- else if (squote)
- {
- if (*input == '\'')
- {
- squote = 0;
- }
- else
- {
- *arg++ = *input;
- }
- }
- else if (dquote)
- {
- if (*input == '"')
- {
- dquote = 0;
- }
- else
- {
- *arg++ = *input;
- }
- }
- else
- {
- if (*input == '\'')
- {
- squote = 1;
- }
- else if (*input == '"')
- {
- dquote = 1;
- }
- else
- {
- *arg++ = *input;
- }
- }
- input++;
- }
- }
- *arg = EOS;
- argv[argc] = strdup (copybuf);
- if (argv[argc] == NULL)
- {
- freeargv (argv);
- argv = NULL;
- break;
- }
- argc++;
- argv[argc] = NULL;
-
- while (ISBLANK (*input))
- {
- input++;
- }
- }
- while (*input != EOS);
- }
- return (argv);
-}
-
-#ifdef MAIN
-
-/* Simple little test driver. */
-
-static const char *const tests[] =
-{
- "a simple command line",
- "arg 'foo' is single quoted",
- "arg \"bar\" is double quoted",
- "arg \"foo bar\" has embedded whitespace",
- "arg 'Jack said \\'hi\\'' has single quotes",
- "arg 'Jack said \\\"hi\\\"' has double quotes",
- "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9",
-
- /* This should be expanded into only one argument. */
- "trailing-whitespace ",
-
- "",
- NULL
-};
-
-int main ()
-{
- char **argv;
- const char *const *test;
- char **targs;
-
- for (test = tests; *test != NULL; test++)
- {
- printf ("buildargv(\"%s\")\n", *test);
- if ((argv = buildargv (*test)) == NULL)
- {
- printf ("failed!\n\n");
- }
- else
- {
- for (targs = argv; *targs != NULL; targs++)
- {
- printf ("\t\"%s\"\n", *targs);
- }
- printf ("\n");
- }
- freeargv (argv);
- }
-
- return 0;
-}
-
-#endif /* MAIN */
diff --git a/xbmc/lib/libshout/cbuf2.c b/xbmc/lib/libshout/cbuf2.c
deleted file mode 100644
index 40fc2e6a6d..0000000000
--- a/xbmc/lib/libshout/cbuf2.c
+++ /dev/null
@@ -1,847 +0,0 @@
-/* cbuf2.c
- * circular buffer lib - version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "relaylib.h"
-#include "cbuf2.h"
-#include "debug.h"
-#include "ripogg.h"
-
-/*****************************************************************************
- * Global variables
- *****************************************************************************/
-/* The circular buffer */
-CBUF2 g_cbuf2;
-
-/*****************************************************************************
- * Notes:
- *
- * The terminology "count" should refer to a length, starting from
- * the first filled byte.
- *
- * The terminology "offset" == "count"
- *
- * The terminology "pos" should refer to the absolute array index,
- * starting from the beginning of the allocated buffer.
- *
- * The terminology "idx" == "pos"
- *
- * The read & write indices always point to the next byte to be read
- * or written. When the buffer is full or empty, they are equal.
- * Use the item_count to distinguish these cases.
- *****************************************************************************/
-/*****************************************************************************
- * Private functions
- *****************************************************************************/
-static u_long cbuf2_idx_to_chunk (CBUF2 *cbuf2, u_long idx);
-static u_long cbuf2_add (CBUF2 *cbuf2, u_long pos, u_long len);
-static void cbuf2_get_used_fragments (CBUF2 *cbuf2, u_long* frag1,
- u_long* frag2);
-static void cbuf2_advance_metadata_list (CBUF2* cbuf2);
-static error_code cbuf2_extract_relay_mp3 (CBUF2 *cbuf2, char *data,
- u_long *pos, u_long *len,
- int icy_metadata);
-static error_code cbuf2_extract_relay_ogg (CBUF2 *cbuf2, RELAY_LIST* ptr);
-static u_long cbuf2_offset (CBUF2 *cbuf2, u_long pos);
-static u_long cbuf2_offset_2 (CBUF2 *cbuf2, u_long pos);
-#if defined (commentout)
-static u_long cbuf2_subtract (CBUF2 *cbuf2, u_long pos1, u_long pos2);
-#endif
-
-/*****************************************************************************
- * Function definitions
- *****************************************************************************/
-error_code
-cbuf2_init (CBUF2 *cbuf2, int content_type, int have_relay,
- unsigned long chunk_size, unsigned long num_chunks)
-{
- if (chunk_size == 0 || num_chunks == 0) {
- return SR_ERROR_INVALID_PARAM;
- }
- cbuf2->have_relay = have_relay;
- cbuf2->content_type = content_type;
- cbuf2->chunk_size = chunk_size;
- cbuf2->num_chunks = num_chunks;
- cbuf2->size = chunk_size * num_chunks;
- cbuf2->buf = (char*) malloc (cbuf2->size);
- cbuf2->base_idx = 0;
- cbuf2->item_count = 0;
- cbuf2->next_song = 0; /* MP3 only */
- cbuf2->song_page = 0; /* OGG only */
- cbuf2->song_page_done = 0; /* OGG only */
-
- INIT_LIST_HEAD (&cbuf2->metadata_list);
- INIT_LIST_HEAD (&cbuf2->ogg_page_list);
-
- cbuf2->cbuf_sem = threadlib_create_sem();
- threadlib_signal_sem (&cbuf2->cbuf_sem);
-
- return SR_SUCCESS;
-}
-
-void
-cbuf2_destroy (CBUF2 *cbuf2)
-{
- if (cbuf2->buf) {
- free (cbuf2->buf);
- cbuf2->buf = NULL;
- /* GCS FIX: Delete metadata queue */
- threadlib_destroy_sem(&cbuf2->cbuf_sem);
- }
-}
-
-static error_code
-cbuf2_insert (CBUF2 *cbuf2, const char *data, u_long count)
-{
- u_long ft;
- u_long write_idx;
-
- if (cbuf2_get_free (cbuf2) < count) {
- return SR_ERROR_BUFFER_FULL;
- }
-
- write_idx = cbuf2_write_index (cbuf2);
- ft = cbuf2_get_free_tail (cbuf2);
- if (ft >= count) {
- memcpy (&cbuf2->buf[write_idx], data, count);
- } else {
- memcpy (&cbuf2->buf[write_idx], data, ft);
- memcpy (&cbuf2->buf[0], &data[ft], count-ft);
- }
- cbuf2->item_count += count;
- return SR_SUCCESS;
-}
-
-static void
-cbuf2_advance_metadata_list (CBUF2* cbuf2)
-{
- u_long frag1, frag2;
- u_long metadata_pos;
- u_long chunk_no;
- LIST *p;
- METADATA_LIST *tmp;
-
- cbuf2_get_used_fragments (cbuf2, &frag1, &frag2);
- chunk_no = cbuf2_idx_to_chunk (cbuf2, cbuf2->base_idx);
-
- /* Loop through all metadata, from tail to head */
- list_for_each_prev (p, &(cbuf2->metadata_list)) {
-
- /* Get position of metadata */
- tmp = list_entry(p, METADATA_LIST, m_list);
- metadata_pos = (tmp->m_chunk + 1) * cbuf2->chunk_size - 1;
- debug_printf ("CE3: %d\n", metadata_pos);
-
- if (metadata_pos >= cbuf2->base_idx
- && metadata_pos < cbuf2->base_idx + frag1) {
- /* Nothing to do */
- } else if (frag2 > 0 && metadata_pos <= frag2) {
- /* Nothing to do */
- } else {
- /* Push metadata forward to most recent read pointer */
- tmp->m_chunk = chunk_no;
- }
- /* If metadata is at head, evict all previous metadata from the list */
- debug_printf ("CE4: %d %d\n", tmp->m_chunk, chunk_no);
- if (tmp->m_chunk == chunk_no) {
- while (p->prev != &cbuf2->metadata_list) {
- LIST* pp = p->prev;
- list_del (p->prev);
- free (list_entry (pp,METADATA_LIST,m_list));
- }
- }
- }
- debug_printf ("CBUF_EXTRACT\n");
- cbuf2_debug_lists (cbuf2);
-}
-
-static void
-cbuf2_advance_relay_list (CBUF2* cbuf2, u_long count)
-{
- RELAY_LIST *prev, *ptr, *next;
-
- ptr = g_relay_list;
- if (ptr == NULL) {
- return;
- }
- prev = NULL;
- while (ptr != NULL) {
- next = ptr->m_next;
- if (!ptr->m_is_new) {
- if (ptr->m_cbuf_pos >= count) {
- u_long old_pos = ptr->m_cbuf_pos;
- ptr->m_cbuf_pos -= count;
- debug_printf ("Updated relay pointer: %d -> %d\n",
- old_pos, ptr->m_cbuf_pos);
- prev = ptr;
- } else {
- debug_printf ("Relay: Client %d couldn't keep up with cbuf\n",
- ptr->m_sock);
- relaylib_disconnect (prev, ptr);
- }
- }
- ptr = next;
- }
-}
-
-void
-cbuf2_set_next_song (CBUF2 *cbuf2, u_long pos)
-{
- cbuf2->next_song = pos;
-}
-
-/* Advance the cbuffer while respecting ogg page boundaries */
-error_code
-cbuf2_advance_ogg (CBUF2 *cbuf2, int requested_free_size)
-{
- u_long count;
- LIST *p, *n;
- OGG_PAGE_LIST *tmp;
-
- if (cbuf2->item_count + requested_free_size <= cbuf2->size) {
- return SR_SUCCESS;
- }
-
- if (cbuf2->have_relay) {
- debug_printf ("Waiting for g_relay_list_sem\n");
- threadlib_waitfor_sem (&g_relay_list_sem);
- }
- debug_printf ("Waiting for cbuf2->cbuf_sem\n");
- threadlib_waitfor_sem (&cbuf2->cbuf_sem);
-
- /* count is the amount we're going to free up */
- count = requested_free_size - (cbuf2->size - cbuf2->item_count);
-
- /* Loop through ogg pages, from head to tail. Eject pages that
- that map into the portion of the buffer that we are freeing. */
- p = cbuf2->ogg_page_list.next;
- list_for_each_safe (p, n, &(cbuf2->ogg_page_list)) {
- u_long pos;
- tmp = list_entry(p, OGG_PAGE_LIST, m_list);
- pos = cbuf2_offset (cbuf2, tmp->m_page_start);
- if (pos > count) {
- break;
- }
- list_del (p);
- if (tmp->m_page_flags & OGG_PAGE_EOS) {
- free (tmp->m_header_buf_ptr);
- }
- free (tmp);
- if (cbuf2->item_count + requested_free_size <= cbuf2->size) {
- break;
- }
- }
- cbuf2->base_idx = cbuf2_add (cbuf2, cbuf2->base_idx, count);
- cbuf2->item_count -= count;
-
- if (cbuf2->have_relay) {
- cbuf2_advance_relay_list (cbuf2, count);
- }
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- if (cbuf2->have_relay) {
- threadlib_signal_sem (&g_relay_list_sem);
- }
-
- if (cbuf2->item_count + requested_free_size <= cbuf2->size) {
- return SR_SUCCESS;
- } else {
- return SR_ERROR_BUFFER_EMPTY;
- }
-}
-
-/* On extract, we need to update all the relay pointers. */
-/* GCS Now it always extracts a chunk */
-error_code
-cbuf2_extract (CBUF2 *cbuf2, char *data, u_long count, u_long* curr_song)
-{
- u_long frag1, frag2;
-
- /* Don't need to lock this, only the ripping thread changes it. */
- if (cbuf2->item_count < count) {
- return SR_ERROR_BUFFER_EMPTY;
- }
-
- if (cbuf2->have_relay) {
- debug_printf ("Waiting for g_relay_list_sem\n");
- threadlib_waitfor_sem (&g_relay_list_sem);
- }
- debug_printf ("Waiting for cbuf2->cbuf_sem\n");
- threadlib_waitfor_sem (&cbuf2->cbuf_sem);
- cbuf2_get_used_fragments (cbuf2, &frag1, &frag2);
- if (frag1 >= count) {
- memcpy (data, &cbuf2->buf[cbuf2->base_idx], count);
- } else {
- debug_printf ("This should never happen\n");
- memcpy (data, &cbuf2->buf[cbuf2->base_idx], frag1);
- memcpy (&data[frag1], &cbuf2->buf[0], count-frag1);
- }
- cbuf2->base_idx = cbuf2_add (cbuf2, cbuf2->base_idx, count);
- cbuf2->item_count -= count;
- debug_printf ("CE2: %d\n", cbuf2->base_idx);
-
- *curr_song = cbuf2->next_song;
- if (cbuf2->next_song < count) {
- cbuf2->next_song = 0;
- } else {
- cbuf2->next_song -= count;
- }
-
- cbuf2_advance_metadata_list (cbuf2);
-
- if (cbuf2->have_relay) {
- cbuf2_advance_relay_list (cbuf2, count);
- }
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- if (cbuf2->have_relay) {
- threadlib_signal_sem (&g_relay_list_sem);
- }
- return SR_SUCCESS;
-}
-
-error_code
-cbuf2_fastforward (CBUF2 *cbuf2, u_long count)
-{
- threadlib_waitfor_sem (&cbuf2->cbuf_sem);
- if (cbuf2->item_count < count) {
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- return SR_ERROR_BUFFER_EMPTY;
- }
- cbuf2->base_idx = cbuf2_add (cbuf2, cbuf2->base_idx, count);
- cbuf2->item_count -= count;
-
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- return SR_SUCCESS;
-}
-
-error_code
-cbuf2_peek (CBUF2 *cbuf2, char *data, u_long count)
-{
- u_long frag1, frag2;
-
- if (cbuf2->item_count < count) {
- return SR_ERROR_BUFFER_EMPTY;
- }
-
- threadlib_waitfor_sem (&cbuf2->cbuf_sem);
- cbuf2_get_used_fragments (cbuf2, &frag1, &frag2);
- if (frag1 >= count) {
- memcpy (data, &cbuf2->buf[cbuf2->base_idx], count);
- } else {
- memcpy (data, &cbuf2->buf[cbuf2->base_idx], frag1);
- memcpy (&data[frag1], &cbuf2->buf[0], count-frag1);
- }
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- return SR_SUCCESS;
-}
-
-error_code
-cbuf2_insert_chunk (CBUF2 *cbuf2, const char *data, u_long count,
- int content_type, TRACK_INFO* ti)
-{
- LIST this_page_list;
- int chunk_no;
- error_code rc;
-
- /* Identify OGG pages using rip_ogg_process_chunk().
- We can do this before locking the CBUF to improve
- concurrency with relay threads. */
- if (content_type == CONTENT_TYPE_OGG) {
- OGG_PAGE_LIST* tmp;
- LIST *p;
- unsigned long page_loc;
-
- rip_ogg_process_chunk (&this_page_list, data, count, ti);
-
- if (list_empty(&cbuf2->ogg_page_list)) {
- page_loc = 0;
- } else {
- p = cbuf2->ogg_page_list.prev;
- tmp = list_entry(p, OGG_PAGE_LIST, m_list);
- page_loc = cbuf2_add (cbuf2, tmp->m_page_start, tmp->m_page_len);
- }
-
- // p = &this_page_list.next;
- list_for_each (p, &this_page_list) {
- tmp = list_entry(p, OGG_PAGE_LIST, m_list);
- tmp->m_page_start = page_loc;
- page_loc = cbuf2_add (cbuf2, page_loc, tmp->m_page_len);
- }
- }
-
- /* Insert data */
- threadlib_waitfor_sem (&cbuf2->cbuf_sem);
- chunk_no = cbuf2_idx_to_chunk (cbuf2, cbuf2_write_index(cbuf2));
- rc = cbuf2_insert (cbuf2, data, count);
- if (rc != SR_SUCCESS) {
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- return rc;
- }
-
- if (content_type == CONTENT_TYPE_OGG) {
- list_splice (&this_page_list, cbuf2->ogg_page_list.prev);
- } else if (ti && ti->have_track_info) {
- /* Insert metadata data */
-#if defined (commentout)
- int num_bytes;
- unsigned char num_16_bytes;
-#endif
- METADATA_LIST* ml;
- ml = (METADATA_LIST*) malloc (sizeof(METADATA_LIST));
- /* GCS FIX: Check malloc error */
- ml->m_chunk = chunk_no;
-#if defined (commentout)
- num_bytes = snprintf (&ml->m_composed_metadata[1], MAX_METADATA_LEN,
- "StreamTitle='%s - %s';",
- ti->artist, ti->title);
- ml->m_composed_metadata[MAX_METADATA_LEN] = 0; // note, not LEN-1
- num_16_bytes = (num_bytes + 15) / 16;
- ml->m_composed_metadata[0] = num_16_bytes;
-#endif
- memcpy (ml->m_composed_metadata, ti->composed_metadata,
- MAX_METADATA_LEN+1);
- list_add_tail (&(ml->m_list), &(cbuf2->metadata_list));
- }
- debug_printf ("CBUF_INSERT\n");
- cbuf2_debug_lists (cbuf2);
-
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- return SR_SUCCESS;
-}
-
-/* Relay always gets one chunk. Return 1 if we got a chunk,
- return 0 if the buffer is empty.
-*/
-error_code
-cbuf2_extract_relay (CBUF2 *cbuf2, RELAY_LIST* ptr)
-{
- if (cbuf2->content_type == CONTENT_TYPE_OGG) {
- return cbuf2_extract_relay_ogg (cbuf2, ptr);
- } else {
- return cbuf2_extract_relay_mp3 (cbuf2, ptr->m_buffer,
- &ptr->m_cbuf_pos, &ptr->m_left_to_send,
- ptr->m_icy_metadata);
- }
-}
-
-static error_code
-cbuf2_extract_relay_ogg (CBUF2 *cbuf2, RELAY_LIST* ptr)
-{
- if (ptr->m_header_buf_ptr) {
- u_long remaining = ptr->m_header_buf_len - ptr->m_header_buf_off;
- if (remaining > ptr->m_buffer_size) {
- memcpy (ptr->m_buffer,
- &ptr->m_header_buf_ptr[ptr->m_header_buf_off],
- ptr->m_buffer_size);
- ptr->m_header_buf_off += ptr->m_buffer_size;
- ptr->m_left_to_send = ptr->m_buffer_size;
- } else {
- memcpy (ptr->m_buffer,
- &ptr->m_header_buf_ptr[ptr->m_header_buf_off],
- remaining);
- ptr->m_header_buf_ptr = 0;
- ptr->m_header_buf_off = 0;
- ptr->m_header_buf_len = 0;
- ptr->m_left_to_send = remaining;
- }
- } else {
- u_long frag1, frag2;
- u_long relay_idx, remaining;
-
- threadlib_waitfor_sem (&cbuf2->cbuf_sem);
- relay_idx = cbuf2_add (cbuf2, cbuf2->base_idx, ptr->m_cbuf_pos);
- cbuf2_get_used_fragments (cbuf2, &frag1, &frag2);
- if (ptr->m_cbuf_pos < frag1) {
- remaining = frag1 - ptr->m_cbuf_pos;
- } else {
- remaining = cbuf2->item_count - ptr->m_cbuf_pos;
- }
- debug_printf ("%p p=%d/t=%d (f1=%d,f2=%d) [r=%d/bs=%d]\n",
- ptr,
- ptr->m_cbuf_pos, cbuf2->item_count,
- frag1, frag2,
- remaining, ptr->m_buffer_size);
- if (remaining == 0) {
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- return SR_ERROR_BUFFER_EMPTY;
- }
- if (remaining > ptr->m_buffer_size) {
- memcpy (ptr->m_buffer, &cbuf2->buf[relay_idx], ptr->m_buffer_size);
- ptr->m_left_to_send = ptr->m_buffer_size;
- ptr->m_cbuf_pos += ptr->m_buffer_size;
- } else {
- memcpy (ptr->m_buffer, &cbuf2->buf[relay_idx], remaining);
- ptr->m_left_to_send = remaining;
- ptr->m_cbuf_pos += remaining;
- }
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- }
- return SR_SUCCESS;
-}
-
-static error_code
-cbuf2_extract_relay_mp3 (CBUF2 *cbuf2, char *data, u_long *pos, u_long *len,
- int icy_metadata)
-{
- u_long frag1, frag2;
- u_long relay_chunk_no;
- u_long relay_idx;
- u_long old_pos;
- *len = 0;
-
- /* Check if there is data to send to the relay */
- threadlib_waitfor_sem (&cbuf2->cbuf_sem);
- cbuf2_get_used_fragments (cbuf2, &frag1, &frag2);
- if (*pos + cbuf2->chunk_size > cbuf2->item_count) {
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- return SR_ERROR_BUFFER_EMPTY;
- }
-
- /* Otherwise, there is enough data */
- /* The *pos is the offset from the filled part of the buffer */
- old_pos = *pos;
- relay_idx = cbuf2_add (cbuf2, cbuf2->base_idx, *pos);
- relay_chunk_no = cbuf2_idx_to_chunk (cbuf2, *pos);
- memcpy (data, &cbuf2->buf[relay_idx], cbuf2->chunk_size);
- *pos += cbuf2->chunk_size;
- *len = cbuf2->chunk_size;
- debug_printf ("Updated relay pointer: %d -> %d (%d %d %d)\n",
- old_pos, *pos, cbuf2->base_idx,
- relay_idx, cbuf2_write_index(cbuf2));
- debug_printf ("Partial request fulfilled: %d bytes (%d)\n", *len,
- icy_metadata);
- if (icy_metadata) {
- int have_metadata = 0;
- LIST *p = cbuf2->metadata_list.next;
- METADATA_LIST *tmp;
- list_for_each (p, &(cbuf2->metadata_list)) {
- tmp = list_entry(p, METADATA_LIST, m_list);
- debug_printf ("Comparing metadata: meta=%d relay=%d\n",
- tmp->m_chunk, relay_chunk_no);
- if (tmp->m_chunk == relay_chunk_no) {
- debug_printf ("Got metadata!\n");
- have_metadata = 1;
- break;
- }
- }
- if (have_metadata) {
- int metadata_len = tmp->m_composed_metadata[0] * 16 + 1;
- memcpy (&data[cbuf2->chunk_size],tmp->m_composed_metadata,
- metadata_len);
- *len += metadata_len;
- } else {
- data[cbuf2->chunk_size] = '\0';
- (*len) ++;
- }
- }
- debug_printf ("Final request fulfilled: %d bytes\n", *len);
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- return SR_SUCCESS;
-}
-
-void
-cbuf2_debug_lists (CBUF2 *cbuf2)
-{
- LIST *p;
-
- debug_printf ("---CBUF_DEBUG_META_LIST---\n");
- debug_printf("%ld: <size>\n", cbuf2->size);
- debug_printf("%ld: Start\n", cbuf2->base_idx);
- list_for_each (p, &(cbuf2->metadata_list)) {
- METADATA_LIST *meta_tmp;
- int metadata_pos;
- meta_tmp = list_entry (p, METADATA_LIST, m_list);
- metadata_pos = (meta_tmp->m_chunk + 1) * cbuf2->chunk_size - 1;
- debug_printf("%ld: %d [%d]%s\n",
- metadata_pos,
- meta_tmp->m_chunk,
- (int) meta_tmp->m_composed_metadata[0],
- &meta_tmp->m_composed_metadata[1]);
- }
- debug_printf("%ld: End\n", cbuf2_write_index(cbuf2));
-
- debug_printf ("---CBUF_DEBUG_OGG_LIST---\n");
- debug_printf("%ld: <size>\n", cbuf2->size);
- debug_printf("%ld: Start\n", cbuf2->base_idx);
- list_for_each (p, &(cbuf2->ogg_page_list)) {
- OGG_PAGE_LIST *ogg_tmp;
- ogg_tmp = list_entry (p, OGG_PAGE_LIST, m_list);
- debug_printf("ogg page = %02x [%ld, %ld, %ld]\n",
- ogg_tmp->m_page_flags,
- ogg_tmp->m_page_start,
- ogg_tmp->m_page_len,
- cbuf2_add(cbuf2,ogg_tmp->m_page_start,
- ogg_tmp->m_page_len));
- }
- if (cbuf2->song_page) {
- debug_printf ("%ld(%ld): Song Page\n",
- cbuf2->song_page->m_page_start,
- cbuf2->song_page_done);
- } else {
- debug_printf ("---: Song Page\n");
- }
- debug_printf ("%ld: End\n", cbuf2_write_index(cbuf2));
- debug_printf ("---\n");
-}
-
-error_code
-cbuf2_ogg_peek_song (CBUF2 *cbuf2, char* out_buf,
- unsigned long buf_size,
- unsigned long* amt_filled,
- int* eos)
-{
- error_code ret;
- unsigned long song_offset;
-
- *amt_filled = 0;
- *eos = 0;
-
- /* First time through, set the song_page */
- if (!cbuf2->song_page) {
- if (cbuf2->ogg_page_list.next) {
- cbuf2->song_page = list_entry (cbuf2->ogg_page_list.next,
- OGG_PAGE_LIST, m_list);
- cbuf2->song_page_done = 0;
- } else {
- return SR_SUCCESS;
- }
- }
-
- /* Advance song_page if old one is finished */
- if (cbuf2->song_page_done == cbuf2->song_page->m_page_len) {
- if (cbuf2->song_page->m_list.next == &cbuf2->ogg_page_list) {
- return SR_SUCCESS;
- } else {
- cbuf2->song_page = list_entry (cbuf2->song_page->m_list.next,
- OGG_PAGE_LIST, m_list);
- cbuf2->song_page_done = 0;
- }
- }
-
- /* Calculate the amount to return to the caller */
- *amt_filled = cbuf2->song_page->m_page_len - cbuf2->song_page_done;
- if (*amt_filled > buf_size) {
- *amt_filled = buf_size;
- } else {
- if (cbuf2->song_page->m_page_flags & OGG_PAGE_EOS) {
- *eos = 1;
- }
- }
-
- song_offset = cbuf2_offset_2 (cbuf2, cbuf2->song_page->m_page_start);
- song_offset += cbuf2->song_page_done;
- ret = cbuf2_peek_rgn (cbuf2, out_buf, song_offset, *amt_filled);
- if (ret != SR_SUCCESS) {
- return ret;
- }
-
- cbuf2->song_page_done += *amt_filled;
- return SR_SUCCESS;
-}
-
-u_long
-cbuf2_get_free (CBUF2 *cbuf2)
-{
- return cbuf2->size - cbuf2->item_count;
-}
-
-/* Returns the amount of contiguous free memory immediately
- following the write index */
-u_long
-cbuf2_get_free_tail (CBUF2 *cbuf2)
-{
- unsigned long ft = cbuf2->size - cbuf2_write_index(cbuf2);
- unsigned long fr = cbuf2_get_free(cbuf2);
- if (ft > fr) {
- return fr;
- } else {
- return ft;
- }
-}
-
-/* Returns the amount of contiguous used memory from read_ptr
- to end of cbuf, and then from start to end of used. */
-static void
-cbuf2_get_used_fragments (CBUF2 *cbuf2, u_long* frag1, u_long* frag2)
-{
- u_long ut = cbuf2->size - cbuf2->base_idx;
- u_long us = cbuf2->item_count;
- if (us > ut) {
- *frag1 = ut;
- *frag2 = us - ut;
- } else {
- *frag1 = us;
- *frag2 = 0;
- }
-}
-
-u_long
-cbuf2_write_index (CBUF2 *cbuf2)
-{
- return cbuf2_add (cbuf2, cbuf2->base_idx, cbuf2->item_count);
-}
-
-static u_long
-cbuf2_add (CBUF2 *cbuf2, u_long pos, u_long len)
-{
- pos += len;
- if (pos >= cbuf2->size)
- pos -= cbuf2->size;
- return pos;
-}
-
-static u_long
-cbuf2_offset (CBUF2 *cbuf2, u_long pos)
-{
- long diff = pos - cbuf2->base_idx;
- if (diff >= 0) {
- return diff;
- } else {
- return diff + cbuf2->size;
- }
-}
-
-/* This is like the above, but it never returns zero */
-static u_long
-cbuf2_offset_2 (CBUF2 *cbuf2, u_long pos)
-{
- long diff = pos - cbuf2->base_idx;
- if (diff > 0) {
- return diff;
- } else {
- return diff + cbuf2->size;
- }
-}
-
-/* returns pos1 - pos2 (not used) */
-#if defined (commentout)
-static u_long
-cbuf2_subtract (CBUF2 *cbuf2, u_long pos1, u_long pos2)
-{
- long diff = pos1 - pos2;
- if (diff > 0) {
- return diff;
- } else {
- return diff + cbuf2->item_count;
- }
-}
-#endif
-
-static u_long
-cbuf2_idx_to_chunk (CBUF2 *cbuf2, u_long idx)
-{
- return idx / cbuf2->chunk_size;
-}
-
-error_code
-cbuf2_peek_rgn (CBUF2 *cbuf2, char *out_buf, u_long start_offset,
- u_long length)
-{
- u_long sidx;
-
- if (length > cbuf2->item_count)
- return SR_ERROR_BUFFER_EMPTY;
- sidx = cbuf2_add (cbuf2, cbuf2->base_idx, start_offset);
- if (sidx + length > cbuf2->size) {
- int first_hunk = cbuf2->size - sidx;
- memcpy (out_buf, cbuf2->buf+sidx, first_hunk);
- sidx = 0;
- length -= first_hunk;
- out_buf += first_hunk;
- }
- memcpy (out_buf, cbuf2->buf+sidx, length);
-
- return SR_SUCCESS;
-}
-
-error_code
-cbuf2_init_relay_entry (CBUF2 *cbuf2, RELAY_LIST* ptr, u_long burst_request)
-{
- int buffer_size;
- LIST *p;
- OGG_PAGE_LIST *tmp;
-
- threadlib_waitfor_sem (&cbuf2->cbuf_sem);
- if (burst_request >= cbuf2->item_count) {
- ptr->m_cbuf_pos = 0;
- } else {
- ptr->m_cbuf_pos = cbuf2->item_count - burst_request;
- }
- if (cbuf2->content_type == CONTENT_TYPE_OGG) {
- /* Move to ogg page boundary */
- int no_boundary_yet = 1;
- u_long req_pos = ptr->m_cbuf_pos;
- p = cbuf2->ogg_page_list.next;
- list_for_each (p, &(cbuf2->ogg_page_list)) {
- u_long page_offset;
- tmp = list_entry(p, OGG_PAGE_LIST, m_list);
- page_offset = cbuf2_offset (cbuf2, tmp->m_page_start);
- if (page_offset < req_pos || no_boundary_yet) {
- if (tmp->m_page_flags & OGG_PAGE_BOS) {
- ptr->m_cbuf_pos = page_offset;
- ptr->m_header_buf_ptr = 0;
- ptr->m_header_buf_len = 0;
- ptr->m_header_buf_off = 0;
- no_boundary_yet = 0;
- } else if (!(tmp->m_page_flags & OGG_PAGE_2)) {
- ptr->m_cbuf_pos = page_offset;
- ptr->m_header_buf_ptr = tmp->m_header_buf_ptr;
- ptr->m_header_buf_len = tmp->m_header_buf_len;
- ptr->m_header_buf_off = 0;
- no_boundary_yet = 0;
- }
- }
- debug_printf ("Computing cbuf2_offset: "
- "req=%d pos=%d bas=%d pag=%d off=%d hbuf=%d\n",
- req_pos, ptr->m_cbuf_pos,
- cbuf2->base_idx, tmp->m_page_start,
- page_offset, ptr->m_header_buf_ptr);
- if (!no_boundary_yet && page_offset > req_pos) {
- debug_printf ("Done computing cbuf2_offset\n");
- break;
- }
- }
- if (no_boundary_yet) {
- return SR_ERROR_NO_OGG_PAGES_FOR_RELAY;
- }
- } else {
- /* Move to metadata boundary */
- ptr->m_cbuf_pos = (ptr->m_cbuf_pos / cbuf2->chunk_size)
- * cbuf2->chunk_size;
- }
- debug_printf ("cbuf2_init_relay_entry: %d %d %d %d\n",
- ptr->m_cbuf_pos,
- cbuf2->base_idx,
- cbuf2->item_count,
- cbuf2->size
- );
-
- if (ptr->m_icy_metadata) {
- buffer_size = cbuf2->chunk_size + 16*256;
- ptr->m_buffer = (char*) malloc (sizeof(char)*buffer_size);
- ptr->m_buffer_size = buffer_size;
- } else {
- buffer_size = cbuf2->chunk_size;
- ptr->m_buffer = (char*) malloc (sizeof(char)*buffer_size);
- ptr->m_buffer_size = buffer_size;
- }
- /* GCS FIX: check for memory error */
- threadlib_signal_sem (&cbuf2->cbuf_sem);
- debug_printf ("Setting relay buffer size to %d\n", buffer_size);
- return SR_SUCCESS;
-}
diff --git a/xbmc/lib/libshout/cbuf2.h b/xbmc/lib/libshout/cbuf2.h
deleted file mode 100644
index 093e0ab1d6..0000000000
--- a/xbmc/lib/libshout/cbuf2.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* cbuf2.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __CBUF2_H__
-#define __CBUF2_H__
-
-#include "srtypes.h"
-#include "threadlib.h"
-#include "list.h"
-#include "relaylib.h"
-
-/* Each metadata within the cbuf gets this struct */
-typedef struct METADATA_LIST_struct METADATA_LIST;
-struct METADATA_LIST_struct
-{
- unsigned long m_chunk;
- /* m_composed_metadata includes 1 byte for size*16 */
- char m_composed_metadata[MAX_METADATA_LEN+1];
- LIST m_list;
-};
-
-#define OGG_PAGE_BOS 0x01
-#define OGG_PAGE_EOS 0x02
-#define OGG_PAGE_2 0x04
-
-/* Each ogg page boundary within the cbuf gets this struct */
-typedef struct OGG_PAGE_LIST_struct OGG_PAGE_LIST;
-struct OGG_PAGE_LIST_struct
-{
- unsigned long m_page_start;
- unsigned long m_page_len;
- unsigned long m_page_flags;
- unsigned char *m_header_buf_ptr;
- unsigned long m_header_buf_len;
- LIST m_list;
-};
-
-typedef struct CBUF2_struct
-{
- char* buf;
- int content_type;
- int have_relay;
- u_long num_chunks;
- u_long chunk_size;
- u_long size; /* size is chunk_size * num_chunks */
- u_long base_idx;
- u_long item_count; /* Amount filled */
- u_long next_song; /* start of next song (mp3 only) */
- OGG_PAGE_LIST* song_page; /* current page being written (ogg only) */
- u_long song_page_done; /* amount finished in current page (ogg) */
-
- HSEM cbuf_sem;
-
- LIST metadata_list;
- LIST ogg_page_list;
- LIST frame_list;
-} CBUF2;
-
-
-/*****************************************************************************
- * Global variables
- *****************************************************************************/
-extern CBUF2 g_cbuf2;
-
-
-/*****************************************************************************
- * Function prototypes
- *****************************************************************************/
-error_code
-cbuf2_init (CBUF2 *cbuf2, int content_type, int have_relay,
- unsigned long chunk_size, unsigned long num_chunks);
-void cbuf2_destroy(CBUF2 *buffer);
-error_code cbuf2_extract (CBUF2 *cbuf2, char *data,
- u_long count, u_long* curr_song);
-error_code cbuf2_peek(CBUF2 *buffer, char *items, u_long count);
-error_code cbuf2_insert_chunk (CBUF2 *cbuf2, const char *data, u_long count,
- int content_type, TRACK_INFO* ti);
-error_code cbuf2_fastforward (CBUF2 *buffer, u_long count);
-error_code cbuf2_peek_rgn (CBUF2 *buffer, char *out_buf,
- u_long start, u_long length);
-
-u_long cbuf2_get_free(CBUF2 *buffer);
-u_long cbuf2_get_free_tail (CBUF2 *cbuf2);
-u_long cbuf2_write_index (CBUF2 *cbuf2);
-
-void cbuf2_set_next_song (CBUF2 *cbuf2, u_long pos);
-
-error_code cbuf2_init_relay_entry (CBUF2 *cbuf2, RELAY_LIST* ptr,
- u_long burst_request);
-
-error_code
-cbuf2_ogg_peek_song (CBUF2 *cbuf2, char* out_buf,
- unsigned long buf_size,
- unsigned long* amt_filled,
- int* eos);
-
-#if defined (commentout)
-error_code cbuf2_extract_relay (CBUF2 *cbuf2, char *data, u_long *pos,
- u_long *len, int icy_metadata);
-#endif
-error_code cbuf2_extract_relay (CBUF2 *cbuf2, RELAY_LIST* ptr);
-error_code cbuf2_advance_ogg (CBUF2 *cbuf2, int requested_free_size);
-void cbuf2_debug_lists (CBUF2 *cbuf2);
-
-#endif
diff --git a/xbmc/lib/libshout/charmaps.h b/xbmc/lib/libshout/charmaps.h
deleted file mode 100644
index 690d8906f8..0000000000
--- a/xbmc/lib/libshout/charmaps.h
+++ /dev/null
@@ -1,57 +0,0 @@
-
-/*
- * If you need to generate more maps, use makemap.c on a system
- * with a decent iconv.
- */
-
-static const unsigned short mapping_iso_8859_2[256] = {
- 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
- 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
- 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
- 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
- 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
- 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
- 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
- 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
- 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
- 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
- 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
- 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
- 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
- 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
- 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
- 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
- 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
- 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
- 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7,
- 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b,
- 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7,
- 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c,
- 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
- 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
- 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
- 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
- 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
- 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
- 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
- 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9
-};
-
-static struct {
- const char *name;
- const unsigned short *map;
- struct charset *charset;
-} maps[] = {
- { "ISO-8859-2", mapping_iso_8859_2, 0 },
- { 0, 0, 0 }
-};
-
-static const struct {
- const char *bad;
- const char *good;
-} names[] = {
- { "ANSI_X3.4-1968", "us-ascii" },
- { 0, 0 }
-};
diff --git a/xbmc/lib/libshout/charset.c b/xbmc/lib/libshout/charset.c
deleted file mode 100644
index 29b214a0f3..0000000000
--- a/xbmc/lib/libshout/charset.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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
- */
-
-/*
- * See the corresponding header file for a description of the functions
- * that this file provides.
- *
- * This was first written for Ogg Vorbis but could be of general use.
- *
- * The only deliberate assumption about data sizes is that a short has
- * at least 16 bits, but this code has only been tested on systems with
- * 8-bit char, 16-bit short and 32-bit int.
- */
-
-#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */
-
-#include <stdlib.h>
-
-#include "charset.h"
-
-#include "charmaps.h"
-
-/*
- * This is like the standard strcasecmp, but it does not depend
- * on the locale. Locale-dependent functions can be dangerous:
- * we once had a bug involving strcasecmp("iso", "ISO") in a
- * Turkish locale!
- *
- * (I'm not really sure what the official standard says
- * about the sign of strcasecmp("Z", "["), but usually
- * we're only interested in whether it's zero.)
- */
-
-static int ascii_strcasecmp(const char *s1, const char *s2)
-{
- char c1, c2;
-
- for (;; s1++, s2++) {
- if (!*s1 || !*s1)
- break;
- if (*s1 == *s2)
- continue;
- c1 = *s1;
- if ('a' <= c1 && c1 <= 'z')
- c1 += 'A' - 'a';
- c2 = *s2;
- if ('a' <= c2 && c2 <= 'z')
- c2 += 'A' - 'a';
- if (c1 != c2)
- break;
- }
- return (unsigned char)*s1 - (unsigned char)*s2;
-}
-
-/*
- * UTF-8 equivalents of the C library's wctomb() and mbtowc().
- */
-
-int utf8_mbtowc(int *pwc, const char *s, size_t n)
-{
- unsigned char c;
- int wc, i, k;
-
- if (!n || !s)
- return 0;
-
- c = *s;
- if (c < 0x80) {
- if (pwc)
- *pwc = c;
- return c ? 1 : 0;
- }
- else if (c < 0xc2)
- return -1;
- else if (c < 0xe0) {
- if (n >= 2 && (s[1] & 0xc0) == 0x80) {
- if (pwc)
- *pwc = ((c & 0x1f) << 6) | (s[1] & 0x3f);
- return 2;
- }
- else
- return -1;
- }
- else if (c < 0xf0)
- k = 3;
- else if (c < 0xf8)
- k = 4;
- else if (c < 0xfc)
- k = 5;
- else if (c < 0xfe)
- k = 6;
- else
- return -1;
-
- if (n < k)
- return -1;
- wc = *s++ & ((1 << (7 - k)) - 1);
- for (i = 1; i < k; i++) {
- if ((*s & 0xc0) != 0x80)
- return -1;
- wc = (wc << 6) | (*s++ & 0x3f);
- }
- if (wc < (1 << (5 * k - 4)))
- return -1;
- if (pwc)
- *pwc = wc;
- return k;
-}
-
-int utf8_wctomb(char *s, int wc1)
-{
- unsigned int wc = wc1;
-
- if (!s)
- return 0;
- if (wc < (1 << 7)) {
- *s++ = wc;
- return 1;
- }
- else if (wc < (1 << 11)) {
- *s++ = 0xc0 | (wc >> 6);
- *s++ = 0x80 | (wc & 0x3f);
- return 2;
- }
- else if (wc < (1 << 16)) {
- *s++ = 0xe0 | (wc >> 12);
- *s++ = 0x80 | ((wc >> 6) & 0x3f);
- *s++ = 0x80 | (wc & 0x3f);
- return 3;
- }
- else if (wc < (1 << 21)) {
- *s++ = 0xf0 | (wc >> 18);
- *s++ = 0x80 | ((wc >> 12) & 0x3f);
- *s++ = 0x80 | ((wc >> 6) & 0x3f);
- *s++ = 0x80 | (wc & 0x3f);
- return 4;
- }
- else if (wc < (1 << 26)) {
- *s++ = 0xf8 | (wc >> 24);
- *s++ = 0x80 | ((wc >> 18) & 0x3f);
- *s++ = 0x80 | ((wc >> 12) & 0x3f);
- *s++ = 0x80 | ((wc >> 6) & 0x3f);
- *s++ = 0x80 | (wc & 0x3f);
- return 5;
- }
- else if (wc < (1 << 31)) {
- *s++ = 0xfc | (wc >> 30);
- *s++ = 0x80 | ((wc >> 24) & 0x3f);
- *s++ = 0x80 | ((wc >> 18) & 0x3f);
- *s++ = 0x80 | ((wc >> 12) & 0x3f);
- *s++ = 0x80 | ((wc >> 6) & 0x3f);
- *s++ = 0x80 | (wc & 0x3f);
- return 6;
- }
- else
- return -1;
-}
-
-/*
- * The charset "object" and methods.
- */
-
-struct charset {
- int max;
- int (*mbtowc)(void *table, int *pwc, const char *s, size_t n);
- int (*wctomb)(void *table, char *s, int wc);
- void *map;
-};
-
-int charset_mbtowc(struct charset *charset, int *pwc, const char *s, size_t n)
-{
- return (*charset->mbtowc)(charset->map, pwc, s, n);
-}
-
-int charset_wctomb(struct charset *charset, char *s, int wc)
-{
- return (*charset->wctomb)(charset->map, s, wc);
-}
-
-int charset_max(struct charset *charset)
-{
- return charset->max;
-}
-
-/*
- * Implementation of UTF-8.
- */
-
-static int mbtowc_utf8(void *map, int *pwc, const char *s, size_t n)
-{
- return utf8_mbtowc(pwc, s, n);
-}
-
-static int wctomb_utf8(void *map, char *s, int wc)
-{
- return utf8_wctomb(s, wc);
-}
-
-/*
- * Implementation of US-ASCII.
- * Probably on most architectures this compiles to less than 256 bytes
- * of code, so we can save space by not having a table for this one.
- */
-
-static int mbtowc_ascii(void *map, int *pwc, const char *s, size_t n)
-{
- int wc;
-
- if (!n || !s)
- return 0;
- wc = (unsigned char)*s;
- if (wc & ~0x7f)
- return -1;
- if (pwc)
- *pwc = wc;
- return wc ? 1 : 0;
-}
-
-static int wctomb_ascii(void *map, char *s, int wc)
-{
- if (!s)
- return 0;
- if (wc & ~0x7f)
- return -1;
- *s = wc;
- return 1;
-}
-
-/*
- * Implementation of ISO-8859-1.
- * Probably on most architectures this compiles to less than 256 bytes
- * of code, so we can save space by not having a table for this one.
- */
-
-static int mbtowc_iso1(void *map, int *pwc, const char *s, size_t n)
-{
- int wc;
-
- if (!n || !s)
- return 0;
- wc = (unsigned char)*s;
- if (wc & ~0xff)
- return -1;
- if (pwc)
- *pwc = wc;
- return wc ? 1 : 0;
-}
-
-static int wctomb_iso1(void *map, char *s, int wc)
-{
- if (!s)
- return 0;
- if (wc & ~0xff)
- return -1;
- *s = wc;
- return 1;
-}
-
-/*
- * Implementation of any 8-bit charset.
- */
-
-struct map {
- const unsigned short *from;
- struct inverse_map *to;
-};
-
-static int mbtowc_8bit(void *map1, int *pwc, const char *s, size_t n)
-{
- struct map *map = map1;
- unsigned short wc;
-
- if (!n || !s)
- return 0;
- wc = map->from[(unsigned char)*s];
- if (wc == 0xffff)
- return -1;
- if (pwc)
- *pwc = (int)wc;
- return wc ? 1 : 0;
-}
-
-/*
- * For the inverse map we use a hash table, which has the advantages
- * of small constant memory requirement and simple memory allocation,
- * but the disadvantage of slow conversion in the worst case.
- * If you need real-time performance while letting a potentially
- * malicious user define their own map, then the method used in
- * linux/drivers/char/consolemap.c would be more appropriate.
- */
-
-struct inverse_map {
- unsigned char first[256];
- unsigned char next[256];
-};
-
-/*
- * The simple hash is good enough for this application.
- * Use the alternative trivial hashes for testing.
- */
-#define HASH(i) ((i) & 0xff)
-/* #define HASH(i) 0 */
-/* #define HASH(i) 99 */
-
-static struct inverse_map *make_inverse_map(const unsigned short *from)
-{
- struct inverse_map *to;
- char used[256];
- int i, j, k;
-
- to = (struct inverse_map *)malloc(sizeof(struct inverse_map));
- if (!to)
- return 0;
- for (i = 0; i < 256; i++)
- to->first[i] = to->next[i] = used[i] = 0;
- for (i = 255; i >= 0; i--)
- if (from[i] != 0xffff) {
- k = HASH(from[i]);
- to->next[i] = to->first[k];
- to->first[k] = i;
- used[k] = 1;
- }
-
- /* Point the empty buckets at an empty list. */
- for (i = 0; i < 256; i++)
- if (!to->next[i])
- break;
- if (i < 256)
- for (j = 0; j < 256; j++)
- if (!used[j])
- to->first[j] = i;
-
- return to;
-}
-
-int wctomb_8bit(void *map1, char *s, int wc1)
-{
- struct map *map = map1;
- unsigned short wc = wc1;
- int i;
-
- if (!s)
- return 0;
-
- if (wc1 & ~0xffff)
- return -1;
-
- if (1) /* Change 1 to 0 to test the case where malloc fails. */
- if (!map->to)
- map->to = make_inverse_map(map->from);
-
- if (map->to) {
- /* Use the inverse map. */
- i = map->to->first[HASH(wc)];
- for (;;) {
- if (map->from[i] == wc) {
- *s = i;
- return 1;
- }
- if (!(i = map->to->next[i]))
- break;
- }
- }
- else {
- /* We don't have an inverse map, so do a linear search. */
- for (i = 0; i < 256; i++)
- if (map->from[i] == wc) {
- *s = i;
- return 1;
- }
- }
-
- return -1;
-}
-
-/*
- * The "constructor" charset_find().
- */
-
-struct charset charset_utf8 = {
- 6,
- &mbtowc_utf8,
- &wctomb_utf8,
- 0
-};
-
-struct charset charset_iso1 = {
- 1,
- &mbtowc_iso1,
- &wctomb_iso1,
- 0
-};
-
-struct charset charset_ascii = {
- 1,
- &mbtowc_ascii,
- &wctomb_ascii,
- 0
-};
-
-struct charset *charset_find(const char *code)
-{
- int i;
-
- /* Find good (MIME) name. */
- for (i = 0; names[i].bad; i++)
- if (!ascii_strcasecmp(code, names[i].bad)) {
- code = names[i].good;
- break;
- }
-
- /* Recognise some charsets for which we avoid using a table. */
- if (!ascii_strcasecmp(code, "UTF-8"))
- return &charset_utf8;
- if (!ascii_strcasecmp(code, "US-ASCII"))
- return &charset_ascii;
- if (!ascii_strcasecmp(code, "ISO-8859-1"))
- return &charset_iso1;
-
- /* Look for a mapping for a simple 8-bit encoding. */
- for (i = 0; maps[i].name; i++)
- if (!ascii_strcasecmp(code, maps[i].name)) {
- if (!maps[i].charset) {
- maps[i].charset = (struct charset *)malloc(sizeof(struct charset));
- if (maps[i].charset) {
- struct map *map = (struct map *)malloc(sizeof(struct map));
- if (!map) {
- free(maps[i].charset);
- maps[i].charset = 0;
- }
- else {
- maps[i].charset->max = 1;
- maps[i].charset->mbtowc = &mbtowc_8bit;
- maps[i].charset->wctomb = &wctomb_8bit;
- maps[i].charset->map = map;
- map->from = maps[i].map;
- map->to = 0; /* inverse mapping is created when required */
- }
- }
- }
- return maps[i].charset;
- }
-
- return 0;
-}
-
-/*
- * Function to convert a buffer from one encoding to another.
- * Invalid bytes are replaced by '#', and characters that are
- * not available in the target encoding are replaced by '?'.
- * Each of TO and TOLEN may be zero, if the result is not needed.
- * The output buffer is null-terminated, so it is all right to
- * use charset_convert(fromcode, tocode, s, strlen(s), &t, 0).
- */
-
-int charset_convert(const char *fromcode, const char *tocode,
- const char *from, size_t fromlen,
- char **to, size_t *tolen)
-{
- int ret = 0;
- struct charset *charset1, *charset2;
- char *tobuf, *p, *newbuf;
- int i, j, wc;
-
- charset1 = charset_find(fromcode);
- charset2 = charset_find(tocode);
- if (!charset1 || !charset2 )
- return -1;
-
- tobuf = (char *)malloc(fromlen * charset2->max + 1);
- if (!tobuf)
- return -2;
-
- for (p = tobuf; fromlen; from += i, fromlen -= i, p += j) {
- i = charset_mbtowc(charset1, &wc, from, fromlen);
- if (!i)
- i = 1;
- else if (i == -1) {
- i = 1;
- wc = '#';
- ret = 2;
- }
- j = charset_wctomb(charset2, p, wc);
- if (j == -1) {
- if (!ret)
- ret = 1;
- j = charset_wctomb(charset2, p, '?');
- if (j == -1)
- j = 0;
- }
- }
-
- if (tolen)
- *tolen = p - tobuf;
- *p++ = '\0';
- if (to) {
- newbuf = realloc(tobuf, p - tobuf);
- *to = newbuf ? newbuf : tobuf;
- }
- else
- free(tobuf);
-
- return ret;
-}
-
-#endif /* USE_CHARSET_ICONV */
diff --git a/xbmc/lib/libshout/charset.h b/xbmc/lib/libshout/charset.h
deleted file mode 100755
index b5e2fb7384..0000000000
--- a/xbmc/lib/libshout/charset.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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
- */
-
-#include <stdlib.h>
-
-/*
- * These functions are like the C library's mbtowc() and wctomb(),
- * but instead of depending on the locale they always work in UTF-8,
- * and they use int instead of wchar_t.
- */
-
-int utf8_mbtowc(int *pwc, const char *s, size_t n);
-int utf8_wctomb(char *s, int wc);
-
-/*
- * This is an object-oriented version of mbtowc() and wctomb().
- * The caller first uses charset_find() to get a pointer to struct
- * charset, then uses the mbtowc() and wctomb() methods on it.
- * The function charset_max() gives the maximum length of a
- * multibyte character in that encoding.
- * This API is only appropriate for stateless encodings like UTF-8
- * or ISO-8859-3, but I have no intention of implementing anything
- * other than UTF-8 and 8-bit encodings.
- *
- * MINOR BUG: If there is no memory charset_find() may return 0 and
- * there is no way to distinguish this case from an unknown encoding.
- */
-
-struct charset;
-
-struct charset *charset_find(const char *code);
-
-int charset_mbtowc(struct charset *charset, int *pwc, const char *s, size_t n);
-int charset_wctomb(struct charset *charset, char *s, int wc);
-int charset_max(struct charset *charset);
-
-/*
- * Function to convert a buffer from one encoding to another.
- * Invalid bytes are replaced by '#', and characters that are
- * not available in the target encoding are replaced by '?'.
- * Each of TO and TOLEN may be zero if the result is not wanted.
- * The input or output may contain null bytes, but the output
- * buffer is also null-terminated, so it is all right to
- * use charset_convert(fromcode, tocode, s, strlen(s), &t, 0).
- *
- * Return value:
- *
- * -2 : memory allocation failed
- * -1 : unknown encoding
- * 0 : data was converted exactly
- * 1 : valid data was converted approximately (using '?')
- * 2 : input was invalid (but still converted, using '#')
- */
-
-int charset_convert(const char *fromcode, const char *tocode,
- const char *from, size_t fromlen,
- char **to, size_t *tolen);
diff --git a/xbmc/lib/libshout/compat.h b/xbmc/lib/libshout/compat.h
deleted file mode 100644
index 9c98f76ef8..0000000000
--- a/xbmc/lib/libshout/compat.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* compat.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __COMPAT_H__
-#define __COMPAT_H__
-
-#if WIN32
-#include <direct.h>
-#include <windows.h>
-#include <process.h>
-#else
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <semaphore.h>
-#include <pthread.h>
-#endif
-
-//
-// This file handles all portablity issues with streamripper
-//
-
-// File Routines
-//////////////////////////////////////////
-
-#ifdef WIN32
-
-#define FHANDLE HANDLE
-#define OpenFile(_filename_) CreateFile(_filename_, GENERIC_READ, \
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, \
- FILE_ATTRIBUTE_NORMAL, NULL)
-// #define CloseFile(_fhandle_) CloseHandle(_fhandle_)
-#define TruncateFile(_filename_) \
- CloseFile(CreateFile(_filename_, GENERIC_WRITE, \
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, \
- TRUNCATE_EXISTING, \
- FILE_ATTRIBUTE_NORMAL, NULL))
-//#define MoveFile(_oldfile_, _newfile_) MoveFile(_oldfile_, _newfile_)
-#define INVALID_FHANDLE INVALID_HANDLE_VALUE
-#elif __UNIX__
-
-#define FHANDLE int
-// #define OpenFile(_filename_) open(_filename_, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
-// #define CloseFile(_fhandle_) close(_fhandle_)
-// #define TruncateFile(_filename_) CloseFile(open(_filename_, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))
-// #define MoveFile(_oldfile_, _newfile_) rename(_oldfile_, _newfile_)
-// #define DeleteFile(_file_) (!unlink(_file_))
-#define INVALID_FHANDLE -1
-
-#endif
-
-// Thread Routines
-#if WIN32
-#define THANDLE HANDLE
-#define BeginThread(_thandle_, callback, arg) \
- {_thandle_ = (THANDLE)_beginthread((void*) callback, 0, (void*) arg);}
-#define WaitForThread(_thandle_) WaitForSingleObject(_thandle_, INFINITE);
-#define DestroyThread(_thandle_) CloseHandle(_thandle_)
-
-#define HSEM HANDLE
-#define SemInit(_s_) {_s_ = CreateEvent(NULL, TRUE, FALSE, NULL);}
-#define SemWait(_s_) {WaitForSingleObject(_s_, INFINITE); ResetEvent(_s_);}
-#define SemPost(_s_) SetEvent(_s_)
-#define SemDestroy(_s_) CloseHandle(_s_)
-
-
-#elif __UNIX__
-
-#define THANDLE pthread_t
-#define BeginThread(_thandle_, callback, arg) \
- pthread_create(&_thandle_, NULL, \
- (void *)callback, (void *)arg)
-#define WaitForThread(_thandle_) pthread_join(_thandle_, NULL)
-#define DestroyThread(_thandle_) // is there one for unix?
-#define HSEM sem_t
-#define SemInit(_s_) sem_init(&(_s_), 0, 0)
-#define SemWait(_s_) sem_wait(&(_s_))
-#define SemPost(_s_) sem_post(&(_s_))
-#define SemDestroy(_s_) sem_destroy(&(_s_))
-#define Sleep(x) usleep(1000*x)
-
-#endif
-
-// Socket Routines
-//////////////////////////////////////////
-
-#if WIN32
-//#define EAGAIN WSAEWOULDBLOCK
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#elif __UNIX__
-#define closesocket close
-#define SOCKET_ERROR -1
-#define WSACleanup()
-#endif
-
-// Other stuff
-//////////////////////////////////////////
-
-#if WIN32
-#define snprintf _snprintf
-#endif
-
-#endif // __COMPAT_H__
diff --git a/xbmc/lib/libshout/config.h b/xbmc/lib/libshout/config.h
deleted file mode 100644
index 04fe9c548c..0000000000
--- a/xbmc/lib/libshout/config.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/* lib/config.h. Generated from config.h.in by configure. */
-/* lib/config.h.in. Generated from configure.ac by autoheader. */
-
-/* Whether the system has connect() */
-#define HAVE_CONNECT 1
-
-/* Define to 1 if you have curses.h */
-#define HAVE_CURSES_H 0
-
-/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
- */
-#define HAVE_DIRENT_H 1
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-/* #undef HAVE_DOPRNT */
-
-/* Define to 1 if you have faad2 libraries installed */
-#define HAVE_FAAD 0
-
-/* Define if you have the iconv() function. */
-#define HAVE_ICONV 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `iswcntrl' function. */
-#define HAVE_ISWCNTRL 1
-
-/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
-#define HAVE_LANGINFO_CODESET 1
-
-/* Define to 1 if you have the `inet' library (-linet). */
-/* #undef HAVE_LIBINET */
-
-/* Define to 1 if you have the `m' library (-lm). */
-#define HAVE_LIBM 1
-
-/* Define to 1 if you have the `nsl' library (-lnsl). */
-/* #undef HAVE_LIBNSL */
-
-/* Define to 1 if you have the `nsl_s' library (-lnsl_s). */
-/* #undef HAVE_LIBNSL_S */
-
-/* Define to 1 if you have the `rt' library (-lrt). */
-#define HAVE_LIBRT 1
-
-/* Define to 1 if you have the `sem' library (-lsem). */
-/* #undef HAVE_LIBSEM */
-
-/* Define to 1 if you have the `socket' library (-lsocket). */
-/* #undef HAVE_LIBSOCKET */
-
-/* Define to 1 if you have the `tre' library (-ltre). */
-#define HAVE_LIBTRE 1
-
-/* Define if you have locale_charset() in <localcharset.h>. */
-/* #undef HAVE_LOCALE_CHARSET */
-
-/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
-#define HAVE_MBRTOWC 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `mkdir' function. */
-#define HAVE_MKDIR 1
-
-/* Define to 1 if you have ncurses.h */
-/* #undef HAVE_NCURSES_H */
-
-/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
-/* #undef HAVE_NDIR_H */
-
-/* Define to 1 if you have both the ogg and vorbis libraries installed */
-#define HAVE_OGG_VORBIS 1
-
-/* Define to 1 if you have the `socket' function. */
-#define HAVE_SOCKET 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strerror' function. */
-#define HAVE_STRERROR 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strstr' function. */
-#define HAVE_STRSTR 1
-
-/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
- */
-/* #undef HAVE_SYS_DIR_H */
-
-/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
- */
-/* #undef HAVE_SYS_NDIR_H */
-
-/* Define to 1 if you have the <sys/sockio.h> header file. */
-/* #undef HAVE_SYS_SOCKIO_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if the system has the type `uint32_t'. */
-#define HAVE_UINT32_T 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if the system has the type `u_int32_t'. */
-#define HAVE_U_INT32_T 1
-
-/* Define to 1 if you have the `vprintf' function. */
-#define HAVE_VPRINTF 1
-
-/* Define to 1 if you have the `vswprintf' function. */
-#define HAVE_VSWPRINTF 1
-
-/* Define to 1 if you have the <wchar.h> header file. */
-/* #define HAVE_WCHAR_H 1 */
-
-/* Define to 1 if you have wide characters, iconv, and regwcomp */
-/* #define HAVE_WCHAR_SUPPORT 1 */
-
-/* Define to 1 if the system has the type `wchar_t'. */
-/* #define HAVE_WCHAR_T 1 */
-
-/* Define to 1 if you have the <wctype.h> header file. */
-/* #define HAVE_WCTYPE_H 1 */
-
-/* Define as const if the declaration of iconv() needs const. */
-/* #define ICONV_CONST */
-
-/* Various undefs of PACKAGE_* from XBMC's config.h */
-#undef PACKAGE
-#undef PACKAGE_BUGREPORT
-#undef PACKAGE_NAME
-#undef PACKAGE_STRING
-#undef PACKAGE_TARNAME
-#undef PACKAGE_VERSION
-
-/* Name of package */
-#define PACKAGE "streamripper"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "streamripper"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "streamripper 1.62.2"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "streamripper"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.62.2"
-
-/* Define as the return type of signal handlers (`int' or `void'). */
-#define RETSIGTYPE void
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Version number of package */
-#define VERSION "1.62.2"
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
diff --git a/xbmc/lib/libshout/config.h.in b/xbmc/lib/libshout/config.h.in
deleted file mode 100644
index 61e2b75f12..0000000000
--- a/xbmc/lib/libshout/config.h.in
+++ /dev/null
@@ -1,172 +0,0 @@
-/* lib/config.h.in. Generated from configure.ac by autoheader. */
-
-/* Whether the system has connect() */
-#undef HAVE_CONNECT
-
-/* Define to 1 if you have curses.h */
-#undef HAVE_CURSES_H
-
-/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
- */
-#undef HAVE_DIRENT_H
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-#undef HAVE_DOPRNT
-
-/* Define to 1 if you have faad2 libraries installed */
-#undef HAVE_FAAD
-
-/* Define if you have the iconv() function. */
-#undef HAVE_ICONV
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the `iswcntrl' function. */
-#undef HAVE_ISWCNTRL
-
-/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
-#undef HAVE_LANGINFO_CODESET
-
-/* Define to 1 if you have the `inet' library (-linet). */
-#undef HAVE_LIBINET
-
-/* Define to 1 if you have the `m' library (-lm). */
-#undef HAVE_LIBM
-
-/* Define to 1 if you have the `nsl' library (-lnsl). */
-#undef HAVE_LIBNSL
-
-/* Define to 1 if you have the `nsl_s' library (-lnsl_s). */
-#undef HAVE_LIBNSL_S
-
-/* Define to 1 if you have the `rt' library (-lrt). */
-#undef HAVE_LIBRT
-
-/* Define to 1 if you have the `sem' library (-lsem). */
-#undef HAVE_LIBSEM
-
-/* Define to 1 if you have the `socket' library (-lsocket). */
-#undef HAVE_LIBSOCKET
-
-/* Define to 1 if you have the `tre' library (-ltre). */
-#undef HAVE_LIBTRE
-
-/* Define if you have locale_charset() in <localcharset.h>. */
-#undef HAVE_LOCALE_CHARSET
-
-/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
-#undef HAVE_MBRTOWC
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have the `mkdir' function. */
-#undef HAVE_MKDIR
-
-/* Define to 1 if you have ncurses.h */
-#undef HAVE_NCURSES_H
-
-/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
-#undef HAVE_NDIR_H
-
-/* Define to 1 if you have both the ogg and vorbis libraries installed */
-#undef HAVE_OGG_VORBIS
-
-/* Define to 1 if you have the `socket' function. */
-#undef HAVE_SOCKET
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the `strerror' function. */
-#undef HAVE_STRERROR
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the `strstr' function. */
-#undef HAVE_STRSTR
-
-/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
- */
-#undef HAVE_SYS_DIR_H
-
-/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
- */
-#undef HAVE_SYS_NDIR_H
-
-/* Define to 1 if you have the <sys/sockio.h> header file. */
-#undef HAVE_SYS_SOCKIO_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if the system has the type `uint32_t'. */
-#undef HAVE_UINT32_T
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if the system has the type `u_int32_t'. */
-#undef HAVE_U_INT32_T
-
-/* Define to 1 if you have the `vprintf' function. */
-#undef HAVE_VPRINTF
-
-/* Define to 1 if you have the `vswprintf' function. */
-#undef HAVE_VSWPRINTF
-
-/* Define to 1 if you have the <wchar.h> header file. */
-#undef HAVE_WCHAR_H
-
-/* Define to 1 if you have wide characters, iconv, and regwcomp */
-#undef HAVE_WCHAR_SUPPORT
-
-/* Define to 1 if the system has the type `wchar_t'. */
-#undef HAVE_WCHAR_T
-
-/* Define to 1 if you have the <wctype.h> header file. */
-#undef HAVE_WCTYPE_H
-
-/* Define as const if the declaration of iconv() needs const. */
-#undef ICONV_CONST
-
-/* Name of package */
-#undef PACKAGE
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* Define as the return type of signal handlers (`int' or `void'). */
-#undef RETSIGTYPE
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Version number of package */
-#undef VERSION
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-#undef size_t
diff --git a/xbmc/lib/libshout/confw32.h b/xbmc/lib/libshout/confw32.h
deleted file mode 100644
index dcff6eb4d4..0000000000
--- a/xbmc/lib/libshout/confw32.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/* lib/config.h. Generated by configure. */
-/* lib/config.h.in. Generated from configure.ac by autoheader. */
-
-/* Whether the system has connect() */
-#undef HAVE_CONNECT
-
-/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
- */
-#undef HAVE_DIRENT_H
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-#undef HAVE_DOPRNT
-
-/* Define to 1 if you have faad2 libraries installed */
-#undef HAVE_FAAD
-
-/* Define if you have the iconv() function. */
-#define HAVE_ICONV 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the `iswcntrl' function. */
-#define HAVE_ISWCNTRL 1
-
-/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
-#undef HAVE_LANGINFO_CODESET
-
-/* Define to 1 if you have the `inet' library (-linet). */
-#undef HAVE_LIBINET
-
-/* Define to 1 if you have the `m' library (-lm). */
-#define HAVE_LIBM 1
-
-/* Define to 1 if you have the `nsl' library (-lnsl). */
-#undef HAVE_LIBNSL
-
-/* Define to 1 if you have the `nsl_s' library (-lnsl_s). */
-#undef HAVE_LIBNSL_S
-
-/* Define to 1 if you have the `rt' library (-lrt). */
-#undef HAVE_LIBRT
-
-/* Define to 1 if you have the `sem' library (-lsem). */
-#undef HAVE_LIBSEM
-
-/* Define to 1 if you have the `socket' library (-lsocket). */
-#undef HAVE_LIBSOCKET
-
-/* Define to 1 if you have the `tre' library (-ltre). */
-#define HAVE_LIBTRE 1
-
-/* Define if you have locale_charset() in <localcharset.h>. */
-#undef HAVE_LOCALE_CHARSET
-
-/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
-#define HAVE_MBRTOWC 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `mkdir' function. */
-#define HAVE_MKDIR 1
-
-/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
-#undef HAVE_NDIR_H
-
-/* Define to 1 if you have both the ogg and vorbis libraries installed */
-#define HAVE_OGG_VORBIS 1
-
-/* Define to 1 if you have the `socket' function. */
-#define HAVE_SOCKET 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strerror' function. */
-#define HAVE_STRERROR 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strstr' function. */
-#define HAVE_STRSTR 1
-
-/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
- */
-#undef HAVE_SYS_DIR_H
-
-/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
- */
-#undef HAVE_SYS_NDIR_H
-
-/* Define to 1 if you have the <sys/sockio.h> header file. */
-#undef HAVE_SYS_SOCKIO_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if the system has the type `uint32_t'. */
-#undef HAVE_UINT32_T
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if the system has the type `u_int32_t'. */
-#undef HAVE_U_INT32_T
-
-/* Define to 1 if you have the `vprintf' function. */
-#define HAVE_VPRINTF 1
-
-/* Define to 1 if you have the `vswprintf' function. */
-#undef HAVE_VSWPRINTF
-
-/* Define to 1 if you have the <wchar.h> header file. */
-#define HAVE_WCHAR_H 1
-
-/* Define to 1 if wide characters is supported */
-#undef HAVE_WCHAR_SUPPORT
-
-/* Define to 1 if the system has the type `wchar_t'. */
-#define HAVE_WCHAR_T 1
-
-/* Define to 1 if you have the <wctype.h> header file. */
-#define HAVE_WCTYPE_H 1
-
-/* Define as const if the declaration of iconv() needs const. */
-#define ICONV_CONST
-
-/* Name of package */
-#define PACKAGE "streamripper"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "streamripper"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "streamripper 1.61.0b"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "streamripper"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.61.0b"
-
-/* Define as the return type of signal handlers (`int' or `void'). */
-#define RETSIGTYPE void
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Version number of package */
-#define VERSION "1.61.0b"
-
-/* Define to `unsigned' if <sys/types.h> does not define. */
-/* #undef size_t */
diff --git a/xbmc/lib/libshout/debug.c b/xbmc/lib/libshout/debug.c
deleted file mode 100644
index bd99b498b8..0000000000
--- a/xbmc/lib/libshout/debug.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/* debug.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include "srtypes.h"
-#include "threadlib.h"
-#include "rip_manager.h"
-#include "mchar.h"
-#include "debug.h"
-
-#if WIN32
- #define vsnprintf _vsnprintf
- #define vswprintf _vsnwprintf
-#else
- /* This prototype is missing in some systems */
- int vswprintf (wchar_t * ws, size_t n, const wchar_t * format, va_list arg);
-#endif
-
-/*****************************************************************************
- * Public functions
- *****************************************************************************/
-#define DEBUG_BUF_LEN 2048
-int debug_on = 0;
-FILE* gcsfp = 0;
-static HSEM m_debug_lock;
-static char* debug_filename = 0;
-static char filename_buf[SR_MAX_PATH];
-static char* default_filename = "gcs.txt";
-static int debug_initialized = 0;
-
-void
-debug_set_filename (char* filename)
-{
- sr_strncpy (filename_buf, filename, SR_MAX_PATH);
- debug_filename = filename_buf;
-}
-
-void
-debug_enable (void)
-{
- debug_on = 1;
- if (!debug_filename) {
- debug_filename = default_filename;
- }
-}
-
-void
-debug_open (void)
-{
- if (!debug_on) return;
- if (!gcsfp) {
- gcsfp = fopen(debug_filename, "a");
- if (!gcsfp) {
- debug_on = 0;
- }
- }
-}
-
-void
-debug_close (void)
-{
- if (!debug_on) return;
- if (gcsfp) {
- fclose(gcsfp);
- gcsfp = 0;
- }
-}
-
-void
-#ifdef XBMC
-debug_printf2 (char* fmt, ...)
-#else
-debug_printf (char* fmt, ...)
-#endif
-{
- int was_open = 1;
- va_list argptr;
-
- if (!debug_on) {
- /* Uncomment to debug debug_mprintf() */
-#if defined (commentout)
- va_start (argptr, fmt);
- vprintf (fmt, argptr);
- va_end (argptr);
-#endif
- return;
- }
-
- if (!debug_initialized) {
- m_debug_lock = threadlib_create_sem();
- threadlib_signal_sem(&m_debug_lock);
- }
- threadlib_waitfor_sem (&m_debug_lock);
-
- va_start (argptr, fmt);
- if (!gcsfp) {
- was_open = 0;
- debug_open();
- if (!gcsfp) return;
- }
- if (!debug_initialized) {
- debug_initialized = 1;
- fprintf (gcsfp, "=========================\n");
- fprintf (gcsfp, "STREAMRIPPER " SRPLATFORM " " SRVERSION "\n");
- }
-
- vfprintf (gcsfp, fmt, argptr);
- fflush (gcsfp);
-
- va_end (argptr);
- if (!was_open) {
- debug_close ();
- }
- threadlib_signal_sem (&m_debug_lock);
-}
-
-void
-debug_mprintf (mchar* fmt, ...)
-{
- int was_open = 1;
- va_list argptr;
- int rc;
-#if defined HAVE_WCHAR_SUPPORT
- mchar mbuf[DEBUG_BUF_LEN];
-#endif
- char cbuf[DEBUG_BUF_LEN];
-
- if (!debug_on) return;
-
- if (!debug_initialized) {
- m_debug_lock = threadlib_create_sem();
- threadlib_signal_sem(&m_debug_lock);
- }
- threadlib_waitfor_sem (&m_debug_lock);
-
- va_start (argptr, fmt);
- if (!gcsfp) {
- was_open = 0;
- debug_open();
- if (!gcsfp) return;
- }
- if (!debug_initialized) {
- debug_initialized = 1;
- fprintf (gcsfp, "=========================\n");
- fprintf (gcsfp, "STREAMRIPPER " SRPLATFORM " " SRVERSION "\n");
- }
-
-#if defined HAVE_WCHAR_SUPPORT
- rc = vswprintf (mbuf, DEBUG_BUF_LEN, fmt, argptr);
- debug_on = 0; /* Avoid recursive call which hangs on semaphore */
- rc = string_from_mstring (cbuf, DEBUG_BUF_LEN, mbuf, CODESET_LOCALE);
- debug_on = 1;
-#else
- rc = vsnprintf (cbuf, DEBUG_BUF_LEN, fmt, argptr);
-#endif
-
- fwrite (cbuf, 1, rc, gcsfp);
-
- fflush (gcsfp);
-
- va_end (argptr);
- if (!was_open) {
- debug_close ();
- }
- threadlib_signal_sem (&m_debug_lock);
-}
-
-void
-debug_print_error (void)
-{
-#if defined (WIN32)
- LPVOID lpMsgBuf;
- FormatMessage (
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR) &lpMsgBuf,
- 0,
- NULL
- );
- debug_printf ("%s", lpMsgBuf);
- LocalFree (lpMsgBuf);
-#endif
-}
diff --git a/xbmc/lib/libshout/debug.h b/xbmc/lib/libshout/debug.h
deleted file mode 100644
index 2b6cbb18b4..0000000000
--- a/xbmc/lib/libshout/debug.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* debug.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __DEBUG_H__
-#define __DEBUG_H__
-
-#include "srtypes.h"
-#include "time.h"
-#include <stdio.h>
-
-void debug_open (void);
-void debug_set_filename (char* filename);
-void debug_close (void);
-#ifdef XBMC
-void debug_printf2 (char* fmt, ...);
-#define debug_printf debug_printf2
-#else
-void debug_printf2 (char* fmt, ...);
-#endif
-void debug_mprintf (mchar* fmt, ...);
-void debug_enable (void);
-void debug_print_error (void);
-
-#endif
diff --git a/xbmc/lib/libshout/external.c b/xbmc/lib/libshout/external.c
deleted file mode 100644
index eb9b9c787a..0000000000
--- a/xbmc/lib/libshout/external.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/* external.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#if defined (WIN32)
-#include <process.h>
-#include <io.h>
-#else
-#include <unistd.h>
-#include <sys/wait.h>
-#endif
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <string.h>
-#include "debug.h"
-#include "mchar.h"
-#include "external.h"
-#include "compat.h"
-
-/* Unix:
-http://www.cs.uleth.ca/~holzmann/C/system/pipeforkexec.html
-http://www.ecst.csuchico.edu/~beej/guide/ipc/fork.html
-*/
-/* Win32:
-Non-blocking pipe using PeekNamedPipe():
-http://list-archive.xemacs.org/xemacs-beta/199910/msg00263.html
-Using GenerateConsoleCtrlEvent():
-http://www.byte.com/art/9410/sec14/art3.htm
-*/
-
-/* ----------------------------- SHARED FUNCTIONS ------------------------ */
-External_Process*
-alloc_ep (void)
-{
- External_Process* ep;
- ep = (External_Process*) malloc (sizeof (External_Process));
- if (!ep) return 0;
- ep->line_buf[0] = 0;
- ep->line_buf_idx = 0;
- ep->album_buf[0] = 0;
- ep->artist_buf[0] = 0;
- ep->title_buf[0] = 0;
- return ep;
-}
-
-int
-parse_external_byte (External_Process* ep, TRACK_INFO* ti, char c)
-{
- int got_metadata = 0;
-
- if (c != '\r' && c != '\n') {
- if (ep->line_buf_idx < MAX_EXT_LINE_LEN-1) {
- ep->line_buf[ep->line_buf_idx++] = c;
- ep->line_buf[ep->line_buf_idx] = 0;
- }
- } else {
- if (!strcmp (".",ep->line_buf)) {
- /* Found end of record! */
- mchar w_raw_metadata[MAX_TRACK_LEN];
- mstring_from_string (ti->artist, MAX_TRACK_LEN, ep->artist_buf,
- CODESET_METADATA);
- mstring_from_string (ti->album, MAX_TRACK_LEN, ep->album_buf,
- CODESET_METADATA);
- mstring_from_string (ti->title, MAX_TRACK_LEN, ep->title_buf,
- CODESET_METADATA);
- /* GCS FIX - this is not quite right */
- msnprintf (w_raw_metadata, MAX_EXT_LINE_LEN, m_S m_(" - ") m_S,
- ti->artist, ti->title);
- string_from_mstring (ti->raw_metadata, MAX_EXT_LINE_LEN,
- w_raw_metadata, CODESET_METADATA);
- ti->have_track_info = 1;
- ti->save_track = TRUE;
-
- ep->artist_buf[0] = 0;
- ep->album_buf[0] = 0;
- ep->title_buf[0] = 0;
- got_metadata = 1;
- } else if (!strncmp("ARTIST=",ep->line_buf,strlen("ARTIST="))) {
- strcpy (ep->artist_buf, &ep->line_buf[strlen("ARTIST=")]);
- } else if (!strncmp("ALBUM=",ep->line_buf,strlen("ALBUM="))) {
- strcpy (ep->album_buf, &ep->line_buf[strlen("ALBUM=")]);
- } else if (!strncmp("TITLE=",ep->line_buf,strlen("TITLE="))) {
- strcpy (ep->title_buf, &ep->line_buf[strlen("TITLE=")]);
- }
- ep->line_buf[0] = 0;
- ep->line_buf_idx = 0;
- }
-
- return got_metadata;
-}
-
-
-/* ----------------------------- WIN32 FUNCTIONS ------------------------- */
-#if defined (WIN32)
-
-
-External_Process*
-spawn_external (char* cmd)
-{
- External_Process* ep;
- HANDLE hChildStdinRd;
- HANDLE hChildStdinWr;
- HANDLE hChildStdoutWr;
-
- SECURITY_ATTRIBUTES saAttr;
- PROCESS_INFORMATION piProcInfo;
- STARTUPINFO startup_info;
- BOOL rc;
- DWORD creation_flags;
-
- ep = alloc_ep ();
- if (!ep) return 0;
-
- /* Set the bInheritHandle flag so pipe handles are inherited. */
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
- saAttr.bInheritHandle = TRUE;
- saAttr.lpSecurityDescriptor = NULL;
-
- /* Create a pipe for the child process's STDOUT. */
- if (!CreatePipe (&ep->mypipe, &hChildStdoutWr, &saAttr, 0)) {
- debug_printf ("Stdout pipe creation failed\n");
- free (ep);
- return 0;
- }
-
- /* Ensure the read handle to the pipe for STDOUT is not inherited.*/
- SetHandleInformation (ep->mypipe, HANDLE_FLAG_INHERIT, 0);
-
- /* Create a pipe for the child process's STDIN. */
- if (!CreatePipe (&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) {
- debug_printf ("Stdin pipe creation failed\n");
- free (ep);
- return 0;
- }
-
- /* Ensure the write handle to the pipe for STDIN is not inherited. */
- SetHandleInformation (hChildStdinWr, HANDLE_FLAG_INHERIT, 0);
-
- /* create the child process */
- ZeroMemory (&piProcInfo, sizeof(PROCESS_INFORMATION));
- ZeroMemory (&startup_info, sizeof(STARTUPINFO));
- startup_info.cb = sizeof(STARTUPINFO);
- startup_info.hStdError = hChildStdoutWr;
- startup_info.hStdOutput = hChildStdoutWr;
- startup_info.hStdInput = hChildStdinRd;
- startup_info.dwFlags |= STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
- //startup_info.wShowWindow = SW_SHOW;
- startup_info.wShowWindow = SW_HIDE;
-
- creation_flags = 0;
- creation_flags |= CREATE_NEW_PROCESS_GROUP;
- //creation_flags |= CREATE_NEW_CONSOLE;
-
- rc = CreateProcess (
- NULL, // executable name
- cmd, // command line
- NULL, // process security attributes
- NULL, // primary thread security attributes
- TRUE, // handles are inherited
- creation_flags, // creation flags
- NULL, // use parent's environment
- NULL, // use parent's current directory
- &startup_info, // STARTUPINFO pointer
- &piProcInfo); // receives PROCESS_INFORMATION
- if (rc == 0) {
- debug_printf ("CreateProcess() failed\n");
- free (ep);
- return 0;
- }
- ep->hproc = piProcInfo.hProcess;
- ep->pid = piProcInfo.dwProcessId;
- //CloseHandle (piProcInfo.hProcess);
- CloseHandle (piProcInfo.hThread);
-
- Sleep (0);
- return ep;
-}
-
-int
-read_external (External_Process* ep, TRACK_INFO* ti)
-{
- char c;
- int rc;
- int got_metadata = 0;
- DWORD num_read;
-
- ti->have_track_info = 0;
-
- Sleep (0);
- while (1) {
- DWORD bytes_avail = 0;
- rc = PeekNamedPipe (ep->mypipe, NULL, 0, NULL, &bytes_avail, NULL);
- if (!rc) {
- DWORD error_code;
- /* Pipe closed? */
- /* GCS FIX: Restart external program if pipe closed */
- error_code = GetLastError ();
- debug_printf ("PeekNamedPipe failed, error_code = %d\n",
- error_code);
- return 0;
- }
- if (bytes_avail <= 0) {
- /* Pipe blocked */
- return got_metadata;
- }
- /* Pipe has data available, so read it */
- rc = ReadFile (ep->mypipe, &c, 1, &num_read, NULL);
- if (rc > 0 && num_read > 0) {
- int got_meta_byte;
- got_meta_byte = parse_external_byte (ep, ti, c);
- if (got_meta_byte) {
- got_metadata = 1;
- }
- }
- }
-}
-
-void
-close_external (External_Process** epp)
-{
- External_Process* ep = *epp;
- BOOL rc;
-
- rc = GenerateConsoleCtrlEvent (CTRL_C_EVENT, ep->pid);
- if (!rc) {
- /* The console control event will fail for the winamp
- plugin. Therefore, no choice but to kill
- the process using TerminateProcess()... */
- debug_print_error ();
- debug_printf ("rc = %d, gle = %d\n", rc, GetLastError());
- rc = TerminateProcess (ep->hproc, 0);
- debug_printf ("Terminated process: %d\n", rc);
- }
- CloseHandle (ep->hproc);
-
- free (ep);
- *epp = 0;
-}
-
-/* ----------------------------- UNIX FUNCTIONS -------------------------- */
-#else
-
-/* These functions are in either libiberty, or included in argv.c */
-char** buildargv (char *sp);
-
-External_Process*
-spawn_external (char* cmd)
-{
- External_Process* ep;
- int rc;
-
- ep = alloc_ep ();
- if (!ep) return 0;
-
- /* Create the pipes */
- rc = pipe (ep->mypipe);
- if (rc) {
- fprintf (stderr, "Can't open pipes\n");
- free (ep);
- return 0;
- }
- /* Create the child process. */
- ep->pid = fork ();
- if (ep->pid == (pid_t) 0) {
- /* This is the child process. */
- int i = 0;
- char** argv;
-
- close (ep->mypipe[0]);
- dup2 (ep->mypipe[1],1);
- close (ep->mypipe[1]);
-
- argv = buildargv (cmd);
- while (argv[i]) {
- debug_printf ("argv[%d] = %s\n", i, argv[i]);
- i++;
- }
-
- execvp (argv[0],&argv[0]);
- /* Doesn't return */
- fprintf (stderr, "Error, returned from execlp\n");
- exit (-1);
- } else if (ep->pid < (pid_t) 0) {
- /* The fork failed. */
- close (ep->mypipe[0]);
- close (ep->mypipe[1]);
- fprintf (stderr, "Fork failed.\n");
- free (ep);
- return 0;
- } else {
- /* This is the parent process. */
- close (ep->mypipe[1]);
- rc = fcntl (ep->mypipe[0], F_SETFL, O_NONBLOCK);
- return ep;
- }
-}
-
-int
-read_external (External_Process* ep, TRACK_INFO* ti)
-{
- char c;
- int rc;
- int got_metadata = 0;
-
- ti->have_track_info = 0;
-
- while (1) {
- rc = read (ep->mypipe[0],&c,1);
- if (rc > 0) {
- int got_meta_byte;
- got_meta_byte = parse_external_byte (ep, ti, c);
- if (got_meta_byte) {
- got_metadata = 1;
- }
- } else if (rc == 0) {
- /* Pipe closed */
- /* GCS FIX: Restart external program if pipe closed */
- return 0;
- } else {
- if (errno == EAGAIN) {
- /* Would block */
- return got_metadata;
- }
- /* GCS FIX: Figure out the error here. */
- return 0;
- }
- }
-}
-
-void
-close_external (External_Process** epp)
-{
- int rv;
- External_Process* ep = *epp;
-
- printf ("I should be exiting soon...\n");
- kill (ep->pid,SIGTERM);
- usleep (0);
- if (waitpid (ep->pid,&rv,WNOHANG) == 0) {
- printf ("Waiting for cleanup\n");
- usleep (2000);
- kill (ep->pid,SIGKILL);
- }
- wait(&rv);
- free (ep);
- *epp = 0;
-}
-#endif
diff --git a/xbmc/lib/libshout/external.h b/xbmc/lib/libshout/external.h
deleted file mode 100644
index d59fdaf014..0000000000
--- a/xbmc/lib/libshout/external.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* external.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __external_h__
-#define __external_h__
-
-#include "srtypes.h"
-
-#define MAX_EXT_LINE_LEN 255
-
-typedef struct external_process External_Process;
-struct external_process
-{
-#if defined (WIN32)
- HANDLE mypipe; /* read from child stdout */
- HANDLE hproc;
- DWORD pid;
-#else
- int mypipe[2]; /* 0 is for parent reading, 1 is for parent writing */
- pid_t pid;
-#endif
- int line_buf_idx;
- char line_buf[MAX_EXT_LINE_LEN];
- char album_buf[MAX_EXT_LINE_LEN];
- char artist_buf[MAX_EXT_LINE_LEN];
- char title_buf[MAX_EXT_LINE_LEN];
- char metadata_buf[MAX_EXT_LINE_LEN];
-};
-
-External_Process* spawn_external (char* cmd);
-int read_external (External_Process* ep, TRACK_INFO* ti);
-void close_external (External_Process** epp);
-
-#endif
diff --git a/xbmc/lib/libshout/filelib.c b/xbmc/lib/libshout/filelib.c
deleted file mode 100644
index 129aaa9812..0000000000
--- a/xbmc/lib/libshout/filelib.c
+++ /dev/null
@@ -1,1247 +0,0 @@
-/* filelib.c
- * library routines for file operations
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include "compat.h"
-#include "filelib.h"
-#include "mchar.h"
-#include "debug.h"
-#include <assert.h>
-#include <sys/types.h>
-#include "uce_dirent.h"
-
-#define TEMP_STR_LEN (SR_MAX_PATH*2)
-
-/*****************************************************************************
- * Public functions
- *****************************************************************************/
-error_code filelib_write_track(char *buf, u_long size);
-error_code filelib_write_show(char *buf, u_long size);
-void filelib_shutdown();
-error_code filelib_remove(char *filename);
-
-
-/*****************************************************************************
- * Private Functions
- *****************************************************************************/
-static error_code device_split (mchar* dirname, mchar* device, mchar* path);
-static error_code mkdir_if_needed (mchar *str);
-static error_code mkdir_recursive (mchar *str, int make_last);
-static void close_file (FHANDLE* fp);
-static void close_files ();
-static error_code filelib_write (FHANDLE fp, char *buf, u_long size);
-static BOOL file_exists (mchar *filename);
-static void trim_filename (mchar* out, mchar *filename);
-static void trim_mp3_suffix (mchar *filename);
-static error_code filelib_open_for_write (FHANDLE* fp, mchar *filename);
-static void
-parse_and_subst_dir (mchar* pattern_head, mchar* pattern_tail,
- mchar* opat_path, int is_for_showfile);
-static void
-parse_and_subst_pat (mchar* newfile,
- TRACK_INFO* ti,
- mchar* directory,
- mchar* pattern,
- mchar* extension);
-static void set_default_pattern (BOOL get_separate_dirs, BOOL do_count);
-static error_code
-set_output_directory (mchar* global_output_directory,
- mchar* global_output_pattern,
- mchar* output_pattern,
- mchar* output_directory,
- mchar* default_pattern,
- mchar* default_pattern_tail,
- int get_separate_dirs,
- int get_date_stamp,
- int is_for_showfile
- );
-static error_code sr_getcwd (mchar* dirbuf);
-static error_code add_trailing_slash (mchar *str);
-static int get_next_sequence_number (mchar* fn_base);
-static void fill_date_buf (mchar* datebuf, int datebuf_len);
-static error_code filelib_open_showfiles ();
-static void move_file (mchar* new_filename, mchar* old_filename);
-static mchar* replace_invalid_chars (mchar *str);
-
-/*****************************************************************************
- * Private Vars
- *****************************************************************************/
-#define DATEBUF_LEN 50
-static FHANDLE m_file;
-static FHANDLE m_show_file;
-static FHANDLE m_cue_file;
-static int m_count;
-static int m_do_show;
-static mchar m_default_pattern[SR_MAX_PATH];
-static mchar m_default_showfile_pattern[SR_MAX_PATH];
-static mchar m_output_directory[SR_MAX_PATH];
-static mchar m_output_pattern[SR_MAX_PATH];
-static mchar m_incomplete_directory[SR_MAX_PATH];
-static mchar m_incomplete_filename[SR_MAX_PATH];
-static mchar m_showfile_directory[SR_MAX_PATH];
-static mchar m_showfile_pattern[SR_MAX_PATH];
-static BOOL m_keep_incomplete = TRUE;
-static int m_max_filename_length;
-static mchar m_show_name[SR_MAX_PATH];
-static mchar m_cue_name[SR_MAX_PATH];
-static mchar m_icy_name[SR_MAX_PATH];
-static mchar* m_extension;
-static BOOL m_do_individual_tracks;
-static mchar m_session_datebuf[DATEBUF_LEN];
-static mchar m_stripped_icy_name[SR_MAX_PATH];
-
-// For now we're not going to care. If it makes it good. it not, will know
-// When we try to create a file in the path.
-static error_code
-mkdir_if_needed (mchar *str)
-{
- char s[SR_MAX_PATH];
- string_from_mstring (s, SR_MAX_PATH, str, CODESET_FILESYS);
-#if WIN32
- mkdir (s);
-#else
- mkdir (s, 0777);
-#endif
- return SR_SUCCESS;
-}
-
-/* Recursively make directories. If make_last == 1, then the final
- substring (after the last '/') is considered a directory rather
- than a file name */
-#ifndef XBMC
-static error_code
-mkdir_recursive (mchar *str, int make_last)
-{
- mchar buf[SR_MAX_PATH];
- mchar* p = buf;
- mchar q;
-
- buf[0] = 0;
- while ((q = *p++ = *str++) != 0) {
- if (ISSLASH(q)) {
- *p = 0;
- mkdir_if_needed (buf);
- }
- }
- if (make_last) {
- mkdir_if_needed (str);
- }
- return SR_SUCCESS;
-}
-#endif
-
-error_code
-filelib_init (BOOL do_individual_tracks,
- BOOL do_count,
- int count_start,
- BOOL keep_incomplete,
- BOOL do_show_file,
- int content_type,
- char* output_directory, /* Locale encoded - from command line */
- char* output_pattern, /* Locale encoded - from command line */
- char* showfile_pattern, /* Locale encoded - from command line */
- int get_separate_dirs,
- int get_date_stamp,
- char* icy_name)
-{
-#ifndef XBMC
- mchar tmp_output_directory[SR_MAX_PATH];
- mchar tmp_output_pattern[SR_MAX_PATH];
- mchar tmp_showfile_pattern[SR_MAX_PATH];
-
- m_file = INVALID_FHANDLE;
- m_show_file = INVALID_FHANDLE;
- m_cue_file = INVALID_FHANDLE;
- m_count = do_count ? count_start : -1;
- m_keep_incomplete = keep_incomplete;
- memset(&m_output_directory, 0, SR_MAX_PATH);
- m_show_name[0] = 0;
- m_do_show = do_show_file;
- m_do_individual_tracks = do_individual_tracks;
-
- debug_printf ("FILELIB_INIT: output_directory=%s\n",
- output_directory ? output_directory : "");
- debug_printf ("FILELIB_INIT: output_pattern=%s\n",
- output_pattern ? output_pattern : "");
- debug_printf ("FILELIB_INIT: showfile_pattern=%s\n",
- showfile_pattern ? showfile_pattern : "");
-
- mstring_from_string (tmp_output_directory, SR_MAX_PATH, output_directory,
- CODESET_LOCALE);
- mstring_from_string (tmp_output_pattern, SR_MAX_PATH, output_pattern,
- CODESET_LOCALE);
- mstring_from_string (tmp_showfile_pattern, SR_MAX_PATH, showfile_pattern,
- CODESET_LOCALE);
- mstring_from_string (m_icy_name, SR_MAX_PATH, icy_name,
- CODESET_METADATA);
- debug_printf ("Converted output directory: len=%d\n",
- mstrlen (tmp_output_directory));
- mstrcpy (m_stripped_icy_name, m_icy_name);
-
- replace_invalid_chars (m_stripped_icy_name);
-
- switch (content_type) {
- case CONTENT_TYPE_MP3:
- m_extension = m_(".mp3");
- break;
- case CONTENT_TYPE_NSV:
- case CONTENT_TYPE_ULTRAVOX:
- m_extension = m_(".nsv");
- break;
- case CONTENT_TYPE_OGG:
- m_extension = m_(".ogg");
- break;
- case CONTENT_TYPE_AAC:
- m_extension = m_(".aac");
- break;
- default:
- fprintf (stderr, "Error (wrong suggested content type: %d)\n",
- content_type);
- return SR_ERROR_PROGRAM_ERROR;
- }
-
- /* Initialize session date */
- fill_date_buf (m_session_datebuf, DATEBUF_LEN);
-
- /* Set up the proper pattern if we're using -q and -s flags */
- set_default_pattern (get_separate_dirs, do_count);
-
- /* Get the path to the "parent" directory. This is the directory
- that contains the incomplete dir and the show files.
- It might not contain the complete files if an output_pattern
- was specified. */
- set_output_directory (m_output_directory,
- m_output_pattern,
- tmp_output_pattern,
- tmp_output_directory,
- m_default_pattern,
- m_("%A - %T"),
- get_separate_dirs,
- get_date_stamp,
- 0);
-
- msnprintf (m_incomplete_directory, SR_MAX_PATH, m_S m_S m_C,
- m_output_directory, m_("incomplete"), PATH_SLASH);
-
- /* Recursively make the output directory & incomplete directory */
- if (m_do_individual_tracks) {
- debug_mprintf (m_("Trying to make output_directory: ") m_S m_("\n"),
- m_output_directory);
- mkdir_recursive (m_output_directory, 1);
-
- /* Next, make the incomplete directory */
- if (m_do_individual_tracks) {
- debug_mprintf (m_("Trying to make incomplete_directory: ")
- m_S m_("\n"), m_incomplete_directory);
- mkdir_if_needed (m_incomplete_directory);
- }
- }
-
- /* Compute the amount of remaining path length for the filenames */
- m_max_filename_length = SR_MAX_PATH - mstrlen(m_incomplete_directory);
-
- /* Get directory and pattern of showfile */
- if (do_show_file) {
- if (*tmp_showfile_pattern) {
- trim_mp3_suffix (tmp_showfile_pattern);
- if (mstrlen(m_show_name) > SR_MAX_PATH - 5) {
- return SR_ERROR_DIR_PATH_TOO_LONG;
- }
- }
- set_output_directory (m_showfile_directory,
- m_showfile_pattern,
- tmp_showfile_pattern,
- tmp_output_directory,
- m_default_showfile_pattern,
- m_(""),
- get_separate_dirs,
- get_date_stamp,
- 1);
- mkdir_recursive (m_showfile_directory, 1);
- filelib_open_showfiles ();
- }
-#endif
-
- return SR_SUCCESS;
-}
-
-/* This sets the value for m_default_pattern and m_default_showfile_pattern,
- using the -q & -s flags. This function cannot overflow
- these static buffers. */
-#ifndef XBMC
-static void
-set_default_pattern (BOOL get_separate_dirs, BOOL do_count)
-{
- /* m_default_pattern */
- m_default_pattern[0] = 0;
- if (get_separate_dirs) {
- mstrcpy (m_default_pattern, m_("%S") PATH_SLASH_STR);
- }
- if (do_count) {
- if (m_count < 0) {
- mstrncat (m_default_pattern, m_("%q_"), SR_MAX_PATH);
- } else {
- msnprintf (&m_default_pattern[mstrlen(m_default_pattern)],
- SR_MAX_PATH - mstrlen(m_default_pattern),
- m_("%%%dq_"), m_count);
- }
- }
- mstrncat (m_default_pattern, m_("%A - %T"), SR_MAX_PATH);
-
- /* m_default_showfile_pattern */
- m_default_showfile_pattern[0] = 0;
- if (get_separate_dirs) {
- mstrcpy (m_default_showfile_pattern, m_("%S") PATH_SLASH_STR);
- }
- mstrncat (m_default_showfile_pattern, m_("sr_program_%d"), SR_MAX_PATH);
-}
-
-/* This function sets the value of m_output_directory or
- m_showfile_directory. */
-static error_code
-set_output_directory (mchar* global_output_directory,
- mchar* global_output_pattern,
- mchar* output_pattern,
- mchar* output_directory,
- mchar* default_pattern,
- mchar* default_pattern_tail,
- int get_separate_dirs,
- int get_date_stamp,
- int is_for_showfile
- )
-{
- error_code ret;
- mchar opat_device[3];
- mchar odir_device[3];
- mchar cwd_device[3];
- mchar* device;
- mchar opat_path[SR_MAX_PATH];
- mchar odir_path[SR_MAX_PATH];
- mchar cwd_path[SR_MAX_PATH];
- mchar cwd[SR_MAX_PATH];
-
- mchar pattern_head[SR_MAX_PATH];
- mchar pattern_tail[SR_MAX_PATH];
-
- /* Initialize strings */
- cwd[0] = 0;
- odir_device[0] = 0;
- opat_device[0] = 0;
- odir_path[0] = 0;
- opat_path[0] = 0;
- ret = sr_getcwd (cwd);
- if (ret != SR_SUCCESS) return ret;
-
- if (!output_pattern || !(*output_pattern)) {
- output_pattern = default_pattern;
- }
-
- /* Get the device. It can be empty. */
- if (output_directory && *output_directory) {
- device_split (output_directory, odir_device, odir_path);
- debug_printf ("devicesplit: %d -> %d %d\n",
- mstrlen (output_directory),
- mstrlen (odir_device),
- mstrlen (odir_path));
- }
- device_split (output_pattern, opat_device, opat_path);
- device_split (cwd, cwd_device, cwd_path);
- if (*opat_device) {
- device = opat_device;
- } else if (*odir_device) {
- device = odir_device;
- } else {
- /* No device */
- device = m_("");
- }
-
- /* Generate the output file pattern. */
- if (IS_ABSOLUTE_PATH(opat_path)) {
- cwd_path[0] = 0;
- odir_path[0] = 0;
- debug_printf ("Got opat_path absolute path\n");
- } else if (IS_ABSOLUTE_PATH(odir_path)) {
- cwd_path[0] = 0;
- debug_printf ("Got odir_path absolute path\n");
- }
- if (*odir_path) {
- ret = add_trailing_slash(odir_path);
- if (ret != SR_SUCCESS) return ret;
- }
- if (*cwd_path) {
- ret = add_trailing_slash(cwd_path);
- if (ret != SR_SUCCESS) return ret;
- }
- if (mstrlen(device) + mstrlen(cwd_path) + mstrlen(opat_path)
- + mstrlen(odir_path) > SR_MAX_PATH-1) {
- return SR_ERROR_DIR_PATH_TOO_LONG;
- }
-
- /* Fill in %S and %d patterns */
- msnprintf (pattern_head, SR_MAX_PATH, m_S m_S m_S, device,
- cwd_path, odir_path);
- debug_printf ("Composed pattern head (%d) <- (%d,%d,%d)\n",
- mstrlen(pattern_head), mstrlen(device),
- mstrlen(cwd_path), mstrlen(odir_path));
- parse_and_subst_dir (pattern_head, pattern_tail, opat_path,
- is_for_showfile);
-
- /* In case there is no %A, no %T, etc., use the default pattern */
- if (!*pattern_tail) {
- mstrcpy (pattern_tail, default_pattern_tail);
- }
-
- /* Set the global variables */
- mstrcpy (global_output_directory, pattern_head);
- add_trailing_slash (global_output_directory);
- mstrcpy (global_output_pattern, pattern_tail);
-
- return SR_SUCCESS;
-}
-#endif
-
-/* Parse & substitute the output pattern. What we're trying to
- get is everything up to the pattern specifiers that change
- from track to track: %A, %T, %a, %D, %q, or %Q.
- If %S or %d appear before this, substitute in.
- If it's for the showfile, then we don't advance pattern_head
- If there is no %A, no %T, etc.
-*/
-static void
-parse_and_subst_dir (mchar* pattern_head, mchar* pattern_tail,
- mchar* opat_path, int is_for_showfile)
-{
- int opi = 0;
- unsigned int phi = 0;
- int ph_base_len;
- int op_tail_idx;
-
- phi = mstrlen(pattern_head);
- opi = 0;
- ph_base_len = phi;
- op_tail_idx = opi;
-
- while (phi < SR_MAX_BASE) {
- if (ISSLASH(opat_path[opi])) {
- pattern_head[phi++] = PATH_SLASH;
- opi++;
- ph_base_len = phi;
- op_tail_idx = opi;
- continue;
- }
- if (opat_path[opi] == 0) {
- /* This means there are no artist/title info in the filename.
- In this case, we fall back on the default pattern. */
- if (!is_for_showfile) {
- ph_base_len = phi;
- op_tail_idx = opi;
- }
- break;
- }
- if (opat_path[opi] != m_('%')) {
- pattern_head[phi++] = opat_path[opi++];
- continue;
- }
- /* If we got here, we have a '%' */
- switch (opat_path[opi+1]) {
- case m_('%'):
- pattern_head[phi++]=m_('%');
- opi+=2;
- continue;
- case m_('S'):
- /* append stream name */
- mstrncpy (&pattern_head[phi], m_stripped_icy_name,
- SR_MAX_BASE-phi);
- phi = mstrlen (pattern_head);
- opi+=2;
- continue;
- case m_('d'):
- /* append date info */
- mstrncpy (&pattern_head[phi], m_session_datebuf, SR_MAX_BASE-phi);
- phi = mstrlen (pattern_head);
- opi+=2;
- continue;
- case m_('0'): case m_('1'): case m_('2'): case m_('3'): case m_('4'):
- case m_('5'): case m_('6'): case m_('7'): case m_('8'): case m_('9'):
- case m_('a'):
- case m_('A'):
- case m_('D'):
- case m_('q'):
- case m_('T'):
- /* These are track specific patterns */
- break;
- case 0:
- /* This means there are no artist/title info in the filename.
- In this case, we fall back on the default pattern. */
- pattern_head[phi++] = opat_path[opi++];
- if (!is_for_showfile) {
- ph_base_len = phi;
- op_tail_idx = opi;
- }
- break;
- default:
- /* This is an illegal pattern, so copy the '%' and continue */
- pattern_head[phi++] = opat_path[opi++];
- continue;
- }
- /* If we got to here, it means that we hit something like %A or %T */
- break;
- }
- /* Terminate the pattern_head string */
- pattern_head[ph_base_len] = 0;
-
- mstrcpy (pattern_tail, &opat_path[op_tail_idx]);
-}
-
-static void
-fill_date_buf (mchar* datebuf, int datebuf_len)
-{
- char tmp[DATEBUF_LEN];
- time_t now = time(NULL);
- strftime (tmp, datebuf_len, "%Y_%m_%d_%H_%M_%S", localtime(&now));
- mstring_from_string (datebuf, DATEBUF_LEN, tmp, CODESET_FILESYS);
-}
-
-static error_code
-add_trailing_slash (mchar *str)
-{
- int len = mstrlen(str);
- if (len >= SR_MAX_PATH-1)
- return SR_ERROR_DIR_PATH_TOO_LONG;
- if (!ISSLASH(str[mstrlen(str)-1]))
- mstrncat (str, PATH_SLASH_STR, SR_MAX_PATH);
- return SR_SUCCESS;
-}
-
-/* Split off the device */
-static error_code
-device_split (mchar* dirname,
- mchar* device,
- mchar* path
- )
-{
- int di;
-
- if (HAS_DEVICE(dirname)) {
- device[0] = dirname[0];
- device[1] = dirname[1];
- device[2] = 0;
- di = 2;
- } else {
- device[0] = 0;
- di = 0;
- }
- mstrcpy (path, &dirname[di]);
- return SR_SUCCESS;
-}
-
-static error_code
-sr_getcwd (mchar* dirbuf)
-{
- char db[SR_MAX_PATH];
-#if defined (WIN32)
- if (!_getcwd (db, SR_MAX_PATH)) {
- debug_printf ("getcwd returned zero?\n");
- return SR_ERROR_DIR_PATH_TOO_LONG;
- }
-#else
- if (!getcwd (db, SR_MAX_PATH)) {
- debug_printf ("getcwd returned zero?\n");
- return SR_ERROR_DIR_PATH_TOO_LONG;
- }
-#endif
- mstring_from_string (dirbuf, SR_MAX_PATH, db, CODESET_FILESYS);
- return SR_SUCCESS;
-}
-
-void close_file (FHANDLE* fp)
-{
- if (*fp != INVALID_FHANDLE) {
-#if defined WIN32
- CloseHandle (*fp);
-#else
- close (*fp);
-#endif
- *fp = INVALID_FHANDLE;
- }
-}
-
-#ifndef XBMC
-void close_files()
-{
- close_file (&m_file);
- close_file (&m_show_file);
- close_file (&m_cue_file);
-}
-
-BOOL
-file_exists (mchar *filename)
-{
- FHANDLE f;
- char fn[SR_MAX_PATH];
- string_from_mstring (fn, SR_MAX_PATH, filename, CODESET_FILESYS);
-#if defined (WIN32)
- f = CreateFile (fn, GENERIC_READ,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
-#else
- f = open (fn, O_RDONLY);
-#endif
- if (f == INVALID_FHANDLE) {
- return FALSE;
- }
- close_file (&f);
- return TRUE;
-}
-#endif
-
-error_code
-filelib_write_cue (TRACK_INFO* ti, int secs)
-{
-#ifndef XBMC
- static int track_no = 1;
- int rc;
- char buf1[MAX_TRACK_LEN];
- char buf2[MAX_TRACK_LEN];
-
- if (!m_do_show) return SR_SUCCESS;
- if (!m_cue_file) return SR_SUCCESS;
-
- rc = snprintf (buf2, MAX_TRACK_LEN, " TRACK %02d AUDIO\n", track_no++);
- filelib_write (m_cue_file, buf2, rc);
- string_from_mstring (buf1, MAX_TRACK_LEN, ti->title, CODESET_ID3);
- rc = snprintf (buf2, MAX_TRACK_LEN, " TITLE \"%s\"\n", buf1);
- filelib_write (m_cue_file, buf2, rc);
- string_from_mstring (buf1, MAX_TRACK_LEN, ti->artist, CODESET_ID3);
- rc = snprintf (buf2, MAX_TRACK_LEN, " PERFORMER \"%s\"\n", buf1);
- filelib_write (m_cue_file, buf2, rc);
- rc = snprintf (buf2, MAX_TRACK_LEN, " INDEX 01 %02d:%02d:00\n",
- secs / 60, secs % 60);
- filelib_write (m_cue_file, buf2, rc);
-#endif
- return SR_SUCCESS;
-}
-
-/* It's a bit touch and go here. My artist substitution might
- be into a directory, in which case I don't have enough
- room for a legit file name */
-/* Also, what about versioning of completed filenames? */
-/* If (TRACK_INFO* ti) is NULL, that means we're being called for the
- showfile, and therefore some parts don't apply */
-static void
-parse_and_subst_pat (mchar* newfile,
- TRACK_INFO* ti,
- mchar* directory,
- mchar* pattern,
- mchar* extension)
-{
- mchar stripped_artist[SR_MAX_PATH];
- mchar stripped_title[SR_MAX_PATH];
- mchar stripped_album[SR_MAX_PATH];
-#define DATEBUF_LEN 50
- mchar temp[DATEBUF_LEN];
- mchar datebuf[DATEBUF_LEN];
- int opi = 0;
- int nfi = 0;
- int done;
- mchar* pat = pattern;
-
- /* Reserve 5 bytes: 4 for the .mp3 extension, and 1 for null char */
- int MAX_FILEBASELEN = SR_MAX_PATH-5;
-
- mstrcpy (newfile, directory);
- opi = 0;
- nfi = mstrlen(newfile);
- done = 0;
-
- /* Strip artist, title, album */
- debug_printf ("parse_and_subst_pat: stripping\n");
- if (ti) {
- mstrncpy (stripped_artist, ti->artist, SR_MAX_PATH);
- mstrncpy (stripped_title, ti->title, SR_MAX_PATH);
- mstrncpy (stripped_album, ti->album, SR_MAX_PATH);
- replace_invalid_chars (stripped_artist);
- replace_invalid_chars (stripped_title);
- replace_invalid_chars (stripped_album);
- }
-
- debug_printf ("parse_and_subst_pat: substitute pattern\n");
- while (nfi < MAX_FILEBASELEN) {
- if (pat[opi] == 0) {
- done = 1;
- break;
- }
- if (pat[opi] != m_('%')) {
- newfile[nfi++] = pat[opi++];
- newfile[nfi] = 0;
- continue;
- }
- /* If we got here, we have a '%' */
- switch (pat[opi+1]) {
- case m_('%'):
- newfile[nfi++] = m_('%');
- newfile[nfi] = 0;
- opi+=2;
- continue;
- case m_('S'):
- /* stream name */
- /* GCS FIX: Not sure here */
- mstrncat (newfile, m_icy_name, MAX_FILEBASELEN-nfi);
- nfi = mstrlen (newfile);
- opi+=2;
- continue;
- case m_('d'):
- /* append date info */
- mstrncat (newfile, m_session_datebuf, MAX_FILEBASELEN-nfi);
- nfi = mstrlen (newfile);
- opi+=2;
- continue;
- case m_('D'):
- /* current timestamp */
- fill_date_buf (datebuf, DATEBUF_LEN);
- mstrncat (newfile, datebuf, MAX_FILEBASELEN-nfi);
- nfi = mstrlen (newfile);
- opi+=2;
- continue;
- case m_('a'):
- /* album */
- if (!ti) goto illegal_pattern;
- mstrncat (newfile, stripped_album, MAX_FILEBASELEN-nfi);
- nfi = mstrlen (newfile);
- opi+=2;
- continue;
- case m_('A'):
- /* artist */
- if (!ti) goto illegal_pattern;
- mstrncat (newfile, stripped_artist, MAX_FILEBASELEN-nfi);
- nfi = mstrlen (newfile);
- opi+=2;
- continue;
- case m_('q'):
- /* automatic sequence number */
- msnprintf (temp, DATEBUF_LEN, m_("%04d"),
- get_next_sequence_number (newfile));
- mstrncat (newfile, temp, MAX_FILEBASELEN-nfi);
- nfi = mstrlen (newfile);
- opi+=2;
- continue;
- case m_('T'):
- /* title */
- if (!ti) goto illegal_pattern;
- mstrncat (newfile, stripped_title, MAX_FILEBASELEN-nfi);
- nfi = mstrlen (newfile);
- opi+=2;
- continue;
- case 0:
- /* The pattern ends in '%', but that's ok. */
- newfile[nfi++] = pat[opi++];
- newfile[nfi] = 0;
- done = 1;
- break;
- case m_('0'): case m_('1'): case m_('2'): case m_('3'): case m_('4'):
- case m_('5'): case m_('6'): case m_('7'): case m_('8'): case m_('9'):
- {
- /* Get integer */
- int ai = 0;
- mchar ascii_buf[7]; /* max 6 chars */
- while (isdigit (pat[opi+1+ai]) && ai < 6) {
- ascii_buf[ai] = pat[opi+1+ai];
- ai ++;
- }
- ascii_buf[ai] = 0;
- /* If we got a q, get starting number */
- if (pat[opi+1+ai] == m_('q')) {
- if (m_count == -1) {
- m_count = mtol(ascii_buf);
- }
- msnprintf (temp, DATEBUF_LEN, m_("%04d"), m_count);
- mstrncat (newfile, temp, MAX_FILEBASELEN-nfi);
- nfi = mstrlen (newfile);
- opi+=ai+2;
- continue;
- }
- /* Otherwise, no 'q', so drop through to default case */
- }
- default:
- illegal_pattern:
- /* Illegal pattern, but that's ok. */
- newfile[nfi++] = pat[opi++];
- newfile[nfi] = 0;
- continue;
- }
- }
-
- /* Pop on the extension */
- /* GCS FIX - is SR_MAX_PATH right here? */
- debug_printf ("parse_and_subst_pat: pop on the extension\n");
- mstrncat (newfile, extension, SR_MAX_PATH);
-}
-
-error_code
-filelib_start (TRACK_INFO* ti)
-{
-#ifndef XBMC
- mchar newfile[TEMP_STR_LEN];
- mchar fnbase[TEMP_STR_LEN];
- mchar fnbase1[TEMP_STR_LEN];
- mchar fnbase2[TEMP_STR_LEN];
-
- if (!m_do_individual_tracks) return SR_SUCCESS;
-
- close_file(&m_file);
-
- /* Compose and trim filename (not including directory) */
- msnprintf (fnbase1, TEMP_STR_LEN, m_S m_(" - ") m_S,
- ti->artist, ti->title);
- trim_filename (fnbase, fnbase1);
- msnprintf (newfile, TEMP_STR_LEN, m_S m_S m_S,
- m_incomplete_directory, fnbase, m_extension);
- if (m_keep_incomplete) {
- int n = 1;
- mchar oldfile[TEMP_STR_LEN];
- msnprintf (oldfile, TEMP_STR_LEN, m_S m_S m_S,
- m_incomplete_directory, fnbase, m_extension);
- mstrcpy (fnbase1, fnbase);
- while (file_exists (oldfile)) {
- msnprintf (fnbase1, TEMP_STR_LEN, m_("(%d)") m_S,
- n, fnbase);
- trim_filename (fnbase2, fnbase1);
- msnprintf (oldfile, TEMP_STR_LEN, m_S m_S m_S,
- m_incomplete_directory,
- fnbase2, m_extension);
- n++;
- }
- if (mstrcmp (newfile, oldfile) != 0) {
- move_file (oldfile, newfile);
- }
- }
- mstrcpy (m_incomplete_filename, newfile);
- return filelib_open_for_write(&m_file, newfile);
-#else
- return SR_SUCCESS;
-#endif
-}
-
-static long
-get_file_size (mchar *filename)
-{
- FILE* fp;
- long len;
- char fn[SR_MAX_PATH];
-
- string_from_mstring (fn, SR_MAX_PATH, filename, CODESET_FILESYS);
- fp = fopen (fn, "r");
- if (!fp) return 0;
-
- if (fseek (fp, 0, SEEK_END)) {
- fclose(fp);
- return 0;
- }
-
- len = ftell (fp);
- if (len < 0) {
- fclose(fp);
- return 0;
- }
-
- fclose (fp);
- return len;
-}
-
-/*
- * Added by Daniel Lord 29.06.2005 to only overwrite files with better
- * captures, modified by GCS to get file size from file system
- */
-static BOOL
-new_file_is_better (mchar *oldfile, mchar *newfile)
-{
- long oldfilesize=0;
- long newfilesize=0;
-
- oldfilesize = get_file_size (oldfile);
- newfilesize = get_file_size (newfile);
-
- /*
- * simple size check for now. Newfile should have at least 1Meg. Else it's
- * not very usefull most of the time.
- */
- /* GCS: This isn't quite true for low bitrate streams. */
-#if defined (commentout)
- if (newfilesize <= 524288) {
- debug_printf("NFB: newfile smaller as 524288\n");
- return FALSE;
- }
-#endif
-
- if (oldfilesize == -1) {
- /* make sure we get the file in case of errors */
- debug_printf("NFB: could not get old filesize\n");
- return TRUE;
- }
-
- if (oldfilesize == newfilesize) {
- debug_printf("NFB: Size Match\n");
- return FALSE;
- }
-
- if (newfilesize < oldfilesize) {
- debug_printf("NFB:newfile bigger as oldfile\n");
- return FALSE;
- }
-
- debug_printf ("NFB:oldfilesize = %li, newfilesize = %li, "
- "overwriting file\n", oldfilesize, newfilesize);
- return TRUE;
-}
-
-void
-truncate_file (mchar* filename)
-{
- char fn[SR_MAX_PATH];
- string_from_mstring (fn, SR_MAX_PATH, filename, CODESET_FILESYS);
- debug_printf ("Trying to truncate file: %s\n", fn);
-#if defined WIN32
- CloseHandle (CreateFile(fn, GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
- TRUNCATE_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL));
-#else
- close (open (fn, O_RDWR | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
-#endif
-}
-
-void
-move_file (mchar* new_filename, mchar* old_filename)
-{
- char old_fn[SR_MAX_PATH];
- char new_fn[SR_MAX_PATH];
- string_from_mstring (old_fn, SR_MAX_PATH, old_filename, CODESET_FILESYS);
- string_from_mstring (new_fn, SR_MAX_PATH, new_filename, CODESET_FILESYS);
-#if defined WIN32
- MoveFile(old_fn, new_fn);
-#else
- rename (old_fn, new_fn);
-#endif
-}
-
-void
-delete_file (mchar* filename)
-{
- char fn[SR_MAX_PATH];
- string_from_mstring (fn, SR_MAX_PATH, filename, CODESET_FILESYS);
-#if defined WIN32
- DeleteFile (fn);
-#else
- unlink (fn);
-#endif
-}
-
-// Moves the file from incomplete to complete directory
-// fullpath is an output parameter
-error_code
-filelib_end (TRACK_INFO* ti,
- enum OverwriteOpt overwrite,
- BOOL truncate_dup,
- mchar *fullpath)
-{
-#ifndef XBMC
- BOOL ok_to_write = TRUE;
- mchar newfile[TEMP_STR_LEN];
-
- if (!m_do_individual_tracks) return SR_SUCCESS;
-
- close_file (&m_file);
-
- /* Construct filename for completed file */
- parse_and_subst_pat (newfile, ti, m_output_directory,
- m_output_pattern, m_extension);
-
- /* Build up the output directory */
- mkdir_recursive (newfile, 0);
-
- // If we are over writing existing tracks
- switch (overwrite) {
- case OVERWRITE_ALWAYS:
- ok_to_write = TRUE;
- break;
- case OVERWRITE_NEVER:
- if (file_exists (newfile)) {
- ok_to_write = FALSE;
- } else {
- ok_to_write = TRUE;
- }
- break;
- case OVERWRITE_LARGER:
- default:
- /* Smart overwriting -- only overwrite if new file is bigger */
- ok_to_write = new_file_is_better (newfile, m_incomplete_filename);
- break;
- }
-
- if (ok_to_write) {
- if (file_exists (newfile)) {
- delete_file (newfile);
- }
- move_file (newfile, m_incomplete_filename);
- } else {
- if (truncate_dup && file_exists (m_incomplete_filename)) {
- // TruncateFile(m_incomplete_filename);
- truncate_file (m_incomplete_filename);
- }
- }
-
- if (fullpath) {
- mstrcpy (fullpath, newfile);
- }
- if (m_count != -1)
- m_count++;
-#endif
- return SR_SUCCESS;
-}
-
-static error_code
-filelib_open_for_write (FHANDLE* fp, mchar* filename)
-{
- char fn[SR_MAX_PATH];
- string_from_mstring (fn, SR_MAX_PATH, filename, CODESET_FILESYS);
- debug_printf ("Trying to create file: %s\n", fn);
-#if WIN32
- *fp = CreateFile (fn, GENERIC_WRITE, // open for reading
- FILE_SHARE_READ, // share for reading
- NULL, // no security
- CREATE_ALWAYS, // existing file only
- FILE_ATTRIBUTE_NORMAL, // normal file
- NULL); // no attr. template
- if (*fp == INVALID_FHANDLE) {
- int r = GetLastError();
- r = strlen(fn);
- printf ("ERROR creating file: %s\n",filename);
- return SR_ERROR_CANT_CREATE_FILE;
- }
-#else
- /* For unix, we need to convert to char, and just open.
- http://mail.nl.linux.org/linux-utf8/2001-02/msg00103.html
- */
- *fp = open (fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- if (*fp == INVALID_FHANDLE) {
- /* GCS FIX -- need error message here! */
- // printf ("ERROR creating file: %s\n",filename);
- return SR_ERROR_CANT_CREATE_FILE;
- }
-#endif
- return SR_SUCCESS;
-}
-
-error_code
-filelib_write (FHANDLE fp, char *buf, u_long size)
-{
- if (!fp) {
- debug_printf("filelib_write: fp = 0\n");
- return SR_ERROR_CANT_WRITE_TO_FILE;
- }
-#if WIN32
- {
- DWORD bytes_written = 0;
- if (!WriteFile(fp, buf, size, &bytes_written, NULL))
- return SR_ERROR_CANT_WRITE_TO_FILE;
- }
-#else
- if (write(fp, buf, size) == -1)
- return SR_ERROR_CANT_WRITE_TO_FILE;
-#endif
-
- return SR_SUCCESS;
-}
-
-error_code
-filelib_write_track(char *buf, u_long size)
-{
-#ifndef XBMC
- return filelib_write (m_file, buf, size);
-#else
- return SR_SUCCESS;
-#endif
-}
-
-static error_code
-filelib_open_showfiles ()
-{
- int rc;
- mchar mcue_buf[1024];
- char cue_buf[1024];
-
- parse_and_subst_pat (m_show_name, 0, m_showfile_directory,
- m_showfile_pattern, m_extension);
- parse_and_subst_pat (m_cue_name, 0, m_showfile_directory,
- m_showfile_pattern,
- m_(".cue"));
-
- rc = filelib_open_for_write (&m_cue_file, m_cue_name);
- if (rc != SR_SUCCESS) {
- m_do_show = 0;
- return rc;
- }
-
- /* Write cue header here */
- /* GCS FIX: What encoding should the FILE line be? */
- rc = msnprintf (mcue_buf, 1024, m_("FILE \"") m_S m_("\" MP3\n"),
- m_show_name);
- rc = string_from_mstring (cue_buf, 1024, mcue_buf, CODESET_FILESYS);
- rc = filelib_write (m_cue_file, cue_buf, rc);
- if (rc != SR_SUCCESS) {
- m_do_show = 0;
- return rc;
- }
- rc = filelib_open_for_write (&m_show_file, m_show_name);
- if (rc != SR_SUCCESS) {
- m_do_show = 0;
- return rc;
- }
- return rc;
-}
-
-#ifndef XBMC
-error_code
-filelib_write_show(char *buf, u_long size)
-{
- error_code rc;
- if (!m_do_show) {
- return SR_SUCCESS;
- }
- rc = filelib_write (m_show_file, buf, size);
- if (rc != SR_SUCCESS) {
- m_do_show = 0;
- }
- return rc;
-}
-#endif
-
-void
-filelib_shutdown()
-{
-#ifndef XBMC
- close_files();
-#endif
-}
-
-/* GCS: This should get only the name, not the directory */
-#ifndef XBMC
-static void
-trim_filename (mchar* out, mchar *filename)
-{
- long maxlen = m_max_filename_length;
- mstrncpy (out, filename, MAX_TRACK_LEN);
- replace_invalid_chars (out);
- out[maxlen-4] = 0; // -4 = make room for ".mp3"
-}
-
-static void
-trim_mp3_suffix (mchar *filename)
-{
- mchar* suffix_ptr;
- if (mstrlen(filename) <= 4) return;
- suffix_ptr = filename + mstrlen(filename) - 4; // -4 for ".mp3"
- if (mstrcmp (suffix_ptr, m_extension) == 0) {
- *suffix_ptr = 0;
- }
-}
-#endif
-
-/* GCS FIX: This may not work with filesystem charsets where 0-9 are
- not ascii compatible? */
-static int
-get_next_sequence_number (mchar* fn_base)
-{
- int rc;
- int di = 0;
- int edi = 0;
- int seq;
- mchar dir_name[SR_MAX_PATH];
- mchar fn_prefix[SR_MAX_PATH];
- char dname[SR_MAX_PATH];
- char fnp[SR_MAX_PATH];
- DIR* dp;
- struct dirent* de;
-
- /* Get directory from fn_base */
- while (fn_base[di]) {
- if (ISSLASH(fn_base[di])) {
- edi = di;
- }
- di++;
- }
- mstrncpy (dir_name, fn_base, SR_MAX_PATH);
- dir_name[edi] = 0;
-
- /* Get fn prefix from fn_base */
- fn_prefix[0] = 0;
- mstrcpy (fn_prefix, &fn_base[edi+1]);
-
- rc = string_from_mstring (dname, SR_MAX_PATH, dir_name, CODESET_FILESYS);
- rc = string_from_mstring (fnp, SR_MAX_PATH, fn_prefix, CODESET_FILESYS);
-
- /* Look through directory for a filenames that match prefix */
- if ((dp = opendir (dname)) == 0) {
- return 0;
- }
- seq = 0;
- while ((de = readdir (dp)) != 0) {
- if (strncmp(de->d_name, fnp, strlen(fnp)) == 0) {
- if (isdigit(de->d_name[strlen(fnp)])) {
- int this_seq = atoi(&de->d_name[strlen(fnp)]);
- if (seq <= this_seq) {
- seq = this_seq + 1;
- }
- }
- }
- }
- closedir (dp);
- return seq;
-}
-
-/* GCS FIX: This should only strip "." at beginning of path */
-mchar*
-replace_invalid_chars (mchar *str)
-{
-# if defined (WIN32)
- mchar invalid_chars[] = m_("\\/:*?\"<>|~");
-# else
- mchar invalid_chars[] = m_("\\/:*?\"<>|.~");
-# endif
- mchar replacement = m_('-');
-
- mchar *oldstr = str;
- mchar *newstr = str;
-
- if (!str) return NULL;
-
- for (;*oldstr; oldstr++) {
- if (mstrchr(invalid_chars, *oldstr) == NULL) {
- *newstr++ = *oldstr;
- } else {
- *newstr++ = replacement;
- }
- }
- *newstr = '\0';
-
- return str;
-}
diff --git a/xbmc/lib/libshout/filelib.h b/xbmc/lib/libshout/filelib.h
deleted file mode 100644
index 273ef40aa7..0000000000
--- a/xbmc/lib/libshout/filelib.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* filelib.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __FILELIB_H__
-#define __FILELIB_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#include "srtypes.h"
-#if WIN32
-#include <windows.h>
-#endif
-
-#if WIN32
-#define PATH_SLASH m_('\\')
-#define PATH_SLASH_STR m_("\\")
-#else
-#define PATH_SLASH m_('/')
-#define PATH_SLASH_STR m_("/")
-#endif
-
-
-/* Pathname support.
- Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
- Licence: GNU LGPL */
-/* ISSLASH(C) tests whether C is a directory separator character.
- IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not,
- it may be concatenated to a directory pathname. */
-#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
- /* Win32, OS/2, DOS */
-# define ISSLASH(C) ((C) == m_('/') || (C) == m_('\\'))
-# define HAS_DEVICE(P) \
- ((((P)[0] >= m_('A') && (P)[0] <= m_('Z')) \
- || ((P)[0] >= m_('a') && (P)[0] <= m_('z'))) \
- && (P)[1] == m_(':'))
-/* GCS: This is not correct, because it could be c:foo which is relative */
-/* # define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) */
-# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
-#else
- /* Unix */
-# define ISSLASH(C) ((C) == m_('/'))
-# define HAS_DEVICE(P) (0)
-# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
-#endif
-
-#define SR_MIN_FILENAME 54 /* For files in incomplete */
-#define SR_MIN_COMPLETEDIR 10 /* For dir with radio station name */
-#define SR_DATE_LEN 11
-#define SR_MIN_COMPLETE_W_DATE (SR_MIN_COMPLETEDIR+SR_DATE_LEN)
-/* Directory lengths, including trailing slash */
-#define SR_MAX_INCOMPLETE (SR_MAX_PATH-SR_MIN_FILENAME)
-#define SR_MAX_COMPLETE (SR_MAX_INCOMPLETE-strlen("incomplete/"))
-#define SR_MAX_BASE (SR_MAX_COMPLETE-SR_MIN_COMPLETEDIR-strlen("/"))
-#define SR_MAX_BASE_W_DATE (SR_MAX_BASE-SR_MIN_COMPLETE_W_DATE)
-
-
-error_code
-filelib_init (BOOL do_individual_tracks,
- BOOL do_count,
- int count_start,
- BOOL keep_incomplete,
- BOOL do_show_file,
- int content_type,
- char* output_directory,
- char* output_pattern,
- char* showfile_pattern,
- int get_separate_dirs,
- int get_date_stamp,
- char* icy_name);
-error_code filelib_start (TRACK_INFO* ti);
-error_code filelib_end (TRACK_INFO* ti, enum OverwriteOpt overwrite,
- BOOL truncate_dup, mchar *fullpath);
-error_code filelib_write_track(char *buf, u_long size);
-error_code filelib_write_show(char *buf, u_long size);
-void filelib_shutdown();
-error_code filelib_remove(char *filename);
-error_code filelib_write_cue(TRACK_INFO* ti, int secs);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif //FILELIB
diff --git a/xbmc/lib/libshout/findsep.c b/xbmc/lib/libshout/findsep.c
deleted file mode 100644
index 15a3d55675..0000000000
--- a/xbmc/lib/libshout/findsep.c
+++ /dev/null
@@ -1,531 +0,0 @@
-/* findsep.c
- * library routines for find silent points in mp3 data
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Portions are adapted from minimad.c, included with the
- * libmad library, distributed under the GNU General Public License.
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <stdlib.h>
-#include <math.h>
-#include <assert.h>
-#if defined(_LINUX) && !defined(__APPLE__)
-#include <mad.h>
-#else
-#include "mad.h"
-#endif
-#include "findsep.h"
-#include "srtypes.h"
-#include "debug.h"
-#include "list.h"
-
-#define MIN_RMS_SILENCE 100
-#define MAX_RMS_SILENCE 32767 //max short
-#define NUM_SILTRACKERS 30
-#define READSIZE 2000
-// #define READSIZE 1000
-
-/* Uncomment to dump an mp3 of the search window. */
-// #define MAKE_DUMP_MP3 1
-
-typedef struct FRAME_LIST_struct FRAME_LIST;
-struct FRAME_LIST_struct
-{
- const unsigned char* m_framepos;
- long m_samples;
- long m_pcmpos;
- LIST m_list;
-};
-
-typedef struct SILENCETRACKERst
-{
- long insilencecount;
- double silencevol;
- unsigned long silstart_samp;
- BOOL foundsil;
-} SILENCETRACKER;
-
-typedef struct DECODE_STRUCTst
-{
- unsigned char* mpgbuf;
- long mpgsize;
- long mpgpos;
- long len_to_sw_ms;
- long searchwindow_ms;
- long silence_ms;
- long silence_samples;
- unsigned long len_to_sw_start_samp;
- unsigned long len_to_sw_end_samp;
- unsigned long pcmpos;
- long samplerate;
- SILENCETRACKER siltrackers[NUM_SILTRACKERS];
- LIST frame_list;
-} DECODE_STRUCT;
-
-typedef struct GET_BITRATE_STRUCTst
-{
- unsigned long bitrate;
- unsigned char* mpgbuf;
- long mpgsize;
-} GET_BITRATE_STRUCT;
-
-/*****************************************************************************
- * Public functions
- *****************************************************************************/
-
-/*****************************************************************************
- * Private functions
- *****************************************************************************/
-static void init_siltrackers(SILENCETRACKER* siltrackers);
-static void apply_padding (DECODE_STRUCT* ds, unsigned long silstart,
- long padding1, long padding2,
- u_long* pos1, u_long* pos2);
-static void free_frame_list (DECODE_STRUCT* ds);
-static enum mad_flow input(void *data, struct mad_stream *ms);
-static void search_for_silence(DECODE_STRUCT *ds, double vol);
-static signed int scale(mad_fixed_t sample);
-static enum mad_flow output(void *data, struct mad_header const *header,
- struct mad_pcm *pcm);
-static enum mad_flow filter (void *data, struct mad_stream const *ms,
- struct mad_frame *frame);
-static enum mad_flow error(void *data, struct mad_stream *ms,
- struct mad_frame *frame);
-static enum mad_flow header(void *data, struct mad_header const *pheader);
-static enum mad_flow input_get_bitrate (void *data, struct mad_stream *stream);
-static enum mad_flow header_get_bitrate (void *data,
- struct mad_header const *pheader);
-
-/*****************************************************************************
- * Private Vars
- *****************************************************************************/
-
-/*****************************************************************************
- * Functions
- *****************************************************************************/
-error_code
-findsep_silence (const u_char* mpgbuf,
- long mpgsize,
- long len_to_sw,
- long searchwindow,
- long silence_length,
- long padding1,
- long padding2,
- u_long* pos1,
- u_long* pos2
- )
-{
- DECODE_STRUCT ds;
- struct mad_decoder decoder;
- int result;
- unsigned long silstart;
- int i;
-
- ds.mpgbuf = (unsigned char*)mpgbuf;
- ds.mpgsize = mpgsize;
- ds.pcmpos = 0;
- ds.mpgpos= 0;
- ds.samplerate = 0;
- ds.len_to_sw_ms = len_to_sw;
- ds.searchwindow_ms = searchwindow;
- ds.silence_ms = silence_length;
- INIT_LIST_HEAD (&ds.frame_list);
-
- debug_printf ("FINDSEP: %p -> %p (%d)\n", mpgbuf, mpgbuf+mpgsize, mpgsize);
-
- init_siltrackers(ds.siltrackers);
-
-#if defined (MAKE_DUMP_MP3)
- {
- FILE* fp = fopen("dump.mp3", "wb");
- fwrite(mpgbuf, mpgsize, 1, fp);
- fclose(fp);
- }
-#endif
-
- /* Run decoder */
- mad_decoder_init(&decoder, &ds,
- input /* input */,
- header/* header */,
- filter /* filter */,
- output /* output */,
- error /* error */,
- NULL /* message */);
- result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
- mad_decoder_finish(&decoder);
-
- debug_printf ("total length: %d\n", ds.pcmpos);
- debug_printf ("silence_length: %d ms\n", ds.silence_ms);
- debug_printf ("silence_samples: %d\n", ds.silence_samples);
-
- /* Search through siltrackers to find minimum volume point */
- assert(ds.mpgsize != 0);
- silstart = ds.pcmpos/2;
- for(i = 0; i < NUM_SILTRACKERS; i++) {
- debug_printf("SILT: %2d/%8g, pcm=%4d, found=%d, insil=%d\n",
- i,
- ds.siltrackers[i].silencevol,
- ds.siltrackers[i].silstart_samp,
- ds.siltrackers[i].foundsil,
- ds.siltrackers[i].insilencecount
- );
- if (ds.siltrackers[i].foundsil) {
- debug_printf("found!\n");
- silstart = ds.siltrackers[i].silstart_samp;
- break;
- }
- }
-
- if (i == NUM_SILTRACKERS) {
- debug_printf("warning: no silence found between tracks\n");
- }
-
- /* Now that we have the start of the silence, let's add the padding */
- apply_padding (&ds, silstart, padding1, padding2, pos1, pos2);
-
- /* Free the list of frame info */
- free_frame_list (&ds);
-
- return SR_SUCCESS;
-}
-
-void init_siltrackers(SILENCETRACKER* siltrackers)
-{
- int i;
- long stepsize = (MAX_RMS_SILENCE - MIN_RMS_SILENCE) / (NUM_SILTRACKERS-1);
- long rms = MIN_RMS_SILENCE;
- for (i = 0; i < NUM_SILTRACKERS; i++, rms += stepsize) {
- siltrackers[i].foundsil = 0;
- siltrackers[i].silstart_samp = 0;
- siltrackers[i].insilencecount = 0;
- siltrackers[i].silencevol = rms;
- }
-}
-
-static void
-apply_padding (DECODE_STRUCT* ds,
- unsigned long silstart,
- long padding1,
- long padding2,
- u_long* pos1,
- u_long* pos2
- )
-{
- /* Compute positions in samples */
- FRAME_LIST *pos;
- long pos1s, pos2s;
-
- pos1s = silstart
- + (ds->silence_samples/2)
- + padding1 * (ds->samplerate/1000);
- pos2s = silstart
- + (ds->silence_samples/2)
- - padding2 * (ds->samplerate/1000);
-
- debug_printf ("Applying padding: p1,p2 = (%d,%d), pos1s,pos2s = (%d,%d)\n", padding1, padding2, pos1s, pos2s);
-
- /* GCS FIX: Need to check for pos == null */
- /* GCS FIX: Watch out for -1, might have mem error! */
- pos = list_entry (ds->frame_list.next, FRAME_LIST, m_list);
- if (pos1s < pos->m_pcmpos) {
- *pos1 = pos->m_framepos - ds->mpgbuf - 1;
- }
- if (pos2s < pos->m_pcmpos) {
- *pos2 = pos->m_framepos - ds->mpgbuf;
- }
- list_for_each_entry (pos, FRAME_LIST, &(ds->frame_list), m_list) {
- if (pos1s >= pos->m_pcmpos) {
- *pos1 = pos->m_framepos - ds->mpgbuf - 1;
- }
- if (pos2s >= pos->m_pcmpos) {
- *pos2 = pos->m_framepos - ds->mpgbuf;
- }
- }
- debug_printf ("pos1, pos2 = %d,%d (%d) (%02x%02x)\n",
- *pos1, *pos2,
- *pos1 - *pos2,
- ds->mpgbuf[*pos2],
- ds->mpgbuf[*pos2+1]);
-}
-
-static void
-free_frame_list (DECODE_STRUCT* ds)
-{
- FRAME_LIST *pos, *n;
- /* GCS: This seems to be the best way to go through a list.
- Note no compiler warnings. */
- list_for_each_entry_safe (pos, FRAME_LIST, n, &(ds->frame_list), m_list) {
- list_del (&(pos->m_list));
- free (pos);
- }
-}
-
-enum mad_flow
-input(void *data, struct mad_stream *ms)
-{
- DECODE_STRUCT *ds = (DECODE_STRUCT *)data;
- long frameoffset = 0;
- long espnextpos = ds->mpgpos+READSIZE;
-
- /* GCS FIX: This trims the last READSIZE from consideration */
- if (espnextpos > ds->mpgsize) {
- return MAD_FLOW_STOP;
- }
-
- if (ms->next_frame) {
- frameoffset = &(ds->mpgbuf[ds->mpgpos]) - ms->next_frame;
- /* GCS July 8, 2004
- This is the famous frameoffset != READSIZE bug.
- What appears to be happening is libmad is not syncing
- properly on the broken initial frame. Therefore,
- if there is no header yet (hence no ds->samplerate),
- we'll nudge along the buffer to try to resync.
- */
- if (frameoffset == READSIZE) {
- if (!ds->samplerate) {
- frameoffset--;
- } else {
- FILE* fp;
- debug_printf ("%p | %p | %p | %p | %d\n",
- ds->mpgbuf, ds->mpgpos, &(ds->mpgbuf[ds->mpgpos]),
- ms->next_frame, frameoffset);
- fprintf (stderr, "ERROR: frameoffset != READSIZE\n");
- debug_printf ("ERROR: frameoffset != READSIZE\n");
- fp = fopen ("gcs1.txt","w");
- fwrite(ds->mpgbuf,1,ds->mpgsize,fp);
- fclose(fp);
- exit (-1);
- }
- }
- }
- debug_printf ("%p | %p | %p |< %p | %p >| %d\n",
- ds->mpgbuf,
- ds->mpgpos,
- &(ds->mpgbuf[ds->mpgpos]),
- ms->this_frame,
- ms->next_frame,
- frameoffset);
-
- mad_stream_buffer (ms, (const unsigned char*)
- (ds->mpgbuf+ds->mpgpos)-frameoffset,
- READSIZE);
- ds->mpgpos += READSIZE - frameoffset;
-
- return MAD_FLOW_CONTINUE;
-}
-
-void
-search_for_silence (DECODE_STRUCT *ds, double vol)
-{
- int i;
- for(i = 0; i < NUM_SILTRACKERS; i++) {
- SILENCETRACKER *pstracker = &ds->siltrackers[i];
-
- if (pstracker->foundsil)
- continue;
-
- if (vol < pstracker->silencevol) {
- if (pstracker->insilencecount == 0) {
- pstracker->silstart_samp = ds->pcmpos;
- }
- pstracker->insilencecount++;
- } else {
- pstracker->insilencecount = 0;
- }
-
- if (pstracker->insilencecount > ds->silence_samples) {
- pstracker->foundsil = TRUE;
- }
- }
-}
-
-signed int
-scale(mad_fixed_t sample)
-{
- /* round */
- sample += (1L << (MAD_F_FRACBITS - 16));
-
- /* clip */
- if (sample >= MAD_F_ONE)
- sample = MAD_F_ONE - 1;
- else if (sample < -MAD_F_ONE)
- sample = -MAD_F_ONE;
-
- /* quantize */
- return sample >> (MAD_F_FRACBITS + 1 - 16);
-}
-
-static enum mad_flow
-filter (void *data, struct mad_stream const *ms, struct mad_frame *frame)
-{
- DECODE_STRUCT *ds = (DECODE_STRUCT *)data;
- FRAME_LIST* fl;
-
- fl = (FRAME_LIST*) malloc (sizeof(FRAME_LIST));
- fl->m_framepos = ms->this_frame;
- fl->m_samples = 0;
- fl->m_pcmpos = 0;
- list_add_tail (&(fl->m_list), &(ds->frame_list));
-
-#if defined (commentout)
- debug_printf ("FILTER: %p (%02x%02x) | %p\n",
- ms->this_frame,
- ms->this_frame[0],
- ms->this_frame[1],
- ms->next_frame);
-#endif
-
- return MAD_FLOW_CONTINUE;
-}
-
-enum mad_flow
-output (void *data, struct mad_header const *header,
- struct mad_pcm *pcm)
-{
- DECODE_STRUCT *ds = (DECODE_STRUCT *)data;
- FRAME_LIST *fl;
- unsigned int nchannels, nsamples;
- mad_fixed_t const *left_ch, *right_ch;
- static short lastSample = 0;
- static signed int sample;
- double v;
-
- nchannels = pcm->channels;
- nsamples = pcm->length;
- left_ch = pcm->samples[0];
- right_ch = pcm->samples[1];
-
- /* Get frame entry */
- fl = list_entry (ds->frame_list.prev, FRAME_LIST, m_list);
- fl->m_samples = nsamples;
- fl->m_pcmpos = ds->pcmpos;
-
- if (ds->pcmpos > ds->len_to_sw_start_samp
- && ds->pcmpos < ds->len_to_sw_end_samp) {
- debug_printf ("* %d\n", ds->pcmpos);
- } else {
- debug_printf ("- %d\n", ds->pcmpos);
- }
-#if defined (commentout)
-#endif
-
- while(nsamples--) {
- /* output sample(s) in 16-bit signed little-endian PCM */
- /* GCS FIX: Does this work on big endian machines??? */
- lastSample = sample;
- sample = (short) scale (*left_ch++);
- // fwrite(&sample, sizeof(short), 1, fp);
-
- if (nchannels == 2) {
- // make mono
- sample = (sample+scale(*right_ch++))/2;
- }
-
- // get the instantanous volume
- v = (lastSample*lastSample)+(sample*sample);
- v = sqrt(v / 2);
- if (ds->pcmpos > ds->len_to_sw_start_samp
- && ds->pcmpos < ds->len_to_sw_end_samp)
- {
- search_for_silence(ds, v);
- }
- ds->pcmpos++;
- }
-
- return MAD_FLOW_CONTINUE;
-}
-
-static enum
-mad_flow header(void *data, struct mad_header const *pheader)
-{
- DECODE_STRUCT *ds = (DECODE_STRUCT *)data;
- if (!ds->samplerate) {
- ds->samplerate = pheader->samplerate;
- ds->silence_samples = ds->silence_ms * (ds->samplerate/1000);
- ds->len_to_sw_start_samp = ds->len_to_sw_ms * (ds->samplerate/1000);
- ds->len_to_sw_end_samp = (ds->len_to_sw_ms + ds->searchwindow_ms)
- * (ds->samplerate/1000);
- debug_printf ("Setting samplerate: %ld\n",ds->samplerate);
- }
- return MAD_FLOW_CONTINUE;
-}
-
-enum mad_flow
-error(void *data, struct mad_stream *ms, struct mad_frame *frame)
-{
- if (MAD_RECOVERABLE(ms->error)) {
- debug_printf("mad error 0x%04x\n", ms->error);
- return MAD_FLOW_CONTINUE;
- }
-
- debug_printf("unrecoverable mad error 0x%04x\n", ms->error);
- return MAD_FLOW_BREAK;
-}
-
-/* The following routines have nothing to do with finding a separation
- * point. Instead, they have to do with finding the bitrate. However,
- * they are included here because they are "mad" related.
- */
-error_code
-find_bitrate(unsigned long* bitrate, const u_char* mpgbuf, long mpgsize)
-{
- struct mad_decoder decoder;
- GET_BITRATE_STRUCT gbs;
- int result;
-
- /* initialize and start decoder */
- gbs.mpgbuf = (unsigned char*) mpgbuf;
- gbs.mpgsize = mpgsize;
- gbs.bitrate = 0;
- mad_decoder_init(&decoder,
- &gbs,
- input_get_bitrate /* input */,
- header_get_bitrate /* header */,
- NULL /* filter */,
- NULL /* output */,
- NULL /* error */,
- NULL /* message */);
- result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
- mad_decoder_finish(&decoder);
- *bitrate = gbs.bitrate;
- return SR_SUCCESS;
-}
-
-static enum mad_flow
-input_get_bitrate (void *data, struct mad_stream *stream)
-{
- GET_BITRATE_STRUCT* gbs = (GET_BITRATE_STRUCT*) data;
-
- if (!gbs->mpgsize)
- return MAD_FLOW_STOP;
-
- mad_stream_buffer(stream, gbs->mpgbuf, gbs->mpgsize);
- gbs->mpgsize = 0;
- return MAD_FLOW_CONTINUE;
-}
-
-static enum mad_flow
-header_get_bitrate (void *data, struct mad_header const *pheader)
-{
- GET_BITRATE_STRUCT* gbs = (GET_BITRATE_STRUCT*) data;
-
- gbs->bitrate = pheader->bitrate; /* stream bitrate (bps) */
- debug_printf ("Decoded bitrate from stream: %ld\n", gbs->bitrate);
- return MAD_FLOW_STOP;
-}
diff --git a/xbmc/lib/libshout/findsep.h b/xbmc/lib/libshout/findsep.h
deleted file mode 100644
index d7c000ed50..0000000000
--- a/xbmc/lib/libshout/findsep.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* findsep.h
- * library routines for find silent points in mp3 data
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __FINDSEP_H__
-#define __FINDSEP_H__
-
-#include "srtypes.h"
-
-error_code
-findsep_silence (const u_char* mpgbuf,
- long mpgsize,
- long len_to_sw,
- long searchwindow,
- long silence_length,
- long padding1,
- long padding2,
- u_long* pos1,
- u_long* pos2
- );
-error_code find_bitrate(unsigned long* bitrate, const u_char* mpgbuf,
- long mpgsize);
-
-#endif //__FINDSEP_H__
diff --git a/xbmc/lib/libshout/http.c b/xbmc/lib/libshout/http.c
deleted file mode 100644
index c8d55e6d03..0000000000
--- a/xbmc/lib/libshout/http.c
+++ /dev/null
@@ -1,800 +0,0 @@
-/* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include "compat.h"
-#include "srtypes.h"
-#include "socklib.h"
-#include "http.h"
-#include "mchar.h" /* for substrn_until, etc. */
-#include "debug.h"
-
-/******************************************************************************
- * Function prototypes
- *****************************************************************************/
-static char* make_auth_header(const char *header_name,
- const char *username, const char *password);
-static error_code httplib_get_sc_header(const char* url, HSOCKET *sock,
- SR_HTTP_HEADER *info);
-static char* b64enc(const char *buf, int size);
-
-/******************************************************************************
- * Private Vars
- *****************************************************************************/
-#define MAX_PLS_LEN 8192
-#define MAX_M3U_LEN 8192
-
-
-/******************************************************************************
- * Functions
- *****************************************************************************/
-
-/* Connect to a shoutcast type stream, leaves when it's about to
- get the header info */
-error_code
-httplib_sc_connect (HSOCKET *sock, const char *url, const char *proxyurl,
- SR_HTTP_HEADER *info, char *useragent, char *if_name)
-{
- char headbuf[MAX_HEADER_LEN];
- URLINFO url_info;
- int ret;
-
- while (1) {
- debug_printf ("***** URL = %s *****\n", url);
- debug_printf("inet_sc_connect(): calling httplib_parse_url\n");
- if (proxyurl) {
- if ((ret = httplib_parse_url(proxyurl, &url_info)) != SR_SUCCESS) {
- return ret;
- }
- } else if ((ret = httplib_parse_url(url, &url_info)) != SR_SUCCESS) {
- return ret;
- }
-
- debug_printf("inet_sc_connect(): calling sockinit\n");
- if ((ret = socklib_init()) != SR_SUCCESS)
- return ret;
-
- debug_printf("inet_sc_connect(): calling sock_open: host=%s, port=%d\n",
- url_info.host, url_info.port);
- if ((ret = socklib_open(sock, url_info.host, url_info.port, if_name)) != SR_SUCCESS)
- return ret;
-
- debug_printf("inet_sc_connect(): calling httplib_construct_sc_request\n");
- if ((ret = httplib_construct_sc_request(url, proxyurl, headbuf, useragent)) != SR_SUCCESS)
- return ret;
-
- debug_printf("inet_sc_connect(): calling socklib_sendall\n");
- if ((ret = socklib_sendall(sock, headbuf, strlen(headbuf))) < 0)
- return ret;
-
- debug_printf("inet_sc_connect(): calling get_sc_header\n");
- if ((ret = httplib_get_sc_header(url, sock, info)) != SR_SUCCESS)
- return ret;
-
- if (*info->http_location) {
- /* RECURSIVE CASE */
- debug_printf ("Redirecting: %s\n", info->http_location);
- url = info->http_location;
- //inet_sc_connect(sock, info->http_location, proxyurl, info, useragent, if_name);
- } else {
- break;
- }
- }
-
- return SR_SUCCESS;
-}
-
-/*
- * Parse's a url as in http://host:port/path or host/path, etc..
- * and now http://username:password@server:4480
- */
-error_code
-httplib_parse_url(const char *url, URLINFO *urlinfo)
-{
- /* see if we have a proto */
- char *s = strstr(url, "://");
- int ret;
-
- /* if we have a proto, just skip it. should we care about
- the proto? like fail if it's not http? */
- if (s) url = s + strlen("://");
- memcpy(urlinfo->path, (void *)"/\0", 2);
-
- /* search for a login '@' token */
- if (strchr(url, '@') != NULL) {
- ret = sscanf(url, "%1023[^:]:%1023[^@]", urlinfo->username, urlinfo->password);
-#if defined (commentout)
- if (ret < 2) return SR_ERROR_PARSE_FAILURE;
-#endif
- if (ret < 1) {
- return SR_ERROR_PARSE_FAILURE;
- } else if (ret == 1) {
- urlinfo->password[0] = '\0';
- }
- url = strchr(url, '@') + 1;
- } else {
- urlinfo->username[0] = '\0';
- urlinfo->password[0] = '\0';
- }
-
- /* search for a port seperator */
- if (strchr(url, ':') != NULL) {
- ret = sscanf(url, "%511[^:]:%hu/%252s", urlinfo->host,
- (short unsigned int*)&urlinfo->port, urlinfo->path+1);
- if (urlinfo->port < 1) return SR_ERROR_PARSE_FAILURE;
- ret -= 1;
- } else {
- urlinfo->port = 80;
- ret = sscanf(url, "%511[^/]/%252s", urlinfo->host, urlinfo->path+1);
- }
- if (ret < 1) return SR_ERROR_INVALID_URL;
-
- return SR_SUCCESS;
-}
-
-error_code
-httplib_construct_sc_request(const char *url, const char* proxyurl, char *buffer, char *useragent)
-{
- int ret;
- URLINFO ui;
- URLINFO proxyui;
- char myurl[MAX_URL_LEN];
- if ((ret = httplib_parse_url(url, &ui)) != SR_SUCCESS)
- return ret;
-
- if (proxyurl) {
- sprintf(myurl, "http://%s:%d%s", ui.host, ui.port, ui.path);
- if ((ret = httplib_parse_url(proxyurl, &proxyui)) != SR_SUCCESS)
- return ret;
- } else {
- strcpy(myurl, ui.path);
- }
-
- snprintf(buffer, MAX_HEADER_LEN + MAX_HOST_LEN + SR_MAX_PATH,
- "GET %s HTTP/1.0\r\n"
- "Host: %s:%d\r\n"
- "User-Agent: %s\r\n"
- "Icy-MetaData:1\r\n",
- myurl,
- ui.host,
- ui.port,
- useragent[0] ? useragent : "Streamripper/1.x");
-
- // http authentication (not proxy, see below for that)
- if (ui.username[0] && ui.password[0]) {
- char *authbuf = make_auth_header("Authorization",
- ui.username,
- ui.password);
- strcat(buffer, authbuf);
- free(authbuf);
- }
-
-#if defined (commentout)
- // proxy auth stuff
- if (proxyurl && proxyui.username[0] && proxyui.password[0]) {
- char *authbuf = make_auth_header("Proxy-Authorization",
- proxyui.username,
- proxyui.password);
- strcat(buffer, authbuf);
- free(authbuf);
- }
-#endif
- /* GCS Testing... Proxy authentication w/o password bug */
- if (proxyurl && proxyui.username[0]) {
- char *authbuf = make_auth_header("Proxy-Authorization",
- proxyui.username,
- proxyui.password);
- strcat(buffer, authbuf);
- free(authbuf);
- }
-
-
- strcat(buffer, "\r\n");
-
- return SR_SUCCESS;
-}
-
-// Make the 'Authorization: Basic xxxxxx\r\n' or 'Proxy-Authorization...'
-// headers for the HTTP request.
-static char*
-make_auth_header (const char *header_name, const char *username,
- const char *password)
-{
- char *authbuf = malloc(strlen(header_name)
- + strlen(username)
- + strlen(password)
- + MAX_URI_STRING);
- char *auth64;
- sprintf(authbuf, "%s:%s", username, password);
- auth64 = b64enc(authbuf, strlen(authbuf));
- sprintf(authbuf, "%s: Basic %s\r\n", header_name, auth64);
- free(auth64);
- return authbuf;
-}
-
-// Here we pretend we're IE 5, hehe
-error_code
-httplib_construct_page_request (const char *url, BOOL proxyformat, char *buffer)
-{
- int ret;
- URLINFO ui;
- char myurl[MAX_URL_LEN];
- if ((ret = httplib_parse_url(url, &ui)) != SR_SUCCESS)
- return ret;
-
- if (proxyformat)
- sprintf(myurl, "http://%s:%d%s", ui.host, ui.port, ui.path);
- else
- strcpy(myurl, ui.path);
-
- snprintf(buffer, MAX_HEADER_LEN + MAX_HOST_LEN + SR_MAX_PATH,
- "GET %s HTTP/1.0\r\n"
- "Host: %s:%d\r\n"
- "Accept: */*\r\n"
- "Accept-Language: en-us\r\n"
- "Accept-Encoding: gzip, deflate\r\n"
- "User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\r\n"
- "Connection: Keep-Alive\r\n\r\n",
- myurl,
- ui.host,
- ui.port);
-
-
- return SR_SUCCESS;
-}
-
-/* Return 1 if a match was found, 0 if not found */
-int
-extract_header_value (char *header, char *dest, char *match, int maxlen)
-{
- char* start = (char *)strstr(header, match);
- if (start) {
- subnstr_until(start+strlen(match), "\n", dest, maxlen);
- return 1;
- } else {
- return 0;
- }
-}
-
-error_code
-httplib_parse_sc_header (const char *url, char *header, SR_HTTP_HEADER *info)
-{
- int rc;
- char *start;
- char versionbuf[64];
- char stempbr[MAX_ICY_STRING];
- URLINFO url_info;
- int url_path_len;
- int content_type_by_url;
-
- if (!header || !info)
- return SR_ERROR_INVALID_PARAM;
-
- /* Parse the url here, before doing memset, because in the
- recursive case, it is the location referrer */
- rc = httplib_parse_url (url, &url_info);
- if (rc != SR_SUCCESS) return rc;
-
- memset(info, 0, sizeof(SR_HTTP_HEADER));
-
- debug_printf("http header:\n%s\n", header);
-
- // Get the ICY code.
- start = (char *)strstr(header, "ICY ");
- if (!start) {
- start = (char *)strstr(header, "HTTP/1.");
- if (!start) return SR_ERROR_NO_RESPOSE_HEADER;
- }
- start = strstr(start, " ") + 1;
- sscanf(start, "%i", &info->icy_code);
- if (info->icy_code >= 400) {
- switch (info->icy_code)
- {
- case 400:
- return SR_ERROR_HTTP_400_ERROR;
- case 404:
- return SR_ERROR_HTTP_404_ERROR;
- case 401:
- return SR_ERROR_HTTP_401_ERROR;
- case 403:
- return SR_ERROR_HTTP_403_ERROR;
- case 407:
- return SR_ERROR_HTTP_407_ERROR;
- case 502:
- return SR_ERROR_HTTP_502_ERROR;
- default:
- return SR_ERROR_NO_ICY_CODE;
- }
- }
-
- // read generic headers
- extract_header_value(header, info->http_location, "Location:",
- sizeof(info->http_location));
- extract_header_value(header, info->server, "Server:",
- sizeof(info->server));
- rc = extract_header_value(header, info->icy_name, "icy-name:",
- sizeof(info->icy_name));
- if (rc == 0) {
- /* Icecast 2.0.1 */
- rc = extract_header_value(header, info->icy_name, "ice-name:",
- sizeof(info->icy_name));
- }
- info->have_icy_name = rc;
- extract_header_value(header, info->icy_url, "icy-url:",
- sizeof(info->icy_url));
- rc = extract_header_value(header, stempbr,
- "icy-br:", sizeof(stempbr));
- if (rc) {
- info->icy_bitrate = atoi(stempbr);
- }
-
- /* interpret the content type from http header */
- rc = extract_header_value(header, stempbr,
- "Content-Type:", sizeof(stempbr));
- if (rc == 0) {
- rc = extract_header_value(header, stempbr,
- "content-type:", sizeof(stempbr));
- }
- if (rc == 0) {
- info->content_type = CONTENT_TYPE_UNKNOWN;
- }
- else if (strstr(stempbr,"audio/mpeg")) {
- info->content_type = CONTENT_TYPE_MP3;
- }
- else if (strstr(stempbr,"video/nsv")) {
- info->content_type = CONTENT_TYPE_NSV;
- }
- else if (strstr(stempbr,"misc/ultravox")) {
- info->content_type = CONTENT_TYPE_ULTRAVOX;
- }
- else if (strstr(stempbr,"application/ogg")) {
- info->content_type = CONTENT_TYPE_OGG;
- }
- else if (strstr(stempbr,"audio/aac")) {
- info->content_type = CONTENT_TYPE_AAC;
- }
- else if (strstr(stempbr,"audio/x-scpls")) {
- info->content_type = CONTENT_TYPE_PLS;
- }
- else {
- info->content_type = CONTENT_TYPE_UNKNOWN;
- }
-
- /* Look at url for more content type hints */
- url_path_len = strlen(url_info.path);
- content_type_by_url = CONTENT_TYPE_UNKNOWN;
- if (url_path_len >= 4) {
- if (!strcmp (&url_info.path[url_path_len-4], ".aac")) {
- content_type_by_url = CONTENT_TYPE_AAC;
- } else if (!strcmp (&url_info.path[url_path_len-4], ".ogg")) {
- content_type_by_url = CONTENT_TYPE_OGG;
- } else if (!strcmp (&url_info.path[url_path_len-4], ".mp3")) {
- content_type_by_url = CONTENT_TYPE_MP3;
- } else if (!strcmp (&url_info.path[url_path_len-4], ".nsv")) {
- content_type_by_url = CONTENT_TYPE_NSV;
- } else if (!strcmp (&url_info.path[url_path_len-4], ".pls")) {
- content_type_by_url = CONTENT_TYPE_PLS;
- } else if (!strcmp (&url_info.path[url_path_len-4], ".m3u")) {
- content_type_by_url = CONTENT_TYPE_M3U;
- }
- }
-
- // Try to guess the server
-
- // Check for Streamripper relay
- if ((start = (char *)strstr(header, "[relay stream]")) != NULL) {
- strcpy(info->server, "Streamripper relay server");
- }
- // Check for Shoutcast
- else if ((start = (char *)strstr(header, "SHOUTcast")) != NULL) {
- strcpy(info->server, "SHOUTcast/");
- if ((start = (char *)strstr(start, "Server/")) != NULL) {
- sscanf(start, "Server/%63[^<]<", versionbuf);
- strcat(info->server, versionbuf);
- }
-
- }
- // Check for Icecast 2
- else if ((start = (char *)strstr(header, "Icecast 2")) != NULL) {
- /* aac on icecast 2.0-2.1 declares content type of audio/mpeg */
- if (info->content_type == CONTENT_TYPE_MP3 &&
- content_type_by_url != CONTENT_TYPE_UNKNOWN) {
- info->content_type = content_type_by_url;
- }
- }
- // Check for Icecast 1
- else if ((start = (char *)strstr(header, "icecast")) != NULL) {
- if (!info->server[0]) {
- strcpy(info->server, "icecast/");
- if ((start = (char *)strstr(start, "version ")) != NULL) {
- sscanf(start, "version %63[^<]<", versionbuf);
- strcat(info->server, versionbuf);
- }
- }
-
- // icecast 1.x headers.
- extract_header_value(header, info->icy_url, "x-audiocast-server-url:",
- sizeof(info->icy_url));
- rc = extract_header_value(header, info->icy_name, "x-audiocast-name:",
- sizeof(info->icy_name));
- info->have_icy_name |= rc;
- extract_header_value(header, info->icy_genre, "x-audiocast-genre:",
- sizeof(info->icy_genre));
- rc = extract_header_value(header, stempbr, "x-audiocast-bitrate:",
- sizeof(stempbr));
- if (rc) {
- info->icy_bitrate = atoi(stempbr);
- }
- }
- // WTF is Zwitterion?
- else if ((start = (char *)strstr(header, "Zwitterion v")) != NULL) {
- sscanf(start, "%[^<]<", info->server);
- }
-
- /* Last chance to deduce content type */
- if (info->content_type == CONTENT_TYPE_UNKNOWN) {
- if (content_type_by_url == CONTENT_TYPE_UNKNOWN) {
- info->content_type = CONTENT_TYPE_MP3;
- } else {
- info->content_type = content_type_by_url;
- }
- }
-
- debug_printf ("Deduced content type: %d\n", info->content_type);
-
- // Make sure we don't have any CRLF's at the end of our strings
- trim(info->icy_url);
- trim(info->icy_genre);
- trim(info->icy_name);
- trim(info->http_location);
- trim(info->server);
-
- //get the meta interval
- start = (char*)strstr(header, "icy-metaint:");
- if (start) {
- sscanf(start, "icy-metaint:%i", &info->meta_interval);
- if (info->meta_interval < 1) {
- info->meta_interval = NO_META_INTERVAL;
-#if defined (commentout)
- /* GCS: I don't think we want an error here. */
- return SR_ERROR_NO_META_INTERVAL;
-#endif
- }
- } else {
- info->meta_interval = NO_META_INTERVAL;
- }
-
- return SR_SUCCESS;
-}
-
-/*
- * Constructs a HTTP response header from the SR_HTTP_HEADER struct, if data is null it is not
- * added to the header
- */
-error_code
-httplib_construct_sc_response(SR_HTTP_HEADER *info, char *header, int size, int icy_meta_support)
-{
- char *buf = (char *)malloc(size);
-
-#if defined (commentout)
- char* test_header =
- "HTTP/1.0 200 OK\r\n"
- "Content-Type: application/ogg\r\n"
- "ice-audio-info: ice-samplerate=44100\r\n"
- "ice-bitrate: Quality 0\r\n"
- "ice-description: This is my server desription\r\n"
- "ice-genre: Rock\r\n"
- "ice-name: This is my server desription\r\n"
- "ice-private: 0\r\n"
- "ice-public: 1\r\n"
- "ice-url: http://www.oddsock.org\r\n"
- "Server: Icecast 2.0.1\r\n\r\n";
-#endif
-
- if (!info || !header || size < 1)
- return SR_ERROR_INVALID_PARAM;
-
- memset(header, 0, size);
-
-#if defined (commentout)
- /* GCS - try this */
- strcpy (header, test_header);
- return SR_SUCCESS;
-#endif
-
- /* GCS: The code used to give HTTP instead of ICY for the response header,
- like this: sprintf(buf, "HTTP/1.0 200 OK\r\n"); */
- sprintf (buf, "ICY 200 OK\r\n");
- strcat(header, buf);
-
- if (info->http_location[0])
- {
- sprintf(buf, "Location:%s\r\n", info->http_location);
- strcat(header, buf);
- }
-
- if (info->server[0])
- {
- sprintf(buf, "Server:%s\r\n", info->server);
- strcat(header, buf);
- }
-
-#if defined (commentout)
- if (info->icy_name[0])
- {
- sprintf(buf, "icy-name:%s\r\n", info->icy_name);
- strcat(header, buf);
- }
-#endif
- if (info->have_icy_name) {
- sprintf(buf, "icy-name:%s\r\n", info->icy_name);
- strcat(header, buf);
- }
-
- if (info->icy_url[0])
- {
- sprintf(buf, "icy-url:%s\r\n", info->icy_url);
- strcat(header, buf);
- }
-
- if (info->icy_bitrate)
- {
- sprintf(buf, "icy-br:%d\r\n", info->icy_bitrate);
- strcat(header, buf);
- }
-
- if (info->icy_genre[0])
- {
- sprintf(buf, "icy-genre:%s\r\n", info->icy_genre);
- strcat(header, buf);
- }
-
- if ((info->meta_interval > 0) && icy_meta_support)
- {
- sprintf(buf, "icy-metaint:%d\r\n", info->meta_interval);
- strcat(header, buf);
- }
-
- switch (info->content_type) {
- case CONTENT_TYPE_MP3:
- sprintf (buf, "Content-Type: audio/mpeg\r\n");
- strcat(header, buf);
- break;
- case CONTENT_TYPE_NSV:
- sprintf (buf, "Content-Type: video/nsv\r\n");
- strcat(header, buf);
- break;
- case CONTENT_TYPE_OGG:
- sprintf (buf, "Content-Type: application/ogg\r\n");
- strcat(header, buf);
- break;
- case CONTENT_TYPE_ULTRAVOX:
- sprintf (buf, "Content-Type: misc/ultravox\r\n");
- strcat(header, buf);
- break;
- case CONTENT_TYPE_AAC:
- sprintf (buf, "Content-Type: audio/aac\r\n");
- strcat(header, buf);
- break;
- }
-
- free(buf);
- strcat(header, "\r\n");
-
- debug_printf ("Constructed response header:\n");
- debug_printf ("%s", header);
-
- return SR_SUCCESS;
-}
-
-/*
-[playlist]
-numberofentries=1
-File1=http://localhost:8000/
-Title1=(#1 - 530/18385) GCS hit radio
-Length1=-1
-Version=2
-*/
-error_code
-httplib_get_pls (HSOCKET *sock, SR_HTTP_HEADER *info)
-{
- int s, bytes;
- error_code rc;
- char buf[MAX_PLS_LEN];
- char location_buf[MAX_PLS_LEN];
- char title_buf[MAX_PLS_LEN];
- const int timeout = 30;
-
- debug_printf ("Reading pls\n");
- bytes = socklib_recvall (sock, buf, MAX_PLS_LEN, timeout);
- if (bytes < SR_SUCCESS) return bytes;
- if (bytes == 0 || bytes == MAX_PLS_LEN) {
- debug_printf("Failed in getting PLS (%d bytes)\n", bytes);
- return SR_ERROR_CANT_PARSE_PLS;
- }
- buf[bytes] = 0;
-
- debug_printf ("Parsing pls\n");
- debug_printf ("%s\n", buf);
- debug_printf ("---\n");
-
- rc = SR_ERROR_CANT_PARSE_PLS;
- for (s = 1; s <= 99; s++) {
- char buf1[20];
- int num_scanned, used, total, open;
- int best_open = 0;
-
- sprintf (buf1, "File%d=", s);
- if (!extract_header_value (buf, location_buf, buf1,
- sizeof(location_buf))) {
- break;
- }
- if (s == 1) {
- strcpy (info->http_location, location_buf);
- rc = SR_SUCCESS;
- }
-
- sprintf (buf1, "Title%d=", s);
- if (!extract_header_value (buf, title_buf, buf1, sizeof(title_buf))) {
- break;
- }
- num_scanned = sscanf (title_buf, "(#%*[0-9] - %d/%d",&used,&total);
- if (num_scanned != 2) {
- break;
- }
- open = total - used;
- if (open > best_open) {
- strcpy (info->http_location, location_buf);
- best_open = open;
- }
- }
-
- strcpy (info->http_location, location_buf);
-
- return rc;
-}
-
-/*
-#EXTM3U
-#EXTINF:111,3rd Bass - Al z A-B-Cee z
-mp3/3rd Bass/3rd bass - Al z A-B-Cee z.mp3
-*/
-error_code
-httplib_get_m3u (HSOCKET *sock, SR_HTTP_HEADER *info)
-{
- int bytes;
- char buf[MAX_M3U_LEN];
- const int timeout = 30;
- char* p;
-
- debug_printf ("Reading m3u\n");
- bytes = socklib_recvall (sock, buf, MAX_M3U_LEN, timeout);
- if (bytes < SR_SUCCESS) return bytes;
- if (bytes == 0 || bytes == MAX_M3U_LEN) {
- debug_printf("Failed in getting M3U (%d bytes)\n", bytes);
- return SR_ERROR_CANT_PARSE_M3U;
- }
- buf[bytes] = 0;
-
- debug_printf ("Parsing m3u\n");
- debug_printf ("%s\n", buf);
- debug_printf ("---\n");
-
- for (p = strtok (buf,"\n"); p!= 0; p = strtok (0, "\n")) {
- size_t len;
- if (p[0] == '#') {
- continue;
- }
- len = strlen (p);
- if (len > 4 && !strcmp (&p[len-4], ".mp3")) {
- continue;
- }
- strcpy (info->http_location, p);
- debug_printf ("Redirecting from M3U to: %s\n", p);
- return SR_SUCCESS;
- }
-
- debug_printf ("Failed parsing M3U\n");
- return SR_ERROR_CANT_PARSE_M3U;
-}
-
-static error_code
-httplib_get_sc_header(const char* url, HSOCKET *sock, SR_HTTP_HEADER *info)
-{
- int ret;
- char headbuf[MAX_HEADER_LEN] = {'\0'};
-
- if ((ret = socklib_read_header(sock, headbuf, MAX_HEADER_LEN, NULL)) != SR_SUCCESS)
- return ret;
-
- if ((ret = httplib_parse_sc_header(url, headbuf, info)) != SR_SUCCESS)
- return ret;
-
- if (info->content_type == CONTENT_TYPE_PLS) {
- ret = httplib_get_pls (sock, info);
- if (ret != SR_SUCCESS) return ret;
- } else if (info->content_type == CONTENT_TYPE_M3U) {
- ret = httplib_get_m3u (sock, info);
- if (ret != SR_SUCCESS) return ret;
- }
-
- return SR_SUCCESS;
-}
-
-// taken from:
-// Copyright (c) 2000 Virtual Unlimited B.V.
-// Author: Bob Deblier <bob@virtualunlimited.com>
-// thanks bob ;)
-#define CHARS_PER_LINE 72
-static char*
-b64enc(const char *inbuf, int size)
-{
- /* encode 72 characters per line */
- static const char* to_b64 =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- int div = size / 3;
- int rem = size % 3;
- int chars = div*4 + rem + 1;
- int newlines = (chars + CHARS_PER_LINE - 1) / CHARS_PER_LINE;
-
- const char* data = inbuf;
- char* string = (char*) malloc(chars + newlines + 1 + 100);
-
- if (string) {
- register char* buf = string;
-
- chars = 0;
-
- /*@+charindex@*/
- while (div > 0) {
- buf[0] = to_b64[ (data[0] >> 2) & 0x3f];
- buf[1] = to_b64[((data[0] << 4) & 0x30) + ((data[1] >> 4) & 0xf)];
- buf[2] = to_b64[((data[1] << 2) & 0x3c) + ((data[2] >> 6) & 0x3)];
- buf[3] = to_b64[ data[2] & 0x3f];
- data += 3;
- buf += 4;
- div--;
- chars += 4;
- if (chars == CHARS_PER_LINE) {
- chars = 0;
- *(buf++) = '\n';
- }
- }
- switch (rem) {
- case 2:
- buf[0] = to_b64[ (data[0] >> 2) & 0x3f];
- buf[1] = to_b64[((data[0] << 4) & 0x30) + ((data[1] >> 4) & 0xf)];
- buf[2] = to_b64[ (data[1] << 2) & 0x3c];
- buf[3] = '=';
- buf += 4;
- chars += 4;
- break;
- case 1:
- buf[0] = to_b64[ (data[0] >> 2) & 0x3f];
- buf[1] = to_b64[ (data[0] << 4) & 0x30];
- buf[2] = '=';
- buf[3] = '=';
- buf += 4;
- chars += 4;
- break;
- }
- /* *(buf++) = '\n'; This would result in a buffer overrun */
- *buf = '\0';
- }
- return string;
-}
-
diff --git a/xbmc/lib/libshout/http.h b/xbmc/lib/libshout/http.h
deleted file mode 100644
index 52a2b9ea1b..0000000000
--- a/xbmc/lib/libshout/http.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef __HTTP_H__
-#define __HTTP_H__
-
-#include "srtypes.h"
-
-typedef struct SR_HTTP_HEADERst
-{
- int content_type;
- int meta_interval;
- int have_icy_name;
- char icy_name[MAX_ICY_STRING];
- int icy_code;
- int icy_bitrate;
- char icy_genre[MAX_ICY_STRING];
- char icy_url[MAX_ICY_STRING];
- char http_location[MAX_HOST_LEN];
- char server[MAX_SERVER_LEN];
-} SR_HTTP_HEADER;
-
-typedef struct URLINFOst
-{
- char host[MAX_HOST_LEN];
- char path[SR_MAX_PATH];
- u_short port;
- char username[MAX_URI_STRING];
- char password[MAX_URI_STRING];
-} URLINFO;
-
-error_code httplib_parse_url(const char *url, URLINFO *urlinfo);
-error_code httplib_parse_sc_header(const char* url, char *header, SR_HTTP_HEADER *info);
-error_code httplib_construct_sc_request(const char *url, const char* proxyurl, char *buffer, char *useragent);
-error_code httplib_construct_page_request(const char *url, BOOL proxyformat, char *buffer);
-error_code httplib_construct_sc_response(SR_HTTP_HEADER *info, char *header, int size, int icy_meta_support);
-error_code inet_get_webpage_alloc(HSOCKET *sock, const char *url,
- const char *proxyurl,
- char **buffer, unsigned long *size);
-error_code httplib_sc_connect(HSOCKET *sock, const char *url,
- const char *proxyurl,
- SR_HTTP_HEADER *info, char *useragent,
- char *if_name);
-
-
-#endif //__HTTP_H__
diff --git a/xbmc/lib/libshout/iconvert.c b/xbmc/lib/libshout/iconvert.c
deleted file mode 100644
index ea34891b3d..0000000000
--- a/xbmc/lib/libshout/iconvert.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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
- */
-
-#ifdef HAVE_ICONV
-
-#include <assert.h>
-#include <errno.h>
-#include <iconv.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
- * Convert data from one encoding to another. Return:
- *
- * -2 : memory allocation failed
- * -1 : unknown encoding
- * 0 : data was converted exactly
- * 1 : data was converted inexactly
- * 2 : data was invalid (but still converted)
- *
- * We convert in two steps, via UTF-8, as this is the only
- * reliable way of distinguishing between invalid input
- * and valid input which iconv refuses to transliterate.
- * We convert from UTF-8 twice, because we have no way of
- * knowing whether the conversion was exact if iconv returns
- * E2BIG (due to a bug in the specification of iconv).
- * An alternative approach is to assume that the output of
- * iconv is never more than 4 times as long as the input,
- * but I prefer to avoid that assumption if possible.
- */
-
-int iconvert(const char *fromcode, const char *tocode,
- const char *from, size_t fromlen,
- char **to, size_t *tolen)
-{
- int ret = 0;
- iconv_t cd1, cd2;
- char *ib;
- char *ob;
- char *utfbuf = 0, *outbuf, *newbuf;
- size_t utflen, outlen, ibl, obl, k;
- char tbuf[2048];
-
- cd1 = iconv_open("UTF-8", fromcode);
- if (cd1 == (iconv_t)(-1))
- return -1;
-
- cd2 = (iconv_t)(-1);
- /* Don't use strcasecmp() as it's locale-dependent. */
- if (!strchr("Uu", tocode[0]) ||
- !strchr("Tt", tocode[1]) ||
- !strchr("Ff", tocode[2]) ||
- tocode[3] != '-' ||
- tocode[4] != '8' ||
- tocode[5] != '\0') {
- char *tocode1;
-
- /*
- * Try using this non-standard feature of glibc and libiconv.
- * This is deliberately not a config option as people often
- * change their iconv library without rebuilding applications.
- */
- tocode1 = (char *)malloc(strlen(tocode) + 11);
- if (!tocode1)
- goto fail;
-
- strcpy(tocode1, tocode);
- strcat(tocode1, "//TRANSLIT");
- cd2 = iconv_open(tocode1, "UTF-8");
- free(tocode1);
-
- if (cd2 == (iconv_t)(-1))
- cd2 = iconv_open(tocode, fromcode);
-
- if (cd2 == (iconv_t)(-1)) {
- iconv_close(cd1);
- return -1;
- }
- }
-
- utflen = 1; /*fromlen * 2 + 1; XXX */
- utfbuf = (char *)malloc(utflen);
- if (!utfbuf)
- goto fail;
-
- /* Convert to UTF-8 */
- ib = (char *)from;
- ibl = fromlen;
- ob = utfbuf;
- obl = utflen;
- for (;;) {
- k = iconv(cd1, &ib, &ibl, &ob, &obl);
- assert((!k && !ibl) ||
- (k == (size_t)(-1) && errno == E2BIG && ibl && obl < 6) ||
- (k == (size_t)(-1) &&
- (errno == EILSEQ || errno == EINVAL) && ibl));
- if (!ibl)
- break;
- if (obl < 6) {
- /* Enlarge the buffer */
- utflen *= 2;
- newbuf = (char *)realloc(utfbuf, utflen);
- if (!newbuf)
- goto fail;
- ob = (ob - utfbuf) + newbuf;
- obl = utflen - (ob - newbuf);
- utfbuf = newbuf;
- }
- else {
- /* Invalid input */
- ib++, ibl--;
- *ob++ = '#', obl--;
- ret = 2;
- iconv(cd1, 0, 0, 0, 0);
- }
- }
-
- if (cd2 == (iconv_t)(-1)) {
- /* The target encoding was UTF-8 */
- if (tolen)
- *tolen = ob - utfbuf;
- if (!to) {
- free(utfbuf);
- iconv_close(cd1);
- return ret;
- }
- newbuf = (char *)realloc(utfbuf, (ob - utfbuf) + 1);
- if (!newbuf)
- goto fail;
- ob = (ob - utfbuf) + newbuf;
- *ob = '\0';
- *to = newbuf;
- iconv_close(cd1);
- return ret;
- }
-
- /* Truncate the buffer to be tidy */
- utflen = ob - utfbuf;
- newbuf = (char *)realloc(utfbuf, utflen);
- if (!newbuf)
- goto fail;
- utfbuf = newbuf;
-
- /* Convert from UTF-8 to discover how long the output is */
- outlen = 0;
- ib = utfbuf;
- ibl = utflen;
- while (ibl) {
- ob = tbuf;
- obl = sizeof(tbuf);
- k = iconv(cd2, &ib, &ibl, &ob, &obl);
- assert((k != (size_t)(-1) && !ibl) ||
- (k == (size_t)(-1) && errno == E2BIG && ibl) ||
- (k == (size_t)(-1) && errno == EILSEQ && ibl));
- if (ibl && !(k == (size_t)(-1) && errno == E2BIG)) {
- /* Replace one character */
- char *tb = "?";
- size_t tbl = 1;
-
- outlen += ob - tbuf;
- ob = tbuf;
- obl = sizeof(tbuf);
- k = iconv(cd2, &tb, &tbl, &ob, &obl);
- assert((!k && !tbl) ||
- (k == (size_t)(-1) && errno == EILSEQ && tbl));
- for (++ib, --ibl; ibl && (*ib & 0x80); ib++, ibl--)
- ;
- }
- outlen += ob - tbuf;
- }
- ob = tbuf;
- obl = sizeof(tbuf);
- k = iconv(cd2, 0, 0, &ob, &obl);
- assert(!k);
- outlen += ob - tbuf;
-
- /* Convert from UTF-8 for real */
- outbuf = (char *)malloc(outlen + 1);
- if (!outbuf)
- goto fail;
- ib = utfbuf;
- ibl = utflen;
- ob = outbuf;
- obl = outlen;
- while (ibl) {
- k = iconv(cd2, &ib, &ibl, &ob, &obl);
- assert((k != (size_t)(-1) && !ibl) ||
- (k == (size_t)(-1) && errno == EILSEQ && ibl));
- if (k && !ret)
- ret = 1;
- if (ibl && !(k == (size_t)(-1) && errno == E2BIG)) {
- /* Replace one character */
- char *tb = "?";
- size_t tbl = 1;
-
- k = iconv(cd2, &tb, &tbl, &ob, &obl);
- assert((!k && !tbl) ||
- (k == (size_t)(-1) && errno == EILSEQ && tbl));
- for (++ib, --ibl; ibl && (*ib & 0x80); ib++, ibl--)
- ;
- }
- }
- k = iconv(cd2, 0, 0, &ob, &obl);
- assert(!k);
- assert(!obl);
- *ob = '\0';
-
- free(utfbuf);
- iconv_close(cd1);
- iconv_close(cd2);
- if (tolen)
- *tolen = outlen;
- if (!to) {
- free(outbuf);
- return ret;
- }
- *to = outbuf;
- return ret;
-
- fail:
- free(utfbuf);
- iconv_close(cd1);
- if (cd2 != (iconv_t)(-1))
- iconv_close(cd2);
- return -2;
-}
-
-#endif /* HAVE_ICONV */
diff --git a/xbmc/lib/libshout/ictest.c b/xbmc/lib/libshout/ictest.c
deleted file mode 100644
index 4da23028d6..0000000000
--- a/xbmc/lib/libshout/ictest.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <locale.h>
-#include <iconv.h>
-#include <wchar.h>
-#include <wctype.h>
-
-int
-main (int argc, char* argv[])
-{
- wchar_t buf[1024];
-
- setlocale (LC_CTYPE, "");
- swprintf (buf, 1024, L"%ls", L"HiHi");
- printf ("%d wide chars in arg\n", wcslen(L"HiHi"));
- printf ("%d wide chars in buf\n", wcslen(buf));
- return 0;
-}
-
diff --git a/xbmc/lib/libshout/libshout/libshout.sln b/xbmc/lib/libshout/libshout/libshout.sln
deleted file mode 100644
index b3027cc47e..0000000000
--- a/xbmc/lib/libshout/libshout/libshout.sln
+++ /dev/null
@@ -1,21 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 8.00
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libshout", "libshout.vcproj", "{76850A99-4EC7-4196-B3EA-E4120A00E8A6}"
- ProjectSection(ProjectDependencies) = postProject
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfiguration) = preSolution
- Debug = Debug
- Release = Release
- EndGlobalSection
- GlobalSection(ProjectConfiguration) = postSolution
- {76850A99-4EC7-4196-B3EA-E4120A00E8A6}.Debug.ActiveCfg = Debug|Win32
- {76850A99-4EC7-4196-B3EA-E4120A00E8A6}.Debug.Build.0 = Debug|Win32
- {76850A99-4EC7-4196-B3EA-E4120A00E8A6}.Release.ActiveCfg = Release|Win32
- {76850A99-4EC7-4196-B3EA-E4120A00E8A6}.Release.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- EndGlobalSection
- GlobalSection(ExtensibilityAddIns) = postSolution
- EndGlobalSection
-EndGlobal
diff --git a/xbmc/lib/libshout/libshout/libshout.vcproj b/xbmc/lib/libshout/libshout/libshout.vcproj
deleted file mode 100644
index aea7fe6f11..0000000000
--- a/xbmc/lib/libshout/libshout/libshout.vcproj
+++ /dev/null
@@ -1,336 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="9,00"
- Name="libshout"
- ProjectGUID="{76850A99-4EC7-4196-B3EA-E4120A00E8A6}"
- Keyword="Win32Proj"
- TargetFrameworkVersion="131072"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(SolutionDir)libs\$(ProjectName)\$(ConfigurationName)\"
- IntermediateDirectory="$(SolutionDir)objs\$(ProjectName)\$(ConfigurationName)\"
- ConfigurationType="4"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="regex;..\..\..\cores\paplayer;..\..\..\xbmc\cores\dvdplayer\DVDCodecs;..\..\libiconv;..\..\..\cores\dvdplayer\DVDCodecs\Audio\libmad;..\..\..\..\lib\libiconv\include"
- PreprocessorDefinitions="WIN32;_DEBUG;_LIB;XBMC;HAVE_ICONV;ANSI_PROTOTYPES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- AdditionalDependencies="libmad.lib ogg_static.lib vorbis_static.lib"
- OutputFile="$(OutDir)/libshout.lib"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)libs\$(ProjectName)\$(ConfigurationName)\"
- IntermediateDirectory="$(SolutionDir)objs\$(ProjectName)\$(ConfigurationName)\"
- ConfigurationType="4"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="regex;..\..\..\cores\paplayer;..\..\..\xbmc\cores\dvdplayer\DVDCodecs;..\..\libiconv;..\..\..\cores\dvdplayer\DVDCodecs\Audio\libmad;..\..\..\..\lib\libiconv\include"
- PreprocessorDefinitions="WIN32;NDEBUG;_LIB;XBMC;HAVE_ICONV;ANSI_PROTOTYPES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
- RuntimeLibrary="0"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- DebugInformationFormat="0"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- AdditionalDependencies="libmad.lib ogg_static.lib vorbis_static.lib"
- OutputFile="$(OutDir)/libshout.lib"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Quelldateien"
- Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath="..\argv.c"
- >
- </File>
- <File
- RelativePath="..\cbuf2.c"
- >
- </File>
- <File
- RelativePath="..\charset.c"
- >
- </File>
- <File
- RelativePath="..\debug.c"
- >
- </File>
- <File
- RelativePath="..\external.c"
- >
- </File>
- <File
- RelativePath="..\filelib.c"
- >
- </File>
- <File
- RelativePath="..\findsep.c"
- >
- </File>
- <File
- RelativePath="..\http.c"
- >
- </File>
- <File
- RelativePath="..\iconvert.c"
- >
- </File>
- <File
- RelativePath="..\ictest.c"
- >
- </File>
- <File
- RelativePath="..\mchar.c"
- >
- </File>
- <File
- RelativePath="..\mpeg.c"
- >
- </File>
- <File
- RelativePath="..\parse.c"
- >
- </File>
- <File
- RelativePath="..\relaylib.c"
- >
- </File>
- <File
- RelativePath="..\rip_manager.c"
- >
- </File>
- <File
- RelativePath="..\ripaac.c"
- >
- </File>
- <File
- RelativePath="..\ripogg.c"
- >
- </File>
- <File
- RelativePath="..\ripstream.c"
- >
- </File>
- <File
- RelativePath="..\socklib.c"
- >
- </File>
- <File
- RelativePath=".\stdafx.cpp"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- UsePrecompiledHeader="1"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- UsePrecompiledHeader="1"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\threadlib.c"
- >
- </File>
- <File
- RelativePath="..\utf8.c"
- >
- </File>
- </Filter>
- <Filter
- Name="Headerdateien"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath="..\cbuf2.h"
- >
- </File>
- <File
- RelativePath="..\charset.h"
- >
- </File>
- <File
- RelativePath="..\debug.h"
- >
- </File>
- <File
- RelativePath="..\external.h"
- >
- </File>
- <File
- RelativePath="..\filelib.h"
- >
- </File>
- <File
- RelativePath="..\findsep.h"
- >
- </File>
- <File
- RelativePath="..\http.h"
- >
- </File>
- <File
- RelativePath="..\mchar.h"
- >
- </File>
- <File
- RelativePath="..\parse.h"
- >
- </File>
- <File
- RelativePath="..\relaylib.h"
- >
- </File>
- <File
- RelativePath="..\rip_manager.h"
- >
- </File>
- <File
- RelativePath="..\ripogg.h"
- >
- </File>
- <File
- RelativePath="..\ripstream.h"
- >
- </File>
- <File
- RelativePath="..\socklib.h"
- >
- </File>
- <File
- RelativePath=".\stdafx.h"
- >
- </File>
- <File
- RelativePath="..\threadlib.h"
- >
- </File>
- <File
- RelativePath="..\utf8.h"
- >
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/xbmc/lib/libshout/libshout/libshout.vcxproj b/xbmc/lib/libshout/libshout/libshout.vcxproj
deleted file mode 100644
index d0fa8343b4..0000000000
--- a/xbmc/lib/libshout/libshout/libshout.vcxproj
+++ /dev/null
@@ -1,130 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{76850A99-4EC7-4196-B3EA-E4120A00E8A6}</ProjectGuid>
- <Keyword>Win32Proj</Keyword>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
- <Import Project="..\..\..\..\project\VS2010Express\XBMC for Windows.props" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
- <Import Project="..\..\..\..\project\VS2010Express\XBMC for Windows.props" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup>
- <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)libs\$(TargetName)\$(Configuration)\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)libs\$(TargetName)\$(Configuration)\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>regex;..\..\..\cores\paplayer;..\..\..\xbmc\cores\dvdplayer\DVDCodecs;..\..\libiconv;..\..\..\cores\dvdplayer\DVDCodecs\Audio\libmad;..\..\..\..\lib\libiconv\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;XBMC;HAVE_ICONV;ANSI_PROTOTYPES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>true</MinimalRebuild>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
- </ClCompile>
- <Lib>
- <AdditionalDependencies>libmad.lib;ogg_static.lib;vorbis_static.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <OutputFile>$(OutDir)libshout.lib</OutputFile>
- </Lib>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <AdditionalIncludeDirectories>regex;..\..\..\cores\paplayer;..\..\..\xbmc\cores\dvdplayer\DVDCodecs;..\..\libiconv;..\..\..\cores\dvdplayer\DVDCodecs\Audio\libmad;..\..\..\..\lib\libiconv\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;XBMC;HAVE_ICONV;ANSI_PROTOTYPES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <DebugInformationFormat>
- </DebugInformationFormat>
- </ClCompile>
- <Lib>
- <AdditionalDependencies>libmad.lib;ogg_static.lib;vorbis_static.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <OutputFile>$(OutDir)libshout.lib</OutputFile>
- </Lib>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="..\argv.c" />
- <ClCompile Include="..\cbuf2.c" />
- <ClCompile Include="..\charset.c" />
- <ClCompile Include="..\debug.c" />
- <ClCompile Include="..\external.c" />
- <ClCompile Include="..\filelib.c" />
- <ClCompile Include="..\findsep.c" />
- <ClCompile Include="..\http.c" />
- <ClCompile Include="..\iconvert.c" />
- <ClCompile Include="..\ictest.c" />
- <ClCompile Include="..\mchar.c" />
- <ClCompile Include="..\mpeg.c" />
- <ClCompile Include="..\parse.c" />
- <ClCompile Include="..\relaylib.c" />
- <ClCompile Include="..\rip_manager.c" />
- <ClCompile Include="..\ripaac.c" />
- <ClCompile Include="..\ripogg.c" />
- <ClCompile Include="..\ripstream.c" />
- <ClCompile Include="..\socklib.c" />
- <ClCompile Include="stdafx.cpp">
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
- </ClCompile>
- <ClCompile Include="..\threadlib.c" />
- <ClCompile Include="..\utf8.c" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="..\cbuf2.h" />
- <ClInclude Include="..\charset.h" />
- <ClInclude Include="..\debug.h" />
- <ClInclude Include="..\external.h" />
- <ClInclude Include="..\filelib.h" />
- <ClInclude Include="..\findsep.h" />
- <ClInclude Include="..\http.h" />
- <ClInclude Include="..\mchar.h" />
- <ClInclude Include="..\parse.h" />
- <ClInclude Include="..\relaylib.h" />
- <ClInclude Include="..\rip_manager.h" />
- <ClInclude Include="..\ripogg.h" />
- <ClInclude Include="..\ripstream.h" />
- <ClInclude Include="..\socklib.h" />
- <ClInclude Include="stdafx.h" />
- <ClInclude Include="..\threadlib.h" />
- <ClInclude Include="..\utf8.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/xbmc/lib/libshout/libshout/libshout.vcxproj.filters b/xbmc/lib/libshout/libshout/libshout.vcxproj.filters
deleted file mode 100644
index 262f9535b7..0000000000
--- a/xbmc/lib/libshout/libshout/libshout.vcxproj.filters
+++ /dev/null
@@ -1,134 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Quelldateien">
- <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
- <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
- </Filter>
- <Filter Include="Headerdateien">
- <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
- <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="..\argv.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\cbuf2.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\charset.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\debug.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\external.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\filelib.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\findsep.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\http.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\iconvert.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\ictest.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\mchar.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\mpeg.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\parse.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\relaylib.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\rip_manager.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\ripaac.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\ripogg.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\ripstream.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\socklib.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="stdafx.cpp">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\threadlib.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- <ClCompile Include="..\utf8.c">
- <Filter>Quelldateien</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="..\cbuf2.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\charset.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\debug.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\external.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\filelib.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\findsep.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\http.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\mchar.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\parse.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\relaylib.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\rip_manager.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\ripogg.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\ripstream.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\socklib.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="stdafx.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\threadlib.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- <ClInclude Include="..\utf8.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/xbmc/lib/libshout/libshout/regex/regcomp.c b/xbmc/lib/libshout/libshout/regex/regcomp.c
deleted file mode 100644
index 4cf168821c..0000000000
--- a/xbmc/lib/libshout/libshout/regex/regcomp.c
+++ /dev/null
@@ -1,3801 +0,0 @@
-/* Extended regular expression matching and search library.
- Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
-
- The GNU C 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.
-
- The GNU C 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 GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
- size_t length, reg_syntax_t syntax);
-static void re_compile_fastmap_iter (regex_t *bufp,
- const re_dfastate_t *init_state,
- char *fastmap);
-static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len);
-#ifdef RE_ENABLE_I18N
-static void free_charset (re_charset_t *cset);
-#endif /* RE_ENABLE_I18N */
-static void free_workarea_compile (regex_t *preg);
-static reg_errcode_t create_initial_state (re_dfa_t *dfa);
-#ifdef RE_ENABLE_I18N
-static void optimize_utf8 (re_dfa_t *dfa);
-#endif
-static reg_errcode_t analyze (regex_t *preg);
-static reg_errcode_t preorder (bin_tree_t *root,
- reg_errcode_t (fn (void *, bin_tree_t *)),
- void *extra);
-static reg_errcode_t postorder (bin_tree_t *root,
- reg_errcode_t (fn (void *, bin_tree_t *)),
- void *extra);
-static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node);
-static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node);
-static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg,
- bin_tree_t *node);
-static reg_errcode_t calc_first (void *extra, bin_tree_t *node);
-static reg_errcode_t calc_next (void *extra, bin_tree_t *node);
-static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node);
-static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint);
-static int search_duplicated_node (const re_dfa_t *dfa, int org_node,
- unsigned int constraint);
-static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
-static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
- int node, int root);
-static reg_errcode_t calc_inveclosure (re_dfa_t *dfa);
-static int fetch_number (re_string_t *input, re_token_t *token,
- reg_syntax_t syntax);
-static int peek_token (re_token_t *token, re_string_t *input,
- reg_syntax_t syntax) internal_function;
-static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,
- reg_syntax_t syntax, reg_errcode_t *err);
-static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,
- re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
-static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,
- re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
-static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,
- re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
-static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,
- re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
-static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,
- re_dfa_t *dfa, re_token_t *token,
- reg_syntax_t syntax, reg_errcode_t *err);
-static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa,
- re_token_t *token, reg_syntax_t syntax,
- reg_errcode_t *err);
-static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,
- re_string_t *regexp,
- re_token_t *token, int token_len,
- re_dfa_t *dfa,
- reg_syntax_t syntax,
- int accept_hyphen);
-static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
- re_string_t *regexp,
- re_token_t *token);
-#ifdef RE_ENABLE_I18N
-static reg_errcode_t build_equiv_class (bitset_t sbcset,
- re_charset_t *mbcset,
- int *equiv_class_alloc,
- const unsigned char *name);
-static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
- bitset_t sbcset,
- re_charset_t *mbcset,
- int *char_class_alloc,
- const unsigned char *class_name,
- reg_syntax_t syntax);
-#else /* not RE_ENABLE_I18N */
-static reg_errcode_t build_equiv_class (bitset_t sbcset,
- const unsigned char *name);
-static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
- bitset_t sbcset,
- const unsigned char *class_name,
- reg_syntax_t syntax);
-#endif /* not RE_ENABLE_I18N */
-static bin_tree_t *build_charclass_op (re_dfa_t *dfa,
- RE_TRANSLATE_TYPE trans,
- const unsigned char *class_name,
- const unsigned char *extra,
- int non_match, reg_errcode_t *err);
-static bin_tree_t *create_tree (re_dfa_t *dfa,
- bin_tree_t *left, bin_tree_t *right,
- re_token_type_t type);
-static bin_tree_t *create_token_tree (re_dfa_t *dfa,
- bin_tree_t *left, bin_tree_t *right,
- const re_token_t *token);
-static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
-static void free_token (re_token_t *node);
-static reg_errcode_t free_tree (void *extra, bin_tree_t *node);
-static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);
-
-/* This table gives an error message for each of the error codes listed
- in regex.h. Obviously the order here has to be same as there.
- POSIX doesn't require that we do anything for REG_NOERROR,
- but why not be nice? */
-
-const char __re_error_msgid[] attribute_hidden =
- {
-#define REG_NOERROR_IDX 0
- gettext_noop ("Success") /* REG_NOERROR */
- "\0"
-#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
- gettext_noop ("No match") /* REG_NOMATCH */
- "\0"
-#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match")
- gettext_noop ("Invalid regular expression") /* REG_BADPAT */
- "\0"
-#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
- gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
- "\0"
-#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character")
- gettext_noop ("Invalid character class name") /* REG_ECTYPE */
- "\0"
-#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name")
- gettext_noop ("Trailing backslash") /* REG_EESCAPE */
- "\0"
-#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash")
- gettext_noop ("Invalid back reference") /* REG_ESUBREG */
- "\0"
-#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference")
- gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */
- "\0"
-#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^")
- gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
- "\0"
-#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
- gettext_noop ("Unmatched \\{") /* REG_EBRACE */
- "\0"
-#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{")
- gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
- "\0"
-#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
- gettext_noop ("Invalid range end") /* REG_ERANGE */
- "\0"
-#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end")
- gettext_noop ("Memory exhausted") /* REG_ESPACE */
- "\0"
-#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted")
- gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
- "\0"
-#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
- gettext_noop ("Premature end of regular expression") /* REG_EEND */
- "\0"
-#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression")
- gettext_noop ("Regular expression too big") /* REG_ESIZE */
- "\0"
-#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big")
- gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
- };
-
-const size_t __re_error_msgid_idx[] attribute_hidden =
- {
- REG_NOERROR_IDX,
- REG_NOMATCH_IDX,
- REG_BADPAT_IDX,
- REG_ECOLLATE_IDX,
- REG_ECTYPE_IDX,
- REG_EESCAPE_IDX,
- REG_ESUBREG_IDX,
- REG_EBRACK_IDX,
- REG_EPAREN_IDX,
- REG_EBRACE_IDX,
- REG_BADBR_IDX,
- REG_ERANGE_IDX,
- REG_ESPACE_IDX,
- REG_BADRPT_IDX,
- REG_EEND_IDX,
- REG_ESIZE_IDX,
- REG_ERPAREN_IDX
- };
-
-/* Entry points for GNU code. */
-
-/* re_compile_pattern is the GNU regular expression compiler: it
- compiles PATTERN (of length LENGTH) and puts the result in BUFP.
- Returns 0 if the pattern was valid, otherwise an error string.
-
- Assumes the `allocated' (and perhaps `buffer') and `translate' fields
- are set in BUFP on entry. */
-
-const char *
-re_compile_pattern (pattern, length, bufp)
- const char *pattern;
- size_t length;
- struct re_pattern_buffer *bufp;
-{
- reg_errcode_t ret;
-
- /* And GNU code determines whether or not to get register information
- by passing null for the REGS argument to re_match, etc., not by
- setting no_sub, unless RE_NO_SUB is set. */
- bufp->no_sub = !!(re_syntax_options & RE_NO_SUB);
-
- /* Match anchors at newline. */
- bufp->newline_anchor = 1;
-
- ret = re_compile_internal (bufp, pattern, length, re_syntax_options);
-
- if (!ret)
- return NULL;
- return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
-}
-#ifdef _LIBC
-weak_alias (__re_compile_pattern, re_compile_pattern)
-#endif
-
-/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can
- also be assigned to arbitrarily: each pattern buffer stores its own
- syntax, so it can be changed between regex compilations. */
-/* This has no initializer because initialized variables in Emacs
- become read-only after dumping. */
-reg_syntax_t re_syntax_options;
-
-
-/* Specify the precise syntax of regexps for compilation. This provides
- for compatibility for various utilities which historically have
- different, incompatible syntaxes.
-
- The argument SYNTAX is a bit mask comprised of the various bits
- defined in regex.h. We return the old syntax. */
-
-reg_syntax_t
-re_set_syntax (syntax)
- reg_syntax_t syntax;
-{
- reg_syntax_t ret = re_syntax_options;
-
- re_syntax_options = syntax;
- return ret;
-}
-#ifdef _LIBC
-weak_alias (__re_set_syntax, re_set_syntax)
-#endif
-
-int
-re_compile_fastmap (bufp)
- struct re_pattern_buffer *bufp;
-{
- re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
- char *fastmap = bufp->fastmap;
-
- memset (fastmap, '\0', sizeof (char) * SBC_MAX);
- re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);
- if (dfa->init_state != dfa->init_state_word)
- re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);
- if (dfa->init_state != dfa->init_state_nl)
- re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);
- if (dfa->init_state != dfa->init_state_begbuf)
- re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);
- bufp->fastmap_accurate = 1;
- return 0;
-}
-#ifdef _LIBC
-weak_alias (__re_compile_fastmap, re_compile_fastmap)
-#endif
-
-static inline void
-__attribute ((always_inline))
-re_set_fastmap (char *fastmap, int icase, int ch)
-{
- fastmap[ch] = 1;
- if (icase)
- fastmap[tolower (ch)] = 1;
-}
-
-/* Helper function for re_compile_fastmap.
- Compile fastmap for the initial_state INIT_STATE. */
-
-static void
-re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
- char *fastmap)
-{
- re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
- int node_cnt;
- int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
- for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
- {
- int node = init_state->nodes.elems[node_cnt];
- re_token_type_t type = dfa->nodes[node].type;
-
- if (type == CHARACTER)
- {
- re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
-#ifdef RE_ENABLE_I18N
- if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
- {
- unsigned char *buf = alloca (dfa->mb_cur_max), *p;
- wchar_t wc;
- mbstate_t state;
-
- p = buf;
- *p++ = dfa->nodes[node].opr.c;
- while (++node < dfa->nodes_len
- && dfa->nodes[node].type == CHARACTER
- && dfa->nodes[node].mb_partial)
- *p++ = dfa->nodes[node].opr.c;
- memset (&state, '\0', sizeof (state));
- if (mbrtowc (&wc, (const char *) buf, p - buf,
- &state) == p - buf
- && (__wcrtomb ((char *) buf, towlower (wc), &state)
- != (size_t) -1))
- re_set_fastmap (fastmap, 0, buf[0]);
- }
-#endif
- }
- else if (type == SIMPLE_BRACKET)
- {
- int i, ch;
- for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
- {
- int j;
- bitset_word_t w = dfa->nodes[node].opr.sbcset[i];
- for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
- if (w & ((bitset_word_t) 1 << j))
- re_set_fastmap (fastmap, icase, ch);
- }
- }
-#ifdef RE_ENABLE_I18N
- else if (type == COMPLEX_BRACKET)
- {
- int i;
- re_charset_t *cset = dfa->nodes[node].opr.mbcset;
- if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes
- || cset->nranges || cset->nchar_classes)
- {
-# ifdef _LIBC
- if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0)
- {
- /* In this case we want to catch the bytes which are
- the first byte of any collation elements.
- e.g. In da_DK, we want to catch 'a' since "aa"
- is a valid collation element, and don't catch
- 'b' since 'b' is the only collation element
- which starts from 'b'. */
- const int32_t *table = (const int32_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
- for (i = 0; i < SBC_MAX; ++i)
- if (table[i] < 0)
- re_set_fastmap (fastmap, icase, i);
- }
-# else
- if (dfa->mb_cur_max > 1)
- for (i = 0; i < SBC_MAX; ++i)
- if (__btowc (i) == WEOF)
- re_set_fastmap (fastmap, icase, i);
-# endif /* not _LIBC */
- }
- for (i = 0; i < cset->nmbchars; ++i)
- {
- char buf[256];
- mbstate_t state;
- memset (&state, '\0', sizeof (state));
- if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
- re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
- if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
- {
- if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)
- != (size_t) -1)
- re_set_fastmap (fastmap, 0, *(unsigned char *) buf);
- }
- }
- }
-#endif /* RE_ENABLE_I18N */
- else if (type == OP_PERIOD
-#ifdef RE_ENABLE_I18N
- || type == OP_UTF8_PERIOD
-#endif /* RE_ENABLE_I18N */
- || type == END_OF_RE)
- {
- memset (fastmap, '\1', sizeof (char) * SBC_MAX);
- if (type == END_OF_RE)
- bufp->can_be_null = 1;
- return;
- }
- }
-}
-
-/* Entry point for POSIX code. */
-/* regcomp takes a regular expression as a string and compiles it.
-
- PREG is a regex_t *. We do not expect any fields to be initialized,
- since POSIX says we shouldn't. Thus, we set
-
- `buffer' to the compiled pattern;
- `used' to the length of the compiled pattern;
- `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
- REG_EXTENDED bit in CFLAGS is set; otherwise, to
- RE_SYNTAX_POSIX_BASIC;
- `newline_anchor' to REG_NEWLINE being set in CFLAGS;
- `fastmap' to an allocated space for the fastmap;
- `fastmap_accurate' to zero;
- `re_nsub' to the number of subexpressions in PATTERN.
-
- PATTERN is the address of the pattern string.
-
- CFLAGS is a series of bits which affect compilation.
-
- If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
- use POSIX basic syntax.
-
- If REG_NEWLINE is set, then . and [^...] don't match newline.
- Also, regexec will try a match beginning after every newline.
-
- If REG_ICASE is set, then we considers upper- and lowercase
- versions of letters to be equivalent when matching.
-
- If REG_NOSUB is set, then when PREG is passed to regexec, that
- routine will report only success or failure, and nothing about the
- registers.
-
- It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
- the return codes and their meanings.) */
-
-int
-regcomp (preg, pattern, cflags)
- regex_t *__restrict preg;
- const char *__restrict pattern;
- int cflags;
-{
- reg_errcode_t ret;
- reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED
- : RE_SYNTAX_POSIX_BASIC);
-
- preg->buffer = NULL;
- preg->allocated = 0;
- preg->used = 0;
-
- /* Try to allocate space for the fastmap. */
- preg->fastmap = re_malloc (char, SBC_MAX);
- if (BE (preg->fastmap == NULL, 0))
- return REG_ESPACE;
-
- syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0;
-
- /* If REG_NEWLINE is set, newlines are treated differently. */
- if (cflags & REG_NEWLINE)
- { /* REG_NEWLINE implies neither . nor [^...] match newline. */
- syntax &= ~RE_DOT_NEWLINE;
- syntax |= RE_HAT_LISTS_NOT_NEWLINE;
- /* It also changes the matching behavior. */
- preg->newline_anchor = 1;
- }
- else
- preg->newline_anchor = 0;
- preg->no_sub = !!(cflags & REG_NOSUB);
- preg->translate = NULL;
-
- ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);
-
- /* POSIX doesn't distinguish between an unmatched open-group and an
- unmatched close-group: both are REG_EPAREN. */
- if (ret == REG_ERPAREN)
- ret = REG_EPAREN;
-
- /* We have already checked preg->fastmap != NULL. */
- if (BE (ret == REG_NOERROR, 1))
- /* Compute the fastmap now, since regexec cannot modify the pattern
- buffer. This function never fails in this implementation. */
- (void) re_compile_fastmap (preg);
- else
- {
- /* Some error occurred while compiling the expression. */
- re_free (preg->fastmap);
- preg->fastmap = NULL;
- }
-
- return (int) ret;
-}
-#ifdef _LIBC
-weak_alias (__regcomp, regcomp)
-#endif
-
-/* Returns a message corresponding to an error code, ERRCODE, returned
- from either regcomp or regexec. We don't use PREG here. */
-
-size_t
-regerror (errcode, preg, errbuf, errbuf_size)
- int errcode;
- const regex_t *__restrict preg;
- char *__restrict errbuf;
- size_t errbuf_size;
-{
- const char *msg;
- size_t msg_size;
-
- if (BE (errcode < 0
- || errcode >= (int) (sizeof (__re_error_msgid_idx)
- / sizeof (__re_error_msgid_idx[0])), 0))
- /* Only error codes returned by the rest of the code should be passed
- to this routine. If we are given anything else, or if other regex
- code generates an invalid error code, then the program has a bug.
- Dump core so we can fix it. */
- abort ();
-
- msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]);
-
- msg_size = strlen (msg) + 1; /* Includes the null. */
-
- if (BE (errbuf_size != 0, 1))
- {
- if (BE (msg_size > errbuf_size, 0))
- {
-#if defined HAVE_MEMPCPY || defined _LIBC
- *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
-#else
- memcpy (errbuf, msg, errbuf_size - 1);
- errbuf[errbuf_size - 1] = 0;
-#endif
- }
- else
- memcpy (errbuf, msg, msg_size);
- }
-
- return msg_size;
-}
-#ifdef _LIBC
-weak_alias (__regerror, regerror)
-#endif
-
-
-#ifdef RE_ENABLE_I18N
-/* This static array is used for the map to single-byte characters when
- UTF-8 is used. Otherwise we would allocate memory just to initialize
- it the same all the time. UTF-8 is the preferred encoding so this is
- a worthwhile optimization. */
-static const bitset_t utf8_sb_map =
-{
- /* Set the first 128 bits. */
- [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX
-};
-#endif
-
-
-static void
-free_dfa_content (re_dfa_t *dfa)
-{
- int i, j;
-
- if (dfa->nodes)
- for (i = 0; i < dfa->nodes_len; ++i)
- free_token (dfa->nodes + i);
- re_free (dfa->nexts);
- for (i = 0; i < dfa->nodes_len; ++i)
- {
- if (dfa->eclosures != NULL)
- re_node_set_free (dfa->eclosures + i);
- if (dfa->inveclosures != NULL)
- re_node_set_free (dfa->inveclosures + i);
- if (dfa->edests != NULL)
- re_node_set_free (dfa->edests + i);
- }
- re_free (dfa->edests);
- re_free (dfa->eclosures);
- re_free (dfa->inveclosures);
- re_free (dfa->nodes);
-
- if (dfa->state_table)
- for (i = 0; i <= dfa->state_hash_mask; ++i)
- {
- struct re_state_table_entry *entry = dfa->state_table + i;
- for (j = 0; j < entry->num; ++j)
- {
- re_dfastate_t *state = entry->array[j];
- free_state (state);
- }
- re_free (entry->array);
- }
- re_free (dfa->state_table);
-#ifdef RE_ENABLE_I18N
- if (dfa->sb_char != utf8_sb_map)
- re_free (dfa->sb_char);
-#endif
- re_free (dfa->subexp_map);
-#ifdef DEBUG
- re_free (dfa->re_str);
-#endif
-
- re_free (dfa);
-}
-
-
-/* Free dynamically allocated space used by PREG. */
-
-void
-regfree (preg)
- regex_t *preg;
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- if (BE (dfa != NULL, 1))
- free_dfa_content (dfa);
- preg->buffer = NULL;
- preg->allocated = 0;
-
- re_free (preg->fastmap);
- preg->fastmap = NULL;
-
- re_free (preg->translate);
- preg->translate = NULL;
-}
-#ifdef _LIBC
-weak_alias (__regfree, regfree)
-#endif
-
-/* Entry points compatible with 4.2 BSD regex library. We don't define
- them unless specifically requested. */
-
-#if defined _REGEX_RE_COMP || defined _LIBC
-
-/* BSD has one and only one pattern buffer. */
-static struct re_pattern_buffer re_comp_buf;
-
-char *
-# ifdef _LIBC
-/* Make these definitions weak in libc, so POSIX programs can redefine
- these names if they don't use our functions, and still use
- regcomp/regexec above without link errors. */
-weak_function
-# endif
-re_comp (s)
- const char *s;
-{
- reg_errcode_t ret;
- char *fastmap;
-
- if (!s)
- {
- if (!re_comp_buf.buffer)
- return gettext ("No previous regular expression");
- return 0;
- }
-
- if (re_comp_buf.buffer)
- {
- fastmap = re_comp_buf.fastmap;
- re_comp_buf.fastmap = NULL;
- __regfree (&re_comp_buf);
- memset (&re_comp_buf, '\0', sizeof (re_comp_buf));
- re_comp_buf.fastmap = fastmap;
- }
-
- if (re_comp_buf.fastmap == NULL)
- {
- re_comp_buf.fastmap = (char *) malloc (SBC_MAX);
- if (re_comp_buf.fastmap == NULL)
- return (char *) gettext (__re_error_msgid
- + __re_error_msgid_idx[(int) REG_ESPACE]);
- }
-
- /* Since `re_exec' always passes NULL for the `regs' argument, we
- don't need to initialize the pattern buffer fields which affect it. */
-
- /* Match anchors at newlines. */
- re_comp_buf.newline_anchor = 1;
-
- ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options);
-
- if (!ret)
- return NULL;
-
- /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */
- return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
-}
-
-#ifdef _LIBC
-libc_freeres_fn (free_mem)
-{
- __regfree (&re_comp_buf);
-}
-#endif
-
-#endif /* _REGEX_RE_COMP */
-
-/* Internal entry point.
- Compile the regular expression PATTERN, whose length is LENGTH.
- SYNTAX indicate regular expression's syntax. */
-
-static reg_errcode_t
-re_compile_internal (regex_t *preg, const char * pattern, size_t length,
- reg_syntax_t syntax)
-{
- reg_errcode_t err = REG_NOERROR;
- re_dfa_t *dfa;
- re_string_t regexp;
-
- /* Initialize the pattern buffer. */
- preg->fastmap_accurate = 0;
- preg->syntax = syntax;
- preg->not_bol = preg->not_eol = 0;
- preg->used = 0;
- preg->re_nsub = 0;
- preg->can_be_null = 0;
- preg->regs_allocated = REGS_UNALLOCATED;
-
- /* Initialize the dfa. */
- dfa = (re_dfa_t *) preg->buffer;
- if (BE (preg->allocated < sizeof (re_dfa_t), 0))
- {
- /* If zero allocated, but buffer is non-null, try to realloc
- enough space. This loses if buffer's address is bogus, but
- that is the user's responsibility. If ->buffer is NULL this
- is a simple allocation. */
- dfa = re_realloc (preg->buffer, re_dfa_t, 1);
- if (dfa == NULL)
- return REG_ESPACE;
- preg->allocated = sizeof (re_dfa_t);
- preg->buffer = (unsigned char *) dfa;
- }
- preg->used = sizeof (re_dfa_t);
-
- err = init_dfa (dfa, length);
- if (BE (err != REG_NOERROR, 0))
- {
- free_dfa_content (dfa);
- preg->buffer = NULL;
- preg->allocated = 0;
- return err;
- }
-#ifdef DEBUG
- /* Note: length+1 will not overflow since it is checked in init_dfa. */
- dfa->re_str = re_malloc (char, length + 1);
- strncpy (dfa->re_str, pattern, length + 1);
-#endif
-
- __libc_lock_init (dfa->lock);
-
- err = re_string_construct (&regexp, pattern, length, preg->translate,
- syntax & RE_ICASE, dfa);
- if (BE (err != REG_NOERROR, 0))
- {
- re_compile_internal_free_return:
- free_workarea_compile (preg);
- re_string_destruct (&regexp);
- free_dfa_content (dfa);
- preg->buffer = NULL;
- preg->allocated = 0;
- return err;
- }
-
- /* Parse the regular expression, and build a structure tree. */
- preg->re_nsub = 0;
- dfa->str_tree = parse (&regexp, preg, syntax, &err);
- if (BE (dfa->str_tree == NULL, 0))
- goto re_compile_internal_free_return;
-
- /* Analyze the tree and create the nfa. */
- err = analyze (preg);
- if (BE (err != REG_NOERROR, 0))
- goto re_compile_internal_free_return;
-
-#ifdef RE_ENABLE_I18N
- /* If possible, do searching in single byte encoding to speed things up. */
- if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL)
- optimize_utf8 (dfa);
-#endif
-
- /* Then create the initial state of the dfa. */
- err = create_initial_state (dfa);
-
- /* Release work areas. */
- free_workarea_compile (preg);
- re_string_destruct (&regexp);
-
- if (BE (err != REG_NOERROR, 0))
- {
- free_dfa_content (dfa);
- preg->buffer = NULL;
- preg->allocated = 0;
- }
-
- return err;
-}
-
-/* Initialize DFA. We use the length of the regular expression PAT_LEN
- as the initial length of some arrays. */
-
-static reg_errcode_t
-init_dfa (re_dfa_t *dfa, size_t pat_len)
-{
- unsigned int table_size;
-#ifndef _LIBC
- char *codeset_name;
-#endif
-
- memset (dfa, '\0', sizeof (re_dfa_t));
-
- /* Force allocation of str_tree_storage the first time. */
- dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
-
- /* Avoid overflows. */
- if (pat_len == SIZE_MAX)
- return REG_ESPACE;
-
- dfa->nodes_alloc = pat_len + 1;
- dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);
-
- /* table_size = 2 ^ ceil(log pat_len) */
- for (table_size = 1; ; table_size <<= 1)
- if (table_size > pat_len)
- break;
-
- dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
- dfa->state_hash_mask = table_size - 1;
-
- dfa->mb_cur_max = MB_CUR_MAX;
-#ifdef _LIBC
- if (dfa->mb_cur_max == 6
- && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
- dfa->is_utf8 = 1;
- dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
- != 0);
-#else
-# ifdef HAVE_LANGINFO_CODESET
- codeset_name = nl_langinfo (CODESET);
-# else
- codeset_name = getenv ("LC_ALL");
- if (codeset_name == NULL || codeset_name[0] == '\0')
- codeset_name = getenv ("LC_CTYPE");
- if (codeset_name == NULL || codeset_name[0] == '\0')
- codeset_name = getenv ("LANG");
- if (codeset_name == NULL)
- codeset_name = "";
- else if (strchr (codeset_name, '.') != NULL)
- codeset_name = strchr (codeset_name, '.') + 1;
-# endif
-
- if (strcasecmp (codeset_name, "UTF-8") == 0
- || strcasecmp (codeset_name, "UTF8") == 0)
- dfa->is_utf8 = 1;
-
- /* We check exhaustively in the loop below if this charset is a
- superset of ASCII. */
- dfa->map_notascii = 0;
-#endif
-
-#ifdef RE_ENABLE_I18N
- if (dfa->mb_cur_max > 1)
- {
- if (dfa->is_utf8)
- dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
- else
- {
- int i, j, ch;
-
- dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
- if (BE (dfa->sb_char == NULL, 0))
- return REG_ESPACE;
-
- /* Set the bits corresponding to single byte chars. */
- for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
- for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
- {
- wint_t wch = __btowc (ch);
- if (wch != WEOF)
- dfa->sb_char[i] |= (bitset_word_t) 1 << j;
-# ifndef _LIBC
- if (isascii (ch) && wch != ch)
- dfa->map_notascii = 1;
-# endif
- }
- }
- }
-#endif
-
- if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0))
- return REG_ESPACE;
- return REG_NOERROR;
-}
-
-/* Initialize WORD_CHAR table, which indicate which character is
- "word". In this case "word" means that it is the word construction
- character used by some operators like "\<", "\>", etc. */
-
-static void
-internal_function
-init_word_char (re_dfa_t *dfa)
-{
- int i, j, ch;
- dfa->word_ops_used = 1;
- for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
- for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
- if (isalnum (ch) || ch == '_')
- dfa->word_char[i] |= (bitset_word_t) 1 << j;
-}
-
-/* Free the work area which are only used while compiling. */
-
-static void
-free_workarea_compile (regex_t *preg)
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- bin_tree_storage_t *storage, *next;
- for (storage = dfa->str_tree_storage; storage; storage = next)
- {
- next = storage->next;
- re_free (storage);
- }
- dfa->str_tree_storage = NULL;
- dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
- dfa->str_tree = NULL;
- re_free (dfa->org_indices);
- dfa->org_indices = NULL;
-}
-
-/* Create initial states for all contexts. */
-
-static reg_errcode_t
-create_initial_state (re_dfa_t *dfa)
-{
- int first, i;
- reg_errcode_t err;
- re_node_set init_nodes;
-
- /* Initial states have the epsilon closure of the node which is
- the first node of the regular expression. */
- first = dfa->str_tree->first->node_idx;
- dfa->init_node = first;
- err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- /* The back-references which are in initial states can epsilon transit,
- since in this case all of the subexpressions can be null.
- Then we add epsilon closures of the nodes which are the next nodes of
- the back-references. */
- if (dfa->nbackref > 0)
- for (i = 0; i < init_nodes.nelem; ++i)
- {
- int node_idx = init_nodes.elems[i];
- re_token_type_t type = dfa->nodes[node_idx].type;
-
- int clexp_idx;
- if (type != OP_BACK_REF)
- continue;
- for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)
- {
- re_token_t *clexp_node;
- clexp_node = dfa->nodes + init_nodes.elems[clexp_idx];
- if (clexp_node->type == OP_CLOSE_SUBEXP
- && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx)
- break;
- }
- if (clexp_idx == init_nodes.nelem)
- continue;
-
- if (type == OP_BACK_REF)
- {
- int dest_idx = dfa->edests[node_idx].elems[0];
- if (!re_node_set_contains (&init_nodes, dest_idx))
- {
- re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);
- i = 0;
- }
- }
- }
-
- /* It must be the first time to invoke acquire_state. */
- dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0);
- /* We don't check ERR here, since the initial state must not be NULL. */
- if (BE (dfa->init_state == NULL, 0))
- return err;
- if (dfa->init_state->has_constraint)
- {
- dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,
- CONTEXT_WORD);
- dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes,
- CONTEXT_NEWLINE);
- dfa->init_state_begbuf = re_acquire_state_context (&err, dfa,
- &init_nodes,
- CONTEXT_NEWLINE
- | CONTEXT_BEGBUF);
- if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL
- || dfa->init_state_begbuf == NULL, 0))
- return err;
- }
- else
- dfa->init_state_word = dfa->init_state_nl
- = dfa->init_state_begbuf = dfa->init_state;
-
- re_node_set_free (&init_nodes);
- return REG_NOERROR;
-}
-
-#ifdef RE_ENABLE_I18N
-/* If it is possible to do searching in single byte encoding instead of UTF-8
- to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change
- DFA nodes where needed. */
-
-static void
-optimize_utf8 (re_dfa_t *dfa)
-{
- int node, i, mb_chars = 0, has_period = 0;
-
- for (node = 0; node < dfa->nodes_len; ++node)
- switch (dfa->nodes[node].type)
- {
- case CHARACTER:
- if (dfa->nodes[node].opr.c >= 0x80)
- mb_chars = 1;
- break;
- case ANCHOR:
- switch (dfa->nodes[node].opr.idx)
- {
- case LINE_FIRST:
- case LINE_LAST:
- case BUF_FIRST:
- case BUF_LAST:
- break;
- default:
- /* Word anchors etc. cannot be handled. */
- return;
- }
- break;
- case OP_PERIOD:
- has_period = 1;
- break;
- case OP_BACK_REF:
- case OP_ALT:
- case END_OF_RE:
- case OP_DUP_ASTERISK:
- case OP_OPEN_SUBEXP:
- case OP_CLOSE_SUBEXP:
- break;
- case COMPLEX_BRACKET:
- return;
- case SIMPLE_BRACKET:
- /* Just double check. The non-ASCII range starts at 0x80. */
- assert (0x80 % BITSET_WORD_BITS == 0);
- for (i = 0x80 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i)
- if (dfa->nodes[node].opr.sbcset[i])
- return;
- break;
- default:
- abort ();
- }
-
- if (mb_chars || has_period)
- for (node = 0; node < dfa->nodes_len; ++node)
- {
- if (dfa->nodes[node].type == CHARACTER
- && dfa->nodes[node].opr.c >= 0x80)
- dfa->nodes[node].mb_partial = 0;
- else if (dfa->nodes[node].type == OP_PERIOD)
- dfa->nodes[node].type = OP_UTF8_PERIOD;
- }
-
- /* The search can be in single byte locale. */
- dfa->mb_cur_max = 1;
- dfa->is_utf8 = 0;
- dfa->has_mb_node = dfa->nbackref > 0 || has_period;
-}
-#endif
-
-/* Analyze the structure tree, and calculate "first", "next", "edest",
- "eclosure", and "inveclosure". */
-
-static reg_errcode_t
-analyze (regex_t *preg)
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- reg_errcode_t ret;
-
- /* Allocate arrays. */
- dfa->nexts = re_malloc (int, dfa->nodes_alloc);
- dfa->org_indices = re_malloc (int, dfa->nodes_alloc);
- dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
- dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
- if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL
- || dfa->eclosures == NULL, 0))
- return REG_ESPACE;
-
- dfa->subexp_map = re_malloc (int, preg->re_nsub);
- if (dfa->subexp_map != NULL)
- {
- int i;
- for (i = 0; i < preg->re_nsub; i++)
- dfa->subexp_map[i] = i;
- preorder (dfa->str_tree, optimize_subexps, dfa);
- for (i = 0; i < preg->re_nsub; i++)
- if (dfa->subexp_map[i] != i)
- break;
- if (i == preg->re_nsub)
- {
- free (dfa->subexp_map);
- dfa->subexp_map = NULL;
- }
- }
-
- ret = postorder (dfa->str_tree, lower_subexps, preg);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
- ret = postorder (dfa->str_tree, calc_first, dfa);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
- preorder (dfa->str_tree, calc_next, dfa);
- ret = preorder (dfa->str_tree, link_nfa_nodes, dfa);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
- ret = calc_eclosure (dfa);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
-
- /* We only need this during the prune_impossible_nodes pass in regexec.c;
- skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */
- if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match)
- || dfa->nbackref)
- {
- dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len);
- if (BE (dfa->inveclosures == NULL, 0))
- return REG_ESPACE;
- ret = calc_inveclosure (dfa);
- }
-
- return ret;
-}
-
-/* Our parse trees are very unbalanced, so we cannot use a stack to
- implement parse tree visits. Instead, we use parent pointers and
- some hairy code in these two functions. */
-static reg_errcode_t
-postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
- void *extra)
-{
- bin_tree_t *node, *prev;
-
- for (node = root; ; )
- {
- /* Descend down the tree, preferably to the left (or to the right
- if that's the only child). */
- while (node->left || node->right)
- if (node->left)
- node = node->left;
- else
- node = node->right;
-
- do
- {
- reg_errcode_t err = fn (extra, node);
- if (BE (err != REG_NOERROR, 0))
- return err;
- if (node->parent == NULL)
- return REG_NOERROR;
- prev = node;
- node = node->parent;
- }
- /* Go up while we have a node that is reached from the right. */
- while (node->right == prev || node->right == NULL);
- node = node->right;
- }
-}
-
-static reg_errcode_t
-preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
- void *extra)
-{
- bin_tree_t *node;
-
- for (node = root; ; )
- {
- reg_errcode_t err = fn (extra, node);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- /* Go to the left node, or up and to the right. */
- if (node->left)
- node = node->left;
- else
- {
- bin_tree_t *prev = NULL;
- while (node->right == prev || node->right == NULL)
- {
- prev = node;
- node = node->parent;
- if (!node)
- return REG_NOERROR;
- }
- node = node->right;
- }
- }
-}
-
-/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell
- re_search_internal to map the inner one's opr.idx to this one's. Adjust
- backreferences as well. Requires a preorder visit. */
-static reg_errcode_t
-optimize_subexps (void *extra, bin_tree_t *node)
-{
- re_dfa_t *dfa = (re_dfa_t *) extra;
-
- if (node->token.type == OP_BACK_REF && dfa->subexp_map)
- {
- int idx = node->token.opr.idx;
- node->token.opr.idx = dfa->subexp_map[idx];
- dfa->used_bkref_map |= 1 << node->token.opr.idx;
- }
-
- else if (node->token.type == SUBEXP
- && node->left && node->left->token.type == SUBEXP)
- {
- int other_idx = node->left->token.opr.idx;
-
- node->left = node->left->left;
- if (node->left)
- node->left->parent = node;
-
- dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx];
- if (other_idx < BITSET_WORD_BITS)
- dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx);
- }
-
- return REG_NOERROR;
-}
-
-/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation
- of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */
-static reg_errcode_t
-lower_subexps (void *extra, bin_tree_t *node)
-{
- regex_t *preg = (regex_t *) extra;
- reg_errcode_t err = REG_NOERROR;
-
- if (node->left && node->left->token.type == SUBEXP)
- {
- node->left = lower_subexp (&err, preg, node->left);
- if (node->left)
- node->left->parent = node;
- }
- if (node->right && node->right->token.type == SUBEXP)
- {
- node->right = lower_subexp (&err, preg, node->right);
- if (node->right)
- node->right->parent = node;
- }
-
- return err;
-}
-
-static bin_tree_t *
-lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node)
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- bin_tree_t *body = node->left;
- bin_tree_t *op, *cls, *tree1, *tree;
-
- if (preg->no_sub
- /* We do not optimize empty subexpressions, because otherwise we may
- have bad CONCAT nodes with NULL children. This is obviously not
- very common, so we do not lose much. An example that triggers
- this case is the sed "script" /\(\)/x. */
- && node->left != NULL
- && (node->token.opr.idx >= BITSET_WORD_BITS
- || !(dfa->used_bkref_map
- & ((bitset_word_t) 1 << node->token.opr.idx))))
- return node->left;
-
- /* Convert the SUBEXP node to the concatenation of an
- OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */
- op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP);
- cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP);
- tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls;
- tree = create_tree (dfa, op, tree1, CONCAT);
- if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
-
- op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx;
- op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp;
- return tree;
-}
-
-/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton
- nodes. Requires a postorder visit. */
-static reg_errcode_t
-calc_first (void *extra, bin_tree_t *node)
-{
- re_dfa_t *dfa = (re_dfa_t *) extra;
- if (node->token.type == CONCAT)
- {
- node->first = node->left->first;
- node->node_idx = node->left->node_idx;
- }
- else
- {
- node->first = node;
- node->node_idx = re_dfa_add_node (dfa, node->token);
- if (BE (node->node_idx == -1, 0))
- return REG_ESPACE;
- }
- return REG_NOERROR;
-}
-
-/* Pass 2: compute NEXT on the tree. Preorder visit. */
-static reg_errcode_t
-calc_next (void *extra, bin_tree_t *node)
-{
- switch (node->token.type)
- {
- case OP_DUP_ASTERISK:
- node->left->next = node;
- break;
- case CONCAT:
- node->left->next = node->right->first;
- node->right->next = node->next;
- break;
- default:
- if (node->left)
- node->left->next = node->next;
- if (node->right)
- node->right->next = node->next;
- break;
- }
- return REG_NOERROR;
-}
-
-/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */
-static reg_errcode_t
-link_nfa_nodes (void *extra, bin_tree_t *node)
-{
- re_dfa_t *dfa = (re_dfa_t *) extra;
- int idx = node->node_idx;
- reg_errcode_t err = REG_NOERROR;
-
- switch (node->token.type)
- {
- case CONCAT:
- break;
-
- case END_OF_RE:
- assert (node->next == NULL);
- break;
-
- case OP_DUP_ASTERISK:
- case OP_ALT:
- {
- int left, right;
- dfa->has_plural_match = 1;
- if (node->left != NULL)
- left = node->left->first->node_idx;
- else
- left = node->next->node_idx;
- if (node->right != NULL)
- right = node->right->first->node_idx;
- else
- right = node->next->node_idx;
- assert (left > -1);
- assert (right > -1);
- err = re_node_set_init_2 (dfa->edests + idx, left, right);
- }
- break;
-
- case ANCHOR:
- case OP_OPEN_SUBEXP:
- case OP_CLOSE_SUBEXP:
- err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx);
- break;
-
- case OP_BACK_REF:
- dfa->nexts[idx] = node->next->node_idx;
- if (node->token.type == OP_BACK_REF)
- re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]);
- break;
-
- default:
- assert (!IS_EPSILON_NODE (node->token.type));
- dfa->nexts[idx] = node->next->node_idx;
- break;
- }
-
- return err;
-}
-
-/* Duplicate the epsilon closure of the node ROOT_NODE.
- Note that duplicated nodes have constraint INIT_CONSTRAINT in addition
- to their own constraint. */
-
-static reg_errcode_t
-internal_function
-duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
- int root_node, unsigned int init_constraint)
-{
- int org_node, clone_node, ret;
- unsigned int constraint = init_constraint;
- for (org_node = top_org_node, clone_node = top_clone_node;;)
- {
- int org_dest, clone_dest;
- if (dfa->nodes[org_node].type == OP_BACK_REF)
- {
- /* If the back reference epsilon-transit, its destination must
- also have the constraint. Then duplicate the epsilon closure
- of the destination of the back reference, and store it in
- edests of the back reference. */
- org_dest = dfa->nexts[org_node];
- re_node_set_empty (dfa->edests + clone_node);
- clone_dest = duplicate_node (dfa, org_dest, constraint);
- if (BE (clone_dest == -1, 0))
- return REG_ESPACE;
- dfa->nexts[clone_node] = dfa->nexts[org_node];
- ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
- if (BE (ret < 0, 0))
- return REG_ESPACE;
- }
- else if (dfa->edests[org_node].nelem == 0)
- {
- /* In case of the node can't epsilon-transit, don't duplicate the
- destination and store the original destination as the
- destination of the node. */
- dfa->nexts[clone_node] = dfa->nexts[org_node];
- break;
- }
- else if (dfa->edests[org_node].nelem == 1)
- {
- /* In case of the node can epsilon-transit, and it has only one
- destination. */
- org_dest = dfa->edests[org_node].elems[0];
- re_node_set_empty (dfa->edests + clone_node);
- if (dfa->nodes[org_node].type == ANCHOR)
- {
- /* In case of the node has another constraint, append it. */
- if (org_node == root_node && clone_node != org_node)
- {
- /* ...but if the node is root_node itself, it means the
- epsilon closure have a loop, then tie it to the
- destination of the root_node. */
- ret = re_node_set_insert (dfa->edests + clone_node,
- org_dest);
- if (BE (ret < 0, 0))
- return REG_ESPACE;
- break;
- }
- constraint |= dfa->nodes[org_node].opr.ctx_type;
- }
- clone_dest = duplicate_node (dfa, org_dest, constraint);
- if (BE (clone_dest == -1, 0))
- return REG_ESPACE;
- ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
- if (BE (ret < 0, 0))
- return REG_ESPACE;
- }
- else /* dfa->edests[org_node].nelem == 2 */
- {
- /* In case of the node can epsilon-transit, and it has two
- destinations. In the bin_tree_t and DFA, that's '|' and '*'. */
- org_dest = dfa->edests[org_node].elems[0];
- re_node_set_empty (dfa->edests + clone_node);
- /* Search for a duplicated node which satisfies the constraint. */
- clone_dest = search_duplicated_node (dfa, org_dest, constraint);
- if (clone_dest == -1)
- {
- /* There are no such a duplicated node, create a new one. */
- reg_errcode_t err;
- clone_dest = duplicate_node (dfa, org_dest, constraint);
- if (BE (clone_dest == -1, 0))
- return REG_ESPACE;
- ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
- if (BE (ret < 0, 0))
- return REG_ESPACE;
- err = duplicate_node_closure (dfa, org_dest, clone_dest,
- root_node, constraint);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- else
- {
- /* There are a duplicated node which satisfy the constraint,
- use it to avoid infinite loop. */
- ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
- if (BE (ret < 0, 0))
- return REG_ESPACE;
- }
-
- org_dest = dfa->edests[org_node].elems[1];
- clone_dest = duplicate_node (dfa, org_dest, constraint);
- if (BE (clone_dest == -1, 0))
- return REG_ESPACE;
- ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
- if (BE (ret < 0, 0))
- return REG_ESPACE;
- }
- org_node = org_dest;
- clone_node = clone_dest;
- }
- return REG_NOERROR;
-}
-
-/* Search for a node which is duplicated from the node ORG_NODE, and
- satisfies the constraint CONSTRAINT. */
-
-static int
-search_duplicated_node (const re_dfa_t *dfa, int org_node,
- unsigned int constraint)
-{
- int idx;
- for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx)
- {
- if (org_node == dfa->org_indices[idx]
- && constraint == dfa->nodes[idx].constraint)
- return idx; /* Found. */
- }
- return -1; /* Not found. */
-}
-
-/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.
- Return the index of the new node, or -1 if insufficient storage is
- available. */
-
-static int
-duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint)
-{
- int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
- if (BE (dup_idx != -1, 1))
- {
- dfa->nodes[dup_idx].constraint = constraint;
- if (dfa->nodes[org_idx].type == ANCHOR)
- dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type;
- dfa->nodes[dup_idx].duplicated = 1;
-
- /* Store the index of the original node. */
- dfa->org_indices[dup_idx] = org_idx;
- }
- return dup_idx;
-}
-
-static reg_errcode_t
-calc_inveclosure (re_dfa_t *dfa)
-{
- int src, idx, ret;
- for (idx = 0; idx < dfa->nodes_len; ++idx)
- re_node_set_init_empty (dfa->inveclosures + idx);
-
- for (src = 0; src < dfa->nodes_len; ++src)
- {
- int *elems = dfa->eclosures[src].elems;
- for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
- {
- ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);
- if (BE (ret == -1, 0))
- return REG_ESPACE;
- }
- }
-
- return REG_NOERROR;
-}
-
-/* Calculate "eclosure" for all the node in DFA. */
-
-static reg_errcode_t
-calc_eclosure (re_dfa_t *dfa)
-{
- int node_idx, incomplete;
-#ifdef DEBUG
- assert (dfa->nodes_len > 0);
-#endif
- incomplete = 0;
- /* For each nodes, calculate epsilon closure. */
- for (node_idx = 0; ; ++node_idx)
- {
- reg_errcode_t err;
- re_node_set eclosure_elem;
- if (node_idx == dfa->nodes_len)
- {
- if (!incomplete)
- break;
- incomplete = 0;
- node_idx = 0;
- }
-
-#ifdef DEBUG
- assert (dfa->eclosures[node_idx].nelem != -1);
-#endif
-
- /* If we have already calculated, skip it. */
- if (dfa->eclosures[node_idx].nelem != 0)
- continue;
- /* Calculate epsilon closure of `node_idx'. */
- err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- if (dfa->eclosures[node_idx].nelem == 0)
- {
- incomplete = 1;
- re_node_set_free (&eclosure_elem);
- }
- }
- return REG_NOERROR;
-}
-
-/* Calculate epsilon closure of NODE. */
-
-static reg_errcode_t
-calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
-{
- reg_errcode_t err;
- unsigned int constraint;
- int i, incomplete;
- re_node_set eclosure;
- incomplete = 0;
- err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- /* This indicates that we are calculating this node now.
- We reference this value to avoid infinite loop. */
- dfa->eclosures[node].nelem = -1;
-
- constraint = ((dfa->nodes[node].type == ANCHOR)
- ? dfa->nodes[node].opr.ctx_type : 0);
- /* If the current node has constraints, duplicate all nodes.
- Since they must inherit the constraints. */
- if (constraint
- && dfa->edests[node].nelem
- && !dfa->nodes[dfa->edests[node].elems[0]].duplicated)
- {
- err = duplicate_node_closure (dfa, node, node, node, constraint);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
-
- /* Expand each epsilon destination nodes. */
- if (IS_EPSILON_NODE(dfa->nodes[node].type))
- for (i = 0; i < dfa->edests[node].nelem; ++i)
- {
- re_node_set eclosure_elem;
- int edest = dfa->edests[node].elems[i];
- /* If calculating the epsilon closure of `edest' is in progress,
- return intermediate result. */
- if (dfa->eclosures[edest].nelem == -1)
- {
- incomplete = 1;
- continue;
- }
- /* If we haven't calculated the epsilon closure of `edest' yet,
- calculate now. Otherwise use calculated epsilon closure. */
- if (dfa->eclosures[edest].nelem == 0)
- {
- err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- else
- eclosure_elem = dfa->eclosures[edest];
- /* Merge the epsilon closure of `edest'. */
- re_node_set_merge (&eclosure, &eclosure_elem);
- /* If the epsilon closure of `edest' is incomplete,
- the epsilon closure of this node is also incomplete. */
- if (dfa->eclosures[edest].nelem == 0)
- {
- incomplete = 1;
- re_node_set_free (&eclosure_elem);
- }
- }
-
- /* Epsilon closures include itself. */
- re_node_set_insert (&eclosure, node);
- if (incomplete && !root)
- dfa->eclosures[node].nelem = 0;
- else
- dfa->eclosures[node] = eclosure;
- *new_set = eclosure;
- return REG_NOERROR;
-}
-
-/* Functions for token which are used in the parser. */
-
-/* Fetch a token from INPUT.
- We must not use this function inside bracket expressions. */
-
-static void
-internal_function
-fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax)
-{
- re_string_skip_bytes (input, peek_token (result, input, syntax));
-}
-
-/* Peek a token from INPUT, and return the length of the token.
- We must not use this function inside bracket expressions. */
-
-static int
-internal_function
-peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
-{
- unsigned char c;
-
- if (re_string_eoi (input))
- {
- token->type = END_OF_RE;
- return 0;
- }
-
- c = re_string_peek_byte (input, 0);
- token->opr.c = c;
-
- token->word_char = 0;
-#ifdef RE_ENABLE_I18N
- token->mb_partial = 0;
- if (input->mb_cur_max > 1 &&
- !re_string_first_byte (input, re_string_cur_idx (input)))
- {
- token->type = CHARACTER;
- token->mb_partial = 1;
- return 1;
- }
-#endif
- if (c == '\\')
- {
- unsigned char c2;
- if (re_string_cur_idx (input) + 1 >= re_string_length (input))
- {
- token->type = BACK_SLASH;
- return 1;
- }
-
- c2 = re_string_peek_byte_case (input, 1);
- token->opr.c = c2;
- token->type = CHARACTER;
-#ifdef RE_ENABLE_I18N
- if (input->mb_cur_max > 1)
- {
- wint_t wc = re_string_wchar_at (input,
- re_string_cur_idx (input) + 1);
- token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
- }
- else
-#endif
- token->word_char = IS_WORD_CHAR (c2) != 0;
-
- switch (c2)
- {
- case '|':
- if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR))
- token->type = OP_ALT;
- break;
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- if (!(syntax & RE_NO_BK_REFS))
- {
- token->type = OP_BACK_REF;
- token->opr.idx = c2 - '1';
- }
- break;
- case '<':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.ctx_type = WORD_FIRST;
- }
- break;
- case '>':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.ctx_type = WORD_LAST;
- }
- break;
- case 'b':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.ctx_type = WORD_DELIM;
- }
- break;
- case 'B':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.ctx_type = NOT_WORD_DELIM;
- }
- break;
- case 'w':
- if (!(syntax & RE_NO_GNU_OPS))
- token->type = OP_WORD;
- break;
- case 'W':
- if (!(syntax & RE_NO_GNU_OPS))
- token->type = OP_NOTWORD;
- break;
- case 's':
- if (!(syntax & RE_NO_GNU_OPS))
- token->type = OP_SPACE;
- break;
- case 'S':
- if (!(syntax & RE_NO_GNU_OPS))
- token->type = OP_NOTSPACE;
- break;
- case '`':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.ctx_type = BUF_FIRST;
- }
- break;
- case '\'':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.ctx_type = BUF_LAST;
- }
- break;
- case '(':
- if (!(syntax & RE_NO_BK_PARENS))
- token->type = OP_OPEN_SUBEXP;
- break;
- case ')':
- if (!(syntax & RE_NO_BK_PARENS))
- token->type = OP_CLOSE_SUBEXP;
- break;
- case '+':
- if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
- token->type = OP_DUP_PLUS;
- break;
- case '?':
- if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
- token->type = OP_DUP_QUESTION;
- break;
- case '{':
- if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
- token->type = OP_OPEN_DUP_NUM;
- break;
- case '}':
- if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
- token->type = OP_CLOSE_DUP_NUM;
- break;
- default:
- break;
- }
- return 2;
- }
-
- token->type = CHARACTER;
-#ifdef RE_ENABLE_I18N
- if (input->mb_cur_max > 1)
- {
- wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
- token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
- }
- else
-#endif
- token->word_char = IS_WORD_CHAR (token->opr.c);
-
- switch (c)
- {
- case '\n':
- if (syntax & RE_NEWLINE_ALT)
- token->type = OP_ALT;
- break;
- case '|':
- if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR))
- token->type = OP_ALT;
- break;
- case '*':
- token->type = OP_DUP_ASTERISK;
- break;
- case '+':
- if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
- token->type = OP_DUP_PLUS;
- break;
- case '?':
- if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
- token->type = OP_DUP_QUESTION;
- break;
- case '{':
- if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
- token->type = OP_OPEN_DUP_NUM;
- break;
- case '}':
- if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
- token->type = OP_CLOSE_DUP_NUM;
- break;
- case '(':
- if (syntax & RE_NO_BK_PARENS)
- token->type = OP_OPEN_SUBEXP;
- break;
- case ')':
- if (syntax & RE_NO_BK_PARENS)
- token->type = OP_CLOSE_SUBEXP;
- break;
- case '[':
- token->type = OP_OPEN_BRACKET;
- break;
- case '.':
- token->type = OP_PERIOD;
- break;
- case '^':
- if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) &&
- re_string_cur_idx (input) != 0)
- {
- char prev = re_string_peek_byte (input, -1);
- if (!(syntax & RE_NEWLINE_ALT) || prev != '\n')
- break;
- }
- token->type = ANCHOR;
- token->opr.ctx_type = LINE_FIRST;
- break;
- case '$':
- if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) &&
- re_string_cur_idx (input) + 1 != re_string_length (input))
- {
- re_token_t next;
- re_string_skip_bytes (input, 1);
- peek_token (&next, input, syntax);
- re_string_skip_bytes (input, -1);
- if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP)
- break;
- }
- token->type = ANCHOR;
- token->opr.ctx_type = LINE_LAST;
- break;
- default:
- break;
- }
- return 1;
-}
-
-/* Peek a token from INPUT, and return the length of the token.
- We must not use this function out of bracket expressions. */
-
-static int
-internal_function
-peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
-{
- unsigned char c;
- if (re_string_eoi (input))
- {
- token->type = END_OF_RE;
- return 0;
- }
- c = re_string_peek_byte (input, 0);
- token->opr.c = c;
-
-#ifdef RE_ENABLE_I18N
- if (input->mb_cur_max > 1 &&
- !re_string_first_byte (input, re_string_cur_idx (input)))
- {
- token->type = CHARACTER;
- return 1;
- }
-#endif /* RE_ENABLE_I18N */
-
- if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS)
- && re_string_cur_idx (input) + 1 < re_string_length (input))
- {
- /* In this case, '\' escape a character. */
- unsigned char c2;
- re_string_skip_bytes (input, 1);
- c2 = re_string_peek_byte (input, 0);
- token->opr.c = c2;
- token->type = CHARACTER;
- return 1;
- }
- if (c == '[') /* '[' is a special char in a bracket exps. */
- {
- unsigned char c2;
- int token_len;
- if (re_string_cur_idx (input) + 1 < re_string_length (input))
- c2 = re_string_peek_byte (input, 1);
- else
- c2 = 0;
- token->opr.c = c2;
- token_len = 2;
- switch (c2)
- {
- case '.':
- token->type = OP_OPEN_COLL_ELEM;
- break;
- case '=':
- token->type = OP_OPEN_EQUIV_CLASS;
- break;
- case ':':
- if (syntax & RE_CHAR_CLASSES)
- {
- token->type = OP_OPEN_CHAR_CLASS;
- break;
- }
- /* else fall through. */
- default:
- token->type = CHARACTER;
- token->opr.c = c;
- token_len = 1;
- break;
- }
- return token_len;
- }
- switch (c)
- {
- case '-':
- token->type = OP_CHARSET_RANGE;
- break;
- case ']':
- token->type = OP_CLOSE_BRACKET;
- break;
- case '^':
- token->type = OP_NON_MATCH_LIST;
- break;
- default:
- token->type = CHARACTER;
- }
- return 1;
-}
-
-/* Functions for parser. */
-
-/* Entry point of the parser.
- Parse the regular expression REGEXP and return the structure tree.
- If an error is occured, ERR is set by error code, and return NULL.
- This function build the following tree, from regular expression <reg_exp>:
- CAT
- / \
- / \
- <reg_exp> EOR
-
- CAT means concatenation.
- EOR means end of regular expression. */
-
-static bin_tree_t *
-parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax,
- reg_errcode_t *err)
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- bin_tree_t *tree, *eor, *root;
- re_token_t current_token;
- dfa->syntax = syntax;
- fetch_token (&current_token, regexp, syntax | RE_CARET_ANCHORS_HERE);
- tree = parse_reg_exp (regexp, preg, &current_token, syntax, 0, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- eor = create_tree (dfa, NULL, NULL, END_OF_RE);
- if (tree != NULL)
- root = create_tree (dfa, tree, eor, CONCAT);
- else
- root = eor;
- if (BE (eor == NULL || root == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
- return root;
-}
-
-/* This function build the following tree, from regular expression
- <branch1>|<branch2>:
- ALT
- / \
- / \
- <branch1> <branch2>
-
- ALT means alternative, which represents the operator `|'. */
-
-static bin_tree_t *
-parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
- reg_syntax_t syntax, int nest, reg_errcode_t *err)
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- bin_tree_t *tree, *branch = NULL;
- tree = parse_branch (regexp, preg, token, syntax, nest, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
-
- while (token->type == OP_ALT)
- {
- fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
- if (token->type != OP_ALT && token->type != END_OF_RE
- && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
- {
- branch = parse_branch (regexp, preg, token, syntax, nest, err);
- if (BE (*err != REG_NOERROR && branch == NULL, 0))
- return NULL;
- }
- else
- branch = NULL;
- tree = create_tree (dfa, tree, branch, OP_ALT);
- if (BE (tree == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
- }
- return tree;
-}
-
-/* This function build the following tree, from regular expression
- <exp1><exp2>:
- CAT
- / \
- / \
- <exp1> <exp2>
-
- CAT means concatenation. */
-
-static bin_tree_t *
-parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
- reg_syntax_t syntax, int nest, reg_errcode_t *err)
-{
- bin_tree_t *tree, *exp;
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- tree = parse_expression (regexp, preg, token, syntax, nest, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
-
- while (token->type != OP_ALT && token->type != END_OF_RE
- && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
- {
- exp = parse_expression (regexp, preg, token, syntax, nest, err);
- if (BE (*err != REG_NOERROR && exp == NULL, 0))
- {
- return NULL;
- }
- if (tree != NULL && exp != NULL)
- {
- tree = create_tree (dfa, tree, exp, CONCAT);
- if (tree == NULL)
- {
- *err = REG_ESPACE;
- return NULL;
- }
- }
- else if (tree == NULL)
- tree = exp;
- /* Otherwise exp == NULL, we don't need to create new tree. */
- }
- return tree;
-}
-
-/* This function build the following tree, from regular expression a*:
- *
- |
- a
-*/
-
-static bin_tree_t *
-parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
- reg_syntax_t syntax, int nest, reg_errcode_t *err)
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- bin_tree_t *tree;
- switch (token->type)
- {
- case CHARACTER:
- tree = create_token_tree (dfa, NULL, NULL, token);
- if (BE (tree == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
-#ifdef RE_ENABLE_I18N
- if (dfa->mb_cur_max > 1)
- {
- while (!re_string_eoi (regexp)
- && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
- {
- bin_tree_t *mbc_remain;
- fetch_token (token, regexp, syntax);
- mbc_remain = create_token_tree (dfa, NULL, NULL, token);
- tree = create_tree (dfa, tree, mbc_remain, CONCAT);
- if (BE (mbc_remain == NULL || tree == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
- }
- }
-#endif
- break;
- case OP_OPEN_SUBEXP:
- tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- break;
- case OP_OPEN_BRACKET:
- tree = parse_bracket_exp (regexp, dfa, token, syntax, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- break;
- case OP_BACK_REF:
- if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1))
- {
- *err = REG_ESUBREG;
- return NULL;
- }
- dfa->used_bkref_map |= 1 << token->opr.idx;
- tree = create_token_tree (dfa, NULL, NULL, token);
- if (BE (tree == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
- ++dfa->nbackref;
- dfa->has_mb_node = 1;
- break;
- case OP_OPEN_DUP_NUM:
- if (syntax & RE_CONTEXT_INVALID_DUP)
- {
- *err = REG_BADRPT;
- return NULL;
- }
- /* FALLTHROUGH */
- case OP_DUP_ASTERISK:
- case OP_DUP_PLUS:
- case OP_DUP_QUESTION:
- if (syntax & RE_CONTEXT_INVALID_OPS)
- {
- *err = REG_BADRPT;
- return NULL;
- }
- else if (syntax & RE_CONTEXT_INDEP_OPS)
- {
- fetch_token (token, regexp, syntax);
- return parse_expression (regexp, preg, token, syntax, nest, err);
- }
- /* else fall through */
- case OP_CLOSE_SUBEXP:
- if ((token->type == OP_CLOSE_SUBEXP) &&
- !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
- {
- *err = REG_ERPAREN;
- return NULL;
- }
- /* else fall through */
- case OP_CLOSE_DUP_NUM:
- /* We treat it as a normal character. */
-
- /* Then we can these characters as normal characters. */
- token->type = CHARACTER;
- /* mb_partial and word_char bits should be initialized already
- by peek_token. */
- tree = create_token_tree (dfa, NULL, NULL, token);
- if (BE (tree == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
- break;
- case ANCHOR:
- if ((token->opr.ctx_type
- & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST))
- && dfa->word_ops_used == 0)
- init_word_char (dfa);
- if (token->opr.ctx_type == WORD_DELIM
- || token->opr.ctx_type == NOT_WORD_DELIM)
- {
- bin_tree_t *tree_first, *tree_last;
- if (token->opr.ctx_type == WORD_DELIM)
- {
- token->opr.ctx_type = WORD_FIRST;
- tree_first = create_token_tree (dfa, NULL, NULL, token);
- token->opr.ctx_type = WORD_LAST;
- }
- else
- {
- token->opr.ctx_type = INSIDE_WORD;
- tree_first = create_token_tree (dfa, NULL, NULL, token);
- token->opr.ctx_type = INSIDE_NOTWORD;
- }
- tree_last = create_token_tree (dfa, NULL, NULL, token);
- tree = create_tree (dfa, tree_first, tree_last, OP_ALT);
- if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
- }
- else
- {
- tree = create_token_tree (dfa, NULL, NULL, token);
- if (BE (tree == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
- }
- /* We must return here, since ANCHORs can't be followed
- by repetition operators.
- eg. RE"^*" is invalid or "<ANCHOR(^)><CHAR(*)>",
- it must not be "<ANCHOR(^)><REPEAT(*)>". */
- fetch_token (token, regexp, syntax);
- return tree;
- case OP_PERIOD:
- tree = create_token_tree (dfa, NULL, NULL, token);
- if (BE (tree == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
- if (dfa->mb_cur_max > 1)
- dfa->has_mb_node = 1;
- break;
- case OP_WORD:
- case OP_NOTWORD:
- tree = build_charclass_op (dfa, regexp->trans,
- (const unsigned char *) "alnum",
- (const unsigned char *) "_",
- token->type == OP_NOTWORD, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- break;
- case OP_SPACE:
- case OP_NOTSPACE:
- tree = build_charclass_op (dfa, regexp->trans,
- (const unsigned char *) "space",
- (const unsigned char *) "",
- token->type == OP_NOTSPACE, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- break;
- case OP_ALT:
- case END_OF_RE:
- return NULL;
- case BACK_SLASH:
- *err = REG_EESCAPE;
- return NULL;
- default:
- /* Must not happen? */
-#ifdef DEBUG
- assert (0);
-#endif
- return NULL;
- }
- fetch_token (token, regexp, syntax);
-
- while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
- || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
- {
- tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- /* In BRE consecutive duplications are not allowed. */
- if ((syntax & RE_CONTEXT_INVALID_DUP)
- && (token->type == OP_DUP_ASTERISK
- || token->type == OP_OPEN_DUP_NUM))
- {
- *err = REG_BADRPT;
- return NULL;
- }
- }
-
- return tree;
-}
-
-/* This function build the following tree, from regular expression
- (<reg_exp>):
- SUBEXP
- |
- <reg_exp>
-*/
-
-static bin_tree_t *
-parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
- reg_syntax_t syntax, int nest, reg_errcode_t *err)
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- bin_tree_t *tree;
- size_t cur_nsub;
- cur_nsub = preg->re_nsub++;
-
- fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
-
- /* The subexpression may be a null string. */
- if (token->type == OP_CLOSE_SUBEXP)
- tree = NULL;
- else
- {
- tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);
- if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0))
- *err = REG_EPAREN;
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- }
-
- if (cur_nsub <= '9' - '1')
- dfa->completed_bkref_map |= 1 << cur_nsub;
-
- tree = create_tree (dfa, tree, NULL, SUBEXP);
- if (BE (tree == NULL, 0))
- {
- *err = REG_ESPACE;
- return NULL;
- }
- tree->token.opr.idx = cur_nsub;
- return tree;
-}
-
-/* This function parse repetition operators like "*", "+", "{1,3}" etc. */
-
-static bin_tree_t *
-parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
- re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err)
-{
- bin_tree_t *tree = NULL, *old_tree = NULL;
- int i, start, end, start_idx = re_string_cur_idx (regexp);
- re_token_t start_token = *token;
-
- if (token->type == OP_OPEN_DUP_NUM)
- {
- end = 0;
- start = fetch_number (regexp, token, syntax);
- if (start == -1)
- {
- if (token->type == CHARACTER && token->opr.c == ',')
- start = 0; /* We treat "{,m}" as "{0,m}". */
- else
- {
- *err = REG_BADBR; /* <re>{} is invalid. */
- return NULL;
- }
- }
- if (BE (start != -2, 1))
- {
- /* We treat "{n}" as "{n,n}". */
- end = ((token->type == OP_CLOSE_DUP_NUM) ? start
- : ((token->type == CHARACTER && token->opr.c == ',')
- ? fetch_number (regexp, token, syntax) : -2));
- }
- if (BE (start == -2 || end == -2, 0))
- {
- /* Invalid sequence. */
- if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0))
- {
- if (token->type == END_OF_RE)
- *err = REG_EBRACE;
- else
- *err = REG_BADBR;
-
- return NULL;
- }
-
- /* If the syntax bit is set, rollback. */
- re_string_set_index (regexp, start_idx);
- *token = start_token;
- token->type = CHARACTER;
- /* mb_partial and word_char bits should be already initialized by
- peek_token. */
- return elem;
- }
-
- if (BE (end != -1 && start > end, 0))
- {
- /* First number greater than second. */
- *err = REG_BADBR;
- return NULL;
- }
- }
- else
- {
- start = (token->type == OP_DUP_PLUS) ? 1 : 0;
- end = (token->type == OP_DUP_QUESTION) ? 1 : -1;
- }
-
- fetch_token (token, regexp, syntax);
-
- if (BE (elem == NULL, 0))
- return NULL;
- if (BE (start == 0 && end == 0, 0))
- {
- postorder (elem, free_tree, NULL);
- return NULL;
- }
-
- /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}". */
- if (BE (start > 0, 0))
- {
- tree = elem;
- for (i = 2; i <= start; ++i)
- {
- elem = duplicate_tree (elem, dfa);
- tree = create_tree (dfa, tree, elem, CONCAT);
- if (BE (elem == NULL || tree == NULL, 0))
- goto parse_dup_op_espace;
- }
-
- if (start == end)
- return tree;
-
- /* Duplicate ELEM before it is marked optional. */
- elem = duplicate_tree (elem, dfa);
- old_tree = tree;
- }
- else
- old_tree = NULL;
-
- if (elem->token.type == SUBEXP)
- postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx);
-
- tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT));
- if (BE (tree == NULL, 0))
- goto parse_dup_op_espace;
-
- /* This loop is actually executed only when end != -1,
- to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?... We have
- already created the start+1-th copy. */
- for (i = start + 2; i <= end; ++i)
- {
- elem = duplicate_tree (elem, dfa);
- tree = create_tree (dfa, tree, elem, CONCAT);
- if (BE (elem == NULL || tree == NULL, 0))
- goto parse_dup_op_espace;
-
- tree = create_tree (dfa, tree, NULL, OP_ALT);
- if (BE (tree == NULL, 0))
- goto parse_dup_op_espace;
- }
-
- if (old_tree)
- tree = create_tree (dfa, old_tree, tree, CONCAT);
-
- return tree;
-
- parse_dup_op_espace:
- *err = REG_ESPACE;
- return NULL;
-}
-
-/* Size of the names for collating symbol/equivalence_class/character_class.
- I'm not sure, but maybe enough. */
-#define BRACKET_NAME_BUF_SIZE 32
-
-#ifndef _LIBC
- /* Local function for parse_bracket_exp only used in case of NOT _LIBC.
- Build the range expression which starts from START_ELEM, and ends
- at END_ELEM. The result are written to MBCSET and SBCSET.
- RANGE_ALLOC is the allocated size of mbcset->range_starts, and
- mbcset->range_ends, is a pointer argument sinse we may
- update it. */
-
-static reg_errcode_t
-internal_function
-# ifdef RE_ENABLE_I18N
-build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc,
- bracket_elem_t *start_elem, bracket_elem_t *end_elem)
-# else /* not RE_ENABLE_I18N */
-build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
- bracket_elem_t *end_elem)
-# endif /* not RE_ENABLE_I18N */
-{
- unsigned int start_ch, end_ch;
- /* Equivalence Classes and Character Classes can't be a range start/end. */
- if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
- || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
- 0))
- return REG_ERANGE;
-
- /* We can handle no multi character collating elements without libc
- support. */
- if (BE ((start_elem->type == COLL_SYM
- && strlen ((char *) start_elem->opr.name) > 1)
- || (end_elem->type == COLL_SYM
- && strlen ((char *) end_elem->opr.name) > 1), 0))
- return REG_ECOLLATE;
-
-# ifdef RE_ENABLE_I18N
- {
- wchar_t wc;
- wint_t start_wc;
- wint_t end_wc;
- wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
-
- start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch
- : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
- : 0));
- end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch
- : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
- : 0));
- start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
- ? __btowc (start_ch) : start_elem->opr.wch);
- end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
- ? __btowc (end_ch) : end_elem->opr.wch);
- if (start_wc == WEOF || end_wc == WEOF)
- return REG_ECOLLATE;
- cmp_buf[0] = start_wc;
- cmp_buf[4] = end_wc;
- if (wcscoll (cmp_buf, cmp_buf + 4) > 0)
- return REG_ERANGE;
-
- /* Got valid collation sequence values, add them as a new entry.
- However, for !_LIBC we have no collation elements: if the
- character set is single byte, the single byte character set
- that we build below suffices. parse_bracket_exp passes
- no MBCSET if dfa->mb_cur_max == 1. */
- if (mbcset)
- {
- /* Check the space of the arrays. */
- if (BE (*range_alloc == mbcset->nranges, 0))
- {
- /* There is not enough space, need realloc. */
- wchar_t *new_array_start, *new_array_end;
- int new_nranges;
-
- /* +1 in case of mbcset->nranges is 0. */
- new_nranges = 2 * mbcset->nranges + 1;
- /* Use realloc since mbcset->range_starts and mbcset->range_ends
- are NULL if *range_alloc == 0. */
- new_array_start = re_realloc (mbcset->range_starts, wchar_t,
- new_nranges);
- new_array_end = re_realloc (mbcset->range_ends, wchar_t,
- new_nranges);
-
- if (BE (new_array_start == NULL || new_array_end == NULL, 0))
- return REG_ESPACE;
-
- mbcset->range_starts = new_array_start;
- mbcset->range_ends = new_array_end;
- *range_alloc = new_nranges;
- }
-
- mbcset->range_starts[mbcset->nranges] = start_wc;
- mbcset->range_ends[mbcset->nranges++] = end_wc;
- }
-
- /* Build the table for single byte characters. */
- for (wc = 0; wc < SBC_MAX; ++wc)
- {
- cmp_buf[2] = wc;
- if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
- && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
- bitset_set (sbcset, wc);
- }
- }
-# else /* not RE_ENABLE_I18N */
- {
- unsigned int ch;
- start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch
- : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
- : 0));
- end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch
- : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
- : 0));
- if (start_ch > end_ch)
- return REG_ERANGE;
- /* Build the table for single byte characters. */
- for (ch = 0; ch < SBC_MAX; ++ch)
- if (start_ch <= ch && ch <= end_ch)
- bitset_set (sbcset, ch);
- }
-# endif /* not RE_ENABLE_I18N */
- return REG_NOERROR;
-}
-#endif /* not _LIBC */
-
-#ifndef _LIBC
-/* Helper function for parse_bracket_exp only used in case of NOT _LIBC..
- Build the collating element which is represented by NAME.
- The result are written to MBCSET and SBCSET.
- COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
- pointer argument since we may update it. */
-
-static reg_errcode_t
-internal_function
-# ifdef RE_ENABLE_I18N
-build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
- int *coll_sym_alloc, const unsigned char *name)
-# else /* not RE_ENABLE_I18N */
-build_collating_symbol (bitset_t sbcset, const unsigned char *name)
-# endif /* not RE_ENABLE_I18N */
-{
- size_t name_len = strlen ((const char *) name);
- if (BE (name_len != 1, 0))
- return REG_ECOLLATE;
- else
- {
- bitset_set (sbcset, name[0]);
- return REG_NOERROR;
- }
-}
-#endif /* not _LIBC */
-
-/* This function parse bracket expression like "[abc]", "[a-c]",
- "[[.a-a.]]" etc. */
-
-static bin_tree_t *
-parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
- reg_syntax_t syntax, reg_errcode_t *err)
-{
-#ifdef _LIBC
- const unsigned char *collseqmb;
- const char *collseqwc;
- uint32_t nrules;
- int32_t table_size;
- const int32_t *symb_table;
- const unsigned char *extra;
-
- /* Local function for parse_bracket_exp used in _LIBC environement.
- Seek the collating symbol entry correspondings to NAME.
- Return the index of the symbol in the SYMB_TABLE. */
-
- auto inline int32_t
- __attribute ((always_inline))
- seek_collating_symbol_entry (name, name_len)
- const unsigned char *name;
- size_t name_len;
- {
- int32_t hash = elem_hash ((const char *) name, name_len);
- int32_t elem = hash % table_size;
- if (symb_table[2 * elem] != 0)
- {
- int32_t second = hash % (table_size - 2) + 1;
-
- do
- {
- /* First compare the hashing value. */
- if (symb_table[2 * elem] == hash
- /* Compare the length of the name. */
- && name_len == extra[symb_table[2 * elem + 1]]
- /* Compare the name. */
- && memcmp (name, &extra[symb_table[2 * elem + 1] + 1],
- name_len) == 0)
- {
- /* Yep, this is the entry. */
- break;
- }
-
- /* Next entry. */
- elem += second;
- }
- while (symb_table[2 * elem] != 0);
- }
- return elem;
- }
-
- /* Local function for parse_bracket_exp used in _LIBC environment.
- Look up the collation sequence value of BR_ELEM.
- Return the value if succeeded, UINT_MAX otherwise. */
-
- auto inline unsigned int
- __attribute ((always_inline))
- lookup_collation_sequence_value (br_elem)
- bracket_elem_t *br_elem;
- {
- if (br_elem->type == SB_CHAR)
- {
- /*
- if (MB_CUR_MAX == 1)
- */
- if (nrules == 0)
- return collseqmb[br_elem->opr.ch];
- else
- {
- wint_t wc = __btowc (br_elem->opr.ch);
- return __collseq_table_lookup (collseqwc, wc);
- }
- }
- else if (br_elem->type == MB_CHAR)
- {
- if (nrules != 0)
- return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
- }
- else if (br_elem->type == COLL_SYM)
- {
- size_t sym_name_len = strlen ((char *) br_elem->opr.name);
- if (nrules != 0)
- {
- int32_t elem, idx;
- elem = seek_collating_symbol_entry (br_elem->opr.name,
- sym_name_len);
- if (symb_table[2 * elem] != 0)
- {
- /* We found the entry. */
- idx = symb_table[2 * elem + 1];
- /* Skip the name of collating element name. */
- idx += 1 + extra[idx];
- /* Skip the byte sequence of the collating element. */
- idx += 1 + extra[idx];
- /* Adjust for the alignment. */
- idx = (idx + 3) & ~3;
- /* Skip the multibyte collation sequence value. */
- idx += sizeof (unsigned int);
- /* Skip the wide char sequence of the collating element. */
- idx += sizeof (unsigned int) *
- (1 + *(unsigned int *) (extra + idx));
- /* Return the collation sequence value. */
- return *(unsigned int *) (extra + idx);
- }
- else if (symb_table[2 * elem] == 0 && sym_name_len == 1)
- {
- /* No valid character. Match it as a single byte
- character. */
- return collseqmb[br_elem->opr.name[0]];
- }
- }
- else if (sym_name_len == 1)
- return collseqmb[br_elem->opr.name[0]];
- }
- return UINT_MAX;
- }
-
- /* Local function for parse_bracket_exp used in _LIBC environement.
- Build the range expression which starts from START_ELEM, and ends
- at END_ELEM. The result are written to MBCSET and SBCSET.
- RANGE_ALLOC is the allocated size of mbcset->range_starts, and
- mbcset->range_ends, is a pointer argument sinse we may
- update it. */
-
- auto inline reg_errcode_t
- __attribute ((always_inline))
- build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem)
- re_charset_t *mbcset;
- int *range_alloc;
- bitset_t sbcset;
- bracket_elem_t *start_elem, *end_elem;
- {
- unsigned int ch;
- uint32_t start_collseq;
- uint32_t end_collseq;
-
- /* Equivalence Classes and Character Classes can't be a range
- start/end. */
- if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
- || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
- 0))
- return REG_ERANGE;
-
- start_collseq = lookup_collation_sequence_value (start_elem);
- end_collseq = lookup_collation_sequence_value (end_elem);
- /* Check start/end collation sequence values. */
- if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0))
- return REG_ECOLLATE;
- if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0))
- return REG_ERANGE;
-
- /* Got valid collation sequence values, add them as a new entry.
- However, if we have no collation elements, and the character set
- is single byte, the single byte character set that we
- build below suffices. */
- if (nrules > 0 || dfa->mb_cur_max > 1)
- {
- /* Check the space of the arrays. */
- if (BE (*range_alloc == mbcset->nranges, 0))
- {
- /* There is not enough space, need realloc. */
- uint32_t *new_array_start;
- uint32_t *new_array_end;
- int new_nranges;
-
- /* +1 in case of mbcset->nranges is 0. */
- new_nranges = 2 * mbcset->nranges + 1;
- new_array_start = re_realloc (mbcset->range_starts, uint32_t,
- new_nranges);
- new_array_end = re_realloc (mbcset->range_ends, uint32_t,
- new_nranges);
-
- if (BE (new_array_start == NULL || new_array_end == NULL, 0))
- return REG_ESPACE;
-
- mbcset->range_starts = new_array_start;
- mbcset->range_ends = new_array_end;
- *range_alloc = new_nranges;
- }
-
- mbcset->range_starts[mbcset->nranges] = start_collseq;
- mbcset->range_ends[mbcset->nranges++] = end_collseq;
- }
-
- /* Build the table for single byte characters. */
- for (ch = 0; ch < SBC_MAX; ch++)
- {
- uint32_t ch_collseq;
- /*
- if (MB_CUR_MAX == 1)
- */
- if (nrules == 0)
- ch_collseq = collseqmb[ch];
- else
- ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
- if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
- bitset_set (sbcset, ch);
- }
- return REG_NOERROR;
- }
-
- /* Local function for parse_bracket_exp used in _LIBC environement.
- Build the collating element which is represented by NAME.
- The result are written to MBCSET and SBCSET.
- COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
- pointer argument sinse we may update it. */
-
- auto inline reg_errcode_t
- __attribute ((always_inline))
- build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name)
- re_charset_t *mbcset;
- int *coll_sym_alloc;
- bitset_t sbcset;
- const unsigned char *name;
- {
- int32_t elem, idx;
- size_t name_len = strlen ((const char *) name);
- if (nrules != 0)
- {
- elem = seek_collating_symbol_entry (name, name_len);
- if (symb_table[2 * elem] != 0)
- {
- /* We found the entry. */
- idx = symb_table[2 * elem + 1];
- /* Skip the name of collating element name. */
- idx += 1 + extra[idx];
- }
- else if (symb_table[2 * elem] == 0 && name_len == 1)
- {
- /* No valid character, treat it as a normal
- character. */
- bitset_set (sbcset, name[0]);
- return REG_NOERROR;
- }
- else
- return REG_ECOLLATE;
-
- /* Got valid collation sequence, add it as a new entry. */
- /* Check the space of the arrays. */
- if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0))
- {
- /* Not enough, realloc it. */
- /* +1 in case of mbcset->ncoll_syms is 0. */
- int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
- /* Use realloc since mbcset->coll_syms is NULL
- if *alloc == 0. */
- int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t,
- new_coll_sym_alloc);
- if (BE (new_coll_syms == NULL, 0))
- return REG_ESPACE;
- mbcset->coll_syms = new_coll_syms;
- *coll_sym_alloc = new_coll_sym_alloc;
- }
- mbcset->coll_syms[mbcset->ncoll_syms++] = idx;
- return REG_NOERROR;
- }
- else
- {
- if (BE (name_len != 1, 0))
- return REG_ECOLLATE;
- else
- {
- bitset_set (sbcset, name[0]);
- return REG_NOERROR;
- }
- }
- }
-#endif
-
- re_token_t br_token;
- re_bitset_ptr_t sbcset;
-#ifdef RE_ENABLE_I18N
- re_charset_t *mbcset;
- int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
- int equiv_class_alloc = 0, char_class_alloc = 0;
-#endif /* not RE_ENABLE_I18N */
- int non_match = 0;
- bin_tree_t *work_tree;
- int token_len;
- int first_round = 1;
-#ifdef _LIBC
- collseqmb = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
- nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
- if (nrules)
- {
- /*
- if (MB_CUR_MAX > 1)
- */
- collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
- table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);
- symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_SYMB_TABLEMB);
- extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_SYMB_EXTRAMB);
- }
-#endif
- sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
-#ifdef RE_ENABLE_I18N
- mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
-#endif /* RE_ENABLE_I18N */
-#ifdef RE_ENABLE_I18N
- if (BE (sbcset == NULL || mbcset == NULL, 0))
-#else
- if (BE (sbcset == NULL, 0))
-#endif /* RE_ENABLE_I18N */
- {
- *err = REG_ESPACE;
- return NULL;
- }
-
- token_len = peek_token_bracket (token, regexp, syntax);
- if (BE (token->type == END_OF_RE, 0))
- {
- *err = REG_BADPAT;
- goto parse_bracket_exp_free_return;
- }
- if (token->type == OP_NON_MATCH_LIST)
- {
-#ifdef RE_ENABLE_I18N
- mbcset->non_match = 1;
-#endif /* not RE_ENABLE_I18N */
- non_match = 1;
- if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
- bitset_set (sbcset, '\n');
- re_string_skip_bytes (regexp, token_len); /* Skip a token. */
- token_len = peek_token_bracket (token, regexp, syntax);
- if (BE (token->type == END_OF_RE, 0))
- {
- *err = REG_BADPAT;
- goto parse_bracket_exp_free_return;
- }
- }
-
- /* We treat the first ']' as a normal character. */
- if (token->type == OP_CLOSE_BRACKET)
- token->type = CHARACTER;
-
- while (1)
- {
- bracket_elem_t start_elem, end_elem;
- unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];
- unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];
- reg_errcode_t ret;
- int token_len2 = 0, is_range_exp = 0;
- re_token_t token2;
-
- start_elem.opr.name = start_name_buf;
- ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,
- syntax, first_round);
- if (BE (ret != REG_NOERROR, 0))
- {
- *err = ret;
- goto parse_bracket_exp_free_return;
- }
- first_round = 0;
-
- /* Get information about the next token. We need it in any case. */
- token_len = peek_token_bracket (token, regexp, syntax);
-
- /* Do not check for ranges if we know they are not allowed. */
- if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS)
- {
- if (BE (token->type == END_OF_RE, 0))
- {
- *err = REG_EBRACK;
- goto parse_bracket_exp_free_return;
- }
- if (token->type == OP_CHARSET_RANGE)
- {
- re_string_skip_bytes (regexp, token_len); /* Skip '-'. */
- token_len2 = peek_token_bracket (&token2, regexp, syntax);
- if (BE (token2.type == END_OF_RE, 0))
- {
- *err = REG_EBRACK;
- goto parse_bracket_exp_free_return;
- }
- if (token2.type == OP_CLOSE_BRACKET)
- {
- /* We treat the last '-' as a normal character. */
- re_string_skip_bytes (regexp, -token_len);
- token->type = CHARACTER;
- }
- else
- is_range_exp = 1;
- }
- }
-
- if (is_range_exp == 1)
- {
- end_elem.opr.name = end_name_buf;
- ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,
- dfa, syntax, 1);
- if (BE (ret != REG_NOERROR, 0))
- {
- *err = ret;
- goto parse_bracket_exp_free_return;
- }
-
- token_len = peek_token_bracket (token, regexp, syntax);
-
-#ifdef _LIBC
- *err = build_range_exp (sbcset, mbcset, &range_alloc,
- &start_elem, &end_elem);
-#else
-# ifdef RE_ENABLE_I18N
- *err = build_range_exp (sbcset,
- dfa->mb_cur_max > 1 ? mbcset : NULL,
- &range_alloc, &start_elem, &end_elem);
-# else
- *err = build_range_exp (sbcset, &start_elem, &end_elem);
-# endif
-#endif /* RE_ENABLE_I18N */
- if (BE (*err != REG_NOERROR, 0))
- goto parse_bracket_exp_free_return;
- }
- else
- {
- switch (start_elem.type)
- {
- case SB_CHAR:
- bitset_set (sbcset, start_elem.opr.ch);
- break;
-#ifdef RE_ENABLE_I18N
- case MB_CHAR:
- /* Check whether the array has enough space. */
- if (BE (mbchar_alloc == mbcset->nmbchars, 0))
- {
- wchar_t *new_mbchars;
- /* Not enough, realloc it. */
- /* +1 in case of mbcset->nmbchars is 0. */
- mbchar_alloc = 2 * mbcset->nmbchars + 1;
- /* Use realloc since array is NULL if *alloc == 0. */
- new_mbchars = re_realloc (mbcset->mbchars, wchar_t,
- mbchar_alloc);
- if (BE (new_mbchars == NULL, 0))
- goto parse_bracket_exp_espace;
- mbcset->mbchars = new_mbchars;
- }
- mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
- break;
-#endif /* RE_ENABLE_I18N */
- case EQUIV_CLASS:
- *err = build_equiv_class (sbcset,
-#ifdef RE_ENABLE_I18N
- mbcset, &equiv_class_alloc,
-#endif /* RE_ENABLE_I18N */
- start_elem.opr.name);
- if (BE (*err != REG_NOERROR, 0))
- goto parse_bracket_exp_free_return;
- break;
- case COLL_SYM:
- *err = build_collating_symbol (sbcset,
-#ifdef RE_ENABLE_I18N
- mbcset, &coll_sym_alloc,
-#endif /* RE_ENABLE_I18N */
- start_elem.opr.name);
- if (BE (*err != REG_NOERROR, 0))
- goto parse_bracket_exp_free_return;
- break;
- case CHAR_CLASS:
- *err = build_charclass (regexp->trans, sbcset,
-#ifdef RE_ENABLE_I18N
- mbcset, &char_class_alloc,
-#endif /* RE_ENABLE_I18N */
- start_elem.opr.name, syntax);
- if (BE (*err != REG_NOERROR, 0))
- goto parse_bracket_exp_free_return;
- break;
- default:
- assert (0);
- break;
- }
- }
- if (BE (token->type == END_OF_RE, 0))
- {
- *err = REG_EBRACK;
- goto parse_bracket_exp_free_return;
- }
- if (token->type == OP_CLOSE_BRACKET)
- break;
- }
-
- re_string_skip_bytes (regexp, token_len); /* Skip a token. */
-
- /* If it is non-matching list. */
- if (non_match)
- bitset_not (sbcset);
-
-#ifdef RE_ENABLE_I18N
- /* Ensure only single byte characters are set. */
- if (dfa->mb_cur_max > 1)
- bitset_mask (sbcset, dfa->sb_char);
-
- if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
- || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
- || mbcset->non_match)))
- {
- bin_tree_t *mbc_tree;
- int sbc_idx;
- /* Build a tree for complex bracket. */
- dfa->has_mb_node = 1;
- br_token.type = COMPLEX_BRACKET;
- br_token.opr.mbcset = mbcset;
- mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
- if (BE (mbc_tree == NULL, 0))
- goto parse_bracket_exp_espace;
- for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx)
- if (sbcset[sbc_idx])
- break;
- /* If there are no bits set in sbcset, there is no point
- of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */
- if (sbc_idx < BITSET_WORDS)
- {
- /* Build a tree for simple bracket. */
- br_token.type = SIMPLE_BRACKET;
- br_token.opr.sbcset = sbcset;
- work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
- if (BE (work_tree == NULL, 0))
- goto parse_bracket_exp_espace;
-
- /* Then join them by ALT node. */
- work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT);
- if (BE (work_tree == NULL, 0))
- goto parse_bracket_exp_espace;
- }
- else
- {
- re_free (sbcset);
- work_tree = mbc_tree;
- }
- }
- else
-#endif /* not RE_ENABLE_I18N */
- {
-#ifdef RE_ENABLE_I18N
- free_charset (mbcset);
-#endif
- /* Build a tree for simple bracket. */
- br_token.type = SIMPLE_BRACKET;
- br_token.opr.sbcset = sbcset;
- work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
- if (BE (work_tree == NULL, 0))
- goto parse_bracket_exp_espace;
- }
- return work_tree;
-
- parse_bracket_exp_espace:
- *err = REG_ESPACE;
- parse_bracket_exp_free_return:
- re_free (sbcset);
-#ifdef RE_ENABLE_I18N
- free_charset (mbcset);
-#endif /* RE_ENABLE_I18N */
- return NULL;
-}
-
-/* Parse an element in the bracket expression. */
-
-static reg_errcode_t
-parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
- re_token_t *token, int token_len, re_dfa_t *dfa,
- reg_syntax_t syntax, int accept_hyphen)
-{
-#ifdef RE_ENABLE_I18N
- int cur_char_size;
- cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
- if (cur_char_size > 1)
- {
- elem->type = MB_CHAR;
- elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp));
- re_string_skip_bytes (regexp, cur_char_size);
- return REG_NOERROR;
- }
-#endif /* RE_ENABLE_I18N */
- re_string_skip_bytes (regexp, token_len); /* Skip a token. */
- if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
- || token->type == OP_OPEN_EQUIV_CLASS)
- return parse_bracket_symbol (elem, regexp, token);
- if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen)
- {
- /* A '-' must only appear as anything but a range indicator before
- the closing bracket. Everything else is an error. */
- re_token_t token2;
- (void) peek_token_bracket (&token2, regexp, syntax);
- if (token2.type != OP_CLOSE_BRACKET)
- /* The actual error value is not standardized since this whole
- case is undefined. But ERANGE makes good sense. */
- return REG_ERANGE;
- }
- elem->type = SB_CHAR;
- elem->opr.ch = token->opr.c;
- return REG_NOERROR;
-}
-
-/* Parse a bracket symbol in the bracket expression. Bracket symbols are
- such as [:<character_class>:], [.<collating_element>.], and
- [=<equivalent_class>=]. */
-
-static reg_errcode_t
-parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp,
- re_token_t *token)
-{
- unsigned char ch, delim = token->opr.c;
- int i = 0;
- if (re_string_eoi(regexp))
- return REG_EBRACK;
- for (;; ++i)
- {
- if (i >= BRACKET_NAME_BUF_SIZE)
- return REG_EBRACK;
- if (token->type == OP_OPEN_CHAR_CLASS)
- ch = re_string_fetch_byte_case (regexp);
- else
- ch = re_string_fetch_byte (regexp);
- if (re_string_eoi(regexp))
- return REG_EBRACK;
- if (ch == delim && re_string_peek_byte (regexp, 0) == ']')
- break;
- elem->opr.name[i] = ch;
- }
- re_string_skip_bytes (regexp, 1);
- elem->opr.name[i] = '\0';
- switch (token->type)
- {
- case OP_OPEN_COLL_ELEM:
- elem->type = COLL_SYM;
- break;
- case OP_OPEN_EQUIV_CLASS:
- elem->type = EQUIV_CLASS;
- break;
- case OP_OPEN_CHAR_CLASS:
- elem->type = CHAR_CLASS;
- break;
- default:
- break;
- }
- return REG_NOERROR;
-}
-
- /* Helper function for parse_bracket_exp.
- Build the equivalence class which is represented by NAME.
- The result are written to MBCSET and SBCSET.
- EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,
- is a pointer argument sinse we may update it. */
-
-static reg_errcode_t
-#ifdef RE_ENABLE_I18N
-build_equiv_class (bitset_t sbcset, re_charset_t *mbcset,
- int *equiv_class_alloc, const unsigned char *name)
-#else /* not RE_ENABLE_I18N */
-build_equiv_class (bitset_t sbcset, const unsigned char *name)
-#endif /* not RE_ENABLE_I18N */
-{
-#ifdef _LIBC
- uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
- if (nrules != 0)
- {
- const int32_t *table, *indirect;
- const unsigned char *weights, *extra, *cp;
- unsigned char char_buf[2];
- int32_t idx1, idx2;
- unsigned int ch;
- size_t len;
- /* This #include defines a local function! */
-# include <locale/weight.h>
- /* Calculate the index for equivalence class. */
- cp = name;
- table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
- weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_WEIGHTMB);
- extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_EXTRAMB);
- indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_INDIRECTMB);
- idx1 = findidx (&cp);
- if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0))
- /* This isn't a valid character. */
- return REG_ECOLLATE;
-
- /* Build single byte matcing table for this equivalence class. */
- char_buf[1] = (unsigned char) '\0';
- len = weights[idx1 & 0xffffff];
- for (ch = 0; ch < SBC_MAX; ++ch)
- {
- char_buf[0] = ch;
- cp = char_buf;
- idx2 = findidx (&cp);
-/*
- idx2 = table[ch];
-*/
- if (idx2 == 0)
- /* This isn't a valid character. */
- continue;
- /* Compare only if the length matches and the collation rule
- index is the same. */
- if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24))
- {
- int cnt = 0;
-
- while (cnt <= len &&
- weights[(idx1 & 0xffffff) + 1 + cnt]
- == weights[(idx2 & 0xffffff) + 1 + cnt])
- ++cnt;
-
- if (cnt > len)
- bitset_set (sbcset, ch);
- }
- }
- /* Check whether the array has enough space. */
- if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0))
- {
- /* Not enough, realloc it. */
- /* +1 in case of mbcset->nequiv_classes is 0. */
- int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
- /* Use realloc since the array is NULL if *alloc == 0. */
- int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes,
- int32_t,
- new_equiv_class_alloc);
- if (BE (new_equiv_classes == NULL, 0))
- return REG_ESPACE;
- mbcset->equiv_classes = new_equiv_classes;
- *equiv_class_alloc = new_equiv_class_alloc;
- }
- mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
- }
- else
-#endif /* _LIBC */
- {
- if (BE (strlen ((const char *) name) != 1, 0))
- return REG_ECOLLATE;
- bitset_set (sbcset, *name);
- }
- return REG_NOERROR;
-}
-
- /* Helper function for parse_bracket_exp.
- Build the character class which is represented by NAME.
- The result are written to MBCSET and SBCSET.
- CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,
- is a pointer argument sinse we may update it. */
-
-static reg_errcode_t
-#ifdef RE_ENABLE_I18N
-build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
- re_charset_t *mbcset, int *char_class_alloc,
- const unsigned char *class_name, reg_syntax_t syntax)
-#else /* not RE_ENABLE_I18N */
-build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
- const unsigned char *class_name, reg_syntax_t syntax)
-#endif /* not RE_ENABLE_I18N */
-{
- int i;
- const char *name = (const char *) class_name;
-
- /* In case of REG_ICASE "upper" and "lower" match the both of
- upper and lower cases. */
- if ((syntax & RE_ICASE)
- && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
- name = "alpha";
-
-#ifdef RE_ENABLE_I18N
- /* Check the space of the arrays. */
- if (BE (*char_class_alloc == mbcset->nchar_classes, 0))
- {
- /* Not enough, realloc it. */
- /* +1 in case of mbcset->nchar_classes is 0. */
- int new_char_class_alloc = 2 * mbcset->nchar_classes + 1;
- /* Use realloc since array is NULL if *alloc == 0. */
- wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t,
- new_char_class_alloc);
- if (BE (new_char_classes == NULL, 0))
- return REG_ESPACE;
- mbcset->char_classes = new_char_classes;
- *char_class_alloc = new_char_class_alloc;
- }
- mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
-#endif /* RE_ENABLE_I18N */
-
-#define BUILD_CHARCLASS_LOOP(ctype_func) \
- do { \
- if (BE (trans != NULL, 0)) \
- { \
- for (i = 0; i < SBC_MAX; ++i) \
- if (ctype_func (i)) \
- bitset_set (sbcset, trans[i]); \
- } \
- else \
- { \
- for (i = 0; i < SBC_MAX; ++i) \
- if (ctype_func (i)) \
- bitset_set (sbcset, i); \
- } \
- } while (0)
-
- if (strcmp (name, "alnum") == 0)
- BUILD_CHARCLASS_LOOP (isalnum);
- else if (strcmp (name, "cntrl") == 0)
- BUILD_CHARCLASS_LOOP (iscntrl);
- else if (strcmp (name, "lower") == 0)
- BUILD_CHARCLASS_LOOP (islower);
- else if (strcmp (name, "space") == 0)
- BUILD_CHARCLASS_LOOP (isspace);
- else if (strcmp (name, "alpha") == 0)
- BUILD_CHARCLASS_LOOP (isalpha);
- else if (strcmp (name, "digit") == 0)
- BUILD_CHARCLASS_LOOP (isdigit);
- else if (strcmp (name, "print") == 0)
- BUILD_CHARCLASS_LOOP (isprint);
- else if (strcmp (name, "upper") == 0)
- BUILD_CHARCLASS_LOOP (isupper);
- else if (strcmp (name, "blank") == 0)
- BUILD_CHARCLASS_LOOP (isblank);
- else if (strcmp (name, "graph") == 0)
- BUILD_CHARCLASS_LOOP (isgraph);
- else if (strcmp (name, "punct") == 0)
- BUILD_CHARCLASS_LOOP (ispunct);
- else if (strcmp (name, "xdigit") == 0)
- BUILD_CHARCLASS_LOOP (isxdigit);
- else
- return REG_ECTYPE;
-
- return REG_NOERROR;
-}
-
-static bin_tree_t *
-build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
- const unsigned char *class_name,
- const unsigned char *extra, int non_match,
- reg_errcode_t *err)
-{
- re_bitset_ptr_t sbcset;
-#ifdef RE_ENABLE_I18N
- re_charset_t *mbcset;
- int alloc = 0;
-#endif /* not RE_ENABLE_I18N */
- reg_errcode_t ret;
- re_token_t br_token;
- bin_tree_t *tree;
-
- sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
-#ifdef RE_ENABLE_I18N
- mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
-#endif /* RE_ENABLE_I18N */
-
-#ifdef RE_ENABLE_I18N
- if (BE (sbcset == NULL || mbcset == NULL, 0))
-#else /* not RE_ENABLE_I18N */
- if (BE (sbcset == NULL, 0))
-#endif /* not RE_ENABLE_I18N */
- {
- *err = REG_ESPACE;
- return NULL;
- }
-
- if (non_match)
- {
-#ifdef RE_ENABLE_I18N
- mbcset->non_match = 1;
-#endif /* not RE_ENABLE_I18N */
- }
-
- /* We don't care the syntax in this case. */
- ret = build_charclass (trans, sbcset,
-#ifdef RE_ENABLE_I18N
- mbcset, &alloc,
-#endif /* RE_ENABLE_I18N */
- class_name, 0);
-
- if (BE (ret != REG_NOERROR, 0))
- {
- re_free (sbcset);
-#ifdef RE_ENABLE_I18N
- free_charset (mbcset);
-#endif /* RE_ENABLE_I18N */
- *err = ret;
- return NULL;
- }
- /* \w match '_' also. */
- for (; *extra; extra++)
- bitset_set (sbcset, *extra);
-
- /* If it is non-matching list. */
- if (non_match)
- bitset_not (sbcset);
-
-#ifdef RE_ENABLE_I18N
- /* Ensure only single byte characters are set. */
- if (dfa->mb_cur_max > 1)
- bitset_mask (sbcset, dfa->sb_char);
-#endif
-
- /* Build a tree for simple bracket. */
- br_token.type = SIMPLE_BRACKET;
- br_token.opr.sbcset = sbcset;
- tree = create_token_tree (dfa, NULL, NULL, &br_token);
- if (BE (tree == NULL, 0))
- goto build_word_op_espace;
-
-#ifdef RE_ENABLE_I18N
- if (dfa->mb_cur_max > 1)
- {
- bin_tree_t *mbc_tree;
- /* Build a tree for complex bracket. */
- br_token.type = COMPLEX_BRACKET;
- br_token.opr.mbcset = mbcset;
- dfa->has_mb_node = 1;
- mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
- if (BE (mbc_tree == NULL, 0))
- goto build_word_op_espace;
- /* Then join them by ALT node. */
- tree = create_tree (dfa, tree, mbc_tree, OP_ALT);
- if (BE (mbc_tree != NULL, 1))
- return tree;
- }
- else
- {
- free_charset (mbcset);
- return tree;
- }
-#else /* not RE_ENABLE_I18N */
- return tree;
-#endif /* not RE_ENABLE_I18N */
-
- build_word_op_espace:
- re_free (sbcset);
-#ifdef RE_ENABLE_I18N
- free_charset (mbcset);
-#endif /* RE_ENABLE_I18N */
- *err = REG_ESPACE;
- return NULL;
-}
-
-/* This is intended for the expressions like "a{1,3}".
- Fetch a number from `input', and return the number.
- Return -1, if the number field is empty like "{,1}".
- Return -2, If an error is occured. */
-
-static int
-fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
-{
- int num = -1;
- unsigned char c;
- while (1)
- {
- fetch_token (token, input, syntax);
- c = token->opr.c;
- if (BE (token->type == END_OF_RE, 0))
- return -2;
- if (token->type == OP_CLOSE_DUP_NUM || c == ',')
- break;
- num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2)
- ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0'));
- num = (num > RE_DUP_MAX) ? -2 : num;
- }
- return num;
-}
-
-#ifdef RE_ENABLE_I18N
-static void
-free_charset (re_charset_t *cset)
-{
- re_free (cset->mbchars);
-# ifdef _LIBC
- re_free (cset->coll_syms);
- re_free (cset->equiv_classes);
- re_free (cset->range_starts);
- re_free (cset->range_ends);
-# endif
- re_free (cset->char_classes);
- re_free (cset);
-}
-#endif /* RE_ENABLE_I18N */
-
-/* Functions for binary tree operation. */
-
-/* Create a tree node. */
-
-static bin_tree_t *
-create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
- re_token_type_t type)
-{
- re_token_t t;
- t.type = type;
- return create_token_tree (dfa, left, right, &t);
-}
-
-static bin_tree_t *
-create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
- const re_token_t *token)
-{
- bin_tree_t *tree;
- if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0))
- {
- bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1);
-
- if (storage == NULL)
- return NULL;
- storage->next = dfa->str_tree_storage;
- dfa->str_tree_storage = storage;
- dfa->str_tree_storage_idx = 0;
- }
- tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++];
-
- tree->parent = NULL;
- tree->left = left;
- tree->right = right;
- tree->token = *token;
- tree->token.duplicated = 0;
- tree->token.opt_subexp = 0;
- tree->first = NULL;
- tree->next = NULL;
- tree->node_idx = -1;
-
- if (left != NULL)
- left->parent = tree;
- if (right != NULL)
- right->parent = tree;
- return tree;
-}
-
-/* Mark the tree SRC as an optional subexpression.
- To be called from preorder or postorder. */
-
-static reg_errcode_t
-mark_opt_subexp (void *extra, bin_tree_t *node)
-{
- int idx = (int) (long) extra;
- if (node->token.type == SUBEXP && node->token.opr.idx == idx)
- node->token.opt_subexp = 1;
-
- return REG_NOERROR;
-}
-
-/* Free the allocated memory inside NODE. */
-
-static void
-free_token (re_token_t *node)
-{
-#ifdef RE_ENABLE_I18N
- if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
- free_charset (node->opr.mbcset);
- else
-#endif /* RE_ENABLE_I18N */
- if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
- re_free (node->opr.sbcset);
-}
-
-/* Worker function for tree walking. Free the allocated memory inside NODE
- and its children. */
-
-static reg_errcode_t
-free_tree (void *extra, bin_tree_t *node)
-{
- free_token (&node->token);
- return REG_NOERROR;
-}
-
-
-/* Duplicate the node SRC, and return new node. This is a preorder
- visit similar to the one implemented by the generic visitor, but
- we need more infrastructure to maintain two parallel trees --- so,
- it's easier to duplicate. */
-
-static bin_tree_t *
-duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa)
-{
- const bin_tree_t *node;
- bin_tree_t *dup_root;
- bin_tree_t **p_new = &dup_root, *dup_node = root->parent;
-
- for (node = root; ; )
- {
- /* Create a new tree and link it back to the current parent. */
- *p_new = create_token_tree (dfa, NULL, NULL, &node->token);
- if (*p_new == NULL)
- return NULL;
- (*p_new)->parent = dup_node;
- (*p_new)->token.duplicated = 1;
- dup_node = *p_new;
-
- /* Go to the left node, or up and to the right. */
- if (node->left)
- {
- node = node->left;
- p_new = &dup_node->left;
- }
- else
- {
- const bin_tree_t *prev = NULL;
- while (node->right == prev || node->right == NULL)
- {
- prev = node;
- node = node->parent;
- dup_node = dup_node->parent;
- if (!node)
- return dup_root;
- }
- node = node->right;
- p_new = &dup_node->right;
- }
- }
-}
diff --git a/xbmc/lib/libshout/libshout/regex/regex.c b/xbmc/lib/libshout/libshout/regex/regex.c
deleted file mode 100644
index d2d4f28e01..0000000000
--- a/xbmc/lib/libshout/libshout/regex/regex.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Extended regular expression matching and search library.
- Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
-
- The GNU C 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.
-
- The GNU C 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 GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* Make sure noone compiles this code with a C++ compiler. */
-#ifdef __cplusplus
-# error "This is C code, use a C compiler"
-#endif
-
-#ifdef _LIBC
-/* We have to keep the namespace clean. */
-# define regfree(preg) __regfree (preg)
-# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
-# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
-# define regerror(errcode, preg, errbuf, errbuf_size) \
- __regerror(errcode, preg, errbuf, errbuf_size)
-# define re_set_registers(bu, re, nu, st, en) \
- __re_set_registers (bu, re, nu, st, en)
-# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
- __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
-# define re_match(bufp, string, size, pos, regs) \
- __re_match (bufp, string, size, pos, regs)
-# define re_search(bufp, string, size, startpos, range, regs) \
- __re_search (bufp, string, size, startpos, range, regs)
-# define re_compile_pattern(pattern, length, bufp) \
- __re_compile_pattern (pattern, length, bufp)
-# define re_set_syntax(syntax) __re_set_syntax (syntax)
-# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
- __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
-# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
-
-# include "../locale/localeinfo.h"
-#endif
-
-/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
- GNU regex allows. Include it before <regex.h>, which correctly
- #undefs RE_DUP_MAX and sets it to the right value. */
-#include <limits.h>
-
-#include <regex.h>
-#include "regex_internal.h"
-
-#include "regex_internal.c"
-#include "regcomp.c"
-#include "regexec.c"
-
-/* Binary backward compatibility. */
-#if _LIBC
-# include <shlib-compat.h>
-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
-link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
-int re_max_failures = 2000;
-# endif
-#endif
diff --git a/xbmc/lib/libshout/libshout/regex/regex.h b/xbmc/lib/libshout/libshout/regex/regex.h
deleted file mode 100644
index 807c404ec2..0000000000
--- a/xbmc/lib/libshout/libshout/regex/regex.h
+++ /dev/null
@@ -1,556 +0,0 @@
-/* Definitions for data structures and routines for the regular
- expression library.
- Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006
- Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C 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.
-
- The GNU C 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 GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _REGEX_H
-#define _REGEX_H 1
-
-#include <sys/types.h>
-
-/* Allow the use in C++ code. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* The following two types have to be signed and unsigned integer type
- wide enough to hold a value of a pointer. For most ANSI compilers
- ptrdiff_t and size_t should be likely OK. Still size of these two
- types is 2 for Microsoft C. Ugh... */
-typedef long int s_reg_t;
-typedef unsigned long int active_reg_t;
-
-/* The following bits are used to determine the regexp syntax we
- recognize. The set/not-set meanings are chosen so that Emacs syntax
- remains the value 0. The bits are given in alphabetical order, and
- the definitions shifted by one from the previous bit; thus, when we
- add or remove a bit, only one other definition need change. */
-typedef unsigned long int reg_syntax_t;
-
-/* If this bit is not set, then \ inside a bracket expression is literal.
- If set, then such a \ quotes the following character. */
-#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
-
-/* If this bit is not set, then + and ? are operators, and \+ and \? are
- literals.
- If set, then \+ and \? are operators and + and ? are literals. */
-#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
-
-/* If this bit is set, then character classes are supported. They are:
- [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
- [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
- If not set, then character classes are not supported. */
-#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
-
-/* If this bit is set, then ^ and $ are always anchors (outside bracket
- expressions, of course).
- If this bit is not set, then it depends:
- ^ is an anchor if it is at the beginning of a regular
- expression or after an open-group or an alternation operator;
- $ is an anchor if it is at the end of a regular expression, or
- before a close-group or an alternation operator.
-
- This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
- POSIX draft 11.2 says that * etc. in leading positions is undefined.
- We already implemented a previous draft which made those constructs
- invalid, though, so we haven't changed the code back. */
-#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
-
-/* If this bit is set, then special characters are always special
- regardless of where they are in the pattern.
- If this bit is not set, then special characters are special only in
- some contexts; otherwise they are ordinary. Specifically,
- * + ? and intervals are only special when not after the beginning,
- open-group, or alternation operator. */
-#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
-
-/* If this bit is set, then *, +, ?, and { cannot be first in an re or
- immediately after an alternation or begin-group operator. */
-#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
-
-/* If this bit is set, then . matches newline.
- If not set, then it doesn't. */
-#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
-
-/* If this bit is set, then . doesn't match NUL.
- If not set, then it does. */
-#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
-
-/* If this bit is set, nonmatching lists [^...] do not match newline.
- If not set, they do. */
-#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
-
-/* If this bit is set, either \{...\} or {...} defines an
- interval, depending on RE_NO_BK_BRACES.
- If not set, \{, \}, {, and } are literals. */
-#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
-
-/* If this bit is set, +, ? and | aren't recognized as operators.
- If not set, they are. */
-#define RE_LIMITED_OPS (RE_INTERVALS << 1)
-
-/* If this bit is set, newline is an alternation operator.
- If not set, newline is literal. */
-#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
-
-/* If this bit is set, then `{...}' defines an interval, and \{ and \}
- are literals.
- If not set, then `\{...\}' defines an interval. */
-#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
-
-/* If this bit is set, (...) defines a group, and \( and \) are literals.
- If not set, \(...\) defines a group, and ( and ) are literals. */
-#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
-
-/* If this bit is set, then \<digit> matches <digit>.
- If not set, then \<digit> is a back-reference. */
-#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
-
-/* If this bit is set, then | is an alternation operator, and \| is literal.
- If not set, then \| is an alternation operator, and | is literal. */
-#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
-
-/* If this bit is set, then an ending range point collating higher
- than the starting range point, as in [z-a], is invalid.
- If not set, then when ending range point collates higher than the
- starting range point, the range is ignored. */
-#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
-
-/* If this bit is set, then an unmatched ) is ordinary.
- If not set, then an unmatched ) is invalid. */
-#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
-
-/* If this bit is set, succeed as soon as we match the whole pattern,
- without further backtracking. */
-#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
-
-/* If this bit is set, do not process the GNU regex operators.
- If not set, then the GNU regex operators are recognized. */
-#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
-
-/* If this bit is set, turn on internal regex debugging.
- If not set, and debugging was on, turn it off.
- This only works if regex.c is compiled -DDEBUG.
- We define this bit always, so that all that's needed to turn on
- debugging is to recompile regex.c; the calling code can always have
- this bit set, and it won't affect anything in the normal case. */
-#define RE_DEBUG (RE_NO_GNU_OPS << 1)
-
-/* If this bit is set, a syntactically invalid interval is treated as
- a string of ordinary characters. For example, the ERE 'a{1' is
- treated as 'a\{1'. */
-#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
-
-/* If this bit is set, then ignore case when matching.
- If not set, then case is significant. */
-#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
-
-/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only
- for ^, because it is difficult to scan the regex backwards to find
- whether ^ should be special. */
-#define RE_CARET_ANCHORS_HERE (RE_ICASE << 1)
-
-/* If this bit is set, then \{ cannot be first in an bre or
- immediately after an alternation or begin-group operator. */
-#define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1)
-
-/* If this bit is set, then no_sub will be set to 1 during
- re_compile_pattern. */
-#define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
-
-/* This global variable defines the particular regexp syntax to use (for
- some interfaces). When a regexp is compiled, the syntax used is
- stored in the pattern buffer, so changing this does not affect
- already-compiled regexps. */
-extern reg_syntax_t re_syntax_options;
-
-/* Define combinations of the above bits for the standard possibilities.
- (The [[[ comments delimit what gets put into the Texinfo file, so
- don't delete them!) */
-/* [[[begin syntaxes]]] */
-#define RE_SYNTAX_EMACS 0
-
-#define RE_SYNTAX_AWK \
- (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
- | RE_NO_BK_PARENS | RE_NO_BK_REFS \
- | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
- | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
- | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
-
-#define RE_SYNTAX_GNU_AWK \
- ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
- & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \
- | RE_CONTEXT_INVALID_OPS ))
-
-#define RE_SYNTAX_POSIX_AWK \
- (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
- | RE_INTERVALS | RE_NO_GNU_OPS)
-
-#define RE_SYNTAX_GREP \
- (RE_BK_PLUS_QM | RE_CHAR_CLASSES \
- | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
- | RE_NEWLINE_ALT)
-
-#define RE_SYNTAX_EGREP \
- (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
- | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
- | RE_NEWLINE_ALT | RE_NO_BK_PARENS \
- | RE_NO_BK_VBAR)
-
-#define RE_SYNTAX_POSIX_EGREP \
- (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \
- | RE_INVALID_INTERVAL_ORD)
-
-/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
-#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
-
-#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
-
-/* Syntax bits common to both basic and extended POSIX regex syntax. */
-#define _RE_SYNTAX_POSIX_COMMON \
- (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
- | RE_INTERVALS | RE_NO_EMPTY_RANGES)
-
-#define RE_SYNTAX_POSIX_BASIC \
- (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
-
-/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
- RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
- isn't minimal, since other operators, such as \`, aren't disabled. */
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
- (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
-
-#define RE_SYNTAX_POSIX_EXTENDED \
- (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
- | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
- | RE_NO_BK_PARENS | RE_NO_BK_VBAR \
- | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
-
-/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
- removed and RE_NO_BK_REFS is added. */
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
- (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
- | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
- | RE_NO_BK_PARENS | RE_NO_BK_REFS \
- | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
-/* [[[end syntaxes]]] */
-
-/* Maximum number of duplicates an interval can allow. Some systems
- (erroneously) define this in other header files, but we want our
- value, so remove any previous define. */
-#ifdef RE_DUP_MAX
-# undef RE_DUP_MAX
-#endif
-/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
-#define RE_DUP_MAX (0x7fff)
-
-
-/* POSIX `cflags' bits (i.e., information for `regcomp'). */
-
-/* If this bit is set, then use extended regular expression syntax.
- If not set, then use basic regular expression syntax. */
-#define REG_EXTENDED 1
-
-/* If this bit is set, then ignore case when matching.
- If not set, then case is significant. */
-#define REG_ICASE (REG_EXTENDED << 1)
-
-/* If this bit is set, then anchors do not match at newline
- characters in the string.
- If not set, then anchors do match at newlines. */
-#define REG_NEWLINE (REG_ICASE << 1)
-
-/* If this bit is set, then report only success or fail in regexec.
- If not set, then returns differ between not matching and errors. */
-#define REG_NOSUB (REG_NEWLINE << 1)
-
-
-/* POSIX `eflags' bits (i.e., information for regexec). */
-
-/* If this bit is set, then the beginning-of-line operator doesn't match
- the beginning of the string (presumably because it's not the
- beginning of a line).
- If not set, then the beginning-of-line operator does match the
- beginning of the string. */
-#define REG_NOTBOL 1
-
-/* Like REG_NOTBOL, except for the end-of-line. */
-#define REG_NOTEOL (1 << 1)
-
-/* Use PMATCH[0] to delimit the start and end of the search in the
- buffer. */
-#define REG_STARTEND (1 << 2)
-
-
-/* If any error codes are removed, changed, or added, update the
- `re_error_msg' table in regex.c. */
-typedef enum
-{
-#ifdef _XOPEN_SOURCE
- REG_ENOSYS = -1, /* This will never happen for this implementation. */
-#endif
-
- REG_NOERROR = 0, /* Success. */
- REG_NOMATCH, /* Didn't find a match (for regexec). */
-
- /* POSIX regcomp return error codes. (In the order listed in the
- standard.) */
- REG_BADPAT, /* Invalid pattern. */
- REG_ECOLLATE, /* Inalid collating element. */
- REG_ECTYPE, /* Invalid character class name. */
- REG_EESCAPE, /* Trailing backslash. */
- REG_ESUBREG, /* Invalid back reference. */
- REG_EBRACK, /* Unmatched left bracket. */
- REG_EPAREN, /* Parenthesis imbalance. */
- REG_EBRACE, /* Unmatched \{. */
- REG_BADBR, /* Invalid contents of \{\}. */
- REG_ERANGE, /* Invalid range end. */
- REG_ESPACE, /* Ran out of memory. */
- REG_BADRPT, /* No preceding re for repetition op. */
-
- /* Error codes we've added. */
- REG_EEND, /* Premature end. */
- REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
- REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
-} reg_errcode_t;
-
-/* This data structure represents a compiled pattern. Before calling
- the pattern compiler, the fields `buffer', `allocated', `fastmap',
- `translate', and `no_sub' can be set. After the pattern has been
- compiled, the `re_nsub' field is available. All other fields are
- private to the regex routines. */
-
-#ifndef RE_TRANSLATE_TYPE
-# define RE_TRANSLATE_TYPE unsigned char *
-#endif
-
-struct re_pattern_buffer
-{
- /* Space that holds the compiled pattern. It is declared as
- `unsigned char *' because its elements are sometimes used as
- array indexes. */
- unsigned char *buffer;
-
- /* Number of bytes to which `buffer' points. */
- unsigned long int allocated;
-
- /* Number of bytes actually used in `buffer'. */
- unsigned long int used;
-
- /* Syntax setting with which the pattern was compiled. */
- reg_syntax_t syntax;
-
- /* Pointer to a fastmap, if any, otherwise zero. re_search uses the
- fastmap, if there is one, to skip over impossible starting points
- for matches. */
- char *fastmap;
-
- /* Either a translate table to apply to all characters before
- comparing them, or zero for no translation. The translation is
- applied to a pattern when it is compiled and to a string when it
- is matched. */
- RE_TRANSLATE_TYPE translate;
-
- /* Number of subexpressions found by the compiler. */
- size_t re_nsub;
-
- /* Zero if this pattern cannot match the empty string, one else.
- Well, in truth it's used only in `re_search_2', to see whether or
- not we should use the fastmap, so we don't set this absolutely
- perfectly; see `re_compile_fastmap' (the `duplicate' case). */
- unsigned can_be_null : 1;
-
- /* If REGS_UNALLOCATED, allocate space in the `regs' structure
- for `max (RE_NREGS, re_nsub + 1)' groups.
- If REGS_REALLOCATE, reallocate space if necessary.
- If REGS_FIXED, use what's there. */
-#define REGS_UNALLOCATED 0
-#define REGS_REALLOCATE 1
-#define REGS_FIXED 2
- unsigned regs_allocated : 2;
-
- /* Set to zero when `regex_compile' compiles a pattern; set to one
- by `re_compile_fastmap' if it updates the fastmap. */
- unsigned fastmap_accurate : 1;
-
- /* If set, `re_match_2' does not return information about
- subexpressions. */
- unsigned no_sub : 1;
-
- /* If set, a beginning-of-line anchor doesn't match at the beginning
- of the string. */
- unsigned not_bol : 1;
-
- /* Similarly for an end-of-line anchor. */
- unsigned not_eol : 1;
-
- /* If true, an anchor at a newline matches. */
- unsigned newline_anchor : 1;
-};
-
-typedef struct re_pattern_buffer regex_t;
-
-/* Type for byte offsets within the string. POSIX mandates this. */
-typedef int regoff_t;
-
-
-/* This is the structure we store register match data in. See
- regex.texinfo for a full description of what registers match. */
-struct re_registers
-{
- unsigned num_regs;
- regoff_t *start;
- regoff_t *end;
-};
-
-
-/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
- `re_match_2' returns information about at least this many registers
- the first time a `regs' structure is passed. */
-#ifndef RE_NREGS
-# define RE_NREGS 30
-#endif
-
-
-/* POSIX specification for registers. Aside from the different names than
- `re_registers', POSIX uses an array of structures, instead of a
- structure of arrays. */
-typedef struct
-{
- regoff_t rm_so; /* Byte offset from string's start to substring's start. */
- regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
-} regmatch_t;
-
-/* Declarations for routines. */
-
-/* Sets the current default syntax to SYNTAX, and return the old syntax.
- You can also simply assign to the `re_syntax_options' variable. */
-extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
-
-/* Compile the regular expression PATTERN, with length LENGTH
- and syntax given by the global `re_syntax_options', into the buffer
- BUFFER. Return NULL if successful, and an error string if not. */
-extern const char *re_compile_pattern (const char *__pattern, size_t __length,
- struct re_pattern_buffer *__buffer);
-
-
-/* Compile a fastmap for the compiled pattern in BUFFER; used to
- accelerate searches. Return 0 if successful and -2 if was an
- internal error. */
-extern int re_compile_fastmap (struct re_pattern_buffer *__buffer);
-
-
-/* Search in the string STRING (with length LENGTH) for the pattern
- compiled into BUFFER. Start searching at position START, for RANGE
- characters. Return the starting position of the match, -1 for no
- match, or -2 for an internal error. Also return register
- information in REGS (if REGS and BUFFER->no_sub are nonzero). */
-extern int re_search (struct re_pattern_buffer *__buffer, const char *__string,
- int __length, int __start, int __range,
- struct re_registers *__regs);
-
-
-/* Like `re_search', but search in the concatenation of STRING1 and
- STRING2. Also, stop searching at index START + STOP. */
-extern int re_search_2 (struct re_pattern_buffer *__buffer,
- const char *__string1, int __length1,
- const char *__string2, int __length2, int __start,
- int __range, struct re_registers *__regs, int __stop);
-
-
-/* Like `re_search', but return how many characters in STRING the regexp
- in BUFFER matched, starting at position START. */
-extern int re_match (struct re_pattern_buffer *__buffer, const char *__string,
- int __length, int __start, struct re_registers *__regs);
-
-
-/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
-extern int re_match_2 (struct re_pattern_buffer *__buffer,
- const char *__string1, int __length1,
- const char *__string2, int __length2, int __start,
- struct re_registers *__regs, int __stop);
-
-
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
- ENDS. Subsequent matches using BUFFER and REGS will use this memory
- for recording register information. STARTS and ENDS must be
- allocated with malloc, and must each be at least `NUM_REGS * sizeof
- (regoff_t)' bytes long.
-
- If NUM_REGS == 0, then subsequent matches should allocate their own
- register data.
-
- Unless this function is called, the first search or match using
- PATTERN_BUFFER will allocate its own register data, without
- freeing the old data. */
-extern void re_set_registers (struct re_pattern_buffer *__buffer,
- struct re_registers *__regs,
- unsigned int __num_regs,
- regoff_t *__starts, regoff_t *__ends);
-
-#if defined _REGEX_RE_COMP || defined _LIBC
-# ifndef _CRAY
-/* 4.2 bsd compatibility. */
-extern char *re_comp (const char *);
-extern int re_exec (const char *);
-# endif
-#endif
-
-/* GCC 2.95 and later have "__restrict"; C99 compilers have
- "restrict", and "configure" may have defined "restrict". */
-#ifndef __restrict
-# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
-# if defined restrict || 199901L <= __STDC_VERSION__
-# define __restrict restrict
-# else
-# define __restrict
-# endif
-# endif
-#endif
-/* gcc 3.1 and up support the [restrict] syntax. */
-#ifndef __restrict_arr
-# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) \
- && !defined __GNUG__
-# define __restrict_arr __restrict
-# else
-# define __restrict_arr
-# endif
-#endif
-
-/* POSIX compatibility. */
-extern int regcomp (regex_t *__restrict __preg,
- const char *__restrict __pattern,
- int __cflags);
-
-extern int regexec (const regex_t *__restrict __preg,
- const char *__restrict __string, size_t __nmatch,
- regmatch_t __pmatch[__restrict_arr],
- int __eflags);
-
-extern size_t regerror (int __errcode, const regex_t *__restrict __preg,
- char *__restrict __errbuf, size_t __errbuf_size);
-
-extern void regfree (regex_t *__preg);
-
-
-#ifdef __cplusplus
-}
-#endif /* C++ */
-
-#endif /* regex.h */
diff --git a/xbmc/lib/libshout/libshout/regex/regex_internal.c b/xbmc/lib/libshout/libshout/regex/regex_internal.c
deleted file mode 100644
index 66154e0cea..0000000000
--- a/xbmc/lib/libshout/libshout/regex/regex_internal.c
+++ /dev/null
@@ -1,1717 +0,0 @@
-/* Extended regular expression matching and search library.
- Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
-
- The GNU C 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.
-
- The GNU C 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 GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-static void re_string_construct_common (const char *str, int len,
- re_string_t *pstr,
- RE_TRANSLATE_TYPE trans, int icase,
- const re_dfa_t *dfa) internal_function;
-static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa,
- const re_node_set *nodes,
- unsigned int hash) internal_function;
-static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,
- const re_node_set *nodes,
- unsigned int context,
- unsigned int hash) internal_function;
-
-/* Functions for string operation. */
-
-/* This function allocate the buffers. It is necessary to call
- re_string_reconstruct before using the object. */
-
-static reg_errcode_t
-internal_function
-re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,
- RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
-{
- reg_errcode_t ret;
- int init_buf_len;
-
- /* Ensure at least one character fits into the buffers. */
- if (init_len < dfa->mb_cur_max)
- init_len = dfa->mb_cur_max;
- init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
- re_string_construct_common (str, len, pstr, trans, icase, dfa);
-
- ret = re_string_realloc_buffers (pstr, init_buf_len);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
-
- pstr->word_char = dfa->word_char;
- pstr->word_ops_used = dfa->word_ops_used;
- pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
- pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
- pstr->valid_raw_len = pstr->valid_len;
- return REG_NOERROR;
-}
-
-/* This function allocate the buffers, and initialize them. */
-
-static reg_errcode_t
-internal_function
-re_string_construct (re_string_t *pstr, const char *str, int len,
- RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
-{
- reg_errcode_t ret;
- memset (pstr, '\0', sizeof (re_string_t));
- re_string_construct_common (str, len, pstr, trans, icase, dfa);
-
- if (len > 0)
- {
- ret = re_string_realloc_buffers (pstr, len + 1);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
- }
- pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
-
- if (icase)
- {
-#ifdef RE_ENABLE_I18N
- if (dfa->mb_cur_max > 1)
- {
- while (1)
- {
- ret = build_wcs_upper_buffer (pstr);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
- if (pstr->valid_raw_len >= len)
- break;
- if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
- break;
- ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
- }
- }
- else
-#endif /* RE_ENABLE_I18N */
- build_upper_buffer (pstr);
- }
- else
- {
-#ifdef RE_ENABLE_I18N
- if (dfa->mb_cur_max > 1)
- build_wcs_buffer (pstr);
- else
-#endif /* RE_ENABLE_I18N */
- {
- if (trans != NULL)
- re_string_translate_buffer (pstr);
- else
- {
- pstr->valid_len = pstr->bufs_len;
- pstr->valid_raw_len = pstr->bufs_len;
- }
- }
- }
-
- return REG_NOERROR;
-}
-
-/* Helper functions for re_string_allocate, and re_string_construct. */
-
-static reg_errcode_t
-internal_function
-re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
-{
-#ifdef RE_ENABLE_I18N
- if (pstr->mb_cur_max > 1)
- {
- wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
- if (BE (new_wcs == NULL, 0))
- return REG_ESPACE;
- pstr->wcs = new_wcs;
- if (pstr->offsets != NULL)
- {
- int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len);
- if (BE (new_offsets == NULL, 0))
- return REG_ESPACE;
- pstr->offsets = new_offsets;
- }
- }
-#endif /* RE_ENABLE_I18N */
- if (pstr->mbs_allocated)
- {
- unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char,
- new_buf_len);
- if (BE (new_mbs == NULL, 0))
- return REG_ESPACE;
- pstr->mbs = new_mbs;
- }
- pstr->bufs_len = new_buf_len;
- return REG_NOERROR;
-}
-
-
-static void
-internal_function
-re_string_construct_common (const char *str, int len, re_string_t *pstr,
- RE_TRANSLATE_TYPE trans, int icase,
- const re_dfa_t *dfa)
-{
- pstr->raw_mbs = (const unsigned char *) str;
- pstr->len = len;
- pstr->raw_len = len;
- pstr->trans = trans;
- pstr->icase = icase ? 1 : 0;
- pstr->mbs_allocated = (trans != NULL || icase);
- pstr->mb_cur_max = dfa->mb_cur_max;
- pstr->is_utf8 = dfa->is_utf8;
- pstr->map_notascii = dfa->map_notascii;
- pstr->stop = pstr->len;
- pstr->raw_stop = pstr->stop;
-}
-
-#ifdef RE_ENABLE_I18N
-
-/* Build wide character buffer PSTR->WCS.
- If the byte sequence of the string are:
- <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>
- Then wide character buffer will be:
- <wc1> , WEOF , <wc2> , WEOF , <wc3>
- We use WEOF for padding, they indicate that the position isn't
- a first byte of a multibyte character.
-
- Note that this function assumes PSTR->VALID_LEN elements are already
- built and starts from PSTR->VALID_LEN. */
-
-static void
-internal_function
-build_wcs_buffer (re_string_t *pstr)
-{
-#ifdef _LIBC
- unsigned char buf[MB_LEN_MAX];
- assert (MB_LEN_MAX >= pstr->mb_cur_max);
-#else
- unsigned char buf[64];
-#endif
- mbstate_t prev_st;
- int byte_idx, end_idx, remain_len;
- size_t mbclen;
-
- /* Build the buffers from pstr->valid_len to either pstr->len or
- pstr->bufs_len. */
- end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
- for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
- {
- wchar_t wc;
- const char *p;
-
- remain_len = end_idx - byte_idx;
- prev_st = pstr->cur_state;
- /* Apply the translation if we need. */
- if (BE (pstr->trans != NULL, 0))
- {
- int i, ch;
-
- for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
- {
- ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
- buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
- }
- p = (const char *) buf;
- }
- else
- p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;
- mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);
- if (BE (mbclen == (size_t) -2, 0))
- {
- /* The buffer doesn't have enough space, finish to build. */
- pstr->cur_state = prev_st;
- break;
- }
- else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0))
- {
- /* We treat these cases as a singlebyte character. */
- mbclen = 1;
- wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
- if (BE (pstr->trans != NULL, 0))
- wc = pstr->trans[wc];
- pstr->cur_state = prev_st;
- }
-
- /* Write wide character and padding. */
- pstr->wcs[byte_idx++] = wc;
- /* Write paddings. */
- for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
- pstr->wcs[byte_idx++] = WEOF;
- }
- pstr->valid_len = byte_idx;
- pstr->valid_raw_len = byte_idx;
-}
-
-/* Build wide character buffer PSTR->WCS like build_wcs_buffer,
- but for REG_ICASE. */
-
-static reg_errcode_t
-internal_function
-build_wcs_upper_buffer (re_string_t *pstr)
-{
- mbstate_t prev_st;
- int src_idx, byte_idx, end_idx, remain_len;
- size_t mbclen;
-#ifdef _LIBC
- char buf[MB_LEN_MAX];
- assert (MB_LEN_MAX >= pstr->mb_cur_max);
-#else
- char buf[64];
-#endif
-
- byte_idx = pstr->valid_len;
- end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
-
- /* The following optimization assumes that ASCII characters can be
- mapped to wide characters with a simple cast. */
- if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed)
- {
- while (byte_idx < end_idx)
- {
- wchar_t wc;
-
- if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])
- && mbsinit (&pstr->cur_state))
- {
- /* In case of a singlebyte character. */
- pstr->mbs[byte_idx]
- = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);
- /* The next step uses the assumption that wchar_t is encoded
- ASCII-safe: all ASCII values can be converted like this. */
- pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];
- ++byte_idx;
- continue;
- }
-
- remain_len = end_idx - byte_idx;
- prev_st = pstr->cur_state;
- mbclen = mbrtowc (&wc,
- ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
- + byte_idx), remain_len, &pstr->cur_state);
- if (BE (mbclen + 2 > 2, 1))
- {
- wchar_t wcu = wc;
- if (iswlower (wc))
- {
- size_t mbcdlen;
-
- wcu = towupper (wc);
- mbcdlen = wcrtomb (buf, wcu, &prev_st);
- if (BE (mbclen == mbcdlen, 1))
- memcpy (pstr->mbs + byte_idx, buf, mbclen);
- else
- {
- src_idx = byte_idx;
- goto offsets_needed;
- }
- }
- else
- memcpy (pstr->mbs + byte_idx,
- pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);
- pstr->wcs[byte_idx++] = wcu;
- /* Write paddings. */
- for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
- pstr->wcs[byte_idx++] = WEOF;
- }
- else if (mbclen == (size_t) -1 || mbclen == 0)
- {
- /* It is an invalid character or '\0'. Just use the byte. */
- int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
- pstr->mbs[byte_idx] = ch;
- /* And also cast it to wide char. */
- pstr->wcs[byte_idx++] = (wchar_t) ch;
- if (BE (mbclen == (size_t) -1, 0))
- pstr->cur_state = prev_st;
- }
- else
- {
- /* The buffer doesn't have enough space, finish to build. */
- pstr->cur_state = prev_st;
- break;
- }
- }
- pstr->valid_len = byte_idx;
- pstr->valid_raw_len = byte_idx;
- return REG_NOERROR;
- }
- else
- for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;)
- {
- wchar_t wc;
- const char *p;
- offsets_needed:
- remain_len = end_idx - byte_idx;
- prev_st = pstr->cur_state;
- if (BE (pstr->trans != NULL, 0))
- {
- int i, ch;
-
- for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
- {
- ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
- buf[i] = pstr->trans[ch];
- }
- p = (const char *) buf;
- }
- else
- p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;
- mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);
- if (BE (mbclen + 2 > 2, 1))
- {
- wchar_t wcu = wc;
- if (iswlower (wc))
- {
- size_t mbcdlen;
-
- wcu = towupper (wc);
- mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st);
- if (BE (mbclen == mbcdlen, 1))
- memcpy (pstr->mbs + byte_idx, buf, mbclen);
- else if (mbcdlen != (size_t) -1)
- {
- size_t i;
-
- if (byte_idx + mbcdlen > pstr->bufs_len)
- {
- pstr->cur_state = prev_st;
- break;
- }
-
- if (pstr->offsets == NULL)
- {
- pstr->offsets = re_malloc (int, pstr->bufs_len);
-
- if (pstr->offsets == NULL)
- return REG_ESPACE;
- }
- if (!pstr->offsets_needed)
- {
- for (i = 0; i < (size_t) byte_idx; ++i)
- pstr->offsets[i] = i;
- pstr->offsets_needed = 1;
- }
-
- memcpy (pstr->mbs + byte_idx, buf, mbcdlen);
- pstr->wcs[byte_idx] = wcu;
- pstr->offsets[byte_idx] = src_idx;
- for (i = 1; i < mbcdlen; ++i)
- {
- pstr->offsets[byte_idx + i]
- = src_idx + (i < mbclen ? i : mbclen - 1);
- pstr->wcs[byte_idx + i] = WEOF;
- }
- pstr->len += mbcdlen - mbclen;
- if (pstr->raw_stop > src_idx)
- pstr->stop += mbcdlen - mbclen;
- end_idx = (pstr->bufs_len > pstr->len)
- ? pstr->len : pstr->bufs_len;
- byte_idx += mbcdlen;
- src_idx += mbclen;
- continue;
- }
- else
- memcpy (pstr->mbs + byte_idx, p, mbclen);
- }
- else
- memcpy (pstr->mbs + byte_idx, p, mbclen);
-
- if (BE (pstr->offsets_needed != 0, 0))
- {
- size_t i;
- for (i = 0; i < mbclen; ++i)
- pstr->offsets[byte_idx + i] = src_idx + i;
- }
- src_idx += mbclen;
-
- pstr->wcs[byte_idx++] = wcu;
- /* Write paddings. */
- for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
- pstr->wcs[byte_idx++] = WEOF;
- }
- else if (mbclen == (size_t) -1 || mbclen == 0)
- {
- /* It is an invalid character or '\0'. Just use the byte. */
- int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];
-
- if (BE (pstr->trans != NULL, 0))
- ch = pstr->trans [ch];
- pstr->mbs[byte_idx] = ch;
-
- if (BE (pstr->offsets_needed != 0, 0))
- pstr->offsets[byte_idx] = src_idx;
- ++src_idx;
-
- /* And also cast it to wide char. */
- pstr->wcs[byte_idx++] = (wchar_t) ch;
- if (BE (mbclen == (size_t) -1, 0))
- pstr->cur_state = prev_st;
- }
- else
- {
- /* The buffer doesn't have enough space, finish to build. */
- pstr->cur_state = prev_st;
- break;
- }
- }
- pstr->valid_len = byte_idx;
- pstr->valid_raw_len = src_idx;
- return REG_NOERROR;
-}
-
-/* Skip characters until the index becomes greater than NEW_RAW_IDX.
- Return the index. */
-
-static int
-internal_function
-re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
-{
- mbstate_t prev_st;
- int rawbuf_idx;
- size_t mbclen;
- wchar_t wc = WEOF;
-
- /* Skip the characters which are not necessary to check. */
- for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;
- rawbuf_idx < new_raw_idx;)
- {
- int remain_len;
- remain_len = pstr->len - rawbuf_idx;
- prev_st = pstr->cur_state;
- mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx,
- remain_len, &pstr->cur_state);
- if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
- {
- /* We treat these cases as a single byte character. */
- if (mbclen == 0 || remain_len == 0)
- wc = L'\0';
- else
- wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx);
- mbclen = 1;
- pstr->cur_state = prev_st;
- }
- /* Then proceed the next character. */
- rawbuf_idx += mbclen;
- }
- *last_wc = (wint_t) wc;
- return rawbuf_idx;
-}
-#endif /* RE_ENABLE_I18N */
-
-/* Build the buffer PSTR->MBS, and apply the translation if we need.
- This function is used in case of REG_ICASE. */
-
-static void
-internal_function
-build_upper_buffer (re_string_t *pstr)
-{
- int char_idx, end_idx;
- end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
-
- for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
- {
- int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
- if (BE (pstr->trans != NULL, 0))
- ch = pstr->trans[ch];
- if (islower (ch))
- pstr->mbs[char_idx] = toupper (ch);
- else
- pstr->mbs[char_idx] = ch;
- }
- pstr->valid_len = char_idx;
- pstr->valid_raw_len = char_idx;
-}
-
-/* Apply TRANS to the buffer in PSTR. */
-
-static void
-internal_function
-re_string_translate_buffer (re_string_t *pstr)
-{
- int buf_idx, end_idx;
- end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
-
- for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
- {
- int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];
- pstr->mbs[buf_idx] = pstr->trans[ch];
- }
-
- pstr->valid_len = buf_idx;
- pstr->valid_raw_len = buf_idx;
-}
-
-/* This function re-construct the buffers.
- Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
- convert to upper case in case of REG_ICASE, apply translation. */
-
-static reg_errcode_t
-internal_function
-re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
-{
- int offset = idx - pstr->raw_mbs_idx;
- if (BE (offset < 0, 0))
- {
- /* Reset buffer. */
-#ifdef RE_ENABLE_I18N
- if (pstr->mb_cur_max > 1)
- memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
-#endif /* RE_ENABLE_I18N */
- pstr->len = pstr->raw_len;
- pstr->stop = pstr->raw_stop;
- pstr->valid_len = 0;
- pstr->raw_mbs_idx = 0;
- pstr->valid_raw_len = 0;
- pstr->offsets_needed = 0;
- pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
- : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
- if (!pstr->mbs_allocated)
- pstr->mbs = (unsigned char *) pstr->raw_mbs;
- offset = idx;
- }
-
- if (BE (offset != 0, 1))
- {
- /* Should the already checked characters be kept? */
- if (BE (offset < pstr->valid_raw_len, 1))
- {
- /* Yes, move them to the front of the buffer. */
-#ifdef RE_ENABLE_I18N
- if (BE (pstr->offsets_needed, 0))
- {
- int low = 0, high = pstr->valid_len, mid;
- do
- {
- mid = (high + low) / 2;
- if (pstr->offsets[mid] > offset)
- high = mid;
- else if (pstr->offsets[mid] < offset)
- low = mid + 1;
- else
- break;
- }
- while (low < high);
- if (pstr->offsets[mid] < offset)
- ++mid;
- pstr->tip_context = re_string_context_at (pstr, mid - 1,
- eflags);
- /* This can be quite complicated, so handle specially
- only the common and easy case where the character with
- different length representation of lower and upper
- case is present at or after offset. */
- if (pstr->valid_len > offset
- && mid == offset && pstr->offsets[mid] == offset)
- {
- memmove (pstr->wcs, pstr->wcs + offset,
- (pstr->valid_len - offset) * sizeof (wint_t));
- memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset);
- pstr->valid_len -= offset;
- pstr->valid_raw_len -= offset;
- for (low = 0; low < pstr->valid_len; low++)
- pstr->offsets[low] = pstr->offsets[low + offset] - offset;
- }
- else
- {
- /* Otherwise, just find out how long the partial multibyte
- character at offset is and fill it with WEOF/255. */
- pstr->len = pstr->raw_len - idx + offset;
- pstr->stop = pstr->raw_stop - idx + offset;
- pstr->offsets_needed = 0;
- while (mid > 0 && pstr->offsets[mid - 1] == offset)
- --mid;
- while (mid < pstr->valid_len)
- if (pstr->wcs[mid] != WEOF)
- break;
- else
- ++mid;
- if (mid == pstr->valid_len)
- pstr->valid_len = 0;
- else
- {
- pstr->valid_len = pstr->offsets[mid] - offset;
- if (pstr->valid_len)
- {
- for (low = 0; low < pstr->valid_len; ++low)
- pstr->wcs[low] = WEOF;
- memset (pstr->mbs, 255, pstr->valid_len);
- }
- }
- pstr->valid_raw_len = pstr->valid_len;
- }
- }
- else
-#endif
- {
- pstr->tip_context = re_string_context_at (pstr, offset - 1,
- eflags);
-#ifdef RE_ENABLE_I18N
- if (pstr->mb_cur_max > 1)
- memmove (pstr->wcs, pstr->wcs + offset,
- (pstr->valid_len - offset) * sizeof (wint_t));
-#endif /* RE_ENABLE_I18N */
- if (BE (pstr->mbs_allocated, 0))
- memmove (pstr->mbs, pstr->mbs + offset,
- pstr->valid_len - offset);
- pstr->valid_len -= offset;
- pstr->valid_raw_len -= offset;
-#if DEBUG
- assert (pstr->valid_len > 0);
-#endif
- }
- }
- else
- {
- /* No, skip all characters until IDX. */
- int prev_valid_len = pstr->valid_len;
-
-#ifdef RE_ENABLE_I18N
- if (BE (pstr->offsets_needed, 0))
- {
- pstr->len = pstr->raw_len - idx + offset;
- pstr->stop = pstr->raw_stop - idx + offset;
- pstr->offsets_needed = 0;
- }
-#endif
- pstr->valid_len = 0;
-#ifdef RE_ENABLE_I18N
- if (pstr->mb_cur_max > 1)
- {
- int wcs_idx;
- wint_t wc = WEOF;
-
- if (pstr->is_utf8)
- {
- const unsigned char *raw, *p, *q, *end;
-
- /* Special case UTF-8. Multi-byte chars start with any
- byte other than 0x80 - 0xbf. */
- raw = pstr->raw_mbs + pstr->raw_mbs_idx;
- end = raw + (offset - pstr->mb_cur_max);
- if (end < pstr->raw_mbs)
- end = pstr->raw_mbs;
- p = raw + offset - 1;
-#ifdef _LIBC
- /* We know the wchar_t encoding is UCS4, so for the simple
- case, ASCII characters, skip the conversion step. */
- if (isascii (*p) && BE (pstr->trans == NULL, 1))
- {
- memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
- /* pstr->valid_len = 0; */
- wc = (wchar_t) *p;
- }
- else
-#endif
- for (; p >= end; --p)
- if ((*p & 0xc0) != 0x80)
- {
- mbstate_t cur_state;
- wchar_t wc2;
- int mlen = raw + pstr->len - p;
- unsigned char buf[6];
- size_t mbclen;
-
- q = p;
- if (BE (pstr->trans != NULL, 0))
- {
- int i = mlen < 6 ? mlen : 6;
- while (--i >= 0)
- buf[i] = pstr->trans[p[i]];
- q = buf;
- }
- /* XXX Don't use mbrtowc, we know which conversion
- to use (UTF-8 -> UCS4). */
- memset (&cur_state, 0, sizeof (cur_state));
- mbclen = mbrtowc (&wc2, (const char *) p, mlen,
- &cur_state);
- if (raw + offset - p <= mbclen
- && mbclen < (size_t) -2)
- {
- memset (&pstr->cur_state, '\0',
- sizeof (mbstate_t));
- pstr->valid_len = mbclen - (raw + offset - p);
- wc = wc2;
- }
- break;
- }
- }
-
- if (wc == WEOF)
- pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
- if (wc == WEOF)
- pstr->tip_context
- = re_string_context_at (pstr, prev_valid_len - 1, eflags);
- else
- pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
- && IS_WIDE_WORD_CHAR (wc))
- ? CONTEXT_WORD
- : ((IS_WIDE_NEWLINE (wc)
- && pstr->newline_anchor)
- ? CONTEXT_NEWLINE : 0));
- if (BE (pstr->valid_len, 0))
- {
- for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
- pstr->wcs[wcs_idx] = WEOF;
- if (pstr->mbs_allocated)
- memset (pstr->mbs, 255, pstr->valid_len);
- }
- pstr->valid_raw_len = pstr->valid_len;
- }
- else
-#endif /* RE_ENABLE_I18N */
- {
- int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
- pstr->valid_raw_len = 0;
- if (pstr->trans)
- c = pstr->trans[c];
- pstr->tip_context = (bitset_contain (pstr->word_char, c)
- ? CONTEXT_WORD
- : ((IS_NEWLINE (c) && pstr->newline_anchor)
- ? CONTEXT_NEWLINE : 0));
- }
- }
- if (!BE (pstr->mbs_allocated, 0))
- pstr->mbs += offset;
- }
- pstr->raw_mbs_idx = idx;
- pstr->len -= offset;
- pstr->stop -= offset;
-
- /* Then build the buffers. */
-#ifdef RE_ENABLE_I18N
- if (pstr->mb_cur_max > 1)
- {
- if (pstr->icase)
- {
- reg_errcode_t ret = build_wcs_upper_buffer (pstr);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
- }
- else
- build_wcs_buffer (pstr);
- }
- else
-#endif /* RE_ENABLE_I18N */
- if (BE (pstr->mbs_allocated, 0))
- {
- if (pstr->icase)
- build_upper_buffer (pstr);
- else if (pstr->trans != NULL)
- re_string_translate_buffer (pstr);
- }
- else
- pstr->valid_len = pstr->len;
-
- pstr->cur_idx = 0;
- return REG_NOERROR;
-}
-
-static unsigned char
-internal_function __attribute ((pure))
-re_string_peek_byte_case (const re_string_t *pstr, int idx)
-{
- int ch, off;
-
- /* Handle the common (easiest) cases first. */
- if (BE (!pstr->mbs_allocated, 1))
- return re_string_peek_byte (pstr, idx);
-
-#ifdef RE_ENABLE_I18N
- if (pstr->mb_cur_max > 1
- && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
- return re_string_peek_byte (pstr, idx);
-#endif
-
- off = pstr->cur_idx + idx;
-#ifdef RE_ENABLE_I18N
- if (pstr->offsets_needed)
- off = pstr->offsets[off];
-#endif
-
- ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
-
-#ifdef RE_ENABLE_I18N
- /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I
- this function returns CAPITAL LETTER I instead of first byte of
- DOTLESS SMALL LETTER I. The latter would confuse the parser,
- since peek_byte_case doesn't advance cur_idx in any way. */
- if (pstr->offsets_needed && !isascii (ch))
- return re_string_peek_byte (pstr, idx);
-#endif
-
- return ch;
-}
-
-static unsigned char
-internal_function __attribute ((pure))
-re_string_fetch_byte_case (re_string_t *pstr)
-{
- if (BE (!pstr->mbs_allocated, 1))
- return re_string_fetch_byte (pstr);
-
-#ifdef RE_ENABLE_I18N
- if (pstr->offsets_needed)
- {
- int off, ch;
-
- /* For tr_TR.UTF-8 [[:islower:]] there is
- [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip
- in that case the whole multi-byte character and return
- the original letter. On the other side, with
- [[: DOTLESS SMALL LETTER I return [[:I, as doing
- anything else would complicate things too much. */
-
- if (!re_string_first_byte (pstr, pstr->cur_idx))
- return re_string_fetch_byte (pstr);
-
- off = pstr->offsets[pstr->cur_idx];
- ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
-
- if (! isascii (ch))
- return re_string_fetch_byte (pstr);
-
- re_string_skip_bytes (pstr,
- re_string_char_size_at (pstr, pstr->cur_idx));
- return ch;
- }
-#endif
-
- return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++];
-}
-
-static void
-internal_function
-re_string_destruct (re_string_t *pstr)
-{
-#ifdef RE_ENABLE_I18N
- re_free (pstr->wcs);
- re_free (pstr->offsets);
-#endif /* RE_ENABLE_I18N */
- if (pstr->mbs_allocated)
- re_free (pstr->mbs);
-}
-
-/* Return the context at IDX in INPUT. */
-
-static unsigned int
-internal_function
-re_string_context_at (const re_string_t *input, int idx, int eflags)
-{
- int c;
- if (BE (idx < 0, 0))
- /* In this case, we use the value stored in input->tip_context,
- since we can't know the character in input->mbs[-1] here. */
- return input->tip_context;
- if (BE (idx == input->len, 0))
- return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
- : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
-#ifdef RE_ENABLE_I18N
- if (input->mb_cur_max > 1)
- {
- wint_t wc;
- int wc_idx = idx;
- while(input->wcs[wc_idx] == WEOF)
- {
-#ifdef DEBUG
- /* It must not happen. */
- assert (wc_idx >= 0);
-#endif
- --wc_idx;
- if (wc_idx < 0)
- return input->tip_context;
- }
- wc = input->wcs[wc_idx];
- if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc))
- return CONTEXT_WORD;
- return (IS_WIDE_NEWLINE (wc) && input->newline_anchor
- ? CONTEXT_NEWLINE : 0);
- }
- else
-#endif
- {
- c = re_string_byte_at (input, idx);
- if (bitset_contain (input->word_char, c))
- return CONTEXT_WORD;
- return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0;
- }
-}
-
-/* Functions for set operation. */
-
-static reg_errcode_t
-internal_function
-re_node_set_alloc (re_node_set *set, int size)
-{
- set->alloc = size;
- set->nelem = 0;
- set->elems = re_malloc (int, size);
- if (BE (set->elems == NULL, 0))
- return REG_ESPACE;
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-internal_function
-re_node_set_init_1 (re_node_set *set, int elem)
-{
- set->alloc = 1;
- set->nelem = 1;
- set->elems = re_malloc (int, 1);
- if (BE (set->elems == NULL, 0))
- {
- set->alloc = set->nelem = 0;
- return REG_ESPACE;
- }
- set->elems[0] = elem;
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-internal_function
-re_node_set_init_2 (re_node_set *set, int elem1, int elem2)
-{
- set->alloc = 2;
- set->elems = re_malloc (int, 2);
- if (BE (set->elems == NULL, 0))
- return REG_ESPACE;
- if (elem1 == elem2)
- {
- set->nelem = 1;
- set->elems[0] = elem1;
- }
- else
- {
- set->nelem = 2;
- if (elem1 < elem2)
- {
- set->elems[0] = elem1;
- set->elems[1] = elem2;
- }
- else
- {
- set->elems[0] = elem2;
- set->elems[1] = elem1;
- }
- }
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-internal_function
-re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
-{
- dest->nelem = src->nelem;
- if (src->nelem > 0)
- {
- dest->alloc = dest->nelem;
- dest->elems = re_malloc (int, dest->alloc);
- if (BE (dest->elems == NULL, 0))
- {
- dest->alloc = dest->nelem = 0;
- return REG_ESPACE;
- }
- memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
- }
- else
- re_node_set_init_empty (dest);
- return REG_NOERROR;
-}
-
-/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
- DEST. Return value indicate the error code or REG_NOERROR if succeeded.
- Note: We assume dest->elems is NULL, when dest->alloc is 0. */
-
-static reg_errcode_t
-internal_function
-re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
- const re_node_set *src2)
-{
- int i1, i2, is, id, delta, sbase;
- if (src1->nelem == 0 || src2->nelem == 0)
- return REG_NOERROR;
-
- /* We need dest->nelem + 2 * elems_in_intersection; this is a
- conservative estimate. */
- if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
- {
- int new_alloc = src1->nelem + src2->nelem + dest->alloc;
- int *new_elems = re_realloc (dest->elems, int, new_alloc);
- if (BE (new_elems == NULL, 0))
- return REG_ESPACE;
- dest->elems = new_elems;
- dest->alloc = new_alloc;
- }
-
- /* Find the items in the intersection of SRC1 and SRC2, and copy
- into the top of DEST those that are not already in DEST itself. */
- sbase = dest->nelem + src1->nelem + src2->nelem;
- i1 = src1->nelem - 1;
- i2 = src2->nelem - 1;
- id = dest->nelem - 1;
- for (;;)
- {
- if (src1->elems[i1] == src2->elems[i2])
- {
- /* Try to find the item in DEST. Maybe we could binary search? */
- while (id >= 0 && dest->elems[id] > src1->elems[i1])
- --id;
-
- if (id < 0 || dest->elems[id] != src1->elems[i1])
- dest->elems[--sbase] = src1->elems[i1];
-
- if (--i1 < 0 || --i2 < 0)
- break;
- }
-
- /* Lower the highest of the two items. */
- else if (src1->elems[i1] < src2->elems[i2])
- {
- if (--i2 < 0)
- break;
- }
- else
- {
- if (--i1 < 0)
- break;
- }
- }
-
- id = dest->nelem - 1;
- is = dest->nelem + src1->nelem + src2->nelem - 1;
- delta = is - sbase + 1;
-
- /* Now copy. When DELTA becomes zero, the remaining
- DEST elements are already in place; this is more or
- less the same loop that is in re_node_set_merge. */
- dest->nelem += delta;
- if (delta > 0 && id >= 0)
- for (;;)
- {
- if (dest->elems[is] > dest->elems[id])
- {
- /* Copy from the top. */
- dest->elems[id + delta--] = dest->elems[is--];
- if (delta == 0)
- break;
- }
- else
- {
- /* Slide from the bottom. */
- dest->elems[id + delta] = dest->elems[id];
- if (--id < 0)
- break;
- }
- }
-
- /* Copy remaining SRC elements. */
- memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int));
-
- return REG_NOERROR;
-}
-
-/* Calculate the union set of the sets SRC1 and SRC2. And store it to
- DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
-
-static reg_errcode_t
-internal_function
-re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
- const re_node_set *src2)
-{
- int i1, i2, id;
- if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
- {
- dest->alloc = src1->nelem + src2->nelem;
- dest->elems = re_malloc (int, dest->alloc);
- if (BE (dest->elems == NULL, 0))
- return REG_ESPACE;
- }
- else
- {
- if (src1 != NULL && src1->nelem > 0)
- return re_node_set_init_copy (dest, src1);
- else if (src2 != NULL && src2->nelem > 0)
- return re_node_set_init_copy (dest, src2);
- else
- re_node_set_init_empty (dest);
- return REG_NOERROR;
- }
- for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
- {
- if (src1->elems[i1] > src2->elems[i2])
- {
- dest->elems[id++] = src2->elems[i2++];
- continue;
- }
- if (src1->elems[i1] == src2->elems[i2])
- ++i2;
- dest->elems[id++] = src1->elems[i1++];
- }
- if (i1 < src1->nelem)
- {
- memcpy (dest->elems + id, src1->elems + i1,
- (src1->nelem - i1) * sizeof (int));
- id += src1->nelem - i1;
- }
- else if (i2 < src2->nelem)
- {
- memcpy (dest->elems + id, src2->elems + i2,
- (src2->nelem - i2) * sizeof (int));
- id += src2->nelem - i2;
- }
- dest->nelem = id;
- return REG_NOERROR;
-}
-
-/* Calculate the union set of the sets DEST and SRC. And store it to
- DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
-
-static reg_errcode_t
-internal_function
-re_node_set_merge (re_node_set *dest, const re_node_set *src)
-{
- int is, id, sbase, delta;
- if (src == NULL || src->nelem == 0)
- return REG_NOERROR;
- if (dest->alloc < 2 * src->nelem + dest->nelem)
- {
- int new_alloc = 2 * (src->nelem + dest->alloc);
- int *new_buffer = re_realloc (dest->elems, int, new_alloc);
- if (BE (new_buffer == NULL, 0))
- return REG_ESPACE;
- dest->elems = new_buffer;
- dest->alloc = new_alloc;
- }
-
- if (BE (dest->nelem == 0, 0))
- {
- dest->nelem = src->nelem;
- memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
- return REG_NOERROR;
- }
-
- /* Copy into the top of DEST the items of SRC that are not
- found in DEST. Maybe we could binary search in DEST? */
- for (sbase = dest->nelem + 2 * src->nelem,
- is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; )
- {
- if (dest->elems[id] == src->elems[is])
- is--, id--;
- else if (dest->elems[id] < src->elems[is])
- dest->elems[--sbase] = src->elems[is--];
- else /* if (dest->elems[id] > src->elems[is]) */
- --id;
- }
-
- if (is >= 0)
- {
- /* If DEST is exhausted, the remaining items of SRC must be unique. */
- sbase -= is + 1;
- memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int));
- }
-
- id = dest->nelem - 1;
- is = dest->nelem + 2 * src->nelem - 1;
- delta = is - sbase + 1;
- if (delta == 0)
- return REG_NOERROR;
-
- /* Now copy. When DELTA becomes zero, the remaining
- DEST elements are already in place. */
- dest->nelem += delta;
- for (;;)
- {
- if (dest->elems[is] > dest->elems[id])
- {
- /* Copy from the top. */
- dest->elems[id + delta--] = dest->elems[is--];
- if (delta == 0)
- break;
- }
- else
- {
- /* Slide from the bottom. */
- dest->elems[id + delta] = dest->elems[id];
- if (--id < 0)
- {
- /* Copy remaining SRC elements. */
- memcpy (dest->elems, dest->elems + sbase,
- delta * sizeof (int));
- break;
- }
- }
- }
-
- return REG_NOERROR;
-}
-
-/* Insert the new element ELEM to the re_node_set* SET.
- SET should not already have ELEM.
- return -1 if an error is occured, return 1 otherwise. */
-
-static int
-internal_function
-re_node_set_insert (re_node_set *set, int elem)
-{
- int idx;
- /* In case the set is empty. */
- if (set->alloc == 0)
- {
- if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1))
- return 1;
- else
- return -1;
- }
-
- if (BE (set->nelem, 0) == 0)
- {
- /* We already guaranteed above that set->alloc != 0. */
- set->elems[0] = elem;
- ++set->nelem;
- return 1;
- }
-
- /* Realloc if we need. */
- if (set->alloc == set->nelem)
- {
- int *new_elems;
- set->alloc = set->alloc * 2;
- new_elems = re_realloc (set->elems, int, set->alloc);
- if (BE (new_elems == NULL, 0))
- return -1;
- set->elems = new_elems;
- }
-
- /* Move the elements which follows the new element. Test the
- first element separately to skip a check in the inner loop. */
- if (elem < set->elems[0])
- {
- idx = 0;
- for (idx = set->nelem; idx > 0; idx--)
- set->elems[idx] = set->elems[idx - 1];
- }
- else
- {
- for (idx = set->nelem; set->elems[idx - 1] > elem; idx--)
- set->elems[idx] = set->elems[idx - 1];
- }
-
- /* Insert the new element. */
- set->elems[idx] = elem;
- ++set->nelem;
- return 1;
-}
-
-/* Insert the new element ELEM to the re_node_set* SET.
- SET should not already have any element greater than or equal to ELEM.
- Return -1 if an error is occured, return 1 otherwise. */
-
-static int
-internal_function
-re_node_set_insert_last (re_node_set *set, int elem)
-{
- /* Realloc if we need. */
- if (set->alloc == set->nelem)
- {
- int *new_elems;
- set->alloc = (set->alloc + 1) * 2;
- new_elems = re_realloc (set->elems, int, set->alloc);
- if (BE (new_elems == NULL, 0))
- return -1;
- set->elems = new_elems;
- }
-
- /* Insert the new element. */
- set->elems[set->nelem++] = elem;
- return 1;
-}
-
-/* Compare two node sets SET1 and SET2.
- return 1 if SET1 and SET2 are equivalent, return 0 otherwise. */
-
-static int
-internal_function __attribute ((pure))
-re_node_set_compare (const re_node_set *set1, const re_node_set *set2)
-{
- int i;
- if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)
- return 0;
- for (i = set1->nelem ; --i >= 0 ; )
- if (set1->elems[i] != set2->elems[i])
- return 0;
- return 1;
-}
-
-/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */
-
-static int
-internal_function __attribute ((pure))
-re_node_set_contains (const re_node_set *set, int elem)
-{
- unsigned int idx, right, mid;
- if (set->nelem <= 0)
- return 0;
-
- /* Binary search the element. */
- idx = 0;
- right = set->nelem - 1;
- while (idx < right)
- {
- mid = (idx + right) / 2;
- if (set->elems[mid] < elem)
- idx = mid + 1;
- else
- right = mid;
- }
- return set->elems[idx] == elem ? idx + 1 : 0;
-}
-
-static void
-internal_function
-re_node_set_remove_at (re_node_set *set, int idx)
-{
- if (idx < 0 || idx >= set->nelem)
- return;
- --set->nelem;
- for (; idx < set->nelem; idx++)
- set->elems[idx] = set->elems[idx + 1];
-}
-
-
-/* Add the token TOKEN to dfa->nodes, and return the index of the token.
- Or return -1, if an error will be occured. */
-
-static int
-internal_function
-re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
-{
- int type = token.type;
- if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0))
- {
- size_t new_nodes_alloc = dfa->nodes_alloc * 2;
- int *new_nexts, *new_indices;
- re_node_set *new_edests, *new_eclosures;
- re_token_t *new_nodes;
-
- /* Avoid overflows. */
- if (BE (new_nodes_alloc < dfa->nodes_alloc, 0))
- return -1;
-
- new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc);
- if (BE (new_nodes == NULL, 0))
- return -1;
- dfa->nodes = new_nodes;
- new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc);
- new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc);
- new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
- new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc);
- if (BE (new_nexts == NULL || new_indices == NULL
- || new_edests == NULL || new_eclosures == NULL, 0))
- return -1;
- dfa->nexts = new_nexts;
- dfa->org_indices = new_indices;
- dfa->edests = new_edests;
- dfa->eclosures = new_eclosures;
- dfa->nodes_alloc = new_nodes_alloc;
- }
- dfa->nodes[dfa->nodes_len] = token;
- dfa->nodes[dfa->nodes_len].constraint = 0;
-#ifdef RE_ENABLE_I18N
- dfa->nodes[dfa->nodes_len].accept_mb =
- (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET;
-#endif
- dfa->nexts[dfa->nodes_len] = -1;
- re_node_set_init_empty (dfa->edests + dfa->nodes_len);
- re_node_set_init_empty (dfa->eclosures + dfa->nodes_len);
- return dfa->nodes_len++;
-}
-
-static inline unsigned int
-internal_function
-calc_state_hash (const re_node_set *nodes, unsigned int context)
-{
- unsigned int hash = nodes->nelem + context;
- int i;
- for (i = 0 ; i < nodes->nelem ; i++)
- hash += nodes->elems[i];
- return hash;
-}
-
-/* Search for the state whose node_set is equivalent to NODES.
- Return the pointer to the state, if we found it in the DFA.
- Otherwise create the new one and return it. In case of an error
- return NULL and set the error code in ERR.
- Note: - We assume NULL as the invalid state, then it is possible that
- return value is NULL and ERR is REG_NOERROR.
- - We never return non-NULL value in case of any errors, it is for
- optimization. */
-
-static re_dfastate_t *
-internal_function
-re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,
- const re_node_set *nodes)
-{
- unsigned int hash;
- re_dfastate_t *new_state;
- struct re_state_table_entry *spot;
- int i;
- if (BE (nodes->nelem == 0, 0))
- {
- *err = REG_NOERROR;
- return NULL;
- }
- hash = calc_state_hash (nodes, 0);
- spot = dfa->state_table + (hash & dfa->state_hash_mask);
-
- for (i = 0 ; i < spot->num ; i++)
- {
- re_dfastate_t *state = spot->array[i];
- if (hash != state->hash)
- continue;
- if (re_node_set_compare (&state->nodes, nodes))
- return state;
- }
-
- /* There are no appropriate state in the dfa, create the new one. */
- new_state = create_ci_newstate (dfa, nodes, hash);
- if (BE (new_state == NULL, 0))
- *err = REG_ESPACE;
-
- return new_state;
-}
-
-/* Search for the state whose node_set is equivalent to NODES and
- whose context is equivalent to CONTEXT.
- Return the pointer to the state, if we found it in the DFA.
- Otherwise create the new one and return it. In case of an error
- return NULL and set the error code in ERR.
- Note: - We assume NULL as the invalid state, then it is possible that
- return value is NULL and ERR is REG_NOERROR.
- - We never return non-NULL value in case of any errors, it is for
- optimization. */
-
-static re_dfastate_t *
-internal_function
-re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
- const re_node_set *nodes, unsigned int context)
-{
- unsigned int hash;
- re_dfastate_t *new_state;
- struct re_state_table_entry *spot;
- int i;
- if (nodes->nelem == 0)
- {
- *err = REG_NOERROR;
- return NULL;
- }
- hash = calc_state_hash (nodes, context);
- spot = dfa->state_table + (hash & dfa->state_hash_mask);
-
- for (i = 0 ; i < spot->num ; i++)
- {
- re_dfastate_t *state = spot->array[i];
- if (state->hash == hash
- && state->context == context
- && re_node_set_compare (state->entrance_nodes, nodes))
- return state;
- }
- /* There are no appropriate state in `dfa', create the new one. */
- new_state = create_cd_newstate (dfa, nodes, context, hash);
- if (BE (new_state == NULL, 0))
- *err = REG_ESPACE;
-
- return new_state;
-}
-
-/* Finish initialization of the new state NEWSTATE, and using its hash value
- HASH put in the appropriate bucket of DFA's state table. Return value
- indicates the error code if failed. */
-
-static reg_errcode_t
-register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,
- unsigned int hash)
-{
- struct re_state_table_entry *spot;
- reg_errcode_t err;
- int i;
-
- newstate->hash = hash;
- err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem);
- if (BE (err != REG_NOERROR, 0))
- return REG_ESPACE;
- for (i = 0; i < newstate->nodes.nelem; i++)
- {
- int elem = newstate->nodes.elems[i];
- if (!IS_EPSILON_NODE (dfa->nodes[elem].type))
- re_node_set_insert_last (&newstate->non_eps_nodes, elem);
- }
-
- spot = dfa->state_table + (hash & dfa->state_hash_mask);
- if (BE (spot->alloc <= spot->num, 0))
- {
- int new_alloc = 2 * spot->num + 2;
- re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *,
- new_alloc);
- if (BE (new_array == NULL, 0))
- return REG_ESPACE;
- spot->array = new_array;
- spot->alloc = new_alloc;
- }
- spot->array[spot->num++] = newstate;
- return REG_NOERROR;
-}
-
-static void
-free_state (re_dfastate_t *state)
-{
- re_node_set_free (&state->non_eps_nodes);
- re_node_set_free (&state->inveclosure);
- if (state->entrance_nodes != &state->nodes)
- {
- re_node_set_free (state->entrance_nodes);
- re_free (state->entrance_nodes);
- }
- re_node_set_free (&state->nodes);
- re_free (state->word_trtable);
- re_free (state->trtable);
- re_free (state);
-}
-
-/* Create the new state which is independ of contexts.
- Return the new state if succeeded, otherwise return NULL. */
-
-static re_dfastate_t *
-internal_function
-create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
- unsigned int hash)
-{
- int i;
- reg_errcode_t err;
- re_dfastate_t *newstate;
-
- newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
- if (BE (newstate == NULL, 0))
- return NULL;
- err = re_node_set_init_copy (&newstate->nodes, nodes);
- if (BE (err != REG_NOERROR, 0))
- {
- re_free (newstate);
- return NULL;
- }
-
- newstate->entrance_nodes = &newstate->nodes;
- for (i = 0 ; i < nodes->nelem ; i++)
- {
- re_token_t *node = dfa->nodes + nodes->elems[i];
- re_token_type_t type = node->type;
- if (type == CHARACTER && !node->constraint)
- continue;
-#ifdef RE_ENABLE_I18N
- newstate->accept_mb |= node->accept_mb;
-#endif /* RE_ENABLE_I18N */
-
- /* If the state has the halt node, the state is a halt state. */
- if (type == END_OF_RE)
- newstate->halt = 1;
- else if (type == OP_BACK_REF)
- newstate->has_backref = 1;
- else if (type == ANCHOR || node->constraint)
- newstate->has_constraint = 1;
- }
- err = register_state (dfa, newstate, hash);
- if (BE (err != REG_NOERROR, 0))
- {
- free_state (newstate);
- newstate = NULL;
- }
- return newstate;
-}
-
-/* Create the new state which is depend on the context CONTEXT.
- Return the new state if succeeded, otherwise return NULL. */
-
-static re_dfastate_t *
-internal_function
-create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
- unsigned int context, unsigned int hash)
-{
- int i, nctx_nodes = 0;
- reg_errcode_t err;
- re_dfastate_t *newstate;
-
- newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
- if (BE (newstate == NULL, 0))
- return NULL;
- err = re_node_set_init_copy (&newstate->nodes, nodes);
- if (BE (err != REG_NOERROR, 0))
- {
- re_free (newstate);
- return NULL;
- }
-
- newstate->context = context;
- newstate->entrance_nodes = &newstate->nodes;
-
- for (i = 0 ; i < nodes->nelem ; i++)
- {
- unsigned int constraint = 0;
- re_token_t *node = dfa->nodes + nodes->elems[i];
- re_token_type_t type = node->type;
- if (node->constraint)
- constraint = node->constraint;
-
- if (type == CHARACTER && !constraint)
- continue;
-#ifdef RE_ENABLE_I18N
- newstate->accept_mb |= node->accept_mb;
-#endif /* RE_ENABLE_I18N */
-
- /* If the state has the halt node, the state is a halt state. */
- if (type == END_OF_RE)
- newstate->halt = 1;
- else if (type == OP_BACK_REF)
- newstate->has_backref = 1;
- else if (type == ANCHOR)
- constraint = node->opr.ctx_type;
-
- if (constraint)
- {
- if (newstate->entrance_nodes == &newstate->nodes)
- {
- newstate->entrance_nodes = re_malloc (re_node_set, 1);
- if (BE (newstate->entrance_nodes == NULL, 0))
- {
- free_state (newstate);
- return NULL;
- }
- re_node_set_init_copy (newstate->entrance_nodes, nodes);
- nctx_nodes = 0;
- newstate->has_constraint = 1;
- }
-
- if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context))
- {
- re_node_set_remove_at (&newstate->nodes, i - nctx_nodes);
- ++nctx_nodes;
- }
- }
- }
- err = register_state (dfa, newstate, hash);
- if (BE (err != REG_NOERROR, 0))
- {
- free_state (newstate);
- newstate = NULL;
- }
- return newstate;
-}
diff --git a/xbmc/lib/libshout/libshout/regex/regex_internal.h b/xbmc/lib/libshout/libshout/regex/regex_internal.h
deleted file mode 100644
index 24d0fbba7d..0000000000
--- a/xbmc/lib/libshout/libshout/regex/regex_internal.h
+++ /dev/null
@@ -1,767 +0,0 @@
-/* Extended regular expression matching and search library.
- Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
-
- The GNU C 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.
-
- The GNU C 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 GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _REGEX_INTERNAL_H
-#define _REGEX_INTERNAL_H 1
-
-#include <assert.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC
-# include <langinfo.h>
-#endif
-#if defined HAVE_LOCALE_H || defined _LIBC
-# include <locale.h>
-#endif
-#if defined HAVE_WCHAR_H || defined _LIBC
-# include <wchar.h>
-#endif /* HAVE_WCHAR_H || _LIBC */
-#if defined HAVE_WCTYPE_H || defined _LIBC
-# include <wctype.h>
-#endif /* HAVE_WCTYPE_H || _LIBC */
-#if defined HAVE_STDBOOL_H || defined _LIBC
-# include <stdbool.h>
-#endif /* HAVE_STDBOOL_H || _LIBC */
-#if defined HAVE_STDINT_H || defined _LIBC
-# include <stdint.h>
-#endif /* HAVE_STDINT_H || _LIBC */
-#if defined _LIBC
-# include <bits/libc-lock.h>
-#else
-# define __libc_lock_define(CLASS,NAME)
-# define __libc_lock_init(NAME) do { } while (0)
-# define __libc_lock_lock(NAME) do { } while (0)
-# define __libc_lock_unlock(NAME) do { } while (0)
-#endif
-
-/* In case that the system doesn't have isblank(). */
-#if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank
-# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
-#endif
-
-#ifdef _LIBC
-# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
-# define _RE_DEFINE_LOCALE_FUNCTIONS 1
-# include <locale/localeinfo.h>
-# include <locale/elem-hash.h>
-# include <locale/coll-lookup.h>
-# endif
-#endif
-
-/* This is for other GNU distributions with internationalized messages. */
-#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
-# include <libintl.h>
-# ifdef _LIBC
-# undef gettext
-# define gettext(msgid) \
- INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES)
-# endif
-#else
-# define gettext(msgid) (msgid)
-#endif
-
-#ifndef gettext_noop
-/* This define is so xgettext can find the internationalizable
- strings. */
-# define gettext_noop(String) String
-#endif
-
-/* For loser systems without the definition. */
-#ifndef SIZE_MAX
-# define SIZE_MAX ((size_t) -1)
-#endif
-
-#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC
-# define RE_ENABLE_I18N
-#endif
-
-#if __GNUC__ >= 3
-# define BE(expr, val) __builtin_expect (expr, val)
-#else
-# define BE(expr, val) (expr)
-# define inline
-#endif
-
-/* Number of single byte character. */
-#define SBC_MAX 256
-
-#define COLL_ELEM_LEN_MAX 8
-
-/* The character which represents newline. */
-#define NEWLINE_CHAR '\n'
-#define WIDE_NEWLINE_CHAR L'\n'
-
-/* Rename to standard API for using out of glibc. */
-#ifndef _LIBC
-# define __wctype wctype
-# define __iswctype iswctype
-# define __btowc btowc
-# define __mempcpy mempcpy
-# define __wcrtomb wcrtomb
-# define __regfree regfree
-# define attribute_hidden
-#endif /* not _LIBC */
-
-#ifdef __GNUC__
-# define __attribute(arg) __attribute__ (arg)
-#else
-# define __attribute(arg)
-#endif
-
-extern const char __re_error_msgid[] attribute_hidden;
-extern const size_t __re_error_msgid_idx[] attribute_hidden;
-
-/* An integer used to represent a set of bits. It must be unsigned,
- and must be at least as wide as unsigned int. */
-typedef unsigned long int bitset_word_t;
-/* All bits set in a bitset_word_t. */
-#define BITSET_WORD_MAX ULONG_MAX
-/* Number of bits in a bitset_word_t. */
-#define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT)
-/* Number of bitset_word_t in a bit_set. */
-#define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS)
-typedef bitset_word_t bitset_t[BITSET_WORDS];
-typedef bitset_word_t *re_bitset_ptr_t;
-typedef const bitset_word_t *re_const_bitset_ptr_t;
-
-#define bitset_set(set,i) \
- (set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS)
-#define bitset_clear(set,i) \
- (set[i / BITSET_WORD_BITS] &= ~((bitset_word_t) 1 << i % BITSET_WORD_BITS))
-#define bitset_contain(set,i) \
- (set[i / BITSET_WORD_BITS] & ((bitset_word_t) 1 << i % BITSET_WORD_BITS))
-#define bitset_empty(set) memset (set, '\0', sizeof (bitset_t))
-#define bitset_set_all(set) memset (set, '\xff', sizeof (bitset_t))
-#define bitset_copy(dest,src) memcpy (dest, src, sizeof (bitset_t))
-
-#define PREV_WORD_CONSTRAINT 0x0001
-#define PREV_NOTWORD_CONSTRAINT 0x0002
-#define NEXT_WORD_CONSTRAINT 0x0004
-#define NEXT_NOTWORD_CONSTRAINT 0x0008
-#define PREV_NEWLINE_CONSTRAINT 0x0010
-#define NEXT_NEWLINE_CONSTRAINT 0x0020
-#define PREV_BEGBUF_CONSTRAINT 0x0040
-#define NEXT_ENDBUF_CONSTRAINT 0x0080
-#define WORD_DELIM_CONSTRAINT 0x0100
-#define NOT_WORD_DELIM_CONSTRAINT 0x0200
-
-typedef enum
-{
- INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
- WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
- WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
- INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
- LINE_FIRST = PREV_NEWLINE_CONSTRAINT,
- LINE_LAST = NEXT_NEWLINE_CONSTRAINT,
- BUF_FIRST = PREV_BEGBUF_CONSTRAINT,
- BUF_LAST = NEXT_ENDBUF_CONSTRAINT,
- WORD_DELIM = WORD_DELIM_CONSTRAINT,
- NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT
-} re_context_type;
-
-typedef struct
-{
- int alloc;
- int nelem;
- int *elems;
-} re_node_set;
-
-typedef enum
-{
- NON_TYPE = 0,
-
- /* Node type, These are used by token, node, tree. */
- CHARACTER = 1,
- END_OF_RE = 2,
- SIMPLE_BRACKET = 3,
- OP_BACK_REF = 4,
- OP_PERIOD = 5,
-#ifdef RE_ENABLE_I18N
- COMPLEX_BRACKET = 6,
- OP_UTF8_PERIOD = 7,
-#endif /* RE_ENABLE_I18N */
-
- /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used
- when the debugger shows values of this enum type. */
-#define EPSILON_BIT 8
- OP_OPEN_SUBEXP = EPSILON_BIT | 0,
- OP_CLOSE_SUBEXP = EPSILON_BIT | 1,
- OP_ALT = EPSILON_BIT | 2,
- OP_DUP_ASTERISK = EPSILON_BIT | 3,
- ANCHOR = EPSILON_BIT | 4,
-
- /* Tree type, these are used only by tree. */
- CONCAT = 16,
- SUBEXP = 17,
-
- /* Token type, these are used only by token. */
- OP_DUP_PLUS = 18,
- OP_DUP_QUESTION,
- OP_OPEN_BRACKET,
- OP_CLOSE_BRACKET,
- OP_CHARSET_RANGE,
- OP_OPEN_DUP_NUM,
- OP_CLOSE_DUP_NUM,
- OP_NON_MATCH_LIST,
- OP_OPEN_COLL_ELEM,
- OP_CLOSE_COLL_ELEM,
- OP_OPEN_EQUIV_CLASS,
- OP_CLOSE_EQUIV_CLASS,
- OP_OPEN_CHAR_CLASS,
- OP_CLOSE_CHAR_CLASS,
- OP_WORD,
- OP_NOTWORD,
- OP_SPACE,
- OP_NOTSPACE,
- BACK_SLASH
-
-} re_token_type_t;
-
-#ifdef RE_ENABLE_I18N
-typedef struct
-{
- /* Multibyte characters. */
- wchar_t *mbchars;
-
- /* Collating symbols. */
-# ifdef _LIBC
- int32_t *coll_syms;
-# endif
-
- /* Equivalence classes. */
-# ifdef _LIBC
- int32_t *equiv_classes;
-# endif
-
- /* Range expressions. */
-# ifdef _LIBC
- uint32_t *range_starts;
- uint32_t *range_ends;
-# else /* not _LIBC */
- wchar_t *range_starts;
- wchar_t *range_ends;
-# endif /* not _LIBC */
-
- /* Character classes. */
- wctype_t *char_classes;
-
- /* If this character set is the non-matching list. */
- unsigned int non_match : 1;
-
- /* # of multibyte characters. */
- int nmbchars;
-
- /* # of collating symbols. */
- int ncoll_syms;
-
- /* # of equivalence classes. */
- int nequiv_classes;
-
- /* # of range expressions. */
- int nranges;
-
- /* # of character classes. */
- int nchar_classes;
-} re_charset_t;
-#endif /* RE_ENABLE_I18N */
-
-typedef struct
-{
- union
- {
- unsigned char c; /* for CHARACTER */
- re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */
-#ifdef RE_ENABLE_I18N
- re_charset_t *mbcset; /* for COMPLEX_BRACKET */
-#endif /* RE_ENABLE_I18N */
- int idx; /* for BACK_REF */
- re_context_type ctx_type; /* for ANCHOR */
- } opr;
-#if __GNUC__ >= 2
- re_token_type_t type : 8;
-#else
- re_token_type_t type;
-#endif
- unsigned int constraint : 10; /* context constraint */
- unsigned int duplicated : 1;
- unsigned int opt_subexp : 1;
-#ifdef RE_ENABLE_I18N
- unsigned int accept_mb : 1;
- /* These 2 bits can be moved into the union if needed (e.g. if running out
- of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */
- unsigned int mb_partial : 1;
-#endif
- unsigned int word_char : 1;
-} re_token_t;
-
-#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT)
-
-struct re_string_t
-{
- /* Indicate the raw buffer which is the original string passed as an
- argument of regexec(), re_search(), etc.. */
- const unsigned char *raw_mbs;
- /* Store the multibyte string. In case of "case insensitive mode" like
- REG_ICASE, upper cases of the string are stored, otherwise MBS points
- the same address that RAW_MBS points. */
- unsigned char *mbs;
-#ifdef RE_ENABLE_I18N
- /* Store the wide character string which is corresponding to MBS. */
- wint_t *wcs;
- int *offsets;
- mbstate_t cur_state;
-#endif
- /* Index in RAW_MBS. Each character mbs[i] corresponds to
- raw_mbs[raw_mbs_idx + i]. */
- int raw_mbs_idx;
- /* The length of the valid characters in the buffers. */
- int valid_len;
- /* The corresponding number of bytes in raw_mbs array. */
- int valid_raw_len;
- /* The length of the buffers MBS and WCS. */
- int bufs_len;
- /* The index in MBS, which is updated by re_string_fetch_byte. */
- int cur_idx;
- /* length of RAW_MBS array. */
- int raw_len;
- /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */
- int len;
- /* End of the buffer may be shorter than its length in the cases such
- as re_match_2, re_search_2. Then, we use STOP for end of the buffer
- instead of LEN. */
- int raw_stop;
- /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */
- int stop;
-
- /* The context of mbs[0]. We store the context independently, since
- the context of mbs[0] may be different from raw_mbs[0], which is
- the beginning of the input string. */
- unsigned int tip_context;
- /* The translation passed as a part of an argument of re_compile_pattern. */
- RE_TRANSLATE_TYPE trans;
- /* Copy of re_dfa_t's word_char. */
- re_const_bitset_ptr_t word_char;
- /* 1 if REG_ICASE. */
- unsigned char icase;
- unsigned char is_utf8;
- unsigned char map_notascii;
- unsigned char mbs_allocated;
- unsigned char offsets_needed;
- unsigned char newline_anchor;
- unsigned char word_ops_used;
- int mb_cur_max;
-};
-typedef struct re_string_t re_string_t;
-
-
-struct re_dfa_t;
-typedef struct re_dfa_t re_dfa_t;
-
-#ifndef _LIBC
-# ifdef __i386__
-# define internal_function __attribute ((regparm (3), stdcall))
-# else
-# define internal_function
-# endif
-#endif
-
-#ifndef NOT_IN_libc
-static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
- int new_buf_len)
- internal_function;
-# ifdef RE_ENABLE_I18N
-static void build_wcs_buffer (re_string_t *pstr) internal_function;
-static int build_wcs_upper_buffer (re_string_t *pstr) internal_function;
-# endif /* RE_ENABLE_I18N */
-static void build_upper_buffer (re_string_t *pstr) internal_function;
-static void re_string_translate_buffer (re_string_t *pstr) internal_function;
-static unsigned int re_string_context_at (const re_string_t *input, int idx,
- int eflags)
- internal_function __attribute ((pure));
-#endif
-#define re_string_peek_byte(pstr, offset) \
- ((pstr)->mbs[(pstr)->cur_idx + offset])
-#define re_string_fetch_byte(pstr) \
- ((pstr)->mbs[(pstr)->cur_idx++])
-#define re_string_first_byte(pstr, idx) \
- ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF)
-#define re_string_is_single_byte_char(pstr, idx) \
- ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \
- || (pstr)->wcs[(idx) + 1] != WEOF))
-#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx)
-#define re_string_cur_idx(pstr) ((pstr)->cur_idx)
-#define re_string_get_buffer(pstr) ((pstr)->mbs)
-#define re_string_length(pstr) ((pstr)->len)
-#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
-#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
-#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
-
-#include <alloca.h>
-
-#ifndef _LIBC
-# if HAVE_ALLOCA
-/* The OS usually guarantees only one guard page at the bottom of the stack,
- and a page size can be as small as 4096 bytes. So we cannot safely
- allocate anything larger than 4096 bytes. Also care for the possibility
- of a few compiler-allocated temporary stack slots. */
-# define __libc_use_alloca(n) ((n) < 4032)
-# else
-/* alloca is implemented with malloc, so just use malloc. */
-# define __libc_use_alloca(n) 0
-# endif
-#endif
-
-#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
-#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
-#define re_free(p) free (p)
-
-struct bin_tree_t
-{
- struct bin_tree_t *parent;
- struct bin_tree_t *left;
- struct bin_tree_t *right;
- struct bin_tree_t *first;
- struct bin_tree_t *next;
-
- re_token_t token;
-
- /* `node_idx' is the index in dfa->nodes, if `type' == 0.
- Otherwise `type' indicate the type of this node. */
- int node_idx;
-};
-typedef struct bin_tree_t bin_tree_t;
-
-#define BIN_TREE_STORAGE_SIZE \
- ((1024 - sizeof (void *)) / sizeof (bin_tree_t))
-
-struct bin_tree_storage_t
-{
- struct bin_tree_storage_t *next;
- bin_tree_t data[BIN_TREE_STORAGE_SIZE];
-};
-typedef struct bin_tree_storage_t bin_tree_storage_t;
-
-#define CONTEXT_WORD 1
-#define CONTEXT_NEWLINE (CONTEXT_WORD << 1)
-#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1)
-#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1)
-
-#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD)
-#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE)
-#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF)
-#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF)
-#define IS_ORDINARY_CONTEXT(c) ((c) == 0)
-
-#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_')
-#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR)
-#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_')
-#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR)
-
-#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \
- ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
- || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
- || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\
- || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context)))
-
-#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \
- ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
- || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
- || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \
- || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context)))
-
-struct re_dfastate_t
-{
- unsigned int hash;
- re_node_set nodes;
- re_node_set non_eps_nodes;
- re_node_set inveclosure;
- re_node_set *entrance_nodes;
- struct re_dfastate_t **trtable, **word_trtable;
- unsigned int context : 4;
- unsigned int halt : 1;
- /* If this state can accept `multi byte'.
- Note that we refer to multibyte characters, and multi character
- collating elements as `multi byte'. */
- unsigned int accept_mb : 1;
- /* If this state has backreference node(s). */
- unsigned int has_backref : 1;
- unsigned int has_constraint : 1;
-};
-typedef struct re_dfastate_t re_dfastate_t;
-
-struct re_state_table_entry
-{
- int num;
- int alloc;
- re_dfastate_t **array;
-};
-
-/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */
-
-typedef struct
-{
- int next_idx;
- int alloc;
- re_dfastate_t **array;
-} state_array_t;
-
-/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */
-
-typedef struct
-{
- int node;
- int str_idx; /* The position NODE match at. */
- state_array_t path;
-} re_sub_match_last_t;
-
-/* Store information about the node NODE whose type is OP_OPEN_SUBEXP.
- And information about the node, whose type is OP_CLOSE_SUBEXP,
- corresponding to NODE is stored in LASTS. */
-
-typedef struct
-{
- int str_idx;
- int node;
- state_array_t *path;
- int alasts; /* Allocation size of LASTS. */
- int nlasts; /* The number of LASTS. */
- re_sub_match_last_t **lasts;
-} re_sub_match_top_t;
-
-struct re_backref_cache_entry
-{
- int node;
- int str_idx;
- int subexp_from;
- int subexp_to;
- char more;
- char unused;
- unsigned short int eps_reachable_subexps_map;
-};
-
-typedef struct
-{
- /* The string object corresponding to the input string. */
- re_string_t input;
-#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
- const re_dfa_t *const dfa;
-#else
- const re_dfa_t *dfa;
-#endif
- /* EFLAGS of the argument of regexec. */
- int eflags;
- /* Where the matching ends. */
- int match_last;
- int last_node;
- /* The state log used by the matcher. */
- re_dfastate_t **state_log;
- int state_log_top;
- /* Back reference cache. */
- int nbkref_ents;
- int abkref_ents;
- struct re_backref_cache_entry *bkref_ents;
- int max_mb_elem_len;
- int nsub_tops;
- int asub_tops;
- re_sub_match_top_t **sub_tops;
-} re_match_context_t;
-
-typedef struct
-{
- re_dfastate_t **sifted_states;
- re_dfastate_t **limited_states;
- int last_node;
- int last_str_idx;
- re_node_set limits;
-} re_sift_context_t;
-
-struct re_fail_stack_ent_t
-{
- int idx;
- int node;
- regmatch_t *regs;
- re_node_set eps_via_nodes;
-};
-
-struct re_fail_stack_t
-{
- int num;
- int alloc;
- struct re_fail_stack_ent_t *stack;
-};
-
-struct re_dfa_t
-{
- re_token_t *nodes;
- size_t nodes_alloc;
- size_t nodes_len;
- int *nexts;
- int *org_indices;
- re_node_set *edests;
- re_node_set *eclosures;
- re_node_set *inveclosures;
- struct re_state_table_entry *state_table;
- re_dfastate_t *init_state;
- re_dfastate_t *init_state_word;
- re_dfastate_t *init_state_nl;
- re_dfastate_t *init_state_begbuf;
- bin_tree_t *str_tree;
- bin_tree_storage_t *str_tree_storage;
- re_bitset_ptr_t sb_char;
- int str_tree_storage_idx;
-
- /* number of subexpressions `re_nsub' is in regex_t. */
- unsigned int state_hash_mask;
- int init_node;
- int nbackref; /* The number of backreference in this dfa. */
-
- /* Bitmap expressing which backreference is used. */
- bitset_word_t used_bkref_map;
- bitset_word_t completed_bkref_map;
-
- unsigned int has_plural_match : 1;
- /* If this dfa has "multibyte node", which is a backreference or
- a node which can accept multibyte character or multi character
- collating element. */
- unsigned int has_mb_node : 1;
- unsigned int is_utf8 : 1;
- unsigned int map_notascii : 1;
- unsigned int word_ops_used : 1;
- int mb_cur_max;
- bitset_t word_char;
- reg_syntax_t syntax;
- int *subexp_map;
-#ifdef DEBUG
- char* re_str;
-#endif
- __libc_lock_define (, lock)
-};
-
-#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
-#define re_node_set_remove(set,id) \
- (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
-#define re_node_set_empty(p) ((p)->nelem = 0)
-#define re_node_set_free(set) re_free ((set)->elems)
-
-
-typedef enum
-{
- SB_CHAR,
- MB_CHAR,
- EQUIV_CLASS,
- COLL_SYM,
- CHAR_CLASS
-} bracket_elem_type;
-
-typedef struct
-{
- bracket_elem_type type;
- union
- {
- unsigned char ch;
- unsigned char *name;
- wchar_t wch;
- } opr;
-} bracket_elem_t;
-
-
-/* Inline functions for bitset operation. */
-static inline void
-bitset_not (bitset_t set)
-{
- int bitset_i;
- for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
- set[bitset_i] = ~set[bitset_i];
-}
-
-static inline void
-bitset_merge (bitset_t dest, const bitset_t src)
-{
- int bitset_i;
- for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
- dest[bitset_i] |= src[bitset_i];
-}
-
-static inline void
-bitset_mask (bitset_t dest, const bitset_t src)
-{
- int bitset_i;
- for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
- dest[bitset_i] &= src[bitset_i];
-}
-
-#ifdef RE_ENABLE_I18N
-/* Inline functions for re_string. */
-static inline int
-internal_function __attribute ((pure))
-re_string_char_size_at (const re_string_t *pstr, int idx)
-{
- int byte_idx;
- if (pstr->mb_cur_max == 1)
- return 1;
- for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
- if (pstr->wcs[idx + byte_idx] != WEOF)
- break;
- return byte_idx;
-}
-
-static inline wint_t
-internal_function __attribute ((pure))
-re_string_wchar_at (const re_string_t *pstr, int idx)
-{
- if (pstr->mb_cur_max == 1)
- return (wint_t) pstr->mbs[idx];
- return (wint_t) pstr->wcs[idx];
-}
-
-# ifndef NOT_IN_libc
-static int
-internal_function __attribute ((pure))
-re_string_elem_size_at (const re_string_t *pstr, int idx)
-{
-# ifdef _LIBC
- const unsigned char *p, *extra;
- const int32_t *table, *indirect;
- int32_t tmp;
-# include <locale/weight.h>
- uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
-
- if (nrules != 0)
- {
- table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
- extra = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
- indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_INDIRECTMB);
- p = pstr->mbs + idx;
- tmp = findidx (&p);
- return p - pstr->mbs - idx;
- }
- else
-# endif /* _LIBC */
- return 1;
-}
-# endif
-#endif /* RE_ENABLE_I18N */
-
-#endif /* _REGEX_INTERNAL_H */
diff --git a/xbmc/lib/libshout/libshout/regex/regexec.c b/xbmc/lib/libshout/libshout/regex/regexec.c
deleted file mode 100644
index 135efe7441..0000000000
--- a/xbmc/lib/libshout/libshout/regex/regexec.c
+++ /dev/null
@@ -1,4333 +0,0 @@
-/* Extended regular expression matching and search library.
- Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
-
- The GNU C 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.
-
- The GNU C 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 GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
- int n) internal_function;
-static void match_ctx_clean (re_match_context_t *mctx) internal_function;
-static void match_ctx_free (re_match_context_t *cache) internal_function;
-static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node,
- int str_idx, int from, int to)
- internal_function;
-static int search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
- internal_function;
-static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node,
- int str_idx) internal_function;
-static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop,
- int node, int str_idx)
- internal_function;
-static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
- re_dfastate_t **limited_sts, int last_node,
- int last_str_idx)
- internal_function;
-static reg_errcode_t re_search_internal (const regex_t *preg,
- const char *string, int length,
- int start, int range, int stop,
- size_t nmatch, regmatch_t pmatch[],
- int eflags) internal_function;
-static int re_search_2_stub (struct re_pattern_buffer *bufp,
- const char *string1, int length1,
- const char *string2, int length2,
- int start, int range, struct re_registers *regs,
- int stop, int ret_len) internal_function;
-static int re_search_stub (struct re_pattern_buffer *bufp,
- const char *string, int length, int start,
- int range, int stop, struct re_registers *regs,
- int ret_len) internal_function;
-static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch,
- int nregs, int regs_allocated) internal_function;
-static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx)
- internal_function;
-static int check_matching (re_match_context_t *mctx, int fl_longest_match,
- int *p_match_first) internal_function;
-static int check_halt_state_context (const re_match_context_t *mctx,
- const re_dfastate_t *state, int idx)
- internal_function;
-static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
- regmatch_t *prev_idx_match, int cur_node,
- int cur_idx, int nmatch) internal_function;
-static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
- int str_idx, int dest_node, int nregs,
- regmatch_t *regs,
- re_node_set *eps_via_nodes)
- internal_function;
-static reg_errcode_t set_regs (const regex_t *preg,
- const re_match_context_t *mctx,
- size_t nmatch, regmatch_t *pmatch,
- int fl_backtrack) internal_function;
-static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs)
- internal_function;
-
-#ifdef RE_ENABLE_I18N
-static int sift_states_iter_mb (const re_match_context_t *mctx,
- re_sift_context_t *sctx,
- int node_idx, int str_idx, int max_str_idx)
- internal_function;
-#endif /* RE_ENABLE_I18N */
-static reg_errcode_t sift_states_backward (const re_match_context_t *mctx,
- re_sift_context_t *sctx)
- internal_function;
-static reg_errcode_t build_sifted_states (const re_match_context_t *mctx,
- re_sift_context_t *sctx, int str_idx,
- re_node_set *cur_dest)
- internal_function;
-static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx,
- re_sift_context_t *sctx,
- int str_idx,
- re_node_set *dest_nodes)
- internal_function;
-static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa,
- re_node_set *dest_nodes,
- const re_node_set *candidates)
- internal_function;
-static int check_dst_limits (const re_match_context_t *mctx,
- re_node_set *limits,
- int dst_node, int dst_idx, int src_node,
- int src_idx) internal_function;
-static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx,
- int boundaries, int subexp_idx,
- int from_node, int bkref_idx)
- internal_function;
-static int check_dst_limits_calc_pos (const re_match_context_t *mctx,
- int limit, int subexp_idx,
- int node, int str_idx,
- int bkref_idx) internal_function;
-static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa,
- re_node_set *dest_nodes,
- const re_node_set *candidates,
- re_node_set *limits,
- struct re_backref_cache_entry *bkref_ents,
- int str_idx) internal_function;
-static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx,
- re_sift_context_t *sctx,
- int str_idx, const re_node_set *candidates)
- internal_function;
-static reg_errcode_t merge_state_array (const re_dfa_t *dfa,
- re_dfastate_t **dst,
- re_dfastate_t **src, int num)
- internal_function;
-static re_dfastate_t *find_recover_state (reg_errcode_t *err,
- re_match_context_t *mctx) internal_function;
-static re_dfastate_t *transit_state (reg_errcode_t *err,
- re_match_context_t *mctx,
- re_dfastate_t *state) internal_function;
-static re_dfastate_t *merge_state_with_log (reg_errcode_t *err,
- re_match_context_t *mctx,
- re_dfastate_t *next_state)
- internal_function;
-static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx,
- re_node_set *cur_nodes,
- int str_idx) internal_function;
-#if 0
-static re_dfastate_t *transit_state_sb (reg_errcode_t *err,
- re_match_context_t *mctx,
- re_dfastate_t *pstate)
- internal_function;
-#endif
-#ifdef RE_ENABLE_I18N
-static reg_errcode_t transit_state_mb (re_match_context_t *mctx,
- re_dfastate_t *pstate)
- internal_function;
-#endif /* RE_ENABLE_I18N */
-static reg_errcode_t transit_state_bkref (re_match_context_t *mctx,
- const re_node_set *nodes)
- internal_function;
-static reg_errcode_t get_subexp (re_match_context_t *mctx,
- int bkref_node, int bkref_str_idx)
- internal_function;
-static reg_errcode_t get_subexp_sub (re_match_context_t *mctx,
- const re_sub_match_top_t *sub_top,
- re_sub_match_last_t *sub_last,
- int bkref_node, int bkref_str)
- internal_function;
-static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
- int subexp_idx, int type) internal_function;
-static reg_errcode_t check_arrival (re_match_context_t *mctx,
- state_array_t *path, int top_node,
- int top_str, int last_node, int last_str,
- int type) internal_function;
-static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx,
- int str_idx,
- re_node_set *cur_nodes,
- re_node_set *next_nodes)
- internal_function;
-static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa,
- re_node_set *cur_nodes,
- int ex_subexp, int type)
- internal_function;
-static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa,
- re_node_set *dst_nodes,
- int target, int ex_subexp,
- int type) internal_function;
-static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx,
- re_node_set *cur_nodes, int cur_str,
- int subexp_num, int type)
- internal_function;
-static int build_trtable (const re_dfa_t *dfa,
- re_dfastate_t *state) internal_function;
-#ifdef RE_ENABLE_I18N
-static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
- const re_string_t *input, int idx)
- internal_function;
-# ifdef _LIBC
-static unsigned int find_collation_sequence_value (const unsigned char *mbs,
- size_t name_len)
- internal_function;
-# endif /* _LIBC */
-#endif /* RE_ENABLE_I18N */
-static int group_nodes_into_DFAstates (const re_dfa_t *dfa,
- const re_dfastate_t *state,
- re_node_set *states_node,
- bitset_t *states_ch) internal_function;
-static int check_node_accept (const re_match_context_t *mctx,
- const re_token_t *node, int idx)
- internal_function;
-static reg_errcode_t extend_buffers (re_match_context_t *mctx)
- internal_function;
-
-/* Entry point for POSIX code. */
-
-/* regexec searches for a given pattern, specified by PREG, in the
- string STRING.
-
- If NMATCH is zero or REG_NOSUB was set in the cflags argument to
- `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
- least NMATCH elements, and we set them to the offsets of the
- corresponding matched substrings.
-
- EFLAGS specifies `execution flags' which affect matching: if
- REG_NOTBOL is set, then ^ does not match at the beginning of the
- string; if REG_NOTEOL is set, then $ does not match at the end.
-
- We return 0 if we find a match and REG_NOMATCH if not. */
-
-int
-regexec (preg, string, nmatch, pmatch, eflags)
- const regex_t *__restrict preg;
- const char *__restrict string;
- size_t nmatch;
- regmatch_t pmatch[];
- int eflags;
-{
- reg_errcode_t err;
- int start, length;
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-
- if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND))
- return REG_BADPAT;
-
- if (eflags & REG_STARTEND)
- {
- start = pmatch[0].rm_so;
- length = pmatch[0].rm_eo;
- }
- else
- {
- start = 0;
- length = strlen (string);
- }
-
- __libc_lock_lock (dfa->lock);
- if (preg->no_sub)
- err = re_search_internal (preg, string, length, start, length - start,
- length, 0, NULL, eflags);
- else
- err = re_search_internal (preg, string, length, start, length - start,
- length, nmatch, pmatch, eflags);
- __libc_lock_unlock (dfa->lock);
- return err != REG_NOERROR;
-}
-
-#ifdef _LIBC
-# include <shlib-compat.h>
-versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
-
-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
-__typeof__ (__regexec) __compat_regexec;
-
-int
-attribute_compat_text_section
-__compat_regexec (const regex_t *__restrict preg,
- const char *__restrict string, size_t nmatch,
- regmatch_t pmatch[], int eflags)
-{
- return regexec (preg, string, nmatch, pmatch,
- eflags & (REG_NOTBOL | REG_NOTEOL));
-}
-compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
-# endif
-#endif
-
-/* Entry points for GNU code. */
-
-/* re_match, re_search, re_match_2, re_search_2
-
- The former two functions operate on STRING with length LENGTH,
- while the later two operate on concatenation of STRING1 and STRING2
- with lengths LENGTH1 and LENGTH2, respectively.
-
- re_match() matches the compiled pattern in BUFP against the string,
- starting at index START.
-
- re_search() first tries matching at index START, then it tries to match
- starting from index START + 1, and so on. The last start position tried
- is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same
- way as re_match().)
-
- The parameter STOP of re_{match,search}_2 specifies that no match exceeding
- the first STOP characters of the concatenation of the strings should be
- concerned.
-
- If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match
- and all groups is stroed in REGS. (For the "_2" variants, the offsets are
- computed relative to the concatenation, not relative to the individual
- strings.)
-
- On success, re_match* functions return the length of the match, re_search*
- return the position of the start of the match. Return value -1 means no
- match was found and -2 indicates an internal error. */
-
-int
-re_match (bufp, string, length, start, regs)
- struct re_pattern_buffer *bufp;
- const char *string;
- int length, start;
- struct re_registers *regs;
-{
- return re_search_stub (bufp, string, length, start, 0, length, regs, 1);
-}
-#ifdef _LIBC
-weak_alias (__re_match, re_match)
-#endif
-
-int
-re_search (bufp, string, length, start, range, regs)
- struct re_pattern_buffer *bufp;
- const char *string;
- int length, start, range;
- struct re_registers *regs;
-{
- return re_search_stub (bufp, string, length, start, range, length, regs, 0);
-}
-#ifdef _LIBC
-weak_alias (__re_search, re_search)
-#endif
-
-int
-re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop)
- struct re_pattern_buffer *bufp;
- const char *string1, *string2;
- int length1, length2, start, stop;
- struct re_registers *regs;
-{
- return re_search_2_stub (bufp, string1, length1, string2, length2,
- start, 0, regs, stop, 1);
-}
-#ifdef _LIBC
-weak_alias (__re_match_2, re_match_2)
-#endif
-
-int
-re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop)
- struct re_pattern_buffer *bufp;
- const char *string1, *string2;
- int length1, length2, start, range, stop;
- struct re_registers *regs;
-{
- return re_search_2_stub (bufp, string1, length1, string2, length2,
- start, range, regs, stop, 0);
-}
-#ifdef _LIBC
-weak_alias (__re_search_2, re_search_2)
-#endif
-
-static int
-re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs,
- stop, ret_len)
- struct re_pattern_buffer *bufp;
- const char *string1, *string2;
- int length1, length2, start, range, stop, ret_len;
- struct re_registers *regs;
-{
- const char *str;
- int rval;
- int len = length1 + length2;
- int free_str = 0;
-
- if (BE (length1 < 0 || length2 < 0 || stop < 0, 0))
- return -2;
-
- /* Concatenate the strings. */
- if (length2 > 0)
- if (length1 > 0)
- {
- char *s = re_malloc (char, len);
-
- if (BE (s == NULL, 0))
- return -2;
-#ifdef _LIBC
- memcpy (__mempcpy (s, string1, length1), string2, length2);
-#else
- memcpy (s, string1, length1);
- memcpy (s + length1, string2, length2);
-#endif
- str = s;
- free_str = 1;
- }
- else
- str = string2;
- else
- str = string1;
-
- rval = re_search_stub (bufp, str, len, start, range, stop, regs,
- ret_len);
- if (free_str)
- re_free ((char *) str);
- return rval;
-}
-
-/* The parameters have the same meaning as those of re_search.
- Additional parameters:
- If RET_LEN is nonzero the length of the match is returned (re_match style);
- otherwise the position of the match is returned. */
-
-static int
-re_search_stub (bufp, string, length, start, range, stop, regs, ret_len)
- struct re_pattern_buffer *bufp;
- const char *string;
- int length, start, range, stop, ret_len;
- struct re_registers *regs;
-{
- reg_errcode_t result;
- regmatch_t *pmatch;
- int nregs, rval;
- int eflags = 0;
- re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
-
- /* Check for out-of-range. */
- if (BE (start < 0 || start > length, 0))
- return -1;
- if (BE (start + range > length, 0))
- range = length - start;
- else if (BE (start + range < 0, 0))
- range = -start;
-
- __libc_lock_lock (dfa->lock);
-
- eflags |= (bufp->not_bol) ? REG_NOTBOL : 0;
- eflags |= (bufp->not_eol) ? REG_NOTEOL : 0;
-
- /* Compile fastmap if we haven't yet. */
- if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate)
- re_compile_fastmap (bufp);
-
- if (BE (bufp->no_sub, 0))
- regs = NULL;
-
- /* We need at least 1 register. */
- if (regs == NULL)
- nregs = 1;
- else if (BE (bufp->regs_allocated == REGS_FIXED &&
- regs->num_regs < bufp->re_nsub + 1, 0))
- {
- nregs = regs->num_regs;
- if (BE (nregs < 1, 0))
- {
- /* Nothing can be copied to regs. */
- regs = NULL;
- nregs = 1;
- }
- }
- else
- nregs = bufp->re_nsub + 1;
- pmatch = re_malloc (regmatch_t, nregs);
- if (BE (pmatch == NULL, 0))
- {
- rval = -2;
- goto out;
- }
-
- result = re_search_internal (bufp, string, length, start, range, stop,
- nregs, pmatch, eflags);
-
- rval = 0;
-
- /* I hope we needn't fill ther regs with -1's when no match was found. */
- if (result != REG_NOERROR)
- rval = -1;
- else if (regs != NULL)
- {
- /* If caller wants register contents data back, copy them. */
- bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs,
- bufp->regs_allocated);
- if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0))
- rval = -2;
- }
-
- if (BE (rval == 0, 1))
- {
- if (ret_len)
- {
- assert (pmatch[0].rm_so == start);
- rval = pmatch[0].rm_eo - start;
- }
- else
- rval = pmatch[0].rm_so;
- }
- re_free (pmatch);
- out:
- __libc_lock_unlock (dfa->lock);
- return rval;
-}
-
-static unsigned
-re_copy_regs (regs, pmatch, nregs, regs_allocated)
- struct re_registers *regs;
- regmatch_t *pmatch;
- int nregs, regs_allocated;
-{
- int rval = REGS_REALLOCATE;
- int i;
- int need_regs = nregs + 1;
- /* We need one extra element beyond `num_regs' for the `-1' marker GNU code
- uses. */
-
- /* Have the register data arrays been allocated? */
- if (regs_allocated == REGS_UNALLOCATED)
- { /* No. So allocate them with malloc. */
- regs->start = re_malloc (regoff_t, need_regs);
- regs->end = re_malloc (regoff_t, need_regs);
- if (BE (regs->start == NULL, 0) || BE (regs->end == NULL, 0))
- return REGS_UNALLOCATED;
- regs->num_regs = need_regs;
- }
- else if (regs_allocated == REGS_REALLOCATE)
- { /* Yes. If we need more elements than were already
- allocated, reallocate them. If we need fewer, just
- leave it alone. */
- if (BE (need_regs > regs->num_regs, 0))
- {
- regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs);
- regoff_t *new_end = re_realloc (regs->end, regoff_t, need_regs);
- if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0))
- return REGS_UNALLOCATED;
- regs->start = new_start;
- regs->end = new_end;
- regs->num_regs = need_regs;
- }
- }
- else
- {
- assert (regs_allocated == REGS_FIXED);
- /* This function may not be called with REGS_FIXED and nregs too big. */
- assert (regs->num_regs >= nregs);
- rval = REGS_FIXED;
- }
-
- /* Copy the regs. */
- for (i = 0; i < nregs; ++i)
- {
- regs->start[i] = pmatch[i].rm_so;
- regs->end[i] = pmatch[i].rm_eo;
- }
- for ( ; i < regs->num_regs; ++i)
- regs->start[i] = regs->end[i] = -1;
-
- return rval;
-}
-
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
- ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
- this memory for recording register information. STARTS and ENDS
- must be allocated using the malloc library routine, and must each
- be at least NUM_REGS * sizeof (regoff_t) bytes long.
-
- If NUM_REGS == 0, then subsequent matches should allocate their own
- register data.
-
- Unless this function is called, the first search or match using
- PATTERN_BUFFER will allocate its own register data, without
- freeing the old data. */
-
-void
-re_set_registers (bufp, regs, num_regs, starts, ends)
- struct re_pattern_buffer *bufp;
- struct re_registers *regs;
- unsigned num_regs;
- regoff_t *starts, *ends;
-{
- if (num_regs)
- {
- bufp->regs_allocated = REGS_REALLOCATE;
- regs->num_regs = num_regs;
- regs->start = starts;
- regs->end = ends;
- }
- else
- {
- bufp->regs_allocated = REGS_UNALLOCATED;
- regs->num_regs = 0;
- regs->start = regs->end = (regoff_t *) 0;
- }
-}
-#ifdef _LIBC
-weak_alias (__re_set_registers, re_set_registers)
-#endif
-
-/* Entry points compatible with 4.2 BSD regex library. We don't define
- them unless specifically requested. */
-
-#if defined _REGEX_RE_COMP || defined _LIBC
-int
-# ifdef _LIBC
-weak_function
-# endif
-re_exec (s)
- const char *s;
-{
- return 0 == regexec (&re_comp_buf, s, 0, NULL, 0);
-}
-#endif /* _REGEX_RE_COMP */
-
-/* Internal entry point. */
-
-/* Searches for a compiled pattern PREG in the string STRING, whose
- length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same
- mingings with regexec. START, and RANGE have the same meanings
- with re_search.
- Return REG_NOERROR if we find a match, and REG_NOMATCH if not,
- otherwise return the error code.
- Note: We assume front end functions already check ranges.
- (START + RANGE >= 0 && START + RANGE <= LENGTH) */
-
-static reg_errcode_t
-re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
- eflags)
- const regex_t *preg;
- const char *string;
- int length, start, range, stop, eflags;
- size_t nmatch;
- regmatch_t pmatch[];
-{
- reg_errcode_t err;
- const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
- int left_lim, right_lim, incr;
- int fl_longest_match, match_first, match_kind, match_last = -1;
- int extra_nmatch;
- int sb, ch;
-#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
- re_match_context_t mctx = { .dfa = dfa };
-#else
- re_match_context_t mctx;
-#endif
- char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate
- && range && !preg->can_be_null) ? preg->fastmap : NULL;
- RE_TRANSLATE_TYPE t = preg->translate;
-
-#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
- memset (&mctx, '\0', sizeof (re_match_context_t));
- mctx.dfa = dfa;
-#endif
-
- extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0;
- nmatch -= extra_nmatch;
-
- /* Check if the DFA haven't been compiled. */
- if (BE (preg->used == 0 || dfa->init_state == NULL
- || dfa->init_state_word == NULL || dfa->init_state_nl == NULL
- || dfa->init_state_begbuf == NULL, 0))
- return REG_NOMATCH;
-
-#ifdef DEBUG
- /* We assume front-end functions already check them. */
- assert (start + range >= 0 && start + range <= length);
-#endif
-
- /* If initial states with non-begbuf contexts have no elements,
- the regex must be anchored. If preg->newline_anchor is set,
- we'll never use init_state_nl, so do not check it. */
- if (dfa->init_state->nodes.nelem == 0
- && dfa->init_state_word->nodes.nelem == 0
- && (dfa->init_state_nl->nodes.nelem == 0
- || !preg->newline_anchor))
- {
- if (start != 0 && start + range != 0)
- return REG_NOMATCH;
- start = range = 0;
- }
-
- /* We must check the longest matching, if nmatch > 0. */
- fl_longest_match = (nmatch != 0 || dfa->nbackref);
-
- err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1,
- preg->translate, preg->syntax & RE_ICASE, dfa);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
- mctx.input.stop = stop;
- mctx.input.raw_stop = stop;
- mctx.input.newline_anchor = preg->newline_anchor;
-
- err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
-
- /* We will log all the DFA states through which the dfa pass,
- if nmatch > 1, or this dfa has "multibyte node", which is a
- back-reference or a node which can accept multibyte character or
- multi character collating element. */
- if (nmatch > 1 || dfa->has_mb_node)
- {
- mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1);
- if (BE (mctx.state_log == NULL, 0))
- {
- err = REG_ESPACE;
- goto free_return;
- }
- }
- else
- mctx.state_log = NULL;
-
- match_first = start;
- mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
- : CONTEXT_NEWLINE | CONTEXT_BEGBUF;
-
- /* Check incrementally whether of not the input string match. */
- incr = (range < 0) ? -1 : 1;
- left_lim = (range < 0) ? start + range : start;
- right_lim = (range < 0) ? start : start + range;
- sb = dfa->mb_cur_max == 1;
- match_kind =
- (fastmap
- ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
- | (range >= 0 ? 2 : 0)
- | (t != NULL ? 1 : 0))
- : 8);
-
- for (;; match_first += incr)
- {
- err = REG_NOMATCH;
- if (match_first < left_lim || right_lim < match_first)
- goto free_return;
-
- /* Advance as rapidly as possible through the string, until we
- find a plausible place to start matching. This may be done
- with varying efficiency, so there are various possibilities:
- only the most common of them are specialized, in order to
- save on code size. We use a switch statement for speed. */
- switch (match_kind)
- {
- case 8:
- /* No fastmap. */
- break;
-
- case 7:
- /* Fastmap with single-byte translation, match forward. */
- while (BE (match_first < right_lim, 1)
- && !fastmap[t[(unsigned char) string[match_first]]])
- ++match_first;
- goto forward_match_found_start_or_reached_end;
-
- case 6:
- /* Fastmap without translation, match forward. */
- while (BE (match_first < right_lim, 1)
- && !fastmap[(unsigned char) string[match_first]])
- ++match_first;
-
- forward_match_found_start_or_reached_end:
- if (BE (match_first == right_lim, 0))
- {
- ch = match_first >= length
- ? 0 : (unsigned char) string[match_first];
- if (!fastmap[t ? t[ch] : ch])
- goto free_return;
- }
- break;
-
- case 4:
- case 5:
- /* Fastmap without multi-byte translation, match backwards. */
- while (match_first >= left_lim)
- {
- ch = match_first >= length
- ? 0 : (unsigned char) string[match_first];
- if (fastmap[t ? t[ch] : ch])
- break;
- --match_first;
- }
- if (match_first < left_lim)
- goto free_return;
- break;
-
- default:
- /* In this case, we can't determine easily the current byte,
- since it might be a component byte of a multibyte
- character. Then we use the constructed buffer instead. */
- for (;;)
- {
- /* If MATCH_FIRST is out of the valid range, reconstruct the
- buffers. */
- unsigned int offset = match_first - mctx.input.raw_mbs_idx;
- if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0))
- {
- err = re_string_reconstruct (&mctx.input, match_first,
- eflags);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
-
- offset = match_first - mctx.input.raw_mbs_idx;
- }
- /* If MATCH_FIRST is out of the buffer, leave it as '\0'.
- Note that MATCH_FIRST must not be smaller than 0. */
- ch = (match_first >= length
- ? 0 : re_string_byte_at (&mctx.input, offset));
- if (fastmap[ch])
- break;
- match_first += incr;
- if (match_first < left_lim || match_first > right_lim)
- {
- err = REG_NOMATCH;
- goto free_return;
- }
- }
- break;
- }
-
- /* Reconstruct the buffers so that the matcher can assume that
- the matching starts from the beginning of the buffer. */
- err = re_string_reconstruct (&mctx.input, match_first, eflags);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
-
-#ifdef RE_ENABLE_I18N
- /* Don't consider this char as a possible match start if it part,
- yet isn't the head, of a multibyte character. */
- if (!sb && !re_string_first_byte (&mctx.input, 0))
- continue;
-#endif
-
- /* It seems to be appropriate one, then use the matcher. */
- /* We assume that the matching starts from 0. */
- mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
- match_last = check_matching (&mctx, fl_longest_match,
- range >= 0 ? &match_first : NULL);
- if (match_last != -1)
- {
- if (BE (match_last == -2, 0))
- {
- err = REG_ESPACE;
- goto free_return;
- }
- else
- {
- mctx.match_last = match_last;
- if ((!preg->no_sub && nmatch > 1) || dfa->nbackref)
- {
- re_dfastate_t *pstate = mctx.state_log[match_last];
- mctx.last_node = check_halt_state_context (&mctx, pstate,
- match_last);
- }
- if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match)
- || dfa->nbackref)
- {
- err = prune_impossible_nodes (&mctx);
- if (err == REG_NOERROR)
- break;
- if (BE (err != REG_NOMATCH, 0))
- goto free_return;
- match_last = -1;
- }
- else
- break; /* We found a match. */
- }
- }
-
- match_ctx_clean (&mctx);
- }
-
-#ifdef DEBUG
- assert (match_last != -1);
- assert (err == REG_NOERROR);
-#endif
-
- /* Set pmatch[] if we need. */
- if (nmatch > 0)
- {
- int reg_idx;
-
- /* Initialize registers. */
- for (reg_idx = 1; reg_idx < nmatch; ++reg_idx)
- pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1;
-
- /* Set the points where matching start/end. */
- pmatch[0].rm_so = 0;
- pmatch[0].rm_eo = mctx.match_last;
-
- if (!preg->no_sub && nmatch > 1)
- {
- err = set_regs (preg, &mctx, nmatch, pmatch,
- dfa->has_plural_match && dfa->nbackref > 0);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
- }
-
- /* At last, add the offset to the each registers, since we slided
- the buffers so that we could assume that the matching starts
- from 0. */
- for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
- if (pmatch[reg_idx].rm_so != -1)
- {
-#ifdef RE_ENABLE_I18N
- if (BE (mctx.input.offsets_needed != 0, 0))
- {
- pmatch[reg_idx].rm_so =
- (pmatch[reg_idx].rm_so == mctx.input.valid_len
- ? mctx.input.valid_raw_len
- : mctx.input.offsets[pmatch[reg_idx].rm_so]);
- pmatch[reg_idx].rm_eo =
- (pmatch[reg_idx].rm_eo == mctx.input.valid_len
- ? mctx.input.valid_raw_len
- : mctx.input.offsets[pmatch[reg_idx].rm_eo]);
- }
-#else
- assert (mctx.input.offsets_needed == 0);
-#endif
- pmatch[reg_idx].rm_so += match_first;
- pmatch[reg_idx].rm_eo += match_first;
- }
- for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx)
- {
- pmatch[nmatch + reg_idx].rm_so = -1;
- pmatch[nmatch + reg_idx].rm_eo = -1;
- }
-
- if (dfa->subexp_map)
- for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++)
- if (dfa->subexp_map[reg_idx] != reg_idx)
- {
- pmatch[reg_idx + 1].rm_so
- = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so;
- pmatch[reg_idx + 1].rm_eo
- = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo;
- }
- }
-
- free_return:
- re_free (mctx.state_log);
- if (dfa->nbackref)
- match_ctx_free (&mctx);
- re_string_destruct (&mctx.input);
- return err;
-}
-
-static reg_errcode_t
-prune_impossible_nodes (mctx)
- re_match_context_t *mctx;
-{
- const re_dfa_t *const dfa = mctx->dfa;
- int halt_node, match_last;
- reg_errcode_t ret;
- re_dfastate_t **sifted_states;
- re_dfastate_t **lim_states = NULL;
- re_sift_context_t sctx;
-#ifdef DEBUG
- assert (mctx->state_log != NULL);
-#endif
- match_last = mctx->match_last;
- halt_node = mctx->last_node;
- sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
- if (BE (sifted_states == NULL, 0))
- {
- ret = REG_ESPACE;
- goto free_return;
- }
- if (dfa->nbackref)
- {
- lim_states = re_malloc (re_dfastate_t *, match_last + 1);
- if (BE (lim_states == NULL, 0))
- {
- ret = REG_ESPACE;
- goto free_return;
- }
- while (1)
- {
- memset (lim_states, '\0',
- sizeof (re_dfastate_t *) * (match_last + 1));
- sift_ctx_init (&sctx, sifted_states, lim_states, halt_node,
- match_last);
- ret = sift_states_backward (mctx, &sctx);
- re_node_set_free (&sctx.limits);
- if (BE (ret != REG_NOERROR, 0))
- goto free_return;
- if (sifted_states[0] != NULL || lim_states[0] != NULL)
- break;
- do
- {
- --match_last;
- if (match_last < 0)
- {
- ret = REG_NOMATCH;
- goto free_return;
- }
- } while (mctx->state_log[match_last] == NULL
- || !mctx->state_log[match_last]->halt);
- halt_node = check_halt_state_context (mctx,
- mctx->state_log[match_last],
- match_last);
- }
- ret = merge_state_array (dfa, sifted_states, lim_states,
- match_last + 1);
- re_free (lim_states);
- lim_states = NULL;
- if (BE (ret != REG_NOERROR, 0))
- goto free_return;
- }
- else
- {
- sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last);
- ret = sift_states_backward (mctx, &sctx);
- re_node_set_free (&sctx.limits);
- if (BE (ret != REG_NOERROR, 0))
- goto free_return;
- }
- re_free (mctx->state_log);
- mctx->state_log = sifted_states;
- sifted_states = NULL;
- mctx->last_node = halt_node;
- mctx->match_last = match_last;
- ret = REG_NOERROR;
- free_return:
- re_free (sifted_states);
- re_free (lim_states);
- return ret;
-}
-
-/* Acquire an initial state and return it.
- We must select appropriate initial state depending on the context,
- since initial states may have constraints like "\<", "^", etc.. */
-
-static inline re_dfastate_t *
-__attribute ((always_inline)) internal_function
-acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx,
- int idx)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- if (dfa->init_state->has_constraint)
- {
- unsigned int context;
- context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags);
- if (IS_WORD_CONTEXT (context))
- return dfa->init_state_word;
- else if (IS_ORDINARY_CONTEXT (context))
- return dfa->init_state;
- else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context))
- return dfa->init_state_begbuf;
- else if (IS_NEWLINE_CONTEXT (context))
- return dfa->init_state_nl;
- else if (IS_BEGBUF_CONTEXT (context))
- {
- /* It is relatively rare case, then calculate on demand. */
- return re_acquire_state_context (err, dfa,
- dfa->init_state->entrance_nodes,
- context);
- }
- else
- /* Must not happen? */
- return dfa->init_state;
- }
- else
- return dfa->init_state;
-}
-
-/* Check whether the regular expression match input string INPUT or not,
- and return the index where the matching end, return -1 if not match,
- or return -2 in case of an error.
- FL_LONGEST_MATCH means we want the POSIX longest matching.
- If P_MATCH_FIRST is not NULL, and the match fails, it is set to the
- next place where we may want to try matching.
- Note that the matcher assume that the maching starts from the current
- index of the buffer. */
-
-static int
-internal_function
-check_matching (re_match_context_t *mctx, int fl_longest_match,
- int *p_match_first)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- reg_errcode_t err;
- int match = 0;
- int match_last = -1;
- int cur_str_idx = re_string_cur_idx (&mctx->input);
- re_dfastate_t *cur_state;
- int at_init_state = p_match_first != NULL;
- int next_start_idx = cur_str_idx;
-
- err = REG_NOERROR;
- cur_state = acquire_init_state_context (&err, mctx, cur_str_idx);
- /* An initial state must not be NULL (invalid). */
- if (BE (cur_state == NULL, 0))
- {
- assert (err == REG_ESPACE);
- return -2;
- }
-
- if (mctx->state_log != NULL)
- {
- mctx->state_log[cur_str_idx] = cur_state;
-
- /* Check OP_OPEN_SUBEXP in the initial state in case that we use them
- later. E.g. Processing back references. */
- if (BE (dfa->nbackref, 0))
- {
- at_init_state = 0;
- err = check_subexp_matching_top (mctx, &cur_state->nodes, 0);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- if (cur_state->has_backref)
- {
- err = transit_state_bkref (mctx, &cur_state->nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- }
- }
-
- /* If the RE accepts NULL string. */
- if (BE (cur_state->halt, 0))
- {
- if (!cur_state->has_constraint
- || check_halt_state_context (mctx, cur_state, cur_str_idx))
- {
- if (!fl_longest_match)
- return cur_str_idx;
- else
- {
- match_last = cur_str_idx;
- match = 1;
- }
- }
- }
-
- while (!re_string_eoi (&mctx->input))
- {
- re_dfastate_t *old_state = cur_state;
- int next_char_idx = re_string_cur_idx (&mctx->input) + 1;
-
- if (BE (next_char_idx >= mctx->input.bufs_len, 0)
- || (BE (next_char_idx >= mctx->input.valid_len, 0)
- && mctx->input.valid_len < mctx->input.len))
- {
- err = extend_buffers (mctx);
- if (BE (err != REG_NOERROR, 0))
- {
- assert (err == REG_ESPACE);
- return -2;
- }
- }
-
- cur_state = transit_state (&err, mctx, cur_state);
- if (mctx->state_log != NULL)
- cur_state = merge_state_with_log (&err, mctx, cur_state);
-
- if (cur_state == NULL)
- {
- /* Reached the invalid state or an error. Try to recover a valid
- state using the state log, if available and if we have not
- already found a valid (even if not the longest) match. */
- if (BE (err != REG_NOERROR, 0))
- return -2;
-
- if (mctx->state_log == NULL
- || (match && !fl_longest_match)
- || (cur_state = find_recover_state (&err, mctx)) == NULL)
- break;
- }
-
- if (BE (at_init_state, 0))
- {
- if (old_state == cur_state)
- next_start_idx = next_char_idx;
- else
- at_init_state = 0;
- }
-
- if (cur_state->halt)
- {
- /* Reached a halt state.
- Check the halt state can satisfy the current context. */
- if (!cur_state->has_constraint
- || check_halt_state_context (mctx, cur_state,
- re_string_cur_idx (&mctx->input)))
- {
- /* We found an appropriate halt state. */
- match_last = re_string_cur_idx (&mctx->input);
- match = 1;
-
- /* We found a match, do not modify match_first below. */
- p_match_first = NULL;
- if (!fl_longest_match)
- break;
- }
- }
- }
-
- if (p_match_first)
- *p_match_first += next_start_idx;
-
- return match_last;
-}
-
-/* Check NODE match the current context. */
-
-static int
-internal_function
-check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context)
-{
- re_token_type_t type = dfa->nodes[node].type;
- unsigned int constraint = dfa->nodes[node].constraint;
- if (type != END_OF_RE)
- return 0;
- if (!constraint)
- return 1;
- if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context))
- return 0;
- return 1;
-}
-
-/* Check the halt state STATE match the current context.
- Return 0 if not match, if the node, STATE has, is a halt node and
- match the context, return the node. */
-
-static int
-internal_function
-check_halt_state_context (const re_match_context_t *mctx,
- const re_dfastate_t *state, int idx)
-{
- int i;
- unsigned int context;
-#ifdef DEBUG
- assert (state->halt);
-#endif
- context = re_string_context_at (&mctx->input, idx, mctx->eflags);
- for (i = 0; i < state->nodes.nelem; ++i)
- if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context))
- return state->nodes.elems[i];
- return 0;
-}
-
-/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA
- corresponding to the DFA).
- Return the destination node, and update EPS_VIA_NODES, return -1 in case
- of errors. */
-
-static int
-internal_function
-proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,
- int *pidx, int node, re_node_set *eps_via_nodes,
- struct re_fail_stack_t *fs)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- int i, err;
- if (IS_EPSILON_NODE (dfa->nodes[node].type))
- {
- re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;
- re_node_set *edests = &dfa->edests[node];
- int dest_node;
- err = re_node_set_insert (eps_via_nodes, node);
- if (BE (err < 0, 0))
- return -2;
- /* Pick up a valid destination, or return -1 if none is found. */
- for (dest_node = -1, i = 0; i < edests->nelem; ++i)
- {
- int candidate = edests->elems[i];
- if (!re_node_set_contains (cur_nodes, candidate))
- continue;
- if (dest_node == -1)
- dest_node = candidate;
-
- else
- {
- /* In order to avoid infinite loop like "(a*)*", return the second
- epsilon-transition if the first was already considered. */
- if (re_node_set_contains (eps_via_nodes, dest_node))
- return candidate;
-
- /* Otherwise, push the second epsilon-transition on the fail stack. */
- else if (fs != NULL
- && push_fail_stack (fs, *pidx, candidate, nregs, regs,
- eps_via_nodes))
- return -2;
-
- /* We know we are going to exit. */
- break;
- }
- }
- return dest_node;
- }
- else
- {
- int naccepted = 0;
- re_token_type_t type = dfa->nodes[node].type;
-
-#ifdef RE_ENABLE_I18N
- if (dfa->nodes[node].accept_mb)
- naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx);
- else
-#endif /* RE_ENABLE_I18N */
- if (type == OP_BACK_REF)
- {
- int subexp_idx = dfa->nodes[node].opr.idx + 1;
- naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;
- if (fs != NULL)
- {
- if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1)
- return -1;
- else if (naccepted)
- {
- char *buf = (char *) re_string_get_buffer (&mctx->input);
- if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
- naccepted) != 0)
- return -1;
- }
- }
-
- if (naccepted == 0)
- {
- int dest_node;
- err = re_node_set_insert (eps_via_nodes, node);
- if (BE (err < 0, 0))
- return -2;
- dest_node = dfa->edests[node].elems[0];
- if (re_node_set_contains (&mctx->state_log[*pidx]->nodes,
- dest_node))
- return dest_node;
- }
- }
-
- if (naccepted != 0
- || check_node_accept (mctx, dfa->nodes + node, *pidx))
- {
- int dest_node = dfa->nexts[node];
- *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted;
- if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL
- || !re_node_set_contains (&mctx->state_log[*pidx]->nodes,
- dest_node)))
- return -1;
- re_node_set_empty (eps_via_nodes);
- return dest_node;
- }
- }
- return -1;
-}
-
-static reg_errcode_t
-internal_function
-push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node,
- int nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
-{
- reg_errcode_t err;
- int num = fs->num++;
- if (fs->num == fs->alloc)
- {
- struct re_fail_stack_ent_t *new_array;
- new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t)
- * fs->alloc * 2));
- if (new_array == NULL)
- return REG_ESPACE;
- fs->alloc *= 2;
- fs->stack = new_array;
- }
- fs->stack[num].idx = str_idx;
- fs->stack[num].node = dest_node;
- fs->stack[num].regs = re_malloc (regmatch_t, nregs);
- if (fs->stack[num].regs == NULL)
- return REG_ESPACE;
- memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
- err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);
- return err;
-}
-
-static int
-internal_function
-pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs,
- regmatch_t *regs, re_node_set *eps_via_nodes)
-{
- int num = --fs->num;
- assert (num >= 0);
- *pidx = fs->stack[num].idx;
- memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
- re_node_set_free (eps_via_nodes);
- re_free (fs->stack[num].regs);
- *eps_via_nodes = fs->stack[num].eps_via_nodes;
- return fs->stack[num].node;
-}
-
-/* Set the positions where the subexpressions are starts/ends to registers
- PMATCH.
- Note: We assume that pmatch[0] is already set, and
- pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */
-
-static reg_errcode_t
-internal_function
-set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
- regmatch_t *pmatch, int fl_backtrack)
-{
- const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
- int idx, cur_node;
- re_node_set eps_via_nodes;
- struct re_fail_stack_t *fs;
- struct re_fail_stack_t fs_body = { 0, 2, NULL };
- regmatch_t *prev_idx_match;
- int prev_idx_match_malloced = 0;
-
-#ifdef DEBUG
- assert (nmatch > 1);
- assert (mctx->state_log != NULL);
-#endif
- if (fl_backtrack)
- {
- fs = &fs_body;
- fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc);
- if (fs->stack == NULL)
- return REG_ESPACE;
- }
- else
- fs = NULL;
-
- cur_node = dfa->init_node;
- re_node_set_init_empty (&eps_via_nodes);
-
- if (__libc_use_alloca (nmatch * sizeof (regmatch_t)))
- prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t));
- else
- {
- prev_idx_match = re_malloc (regmatch_t, nmatch);
- if (prev_idx_match == NULL)
- {
- free_fail_stack_return (fs);
- return REG_ESPACE;
- }
- prev_idx_match_malloced = 1;
- }
- memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
-
- for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
- {
- update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch);
-
- if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
- {
- int reg_idx;
- if (fs)
- {
- for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
- if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)
- break;
- if (reg_idx == nmatch)
- {
- re_node_set_free (&eps_via_nodes);
- if (prev_idx_match_malloced)
- re_free (prev_idx_match);
- return free_fail_stack_return (fs);
- }
- cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
- &eps_via_nodes);
- }
- else
- {
- re_node_set_free (&eps_via_nodes);
- if (prev_idx_match_malloced)
- re_free (prev_idx_match);
- return REG_NOERROR;
- }
- }
-
- /* Proceed to next node. */
- cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node,
- &eps_via_nodes, fs);
-
- if (BE (cur_node < 0, 0))
- {
- if (BE (cur_node == -2, 0))
- {
- re_node_set_free (&eps_via_nodes);
- if (prev_idx_match_malloced)
- re_free (prev_idx_match);
- free_fail_stack_return (fs);
- return REG_ESPACE;
- }
- if (fs)
- cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
- &eps_via_nodes);
- else
- {
- re_node_set_free (&eps_via_nodes);
- if (prev_idx_match_malloced)
- re_free (prev_idx_match);
- return REG_NOMATCH;
- }
- }
- }
- re_node_set_free (&eps_via_nodes);
- if (prev_idx_match_malloced)
- re_free (prev_idx_match);
- return free_fail_stack_return (fs);
-}
-
-static reg_errcode_t
-internal_function
-free_fail_stack_return (struct re_fail_stack_t *fs)
-{
- if (fs)
- {
- int fs_idx;
- for (fs_idx = 0; fs_idx < fs->num; ++fs_idx)
- {
- re_node_set_free (&fs->stack[fs_idx].eps_via_nodes);
- re_free (fs->stack[fs_idx].regs);
- }
- re_free (fs->stack);
- }
- return REG_NOERROR;
-}
-
-static void
-internal_function
-update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
- regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch)
-{
- int type = dfa->nodes[cur_node].type;
- if (type == OP_OPEN_SUBEXP)
- {
- int reg_num = dfa->nodes[cur_node].opr.idx + 1;
-
- /* We are at the first node of this sub expression. */
- if (reg_num < nmatch)
- {
- pmatch[reg_num].rm_so = cur_idx;
- pmatch[reg_num].rm_eo = -1;
- }
- }
- else if (type == OP_CLOSE_SUBEXP)
- {
- int reg_num = dfa->nodes[cur_node].opr.idx + 1;
- if (reg_num < nmatch)
- {
- /* We are at the last node of this sub expression. */
- if (pmatch[reg_num].rm_so < cur_idx)
- {
- pmatch[reg_num].rm_eo = cur_idx;
- /* This is a non-empty match or we are not inside an optional
- subexpression. Accept this right away. */
- memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
- }
- else
- {
- if (dfa->nodes[cur_node].opt_subexp
- && prev_idx_match[reg_num].rm_so != -1)
- /* We transited through an empty match for an optional
- subexpression, like (a?)*, and this is not the subexp's
- first match. Copy back the old content of the registers
- so that matches of an inner subexpression are undone as
- well, like in ((a?))*. */
- memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch);
- else
- /* We completed a subexpression, but it may be part of
- an optional one, so do not update PREV_IDX_MATCH. */
- pmatch[reg_num].rm_eo = cur_idx;
- }
- }
- }
-}
-
-/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0
- and sift the nodes in each states according to the following rules.
- Updated state_log will be wrote to STATE_LOG.
-
- Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if...
- 1. When STR_IDX == MATCH_LAST(the last index in the state_log):
- If `a' isn't the LAST_NODE and `a' can't epsilon transit to
- the LAST_NODE, we throw away the node `a'.
- 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts
- string `s' and transit to `b':
- i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw
- away the node `a'.
- ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is
- thrown away, we throw away the node `a'.
- 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b':
- i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the
- node `a'.
- ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away,
- we throw away the node `a'. */
-
-#define STATE_NODE_CONTAINS(state,node) \
- ((state) != NULL && re_node_set_contains (&(state)->nodes, node))
-
-static reg_errcode_t
-internal_function
-sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx)
-{
- reg_errcode_t err;
- int null_cnt = 0;
- int str_idx = sctx->last_str_idx;
- re_node_set cur_dest;
-
-#ifdef DEBUG
- assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL);
-#endif
-
- /* Build sifted state_log[str_idx]. It has the nodes which can epsilon
- transit to the last_node and the last_node itself. */
- err = re_node_set_init_1 (&cur_dest, sctx->last_node);
- if (BE (err != REG_NOERROR, 0))
- return err;
- err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
-
- /* Then check each states in the state_log. */
- while (str_idx > 0)
- {
- /* Update counters. */
- null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0;
- if (null_cnt > mctx->max_mb_elem_len)
- {
- memset (sctx->sifted_states, '\0',
- sizeof (re_dfastate_t *) * str_idx);
- re_node_set_free (&cur_dest);
- return REG_NOERROR;
- }
- re_node_set_empty (&cur_dest);
- --str_idx;
-
- if (mctx->state_log[str_idx])
- {
- err = build_sifted_states (mctx, sctx, str_idx, &cur_dest);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
- }
-
- /* Add all the nodes which satisfy the following conditions:
- - It can epsilon transit to a node in CUR_DEST.
- - It is in CUR_SRC.
- And update state_log. */
- err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
- }
- err = REG_NOERROR;
- free_return:
- re_node_set_free (&cur_dest);
- return err;
-}
-
-static reg_errcode_t
-internal_function
-build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,
- int str_idx, re_node_set *cur_dest)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes;
- int i;
-
- /* Then build the next sifted state.
- We build the next sifted state on `cur_dest', and update
- `sifted_states[str_idx]' with `cur_dest'.
- Note:
- `cur_dest' is the sifted state from `state_log[str_idx + 1]'.
- `cur_src' points the node_set of the old `state_log[str_idx]'
- (with the epsilon nodes pre-filtered out). */
- for (i = 0; i < cur_src->nelem; i++)
- {
- int prev_node = cur_src->elems[i];
- int naccepted = 0;
- int ret;
-
-#ifdef DEBUG
- re_token_type_t type = dfa->nodes[prev_node].type;
- assert (!IS_EPSILON_NODE (type));
-#endif
-#ifdef RE_ENABLE_I18N
- /* If the node may accept `multi byte'. */
- if (dfa->nodes[prev_node].accept_mb)
- naccepted = sift_states_iter_mb (mctx, sctx, prev_node,
- str_idx, sctx->last_str_idx);
-#endif /* RE_ENABLE_I18N */
-
- /* We don't check backreferences here.
- See update_cur_sifted_state(). */
- if (!naccepted
- && check_node_accept (mctx, dfa->nodes + prev_node, str_idx)
- && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1],
- dfa->nexts[prev_node]))
- naccepted = 1;
-
- if (naccepted == 0)
- continue;
-
- if (sctx->limits.nelem)
- {
- int to_idx = str_idx + naccepted;
- if (check_dst_limits (mctx, &sctx->limits,
- dfa->nexts[prev_node], to_idx,
- prev_node, str_idx))
- continue;
- }
- ret = re_node_set_insert (cur_dest, prev_node);
- if (BE (ret == -1, 0))
- return REG_ESPACE;
- }
-
- return REG_NOERROR;
-}
-
-/* Helper functions. */
-
-static reg_errcode_t
-internal_function
-clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx)
-{
- int top = mctx->state_log_top;
-
- if (next_state_log_idx >= mctx->input.bufs_len
- || (next_state_log_idx >= mctx->input.valid_len
- && mctx->input.valid_len < mctx->input.len))
- {
- reg_errcode_t err;
- err = extend_buffers (mctx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
-
- if (top < next_state_log_idx)
- {
- memset (mctx->state_log + top + 1, '\0',
- sizeof (re_dfastate_t *) * (next_state_log_idx - top));
- mctx->state_log_top = next_state_log_idx;
- }
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-internal_function
-merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst,
- re_dfastate_t **src, int num)
-{
- int st_idx;
- reg_errcode_t err;
- for (st_idx = 0; st_idx < num; ++st_idx)
- {
- if (dst[st_idx] == NULL)
- dst[st_idx] = src[st_idx];
- else if (src[st_idx] != NULL)
- {
- re_node_set merged_set;
- err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes,
- &src[st_idx]->nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- dst[st_idx] = re_acquire_state (&err, dfa, &merged_set);
- re_node_set_free (&merged_set);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- }
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-internal_function
-update_cur_sifted_state (const re_match_context_t *mctx,
- re_sift_context_t *sctx, int str_idx,
- re_node_set *dest_nodes)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- reg_errcode_t err = REG_NOERROR;
- const re_node_set *candidates;
- candidates = ((mctx->state_log[str_idx] == NULL) ? NULL
- : &mctx->state_log[str_idx]->nodes);
-
- if (dest_nodes->nelem == 0)
- sctx->sifted_states[str_idx] = NULL;
- else
- {
- if (candidates)
- {
- /* At first, add the nodes which can epsilon transit to a node in
- DEST_NODE. */
- err = add_epsilon_src_nodes (dfa, dest_nodes, candidates);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- /* Then, check the limitations in the current sift_context. */
- if (sctx->limits.nelem)
- {
- err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits,
- mctx->bkref_ents, str_idx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- }
-
- sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
-
- if (candidates && mctx->state_log[str_idx]->has_backref)
- {
- err = sift_states_bkref (mctx, sctx, str_idx, candidates);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-internal_function
-add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes,
- const re_node_set *candidates)
-{
- reg_errcode_t err = REG_NOERROR;
- int i;
-
- re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- if (!state->inveclosure.alloc)
- {
- err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem);
- if (BE (err != REG_NOERROR, 0))
- return REG_ESPACE;
- for (i = 0; i < dest_nodes->nelem; i++)
- re_node_set_merge (&state->inveclosure,
- dfa->inveclosures + dest_nodes->elems[i]);
- }
- return re_node_set_add_intersect (dest_nodes, candidates,
- &state->inveclosure);
-}
-
-static reg_errcode_t
-internal_function
-sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes,
- const re_node_set *candidates)
-{
- int ecl_idx;
- reg_errcode_t err;
- re_node_set *inv_eclosure = dfa->inveclosures + node;
- re_node_set except_nodes;
- re_node_set_init_empty (&except_nodes);
- for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
- {
- int cur_node = inv_eclosure->elems[ecl_idx];
- if (cur_node == node)
- continue;
- if (IS_EPSILON_NODE (dfa->nodes[cur_node].type))
- {
- int edst1 = dfa->edests[cur_node].elems[0];
- int edst2 = ((dfa->edests[cur_node].nelem > 1)
- ? dfa->edests[cur_node].elems[1] : -1);
- if ((!re_node_set_contains (inv_eclosure, edst1)
- && re_node_set_contains (dest_nodes, edst1))
- || (edst2 > 0
- && !re_node_set_contains (inv_eclosure, edst2)
- && re_node_set_contains (dest_nodes, edst2)))
- {
- err = re_node_set_add_intersect (&except_nodes, candidates,
- dfa->inveclosures + cur_node);
- if (BE (err != REG_NOERROR, 0))
- {
- re_node_set_free (&except_nodes);
- return err;
- }
- }
- }
- }
- for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
- {
- int cur_node = inv_eclosure->elems[ecl_idx];
- if (!re_node_set_contains (&except_nodes, cur_node))
- {
- int idx = re_node_set_contains (dest_nodes, cur_node) - 1;
- re_node_set_remove_at (dest_nodes, idx);
- }
- }
- re_node_set_free (&except_nodes);
- return REG_NOERROR;
-}
-
-static int
-internal_function
-check_dst_limits (const re_match_context_t *mctx, re_node_set *limits,
- int dst_node, int dst_idx, int src_node, int src_idx)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- int lim_idx, src_pos, dst_pos;
-
- int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx);
- int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx);
- for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
- {
- int subexp_idx;
- struct re_backref_cache_entry *ent;
- ent = mctx->bkref_ents + limits->elems[lim_idx];
- subexp_idx = dfa->nodes[ent->node].opr.idx;
-
- dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
- subexp_idx, dst_node, dst_idx,
- dst_bkref_idx);
- src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
- subexp_idx, src_node, src_idx,
- src_bkref_idx);
-
- /* In case of:
- <src> <dst> ( <subexp> )
- ( <subexp> ) <src> <dst>
- ( <subexp1> <src> <subexp2> <dst> <subexp3> ) */
- if (src_pos == dst_pos)
- continue; /* This is unrelated limitation. */
- else
- return 1;
- }
- return 0;
-}
-
-static int
-internal_function
-check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries,
- int subexp_idx, int from_node, int bkref_idx)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- const re_node_set *eclosures = dfa->eclosures + from_node;
- int node_idx;
-
- /* Else, we are on the boundary: examine the nodes on the epsilon
- closure. */
- for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx)
- {
- int node = eclosures->elems[node_idx];
- switch (dfa->nodes[node].type)
- {
- case OP_BACK_REF:
- if (bkref_idx != -1)
- {
- struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx;
- do
- {
- int dst, cpos;
-
- if (ent->node != node)
- continue;
-
- if (subexp_idx < BITSET_WORD_BITS
- && !(ent->eps_reachable_subexps_map
- & ((bitset_word_t) 1 << subexp_idx)))
- continue;
-
- /* Recurse trying to reach the OP_OPEN_SUBEXP and
- OP_CLOSE_SUBEXP cases below. But, if the
- destination node is the same node as the source
- node, don't recurse because it would cause an
- infinite loop: a regex that exhibits this behavior
- is ()\1*\1* */
- dst = dfa->edests[node].elems[0];
- if (dst == from_node)
- {
- if (boundaries & 1)
- return -1;
- else /* if (boundaries & 2) */
- return 0;
- }
-
- cpos =
- check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
- dst, bkref_idx);
- if (cpos == -1 /* && (boundaries & 1) */)
- return -1;
- if (cpos == 0 && (boundaries & 2))
- return 0;
-
- if (subexp_idx < BITSET_WORD_BITS)
- ent->eps_reachable_subexps_map
- &= ~((bitset_word_t) 1 << subexp_idx);
- }
- while (ent++->more);
- }
- break;
-
- case OP_OPEN_SUBEXP:
- if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx)
- return -1;
- break;
-
- case OP_CLOSE_SUBEXP:
- if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx)
- return 0;
- break;
-
- default:
- break;
- }
- }
-
- return (boundaries & 2) ? 1 : 0;
-}
-
-static int
-internal_function
-check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit,
- int subexp_idx, int from_node, int str_idx,
- int bkref_idx)
-{
- struct re_backref_cache_entry *lim = mctx->bkref_ents + limit;
- int boundaries;
-
- /* If we are outside the range of the subexpression, return -1 or 1. */
- if (str_idx < lim->subexp_from)
- return -1;
-
- if (lim->subexp_to < str_idx)
- return 1;
-
- /* If we are within the subexpression, return 0. */
- boundaries = (str_idx == lim->subexp_from);
- boundaries |= (str_idx == lim->subexp_to) << 1;
- if (boundaries == 0)
- return 0;
-
- /* Else, examine epsilon closure. */
- return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
- from_node, bkref_idx);
-}
-
-/* Check the limitations of sub expressions LIMITS, and remove the nodes
- which are against limitations from DEST_NODES. */
-
-static reg_errcode_t
-internal_function
-check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
- const re_node_set *candidates, re_node_set *limits,
- struct re_backref_cache_entry *bkref_ents, int str_idx)
-{
- reg_errcode_t err;
- int node_idx, lim_idx;
-
- for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
- {
- int subexp_idx;
- struct re_backref_cache_entry *ent;
- ent = bkref_ents + limits->elems[lim_idx];
-
- if (str_idx <= ent->subexp_from || ent->str_idx < str_idx)
- continue; /* This is unrelated limitation. */
-
- subexp_idx = dfa->nodes[ent->node].opr.idx;
- if (ent->subexp_to == str_idx)
- {
- int ops_node = -1;
- int cls_node = -1;
- for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
- {
- int node = dest_nodes->elems[node_idx];
- re_token_type_t type = dfa->nodes[node].type;
- if (type == OP_OPEN_SUBEXP
- && subexp_idx == dfa->nodes[node].opr.idx)
- ops_node = node;
- else if (type == OP_CLOSE_SUBEXP
- && subexp_idx == dfa->nodes[node].opr.idx)
- cls_node = node;
- }
-
- /* Check the limitation of the open subexpression. */
- /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */
- if (ops_node >= 0)
- {
- err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes,
- candidates);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
-
- /* Check the limitation of the close subexpression. */
- if (cls_node >= 0)
- for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
- {
- int node = dest_nodes->elems[node_idx];
- if (!re_node_set_contains (dfa->inveclosures + node,
- cls_node)
- && !re_node_set_contains (dfa->eclosures + node,
- cls_node))
- {
- /* It is against this limitation.
- Remove it form the current sifted state. */
- err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
- candidates);
- if (BE (err != REG_NOERROR, 0))
- return err;
- --node_idx;
- }
- }
- }
- else /* (ent->subexp_to != str_idx) */
- {
- for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
- {
- int node = dest_nodes->elems[node_idx];
- re_token_type_t type = dfa->nodes[node].type;
- if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP)
- {
- if (subexp_idx != dfa->nodes[node].opr.idx)
- continue;
- /* It is against this limitation.
- Remove it form the current sifted state. */
- err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
- candidates);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- }
- }
- }
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-internal_function
-sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
- int str_idx, const re_node_set *candidates)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- reg_errcode_t err;
- int node_idx, node;
- re_sift_context_t local_sctx;
- int first_idx = search_cur_bkref_entry (mctx, str_idx);
-
- if (first_idx == -1)
- return REG_NOERROR;
-
- local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */
-
- for (node_idx = 0; node_idx < candidates->nelem; ++node_idx)
- {
- int enabled_idx;
- re_token_type_t type;
- struct re_backref_cache_entry *entry;
- node = candidates->elems[node_idx];
- type = dfa->nodes[node].type;
- /* Avoid infinite loop for the REs like "()\1+". */
- if (node == sctx->last_node && str_idx == sctx->last_str_idx)
- continue;
- if (type != OP_BACK_REF)
- continue;
-
- entry = mctx->bkref_ents + first_idx;
- enabled_idx = first_idx;
- do
- {
- int subexp_len;
- int to_idx;
- int dst_node;
- int ret;
- re_dfastate_t *cur_state;
-
- if (entry->node != node)
- continue;
- subexp_len = entry->subexp_to - entry->subexp_from;
- to_idx = str_idx + subexp_len;
- dst_node = (subexp_len ? dfa->nexts[node]
- : dfa->edests[node].elems[0]);
-
- if (to_idx > sctx->last_str_idx
- || sctx->sifted_states[to_idx] == NULL
- || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node)
- || check_dst_limits (mctx, &sctx->limits, node,
- str_idx, dst_node, to_idx))
- continue;
-
- if (local_sctx.sifted_states == NULL)
- {
- local_sctx = *sctx;
- err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
- }
- local_sctx.last_node = node;
- local_sctx.last_str_idx = str_idx;
- ret = re_node_set_insert (&local_sctx.limits, enabled_idx);
- if (BE (ret < 0, 0))
- {
- err = REG_ESPACE;
- goto free_return;
- }
- cur_state = local_sctx.sifted_states[str_idx];
- err = sift_states_backward (mctx, &local_sctx);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
- if (sctx->limited_states != NULL)
- {
- err = merge_state_array (dfa, sctx->limited_states,
- local_sctx.sifted_states,
- str_idx + 1);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
- }
- local_sctx.sifted_states[str_idx] = cur_state;
- re_node_set_remove (&local_sctx.limits, enabled_idx);
-
- /* mctx->bkref_ents may have changed, reload the pointer. */
- entry = mctx->bkref_ents + enabled_idx;
- }
- while (enabled_idx++, entry++->more);
- }
- err = REG_NOERROR;
- free_return:
- if (local_sctx.sifted_states != NULL)
- {
- re_node_set_free (&local_sctx.limits);
- }
-
- return err;
-}
-
-
-#ifdef RE_ENABLE_I18N
-static int
-internal_function
-sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
- int node_idx, int str_idx, int max_str_idx)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- int naccepted;
- /* Check the node can accept `multi byte'. */
- naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx);
- if (naccepted > 0 && str_idx + naccepted <= max_str_idx &&
- !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted],
- dfa->nexts[node_idx]))
- /* The node can't accept the `multi byte', or the
- destination was already thrown away, then the node
- could't accept the current input `multi byte'. */
- naccepted = 0;
- /* Otherwise, it is sure that the node could accept
- `naccepted' bytes input. */
- return naccepted;
-}
-#endif /* RE_ENABLE_I18N */
-
-
-/* Functions for state transition. */
-
-/* Return the next state to which the current state STATE will transit by
- accepting the current input byte, and update STATE_LOG if necessary.
- If STATE can accept a multibyte char/collating element/back reference
- update the destination of STATE_LOG. */
-
-static re_dfastate_t *
-internal_function
-transit_state (reg_errcode_t *err, re_match_context_t *mctx,
- re_dfastate_t *state)
-{
- re_dfastate_t **trtable;
- unsigned char ch;
-
-#ifdef RE_ENABLE_I18N
- /* If the current state can accept multibyte. */
- if (BE (state->accept_mb, 0))
- {
- *err = transit_state_mb (mctx, state);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- }
-#endif /* RE_ENABLE_I18N */
-
- /* Then decide the next state with the single byte. */
-#if 0
- if (0)
- /* don't use transition table */
- return transit_state_sb (err, mctx, state);
-#endif
-
- /* Use transition table */
- ch = re_string_fetch_byte (&mctx->input);
- for (;;)
- {
- trtable = state->trtable;
- if (BE (trtable != NULL, 1))
- return trtable[ch];
-
- trtable = state->word_trtable;
- if (BE (trtable != NULL, 1))
- {
- unsigned int context;
- context
- = re_string_context_at (&mctx->input,
- re_string_cur_idx (&mctx->input) - 1,
- mctx->eflags);
- if (IS_WORD_CONTEXT (context))
- return trtable[ch + SBC_MAX];
- else
- return trtable[ch];
- }
-
- if (!build_trtable (mctx->dfa, state))
- {
- *err = REG_ESPACE;
- return NULL;
- }
-
- /* Retry, we now have a transition table. */
- }
-}
-
-/* Update the state_log if we need */
-re_dfastate_t *
-internal_function
-merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx,
- re_dfastate_t *next_state)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- int cur_idx = re_string_cur_idx (&mctx->input);
-
- if (cur_idx > mctx->state_log_top)
- {
- mctx->state_log[cur_idx] = next_state;
- mctx->state_log_top = cur_idx;
- }
- else if (mctx->state_log[cur_idx] == 0)
- {
- mctx->state_log[cur_idx] = next_state;
- }
- else
- {
- re_dfastate_t *pstate;
- unsigned int context;
- re_node_set next_nodes, *log_nodes, *table_nodes = NULL;
- /* If (state_log[cur_idx] != 0), it implies that cur_idx is
- the destination of a multibyte char/collating element/
- back reference. Then the next state is the union set of
- these destinations and the results of the transition table. */
- pstate = mctx->state_log[cur_idx];
- log_nodes = pstate->entrance_nodes;
- if (next_state != NULL)
- {
- table_nodes = next_state->entrance_nodes;
- *err = re_node_set_init_union (&next_nodes, table_nodes,
- log_nodes);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- }
- else
- next_nodes = *log_nodes;
- /* Note: We already add the nodes of the initial state,
- then we don't need to add them here. */
-
- context = re_string_context_at (&mctx->input,
- re_string_cur_idx (&mctx->input) - 1,
- mctx->eflags);
- next_state = mctx->state_log[cur_idx]
- = re_acquire_state_context (err, dfa, &next_nodes, context);
- /* We don't need to check errors here, since the return value of
- this function is next_state and ERR is already set. */
-
- if (table_nodes != NULL)
- re_node_set_free (&next_nodes);
- }
-
- if (BE (dfa->nbackref, 0) && next_state != NULL)
- {
- /* Check OP_OPEN_SUBEXP in the current state in case that we use them
- later. We must check them here, since the back references in the
- next state might use them. */
- *err = check_subexp_matching_top (mctx, &next_state->nodes,
- cur_idx);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
-
- /* If the next state has back references. */
- if (next_state->has_backref)
- {
- *err = transit_state_bkref (mctx, &next_state->nodes);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- next_state = mctx->state_log[cur_idx];
- }
- }
-
- return next_state;
-}
-
-/* Skip bytes in the input that correspond to part of a
- multi-byte match, then look in the log for a state
- from which to restart matching. */
-re_dfastate_t *
-internal_function
-find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)
-{
- re_dfastate_t *cur_state;
- do
- {
- int max = mctx->state_log_top;
- int cur_str_idx = re_string_cur_idx (&mctx->input);
-
- do
- {
- if (++cur_str_idx > max)
- return NULL;
- re_string_skip_bytes (&mctx->input, 1);
- }
- while (mctx->state_log[cur_str_idx] == NULL);
-
- cur_state = merge_state_with_log (err, mctx, NULL);
- }
- while (*err == REG_NOERROR && cur_state == NULL);
- return cur_state;
-}
-
-/* Helper functions for transit_state. */
-
-/* From the node set CUR_NODES, pick up the nodes whose types are
- OP_OPEN_SUBEXP and which have corresponding back references in the regular
- expression. And register them to use them later for evaluating the
- correspoding back references. */
-
-static reg_errcode_t
-internal_function
-check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes,
- int str_idx)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- int node_idx;
- reg_errcode_t err;
-
- /* TODO: This isn't efficient.
- Because there might be more than one nodes whose types are
- OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
- nodes.
- E.g. RE: (a){2} */
- for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx)
- {
- int node = cur_nodes->elems[node_idx];
- if (dfa->nodes[node].type == OP_OPEN_SUBEXP
- && dfa->nodes[node].opr.idx < BITSET_WORD_BITS
- && (dfa->used_bkref_map
- & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx)))
- {
- err = match_ctx_add_subtop (mctx, node, str_idx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- }
- return REG_NOERROR;
-}
-
-#if 0
-/* Return the next state to which the current state STATE will transit by
- accepting the current input byte. */
-
-static re_dfastate_t *
-transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,
- re_dfastate_t *state)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- re_node_set next_nodes;
- re_dfastate_t *next_state;
- int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input);
- unsigned int context;
-
- *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt)
- {
- int cur_node = state->nodes.elems[node_cnt];
- if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx))
- {
- *err = re_node_set_merge (&next_nodes,
- dfa->eclosures + dfa->nexts[cur_node]);
- if (BE (*err != REG_NOERROR, 0))
- {
- re_node_set_free (&next_nodes);
- return NULL;
- }
- }
- }
- context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags);
- next_state = re_acquire_state_context (err, dfa, &next_nodes, context);
- /* We don't need to check errors here, since the return value of
- this function is next_state and ERR is already set. */
-
- re_node_set_free (&next_nodes);
- re_string_skip_bytes (&mctx->input, 1);
- return next_state;
-}
-#endif
-
-#ifdef RE_ENABLE_I18N
-static reg_errcode_t
-internal_function
-transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- reg_errcode_t err;
- int i;
-
- for (i = 0; i < pstate->nodes.nelem; ++i)
- {
- re_node_set dest_nodes, *new_nodes;
- int cur_node_idx = pstate->nodes.elems[i];
- int naccepted, dest_idx;
- unsigned int context;
- re_dfastate_t *dest_state;
-
- if (!dfa->nodes[cur_node_idx].accept_mb)
- continue;
-
- if (dfa->nodes[cur_node_idx].constraint)
- {
- context = re_string_context_at (&mctx->input,
- re_string_cur_idx (&mctx->input),
- mctx->eflags);
- if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint,
- context))
- continue;
- }
-
- /* How many bytes the node can accept? */
- naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input,
- re_string_cur_idx (&mctx->input));
- if (naccepted == 0)
- continue;
-
- /* The node can accepts `naccepted' bytes. */
- dest_idx = re_string_cur_idx (&mctx->input) + naccepted;
- mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted
- : mctx->max_mb_elem_len);
- err = clean_state_log_if_needed (mctx, dest_idx);
- if (BE (err != REG_NOERROR, 0))
- return err;
-#ifdef DEBUG
- assert (dfa->nexts[cur_node_idx] != -1);
-#endif
- new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx];
-
- dest_state = mctx->state_log[dest_idx];
- if (dest_state == NULL)
- dest_nodes = *new_nodes;
- else
- {
- err = re_node_set_init_union (&dest_nodes,
- dest_state->entrance_nodes, new_nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- context = re_string_context_at (&mctx->input, dest_idx - 1,
- mctx->eflags);
- mctx->state_log[dest_idx]
- = re_acquire_state_context (&err, dfa, &dest_nodes, context);
- if (dest_state != NULL)
- re_node_set_free (&dest_nodes);
- if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0))
- return err;
- }
- return REG_NOERROR;
-}
-#endif /* RE_ENABLE_I18N */
-
-static reg_errcode_t
-internal_function
-transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- reg_errcode_t err;
- int i;
- int cur_str_idx = re_string_cur_idx (&mctx->input);
-
- for (i = 0; i < nodes->nelem; ++i)
- {
- int dest_str_idx, prev_nelem, bkc_idx;
- int node_idx = nodes->elems[i];
- unsigned int context;
- const re_token_t *node = dfa->nodes + node_idx;
- re_node_set *new_dest_nodes;
-
- /* Check whether `node' is a backreference or not. */
- if (node->type != OP_BACK_REF)
- continue;
-
- if (node->constraint)
- {
- context = re_string_context_at (&mctx->input, cur_str_idx,
- mctx->eflags);
- if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
- continue;
- }
-
- /* `node' is a backreference.
- Check the substring which the substring matched. */
- bkc_idx = mctx->nbkref_ents;
- err = get_subexp (mctx, node_idx, cur_str_idx);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
-
- /* And add the epsilon closures (which is `new_dest_nodes') of
- the backreference to appropriate state_log. */
-#ifdef DEBUG
- assert (dfa->nexts[node_idx] != -1);
-#endif
- for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx)
- {
- int subexp_len;
- re_dfastate_t *dest_state;
- struct re_backref_cache_entry *bkref_ent;
- bkref_ent = mctx->bkref_ents + bkc_idx;
- if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx)
- continue;
- subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from;
- new_dest_nodes = (subexp_len == 0
- ? dfa->eclosures + dfa->edests[node_idx].elems[0]
- : dfa->eclosures + dfa->nexts[node_idx]);
- dest_str_idx = (cur_str_idx + bkref_ent->subexp_to
- - bkref_ent->subexp_from);
- context = re_string_context_at (&mctx->input, dest_str_idx - 1,
- mctx->eflags);
- dest_state = mctx->state_log[dest_str_idx];
- prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0
- : mctx->state_log[cur_str_idx]->nodes.nelem);
- /* Add `new_dest_node' to state_log. */
- if (dest_state == NULL)
- {
- mctx->state_log[dest_str_idx]
- = re_acquire_state_context (&err, dfa, new_dest_nodes,
- context);
- if (BE (mctx->state_log[dest_str_idx] == NULL
- && err != REG_NOERROR, 0))
- goto free_return;
- }
- else
- {
- re_node_set dest_nodes;
- err = re_node_set_init_union (&dest_nodes,
- dest_state->entrance_nodes,
- new_dest_nodes);
- if (BE (err != REG_NOERROR, 0))
- {
- re_node_set_free (&dest_nodes);
- goto free_return;
- }
- mctx->state_log[dest_str_idx]
- = re_acquire_state_context (&err, dfa, &dest_nodes, context);
- re_node_set_free (&dest_nodes);
- if (BE (mctx->state_log[dest_str_idx] == NULL
- && err != REG_NOERROR, 0))
- goto free_return;
- }
- /* We need to check recursively if the backreference can epsilon
- transit. */
- if (subexp_len == 0
- && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem)
- {
- err = check_subexp_matching_top (mctx, new_dest_nodes,
- cur_str_idx);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
- err = transit_state_bkref (mctx, new_dest_nodes);
- if (BE (err != REG_NOERROR, 0))
- goto free_return;
- }
- }
- }
- err = REG_NOERROR;
- free_return:
- return err;
-}
-
-/* Enumerate all the candidates which the backreference BKREF_NODE can match
- at BKREF_STR_IDX, and register them by match_ctx_add_entry().
- Note that we might collect inappropriate candidates here.
- However, the cost of checking them strictly here is too high, then we
- delay these checking for prune_impossible_nodes(). */
-
-static reg_errcode_t
-internal_function
-get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- int subexp_num, sub_top_idx;
- const char *buf = (const char *) re_string_get_buffer (&mctx->input);
- /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */
- int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx);
- if (cache_idx != -1)
- {
- const struct re_backref_cache_entry *entry
- = mctx->bkref_ents + cache_idx;
- do
- if (entry->node == bkref_node)
- return REG_NOERROR; /* We already checked it. */
- while (entry++->more);
- }
-
- subexp_num = dfa->nodes[bkref_node].opr.idx;
-
- /* For each sub expression */
- for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx)
- {
- reg_errcode_t err;
- re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx];
- re_sub_match_last_t *sub_last;
- int sub_last_idx, sl_str, bkref_str_off;
-
- if (dfa->nodes[sub_top->node].opr.idx != subexp_num)
- continue; /* It isn't related. */
-
- sl_str = sub_top->str_idx;
- bkref_str_off = bkref_str_idx;
- /* At first, check the last node of sub expressions we already
- evaluated. */
- for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx)
- {
- int sl_str_diff;
- sub_last = sub_top->lasts[sub_last_idx];
- sl_str_diff = sub_last->str_idx - sl_str;
- /* The matched string by the sub expression match with the substring
- at the back reference? */
- if (sl_str_diff > 0)
- {
- if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0))
- {
- /* Not enough chars for a successful match. */
- if (bkref_str_off + sl_str_diff > mctx->input.len)
- break;
-
- err = clean_state_log_if_needed (mctx,
- bkref_str_off
- + sl_str_diff);
- if (BE (err != REG_NOERROR, 0))
- return err;
- buf = (const char *) re_string_get_buffer (&mctx->input);
- }
- if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0)
- /* We don't need to search this sub expression any more. */
- break;
- }
- bkref_str_off += sl_str_diff;
- sl_str += sl_str_diff;
- err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
- bkref_str_idx);
-
- /* Reload buf, since the preceding call might have reallocated
- the buffer. */
- buf = (const char *) re_string_get_buffer (&mctx->input);
-
- if (err == REG_NOMATCH)
- continue;
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
-
- if (sub_last_idx < sub_top->nlasts)
- continue;
- if (sub_last_idx > 0)
- ++sl_str;
- /* Then, search for the other last nodes of the sub expression. */
- for (; sl_str <= bkref_str_idx; ++sl_str)
- {
- int cls_node, sl_str_off;
- const re_node_set *nodes;
- sl_str_off = sl_str - sub_top->str_idx;
- /* The matched string by the sub expression match with the substring
- at the back reference? */
- if (sl_str_off > 0)
- {
- if (BE (bkref_str_off >= mctx->input.valid_len, 0))
- {
- /* If we are at the end of the input, we cannot match. */
- if (bkref_str_off >= mctx->input.len)
- break;
-
- err = extend_buffers (mctx);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- buf = (const char *) re_string_get_buffer (&mctx->input);
- }
- if (buf [bkref_str_off++] != buf[sl_str - 1])
- break; /* We don't need to search this sub expression
- any more. */
- }
- if (mctx->state_log[sl_str] == NULL)
- continue;
- /* Does this state have a ')' of the sub expression? */
- nodes = &mctx->state_log[sl_str]->nodes;
- cls_node = find_subexp_node (dfa, nodes, subexp_num,
- OP_CLOSE_SUBEXP);
- if (cls_node == -1)
- continue; /* No. */
- if (sub_top->path == NULL)
- {
- sub_top->path = calloc (sizeof (state_array_t),
- sl_str - sub_top->str_idx + 1);
- if (sub_top->path == NULL)
- return REG_ESPACE;
- }
- /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node
- in the current context? */
- err = check_arrival (mctx, sub_top->path, sub_top->node,
- sub_top->str_idx, cls_node, sl_str,
- OP_CLOSE_SUBEXP);
- if (err == REG_NOMATCH)
- continue;
- if (BE (err != REG_NOERROR, 0))
- return err;
- sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str);
- if (BE (sub_last == NULL, 0))
- return REG_ESPACE;
- err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
- bkref_str_idx);
- if (err == REG_NOMATCH)
- continue;
- }
- }
- return REG_NOERROR;
-}
-
-/* Helper functions for get_subexp(). */
-
-/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR.
- If it can arrive, register the sub expression expressed with SUB_TOP
- and SUB_LAST. */
-
-static reg_errcode_t
-internal_function
-get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top,
- re_sub_match_last_t *sub_last, int bkref_node, int bkref_str)
-{
- reg_errcode_t err;
- int to_idx;
- /* Can the subexpression arrive the back reference? */
- err = check_arrival (mctx, &sub_last->path, sub_last->node,
- sub_last->str_idx, bkref_node, bkref_str,
- OP_OPEN_SUBEXP);
- if (err != REG_NOERROR)
- return err;
- err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx,
- sub_last->str_idx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx;
- return clean_state_log_if_needed (mctx, to_idx);
-}
-
-/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX.
- Search '(' if FL_OPEN, or search ')' otherwise.
- TODO: This function isn't efficient...
- Because there might be more than one nodes whose types are
- OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
- nodes.
- E.g. RE: (a){2} */
-
-static int
-internal_function
-find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
- int subexp_idx, int type)
-{
- int cls_idx;
- for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx)
- {
- int cls_node = nodes->elems[cls_idx];
- const re_token_t *node = dfa->nodes + cls_node;
- if (node->type == type
- && node->opr.idx == subexp_idx)
- return cls_node;
- }
- return -1;
-}
-
-/* Check whether the node TOP_NODE at TOP_STR can arrive to the node
- LAST_NODE at LAST_STR. We record the path onto PATH since it will be
- heavily reused.
- Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */
-
-static reg_errcode_t
-internal_function
-check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node,
- int top_str, int last_node, int last_str, int type)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- reg_errcode_t err = REG_NOERROR;
- int subexp_num, backup_cur_idx, str_idx, null_cnt;
- re_dfastate_t *cur_state = NULL;
- re_node_set *cur_nodes, next_nodes;
- re_dfastate_t **backup_state_log;
- unsigned int context;
-
- subexp_num = dfa->nodes[top_node].opr.idx;
- /* Extend the buffer if we need. */
- if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0))
- {
- re_dfastate_t **new_array;
- int old_alloc = path->alloc;
- path->alloc += last_str + mctx->max_mb_elem_len + 1;
- new_array = re_realloc (path->array, re_dfastate_t *, path->alloc);
- if (BE (new_array == NULL, 0))
- {
- path->alloc = old_alloc;
- return REG_ESPACE;
- }
- path->array = new_array;
- memset (new_array + old_alloc, '\0',
- sizeof (re_dfastate_t *) * (path->alloc - old_alloc));
- }
-
- str_idx = path->next_idx ?: top_str;
-
- /* Temporary modify MCTX. */
- backup_state_log = mctx->state_log;
- backup_cur_idx = mctx->input.cur_idx;
- mctx->state_log = path->array;
- mctx->input.cur_idx = str_idx;
-
- /* Setup initial node set. */
- context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
- if (str_idx == top_str)
- {
- err = re_node_set_init_1 (&next_nodes, top_node);
- if (BE (err != REG_NOERROR, 0))
- return err;
- err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
- if (BE (err != REG_NOERROR, 0))
- {
- re_node_set_free (&next_nodes);
- return err;
- }
- }
- else
- {
- cur_state = mctx->state_log[str_idx];
- if (cur_state && cur_state->has_backref)
- {
- err = re_node_set_init_copy (&next_nodes, &cur_state->nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- else
- re_node_set_init_empty (&next_nodes);
- }
- if (str_idx == top_str || (cur_state && cur_state->has_backref))
- {
- if (next_nodes.nelem)
- {
- err = expand_bkref_cache (mctx, &next_nodes, str_idx,
- subexp_num, type);
- if (BE (err != REG_NOERROR, 0))
- {
- re_node_set_free (&next_nodes);
- return err;
- }
- }
- cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
- if (BE (cur_state == NULL && err != REG_NOERROR, 0))
- {
- re_node_set_free (&next_nodes);
- return err;
- }
- mctx->state_log[str_idx] = cur_state;
- }
-
- for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;)
- {
- re_node_set_empty (&next_nodes);
- if (mctx->state_log[str_idx + 1])
- {
- err = re_node_set_merge (&next_nodes,
- &mctx->state_log[str_idx + 1]->nodes);
- if (BE (err != REG_NOERROR, 0))
- {
- re_node_set_free (&next_nodes);
- return err;
- }
- }
- if (cur_state)
- {
- err = check_arrival_add_next_nodes (mctx, str_idx,
- &cur_state->non_eps_nodes,
- &next_nodes);
- if (BE (err != REG_NOERROR, 0))
- {
- re_node_set_free (&next_nodes);
- return err;
- }
- }
- ++str_idx;
- if (next_nodes.nelem)
- {
- err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
- if (BE (err != REG_NOERROR, 0))
- {
- re_node_set_free (&next_nodes);
- return err;
- }
- err = expand_bkref_cache (mctx, &next_nodes, str_idx,
- subexp_num, type);
- if (BE (err != REG_NOERROR, 0))
- {
- re_node_set_free (&next_nodes);
- return err;
- }
- }
- context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
- cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
- if (BE (cur_state == NULL && err != REG_NOERROR, 0))
- {
- re_node_set_free (&next_nodes);
- return err;
- }
- mctx->state_log[str_idx] = cur_state;
- null_cnt = cur_state == NULL ? null_cnt + 1 : 0;
- }
- re_node_set_free (&next_nodes);
- cur_nodes = (mctx->state_log[last_str] == NULL ? NULL
- : &mctx->state_log[last_str]->nodes);
- path->next_idx = str_idx;
-
- /* Fix MCTX. */
- mctx->state_log = backup_state_log;
- mctx->input.cur_idx = backup_cur_idx;
-
- /* Then check the current node set has the node LAST_NODE. */
- if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node))
- return REG_NOERROR;
-
- return REG_NOMATCH;
-}
-
-/* Helper functions for check_arrival. */
-
-/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them
- to NEXT_NODES.
- TODO: This function is similar to the functions transit_state*(),
- however this function has many additional works.
- Can't we unify them? */
-
-static reg_errcode_t
-internal_function
-check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx,
- re_node_set *cur_nodes, re_node_set *next_nodes)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- int result;
- int cur_idx;
- reg_errcode_t err = REG_NOERROR;
- re_node_set union_set;
- re_node_set_init_empty (&union_set);
- for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx)
- {
- int naccepted = 0;
- int cur_node = cur_nodes->elems[cur_idx];
-#ifdef DEBUG
- re_token_type_t type = dfa->nodes[cur_node].type;
- assert (!IS_EPSILON_NODE (type));
-#endif
-#ifdef RE_ENABLE_I18N
- /* If the node may accept `multi byte'. */
- if (dfa->nodes[cur_node].accept_mb)
- {
- naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input,
- str_idx);
- if (naccepted > 1)
- {
- re_dfastate_t *dest_state;
- int next_node = dfa->nexts[cur_node];
- int next_idx = str_idx + naccepted;
- dest_state = mctx->state_log[next_idx];
- re_node_set_empty (&union_set);
- if (dest_state)
- {
- err = re_node_set_merge (&union_set, &dest_state->nodes);
- if (BE (err != REG_NOERROR, 0))
- {
- re_node_set_free (&union_set);
- return err;
- }
- }
- result = re_node_set_insert (&union_set, next_node);
- if (BE (result < 0, 0))
- {
- re_node_set_free (&union_set);
- return REG_ESPACE;
- }
- mctx->state_log[next_idx] = re_acquire_state (&err, dfa,
- &union_set);
- if (BE (mctx->state_log[next_idx] == NULL
- && err != REG_NOERROR, 0))
- {
- re_node_set_free (&union_set);
- return err;
- }
- }
- }
-#endif /* RE_ENABLE_I18N */
- if (naccepted
- || check_node_accept (mctx, dfa->nodes + cur_node, str_idx))
- {
- result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]);
- if (BE (result < 0, 0))
- {
- re_node_set_free (&union_set);
- return REG_ESPACE;
- }
- }
- }
- re_node_set_free (&union_set);
- return REG_NOERROR;
-}
-
-/* For all the nodes in CUR_NODES, add the epsilon closures of them to
- CUR_NODES, however exclude the nodes which are:
- - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN.
- - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN.
-*/
-
-static reg_errcode_t
-internal_function
-check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,
- int ex_subexp, int type)
-{
- reg_errcode_t err;
- int idx, outside_node;
- re_node_set new_nodes;
-#ifdef DEBUG
- assert (cur_nodes->nelem);
-#endif
- err = re_node_set_alloc (&new_nodes, cur_nodes->nelem);
- if (BE (err != REG_NOERROR, 0))
- return err;
- /* Create a new node set NEW_NODES with the nodes which are epsilon
- closures of the node in CUR_NODES. */
-
- for (idx = 0; idx < cur_nodes->nelem; ++idx)
- {
- int cur_node = cur_nodes->elems[idx];
- const re_node_set *eclosure = dfa->eclosures + cur_node;
- outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type);
- if (outside_node == -1)
- {
- /* There are no problematic nodes, just merge them. */
- err = re_node_set_merge (&new_nodes, eclosure);
- if (BE (err != REG_NOERROR, 0))
- {
- re_node_set_free (&new_nodes);
- return err;
- }
- }
- else
- {
- /* There are problematic nodes, re-calculate incrementally. */
- err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node,
- ex_subexp, type);
- if (BE (err != REG_NOERROR, 0))
- {
- re_node_set_free (&new_nodes);
- return err;
- }
- }
- }
- re_node_set_free (cur_nodes);
- *cur_nodes = new_nodes;
- return REG_NOERROR;
-}
-
-/* Helper function for check_arrival_expand_ecl.
- Check incrementally the epsilon closure of TARGET, and if it isn't
- problematic append it to DST_NODES. */
-
-static reg_errcode_t
-internal_function
-check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes,
- int target, int ex_subexp, int type)
-{
- int cur_node;
- for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);)
- {
- int err;
-
- if (dfa->nodes[cur_node].type == type
- && dfa->nodes[cur_node].opr.idx == ex_subexp)
- {
- if (type == OP_CLOSE_SUBEXP)
- {
- err = re_node_set_insert (dst_nodes, cur_node);
- if (BE (err == -1, 0))
- return REG_ESPACE;
- }
- break;
- }
- err = re_node_set_insert (dst_nodes, cur_node);
- if (BE (err == -1, 0))
- return REG_ESPACE;
- if (dfa->edests[cur_node].nelem == 0)
- break;
- if (dfa->edests[cur_node].nelem == 2)
- {
- err = check_arrival_expand_ecl_sub (dfa, dst_nodes,
- dfa->edests[cur_node].elems[1],
- ex_subexp, type);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- cur_node = dfa->edests[cur_node].elems[0];
- }
- return REG_NOERROR;
-}
-
-
-/* For all the back references in the current state, calculate the
- destination of the back references by the appropriate entry
- in MCTX->BKREF_ENTS. */
-
-static reg_errcode_t
-internal_function
-expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
- int cur_str, int subexp_num, int type)
-{
- const re_dfa_t *const dfa = mctx->dfa;
- reg_errcode_t err;
- int cache_idx_start = search_cur_bkref_entry (mctx, cur_str);
- struct re_backref_cache_entry *ent;
-
- if (cache_idx_start == -1)
- return REG_NOERROR;
-
- restart:
- ent = mctx->bkref_ents + cache_idx_start;
- do
- {
- int to_idx, next_node;
-
- /* Is this entry ENT is appropriate? */
- if (!re_node_set_contains (cur_nodes, ent->node))
- continue; /* No. */
-
- to_idx = cur_str + ent->subexp_to - ent->subexp_from;
- /* Calculate the destination of the back reference, and append it
- to MCTX->STATE_LOG. */
- if (to_idx == cur_str)
- {
- /* The backreference did epsilon transit, we must re-check all the
- node in the current state. */
- re_node_set new_dests;
- reg_errcode_t err2, err3;
- next_node = dfa->edests[ent->node].elems[0];
- if (re_node_set_contains (cur_nodes, next_node))
- continue;
- err = re_node_set_init_1 (&new_dests, next_node);
- err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type);
- err3 = re_node_set_merge (cur_nodes, &new_dests);
- re_node_set_free (&new_dests);
- if (BE (err != REG_NOERROR || err2 != REG_NOERROR
- || err3 != REG_NOERROR, 0))
- {
- err = (err != REG_NOERROR ? err
- : (err2 != REG_NOERROR ? err2 : err3));
- return err;
- }
- /* TODO: It is still inefficient... */
- goto restart;
- }
- else
- {
- re_node_set union_set;
- next_node = dfa->nexts[ent->node];
- if (mctx->state_log[to_idx])
- {
- int ret;
- if (re_node_set_contains (&mctx->state_log[to_idx]->nodes,
- next_node))
- continue;
- err = re_node_set_init_copy (&union_set,
- &mctx->state_log[to_idx]->nodes);
- ret = re_node_set_insert (&union_set, next_node);
- if (BE (err != REG_NOERROR || ret < 0, 0))
- {
- re_node_set_free (&union_set);
- err = err != REG_NOERROR ? err : REG_ESPACE;
- return err;
- }
- }
- else
- {
- err = re_node_set_init_1 (&union_set, next_node);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set);
- re_node_set_free (&union_set);
- if (BE (mctx->state_log[to_idx] == NULL
- && err != REG_NOERROR, 0))
- return err;
- }
- }
- while (ent++->more);
- return REG_NOERROR;
-}
-
-/* Build transition table for the state.
- Return 1 if succeeded, otherwise return NULL. */
-
-static int
-internal_function
-build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
-{
- reg_errcode_t err;
- int i, j, ch, need_word_trtable = 0;
- bitset_word_t elem, mask;
- bool dests_node_malloced = false;
- bool dest_states_malloced = false;
- int ndests; /* Number of the destination states from `state'. */
- re_dfastate_t **trtable;
- re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl;
- re_node_set follows, *dests_node;
- bitset_t *dests_ch;
- bitset_t acceptable;
-
- struct dests_alloc
- {
- re_node_set dests_node[SBC_MAX];
- bitset_t dests_ch[SBC_MAX];
- } *dests_alloc;
-
- /* We build DFA states which corresponds to the destination nodes
- from `state'. `dests_node[i]' represents the nodes which i-th
- destination state contains, and `dests_ch[i]' represents the
- characters which i-th destination state accepts. */
- if (__libc_use_alloca (sizeof (struct dests_alloc)))
- dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc));
- else
- {
- dests_alloc = re_malloc (struct dests_alloc, 1);
- if (BE (dests_alloc == NULL, 0))
- return 0;
- dests_node_malloced = true;
- }
- dests_node = dests_alloc->dests_node;
- dests_ch = dests_alloc->dests_ch;
-
- /* Initialize transiton table. */
- state->word_trtable = state->trtable = NULL;
-
- /* At first, group all nodes belonging to `state' into several
- destinations. */
- ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch);
- if (BE (ndests <= 0, 0))
- {
- if (dests_node_malloced)
- free (dests_alloc);
- /* Return 0 in case of an error, 1 otherwise. */
- if (ndests == 0)
- {
- state->trtable = (re_dfastate_t **)
- calloc (sizeof (re_dfastate_t *), SBC_MAX);
- return 1;
- }
- return 0;
- }
-
- err = re_node_set_alloc (&follows, ndests + 1);
- if (BE (err != REG_NOERROR, 0))
- goto out_free;
-
- if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX
- + ndests * 3 * sizeof (re_dfastate_t *)))
- dest_states = (re_dfastate_t **)
- alloca (ndests * 3 * sizeof (re_dfastate_t *));
- else
- {
- dest_states = (re_dfastate_t **)
- malloc (ndests * 3 * sizeof (re_dfastate_t *));
- if (BE (dest_states == NULL, 0))
- {
-out_free:
- if (dest_states_malloced)
- free (dest_states);
- re_node_set_free (&follows);
- for (i = 0; i < ndests; ++i)
- re_node_set_free (dests_node + i);
- if (dests_node_malloced)
- free (dests_alloc);
- return 0;
- }
- dest_states_malloced = true;
- }
- dest_states_word = dest_states + ndests;
- dest_states_nl = dest_states_word + ndests;
- bitset_empty (acceptable);
-
- /* Then build the states for all destinations. */
- for (i = 0; i < ndests; ++i)
- {
- int next_node;
- re_node_set_empty (&follows);
- /* Merge the follows of this destination states. */
- for (j = 0; j < dests_node[i].nelem; ++j)
- {
- next_node = dfa->nexts[dests_node[i].elems[j]];
- if (next_node != -1)
- {
- err = re_node_set_merge (&follows, dfa->eclosures + next_node);
- if (BE (err != REG_NOERROR, 0))
- goto out_free;
- }
- }
- dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0);
- if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0))
- goto out_free;
- /* If the new state has context constraint,
- build appropriate states for these contexts. */
- if (dest_states[i]->has_constraint)
- {
- dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows,
- CONTEXT_WORD);
- if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))
- goto out_free;
-
- if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1)
- need_word_trtable = 1;
-
- dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
- CONTEXT_NEWLINE);
- if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0))
- goto out_free;
- }
- else
- {
- dest_states_word[i] = dest_states[i];
- dest_states_nl[i] = dest_states[i];
- }
- bitset_merge (acceptable, dests_ch[i]);
- }
-
- if (!BE (need_word_trtable, 0))
- {
- /* We don't care about whether the following character is a word
- character, or we are in a single-byte character set so we can
- discern by looking at the character code: allocate a
- 256-entry transition table. */
- trtable = state->trtable =
- (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
- if (BE (trtable == NULL, 0))
- goto out_free;
-
- /* For all characters ch...: */
- for (i = 0; i < BITSET_WORDS; ++i)
- for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;
- elem;
- mask <<= 1, elem >>= 1, ++ch)
- if (BE (elem & 1, 0))
- {
- /* There must be exactly one destination which accepts
- character ch. See group_nodes_into_DFAstates. */
- for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)
- ;
-
- /* j-th destination accepts the word character ch. */
- if (dfa->word_char[i] & mask)
- trtable[ch] = dest_states_word[j];
- else
- trtable[ch] = dest_states[j];
- }
- }
- else
- {
- /* We care about whether the following character is a word
- character, and we are in a multi-byte character set: discern
- by looking at the character code: build two 256-entry
- transition tables, one starting at trtable[0] and one
- starting at trtable[SBC_MAX]. */
- trtable = state->word_trtable =
- (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX);
- if (BE (trtable == NULL, 0))
- goto out_free;
-
- /* For all characters ch...: */
- for (i = 0; i < BITSET_WORDS; ++i)
- for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;
- elem;
- mask <<= 1, elem >>= 1, ++ch)
- if (BE (elem & 1, 0))
- {
- /* There must be exactly one destination which accepts
- character ch. See group_nodes_into_DFAstates. */
- for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)
- ;
-
- /* j-th destination accepts the word character ch. */
- trtable[ch] = dest_states[j];
- trtable[ch + SBC_MAX] = dest_states_word[j];
- }
- }
-
- /* new line */
- if (bitset_contain (acceptable, NEWLINE_CHAR))
- {
- /* The current state accepts newline character. */
- for (j = 0; j < ndests; ++j)
- if (bitset_contain (dests_ch[j], NEWLINE_CHAR))
- {
- /* k-th destination accepts newline character. */
- trtable[NEWLINE_CHAR] = dest_states_nl[j];
- if (need_word_trtable)
- trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j];
- /* There must be only one destination which accepts
- newline. See group_nodes_into_DFAstates. */
- break;
- }
- }
-
- if (dest_states_malloced)
- free (dest_states);
-
- re_node_set_free (&follows);
- for (i = 0; i < ndests; ++i)
- re_node_set_free (dests_node + i);
-
- if (dests_node_malloced)
- free (dests_alloc);
-
- return 1;
-}
-
-/* Group all nodes belonging to STATE into several destinations.
- Then for all destinations, set the nodes belonging to the destination
- to DESTS_NODE[i] and set the characters accepted by the destination
- to DEST_CH[i]. This function return the number of destinations. */
-
-static int
-internal_function
-group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
- re_node_set *dests_node, bitset_t *dests_ch)
-{
- reg_errcode_t err;
- int result;
- int i, j, k;
- int ndests; /* Number of the destinations from `state'. */
- bitset_t accepts; /* Characters a node can accept. */
- const re_node_set *cur_nodes = &state->nodes;
- bitset_empty (accepts);
- ndests = 0;
-
- /* For all the nodes belonging to `state', */
- for (i = 0; i < cur_nodes->nelem; ++i)
- {
- re_token_t *node = &dfa->nodes[cur_nodes->elems[i]];
- re_token_type_t type = node->type;
- unsigned int constraint = node->constraint;
-
- /* Enumerate all single byte character this node can accept. */
- if (type == CHARACTER)
- bitset_set (accepts, node->opr.c);
- else if (type == SIMPLE_BRACKET)
- {
- bitset_merge (accepts, node->opr.sbcset);
- }
- else if (type == OP_PERIOD)
- {
-#ifdef RE_ENABLE_I18N
- if (dfa->mb_cur_max > 1)
- bitset_merge (accepts, dfa->sb_char);
- else
-#endif
- bitset_set_all (accepts);
- if (!(dfa->syntax & RE_DOT_NEWLINE))
- bitset_clear (accepts, '\n');
- if (dfa->syntax & RE_DOT_NOT_NULL)
- bitset_clear (accepts, '\0');
- }
-#ifdef RE_ENABLE_I18N
- else if (type == OP_UTF8_PERIOD)
- {
- memset (accepts, '\xff', sizeof (bitset_t) / 2);
- if (!(dfa->syntax & RE_DOT_NEWLINE))
- bitset_clear (accepts, '\n');
- if (dfa->syntax & RE_DOT_NOT_NULL)
- bitset_clear (accepts, '\0');
- }
-#endif
- else
- continue;
-
- /* Check the `accepts' and sift the characters which are not
- match it the context. */
- if (constraint)
- {
- if (constraint & NEXT_NEWLINE_CONSTRAINT)
- {
- bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR);
- bitset_empty (accepts);
- if (accepts_newline)
- bitset_set (accepts, NEWLINE_CHAR);
- else
- continue;
- }
- if (constraint & NEXT_ENDBUF_CONSTRAINT)
- {
- bitset_empty (accepts);
- continue;
- }
-
- if (constraint & NEXT_WORD_CONSTRAINT)
- {
- bitset_word_t any_set = 0;
- if (type == CHARACTER && !node->word_char)
- {
- bitset_empty (accepts);
- continue;
- }
-#ifdef RE_ENABLE_I18N
- if (dfa->mb_cur_max > 1)
- for (j = 0; j < BITSET_WORDS; ++j)
- any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));
- else
-#endif
- for (j = 0; j < BITSET_WORDS; ++j)
- any_set |= (accepts[j] &= dfa->word_char[j]);
- if (!any_set)
- continue;
- }
- if (constraint & NEXT_NOTWORD_CONSTRAINT)
- {
- bitset_word_t any_set = 0;
- if (type == CHARACTER && node->word_char)
- {
- bitset_empty (accepts);
- continue;
- }
-#ifdef RE_ENABLE_I18N
- if (dfa->mb_cur_max > 1)
- for (j = 0; j < BITSET_WORDS; ++j)
- any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));
- else
-#endif
- for (j = 0; j < BITSET_WORDS; ++j)
- any_set |= (accepts[j] &= ~dfa->word_char[j]);
- if (!any_set)
- continue;
- }
- }
-
- /* Then divide `accepts' into DFA states, or create a new
- state. Above, we make sure that accepts is not empty. */
- for (j = 0; j < ndests; ++j)
- {
- bitset_t intersec; /* Intersection sets, see below. */
- bitset_t remains;
- /* Flags, see below. */
- bitset_word_t has_intersec, not_subset, not_consumed;
-
- /* Optimization, skip if this state doesn't accept the character. */
- if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c))
- continue;
-
- /* Enumerate the intersection set of this state and `accepts'. */
- has_intersec = 0;
- for (k = 0; k < BITSET_WORDS; ++k)
- has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k];
- /* And skip if the intersection set is empty. */
- if (!has_intersec)
- continue;
-
- /* Then check if this state is a subset of `accepts'. */
- not_subset = not_consumed = 0;
- for (k = 0; k < BITSET_WORDS; ++k)
- {
- not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k];
- not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k];
- }
-
- /* If this state isn't a subset of `accepts', create a
- new group state, which has the `remains'. */
- if (not_subset)
- {
- bitset_copy (dests_ch[ndests], remains);
- bitset_copy (dests_ch[j], intersec);
- err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]);
- if (BE (err != REG_NOERROR, 0))
- goto error_return;
- ++ndests;
- }
-
- /* Put the position in the current group. */
- result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]);
- if (BE (result < 0, 0))
- goto error_return;
-
- /* If all characters are consumed, go to next node. */
- if (!not_consumed)
- break;
- }
- /* Some characters remain, create a new group. */
- if (j == ndests)
- {
- bitset_copy (dests_ch[ndests], accepts);
- err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]);
- if (BE (err != REG_NOERROR, 0))
- goto error_return;
- ++ndests;
- bitset_empty (accepts);
- }
- }
- return ndests;
- error_return:
- for (j = 0; j < ndests; ++j)
- re_node_set_free (dests_node + j);
- return -1;
-}
-
-#ifdef RE_ENABLE_I18N
-/* Check how many bytes the node `dfa->nodes[node_idx]' accepts.
- Return the number of the bytes the node accepts.
- STR_IDX is the current index of the input string.
-
- This function handles the nodes which can accept one character, or
- one collating element like '.', '[a-z]', opposite to the other nodes
- can only accept one byte. */
-
-static int
-internal_function
-check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
- const re_string_t *input, int str_idx)
-{
- const re_token_t *node = dfa->nodes + node_idx;
- int char_len, elem_len;
- int i;
-
- if (BE (node->type == OP_UTF8_PERIOD, 0))
- {
- unsigned char c = re_string_byte_at (input, str_idx), d;
- if (BE (c < 0xc2, 1))
- return 0;
-
- if (str_idx + 2 > input->len)
- return 0;
-
- d = re_string_byte_at (input, str_idx + 1);
- if (c < 0xe0)
- return (d < 0x80 || d > 0xbf) ? 0 : 2;
- else if (c < 0xf0)
- {
- char_len = 3;
- if (c == 0xe0 && d < 0xa0)
- return 0;
- }
- else if (c < 0xf8)
- {
- char_len = 4;
- if (c == 0xf0 && d < 0x90)
- return 0;
- }
- else if (c < 0xfc)
- {
- char_len = 5;
- if (c == 0xf8 && d < 0x88)
- return 0;
- }
- else if (c < 0xfe)
- {
- char_len = 6;
- if (c == 0xfc && d < 0x84)
- return 0;
- }
- else
- return 0;
-
- if (str_idx + char_len > input->len)
- return 0;
-
- for (i = 1; i < char_len; ++i)
- {
- d = re_string_byte_at (input, str_idx + i);
- if (d < 0x80 || d > 0xbf)
- return 0;
- }
- return char_len;
- }
-
- char_len = re_string_char_size_at (input, str_idx);
- if (node->type == OP_PERIOD)
- {
- if (char_len <= 1)
- return 0;
- /* FIXME: I don't think this if is needed, as both '\n'
- and '\0' are char_len == 1. */
- /* '.' accepts any one character except the following two cases. */
- if ((!(dfa->syntax & RE_DOT_NEWLINE) &&
- re_string_byte_at (input, str_idx) == '\n') ||
- ((dfa->syntax & RE_DOT_NOT_NULL) &&
- re_string_byte_at (input, str_idx) == '\0'))
- return 0;
- return char_len;
- }
-
- elem_len = re_string_elem_size_at (input, str_idx);
- if ((elem_len <= 1 && char_len <= 1) || char_len == 0)
- return 0;
-
- if (node->type == COMPLEX_BRACKET)
- {
- const re_charset_t *cset = node->opr.mbcset;
-# ifdef _LIBC
- const unsigned char *pin
- = ((const unsigned char *) re_string_get_buffer (input) + str_idx);
- int j;
- uint32_t nrules;
-# endif /* _LIBC */
- int match_len = 0;
- wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
- ? re_string_wchar_at (input, str_idx) : 0);
-
- /* match with multibyte character? */
- for (i = 0; i < cset->nmbchars; ++i)
- if (wc == cset->mbchars[i])
- {
- match_len = char_len;
- goto check_node_accept_bytes_match;
- }
- /* match with character_class? */
- for (i = 0; i < cset->nchar_classes; ++i)
- {
- wctype_t wt = cset->char_classes[i];
- if (__iswctype (wc, wt))
- {
- match_len = char_len;
- goto check_node_accept_bytes_match;
- }
- }
-
-# ifdef _LIBC
- nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
- if (nrules != 0)
- {
- unsigned int in_collseq = 0;
- const int32_t *table, *indirect;
- const unsigned char *weights, *extra;
- const char *collseqwc;
- /* This #include defines a local function! */
-# include <locale/weight.h>
-
- /* match with collating_symbol? */
- if (cset->ncoll_syms)
- extra = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
- for (i = 0; i < cset->ncoll_syms; ++i)
- {
- const unsigned char *coll_sym = extra + cset->coll_syms[i];
- /* Compare the length of input collating element and
- the length of current collating element. */
- if (*coll_sym != elem_len)
- continue;
- /* Compare each bytes. */
- for (j = 0; j < *coll_sym; j++)
- if (pin[j] != coll_sym[1 + j])
- break;
- if (j == *coll_sym)
- {
- /* Match if every bytes is equal. */
- match_len = j;
- goto check_node_accept_bytes_match;
- }
- }
-
- if (cset->nranges)
- {
- if (elem_len <= char_len)
- {
- collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
- in_collseq = __collseq_table_lookup (collseqwc, wc);
- }
- else
- in_collseq = find_collation_sequence_value (pin, elem_len);
- }
- /* match with range expression? */
- for (i = 0; i < cset->nranges; ++i)
- if (cset->range_starts[i] <= in_collseq
- && in_collseq <= cset->range_ends[i])
- {
- match_len = elem_len;
- goto check_node_accept_bytes_match;
- }
-
- /* match with equivalence_class? */
- if (cset->nequiv_classes)
- {
- const unsigned char *cp = pin;
- table = (const int32_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
- weights = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
- extra = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
- indirect = (const int32_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
- int32_t idx = findidx (&cp);
- if (idx > 0)
- for (i = 0; i < cset->nequiv_classes; ++i)
- {
- int32_t equiv_class_idx = cset->equiv_classes[i];
- size_t weight_len = weights[idx & 0xffffff];
- if (weight_len == weights[equiv_class_idx & 0xffffff]
- && (idx >> 24) == (equiv_class_idx >> 24))
- {
- int cnt = 0;
-
- idx &= 0xffffff;
- equiv_class_idx &= 0xffffff;
-
- while (cnt <= weight_len
- && (weights[equiv_class_idx + 1 + cnt]
- == weights[idx + 1 + cnt]))
- ++cnt;
- if (cnt > weight_len)
- {
- match_len = elem_len;
- goto check_node_accept_bytes_match;
- }
- }
- }
- }
- }
- else
-# endif /* _LIBC */
- {
- /* match with range expression? */
-#if __GNUC__ >= 2
- wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};
-#else
- wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
- cmp_buf[2] = wc;
-#endif
- for (i = 0; i < cset->nranges; ++i)
- {
- cmp_buf[0] = cset->range_starts[i];
- cmp_buf[4] = cset->range_ends[i];
- if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
- && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
- {
- match_len = char_len;
- goto check_node_accept_bytes_match;
- }
- }
- }
- check_node_accept_bytes_match:
- if (!cset->non_match)
- return match_len;
- else
- {
- if (match_len > 0)
- return 0;
- else
- return (elem_len > char_len) ? elem_len : char_len;
- }
- }
- return 0;
-}
-
-# ifdef _LIBC
-static unsigned int
-internal_function
-find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
-{
- uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
- if (nrules == 0)
- {
- if (mbs_len == 1)
- {
- /* No valid character. Match it as a single byte character. */
- const unsigned char *collseq = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
- return collseq[mbs[0]];
- }
- return UINT_MAX;
- }
- else
- {
- int32_t idx;
- const unsigned char *extra = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
- int32_t extrasize = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra;
-
- for (idx = 0; idx < extrasize;)
- {
- int mbs_cnt, found = 0;
- int32_t elem_mbs_len;
- /* Skip the name of collating element name. */
- idx = idx + extra[idx] + 1;
- elem_mbs_len = extra[idx++];
- if (mbs_len == elem_mbs_len)
- {
- for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt)
- if (extra[idx + mbs_cnt] != mbs[mbs_cnt])
- break;
- if (mbs_cnt == elem_mbs_len)
- /* Found the entry. */
- found = 1;
- }
- /* Skip the byte sequence of the collating element. */
- idx += elem_mbs_len;
- /* Adjust for the alignment. */
- idx = (idx + 3) & ~3;
- /* Skip the collation sequence value. */
- idx += sizeof (uint32_t);
- /* Skip the wide char sequence of the collating element. */
- idx = idx + sizeof (uint32_t) * (extra[idx] + 1);
- /* If we found the entry, return the sequence value. */
- if (found)
- return *(uint32_t *) (extra + idx);
- /* Skip the collation sequence value. */
- idx += sizeof (uint32_t);
- }
- return UINT_MAX;
- }
-}
-# endif /* _LIBC */
-#endif /* RE_ENABLE_I18N */
-
-/* Check whether the node accepts the byte which is IDX-th
- byte of the INPUT. */
-
-static int
-internal_function
-check_node_accept (const re_match_context_t *mctx, const re_token_t *node,
- int idx)
-{
- unsigned char ch;
- ch = re_string_byte_at (&mctx->input, idx);
- switch (node->type)
- {
- case CHARACTER:
- if (node->opr.c != ch)
- return 0;
- break;
-
- case SIMPLE_BRACKET:
- if (!bitset_contain (node->opr.sbcset, ch))
- return 0;
- break;
-
-#ifdef RE_ENABLE_I18N
- case OP_UTF8_PERIOD:
- if (ch >= 0x80)
- return 0;
- /* FALLTHROUGH */
-#endif
- case OP_PERIOD:
- if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE))
- || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL)))
- return 0;
- break;
-
- default:
- return 0;
- }
-
- if (node->constraint)
- {
- /* The node has constraints. Check whether the current context
- satisfies the constraints. */
- unsigned int context = re_string_context_at (&mctx->input, idx,
- mctx->eflags);
- if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
- return 0;
- }
-
- return 1;
-}
-
-/* Extend the buffers, if the buffers have run out. */
-
-static reg_errcode_t
-internal_function
-extend_buffers (re_match_context_t *mctx)
-{
- reg_errcode_t ret;
- re_string_t *pstr = &mctx->input;
-
- /* Double the lengthes of the buffers. */
- ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
-
- if (mctx->state_log != NULL)
- {
- /* And double the length of state_log. */
- /* XXX We have no indication of the size of this buffer. If this
- allocation fail we have no indication that the state_log array
- does not have the right size. */
- re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *,
- pstr->bufs_len + 1);
- if (BE (new_array == NULL, 0))
- return REG_ESPACE;
- mctx->state_log = new_array;
- }
-
- /* Then reconstruct the buffers. */
- if (pstr->icase)
- {
-#ifdef RE_ENABLE_I18N
- if (pstr->mb_cur_max > 1)
- {
- ret = build_wcs_upper_buffer (pstr);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
- }
- else
-#endif /* RE_ENABLE_I18N */
- build_upper_buffer (pstr);
- }
- else
- {
-#ifdef RE_ENABLE_I18N
- if (pstr->mb_cur_max > 1)
- build_wcs_buffer (pstr);
- else
-#endif /* RE_ENABLE_I18N */
- {
- if (pstr->trans != NULL)
- re_string_translate_buffer (pstr);
- }
- }
- return REG_NOERROR;
-}
-
-
-/* Functions for matching context. */
-
-/* Initialize MCTX. */
-
-static reg_errcode_t
-internal_function
-match_ctx_init (re_match_context_t *mctx, int eflags, int n)
-{
- mctx->eflags = eflags;
- mctx->match_last = -1;
- if (n > 0)
- {
- mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n);
- mctx->sub_tops = re_malloc (re_sub_match_top_t *, n);
- if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0))
- return REG_ESPACE;
- }
- /* Already zero-ed by the caller.
- else
- mctx->bkref_ents = NULL;
- mctx->nbkref_ents = 0;
- mctx->nsub_tops = 0; */
- mctx->abkref_ents = n;
- mctx->max_mb_elem_len = 1;
- mctx->asub_tops = n;
- return REG_NOERROR;
-}
-
-/* Clean the entries which depend on the current input in MCTX.
- This function must be invoked when the matcher changes the start index
- of the input, or changes the input string. */
-
-static void
-internal_function
-match_ctx_clean (re_match_context_t *mctx)
-{
- int st_idx;
- for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx)
- {
- int sl_idx;
- re_sub_match_top_t *top = mctx->sub_tops[st_idx];
- for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx)
- {
- re_sub_match_last_t *last = top->lasts[sl_idx];
- re_free (last->path.array);
- re_free (last);
- }
- re_free (top->lasts);
- if (top->path)
- {
- re_free (top->path->array);
- re_free (top->path);
- }
- free (top);
- }
-
- mctx->nsub_tops = 0;
- mctx->nbkref_ents = 0;
-}
-
-/* Free all the memory associated with MCTX. */
-
-static void
-internal_function
-match_ctx_free (re_match_context_t *mctx)
-{
- /* First, free all the memory associated with MCTX->SUB_TOPS. */
- match_ctx_clean (mctx);
- re_free (mctx->sub_tops);
- re_free (mctx->bkref_ents);
-}
-
-/* Add a new backreference entry to MCTX.
- Note that we assume that caller never call this function with duplicate
- entry, and call with STR_IDX which isn't smaller than any existing entry.
-*/
-
-static reg_errcode_t
-internal_function
-match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from,
- int to)
-{
- if (mctx->nbkref_ents >= mctx->abkref_ents)
- {
- struct re_backref_cache_entry* new_entry;
- new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry,
- mctx->abkref_ents * 2);
- if (BE (new_entry == NULL, 0))
- {
- re_free (mctx->bkref_ents);
- return REG_ESPACE;
- }
- mctx->bkref_ents = new_entry;
- memset (mctx->bkref_ents + mctx->nbkref_ents, '\0',
- sizeof (struct re_backref_cache_entry) * mctx->abkref_ents);
- mctx->abkref_ents *= 2;
- }
- if (mctx->nbkref_ents > 0
- && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx)
- mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1;
-
- mctx->bkref_ents[mctx->nbkref_ents].node = node;
- mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx;
- mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from;
- mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to;
-
- /* This is a cache that saves negative results of check_dst_limits_calc_pos.
- If bit N is clear, means that this entry won't epsilon-transition to
- an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If
- it is set, check_dst_limits_calc_pos_1 will recurse and try to find one
- such node.
-
- A backreference does not epsilon-transition unless it is empty, so set
- to all zeros if FROM != TO. */
- mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map
- = (from == to ? ~0 : 0);
-
- mctx->bkref_ents[mctx->nbkref_ents++].more = 0;
- if (mctx->max_mb_elem_len < to - from)
- mctx->max_mb_elem_len = to - from;
- return REG_NOERROR;
-}
-
-/* Search for the first entry which has the same str_idx, or -1 if none is
- found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */
-
-static int
-internal_function
-search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
-{
- int left, right, mid, last;
- last = right = mctx->nbkref_ents;
- for (left = 0; left < right;)
- {
- mid = (left + right) / 2;
- if (mctx->bkref_ents[mid].str_idx < str_idx)
- left = mid + 1;
- else
- right = mid;
- }
- if (left < last && mctx->bkref_ents[left].str_idx == str_idx)
- return left;
- else
- return -1;
-}
-
-/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches
- at STR_IDX. */
-
-static reg_errcode_t
-internal_function
-match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx)
-{
-#ifdef DEBUG
- assert (mctx->sub_tops != NULL);
- assert (mctx->asub_tops > 0);
-#endif
- if (BE (mctx->nsub_tops == mctx->asub_tops, 0))
- {
- int new_asub_tops = mctx->asub_tops * 2;
- re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops,
- re_sub_match_top_t *,
- new_asub_tops);
- if (BE (new_array == NULL, 0))
- return REG_ESPACE;
- mctx->sub_tops = new_array;
- mctx->asub_tops = new_asub_tops;
- }
- mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t));
- if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0))
- return REG_ESPACE;
- mctx->sub_tops[mctx->nsub_tops]->node = node;
- mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx;
- return REG_NOERROR;
-}
-
-/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches
- at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */
-
-static re_sub_match_last_t *
-internal_function
-match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx)
-{
- re_sub_match_last_t *new_entry;
- if (BE (subtop->nlasts == subtop->alasts, 0))
- {
- int new_alasts = 2 * subtop->alasts + 1;
- re_sub_match_last_t **new_array = re_realloc (subtop->lasts,
- re_sub_match_last_t *,
- new_alasts);
- if (BE (new_array == NULL, 0))
- return NULL;
- subtop->lasts = new_array;
- subtop->alasts = new_alasts;
- }
- new_entry = calloc (1, sizeof (re_sub_match_last_t));
- if (BE (new_entry != NULL, 1))
- {
- subtop->lasts[subtop->nlasts] = new_entry;
- new_entry->node = node;
- new_entry->str_idx = str_idx;
- ++subtop->nlasts;
- }
- return new_entry;
-}
-
-static void
-internal_function
-sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
- re_dfastate_t **limited_sts, int last_node, int last_str_idx)
-{
- sctx->sifted_states = sifted_sts;
- sctx->limited_states = limited_sts;
- sctx->last_node = last_node;
- sctx->last_str_idx = last_str_idx;
- re_node_set_init_empty (&sctx->limits);
-}
diff --git a/xbmc/lib/libshout/libshout/stdafx.cpp b/xbmc/lib/libshout/libshout/stdafx.cpp
deleted file mode 100644
index 65ecf95a51..0000000000
--- a/xbmc/lib/libshout/libshout/stdafx.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-// stdafx.cpp : Quelltextdatei, die nur die Standard-Includes einbindet
-// libshout.pch ist der vorcompilierte Header
-// stdafx.obj enthält die vorcompilierte Typinformation
-
-#include "stdafx.h"
-
-// TODO: Verweisen Sie auf zusätzliche Header, die in STDAFX.H
-// und nicht in dieser Datei erforderlich sind.
diff --git a/xbmc/lib/libshout/libshout/stdafx.h b/xbmc/lib/libshout/libshout/stdafx.h
deleted file mode 100644
index b040358515..0000000000
--- a/xbmc/lib/libshout/libshout/stdafx.h
+++ /dev/null
@@ -1,11 +0,0 @@
-// stdafx.h : Includedatei für Standardsystem-Includedateien,
-// oder projektspezifische Includedateien, die häufig benutzt, aber
-// in unregelmäßigen Abständen geändert werden.
-//
-
-#pragma once
-
-
-#define WIN32_LEAN_AND_MEAN // Selten verwendete Teile der Windows-Header nicht einbinden
-
-// TODO: Verweisen Sie hier auf zusätzliche Header, die Ihr Programm erfordert
diff --git a/xbmc/lib/libshout/list.h b/xbmc/lib/libshout/list.h
deleted file mode 100644
index f8ab242a5d..0000000000
--- a/xbmc/lib/libshout/list.h
+++ /dev/null
@@ -1,281 +0,0 @@
-#ifndef __LIST_H__
-#define __LIST_H__
-
-/* GCS: I ripped this off from the linux kernel. Minor modifications. */
-
-#if defined (WIN32)
-#define inline __inline
-#endif
-
-/* #define prefetch(a) (a) */
-#define prefetch(a) 0
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
- struct list_head *next, *prev;
-};
-typedef struct list_head LIST;
-
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
-
-#define INIT_LIST_HEAD(ptr) do { \
- (ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head *prev, struct list_head *next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- entry->next = (void *) 0;
- entry->prev = (void *) 0;
-}
-
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
- */
-static inline void list_del_init(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- INIT_LIST_HEAD(entry);
-}
-
-/**
- * list_move - delete from one list and add as another's head
- * @list: the entry to move
- * @head: the head that will precede our entry
- */
-static inline void list_move(struct list_head *list, struct list_head *head)
-{
- __list_del(list->prev, list->next);
- list_add(list, head);
-}
-
-/**
- * list_move_tail - delete from one list and add as another's tail
- * @list: the entry to move
- * @head: the head that will follow our entry
- */
-static inline void list_move_tail(struct list_head *list,
- struct list_head *head)
-{
- __list_del(list->prev, list->next);
- list_add_tail(list, head);
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(struct list_head *head)
-{
- return head->next == head;
-}
-
-static inline void __list_splice(struct list_head *list,
- struct list_head *head)
-{
- struct list_head *first = list->next;
- struct list_head *last = list->prev;
- struct list_head *at = head->next;
-
- first->prev = head;
- head->next = first;
-
- last->next = at;
- at->prev = last;
-}
-
-/**
- * list_splice - join two lists
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-static inline void list_splice(struct list_head *list, struct list_head *head)
-{
- if (!list_empty(list))
- __list_splice(list, head);
-}
-
-/**
- * list_splice_init - join two lists and reinitialise the emptied list.
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- *
- * The list at @list is reinitialised
- */
-static inline void list_splice_init(struct list_head *list,
- struct list_head *head)
-{
- if (!list_empty(list)) {
- __list_splice(list, head);
- INIT_LIST_HEAD(list);
- }
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
- ((type *)((char *)(ptr)-(uintptr_t)(&((type *)0)->member)))
-
-/**
- * list_for_each - iterate over a list
- * @pos: the &struct list_head to use as a loop counter.
- * @head: the head for your list.
- */
-#define list_for_each(pos, head) \
- for (pos = (head)->next, prefetch(pos->next); pos != (head); \
- pos = pos->next, prefetch(pos->next))
-/**
- * list_for_each_prev - iterate over a list backwards
- * @pos: the &struct list_head to use as a loop counter.
- * @head: the head for your list.
- */
-#define list_for_each_prev(pos, head) \
- for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
- pos = pos->prev, prefetch(pos->prev))
-
-/**
- * list_for_each_safe - iterate over a list safe against removal of list entry
- * @pos: the &struct list_head to use as a loop counter.
- * @n: another &struct list_head to use as temporary storage
- * @head: the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
- for (pos = (head)->next, n = pos->next; pos != (head); \
- pos = n, n = pos->next)
-
-/**
- * list_for_each_entry - iterate over list of given type
- * @pos: the type * to use as a loop counter.
- * @type: the type of the struct this is embedded in.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#if defined (commentout)
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- prefetch(pos->member.next); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member), \
- prefetch(pos->member.next))
-#endif
-#define list_for_each_entry(pos, type, head, member) \
- for (pos = list_entry((head)->next, type, member), \
- prefetch(pos->member.next); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, type, member), \
- prefetch(pos->member.next))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos: the type * to use as a loop counter.
- * @type: the type of the struct this is embedded in.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#if defined (commentout)
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
-#endif
-#define list_for_each_entry_safe(pos, type, n, head, member) \
- for (pos = list_entry((head)->next, type, member), \
- n = list_entry(pos->member.next, type, member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, type, member))
-
-/**
- * list_for_each_entry_continue - iterate over list of given type
- * continuing after existing point
- * @pos: the type * to use as a loop counter.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry_continue(pos, head, member) \
- for (pos = list_entry(pos->member.next, typeof(*pos), member), \
- prefetch(pos->member.next); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member), \
- prefetch(pos->member.next))
-
-#endif
diff --git a/xbmc/lib/libshout/mchar.c b/xbmc/lib/libshout/mchar.c
deleted file mode 100644
index c0a41eea78..0000000000
--- a/xbmc/lib/libshout/mchar.c
+++ /dev/null
@@ -1,601 +0,0 @@
-/* mchar.c
- * Codeset and wide character processing
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * REFS:
- * http://mail.nl.linux.org/linux-utf8/2001-04/msg00083.html
- * http://www.cl.cam.ac.uk/~mgk25/unicode.html
- * http://mail.nl.linux.org/linux-utf8/2001-06/msg00020.html
- * http://mail.nl.linux.org/linux-utf8/2001-04/msg00254.html
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include "srconfig.h"
-#if defined HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if defined HAVE_WCHAR_SUPPORT
-#if defined HAVE_WCHAR_H
-#include <wchar.h>
-#endif
-#if defined HAVE_WCTYPE_H
-#include <wctype.h>
-#endif
-#if defined HAVE_ICONV
-#include <iconv.h>
-#endif
-#endif
-#if defined HAVE_LOCALE_CHARSET
-#include <localcharset.h>
-#elif defined HAVE_LANGINFO_CODESET
-#include <langinfo.h>
-#endif
-#include <locale.h>
-#include <time.h>
-#include <errno.h>
-#include "debug.h"
-#include "srtypes.h"
-#include "mchar.h"
-
-#if WIN32
- #define ICONV_WCHAR "UCS-2-INTERNAL"
- #define vsnprintf _vsnprintf
- #define vswprintf _vsnwprintf
-#else
- #define ICONV_WCHAR "WCHAR_T"
- /* This prototype is missing in some systems */
- int vswprintf (wchar_t * ws, size_t n, const wchar_t * format, va_list arg);
-#endif
-
-
-/*****************************************************************************
- * Public functions
- *****************************************************************************/
-char *left_str(char *str, int len);
-char *subnstr_until(const char *str, char *until, char *newstr, int maxlen);
-// char *strip_invalid_chars(char *str);
-char *format_byte_size(char *str, long size);
-void trim(char *str);
-
-/*****************************************************************************
- * Private global variables
- *****************************************************************************/
-const char* m_codeset_locale;
-const char* m_codeset_filesys;
-const char* m_codeset_id3;
-const char* m_codeset_metadata;
-const char* m_codeset_relay;
-
-/*****************************************************************************
- * These functions are NOT mchar related
- *****************************************************************************/
-char*
-subnstr_until(const char *str, char *until, char *newstr, int maxlen)
-{
- const char *p = str;
- int len = 0;
-
- for(len = 0; strncmp(p, until, strlen(until)) != 0 && len < maxlen-1; p++)
- {
- newstr[len] = *p;
- len++;
- }
- newstr[len] = '\0';
-
- return newstr;
-}
-
-char *left_str(char *str, int len)
-{
- int slen = strlen(str);
-
- if (slen <= len)
- return str;
-
- str[len] = '\0';
- return str;
-}
-
-char *format_byte_size(char *str, long size)
-{
- const long ONE_K = 1024;
- const long ONE_M = ONE_K*ONE_K;
-
- if (size < ONE_K)
- sprintf(str, "%ldb", size);
- else if (size < ONE_M)
- sprintf(str, "%ldkb", size/ONE_K);
- else
- sprintf(str, "%.2fM", (float)size/(ONE_M));
-
- return str;
-}
-
-void trim(char *str)
-{
- int size = strlen(str)-1;
- while(str[size] == 13 || str[size] == 10 || str[size] == ' ')
- {
- str[size] = '\0';
- size--;
- }
- size = strlen(str);
- while(str[0] == ' ')
- {
- size--;
- memmove(str, str+1, size);
- }
- str[size] = '\0';
-}
-
-/* This is a little different from standard strncpy, because:
- 1) behavior is known when dst & src overlap
- 2) only copy n-1 characters max
- 3) then add the null char
-*/
-void
-sr_strncpy (char* dst, char* src, int n)
-{
- int i = 0;
- for (i = 0; i < n-1; i++) {
- if (!(dst[i] = src[i])) {
- return;
- }
- }
- dst[i] = 0;
-}
-
-/*****************************************************************************
- * These functions ARE mchar related
- *****************************************************************************/
-#if HAVE_WCHAR_SUPPORT
-# if HAVE_ICONV
-int
-iconv_convert_string (char* dst, int dst_len, char* src, int src_len,
- const char* dst_codeset, const char* src_codeset)
-{
- size_t rc;
- iconv_t ict;
- size_t src_left, dst_left;
- char *src_ptr, *dst_ptr;
-
- /* First try to convert using iconv. */
- ict = iconv_open (dst_codeset, src_codeset);
- if (ict == (iconv_t)(-1)) {
- printf ("Error on iconv_open(\"%s\",\"%s\")\n",
- dst_codeset, src_codeset);
- perror ("Error string is: ");
- return -1;
- }
- src_left = src_len;
- dst_left = dst_len;
- src_ptr = src;
- dst_ptr = dst;
- rc = iconv (ict,&src_ptr,&src_left,&dst_ptr,&dst_left);
- if (rc == -1) {
- if (errno == EINVAL) {
- /* EINVAL means the last character was truncated
- Declare success and try to continue... */
- debug_printf ("ICONV: EINVAL\n");
- printf ("ICONV: EINVAL\n\n");
- } else if (errno == E2BIG) {
- /* E2BIG means the output buffer was too small. This can
- happen, for example, when converting for id3v1 tags */
- debug_printf ("ICONV: E2BIG\n");
- } else if (errno == EILSEQ) {
- /* Here I should advance cptr and try to continue, right? */
- debug_printf ("ICONV: EILSEQ\n");
- printf ("ICONV: EILSEQ\n\n");
- } else {
- debug_printf ("ICONV: ERROR %d\n", errno);
- printf ("ICONV:ERROR %d\n\n", errno);
- }
- }
- iconv_close (ict);
- return dst_len - dst_left;
-}
-# endif
-
-/* Return value is the number of char occupied by the converted string,
- not including the null character. */
-int
-string_from_wstring (char* c, int clen, wchar_t* w, const char* codeset)
-{
- int rc;
-
-# if HAVE_ICONV
- int wlen, clen_out;
- wlen = wcslen (w) * sizeof(wchar_t);
- debug_printf ("ICONV: c <- w (len=%d,tgt=%s)\n", wlen, codeset);
- rc = iconv_convert_string (c, clen, (char*) w, wlen, codeset, ICONV_WCHAR);
- debug_printf ("rc = %d\n", rc);
- clen_out = rc;
- if (clen_out == clen) clen_out--;
- c[clen_out] = 0;
- return clen_out;
-# endif
-
- rc = wcstombs(c,w,clen);
- if (rc == -1) {
- /* Do something smart here */
- }
- return rc;
-}
-
-/* Return value is the number of wchar_t occupied by the converted string,
- not including the null character. */
-int
-wstring_from_string (wchar_t* w, int wlen, char* c, const char* codeset)
-{
- int rc;
-
-# if HAVE_ICONV
- int clen, wlen_out;
- clen = strlen (c); // <----<<<< GCS FIX. String is arbitrarily encoded.
- debug_printf ("ICONV: w <- c (%s)\n", c);
- rc = iconv_convert_string ((char*) w, wlen * sizeof(wchar_t),
- c, clen, ICONV_WCHAR, codeset);
- debug_printf ("rc = %d\n", rc);
- // debug_mprintf (m("val = ") mS m("\n"), w);
- wlen_out = rc / sizeof(wchar_t);
- if (wlen_out == wlen) wlen_out--;
- w[wlen_out] = 0;
- return wlen_out;
-# endif
-
- /* Currently this never happens, because now iconv is required. */
- rc = mbstowcs(w,c,wlen);
- if (rc == -1) {
- /* Do something smart here */
- }
- return 0;
-}
-
-int
-wchar_from_char (char c, const char* codeset)
-{
- wchar_t w[1];
- int rc;
-
-# if HAVE_ICONV
- rc = iconv_convert_string ((char*) w, sizeof(wchar_t), &c, 1,
- ICONV_WCHAR, codeset);
- if (rc == 1) return w[0];
- /* Otherwise, fall through to mbstowcs method */
-# endif
-
- /* Do something smart here */
- return 0;
-}
-#endif /* HAVE_WCHAR_SUPPORT */
-
-/* Input value mlen is measured in mchar, not bytes.
- Return value is the number of mchar occupied by the converted string,
- not including the null character. */
-int
-mstring_from_string (mchar* m, int mlen, char* c, int codeset_type)
-{
- if (mlen < 0) return 0;
- *m = 0;
- if (!c) return 0;
-#if defined (HAVE_WCHAR_SUPPORT)
- switch (codeset_type) {
- case CODESET_UTF8:
- return wstring_from_string (m, mlen, c, "UTF-8");
- break;
- case CODESET_LOCALE:
- return wstring_from_string (m, mlen, c, m_codeset_locale);
- break;
- case CODESET_FILESYS:
- return wstring_from_string (m, mlen, c, m_codeset_filesys);
- break;
- case CODESET_ID3:
- return wstring_from_string (m, mlen, c, m_codeset_id3);
- break;
- case CODESET_METADATA:
- return wstring_from_string (m, mlen, c, m_codeset_metadata);
- break;
- case CODESET_RELAY:
- return wstring_from_string (m, mlen, c, m_codeset_relay);
- break;
- default:
- printf ("Program error. Bad codeset m->c (%d)\n", codeset_type);
- exit (-1);
- }
-#else
- sr_strncpy (m, c, mlen);
- return strlen (m);
-#endif
-}
-
-/* Return value is the number of char occupied by the converted string,
- not including the null character. */
-int
-string_from_mstring (char* c, int clen, mchar* m, int codeset_type)
-{
- if (clen < 0) return 0;
- *c = 0;
- if (!m) return 0;
-#if defined (HAVE_WCHAR_SUPPORT)
- switch (codeset_type) {
- case CODESET_UTF8:
- return string_from_wstring (c, clen, m, "UTF-8");
- break;
- case CODESET_LOCALE:
- return string_from_wstring (c, clen, m, m_codeset_locale);
- break;
- case CODESET_FILESYS:
- return string_from_wstring (c, clen, m, m_codeset_filesys);
- break;
- case CODESET_ID3:
- return string_from_wstring (c, clen, m, m_codeset_id3);
- break;
- case CODESET_METADATA:
- return string_from_wstring (c, clen, m, m_codeset_metadata);
- break;
- case CODESET_RELAY:
- return string_from_wstring (c, clen, m, m_codeset_relay);
- break;
- default:
- printf ("Program error. Bad codeset c->m.\n");
- exit (-1);
- }
-#else
- sr_strncpy (c, m, clen);
- return strlen (c);
-#endif
-}
-
-mchar
-mchar_from_char (char c, int codeset_type)
-{
-#if defined (HAVE_WCHAR_SUPPORT)
- switch (codeset_type) {
- case CODESET_UTF8:
- return wchar_from_char (c, "UTF-8");
- break;
- case CODESET_LOCALE:
- return wchar_from_char (c, m_codeset_locale);
- break;
- case CODESET_FILESYS:
- return wchar_from_char (c, m_codeset_filesys);
- break;
- case CODESET_ID3:
- return wchar_from_char (c, m_codeset_id3);
- break;
- case CODESET_METADATA:
- return wchar_from_char (c, m_codeset_metadata);
- break;
- case CODESET_RELAY:
- return wchar_from_char (c, m_codeset_relay);
- break;
- default:
- printf ("Program error. Bad codeset c->m.\n");
- exit (-1);
- }
-#else
- return c;
-#endif
-}
-
-const char*
-default_codeset (void)
-{
- const char* fromcode = 0;
-
-#if defined HAVE_LOCALE_CHARSET
- debug_printf ("Using locale_charset() to get system codeset.\n");
- fromcode = locale_charset ();
-#elif defined HAVE_LANGINFO_CODESET
- debug_printf ("Using nl_langinfo() to get system codeset.\n");
- fromcode = nl_langinfo (CODESET);
-#else
- debug_printf ("No way to get system codeset.\n");
-#endif
- if (!fromcode || !fromcode[0]) {
- debug_printf ("No default codeset, using ISO-8859-1.\n");
- fromcode = "ISO-8859-1";
- } else {
- debug_printf ("Found default codeset %s\n", fromcode);
- }
-
-#if defined (WIN32)
- {
- /* This is just for debugging */
- LCID lcid;
- lcid = GetSystemDefaultLCID ();
- debug_printf ("SystemDefaultLCID: %04x\n", lcid);
- lcid = GetUserDefaultLCID ();
- debug_printf ("UserDefaultLCID: %04x\n", lcid);
- }
-#endif
-
-#if defined HAVE_ICONV
- debug_printf ("Have iconv.\n");
-#else
- debug_printf ("No iconv.\n");
-#endif
-
- return fromcode;
-}
-
-void
-set_codesets_default (CODESET_OPTIONS* cs_opt)
-{
- const char* fromcode = 0;
- setlocale (LC_ALL, "");
- setlocale (LC_CTYPE, "");
- debug_printf ("LOCALE is %s\n",setlocale(LC_ALL,NULL));
-
- /* Set default codesets */
- fromcode = default_codeset ();
- if (fromcode) {
- strncpy (cs_opt->codeset_locale, fromcode, MAX_CODESET_STRING);
- strncpy (cs_opt->codeset_filesys, fromcode, MAX_CODESET_STRING);
- strncpy (cs_opt->codeset_id3, fromcode, MAX_CODESET_STRING);
- strncpy (cs_opt->codeset_metadata, fromcode, MAX_CODESET_STRING);
- strncpy (cs_opt->codeset_relay, fromcode, MAX_CODESET_STRING);
- }
-
- /* I could potentially add stuff like forcing filesys to be utf8
- (or whatever) for osx here */
-
-}
-
-/* This sets the global variables (ugh) */
-void
-register_codesets (CODESET_OPTIONS* cs_opt)
-{
- /* For ID3, force UCS-2, UCS-2LE, UCS-2BE, UTF-16LE, and UTF-16BE
- to be UTF-16. This way, we get the BOM like we need.
- This might change if we upgrade to id3v2.4, which allows
- UTF-8 and UTF-16 without BOM. */
- if (!strncmp (cs_opt->codeset_id3, "UCS-2", strlen("UCS-2")) ||
- !strncmp (cs_opt->codeset_id3, "UTF-16", strlen("UTF-16"))) {
- strcpy (cs_opt->codeset_id3, "UTF-16");
- }
-
- m_codeset_locale = cs_opt->codeset_locale;
- m_codeset_filesys = cs_opt->codeset_filesys;
- m_codeset_id3 = cs_opt->codeset_id3;
- m_codeset_metadata = cs_opt->codeset_metadata;
- m_codeset_relay = cs_opt->codeset_relay;
- debug_printf ("Locale codeset: %s\n", m_codeset_locale);
- debug_printf ("Filesys codeset: %s\n", m_codeset_filesys);
- debug_printf ("ID3 codeset: %s\n", m_codeset_id3);
- debug_printf ("Metadata codeset: %s\n", m_codeset_metadata);
- debug_printf ("Relay codeset: %s\n", m_codeset_relay);
-
-
-}
-
-/* This is used to set the codeset byte for id3v2 frames */
-int
-is_id3_unicode (void)
-{
-#if HAVE_WCHAR_SUPPORT
- if (!strcmp ("UTF-16", m_codeset_id3)) {
- return 1;
- }
-#endif
- return 0;
-}
-
-void
-mstrncpy (mchar* dst, mchar* src, int n)
-{
- int i = 0;
- for (i = 0; i < n-1; i++) {
- if (!(dst[i] = src[i])) {
- return;
- }
- }
- dst[i] = 0;
-}
-
-mchar*
-mstrdup (mchar* src)
-{
-#if defined HAVE_WCHAR_SUPPORT
- /* wstrdup/wcsdup is non-standard */
- mchar* new_string = (mchar*) malloc (sizeof(mchar)*(wcslen(src) + 1));
- wcscpy (new_string, src);
- return new_string;
-#else
- return strdup (src);
-#endif
-}
-
-mchar*
-mstrcpy (mchar* dest, const mchar* src)
-{
-#if defined HAVE_WCHAR_SUPPORT
- return wcscpy (dest, src);
-#else
- return strcpy (dest, src);
-#endif
-}
-
-size_t
-mstrlen (mchar* s)
-{
-#if defined HAVE_WCHAR_SUPPORT
- return wcslen (s);
-#else
- return strlen (s);
-#endif
-}
-
-/* GCS FIX: gcc can give a warning about vswprintf. This may require
- setting gcc -std=c99, or gcc -lang-c99 */
-int
-msnprintf (mchar* dest, size_t n, const mchar* fmt, ...)
-{
- int rc;
- va_list ap;
- va_start (ap, fmt);
-#if defined HAVE_WCHAR_SUPPORT
- rc = vswprintf (dest, n, fmt, ap);
- debug_printf ("vswprintf got %d\n", rc);
-#else
- rc = vsnprintf (dest, n, fmt, ap);
-#endif
- va_end (ap);
- return rc;
-}
-
-mchar*
-mstrchr (const mchar* ws, mchar wc)
-{
-#if defined HAVE_WCHAR_SUPPORT
- return wcschr (ws, wc);
-#else
- return strchr (ws, wc);
-#endif
-}
-
-mchar*
-mstrncat (mchar* ws1, const mchar* ws2, size_t n)
-{
-#if defined HAVE_WCHAR_SUPPORT
- return wcsncat (ws1, ws2, n);
-#else
- return strncat (ws1, ws2, n);
-#endif
-}
-
-int
-mstrcmp (const mchar* ws1, const mchar* ws2)
-{
-#if defined HAVE_WCHAR_SUPPORT
- return wcscmp (ws1, ws2);
-#else
- return strcmp (ws1, ws2);
-#endif
-}
-
-long int
-mtol (const mchar* string)
-{
-#if defined HAVE_WCHAR_SUPPORT
- return wcstol (string, 0, 0);
-#else
- return strtol (string, 0, 0);
-#endif
-}
diff --git a/xbmc/lib/libshout/mchar.h b/xbmc/lib/libshout/mchar.h
deleted file mode 100644
index e9b34a2307..0000000000
--- a/xbmc/lib/libshout/mchar.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef __MCHAR_H__
-#define __MCHAR_H__
-
-#include "srtypes.h"
-
-#if HAVE_WCHAR_SUPPORT
-#define m_(x) L##x
-#if defined (WIN32)
-#define m_S L"%s"
-#define m_C L"%c"
-#define m_s L"%S"
-#define m_c L"%C"
-#else
-#define m_S L"%ls"
-#define m_C L"%lc"
-#define m_s L"%s"
-#define m_c L"%c"
-#endif
-#else
-#define m_(x) x
-#define m_S "%s"
-#define m_C "%c"
-#define m_s "%s"
-#define m_c "%c"
-#endif
-
-char *subnstr_until(const char *str, char *until, char *newstr, int maxlen);
-char *left_str(char *str, int len);
-char *format_byte_size(char *str, long size);
-void trim(char *str);
-void sr_strncpy(char* dst, char* src, int n);
-
-//void initialize_default_locale (CODESET_OPTIONS* cs_opt);
-//void set_codeset (char* codeset_type, const char* codeset);
-void set_codesets_default (CODESET_OPTIONS* cs_opt);
-void register_codesets (CODESET_OPTIONS* cs_opt);
-
-int mstring_from_string (mchar* m, int mlen, char* c, int codeset_type);
-int string_from_mstring (char* c, int clen, mchar* m, int codeset_type);
-
-mchar* mstrdup (mchar* src);
-mchar* mstrcpy (mchar* dest, const mchar* src);
-int msnprintf (mchar* dest, size_t n, const mchar* fmt, ...);
-void mstrncpy (mchar* dst, mchar* src, int n);
-size_t mstrlen (mchar* s);
-mchar* mstrchr (const mchar* ws, mchar wc);
-mchar* mstrncat (mchar* ws1, const mchar* ws2, size_t n);
-int mstrcmp (const mchar* ws1, const mchar* ws2);
-long int mtol (const mchar* string);
-
-int is_id3_unicode (void);
-
-#endif /*__MCHAR_H__*/
diff --git a/xbmc/lib/libshout/mpeg.c b/xbmc/lib/libshout/mpeg.c
deleted file mode 100644
index 85107f1a8c..0000000000
--- a/xbmc/lib/libshout/mpeg.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* mpeg.c - jonclegg@yahoo.com
- * various ripped off mpeg stuff, mainly for finding the first good header in a mp3 chunk
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "mpeg.h"
-
-#define MPG_MD_MONO 3
-
-/**********************************************************************************
- * Public functions
- **********************************************************************************/
-error_code mpeg_find_first_header(const char* buffer, int size, int min_good_frames, int *frame_pos);
-error_code mpeg_find_last_header(const char *buffer, int size, int min_good_frames, int *frame_pos);
-
-/**********************************************************************************
- * Private functions
- **********************************************************************************/
-static int get_frame_size(mp3_header_t *mh);
-static BOOL get_header(unsigned char *buff, mp3_header_t *mh);
-static BOOL header_sane(mp3_header_t *mh);
-static BOOL sameHeader(mp3_header_t *mh1, mp3_header_t *mh2);
-static unsigned int decode_bitrate(mp3_header_t *mh);
-
-static unsigned int bitrates[3][3][15] =
-{
- {
- {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448},
- {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384},
- {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}
- },
- {
- {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256},
- {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
- {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}
- },
- {
- {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256},
- {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
- {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}
- }
-};
-
-static unsigned int s_freq_mult[3][4] =
-{
- {882, 960, 640, 0},
- {441, 480, 320, 0},
- {441, 480, 320, 0}
-}; // From FreeAmp Xing decoder
-
-/*
-static char *mode_names[5] = {"stereo", "j-stereo", "dual-ch", "single-ch", "multi-ch"};
-static char *layer_names[3] = {"I", "II", "III"};
-static char *version_names[3] = {"MPEG-1", "MPEG-2 LSF", "MPEG-2.5"};
-static char *version_nums[3] = {"1", "2", "2.5"};
-*/
-
-
-/*
- * Finds the first header good for min_good_frames and fills header_pos with the position
- */
-error_code mpeg_find_first_header(const char* pbuff, int size, int min_good_frames, int *header_pos)
-{
- int i, n;
- unsigned char *buff = (unsigned char*)pbuff;
- unsigned char *buff2;
- mp3_header_t mh1, mh2;
- int frame_size;
- int remaining;
-
- for(i = 0; i < size; i++, buff++)
- {
- if (*buff == 255)
- {
- get_header(buff, &mh1);
- if (!header_sane(&mh1))
- continue;
-
- frame_size = get_frame_size(&mh1);
- if (frame_size < 21)
- continue;
-
- buff2 = buff + frame_size;
- remaining = size - i - frame_size;
- for(n = 1; (n < min_good_frames) && (remaining >= 4); n++)
- {
- get_header(buff2, &mh2);
- if (!header_sane(&mh2)) break;
- if (!sameHeader(&mh1, &mh2)) break;
-
- remaining -= frame_size;
- buff2 += frame_size;
- }
- if (n == min_good_frames)
- {
- *header_pos = i;
- return SR_SUCCESS;
- }
- }
- }
-
- return SR_ERROR_CANT_FIND_MPEG_HEADER;
-}
-
-/*
- * Finds the last good frame within <buffer>, places that frame pos in <header_pos>
- */
-error_code mpeg_find_last_header(const char *buffer, int size, int min_good_frames, int *header_pos)
-{
- int frame_pos = 0;
- int cur = 0;
-
-
- // Keep getting frames till we run out of space
- while(mpeg_find_first_header(&buffer[cur], size-cur, min_good_frames, &frame_pos))
- cur += (frame_pos + 4);
-
- *header_pos = (cur-4);
- return SR_SUCCESS;
-}
-
-
-/*
- * Checks if the headers are the same
- */
-BOOL sameHeader(mp3_header_t *mh1, mp3_header_t *mh2)
-{
- if ((mh1->lay == mh2->lay) &&
- (mh1->version == mh2->version) &&
- (mh1->error_protection == mh2->error_protection) &&
- (mh1->bitrate_index == mh2->bitrate_index) &&
- (mh1->sampling_frequency == mh2->sampling_frequency) &&
- // (mh1->padding == mh2->padding) &&
- (mh1->extension == mh2->extension) &&
- (mh1->mode == mh2->mode) &&
- (mh1->mode_ext == mh2->mode_ext) &&
- (mh1->copyright == mh2->copyright) &&
- (mh1->original == mh2->original) &&
- (mh1->emphasis == mh2->emphasis) &&
- (mh1->stereo == mh2->stereo))
- return TRUE;
- else
- return FALSE;
-}
-
-/*
- * Calcualtes the frame size based of a mp3_header
- */
-int get_frame_size(mp3_header_t *mh)
-{
- long mult = 0;
-
- if (decode_bitrate(mh) == 0)
- return 0;
-
- if (mh->lay == 1)
- return (240 * (decode_bitrate(mh) /
- s_freq_mult[mh->version][mh->sampling_frequency])) * 4;
- else if (mh->lay == 2)
- mult = 2880;
- else if (mh->lay == 3)
- {
- if (mh->version == 0)
- mult = 2880;
- else if (mh->version == 1)
- mult = 1440;
- else if (mh->version == 2) // MPEG 2.5
- mult = 2880;
- }
-
- return mult * decode_bitrate(mh) /
- s_freq_mult[mh->version][mh->sampling_frequency] + mh->padding;
-}
-
-/*
- * Extracts the mp3 header from <buff>
- */
-BOOL get_header(unsigned char *buff, mp3_header_t *mh)
-{
- unsigned char *buffer;
- size_t temp;
-
-
- memset(mh, 0, sizeof(mh));
- buffer = buff;
- temp = ((buffer[0] << 4) & 0xFF0) | ((buffer[1] >> 4) & 0xE);
-
- if (temp != 0xFFE)
- {
- return FALSE;
- }
- else
- {
- switch ((buffer[1] >> 3 & 0x3))
- {
- case 3:
- mh->version = 0;
- break;
- case 2:
- mh->version = 1;
- break;
- case 0:
- mh->version = 2;
- break;
- default:
- return -1;
- break;
- }
- mh->lay = 4 - ((buffer[1] >> 1) & 0x3);
- mh->error_protection = !(buffer[1] & 0x1);
- mh->bitrate_index = (buffer[2] >> 4) & 0x0F;
- mh->sampling_frequency = (buffer[2] >> 2) & 0x3;
- mh->padding = (buffer[2] >> 1) & 0x01;
- mh->extension = buffer[2] & 0x01;
- mh->mode = (buffer[3] >> 6) & 0x3;
- mh->mode_ext = (buffer[3] >> 4) & 0x03;
- mh->copyright = (buffer[3] >> 3) & 0x01;
- mh->original = (buffer[3] >> 2) & 0x1;
- mh->emphasis = (buffer[3]) & 0x3;
- mh->stereo = (mh->mode == MPG_MD_MONO) ? 1 : 2;
-
- return TRUE;
- }
-}
-
-unsigned int decode_bitrate(mp3_header_t *mh)
-{
- return bitrates[mh->version][mh->lay-1][mh->bitrate_index];
-}
-
-/*
- * Checks if the header is even somewhat valid
- */
-BOOL header_sane(mp3_header_t *mh)
-{
- if ( ((mh->lay > 1) && (mh->lay < 4)) &&
- ((mh->bitrate_index > 0) && (mh->bitrate_index < 15)) &&
- ((mh->sampling_frequency >= 0) && (mh->sampling_frequency < 3)) &&
- ((mh->version >= 0) && (mh->version < 3)))
- return TRUE;
-
- return FALSE;
-}
-
diff --git a/xbmc/lib/libshout/mpeg.h b/xbmc/lib/libshout/mpeg.h
deleted file mode 100644
index c57cebceaf..0000000000
--- a/xbmc/lib/libshout/mpeg.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __MPEG_H__
-#define __MPEG_H__
-
-#include "srtypes.h"
-
-typedef struct mp3_headerSt
-{
- int lay;
- int version;
- int error_protection;
- int bitrate_index;
- int sampling_frequency;
- int padding;
- int extension;
- int mode;
- int mode_ext;
- int copyright;
- int original;
- int emphasis;
- int stereo;
-} mp3_header_t;
-
-
-extern error_code mpeg_find_first_header(const char* buffer, int size, int min_good_frames, int *frame_pos);
-extern error_code mpeg_find_last_header(const char *buffer, int size, int min_good_frames, int *frame_pos);
-
-#endif //__MPEG_H__
-
diff --git a/xbmc/lib/libshout/parse.c b/xbmc/lib/libshout/parse.c
deleted file mode 100644
index de77eaf990..0000000000
--- a/xbmc/lib/libshout/parse.c
+++ /dev/null
@@ -1,559 +0,0 @@
-/* parse.c
- * metadata parsing routines
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include "srconfig.h"
-#include "mchar.h"
-#include "debug.h"
-#include "srtypes.h"
-#include "regex.h"
-
-/* GCS FIX: figure out function prototypes for regwcomp, regwexec */
-
-/*****************************************************************************
- * Private global variables
- *****************************************************************************/
-#define MAX_RULE_SIZE 2048
-#define MAX_SUBMATCHES 24
-
-#define PARSERULE_CMD_MATCH 0x01
-#define PARSERULE_CMD_SUBST 0x02
-
-#define PARSERULE_SKIP 0x01
-#define PARSERULE_GLOBAL 0x02
-#define PARSERULE_ICASE 0x04
-#define PARSERULE_SAVE 0x08
-#define PARSERULE_EXCLUDE 0x10
-
-
-struct parse_rule {
- int cmd;
- int flags;
- int artist_idx;
- int title_idx;
- int album_idx;
- int trackno_idx;
- regex_t* reg;
- mchar* match;
- mchar* subst;
-};
-typedef struct parse_rule Parse_Rule;
-
-static Parse_Rule m_default_rule_list[] = {
- { PARSERULE_CMD_MATCH,
- PARSERULE_SKIP,
- 0, 0, 0, 0,
- 0,
-#if defined HAVE_WCHAR_SUPPORT
- /* GCS FIX: L string literals are not good */
- L"^A suivre:",
- L""
-#else
- "^A suivre:",
- ""
-#endif
- },
- { PARSERULE_CMD_SUBST,
- PARSERULE_ICASE,
- 0, 0, 0, 0,
- 0,
-#if defined HAVE_WCHAR_SUPPORT
- L"[[:space:]]*-?[[:space:]]*mp3pro$",
- L""
-#else
- "[[:space:]]*-?[[:space:]]*mp3pro$",
- ""
-#endif
- },
- { PARSERULE_CMD_MATCH,
- PARSERULE_ICASE,
- 1, 2, 0, 0,
- 0,
-#if defined HAVE_WCHAR_SUPPORT
- L"^[[:space:]]*([^-]*[^-[:space:]])[[:space:]]*-[[:space:]]*(.*)[[:space:]]*$",
- L""
-#else
- "^[[:space:]]*([^-]*[^-[:space:]])[[:space:]]*-[[:space:]]*(.*)[[:space:]]*$",
- ""
-#endif
- },
- { 0x00,
- 0x00,
- 0, 0, 0, 0,
- 0,
-#if defined HAVE_WCHAR_SUPPORT
- L"",
- L""
-#else
- "",
- ""
-#endif
- }
-};
-static Parse_Rule* m_global_rule_list = m_default_rule_list;
-
-/*****************************************************************************
- * Public functions
- *****************************************************************************/
-static int
-sr_regcomp (Parse_Rule* pr, mchar* rule_string, int cflags)
-{
-#if defined HAVE_WCHAR_SUPPORT
- return regwcomp(pr->reg, rule_string, cflags);
-#else
- return regcomp(pr->reg, rule_string, cflags);
-#endif
-}
-
-static int
-mregexec (const regex_t* preg, const mchar* string, size_t nmatch,
- regmatch_t pmatch[], int eflags)
-{
-#if defined HAVE_WCHAR_SUPPORT
- return regwexec (preg, string, nmatch, pmatch, eflags);
-#else
- return regexec (preg, string, nmatch, pmatch, eflags);
-#endif
-}
-
-/* Returns 1 if successful, 0 if failure */
-static int
-compile_rule (Parse_Rule* pr, mchar* rule_string)
-{
- int rc;
- int cflags;
-
- pr->reg = (regex_t*) malloc (sizeof(regex_t));
- if (!pr->reg) return 0;
-
- cflags = REG_EXTENDED;
- if (pr->flags & PARSERULE_ICASE) {
- cflags |= REG_ICASE;
- }
- rc = sr_regcomp(pr, rule_string, cflags);
- if (rc != 0) {
- free(pr->reg);
- return 0;
- }
- return 1;
-}
-
-static void
-use_default_rules (void)
-{
- Parse_Rule* rulep;
-
- /* set global rule list to default */
- m_global_rule_list = m_default_rule_list;
-
- /* compile regular expressions */
- for (rulep = m_global_rule_list; rulep->cmd; rulep++) {
- compile_rule (rulep, rulep->match);
- }
-}
-
-static void
-copy_rule_result (mchar* dest, mchar* query_string,
- regmatch_t* pmatch, int idx)
-{
- if (idx > 0 && idx <= MAX_SUBMATCHES) {
- mstrncpy (dest, query_string + pmatch[idx].rm_so,
- pmatch[idx].rm_eo - pmatch[idx].rm_so + 1);
- }
-}
-
-/* Return 1 if successful, or 0 for failure */
-static int
-parse_flags (Parse_Rule* pr, char* flags)
-{
- char flag1;
-
- while ((flag1 = *flags++)) {
- int* tag = 0;
- switch (flag1) {
- case 'e':
- pr->flags |= PARSERULE_SKIP;
- if (pr->cmd != PARSERULE_CMD_MATCH) return 0;
- break;
- case 'g':
- /* GCS FIX: Not yet implemented */
- pr->flags |= PARSERULE_GLOBAL;
- break;
- case 'i':
- pr->flags |= PARSERULE_ICASE;
- break;
- case 's':
- pr->flags |= PARSERULE_SAVE;
- if (pr->cmd != PARSERULE_CMD_MATCH) return 0;
- break;
- case 'x':
- pr->flags |= PARSERULE_EXCLUDE;
- if (pr->cmd != PARSERULE_CMD_MATCH) return 0;
- break;
- case 'A':
- tag = &pr->artist_idx;
- break;
- case 'C':
- tag = &pr->album_idx;
- break;
- case 'N':
- tag = &pr->trackno_idx;
- break;
- case 'T':
- tag = &pr->title_idx;
- break;
- case 0:
- case '\n':
- case '\r':
- return 1;
- default:
- return 0;
- }
- if (tag) {
- int rc;
- int nchar;
- int idx = 0;
-
- if (pr->cmd != PARSERULE_CMD_MATCH) return 0;
- rc = sscanf (flags, "%d%n", &idx, &nchar);
- if (rc == 0 || idx > MAX_SUBMATCHES) {
- return 0;
- }
- flags += nchar;
- *tag = idx;
- }
- }
- return 1;
-}
-
-static char*
-parse_escaped_string (char* outbuf, char* inbuf)
-{
- int escaped = 0;
-
- while (1) {
- switch (*outbuf++ = *inbuf++) {
- case '\\':
- escaped = !escaped;
- break;
- case '/':
- if (!escaped){
- *(--outbuf) = 0;
- return inbuf;
- }
- break;
- case 0:
- return 0;
- break;
- default:
- escaped = 0;
- break;
- }
- }
- /* Never get here */
- return 0;
-}
-
-/* This mega-function reads in the rules file, and loads
- all the rules into the m_global_rules_list data structure */
-void
-init_metadata_parser (char* rules_file)
-{
- FILE* fp;
- int ri; /* Rule index */
-
- if (!rules_file || !*rules_file) {
- use_default_rules ();
- return;
- }
- fp = fopen (rules_file, "r");
- if (!fp) {
- use_default_rules ();
- return;
- }
-
- m_global_rule_list = 0;
- ri = 0;
- while (!feof(fp)) {
- char rule_buf[MAX_RULE_SIZE];
- char match_buf[MAX_RULE_SIZE];
- char subst_buf[MAX_RULE_SIZE];
- mchar w_match_buf[MAX_RULE_SIZE];
- mchar w_subst_buf[MAX_RULE_SIZE];
- char* rbp;
- int got_command;
- int rc;
-
- /* Allocate memory for rule */
- m_global_rule_list = realloc (m_global_rule_list,
- (ri+1) * sizeof(Parse_Rule));
- memset (&m_global_rule_list[ri], 0, sizeof(Parse_Rule));
-
- /* Get next line from file */
- fgets (rule_buf,2048,fp);
-
- /* Skip leading whitespace */
- rbp = rule_buf;
- while (*rbp && isspace(*rbp)) rbp++;
- if (!*rbp) continue;
-
- /* Get command */
- got_command = 0;
- switch (*rbp++) {
- case 'm':
- got_command = 1;
- m_global_rule_list[ri].cmd = PARSERULE_CMD_MATCH;
- break;
- case 's':
- got_command = 1;
- m_global_rule_list[ri].cmd = PARSERULE_CMD_SUBST;
- break;
- case '#':
- got_command = 0;
- break;
- default:
- got_command = 0;
- printf ("Warning: malformed command in rules file:\n%s\n",
- rule_buf);
- break;
- }
- if (!got_command) continue;
-
- /* Skip past fwd slash */
- if (*rbp++ != '/') {
- printf ("Warning: malformed command in rules file:\n%s\n",
- rule_buf);
- continue;
- }
-
- /* Parse match string */
- rbp = parse_escaped_string (match_buf, rbp);
- debug_printf ("match_buf=%s\n", match_buf);
- if (!rbp) {
- printf ("Warning: malformed command in rules file:\n%s\n",
- rule_buf);
- continue;
- }
-
- /* Parse subst string */
- if (m_global_rule_list[ri].cmd == PARSERULE_CMD_SUBST) {
- rbp = parse_escaped_string (subst_buf, rbp);
- debug_printf ("subst_buf=%s\n", subst_buf);
- if (!rbp) {
- printf ("Warning: malformed command in rules file:\n%s\n",
- rule_buf);
- continue;
- }
- }
-
- /* Parse flags */
- rc = parse_flags (&m_global_rule_list[ri], rbp);
- if (!rc) {
- printf ("Warning: malformed command in rules file:\n%s\n",
- rule_buf);
- continue;
- }
-
- /* Compile the rule */
- debug_printf ("Compiling the rule\n");
- mstring_from_string (w_match_buf, MAX_RULE_SIZE, match_buf,
- CODESET_UTF8);
- if (!compile_rule(&m_global_rule_list[ri], w_match_buf)) {
- printf ("Warning: malformed regular expression:\n%s\n",
- match_buf);
- continue;
- }
-
- /* Copy rule strings */
- debug_printf ("Copying rule string (1)\n");
- debug_mprintf (m_("String is ") m_S m_("\n"), w_match_buf);
- m_global_rule_list[ri].match = mstrdup(w_match_buf);
- debug_printf ("Copying rule string (2)\n");
- if (m_global_rule_list[ri].cmd == PARSERULE_CMD_SUBST) {
- debug_printf ("Copying rule string (3)\n");
- mstring_from_string (w_subst_buf, MAX_RULE_SIZE, subst_buf,
- CODESET_UTF8);
- debug_printf ("Copying rule string (4)\n");
- m_global_rule_list[ri].subst = mstrdup(w_subst_buf);
- debug_printf ("Copying rule string (5)\n");
- }
-
- debug_printf ("End of loop\n");
- ri++;
- }
- /* Add null rule to the end */
- m_global_rule_list = realloc (m_global_rule_list,
- (ri+1) * sizeof(Parse_Rule));
- memset (&m_global_rule_list[ri], 0, sizeof(Parse_Rule));
-}
-
-void
-compose_metadata (TRACK_INFO* ti)
-{
- int num_bytes;
- unsigned char num_16_bytes;
- mchar w_composed_metadata[MAX_METADATA_LEN+1];
-
- if (ti->have_track_info) {
- if (ti->artist[0]) {
- msnprintf (w_composed_metadata, MAX_METADATA_LEN,
- m_("StreamTitle='") m_S m_(" - ") m_S m_("';"),
- ti->artist, ti->title);
- } else {
- msnprintf (w_composed_metadata, MAX_METADATA_LEN,
- m_("StreamTitle='") m_S m_("';"),
- ti->title);
- }
- } else {
- debug_printf ("No track info when composing relay metadata\n");
- }
- debug_printf ("Converting relay string to char\n");
- num_bytes = string_from_mstring (&ti->composed_metadata[1],
- MAX_METADATA_LEN,
- w_composed_metadata,
- CODESET_RELAY);
- ti->composed_metadata[MAX_METADATA_LEN] = 0; // note, not LEN-1
- num_16_bytes = (num_bytes + 15) / 16;
- ti->composed_metadata[0] = num_16_bytes;
-}
-
-void
-parse_metadata (TRACK_INFO* ti)
-{
- int eflags;
- int rc;
- mchar query_string[MAX_TRACK_LEN];
- Parse_Rule* rulep;
-
- /* Has any m/.../s rule matched? */
- BOOL save_track_matched = FALSE;
-
- /* Has any m/.../x rule matched? */
- BOOL exclude_track_matched = FALSE;
-
- ti->have_track_info = 0;
- ti->artist[0] = 0;
- ti->title[0] = 0;
- ti->album[0] = 0;
- ti->composed_metadata[0] = 0;
- ti->save_track = TRUE;
- if (!ti->raw_metadata[0]) {
- debug_printf ("Couldn't parse because no meta data\n");
- return;
- }
-
- /* Loop through rules, if we find a matching rule, then use it */
- /* For now, only default rules supported with ascii
- regular expressions. */
- debug_printf ("Converting query string to wide\n");
- mstring_from_string (query_string, MAX_TRACK_LEN,
- ti->raw_metadata, CODESET_METADATA);
- for (rulep = m_global_rule_list; rulep->cmd; rulep++) {
- regmatch_t pmatch[MAX_SUBMATCHES+1];
-
- eflags = 0;
- if (rulep->cmd == PARSERULE_CMD_MATCH) {
- debug_mprintf (m_("Testing match rule: ") m_S m_(" vs. ") m_S m_("\n"),
- query_string, rulep->match);
- if (rulep->flags & PARSERULE_SKIP) {
- rc = mregexec (rulep->reg, query_string, 0, NULL, eflags);
- if (rc != 0) {
- /* Didn't match rule. */
- continue;
- }
- /* GCS FIX: We need to return to the
- caller that the metadata should be dropped. */
- ti->save_track = FALSE;
- ti->have_track_info = 0;
- return;
- } else if (rulep->flags & PARSERULE_SAVE) {
- rc = mregexec (rulep->reg, query_string, 0, NULL, eflags);
- if (rc != 0) {
- /* Didn't match rule. */
- if (!save_track_matched)
- ti->save_track = FALSE;
- continue;
- }
- if (!exclude_track_matched) {
- ti->save_track = TRUE;
- save_track_matched = TRUE;
- }
- } else if (rulep->flags & PARSERULE_EXCLUDE) {
- rc = mregexec (rulep->reg, query_string, 0, NULL, eflags);
- if (rc == 0 && !save_track_matched) {
- /* Rule matched => Exclude track */
- ti->save_track = FALSE;
- exclude_track_matched = TRUE;
- }
- } else {
- eflags = 0;
- rc = mregexec (rulep->reg, query_string, MAX_SUBMATCHES+1,
- pmatch, eflags);
- if (rc != 0) {
- /* Didn't match rule. */
- continue;
- }
- copy_rule_result (ti->artist, query_string, pmatch, rulep->artist_idx);
- copy_rule_result (ti->title, query_string, pmatch, rulep->title_idx);
- copy_rule_result (ti->album, query_string, pmatch, rulep->album_idx);
- ti->have_track_info = 1;
- compose_metadata (ti);
- /* GCS FIX: We don't have a track number. */
- debug_mprintf (m_("Parsed track info.\n")
- m_("ARTIST: ") m_S m_("\n")
- m_("TITLE: ") m_S m_("\n")
- m_("ALBUM: ") m_S m_("\n"),
- ti->artist, ti->title, ti->album);
- return;
- }
- }
- else if (rulep->cmd == PARSERULE_CMD_SUBST) {
- mchar subst_string[MAX_TRACK_LEN];
- int used, left;
- debug_mprintf (m_("Testing subst rule: ") m_S m_(" vs. ") m_S m_("\n"),
- query_string, rulep->match);
- rc = mregexec (rulep->reg, query_string, 1, pmatch, eflags);
- if (rc != 0) {
- /* Didn't match rule. */
- continue;
- }
- /* Update the query string and continue. */
- debug_printf ("Matched at (%d,%d)\n",
- pmatch[0].rm_so, pmatch[0].rm_eo);
- mstrncpy (subst_string, query_string, pmatch[0].rm_so + 1);
- debug_mprintf (m_("(1) subst_string = ") m_S m_("\n"), subst_string);
- used = pmatch[0].rm_so;
- left = MAX_TRACK_LEN - used;
- mstrncpy (subst_string + used, rulep->subst, left);
- debug_mprintf (m_("(2) subst_string = ") m_S m_("\n"), subst_string);
- used += mstrlen (rulep->subst);
- left = MAX_TRACK_LEN - used;
- mstrncpy (subst_string + used,
- query_string + pmatch[0].rm_eo, left);
- debug_mprintf (m_("(3) subst_string = ") m_S m_("\n"), subst_string);
- mstrncpy (query_string, subst_string, MAX_TRACK_LEN);
- debug_mprintf (m_("(4) query_string = ") m_S m_("\n"), query_string);
- }
- }
- debug_printf ("Fell through while parsing data...\n");
- mstrncpy (ti->title, query_string, MAX_TRACK_LEN);
- ti->have_track_info = 1;
- compose_metadata (ti);
-}
diff --git a/xbmc/lib/libshout/parse.h b/xbmc/lib/libshout/parse.h
deleted file mode 100644
index 6e77141414..0000000000
--- a/xbmc/lib/libshout/parse.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __PARSE_H__
-#define __PARSE_H__
-
-#include "srtypes.h"
-
-void init_metadata_parser (char* rules_file);
-void parse_metadata (TRACK_INFO* track_info);
-
-#endif //__PARSE_H__
diff --git a/xbmc/lib/libshout/relaylib.c b/xbmc/lib/libshout/relaylib.c
deleted file mode 100644
index 82757fd734..0000000000
--- a/xbmc/lib/libshout/relaylib.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/* relaylib.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#if WIN32
-#include <winsock2.h>
-#else
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <ctype.h>
-#endif
-
-#if __UNIX__
-#include <arpa/inet.h>
-#elif __BEOS__
-#include <be/net/netdb.h>
-#endif
-
-#include <string.h>
-#include "relaylib.h"
-#include "srtypes.h"
-#include "http.h"
-#include "socklib.h"
-#include "threadlib.h"
-#include "debug.h"
-#include "compat.h"
-#include "rip_manager.h"
-#include "cbuf2.h"
-
-#if defined (WIN32)
-#ifdef errno
-#undef errno
-#endif
-#define errno WSAGetLastError()
-#endif
-
-/*****************************************************************************
- * Global variables
- *****************************************************************************/
-RELAY_LIST* g_relay_list = NULL;
-unsigned long g_relay_list_len = 0;
-HSEM g_relay_list_sem;
-
-/*****************************************************************************
- * Private vars
- *****************************************************************************/
-static HSEM m_sem_not_connected;
-static char m_http_header[MAX_HEADER_LEN];
-static SOCKET m_listensock = SOCKET_ERROR;
-static BOOL m_running = FALSE;
-static BOOL m_initdone = FALSE;
-static THREAD_HANDLE m_hthread;
-static THREAD_HANDLE m_hthread2;
-
-static int m_max_connections;
-static int m_have_metadata;
-
-/*****************************************************************************
- * Private functions
- *****************************************************************************/
-static void thread_accept(void *notused);
-static error_code try_port(u_short port, char *if_name, char *relay_ip);
-static void thread_send(void *notused);
-
-#define BUFSIZE (1024)
-
-#define HTTP_HEADER_TIMEOUT 2
-#define HTTP_HEADER_DELIM "\n"
-#define ICY_METADATA_TAG "Icy-MetaData:"
-
-static void
-destroy_all_hostsocks(void)
-{
- RELAY_LIST* ptr;
-
- threadlib_waitfor_sem (&g_relay_list_sem);
- while (g_relay_list != NULL) {
- ptr = g_relay_list;
- closesocket(ptr->m_sock);
- g_relay_list = ptr->m_next;
- if (ptr->m_buffer != NULL)
- free (ptr->m_buffer);
- free(ptr);
- }
- g_relay_list_len = 0;
- threadlib_signal_sem (&g_relay_list_sem);
-}
-
-static int
-tag_compare (char *str, char *tag)
-{
- int i, a,b;
- int len;
-
- len = strlen(tag);
-
- for (i=0; i<len; i++) {
- a = tolower (str[i]);
- b = tolower (tag[i]);
- if ((a != b) || (a == 0))
- return 1;
- }
- return 0;
-}
-
-static int
-header_receive (int sock, int *icy_metadata)
-{
- fd_set fds;
- struct timeval tv;
- int r;
- char buf[BUFSIZE+1];
- char *md;
-
- *icy_metadata = 0;
-
- while (1) {
- // use select to prevent deadlock on malformed http header
- // that lacks CRLF delimiter
- FD_ZERO(&fds);
- FD_SET(sock, &fds);
- tv.tv_sec = HTTP_HEADER_TIMEOUT;
- tv.tv_usec = 0;
- r = select(sock + 1, &fds, NULL, NULL, &tv);
- if (r != 1) {
- debug_printf ("header_receive: could not select\n");
- break;
- }
-
- r = recv(sock, buf, BUFSIZE, 0);
- if (r <= 0) {
- debug_printf ("header_receive: could not select\n");
- break;
- }
-
- buf[r] = 0;
- md = strtok (buf, HTTP_HEADER_DELIM);
- while (md) {
- debug_printf ("Got token: %s\n", md);
- // Finished when we are at end of header: only CRLF will be there.
- if ((md[0] == '\r') && (md[1] == 0))
- return 0;
-
- // Check for desired tag
- if (tag_compare (md, ICY_METADATA_TAG) == 0) {
- for (md += strlen(ICY_METADATA_TAG); md[0] && (isdigit(md[0]) == 0); md++);
-
- if (md[0])
- *icy_metadata = atoi(md);
-
- debug_printf ("client flag ICY-METADATA is %d\n",
- *icy_metadata);
- }
-
- md = strtok (NULL, HTTP_HEADER_DELIM);
- }
- }
-
- return 1;
-}
-
-
-// Quick function to "eat" incoming data from a socket
-// All data is discarded
-// Returns 0 if successful or SOCKET_ERROR if error
-static int
-swallow_receive (int sock)
-{
- fd_set fds;
- struct timeval tv;
- int ret = 0;
- char buf[BUFSIZE];
- BOOL hasmore = TRUE;
-
- FD_ZERO(&fds);
- while (hasmore) {
- // Poll the socket to see if it has anything to read
- hasmore = FALSE;
- FD_SET(sock, &fds);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- ret = select(sock + 1, &fds, NULL, NULL, &tv);
- if (ret == 1) {
- // Read and throw away data, ignoring errors
- ret = recv(sock, buf, BUFSIZE, 0);
- if (ret > 0) {
- hasmore = TRUE;
- }
- else if (ret == SOCKET_ERROR) {
- break;
- }
- }
- else if (ret == SOCKET_ERROR) {
- break;
- }
- }
-
- return ret;
-}
-
-
-// Makes a socket non-blocking
-void
-make_nonblocking (int sock)
-{
- int opt;
-
-#ifndef WIN32
- opt = fcntl(sock, F_GETFL);
- if (opt != SOCKET_ERROR) {
- fcntl(sock, F_SETFL, opt | O_NONBLOCK);
- }
-#else
- opt = 1;
- ioctlsocket(sock, FIONBIO, &opt);
-#endif
-}
-
-BOOL relaylib_isrunning()
-{
- return m_running;
-}
-
-error_code
-relaylib_set_response_header(char *http_header)
-{
- if (!http_header)
- return SR_ERROR_INVALID_PARAM;
-
- strcpy(m_http_header, http_header);
-
- return SR_SUCCESS;
-}
-
-#ifndef WIN32
-void
-catch_pipe(int code)
-{
- //m_sock = 0;
- //m_connected = FALSE;
- // JCBUG, not sure what to do about this
-}
-#endif
-
-error_code
-relaylib_init (BOOL search_ports, u_short relay_port, u_short max_port,
- u_short *port_used, char *if_name, int max_connections,
- char *relay_ip, int have_metadata)
-{
- int ret;
-#ifdef WIN32
- WSADATA wsd;
-#endif
-
- debug_printf ("relaylib_init()\n");
-
-#ifdef WIN32
- if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
- debug_printf ("relaylib_init(): SR_ERROR_CANT_BIND_ON_PORT\n");
- return SR_ERROR_CANT_BIND_ON_PORT;
- }
-#endif
-
- if (relay_port < 1 || !port_used) {
- debug_printf ("relaylib_init(): SR_ERROR_INVALID_PARAM\n");
- return SR_ERROR_INVALID_PARAM;
- }
-
-#ifndef WIN32
- // catch a SIGPIPE if send fails
- signal(SIGPIPE, catch_pipe);
-#endif
-
- if (m_initdone != TRUE) {
- m_sem_not_connected = threadlib_create_sem();
- g_relay_list_sem = threadlib_create_sem();
- threadlib_signal_sem(&g_relay_list_sem);
-
- // NOTE: we need to signal it here in case we try to destroy
- // relaylib before the thread starts!
- threadlib_signal_sem(&m_sem_not_connected);
- m_initdone = TRUE;
- }
- m_max_connections = max_connections;
- m_have_metadata = have_metadata;
- *port_used = 0;
- if (!search_ports)
- max_port = relay_port;
-
- for(;relay_port <= max_port; relay_port++) {
- ret = try_port ((u_short)relay_port, if_name, relay_ip);
- if (ret == SR_ERROR_CANT_BIND_ON_PORT)
- continue; // Keep searching.
-
- if (ret == SR_SUCCESS) {
- *port_used = relay_port;
- debug_printf ("Relay: Listening on port %d\n", relay_port);
- return SR_SUCCESS;
- } else {
- return ret;
- }
- }
-
- return SR_ERROR_CANT_BIND_ON_PORT;
-}
-
-error_code
-try_port (u_short port, char *if_name, char *relay_ip)
-{
- struct hostent *he;
- struct sockaddr_in local;
-
- m_listensock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
- if (m_listensock == SOCKET_ERROR) {
- debug_printf ("try_port(%d) failed socket() call\n", port);
- return SR_ERROR_SOCK_BASE;
- }
- make_nonblocking(m_listensock);
-
- if ('\0' == *relay_ip) {
- if (read_interface(if_name,&local.sin_addr.s_addr) != 0)
- local.sin_addr.s_addr = htonl(INADDR_ANY);
- } else {
- he = gethostbyname(relay_ip);
- memcpy(&local.sin_addr, he->h_addr_list[0], he->h_length);
- }
-
- local.sin_family = AF_INET;
- local.sin_port = htons(port);
-
-#ifndef WIN32
- {
- // Prevent port error when restarting quickly after a previous exit
- int opt = 1;
- setsockopt(m_listensock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
- }
-#endif
-
- if (bind(m_listensock, (struct sockaddr *)&local, sizeof(local)) == SOCKET_ERROR)
- {
- debug_printf ("try_port(%d) failed bind() call\n", port);
- closesocket(m_listensock);
- m_listensock = SOCKET_ERROR;
- return SR_ERROR_CANT_BIND_ON_PORT;
- }
-
- if (listen(m_listensock, 1) == SOCKET_ERROR)
- {
- debug_printf ("try_port(%d) failed listen() call\n", port);
- closesocket(m_listensock);
- m_listensock = SOCKET_ERROR;
- return SR_ERROR_SOCK_BASE;
- }
-
- debug_printf ("try_port(%d) succeeded\n", port);
- return SR_SUCCESS;
-}
-
-void
-relaylib_shutdown ()
-{
- debug_printf("relaylib_shutdown:start\n");
- if (!relaylib_isrunning()) {
- debug_printf("***relaylib_shutdown:return\n");
- return;
- }
- m_running = FALSE;
- threadlib_signal_sem(&m_sem_not_connected);
- if (closesocket(m_listensock) == SOCKET_ERROR) {
- // JCBUG, what can we do?
- }
- m_listensock = SOCKET_ERROR; // Accept thread will watch for this and not try to accept anymore
- memset(m_http_header, 0, MAX_HEADER_LEN);
- debug_printf("waiting for relay close\n");
- threadlib_waitforclose(&m_hthread);
- threadlib_waitforclose(&m_hthread2);
- destroy_all_hostsocks();
- threadlib_destroy_sem(&m_sem_not_connected);
- m_initdone = FALSE;
-
- debug_printf("relaylib_shutdown:done!\n");
-}
-
-error_code
-relaylib_start ()
-{
- int ret;
-
- m_running = TRUE;
- // Spawn on a thread so it's non-blocking
- if ((ret = threadlib_beginthread(&m_hthread, thread_accept, 0)) != SR_SUCCESS)
- return ret;
-
- if ((ret = threadlib_beginthread(&m_hthread2, thread_send, 0)) != SR_SUCCESS)
- return ret;
-
- return SR_SUCCESS;
-}
-
-void
-thread_accept (void *notused)
-{
- int ret;
- int newsock;
- BOOL good;
- struct sockaddr_in client;
- int iAddrSize = sizeof(client);
- RELAY_LIST* newhostsock;
- int icy_metadata;
- char* client_http_header;
-
- debug_printf("thread_accept:start\n");
-
- while (m_running)
- {
- fd_set fds;
- struct timeval tv;
-
- // this event will keep use from accepting while we
- // have a connection active
- // when a connection gets dropped, or when streamripper shuts down
- // this event will get signaled
- debug_printf("thread_accept:waiting on m_sem_not_connected\n");
- threadlib_waitfor_sem (&m_sem_not_connected);
- if (!m_running) {
- debug_printf("thread_accept:exit (no longer m_running)\n");
- break;
- }
-
- // Poll once per second, instead of blocking forever in
- // accept(), so that we can regain control if relaylib_shutdown()
- // called
- FD_ZERO (&fds);
- while (m_listensock != SOCKET_ERROR)
- {
- FD_SET (m_listensock, &fds);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- debug_printf("thread_accept:calling select()\n");
- ret = select (m_listensock + 1, &fds, NULL, NULL, &tv);
- debug_printf("thread_accept:select() returned\n");
- if (ret == 1) {
- unsigned long num_connected;
- /* If connections are full, do nothing. Note that
- m_max_connections is 0 for infinite connections allowed. */
- threadlib_waitfor_sem (&g_relay_list_sem);
- num_connected = g_relay_list_len;
- threadlib_signal_sem (&g_relay_list_sem);
- if (m_max_connections > 0 && num_connected >= (unsigned long) m_max_connections) {
- continue;
- }
- /* Check for connections */
- debug_printf ("Calling accept()\n");
- newsock = accept (m_listensock, (struct sockaddr *)&client, &iAddrSize);
- if (newsock != SOCKET_ERROR) {
- // Got successful accept
-
- debug_printf ("Relay: Client %d new from %s:%hd\n", newsock,
- inet_ntoa(client.sin_addr), ntohs(client.sin_port));
-
- // Socket is new and its buffer had better have
- // room to hold the entire HTTP header!
- good = FALSE;
- if (header_receive (newsock, &icy_metadata) == 0) {
- int header_len;
- make_nonblocking (newsock);
- client_http_header = client_relay_header_generate(icy_metadata);
- header_len = strlen (client_http_header);
- ret = send (newsock, client_http_header, strlen(client_http_header), 0);
- debug_printf ("Relay: Sent response header to client %d (%d)\n",
- ret, header_len);
- client_relay_header_release (client_http_header);
- if (ret == header_len) {
- newhostsock = malloc (sizeof(RELAY_LIST));
- if (newhostsock != NULL) {
- // Add new client to list (headfirst)
- threadlib_waitfor_sem (&g_relay_list_sem);
- newhostsock->m_is_new = 1;
- newhostsock->m_sock = newsock;
- newhostsock->m_next = g_relay_list;
- if (m_have_metadata) {
- newhostsock->m_icy_metadata = icy_metadata;
- } else {
- newhostsock->m_icy_metadata = 0;
- }
-
- g_relay_list = newhostsock;
- g_relay_list_len++;
- threadlib_signal_sem (&g_relay_list_sem);
- good = TRUE;
- }
- }
- }
-
- if (!good)
- {
- closesocket (newsock);
- debug_printf ("Relay: Client %d disconnected (Unable to receive HTTP header)\n", newsock);
- }
- }
- }
- else if (ret == SOCKET_ERROR)
- {
- // Something went wrong with select
- break;
- }
- }
- threadlib_signal_sem (&m_sem_not_connected); // go back to accept
- }
-
- m_running = FALSE;
-}
-
-/* Sock is ready to receive, so send it from cbuf to relay */
-static BOOL
-send_to_relay (RELAY_LIST* ptr)
-{
- int ret;
- int err_errno;
- BOOL good = TRUE;
- int done = 0;
-
- /* For new clients, initialize cbuf pointers */
- if (ptr->m_is_new) {
- int burst_amount = 32*1024;
- // int burst_amount = 64*1024;
- // int burst_amount = 128*1024;
- ptr->m_offset = 0;
- ptr->m_left_to_send = 0;
-
- cbuf2_init_relay_entry (&g_cbuf2, ptr, burst_amount);
-
- ptr->m_is_new = 0;
- }
-
- while (!done) {
- /* If our private buffer is empty, copy some from the cbuf */
- if (!ptr->m_left_to_send) {
- error_code rc;
- ptr->m_offset = 0;
- rc = cbuf2_extract_relay (&g_cbuf2, ptr);
-
- if (rc == SR_ERROR_BUFFER_EMPTY) {
- break;
- }
- }
- /* Send from the private buffer to the client */
- debug_printf ("Relay: Sending Client %d to the client\n",
- ptr->m_left_to_send );
- ret = send (ptr->m_sock, ptr->m_buffer+ptr->m_offset,
- ptr->m_left_to_send, 0);
- debug_printf ("Relay: Sending to Client returned %d\n", ret );
- if (ret == SOCKET_ERROR) {
- /* Sometimes windows gives me an errno of 0
- Sometimes windows gives me an errno of 183
- See this thread for details:
- http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&selm=8956d3e8.0309100905.6ba60e7f%40posting.google.com
- */
- err_errno = errno;
- if (err_errno == EWOULDBLOCK || err_errno == 0
- || err_errno == 183)
- {
-#if defined (WIN32)
- // Client is slow. Retry later.
- WSASetLastError (0);
-#endif
- } else {
- debug_printf ("Relay: socket error is %d\n",errno);
- good = FALSE;
- }
- done = 1;
- } else {
- // Send was successful
- ptr->m_offset += ret;
- ptr->m_left_to_send -= ret;
- if (ptr->m_left_to_send < 0) {
- /* GCS: can this ever happen??? */
- debug_printf ("ptr->m_left_to_send < 0\n");
- ptr->m_left_to_send = 0;
- done = 1;
- }
- }
- }
- return good;
-}
-
-void
-relaylib_disconnect (RELAY_LIST* prev, RELAY_LIST* ptr)
-{
- RELAY_LIST* next = ptr->m_next;
- int sock = ptr->m_sock;
-
- closesocket (sock);
-
- // Carefully delete this client from list without
- // affecting list order
- if (prev != NULL) {
- prev->m_next = next;
- } else {
- g_relay_list = next;
- }
- if (ptr->m_buffer != NULL)
- free (ptr->m_buffer);
- free (ptr);
- g_relay_list_len --;
-}
-
-void
-thread_send (void *notused)
-{
- RELAY_LIST* prev;
- RELAY_LIST* ptr;
- RELAY_LIST* next;
- int sock;
- BOOL good;
- error_code err = SR_SUCCESS;
-
- while (m_running) {
- threadlib_waitfor_sem (&g_relay_list_sem);
- ptr = g_relay_list;
- if (ptr != NULL) {
- prev = NULL;
- while (ptr != NULL) {
- sock = ptr->m_sock;
- next = ptr->m_next;
-
- if (swallow_receive(sock) != 0) {
- good = FALSE;
- } else {
- good = send_to_relay (ptr);
- }
-
- if (!good) {
- debug_printf ("Relay: Client %d disconnected (%s)\n",
- sock, strerror(errno));
- relaylib_disconnect (prev, ptr);
- } else if (ptr != NULL) {
- prev = ptr;
- }
- ptr = next;
- }
- } else {
- err = SR_ERROR_HOST_NOT_CONNECTED;
- }
- threadlib_signal_sem (&g_relay_list_sem);
- Sleep (50);
- }
-}
diff --git a/xbmc/lib/libshout/relaylib.h b/xbmc/lib/libshout/relaylib.h
deleted file mode 100644
index 0da2312061..0000000000
--- a/xbmc/lib/libshout/relaylib.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* relaylib.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __RELAYLIB_H__
-#define __RELAYLIB_H__
-
-#include "srtypes.h"
-#include "compat.h"
-
-/* Each relay connection gets this struct */
-typedef struct RELAY_LIST_struct RELAY_LIST;
-struct RELAY_LIST_struct
-{
- SOCKET m_sock;
- int m_is_new;
-
- char* m_buffer; // large enough for 1 block & 1 metadata
- u_long m_buffer_size;
- u_long m_cbuf_pos; // must lie along chunck boundary for mp3
- u_long m_offset;
- u_long m_left_to_send;
- int m_icy_metadata; // true if client requested metadata
-
- char* m_header_buf_ptr; // for ogg header pages
- u_long m_header_buf_len; // for ogg header pages
- u_long m_header_buf_off; // for ogg header pages
-
- RELAY_LIST* m_next;
-};
-
-
-/*****************************************************************************
- * Global variables
- *****************************************************************************/
-extern RELAY_LIST* g_relay_list;
-extern unsigned long g_relay_list_len;
-extern HSEM g_relay_list_sem;
-
-
-/*****************************************************************************
- * Function prototypes
- *****************************************************************************/
-error_code relaylib_set_response_header(char *http_header);
-error_code relaylib_init (BOOL search_ports, u_short relay_port, u_short max_port,
- u_short *port_used, char *if_name, int max_connections,
- char *relay_ip, int have_metadata);
-error_code relaylib_start();
-error_code relaylib_send(char *data, int len, int accept_new, int is_meta);
-void relaylib_shutdown();
-BOOL relaylib_isrunning();
-error_code relaylib_send_meta_data(char *track);
-//int get_relay_sockname(struct sockaddr_in *relay);
-void relaylib_disconnect (RELAY_LIST* prev, RELAY_LIST* ptr);
-
-#endif //__RELAYLIB__
diff --git a/xbmc/lib/libshout/rip_manager.c b/xbmc/lib/libshout/rip_manager.c
deleted file mode 100644
index bdf037b5da..0000000000
--- a/xbmc/lib/libshout/rip_manager.c
+++ /dev/null
@@ -1,765 +0,0 @@
-/* rip_manager.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/*
- * This is the top level for the streamripper library. The it handles the
- * connecting the rippers (ripstream, ripshout, riplive) to the sockets
- * (socklib), the output stuff (filelib) and the relay server thing (relaylib)
- * and also all the "features" like auto connecting, directory names.
- *
- * Lots of stuff, and in retrospect it should probably be more splite up. My
- * excuss is that this grew from a bunch of unit tests for the various
- * "sub-systems". In the end i just called it "rip_mananger".
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <errno.h>
-#include <sys/types.h>
-#if !defined (WIN32)
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-
-#include "filelib.h"
-#include "socklib.h"
-#include "http.h"
-#include "mchar.h"
-#include "findsep.h"
-#include "relaylib.h"
-#include "rip_manager.h"
-#include "ripstream.h"
-#include "threadlib.h"
-#include "debug.h"
-#include "compat.h"
-#include "parse.h"
-
-/******************************************************************************
- * Private functions
- *****************************************************************************/
-static void ripthread(void *bla);
-static error_code start_relay(int content_type);
-static void post_status(int status);
-static error_code start_ripping (RIP_MANAGER_OPTIONS* rmo);
-static void destroy_subsystems();
-
-
-/******************************************************************************
- * Private Vars
- *****************************************************************************/
-static SR_HTTP_HEADER m_http_info;
-static HSOCKET m_sock;
-#if defined (commentout)
-static void (*m_destroy_func)();
-#endif
-static RIP_MANAGER_INFO m_ripinfo; // used for UPDATE callback messages
-//static RIP_MANAGER_OPTIONS m_options; // local copy of the options passed to rip_manager_start()
-static THREAD_HANDLE m_hthread; // rip thread handle
-static void (*m_status_callback)(int message, void *data);
-static BOOL m_ripping = FALSE;
-static u_long m_bytes_ripped;
-static BOOL m_write_data = TRUE; // Should we actually write to a file or not
-static HSEM m_started_sem; // to prevent deadlocks when ripping is stopped before its started.
-
-static char* overwrite_opt_strings[] = {
- "", // UNKNOWN
- "always",
- "never",
- "larger"
-};
-
-/*
- * Needs english type messages, just copy pasted for now
- */
-static char m_error_str[NUM_ERROR_CODES][MAX_ERROR_STR];
-#define SET_ERR_STR(str, code) strncpy(m_error_str[code], str, MAX_ERROR_STR);
-
-void init_error_strings()
-{
- SET_ERR_STR("SR_SUCCESS", 0x00);
- SET_ERR_STR("SR_ERROR_CANT_FIND_TRACK_SEPERATION", 0x01);
- SET_ERR_STR("SR_ERROR_DECODE_FAILURE", 0x02);
- SET_ERR_STR("SR_ERROR_INVALID_URL", 0x03);
- SET_ERR_STR("SR_ERROR_WIN32_INIT_FAILURE", 0x04);
- SET_ERR_STR("Could not connect to the stream. Try checking that the stream is up\n"
- "and that your proxy settings are correct.",0x05);
- SET_ERR_STR("SR_ERROR_CANT_RESOLVE_HOSTNAME", 0x06);
- SET_ERR_STR("SR_ERROR_RECV_FAILED", 0x07);
- SET_ERR_STR("SR_ERROR_SEND_FAILED", 0x08);
- SET_ERR_STR("SR_ERROR_PARSE_FAILURE", 0x09);
- SET_ERR_STR("SR_ERROR_NO_RESPOSE_HEADER", 0x0a);
- SET_ERR_STR("Server returned an unknown error code",0x0b);
- SET_ERR_STR("SR_ERROR_NO_META_INTERVAL", 0x0c);
- SET_ERR_STR("SR_ERROR_INVALID_PARAM", 0x0d);
- SET_ERR_STR("SR_ERROR_NO_HTTP_HEADER", 0x0e);
- SET_ERR_STR("SR_ERROR_CANT_GET_LIVE365_ID", 0x0f);
- SET_ERR_STR("SR_ERROR_CANT_ALLOC_MEMORY", 0x10);
- SET_ERR_STR("SR_ERROR_CANT_FIND_IP_PORT", 0x11);
- SET_ERR_STR("SR_ERROR_CANT_FIND_MEMBERNAME", 0x12);
- SET_ERR_STR("SR_ERROR_CANT_FIND_TRACK_NAME", 0x13);
- SET_ERR_STR("SR_ERROR_NULL_MEMBER_NAME", 0x14);
- SET_ERR_STR("SR_ERROR_CANT_FIND_TIME_TAG", 0x15);
- SET_ERR_STR("SR_ERROR_BUFFER_EMPTY", 0x16);
- SET_ERR_STR("SR_ERROR_BUFFER_FULL", 0x17);
- SET_ERR_STR("SR_ERROR_CANT_INIT_XAUDIO", 0x18);
- SET_ERR_STR("SR_ERROR_BUFFER_TOO_SMALL", 0x19);
- SET_ERR_STR("SR_ERROR_CANT_CREATE_THREAD", 0x1A);
- SET_ERR_STR("SR_ERROR_CANT_FIND_MPEG_HEADER", 0x1B);
- SET_ERR_STR("SR_ERROR_INVALID_METADATA", 0x1C);
- SET_ERR_STR("SR_ERROR_NO_TRACK_INFO", 0x1D);
- SET_ERR_STR("SR_EEROR_CANT_FIND_SUBSTR", 0x1E);
- SET_ERR_STR("SR_ERROR_CANT_BIND_ON_PORT", 0x1F);
- SET_ERR_STR("SR_ERROR_HOST_NOT_CONNECTED", 0x20);
- SET_ERR_STR("HTTP:404 Not Found", 0x21);
- SET_ERR_STR("HTTP:401 Unauthorized", 0x22);
- SET_ERR_STR("HTTP:502 Bad Gateway", 0x23); // Connection Refused
- SET_ERR_STR("SR_ERROR_CANT_CREATE_FILE", 0x24);
- SET_ERR_STR("SR_ERROR_CANT_WRITE_TO_FILE", 0x25);
- SET_ERR_STR("SR_ERROR_CANT_CREATE_DIR", 0x26);
- SET_ERR_STR("HTTP:400 Bad Request ", 0x27); // Server Full
- SET_ERR_STR("SR_ERROR_CANT_SET_SOCKET_OPTIONS", 0x28);
- SET_ERR_STR("SR_ERROR_SOCK_BASE", 0x29);
- SET_ERR_STR("SR_ERROR_INVALID_DIRECTORY", 0x2a);
- SET_ERR_STR("SR_ERROR_FAILED_TO_MOVE_FILE", 0x2b);
- SET_ERR_STR("SR_ERROR_CANT_LOAD_MPGLIB", 0x2c);
- SET_ERR_STR("SR_ERROR_CANT_INIT_MPGLIB", 0x2d);
- SET_ERR_STR("SR_ERROR_CANT_UNLOAD_MPGLIB", 0x2e);
- SET_ERR_STR("SR_ERROR_PCM_BUFFER_TO_SMALL", 0x2f);
- SET_ERR_STR("SR_ERROR_CANT_DECODE_MP3", 0x30);
- SET_ERR_STR("SR_ERROR_SOCKET_CLOSED", 0x31);
- SET_ERR_STR("Due to legal reasons Streamripper can no longer work with Live365(tm).\r\n"
- "See streamripper.sourceforge.net for more on this matter.", 0x32);
- SET_ERR_STR("The maximum number of bytes ripped has been reached", 0x33);
- SET_ERR_STR("SR_ERROR_CANT_WAIT_ON_THREAD", 0x34);
- SET_ERR_STR("SR_ERROR_CANT_CREATE_EVENT", 0x35);
- SET_ERR_STR("SR_ERROR_NOT_SHOUTCAST_STREAM", 0x36);
- SET_ERR_STR("HTTP:407 - Proxy Authentication Required", 0x37);
- SET_ERR_STR("HTTP:403 - Access Forbidden (try changing the UserAgent)", 0x38);
- SET_ERR_STR("The output directory length is too long", 0x39);
- SET_ERR_STR("SR_ERROR_PROGRAM_ERROR", 0x3a);
- SET_ERR_STR("SR_ERROR_TIMEOUT", 0x3b);
- SET_ERR_STR("SR_ERROR_SELECT_FAILED", 0x3c);
- SET_ERR_STR("SR_ERROR_RESERVED_WINDOW_EMPTY", 0x3d);
- SET_ERR_STR("SR_ERROR_CANT_BIND_ON_INTERFACE", 0x3e);
- SET_ERR_STR("SR_ERROR_NO_OGG_PAGES_FOR_RELAY", 0x3f);
- SET_ERR_STR("SR_ERROR_CANT_PARSE_PLS", 0x40);
- SET_ERR_STR("SR_ERROR_CANT_PARSE_M3U", 0x41);
-}
-
-char*
-rip_manager_get_error_str(error_code code)
-{
- if (code > 0 || code < -NUM_ERROR_CODES)
- return NULL;
- return m_error_str[-code];
-}
-
-#if defined (commentout)
-u_short
-rip_mananger_get_relay_port()
-{
- return rmo->relay_port;
-}
-#endif
-
-void
-post_error(int err)
-{
- ERROR_INFO err_info;
- err_info._error_code = err;
- strcpy(err_info.error_str, m_error_str[abs(err)]);
- m_status_callback(RM_ERROR, &err_info);
-}
-
-
-void
-post_status(int status)
-{
- if (status != 0)
- m_ripinfo.status = status;
- m_status_callback(RM_UPDATE, &m_ripinfo);
-}
-
-void
-compose_console_string (TRACK_INFO* ti)
-{
- mchar console_string[SR_MAX_PATH];
- msnprintf (console_string, SR_MAX_PATH, m_S m_(" - ") m_S,
- ti->artist, ti->title);
- string_from_mstring (m_ripinfo.filename, SR_MAX_PATH, console_string,
- CODESET_LOCALE);
-}
-
-/*
- * This is called by ripstream when we get a new track.
- * most logic is handled by filelib_start() so we just
- * make sure there are no bad characters in the name and
- * update via the callback
- */
-error_code
-rip_manager_start_track (TRACK_INFO* ti, int track_count)
-{
- int ret;
-
-#if defined (commmentout)
- /* GCS FIX -- here is where i would compose the incomplete filename */
- char* trackname = ti->raw_metadata;
- debug_printf("rip_manager_start_track: %s\n", trackname);
- if (m_write_data && (ret = filelib_start(trackname)) != SR_SUCCESS) {
- return ret;
- }
-#endif
-
- m_write_data = ti->save_track;
-
- if (m_write_data && (ret = filelib_start (ti)) != SR_SUCCESS) {
- return ret;
- }
-
- m_ripinfo.filesize = 0;
- m_ripinfo.track_count = track_count;
-
- /* Compose the string for the console output */
- compose_console_string (ti);
- m_ripinfo.filename[SR_MAX_PATH-1] = '\0';
- m_status_callback(RM_NEW_TRACK, (void*) m_ripinfo.filename);
- post_status(0);
-
- return SR_SUCCESS;
-}
-
-/* Ok, the end_track()'s function is actually to move
- * tracks out from the incomplete directory. It does
- * get called, but only after the 2nd track is played.
- * the first track is *never* complete.
- */
-error_code
-rip_manager_end_track (RIP_MANAGER_OPTIONS* rmo, TRACK_INFO* ti)
-{
- mchar mfullpath[SR_MAX_PATH];
- char fullpath[SR_MAX_PATH];
-
- if (m_write_data) {
- filelib_end (ti, rmo->overwrite,
- GET_TRUNCATE_DUPS(rmo->flags),
- mfullpath);
- }
- post_status(0);
-
- string_from_mstring (fullpath, SR_MAX_PATH, mfullpath, CODESET_FILESYS);
- m_status_callback (RM_TRACK_DONE, (void*)fullpath);
-
- return SR_SUCCESS;
-}
-
-error_code
-rip_manager_put_data(char *buf, int size)
-{
- if (m_write_data)
- filelib_write_track(buf, size);
-
- m_ripinfo.filesize += size;
- m_bytes_ripped += size;
-
- return SR_SUCCESS;
-}
-
-error_code
-rip_manager_put_raw_data(char *buf, int size)
-{
-#if defined (commentout)
- relaylib_send(buf, size, 1, 0);
-#endif
- filelib_write_show (buf, size);
- return SR_SUCCESS;
-}
-
-
-/*
- * Fires up the relaylib stuff. Most of it is so relaylib
- * knows what to call the stream which is what the 'construct_sc_repsonse()'
- * call is about.
- */
-error_code
-start_relay(int content_type)
-{
- int ret;
-
- if (!relaylib_isrunning())
- if ((ret = relaylib_start()) != SR_SUCCESS)
- return ret;
-
- return SR_SUCCESS;
-}
-
-char *
-client_relay_header_generate (int icy_meta_support)
-{
- SR_HTTP_HEADER info = m_http_info;
- char temp_icyname[MAX_SERVER_LEN];
- int ret;
-
- char *headbuf;
- sprintf(temp_icyname, "[%s] %s", "relay stream", info.icy_name);
- strcpy(info.icy_name, temp_icyname);
-
- headbuf = (char *) malloc(MAX_HEADER_LEN);
- ret = httplib_construct_sc_response(&m_http_info, headbuf, MAX_HEADER_LEN, icy_meta_support);
- if (ret != SR_SUCCESS) {
- headbuf[0] = 0;
- }
-
- return headbuf;
-}
-
-void
-client_relay_header_release (char *ch)
-{
- free (ch);
-}
-
-void
-ripthread (void *input_arg)
-{
- error_code ret;
- RIP_MANAGER_OPTIONS* rmo = (RIP_MANAGER_OPTIONS*) input_arg;
- debug_printf ("ripthread RMO_URL = %s\n", rmo->url);
-
- if ((ret = start_ripping(rmo)) != SR_SUCCESS) {
- debug_printf ("Ripthread did start_ripping()\n");
- threadlib_signal_sem (&m_started_sem);
- post_error(ret);
- goto DONE;
- }
- m_status_callback(RM_STARTED, (void *)NULL);
- post_status(RM_STATUS_BUFFERING);
- debug_printf ("Ripthread did initialization\n");
- threadlib_signal_sem(&m_started_sem);
-
- while (TRUE) {
- ret = ripstream_rip(rmo);
-
- /* If the user told us to stop, well, then we bail */
- if (!m_ripping)
- break;
-
- /*
- * Added 8/4/2001 jc --
- * for max number of MB ripped stuff
- * At the time of writting this, i honestly
- * am not sure i understand what happens
- * when once trys to stop the ripping from the lib and
- * the interface it's a weird combonation of threads
- * wnd locks, etc.. all i know is that this appeared to work
- */
- /* GCS Aug 23, 2003: m_bytes_ripped can still overflow */
- if (m_bytes_ripped/1000000 >= (rmo->maxMB_rip_size) &&
- GET_CHECK_MAX_BYTES (rmo->flags)) {
- socklib_close (&m_sock);
- destroy_subsystems ();
- post_error (SR_ERROR_MAX_BYTES_RIPPED);
- break;
- }
-
- /*
- * If the error was anything but a connection failure
- * then we need to report it and bail
- */
- if (ret == SR_SUCCESS_BUFFERING) {
- post_status(RM_STATUS_BUFFERING);
- }
- else if (ret == SR_ERROR_CANT_DECODE_MP3) {
- post_error(ret);
- continue;
- }
- else if ((ret == SR_ERROR_RECV_FAILED ||
- ret == SR_ERROR_TIMEOUT ||
- ret == SR_ERROR_NO_TRACK_INFO ||
- ret == SR_ERROR_SELECT_FAILED) &&
- GET_AUTO_RECONNECT (rmo->flags)) {
- /* Try to reconnect, if thats what the user wants */
- post_status(RM_STATUS_RECONNECTING);
- while (m_ripping) {
- // Hopefully this solves a lingering bug
- // with auto-reconnects failing to bind to the relay port
- // (a long with other unknown problems)
- // it seems that maybe we need two levels of shutdown and startup
- // functions. init_system, init_rip, shutdown_system and shutdown_rip
- // this would be a shutdown_rip, which only lacks the filelib and socklib
- // shutdowns
- // because filelib needs to keep track of it's file counters, and socklib.. umm..
- // not sure about. no reasdon to i imagine.
- socklib_close(&m_sock);
- if (m_ripinfo.ep) {
- debug_printf ("Close external\n");
- close_external (&m_ripinfo.ep);
- }
- relaylib_shutdown();
- filelib_shutdown();
- ripstream_destroy();
- ret = start_ripping (rmo);
- if (ret == SR_SUCCESS)
- break;
-
- /*
- * Should send a message that we are trying
- * .. or something
- */
- Sleep(1000);
- }
- }
- else if (ret != SR_SUCCESS) {
- destroy_subsystems();
- post_error(ret);
- break;
- }
-
- if (m_ripinfo.filesize > 0)
- post_status(RM_STATUS_RIPPING);
- }
-
- // We get here when there was either a fatal error
- // or we we're not auto-reconnecting and the stream just stopped
- // or when we have been told to stop, via the m_ripping flag
- DONE:
- m_status_callback(RM_DONE, &m_ripinfo);
- m_ripping = FALSE;
- debug_printf ("ripthread() exiting!\n");
-}
-
-
-void
-rip_manager_stop()
-{
- // Make sure this function isn't getting called twice
- if (!m_ripping) {
- debug_printf ("rip_manager_stop() called while not m_ripping\n");
- return;
- }
-
- // Make sure the ripping started before we try to stop
- debug_printf ("Waiting for m_started_sem...\n");
- threadlib_waitfor_sem(&m_started_sem);
- m_ripping = FALSE;
-
- // Causes the code running in the thread to bail
- debug_printf ("Closing m_sock...\n");
- socklib_close(&m_sock);
-
- // Kill external process
- if (m_ripinfo.ep) {
- debug_printf ("Close external\n");
- close_external (&m_ripinfo.ep);
- }
-
- // blocks until everything is ok and closed
- debug_printf ("Waiting for m_hthread to close...\n");
- threadlib_waitforclose(&m_hthread);
- debug_printf ("Destroying subsystems...\n");
- destroy_subsystems();
- debug_printf ("Destroying m_started_sem\n");
- threadlib_destroy_sem(&m_started_sem);
- debug_printf ("Done with rip_manager_stop\n");
-}
-
-void
-destroy_subsystems()
-{
- ripstream_destroy();
-#if defined (commentout)
- if (m_destroy_func) {
- m_destroy_func();
- }
-#endif
- relaylib_shutdown();
- socklib_cleanup();
- filelib_shutdown();
-}
-
-static int
-create_pls_file (RIP_MANAGER_OPTIONS* rmo)
-{
- FILE *fid;
-
- if ('\0' == rmo->relay_ip[0]) {
- fprintf(stderr, "can not determine relaying ip, pass ip to -r \n");
- return -1;
- }
-
- fid = fopen (rmo->pls_file, "w");
-
- if (NULL == fid) {
- fprintf(stderr, "could not create playlist file '%s': %d '%s'\n",
- rmo->pls_file, errno, strerror(errno));
- } else {
- fprintf(fid, "[playlist]\n");
- fprintf(fid, "NumberOfEntries=1\n");
- fprintf(fid, "File1=http://%s:%d\n", rmo->relay_ip, rmo->relay_port);
- fclose(fid);
- }
-
- return 0;
-}
-
-static error_code
-start_ripping (RIP_MANAGER_OPTIONS* rmo)
-{
- error_code ret;
-
- char *pproxy = rmo->proxyurl[0] ? rmo->proxyurl : NULL;
- debug_printf ("start_ripping: checkpoint 1\n");
-
- /* If proxy URL not spec'd on command line (or plugin field),
- check the environment variable */
- if (!pproxy) {
- char const *env_http_proxy = getenv ("http_proxy");
- if (env_http_proxy) {
- strncpy (rmo->proxyurl, env_http_proxy, MAX_URL_LEN);
- }
- }
-
- debug_printf ("start_ripping: checkpoint 2\n");
-
- /* Connect to the stream */
- ret = httplib_sc_connect (&m_sock, rmo->url, pproxy, &m_http_info,
- rmo->useragent, rmo->if_name);
- if (ret != SR_SUCCESS) {
- goto RETURN_ERR;
- }
-
- /* If the icy_name exists, but is empty, set to a bogus name so
- that we can create the directory correctly, etc. */
- if (strlen(m_http_info.icy_name) == 0) {
- strcpy (m_http_info.icy_name, "Streamripper_rips");
- }
-
- /* Set the ripinfo struct from the data we now know about the
- * stream, this info are things like server name, type,
- * bitrate etc.. */
- memset(&m_ripinfo, 0, sizeof(RIP_MANAGER_INFO));
- m_ripinfo.meta_interval = m_http_info.meta_interval;
- m_ripinfo.bitrate = m_http_info.icy_bitrate;
- strcpy(m_ripinfo.streamname, m_http_info.icy_name);
- strcpy(m_ripinfo.server_name, m_http_info.server);
-
- /* Initialize file writing code. */
- ret = filelib_init
- (GET_INDIVIDUAL_TRACKS (rmo->flags),
- GET_COUNT_FILES(rmo->flags),
- rmo->count_start,
- GET_KEEP_INCOMPLETE(rmo->flags),
- GET_SINGLE_FILE_OUTPUT(rmo->flags),
- m_http_info.content_type,
- rmo->output_directory,
- rmo->output_pattern,
- rmo->showfile_pattern,
- GET_SEPERATE_DIRS(rmo->flags),
- GET_DATE_STAMP(rmo->flags),
- m_http_info.icy_name);
- if (ret != SR_SUCCESS)
- goto RETURN_ERR;
-
-#if defined (commentout)
- /* This doesn't seem to be used */
- m_status_callback(RM_OUTPUT_DIR, (void*)filelib_get_output_directory);
-#endif
-
- /* Start up external program to get metadata. */
- m_ripinfo.ep = 0;
- if (GET_EXTERNAL_CMD(rmo->flags)) {
- debug_printf ("Spawn external: %s\n", rmo->ext_cmd);
- m_ripinfo.ep = spawn_external (rmo->ext_cmd);
- if (m_ripinfo.ep) {
- debug_printf ("Spawn external succeeded\n");
- } else {
- debug_printf ("Spawn external failed\n");
- }
- }
-
- /* ripstream is good to go, it knows how to get data, and where
- * it's sending it to
- */
- ripstream_destroy();
- ret = ripstream_init(m_sock,
- GET_MAKE_RELAY(rmo->flags),
- rmo->timeout,
- m_http_info.icy_name,
- rmo->dropcount,
- &rmo->sp_opt,
- m_ripinfo.bitrate,
- m_http_info.meta_interval,
- m_http_info.content_type,
- GET_ADD_ID3V1(rmo->flags),
- GET_ADD_ID3V2(rmo->flags),
- m_ripinfo.ep);
- if (ret != SR_SUCCESS) {
- ripstream_destroy();
- goto RETURN_ERR;
- }
-
- /*
- * tells the socket relay to start, this local wrapper is for
- * setting the respond header, it needs to know server info to
- * give winamp any usfull information about
- * the stream we are relaying.. this just sets the header to
- * something very simulare to what we got from the stream.
- */
- if (GET_MAKE_RELAY (rmo->flags)) {
- u_short new_port = 0;
- ret = relaylib_init(GET_SEARCH_PORTS(rmo->flags),
- rmo->relay_port, rmo->max_port,
- &new_port, rmo->if_name,
- rmo->max_connections, rmo->relay_ip,
- m_http_info.meta_interval != NO_META_INTERVAL);
- if (ret != SR_SUCCESS) {
- goto RETURN_ERR;
- }
-
- rmo->relay_port = new_port;
- start_relay(m_http_info.content_type);
-
- if (0 != rmo->pls_file[0]) {
- create_pls_file (rmo);
- }
- }
- post_status(RM_STATUS_BUFFERING);
- return SR_SUCCESS;
-
-RETURN_ERR:
- socklib_close(&m_sock);
-#if defined (commentout)
- if (m_destroy_func)
- m_destroy_func();
-#endif
- return ret;
-}
-
-error_code
-rip_manager_start (void (*status_callback)(int message, void *data),
- RIP_MANAGER_OPTIONS *rmo)
-{
- int ret = 0;
- if (m_ripping)
- return SR_SUCCESS; // to prevent reentrenty
- m_started_sem = threadlib_create_sem();
-
- m_ripping = TRUE;
-
- register_codesets (&rmo->cs_opt);
-
- if (!rmo)
- return SR_ERROR_INVALID_PARAM;
-
- socklib_init();
-
- init_error_strings();
- m_status_callback = status_callback;
- m_bytes_ripped = 0;
-
- /* Initialize the parsing rules */
- init_metadata_parser (rmo->rules_file);
-
-#if defined (commentout)
- /* Get a local copy of the options passed */
- memcpy(&m_options, options, sizeof(RIP_MANAGER_OPTIONS));
-#endif
-
- /* Start the ripping thread */
- m_ripping = TRUE;
- ret = threadlib_beginthread (&m_hthread, ripthread, (void*) rmo);
- return ret;
-}
-
-/* Winamp plugin needs to get content type */
-int
-rip_manager_get_content_type (void)
-{
- return m_http_info.content_type;
-}
-
-enum OverwriteOpt
-string_to_overwrite_opt (char* str)
-{
- int i;
- for (i = 0; i < 4; i++) {
- if (strcmp(str, overwrite_opt_strings[i]) == 0) {
- return i;
- }
- }
- return OVERWRITE_UNKNOWN;
-}
-
-char*
-overwrite_opt_to_string (enum OverwriteOpt oo)
-{
- return overwrite_opt_strings[(int) oo];
-}
-
-void
-set_rip_manager_options_defaults (RIP_MANAGER_OPTIONS *rmo)
-{
- debug_printf ("- set_rip_manager_options_defaults -\n");
- rmo->url[0] = 0;
- rmo->proxyurl[0] = 0;
- strcpy(rmo->output_directory, "./");
- rmo->output_pattern[0] = 0;
- rmo->showfile_pattern[0] = 0;
- rmo->if_name[0] = 0;
- rmo->rules_file[0] = 0;
- rmo->pls_file[0] = 0;
- rmo->relay_ip[0] = 0;
- rmo->relay_port = 8000;
- rmo->max_port = 18000;
- rmo->max_connections = 1;
- rmo->maxMB_rip_size = 0;
- rmo->flags = OPT_AUTO_RECONNECT |
- OPT_SEPERATE_DIRS |
- OPT_SEARCH_PORTS |
- /* OPT_ADD_ID3V1 | -- removed starting 1.62-beta-2 */
- OPT_ADD_ID3V2 |
- OPT_INDIVIDUAL_TRACKS;
- strcpy(rmo->useragent, "sr-POSIX/" SRVERSION);
-
- // Defaults for splitpoint - times are in ms
- rmo->sp_opt.xs = 1;
- rmo->sp_opt.xs_min_volume = 1;
- rmo->sp_opt.xs_silence_length = 1000;
- rmo->sp_opt.xs_search_window_1 = 6000;
- rmo->sp_opt.xs_search_window_2 = 6000;
- rmo->sp_opt.xs_offset = 0;
- rmo->sp_opt.xs_padding_1 = 300;
- rmo->sp_opt.xs_padding_2 = 300;
-
- /* GCS FIX: What is the difference between this timeout
- and the one used in setsockopt()? */
-#if defined (commentout)
- rmo->timeout = 0;
-#endif
- rmo->timeout = 15;
- rmo->dropcount = 0;
-
- // Defaults for codeset
- memset (&rmo->cs_opt, 0, sizeof(CODESET_OPTIONS));
- set_codesets_default (&rmo->cs_opt);
-
- rmo->count_start = 0;
- rmo->overwrite = OVERWRITE_LARGER;
- rmo->ext_cmd[0] = 0;
-}
diff --git a/xbmc/lib/libshout/rip_manager.h b/xbmc/lib/libshout/rip_manager.h
deleted file mode 100644
index 8965ebb9ab..0000000000
--- a/xbmc/lib/libshout/rip_manager.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/* rip_manager.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __RIP_MANANGER_H__
-#define __RIP_MANANGER_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#include "external.h"
-#include "srtypes.h"
-
-#define SRVERSION "1.62.2"
-
-#if defined (WIN32)
-#define SRPLATFORM "windows"
-#else
-#define SRPLATFORM "unix"
-#endif
-
-#define MAX_STATUS_LEN 256
-#define MAX_STREAMNAME_LEN 1024
-#define MAX_SERVER_LEN 1024
-
-// Messages for status_callback hook in rip_manager_init()
-// used for notifing to client whats going on *DO NOT* call
-// rip_mananger_start or rip_mananger_stop from
-// these functions!!! it will cause a deadlock
-#define RM_UPDATE 0x01 // returns a pointer RIP_MANAGER_INFO struct
-#define RM_ERROR 0x02 // returns the error code
-#define RM_DONE 0x03 // NULL
-#define RM_STARTED 0x04 // NULL
-#define RM_NEW_TRACK 0x05 // Name of the new track
-#define RM_TRACK_DONE 0x06 // pull path of the track completed
-// RM_OUTPUT_DIR is now OBSOLETE
-#define RM_OUTPUT_DIR 0x07 // Full path of the output directory
-
-
-// The following are the possible status values for RIP_MANAGER_INFO
-#define RM_STATUS_BUFFERING 0x01
-#define RM_STATUS_RIPPING 0x02
-#define RM_STATUS_RECONNECTING 0x03
-
-
-typedef struct RIP_MANAGER_INFOst
-{
- char streamname[MAX_STREAMNAME_LEN];
- char server_name[MAX_SERVER_LEN];
- int bitrate;
- int meta_interval;
- char filename[SR_MAX_PATH]; // it's not the filename, it's the trackname
- u_long filesize;
- int status;
- int track_count;
- External_Process* ep;
-} RIP_MANAGER_INFO;
-
-
-// Rip manager flags options
-#define OPT_AUTO_RECONNECT 0x00000001 // reconnect automatticly if dropped
-#define OPT_SEPERATE_DIRS 0x00000002 // create a directory named after the server
-#define OPT_SEARCH_PORTS 0x00000008 // relay server should search for a open port
-#define OPT_MAKE_RELAY 0x00000010 // don't make a relay server
-#define OPT_COUNT_FILES 0x00000020 // add a index counter to the filenames
-#define OPT_OBSOLETE 0x00000040 // Used to be OPT_ADD_ID3, now ignored
-#define OPT_DATE_STAMP 0x00000100 // add a date stamp to the output directory
-#define OPT_CHECK_MAX_BYTES 0x00000200 // use the maxMB_rip_size value to know how much to rip
-#define OPT_KEEP_INCOMPLETE 0x00000400 // overwrite files in the incomplete directory, add counter instead
-#define OPT_SINGLE_FILE_OUTPUT 0x00000800 // enable ripping to single file
-#define OPT_TRUNCATE_DUPS 0x00001000 // truncate file in the incomplete directory already present in complete
-#define OPT_INDIVIDUAL_TRACKS 0x00002000 // should we write the individual tracks?
-#define OPT_EXTERNAL_CMD 0x00004000 // use external command to get metadata?
-#define OPT_ADD_ID3V1 0x00008000 // Add ID3V1
-#define OPT_ADD_ID3V2 0x00010000 // Add ID3V2
-
-#define OPT_FLAG_ISSET(flags, opt) ((flags & opt) > 0)
-// #define OPT_FLAG_SET(flags, opt) (flags =| opt)
-#define OPT_FLAG_SET(flags, opt, val) (val ? (flags |= opt) : (flags &= (~opt)))
-
-#define GET_AUTO_RECONNECT(flags) (OPT_FLAG_ISSET(flags, OPT_AUTO_RECONNECT))
-#define GET_SEPERATE_DIRS(flags) (OPT_FLAG_ISSET(flags, OPT_SEPERATE_DIRS))
-#define GET_SEARCH_PORTS(flags) (OPT_FLAG_ISSET(flags, OPT_SEARCH_PORTS))
-#define GET_MAKE_RELAY(flags) (OPT_FLAG_ISSET(flags, OPT_MAKE_RELAY))
-#define GET_COUNT_FILES(flags) (OPT_FLAG_ISSET(flags, OPT_COUNT_FILES))
-// #define GET_ADD_ID3(flags) (OPT_FLAG_ISSET(flags, OPT_ADD_ID3))
-#define GET_DATE_STAMP(flags) (OPT_FLAG_ISSET(flags, OPT_DATE_STAMP))
-#define GET_CHECK_MAX_BYTES(flags) (OPT_FLAG_ISSET(flags, OPT_CHECK_MAX_BYTES))
-#define GET_KEEP_INCOMPLETE(flags) (OPT_FLAG_ISSET(flags, OPT_KEEP_INCOMPLETE))
-#define GET_SINGLE_FILE_OUTPUT(flags) (OPT_FLAG_ISSET(flags, OPT_SINGLE_FILE_OUTPUT))
-#define GET_TRUNCATE_DUPS(flags) (OPT_FLAG_ISSET(flags, OPT_TRUNCATE_DUPS))
-#define GET_INDIVIDUAL_TRACKS(flags) (OPT_FLAG_ISSET(flags, OPT_INDIVIDUAL_TRACKS))
-#define GET_EXTERNAL_CMD(flags) (OPT_FLAG_ISSET(flags, OPT_EXTERNAL_CMD))
-#define GET_ADD_ID3V1(flags) (OPT_FLAG_ISSET(flags, OPT_ADD_ID3V1))
-#define GET_ADD_ID3V2(flags) (OPT_FLAG_ISSET(flags, OPT_ADD_ID3V2))
-
-#if defined (commentout)
-#define SET_AUTO_RECONNECT(flags) (OPT_FLAG_SET(flags, OPT_AUTO_RECONNECT))
-#define SET_SEPERATE_DIRS(flags) (OPT_FLAG_SET(flags, OPT_SEPERATE_DIRS))
-#define SET_OVER_WRITE_TRACKS(flags) (OPT_FLAG_SET(flags, OPT_OVER_WRITE_TRACKS))
-#define SET_SEARCH_PORTS(flags) (OPT_FLAG_SET(flags, OPT_SEARCH_PORTS))
-#define SET_MAKE_RELAY(flags) (OPT_FLAG_SET(flags, OPT_MAKE_RELAY))
-#define SET_COUNT_FILES(flags) (OPT_FLAG_SET(flags, OPT_COUNT_FILES))
-// #define SET_ADD_ID3(flags) (OPT_FLAG_SET(flags, OPT_ADD_ID3))
-#define SET_DATE_STAMP(flags) (OPT_FLAG_SET(flags, OPT_DATE_STAMP))
-#define SET_CHECK_MAX_BYTES(flags) (OPT_FLAG_SET(flags, OPT_CHECK_MAX_BYTES))
-#define SET_KEEP_INCOMPLETE(flags) (OPT_FLAG_SET(flags, OPT_KEEP_INCOMPLETE))
-#define SET_SINGLE_FILE_OUTPUT(flags) (OPT_FLAG_SET(flags, OPT_SINGLE_FILE_OUTPUT))
-#define SET_TRUNCATE_DUPS(flags) (OPT_FLAG_SET(flags, OPT_TRUNCATE_DUPS))
-#define SET_INDIVIDUAL_TRACKS(flags) (OPT_FLAG_SET(flags, OPT_INDIVIDUAL_TRACKS))
-#define SET_EXTERNAL_CMD(flags) (OPT_FLAG_SET(flags, OPT_EXTERNAL_CMD))
-#define SET_ADD_ID3V1(flags) (OPT_FLAG_SET(flags, OPT_ADD_ID3V1))
-#define SET_ADD_ID3V2(flags) (OPT_FLAG_SET(flags, OPT_ADD_ID3V2))
-#endif
-
-typedef struct RIP_MANAGER_OPTIONSst
-{
- char url[MAX_URL_LEN]; // url of the stream to connect to
- char proxyurl[MAX_URL_LEN]; // url of a http proxy server,
- // '\0' otherwise
- char output_directory[SR_MAX_PATH]; // base directory to output files too
- char output_pattern[SR_MAX_PATH]; // filename pattern when ripping
- // with splitting
- char showfile_pattern[SR_MAX_PATH]; // filename base when ripping to
- // single file without splitting
- char if_name[SR_MAX_PATH]; // local interface to use
- char rules_file[SR_MAX_PATH]; // file that holds rules for
- // parsing metadata
- char pls_file[SR_MAX_PATH]; // optional, where to create a
- // rely .pls file
- char relay_ip[SR_MAX_PATH]; // optional, ip to bind relaying
- // socket to
- u_short relay_port; // port to use for the relay server
- // GCS 3/30/07 change to u_short
- u_short max_port; // highest port the relay server
- // can look if it needs to search
- int max_connections; // max number of connections
- // to relay stream
- u_long maxMB_rip_size; // max number of megabytes that
- // can by writen out before we stop
- u_long flags; // all booleans logically OR'd
- // together (see above)
- char useragent[MAX_USERAGENT_STR]; // optional, use a different useragent
- SPLITPOINT_OPTIONS sp_opt; // options for splitpoint rules
- int timeout; // timeout, in seconds, before a
- // stalled connection is forcefully
- // closed
- int dropcount; // number of tracks at beginning
- // of connection to always ignore
- CODESET_OPTIONS cs_opt; // which codeset should i use?
- int count_start; // which number to start counting?
- enum OverwriteOpt overwrite; // overwrite file in complete?
- char ext_cmd[SR_MAX_PATH]; // cmd to spawn for external metadata
-
-} RIP_MANAGER_OPTIONS;
-
-typedef struct ERROR_INFOst
-{
- char error_str[MAX_ERROR_STR];
- error_code _error_code;
-} ERROR_INFO;
-
-
-/* Public functions */
-char *rip_manager_get_error_str(int code);
-//u_short rip_mananger_get_relay_port();
-void set_rip_manager_options_defaults (RIP_MANAGER_OPTIONS *m_opt);
-error_code rip_manager_start (void (*status_callback)(int message, void *data),
- RIP_MANAGER_OPTIONS *options);
-void rip_manager_stop();
-error_code rip_manager_start_track (TRACK_INFO* ti, int track_count);
-error_code rip_manager_end_track(RIP_MANAGER_OPTIONS* rmo, TRACK_INFO* ti);
-error_code rip_manager_put_data(char *buf, int size);
-error_code rip_manager_put_raw_data(char *buf, int size);
-
-char *client_relay_header_generate (int icy_meta_support);
-void client_relay_header_release (char *ch);
-
-char* overwrite_opt_to_string (enum OverwriteOpt oo);
-enum OverwriteOpt string_to_overwrite_opt (char* str);
-int rip_manager_get_content_type (void);
-
-#ifdef __cplusplus
-}
-#endif
-#endif //__RIP_MANANGER_H__
diff --git a/xbmc/lib/libshout/ripaac.c b/xbmc/lib/libshout/ripaac.c
deleted file mode 100644
index 2d4db5409e..0000000000
--- a/xbmc/lib/libshout/ripaac.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/* ripaac.c
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * This file is adapted from faad.c of the ffmpeg project.
- * Copyright (c) 2003 Zdenek Kabelac.
- * Copyright (c) 2004 Thomas Raivio.
- */
-#include "srconfig.h"
-
-#if defined (HAVE_FAAD)
-#if defined (commentout)
-
-#include "faad.h"
-
-typedef struct {
- void* handle; /* dlopen handle */
- void* faac_handle; /* FAAD library handle */
- int sample_size;
- int init;
-
- /* faad calls */
- faacDecHandle (*faacDecOpen)(void);
- faacDecConfigurationPtr (*faacDecGetCurrentConfiguration)(faacDecHandle hDecoder);
-
- void (*faacDecClose)(faacDecHandle hDecoder);
-
-} FAACContext;
-
-static const unsigned long faac_srates[] =
-{
- 96000, 88200, 64000, 48000, 44100, 32000,
- 24000, 22050, 16000, 12000, 11025, 8000
-};
-
-static int faac_init_mp4 (AVCodecContext *avctx)
-{
- FAACContext *s = (FAACContext *) avctx->priv_data;
- unsigned long samplerate;
-#ifndef FAAD2_VERSION
- unsigned long channels;
-#else
- unsigned char channels;
-#endif
- int r = 0;
-
- if (avctx->extradata){
- r = s->faacDecInit2(s->faac_handle, (uint8_t*) avctx->extradata,
- avctx->extradata_size,
- &samplerate, &channels);
- if (r < 0){
- av_log(avctx, AV_LOG_ERROR,
- "faacDecInit2 failed r:%d sr:%ld ch:%ld s:%d\n",
- r, samplerate, (long)channels, avctx->extradata_size);
- } else {
- avctx->sample_rate = samplerate;
- avctx->channels = channels;
- s->init = 1;
- }
- }
-
- return r;
-}
-
-static int faac_decode_frame(AVCodecContext *avctx,
- void *data, int *data_size,
- uint8_t *buf, int buf_size)
-{
- FAACContext *s = (FAACContext *) avctx->priv_data;
-#ifndef FAAD2_VERSION
- unsigned long bytesconsumed;
- short *sample_buffer = NULL;
- unsigned long samples;
- int out;
-#else
- faacDecFrameInfo frame_info;
- void *out;
-#endif
- if(buf_size == 0)
- return 0;
-#ifndef FAAD2_VERSION
- out = s->faacDecDecode(s->faac_handle,
- (unsigned char*)buf,
- &bytesconsumed,
- data,
- &samples);
- samples *= s->sample_size;
- if (data_size)
- *data_size = samples;
- return (buf_size < (int)bytesconsumed)
- ? buf_size : (int)bytesconsumed;
-#else
-
- if(!s->init){
- unsigned long srate;
- unsigned char channels;
- int r = s->faacDecInit(s->faac_handle, buf, buf_size, &srate, &channels);
- if(r < 0){
- av_log(avctx, AV_LOG_ERROR, "faac: codec init failed: %s\n",
- s->faacDecGetErrorMessage(frame_info.error));
- return -1;
- }
- avctx->sample_rate = srate;
- avctx->channels = channels;
- s->init = 1;
- }
-
- out = s->faacDecDecode(s->faac_handle, &frame_info, (unsigned char*)buf, (unsigned long)buf_size);
-
- if (frame_info.error > 0) {
- av_log(avctx, AV_LOG_ERROR, "faac: frame decoding failed: %s\n",
- s->faacDecGetErrorMessage(frame_info.error));
- return -1;
- }
-
- frame_info.samples *= s->sample_size;
- memcpy(data, out, frame_info.samples); // CHECKME - can we cheat this one
-
- if (data_size)
- *data_size = frame_info.samples;
-
- return (buf_size < (int)frame_info.bytesconsumed)
- ? buf_size : (int)frame_info.bytesconsumed;
-#endif
-}
-
-static int faac_decode_end(AVCodecContext *avctx)
-{
- FAACContext *s = (FAACContext *) avctx->priv_data;
-
- if (s->faacDecClose)
- s->faacDecClose(s->faac_handle);
-
- dlclose(s->handle);
- return 0;
-}
-
-static int faac_decode_init(AVCodecContext *avctx)
-{
- FAACContext *s = (FAACContext *) avctx->priv_data;
- faacDecConfigurationPtr faac_cfg;
-
-#ifdef CONFIG_FAADBIN
- const char* err = 0;
-
- s->handle = dlopen(libfaadname, RTLD_LAZY);
- if (!s->handle)
- {
- av_log(avctx, AV_LOG_ERROR, "FAAD library: %s could not be opened! \n%s\n",
- libfaadname, dlerror());
- return -1;
- }
-#define dfaac(a, b) \
- do { static const char* n = "faacDec" #a; \
- if ((s->faacDec ## a = b dlsym( s->handle, n )) == NULL) { err = n; break; } } while(0)
- for(;;) {
-#else /* !CONFIG_FAADBIN */
-#define dfaac(a, b) s->faacDec ## a = faacDec ## a
-#endif /* CONFIG_FAADBIN */
-
- // resolve all needed function calls
- dfaac(Open, (faacDecHandle FAADAPI (*)(void)));
- dfaac(GetCurrentConfiguration, (faacDecConfigurationPtr
- FAADAPI (*)(faacDecHandle)));
-#ifndef FAAD2_VERSION
- dfaac(SetConfiguration, (int FAADAPI (*)(faacDecHandle,
- faacDecConfigurationPtr)));
-
- dfaac(Init, (int FAADAPI (*)(faacDecHandle, unsigned char*,
- unsigned long*, unsigned long*)));
- dfaac(Init2, (int FAADAPI (*)(faacDecHandle, unsigned char*,
- unsigned long, unsigned long*,
- unsigned long*)));
- dfaac(Close, (void FAADAPI (*)(faacDecHandle hDecoder)));
- dfaac(Decode, (int FAADAPI (*)(faacDecHandle, unsigned char*,
- unsigned long*, short*, unsigned long*)));
-#else
- dfaac(SetConfiguration, (unsigned char FAADAPI (*)(faacDecHandle,
- faacDecConfigurationPtr)));
- dfaac(Init, (long FAADAPI (*)(faacDecHandle, unsigned char*,
- unsigned long, unsigned long*, unsigned char*)));
- dfaac(Init2, (char FAADAPI (*)(faacDecHandle, unsigned char*,
- unsigned long, unsigned long*,
- unsigned char*)));
- dfaac(Decode, (void *FAADAPI (*)(faacDecHandle, faacDecFrameInfo*,
- unsigned char*, unsigned long)));
- dfaac(GetErrorMessage, (char* FAADAPI (*)(unsigned char)));
-#endif
-#undef dfacc
-
-#ifdef CONFIG_FAADBIN
- break;
- }
- if (err) {
- dlclose(s->handle);
- av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot resolve %s in %s!\n",
- err, libfaadname);
- return -1;
- }
-#endif
-
- s->faac_handle = s->faacDecOpen();
- if (!s->faac_handle) {
- av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot create handler!\n");
- faac_decode_end(avctx);
- return -1;
- }
-
-
- faac_cfg = s->faacDecGetCurrentConfiguration(s->faac_handle);
-
- if (faac_cfg) {
- switch (avctx->bits_per_sample) {
- case 8: av_log(avctx, AV_LOG_ERROR, "FAADlib unsupported bps %d\n", avctx->bits_per_sample); break;
- default:
- case 16:
-#ifdef FAAD2_VERSION
- faac_cfg->outputFormat = FAAD_FMT_16BIT;
-#endif
- s->sample_size = 2;
- break;
- case 24:
-#ifdef FAAD2_VERSION
- faac_cfg->outputFormat = FAAD_FMT_24BIT;
-#endif
- s->sample_size = 3;
- break;
- case 32:
-#ifdef FAAD2_VERSION
- faac_cfg->outputFormat = FAAD_FMT_32BIT;
-#endif
- s->sample_size = 4;
- break;
- }
-
- faac_cfg->defSampleRate = (!avctx->sample_rate) ? 44100 : avctx->sample_rate;
- faac_cfg->defObjectType = LC;
- }
-
- s->faacDecSetConfiguration(s->faac_handle, faac_cfg);
-
- faac_init_mp4(avctx);
-
- return 0;
-}
-#endif /* commentout */
-
-#endif /* HAVE_FAAD */
diff --git a/xbmc/lib/libshout/ripogg.c b/xbmc/lib/libshout/ripogg.c
deleted file mode 100644
index 83fce2b035..0000000000
--- a/xbmc/lib/libshout/ripogg.c
+++ /dev/null
@@ -1,834 +0,0 @@
-/* ripogg.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * This file is adapted from ogginfo.c of the vorbis-tools project.
- * Copyright 2002 Michael Smith <msmith@xiph.org>
- * Licensed under the GNU GPL, distributed with this program.
- */
-#include "srconfig.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <stdarg.h>
-#include "cbuf2.h"
-#include "ripogg.h"
-#include "utf8.h"
-#include "list.h"
-#include "debug.h"
-#include "mchar.h"
-
-#if (HAVE_OGG_VORBIS)
-#include <ogg/ogg.h>
-#ifdef _LINUX
-#include <vorbis/codec.h>
-#else
-#include <ogg/codec.h>
-#endif
-#include <locale.h>
-
-
-#define CHUNK 4500
-// #define CHUNK 1
-
-#define _(a) (a)
-
-
-struct vorbis_release {
- char *vendor_string;
- char *desc;
-} releases[] = {
- {"Xiphophorus libVorbis I 20000508", "1.0 beta 1 or beta 2"},
- {"Xiphophorus libVorbis I 20001031", "1.0 beta 3"},
- {"Xiphophorus libVorbis I 20010225", "1.0 beta 4"},
- {"Xiphophorus libVorbis I 20010615", "1.0 rc1"},
- {"Xiphophorus libVorbis I 20010813", "1.0 rc2"},
- {"Xiphophorus libVorbis I 20011217", "1.0 rc3"},
- {"Xiphophorus libVorbis I 20011231", "1.0 rc3"},
- {"Xiph.Org libVorbis I 20020717", "1.0"},
- {"Xiph.Org libVorbis I 20030909", "1.0.1"},
- {NULL, NULL},
-};
-
-/* TODO:
- *
- * - detect violations of muxing constraints
- * - detect granulepos 'gaps' (possibly vorbis-specific). (seperate from
- * serial-number gaps)
- */
-typedef struct _stream_processor {
- void (*process_page)(struct _stream_processor *, ogg_page *);
- void (*process_end)(struct _stream_processor *);
- int isillegal;
- int constraint_violated;
- int shownillegal;
- int isnew;
- long seqno;
- int lostseq;
-
- int start;
- int end;
-
- int num;
- char *type;
-
- ogg_uint32_t serial; /* must be 32 bit unsigned */
- ogg_stream_state os;
- void *data;
-} stream_processor;
-
-typedef struct {
- stream_processor *streams;
- int allocated;
- int used;
-
- int in_headers;
-} stream_set;
-
-typedef struct {
- vorbis_info vi;
- vorbis_comment vc;
-
- ogg_int64_t bytes;
- ogg_int64_t lastgranulepos;
- ogg_int64_t firstgranulepos;
-
- int doneheaders;
-} misc_vorbis_info;
-
-
-/*****************************************************************************
- * Private Vars
- *****************************************************************************/
-static int printinfo = 1;
-static int printwarn = 1;
-//static int verbose = 1;
-static int flawed;
-
-static ogg_sync_state ogg_sync;
-static ogg_page page;
-static stream_processor stream;
-static unsigned char* ogg_curr_header;
-static int ogg_curr_header_len;
-
-#define CONSTRAINT_PAGE_AFTER_EOS 1
-#define CONSTRAINT_MUXING_VIOLATED 2
-
-
-/*****************************************************************************
- * Functions
- *****************************************************************************/
-static stream_set *create_stream_set(void) {
- stream_set *set = calloc(1, sizeof(stream_set));
-
- set->streams = calloc(5, sizeof(stream_processor));
- set->allocated = 5;
- set->used = 0;
-
- return set;
-}
-
-static void info(char *format, ...)
-{
- va_list ap;
-
- if(!printinfo)
- return;
-
- va_start(ap, format);
- vfprintf(stdout, format, ap);
- va_end(ap);
-}
-
-static void warn(char *format, ...)
-{
- va_list ap;
-
- flawed = 1;
- if(!printwarn)
- return;
-
- va_start(ap, format);
- vfprintf(stdout, format, ap);
- va_end(ap);
-}
-
-/* Return 1 if the page is a header page */
-static int
-vorbis_process (stream_processor *stream, ogg_page *page, TRACK_INFO* ti)
-{
- ogg_packet packet;
- misc_vorbis_info *inf = stream->data;
- int i, header=0;
- int k;
-
- ogg_stream_pagein(&stream->os, page);
- if (inf->doneheaders < 3)
- header = 1;
-
- while (ogg_stream_packetout(&stream->os, &packet) > 0) {
- if (inf->doneheaders < 3) {
- if (vorbis_synthesis_headerin(&inf->vi, &inf->vc, &packet) < 0) {
- warn(_("Warning: Could not decode vorbis header "
- "packet - invalid vorbis stream (%d)\n"), stream->num);
- continue;
- }
- inf->doneheaders++;
- if (inf->doneheaders == 3) {
- if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1)
- warn(_("Warning: Vorbis stream %d does not have headers "
- "correctly framed. Terminal header page contains "
- "additional packets or has non-zero granulepos\n"),
- stream->num);
- debug_printf("Vorbis headers parsed for stream %d, "
- "information follows...\n", stream->num);
-
- debug_printf("Version: %d\n", inf->vi.version);
- k = 0;
- while(releases[k].vendor_string) {
- if(!strcmp(inf->vc.vendor, releases[k].vendor_string)) {
- debug_printf("Vendor: %s (%s)\n", inf->vc.vendor,
- releases[k].desc);
- break;
- }
- k++;
- }
- if(!releases[k].vendor_string)
- debug_printf("Vendor: %s\n", inf->vc.vendor);
- debug_printf("Channels: %d\n", inf->vi.channels);
- debug_printf("Rate: %ld\n\n", inf->vi.rate);
-
- if(inf->vi.bitrate_nominal > 0)
- debug_printf("Nominal bitrate: %f kb/s\n",
- (double)inf->vi.bitrate_nominal / 1000.0);
- else
- debug_printf("Nominal bitrate not set\n");
-
- if(inf->vi.bitrate_upper > 0)
- debug_printf("Upper bitrate: %f kb/s\n",
- (double)inf->vi.bitrate_upper / 1000.0);
- else
- debug_printf("Upper bitrate not set\n");
-
- if(inf->vi.bitrate_lower > 0)
- debug_printf("Lower bitrate: %f kb/s\n",
- (double)inf->vi.bitrate_lower / 1000.0);
- else
- debug_printf("Lower bitrate not set\n");
-
- if(inf->vc.comments > 0)
- debug_printf ("User comments section follows...\n");
-
- for(i=0; i < inf->vc.comments; i++) {
- char *sep = strchr(inf->vc.user_comments[i], '=');
- char *decoded;
- int j;
- int broken = 0;
- unsigned char *val;
- int bytes;
- int remaining;
-
- if(sep == NULL) {
- warn(_("Warning: Comment %d in stream %d is invalidly "
- "formatted, does not contain '=': \"%s\"\n"),
- i, stream->num, inf->vc.user_comments[i]);
- continue;
- }
-
- for(j=0; j < sep-inf->vc.user_comments[i]; j++) {
- if(inf->vc.user_comments[i][j] < 0x20 ||
- inf->vc.user_comments[i][j] > 0x7D) {
- warn(_("Warning: Invalid comment fieldname in "
- "comment %d (stream %d): \"%s\"\n"),
- i, stream->num, inf->vc.user_comments[i]);
- broken = 1;
- break;
- }
- }
-
- if(broken)
- continue;
-
- val = inf->vc.user_comments[i];
-
- j = sep-inf->vc.user_comments[i]+1;
- while(j < inf->vc.comment_lengths[i])
- {
- remaining = inf->vc.comment_lengths[i] - j;
- if((val[j] & 0x80) == 0)
- bytes = 1;
- else if((val[j] & 0x40) == 0x40) {
- if((val[j] & 0x20) == 0)
- bytes = 2;
- else if((val[j] & 0x10) == 0)
- bytes = 3;
- else if((val[j] & 0x08) == 0)
- bytes = 4;
- else if((val[j] & 0x04) == 0)
- bytes = 5;
- else if((val[j] & 0x02) == 0)
- bytes = 6;
- else {
- warn(_("Warning: Illegal UTF-8 sequence in "
- "comment %d (stream %d): length "
- "marker wrong\n"),
- i, stream->num);
- broken = 1;
- break;
- }
- }
- else {
- warn(_("Warning: Illegal UTF-8 sequence in comment "
- "%d (stream %d): length marker wrong\n"),
- i, stream->num);
- broken = 1;
- break;
- }
-
- if(bytes > remaining) {
- warn(_("Warning: Illegal UTF-8 sequence in comment "
- "%d (stream %d): too few bytes\n"),
- i, stream->num);
- broken = 1;
- break;
- }
-
- switch(bytes) {
- case 1:
- /* No more checks needed */
- break;
- case 2:
- if((val[j+1] & 0xC0) != 0x80)
- broken = 1;
- if((val[j] & 0xFE) == 0xC0)
- broken = 1;
- break;
- case 3:
- if(!((val[j] == 0xE0 && val[j+1] >= 0xA0 &&
- val[j+1] <= 0xBF &&
- (val[j+2] & 0xC0) == 0x80) ||
- (val[j] >= 0xE1 && val[j] <= 0xEC &&
- (val[j+1] & 0xC0) == 0x80 &&
- (val[j+2] & 0xC0) == 0x80) ||
- (val[j] == 0xED && val[j+1] >= 0x80 &&
- val[j+1] <= 0x9F &&
- (val[j+2] & 0xC0) == 0x80) ||
- (val[j] >= 0xEE && val[j] <= 0xEF &&
- (val[j+1] & 0xC0) == 0x80 &&
- (val[j+2] & 0xC0) == 0x80)))
- broken = 1;
- if(val[j] == 0xE0 && (val[j+1] & 0xE0) == 0x80)
- broken = 1;
- break;
- case 4:
- if(!((val[j] == 0xF0 && val[j+1] >= 0x90 &&
- val[j+1] <= 0xBF &&
- (val[j+2] & 0xC0) == 0x80 &&
- (val[j+3] & 0xC0) == 0x80) ||
- (val[j] >= 0xF1 && val[j] <= 0xF3 &&
- (val[j+1] & 0xC0) == 0x80 &&
- (val[j+2] & 0xC0) == 0x80 &&
- (val[j+3] & 0xC0) == 0x80) ||
- (val[j] == 0xF4 && val[j+1] >= 0x80 &&
- val[j+1] <= 0x8F &&
- (val[j+2] & 0xC0) == 0x80 &&
- (val[j+3] & 0xC0) == 0x80)))
- broken = 1;
- if(val[j] == 0xF0 && (val[j+1] & 0xF0) == 0x80)
- broken = 1;
- break;
- /* 5 and 6 aren't actually allowed at this point*/
- case 5:
- broken = 1;
- break;
- case 6:
- broken = 1;
- break;
- }
-
- if(broken) {
- warn(_("Warning: Illegal UTF-8 sequence in comment "
- "%d (stream %d): invalid sequence\n"),
- i, stream->num);
- broken = 1;
- break;
- }
-
- j += bytes;
- }
-
- if(!broken) {
- if(utf8_decode(sep+1, &decoded) < 0) {
- warn(_("Warning: Failure in utf8 decoder. This "
- "should be impossible\n"));
- continue;
- }
- *sep = 0;
- debug_printf ("\t%s=%s\n",
- inf->vc.user_comments[i], decoded);
-
- /* GCS FIX: Need case insensitive compare */
- if (!strcmp(inf->vc.user_comments[i],"artist")
- || !strcmp(inf->vc.user_comments[i],"ARTIST")
- || !strcmp(inf->vc.user_comments[i],"Artist")) {
- /* GCS FIX: This is a bit funky, maybe I need
- to get rid of the ogg built-in utf8 decoder */
- mstring_from_string (ti->artist, MAX_TRACK_LEN,
- decoded, CODESET_LOCALE);
- } else if (!strcmp(inf->vc.user_comments[i],"title")
- || !strcmp(inf->vc.user_comments[i],"TITLE")
- || !strcmp(inf->vc.user_comments[i],"Title")) {
- /* GCS FIX: This is a bit funky, maybe I need
- to get rid of the ogg built-in utf8 decoder */
- mstring_from_string (ti->title, MAX_TRACK_LEN,
- decoded, CODESET_LOCALE);
- ti->have_track_info = 1;
- } else if (!strcmp(inf->vc.user_comments[i],"album")
- || !strcmp(inf->vc.user_comments[i],"ALBUM")
- || !strcmp(inf->vc.user_comments[i],"Album")) {
- /* GCS FIX: This is a bit funky, maybe I need
- to get rid of the ogg built-in utf8 decoder */
- mstring_from_string (ti->album, MAX_TRACK_LEN,
- decoded, CODESET_LOCALE);
- } else if (!strcmp(inf->vc.user_comments[i],"tracknumber")
- || !strcmp(inf->vc.user_comments[i],"TRACKNUMBER")
- || !strcmp(inf->vc.user_comments[i],"Tracknumber")) {
- /* GCS FIX: This is a bit funky, maybe I need
- to get rid of the ogg built-in utf8 decoder */
- mstring_from_string (ti->track, MAX_TRACK_LEN,
- decoded, CODESET_LOCALE);
- }
- free(decoded);
- }
- }
- }
- }
- }
-
- if(!header) {
- ogg_int64_t gp = ogg_page_granulepos(page);
- if(gp > 0) {
- if(gp < inf->lastgranulepos)
-#ifdef _WIN32
- warn(_("Warning: granulepos in stream %d decreases from %I64d to %I64d" ),
- stream->num, inf->lastgranulepos, gp);
-#else
- warn(_("Warning: granulepos in stream %d decreases from %lld to %lld" ),
- stream->num, inf->lastgranulepos, gp);
-#endif
- inf->lastgranulepos = gp;
- }
- else {
- warn(_("Negative granulepos on vorbis stream outside of headers. This file was created by a buggy encoder\n"));
- }
- if(inf->firstgranulepos < 0) { /* Not set yet */
- }
- inf->bytes += page->header_len + page->body_len;
- }
- return header;
-}
-
-static void
-vorbis_end(stream_processor *stream)
-{
- misc_vorbis_info *inf = stream->data;
- long minutes, seconds;
- double bitrate, time;
-
- /* This should be lastgranulepos - startgranulepos, or something like that*/
- time = (double)inf->lastgranulepos / inf->vi.rate;
- minutes = (long)time / 60;
- seconds = (long)time - minutes*60;
- bitrate = inf->bytes*8 / time / 1000.0;
-
-#ifdef _WIN32
- debug_printf ("Vorbis stream %d:\n"
- "\tTotal data length: %I64d bytes\n"
- "\tPlayback length: %ldm:%02lds\n"
- "\tAverage bitrate: %f kbps\n",
- stream->num,inf->bytes, minutes, seconds, bitrate);
-#else
- debug_printf ("Vorbis stream %d:\n"
- "\tTotal data length: %lld bytes\n"
- "\tPlayback length: %ldm:%02lds\n"
- "\tAverage bitrate: %f kbps\n",
- stream->num,inf->bytes, minutes, seconds, bitrate);
-#endif
-
- vorbis_comment_clear(&inf->vc);
- vorbis_info_clear(&inf->vi);
-
- free(stream->data);
-}
-
-static void process_null(stream_processor *stream, ogg_page *page)
-{
- /* This is for invalid streams. */
-}
-
-static void process_other(stream_processor *stream, ogg_page *page )
-{
- ogg_packet packet;
-
- ogg_stream_pagein(&stream->os, page);
-
- while(ogg_stream_packetout(&stream->os, &packet) > 0) {
- /* Should we do anything here? Currently, we don't */
- }
-}
-
-static void free_stream_set(stream_set *set)
-{
- int i;
- for(i=0; i < set->used; i++) {
- if(!set->streams[i].end) {
- warn(_("Warning: EOS not set on stream %d\n"),
- set->streams[i].num);
- if(set->streams[i].process_end)
- set->streams[i].process_end(&set->streams[i]);
- }
- ogg_stream_clear(&set->streams[i].os);
- }
-
- free(set->streams);
- free(set);
-}
-
-static int streams_open(stream_set *set)
-{
- int i;
- int res=0;
- for(i=0; i < set->used; i++) {
- if(!set->streams[i].end)
- res++;
- }
-
- return res;
-}
-
-static void null_start(stream_processor *stream)
-{
- stream->process_end = NULL;
- stream->type = "invalid";
- stream->process_page = process_null;
-}
-
-static void other_start(stream_processor *stream, char *type)
-{
- if(type)
- stream->type = type;
- else
- stream->type = "unknown";
- stream->process_page = process_other;
- stream->process_end = NULL;
-}
-
-static void vorbis_start(stream_processor *stream)
-{
- misc_vorbis_info *info;
-
- stream->type = "vorbis";
- stream->process_page = vorbis_process;
- stream->process_end = vorbis_end;
-
- stream->data = calloc(1, sizeof(misc_vorbis_info));
-
- info = stream->data;
-
- vorbis_comment_init(&info->vc);
- vorbis_info_init(&info->vi);
-}
-
-static stream_processor *find_stream_processor(stream_set *set, ogg_page *page)
-{
- ogg_uint32_t serial = ogg_page_serialno(page);
- int i, found = 0;
- int invalid = 0;
- int constraint = 0;
- stream_processor *stream;
-
- for(i=0; i < set->used; i++) {
- if(serial == set->streams[i].serial) {
- /* We have a match! */
- found = 1;
- stream = &(set->streams[i]);
-
- set->in_headers = 0;
- /* if we have detected EOS, then this can't occur here. */
- if(stream->end) {
- stream->isillegal = 1;
- stream->constraint_violated = CONSTRAINT_PAGE_AFTER_EOS;
- return stream;
- }
-
- stream->isnew = 0;
- stream->start = ogg_page_bos(page);
- stream->end = ogg_page_eos(page);
- stream->serial = serial;
- return stream;
- }
- }
-
- /* If there are streams open, and we've reached the end of the
- * headers, then we can't be starting a new stream.
- * XXX: might this sometimes catch ok streams if EOS flag is missing,
- * but the stream is otherwise ok?
- */
- if(streams_open(set) && !set->in_headers) {
- constraint = CONSTRAINT_MUXING_VIOLATED;
- invalid = 1;
- }
-
- set->in_headers = 1;
-
- if(set->allocated < set->used)
- stream = &set->streams[set->used];
- else {
- set->allocated += 5;
- set->streams = realloc(set->streams, sizeof(stream_processor)*
- set->allocated);
- stream = &set->streams[set->used];
- }
- set->used++;
- stream->num = set->used; /* We count from 1 */
-
- stream->isnew = 1;
- stream->isillegal = invalid;
- stream->constraint_violated = constraint;
-
- {
- int res;
- ogg_packet packet;
-
- /* We end up processing the header page twice, but that's ok. */
- ogg_stream_init(&stream->os, serial);
- ogg_stream_pagein(&stream->os, page);
- res = ogg_stream_packetout(&stream->os, &packet);
- if(res <= 0) {
- warn(_("Warning: Invalid header page, no packet found\n"));
- null_start(stream);
- }
- else if(packet.bytes >= 7 && memcmp(packet.packet, "\001vorbis", 7)==0)
- vorbis_start(stream);
- else if(packet.bytes >= 8 && memcmp(packet.packet, "OggMIDI\0", 8)==0)
- other_start(stream, "MIDI");
- else
- other_start(stream, NULL);
-
- res = ogg_stream_packetout(&stream->os, &packet);
- if(res > 0) {
- warn(_("Warning: Invalid header page in stream %d, "
- "contains multiple packets\n"), stream->num);
- }
-
- /* re-init, ready for processing */
- ogg_stream_clear(&stream->os);
- ogg_stream_init(&stream->os, serial);
- }
-
- stream->start = ogg_page_bos(page);
- stream->end = ogg_page_eos(page);
- stream->serial = serial;
-
- if(stream->serial == 0 || stream->serial == -1) {
- debug_printf ("Note: Stream %d has serial number %d, which is legal but may "
- "cause problems with some tools.", stream->num, stream->serial);
- }
-
- return stream;
-}
-
-void
-rip_ogg_process_chunk (LIST* page_list, const char* buf, u_long size,
- TRACK_INFO* ti)
-{
- OGG_PAGE_LIST* ol;
- int header;
- int ret;
- char *buffer;
- // static ogg_int64_t written = 0;
- // static unsigned int written = 0;
- // static int ogg_page2 = 0;
-
- INIT_LIST_HEAD (page_list);
-
- debug_printf ("-- rip_ogg_process_chunk (%d)\n", size);
-
- buffer = ogg_sync_buffer (&ogg_sync, size);
- memcpy (buffer, buf, size);
- ogg_sync_wrote (&ogg_sync, size);
-
- do {
- switch (ret = ogg_sync_pageout (&ogg_sync, &page)) {
- case -1:
- /* -1 if we were not properly synced and had to skip some bytes */
- debug_printf ("Hole in ogg, skipping bytes\n");
- break;
- case 0:
- /* 0 if we need more data to verify a page */
- debug_printf ("Ogg needs more data\n");
- break;
- case 1:
- /* 1 if we have a page */
- debug_printf ("Found an ogg page!\n");
-
- /* Do stuff needed for decoding vorbis */
- if (ogg_page_bos (&page)) {
- int rc;
- ogg_packet packet;
- ogg_stream_init (&stream.os, ogg_page_serialno (&page));
- ogg_stream_pagein (&stream.os, &page);
- rc = ogg_stream_packetout(&stream.os, &packet);
- if (rc <= 0) {
- printf ("Warning: Invalid header page, no packet found\n");
- // null_start (&stream);
- exit (1);
- } else if (packet.bytes >= 7
- && memcmp(packet.packet, "\001vorbis", 7)==0) {
- vorbis_start (&stream);
- }
- }
- header = vorbis_process (&stream, &page, ti);
- if (ogg_page_eos (&page)) {
- vorbis_end (&stream);
- }
-
- /* Create ogg page boundary struct */
- ol = (OGG_PAGE_LIST*) malloc (sizeof(OGG_PAGE_LIST));
- if (!ol) {
- printf ("Malloc error\n");
- exit (1);
- }
- ol->m_page_len = page.header_len + page.body_len;
- ol->m_page_flags = 0;
-
- /* *****************************************************
- Create header buffer for relay stream. A pointer to the
- header buffer will attached to all pages after page 2.
- If a relay connects in the middle of a song, we send
- the header to the relay. Finally, the memory for the
- header is freed when the last page of the song is
- ejected from the cbuf.
- ** ******************************************************/
- if (ogg_page_bos (&page)) {
- /* First page in song */
- ol->m_page_flags |= OGG_PAGE_BOS;
- ol->m_header_buf_ptr = 0;
- ol->m_header_buf_len = 0;
- ogg_curr_header = (unsigned char*) malloc (ol->m_page_len);
- ogg_curr_header_len = ol->m_page_len;
- memcpy (ogg_curr_header,
- page.header, page.header_len);
- memcpy (ogg_curr_header+page.header_len,
- page.body, page.body_len);
- } else if (header) {
- /* Second or third page in song */
- ol->m_page_flags |= OGG_PAGE_2;
- ol->m_header_buf_ptr = 0;
- ol->m_header_buf_len = 0;
- ogg_curr_header = (unsigned char*)
- realloc (ogg_curr_header,
- ogg_curr_header_len + ol->m_page_len);
- memcpy (ogg_curr_header+ogg_curr_header_len,
- page.header, page.header_len);
- memcpy (ogg_curr_header+ogg_curr_header_len+page.header_len,
- page.body, page.body_len);
- ogg_curr_header_len += ol->m_page_len;
- } else if (!ogg_page_eos (&page)) {
- /* Middle pages in song */
- ol->m_header_buf_ptr = ogg_curr_header;
- ol->m_header_buf_len = ogg_curr_header_len;
- } else {
- /* Last page in song */
- ol->m_page_flags |= OGG_PAGE_EOS;
- ol->m_header_buf_ptr = ogg_curr_header;
- ol->m_header_buf_len = ogg_curr_header_len;
- ogg_curr_header = 0;
- ogg_curr_header_len = 0;
- }
-
- debug_printf ("OGG_PAGE\n"
- " header_len = %d\n"
- " body_len = %d\n"
- " serial no = %d\n"
- " page no = %d\n"
- " bos? = %d\n"
- " eos? = %d\n",
- page.header_len,
- page.body_len,
- ogg_page_serialno (&page),
- ogg_page_pageno (&page),
- ogg_page_bos (&page),
- ogg_page_eos (&page));
- list_add_tail (&(ol->m_list), page_list);
- break;
- }
- } while (ret != 0);
-
- debug_printf ("OGG_SYNC state:\n"
- " storage = %d\n"
- " fill = %d\n"
- " returned = %d\n"
- " unsynced = %d\n"
- " headerbytes = %d\n"
- " bodybytes = %d\n",
- ogg_sync.storage,
- ogg_sync.fill,
- ogg_sync.returned,
- ogg_sync.unsynced,
- ogg_sync.headerbytes,
- ogg_sync.bodybytes);
- // return 1;
-}
-
-void
-rip_ogg_get_current_header (unsigned char** ptr, int* len)
-{
- *ptr = ogg_curr_header;
- *len = ogg_curr_header_len;
-}
-
-void
-rip_ogg_init (void)
-{
- ogg_sync_init (&ogg_sync);
- memset (&stream, 0, sizeof(stream_processor));
- ogg_curr_header = 0;
- ogg_curr_header_len = 0;
-}
-
-#else /* HAVE_OGG_VORBIS == 0 */
-
-void
-rip_ogg_init (void)
-{
-}
-
-void
-rip_ogg_get_current_header (unsigned char** ptr, int* len)
-{
- *ptr = 0;
- *len = 0;
-}
-
-void
-rip_ogg_process_chunk (LIST* page_list, const char* buf, u_long size,
- TRACK_INFO* ti)
-{
- INIT_LIST_HEAD (page_list);
-}
-
-#endif /* HAVE_OGG_VORBIS */
diff --git a/xbmc/lib/libshout/ripogg.h b/xbmc/lib/libshout/ripogg.h
deleted file mode 100644
index 77e6b1d519..0000000000
--- a/xbmc/lib/libshout/ripogg.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* ripogg.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __RIP_OGG_H__
-#define __RIP_OGG_H__
-
-#include "list.h"
-
-void rip_ogg_init (void);
-void rip_ogg_get_current_header (unsigned char** ptr, int* len);
-void rip_ogg_process_chunk (LIST* page_list, const char* buf, u_long size,
- TRACK_INFO* ti);
-
-#endif
diff --git a/xbmc/lib/libshout/ripstream.c b/xbmc/lib/libshout/ripstream.c
deleted file mode 100644
index dab4d864ae..0000000000
--- a/xbmc/lib/libshout/ripstream.c
+++ /dev/null
@@ -1,1105 +0,0 @@
-/* ripstream.c
- * buffer stream data, when a track changes decodes the audio and
- * finds a silent point to split the track
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef _WIN32
-#include <sys/types.h>
-#include <netinet/in.h>
-#endif
-#include "srtypes.h"
-#include "cbuf2.h"
-#include "findsep.h"
-#include "mchar.h"
-#include "parse.h"
-#include "rip_manager.h"
-#include "ripstream.h"
-#include "debug.h"
-#include "filelib.h"
-#include "relaylib.h"
-#include "socklib.h"
-#include "external.h"
-#include "ripogg.h"
-
-/*****************************************************************************
- * Private functions
- *****************************************************************************/
-static error_code find_sep (u_long *pos1, u_long *pos2);
-static error_code start_track_mp3 (TRACK_INFO* ti);
-static error_code end_track_mp3 (RIP_MANAGER_OPTIONS* rmo, u_long pos1, u_long pos2, TRACK_INFO* ti);
-static error_code end_track_ogg (RIP_MANAGER_OPTIONS* rmo, TRACK_INFO* ti);
-
-static void compute_cbuf2_size (SPLITPOINT_OPTIONS *sp_opt,
- int bitrate, int meta_interval);
-static int ms_to_bytes (int ms, int bitrate);
-static int bytes_to_secs (unsigned int bytes);
-static void clear_track_info (TRACK_INFO* ti);
-static int ripstream_recvall (char* buffer, int size);
-
-static error_code get_track_from_metadata (int size, char *newtrack);
-static error_code get_stream_data (char *data_buf, char *track_buf);
-static error_code ripstream_rip_mp3 (RIP_MANAGER_OPTIONS* rmo);
-static error_code ripstream_rip_ogg (RIP_MANAGER_OPTIONS* rmo);
-
-/*****************************************************************************
- * Private Vars
- *****************************************************************************/
-#define DEFAULT_BUFFER_SIZE 1024
-
-static TRACK_INFO m_old_track; /* The track that's being ripped now */
-static TRACK_INFO m_new_track; /* The track that's gonna start soon */
-static TRACK_INFO m_current_track; /* The metadata as I'm parsing it */
-static int m_first_time_through;
-static char m_no_meta_name[MAX_TRACK_LEN] = {'\0'};
-static char *m_getbuffer = NULL;
-static int m_find_silence = -1;
-//static BOOL m_addID3tag = TRUE;
-static BOOL m_add_id3v1 = TRUE;
-static BOOL m_add_id3v2 = TRUE;
-static SPLITPOINT_OPTIONS *m_sp_opt;
-static int m_bitrate;
-static int m_http_bitrate;
-static int m_meta_interval;
-static unsigned int m_cue_sheet_bytes = 0;
-static External_Process* m_external_process = 0;
-
-static int m_cbuf2_size; /* blocks */
-static int m_rw_start_to_cb_end; /* bytes */
-static int m_rw_start_to_sw_start; /* milliseconds */
-static int m_rw_end_to_cb_end; /* bytes */
-static int m_mic_to_cb_end; /* blocks */
-
-static int m_drop_count;
-static int m_track_count = 0;
-static int m_content_type;
-static HSOCKET m_sock;
-static int m_have_relay;
-static int m_timeout;
-
-static int m_meta_interval;
-static unsigned long m_buffersize;
-static int m_chunkcount;
-
-typedef struct ID3V1st
-{
- char tag[3];
- char songtitle[30];
- char artist[30];
- char album[30];
- char year[4];
- char comment[30];
- char genre;
-} ID3V1Tag;
-
-#if defined (commentout)
-typedef struct ID3V2headst {
- char tag[3];
- int version;
- char flags;
- int size;
-} ID3V2head;
-#endif
-
-typedef struct ID3V2framest {
- char id[4];
- int size;
- char pad[3];
-} ID3V2frame;
-
-
-error_code
-ripstream_init (HSOCKET sock,
- int have_relay,
- int timeout,
- char *no_meta_name,
- int drop_count,
- SPLITPOINT_OPTIONS *sp_opt,
- int bitrate,
- int meta_interval,
- int content_type,
- BOOL add_id3v1,
- BOOL add_id3v2,
- External_Process* ep)
-{
- if (!sp_opt || !no_meta_name) {
- printf ("Error: invalid ripstream parameters\n");
- return SR_ERROR_INVALID_PARAM;
- }
-
- m_sock = sock;
- m_have_relay = have_relay;
- m_timeout = timeout;
- m_sp_opt = sp_opt;
- m_track_count = 0;
- m_add_id3v1 = add_id3v1;
- m_add_id3v2 = add_id3v2;
- strcpy(m_no_meta_name, no_meta_name);
- m_drop_count = drop_count;
- m_http_bitrate = bitrate;
- m_bitrate = -1;
- m_content_type = content_type;
- /* GCS RMK: Ripchunk_size is the metaint size, or default size
- if stream doesn't have meta data */
- m_meta_interval = meta_interval;
- m_cue_sheet_bytes = 0;
- m_external_process = ep;
-
- /* From ripshout */
- m_buffersize = (m_meta_interval == NO_META_INTERVAL)
- ? DEFAULT_BUFFER_SIZE : m_meta_interval;
-
- m_chunkcount = 0;
-
- clear_track_info (&m_old_track);
- clear_track_info (&m_new_track);
- clear_track_info (&m_current_track);
- m_first_time_through = 1;
-
- if ((m_getbuffer = malloc(m_buffersize)) == NULL)
- return SR_ERROR_CANT_ALLOC_MEMORY;
-
- return SR_SUCCESS;
-}
-
-void
-ripstream_destroy()
-{
- debug_printf ("RIPSTREAM_DESTROY\n");
- if (m_getbuffer) {free(m_getbuffer); m_getbuffer = NULL;}
- m_find_silence = -1;
- m_cbuf2_size = 0;
- cbuf2_destroy (&g_cbuf2);
-
- clear_track_info (&m_old_track);
- clear_track_info (&m_new_track);
- clear_track_info (&m_current_track);
- m_first_time_through = 1;
-
- m_no_meta_name[0] = '\0';
- m_track_count = 0;
- m_add_id3v1 = TRUE;
- m_add_id3v2 = TRUE;
-
- /* from ripshout */
- m_buffersize = 0;
- m_meta_interval = 0;
- m_chunkcount = 0;
-}
-
-BOOL
-is_track_changed()
-{
- /* If metadata is duplicate of previous, then no change. */
- if (!strcmp(m_old_track.raw_metadata, m_current_track.raw_metadata))
- return 0;
-
- /* Otherwise, there was a change. */
- return 1;
-}
-
-static void
-format_track_info (TRACK_INFO* ti, char* tag)
-{
- debug_mprintf (m_("----- TRACK_INFO ") m_s m_("\n")
- m_("HAVETI: %d\n")
- m_("RAW_MD: ") m_s m_("\n")
- m_("ARTIST: ") m_S m_("\n")
- m_("TITLE: ") m_S m_("\n")
- m_("ALBUM: ") m_S m_("\n")
- m_("SAVE: %d\n"),
- tag,
- ti->have_track_info,
- ti->raw_metadata,
- ti->artist,
- ti->title,
- ti->album,
- ti->save_track);
-}
-
-static void
-clear_track_info (TRACK_INFO* ti)
-{
- ti->have_track_info = 0;
- ti->raw_metadata[0] = 0;
- ti->artist[0] = 0;
- ti->title[0] = 0;
- ti->album[0] = 0;
- ti->track[0] = 0;
- ti->composed_metadata[0] = 0;
- ti->save_track = TRUE;
-}
-
-static void
-copy_track_info (TRACK_INFO* dest, TRACK_INFO* src)
-{
- dest->have_track_info = src->have_track_info;
- strcpy (dest->raw_metadata, src->raw_metadata);
- mstrcpy (dest->artist, src->artist);
- mstrcpy (dest->title, src->title);
- mstrcpy (dest->album, src->album);
- strcpy (dest->composed_metadata, src->composed_metadata);
- dest->save_track = src->save_track;
-}
-
-/**** The main loop for ripping ****/
-error_code
-ripstream_rip (RIP_MANAGER_OPTIONS* rmo)
-{
- if (m_content_type == CONTENT_TYPE_OGG) {
- return ripstream_rip_ogg (rmo);
- } else {
- return ripstream_rip_mp3 (rmo);
- }
-}
-
-static error_code
-ripstream_rip_ogg (RIP_MANAGER_OPTIONS* rmo)
-{
- int ret;
- int real_ret = SR_SUCCESS;
- u_long extract_size;
- static int have_track = 0;
-
- /* get the data from the stream */
- debug_printf ("RIPSTREAM_RIP_OGG: top of loop\n");
- ret = get_stream_data(m_getbuffer, m_current_track.raw_metadata);
- if (ret != SR_SUCCESS) {
- debug_printf("get_stream_data bad return code: %d\n", ret);
- return ret;
- }
-
- if (m_first_time_through) {
- /* Allocate circular buffer */
- m_bitrate = -1;
- m_buffersize = 1024;
- m_cbuf2_size = 128;
- ret = cbuf2_init (&g_cbuf2, m_content_type, m_have_relay,
- m_buffersize, m_cbuf2_size);
- if (ret != SR_SUCCESS) return ret;
- have_track = 0;
- /* Warm up the ogg decoding routines */
- rip_ogg_init ();
- /* Done! */
- m_first_time_through = 0;
- }
-
- /* Copy the data into cbuffer */
- clear_track_info (&m_current_track);
- ret = cbuf2_insert_chunk (&g_cbuf2, m_getbuffer, m_buffersize,
- m_content_type, &m_current_track);
- if (ret != SR_SUCCESS) {
- debug_printf("start_track had bad return code %d\n", ret);
- return ret;
- }
-
- filelib_write_show (m_getbuffer, m_buffersize);
-
- /* If we have unwritten pages for the current track, write them */
- if (have_track) {
- do {
- error_code ret;
- unsigned long amt_filled;
- int got_eos;
- ret = cbuf2_ogg_peek_song (&g_cbuf2, m_getbuffer, m_buffersize,
- &amt_filled, &got_eos);
- debug_printf ("^^^ogg_peek: %d %d\n", amt_filled, got_eos);
- if (ret != SR_SUCCESS) {
- debug_printf ("cbuf2_ogg_peek_song: %d\n",ret);
- return ret;
- }
- if (amt_filled == 0) {
- break;
- }
- ret = rip_manager_put_data (m_getbuffer, amt_filled);
- if (ret != SR_SUCCESS) {
- debug_printf ("rip_manager_put_data(#1): %d\n",ret);
- return ret;
- }
- if (got_eos) {
- end_track_ogg (rmo, &m_old_track);
- have_track = 0;
- break;
- }
- } while (1);
- }
-
- format_track_info (&m_current_track, "current");
-
- /* If we got a new track, then start a new file */
- if (m_current_track.have_track_info) {
- ret = rip_manager_start_track (&m_current_track, m_track_count);
- if (ret != SR_SUCCESS) {
- debug_printf ("rip_manager_start_track failed(#1): %d\n",ret);
- return ret;
- }
- filelib_write_cue (&m_current_track, 0);
- copy_track_info (&m_old_track, &m_current_track);
-
- have_track = 1;
- }
-
- /* If buffer almost full, advance the buffer */
- if (cbuf2_get_free(&g_cbuf2) < m_buffersize) {
- debug_printf ("cbuf2_get_free < m_buffersize\n");
- extract_size = m_buffersize - cbuf2_get_free(&g_cbuf2);
-
- ret = cbuf2_advance_ogg (&g_cbuf2, m_buffersize);
-
- if (ret != SR_SUCCESS) {
- debug_printf("cbuf2_extract had bad return code %d\n", ret);
- return ret;
- }
- }
-
- return real_ret;
-}
-
-static error_code
-ripstream_rip_mp3 (RIP_MANAGER_OPTIONS* rmo)
-{
- int ret;
- int real_ret = SR_SUCCESS;
- u_long extract_size;
-
- /* get the data & meta-data from the stream */
- debug_printf ("RIPSTREAM_RIP: top of loop\n");
- ret = get_stream_data(m_getbuffer, m_current_track.raw_metadata);
- if (ret != SR_SUCCESS) {
- debug_printf("get_stream_data bad return code: %d\n", ret);
- return ret;
- }
-
- /* First time through, need to determine the bitrate.
- The bitrate is needed to do the track splitting parameters
- properly in seconds. See the readme file for details. */
- /* GCS FIX: For VBR streams, the header value may be more reliable. */
- if (m_first_time_through) {
- unsigned long test_bitrate;
- debug_printf("Querying stream for bitrate - first time.\n");
- if (m_content_type == CONTENT_TYPE_MP3) {
- find_bitrate(&test_bitrate, m_getbuffer, m_buffersize);
- m_bitrate = test_bitrate / 1000;
- debug_printf("Got bitrate: %d\n",m_bitrate);
- } else {
- m_bitrate = 0;
- }
-
- if (m_bitrate == 0) {
- /* Couldn't decode from mp3, so let's go with what the
- http header says, or fallback to 24. */
- if (m_http_bitrate > 0)
- m_bitrate = m_http_bitrate;
- else
- m_bitrate = 24;
- }
- compute_cbuf2_size (m_sp_opt, m_bitrate, m_buffersize);
- ret = cbuf2_init (&g_cbuf2, m_content_type, m_have_relay,
- m_buffersize, m_cbuf2_size);
- if (ret != SR_SUCCESS) return ret;
- }
-
- if (m_external_process) {
- /* If using external metadata, check for that */
- clear_track_info (&m_current_track);
- read_external (m_external_process, &m_current_track);
- } else {
- if (m_current_track.raw_metadata[0]) {
- parse_metadata (&m_current_track);
- } else {
- clear_track_info (&m_current_track);
- }
- }
-
- /* Copy the data into cbuffer */
- ret = cbuf2_insert_chunk (&g_cbuf2, m_getbuffer, m_buffersize,
- m_content_type, &m_current_track);
- if (ret != SR_SUCCESS) {
- debug_printf("cbuf2_insert_chunk had bad return code %d\n", ret);
- return ret;
- }
-
- filelib_write_show (m_getbuffer, m_buffersize);
-
- /* First time through, so start a track. */
- if (m_first_time_through) {
- int ret;
- debug_printf ("First time through...\n");
- m_first_time_through = 0;
- if (!m_current_track.have_track_info) {
- strcpy (m_current_track.raw_metadata, m_no_meta_name);
- }
- ret = rip_manager_start_track (&m_current_track, m_track_count);
- if (ret != SR_SUCCESS) {
- debug_printf ("rip_manager_start_track failed(#1): %d\n",ret);
- return ret;
- }
- filelib_write_cue (&m_current_track, 0);
- copy_track_info (&m_old_track, &m_current_track);
- }
-
- /* Check for track change. */
- debug_printf ("m_current_track.have_track_info = %d\n",
- m_current_track.have_track_info);
- if (m_current_track.have_track_info && is_track_changed()) {
- /* Set m_find_silence equal to the number of additional blocks
- needed until we can do silence separation. */
- debug_printf ("VERIFIED TRACK CHANGE (m_find_silence = %d)\n",
- m_find_silence);
- copy_track_info (&m_new_track, &m_current_track);
- if (m_find_silence < 0) {
- if (m_mic_to_cb_end > 0) {
- m_find_silence = m_mic_to_cb_end;
- } else {
- m_find_silence = 0;
- }
- }
- }
-
- format_track_info (&m_old_track, "old");
- format_track_info (&m_new_track, "new");
- format_track_info (&m_current_track, "current");
-
- if (m_find_silence == 0) {
- /* Find separation point */
- u_long pos1, pos2;
- debug_printf ("m_find_silence == 0\n");
- ret = find_sep (&pos1, &pos2);
- if (ret == SR_ERROR_REQUIRED_WINDOW_EMPTY) {
- /* If this happens, the previous song should be truncated to
- zero bytes. */
- pos1 = 0;
- pos2 = 0;
- }
- else if (ret != SR_SUCCESS) {
- debug_printf("find_sep had bad return code %d\n", ret);
- return ret;
- }
-
- /* Write out previous track */
- ret = end_track_mp3 (rmo, pos1, pos2, &m_old_track);
- if (ret != SR_SUCCESS)
- real_ret = ret;
- m_cue_sheet_bytes += pos2;
-
- /* Start next track */
- ret = start_track_mp3 (&m_new_track);
- if (ret != SR_SUCCESS)
- real_ret = ret;
- m_find_silence = -1;
-
- copy_track_info (&m_old_track, &m_new_track);
- }
- if (m_find_silence >= 0) m_find_silence --;
-
- /* If buffer almost full, dump extra to current song. */
- if (cbuf2_get_free(&g_cbuf2) < m_buffersize) {
- u_long curr_song;
- debug_printf ("cbuf2_get_free < m_buffersize\n");
- extract_size = m_buffersize - cbuf2_get_free(&g_cbuf2);
- ret = cbuf2_extract(&g_cbuf2, m_getbuffer, extract_size, &curr_song);
- if (ret != SR_SUCCESS) {
- debug_printf("cbuf2_extract had bad return code %d\n", ret);
- return ret;
- }
-
- /* Post to caller */
- if (curr_song < extract_size) {
- u_long curr_song_bytes = extract_size - curr_song;
- m_cue_sheet_bytes += curr_song_bytes;
- rip_manager_put_data (&m_getbuffer[curr_song], curr_song_bytes);
- }
- }
-
- return real_ret;
-}
-
-error_code
-find_sep (u_long *pos1, u_long *pos2)
-{
- int rw_start, rw_end, sw_sil;
- int ret;
-
- debug_printf ("*** Finding separation point\n");
-
- /* First, find the search region w/in cbuffer. */
- rw_start = g_cbuf2.item_count - m_rw_start_to_cb_end;
- if (rw_start < 0) {
- return SR_ERROR_REQUIRED_WINDOW_EMPTY;
- }
- rw_end = g_cbuf2.item_count - m_rw_end_to_cb_end;
- if (rw_end < 0) {
- return SR_ERROR_REQUIRED_WINDOW_EMPTY;
- }
-
- debug_printf ("search window (bytes): %d,%d,%d\n", rw_start, rw_end,
- g_cbuf2.item_count);
-
- if (m_content_type != CONTENT_TYPE_MP3) {
- sw_sil = (rw_end + rw_start) / 2;
- debug_printf ("(not mp3) taking middle: sw_sil=%d\n", sw_sil);
- *pos1 = rw_start + sw_sil;
- *pos2 = rw_start + sw_sil;
- } else {
- int bufsize = rw_end - rw_start;
- char* buf = (u_char *)malloc(bufsize);
- ret = cbuf2_peek_rgn (&g_cbuf2, buf, rw_start, bufsize);
- if (ret != SR_SUCCESS) {
- debug_printf ("PEEK FAILED: %d\n", ret);
- free(buf);
- return ret;
- }
- debug_printf ("PEEK OK\n");
-
- /* Find silence point */
- ret = findsep_silence (buf,
- bufsize,
- m_rw_start_to_sw_start,
- m_sp_opt->xs_search_window_1
- + m_sp_opt->xs_search_window_2,
- m_sp_opt->xs_silence_length,
- m_sp_opt->xs_padding_1,
- m_sp_opt->xs_padding_2,
- pos1, pos2);
- *pos1 += rw_start;
- *pos2 += rw_start;
- free(buf);
- }
- return SR_SUCCESS;
-}
-
-static error_code
-end_track_mp3 (RIP_MANAGER_OPTIONS* rmo, u_long pos1, u_long pos2, TRACK_INFO* ti)
-{
- // pos1 is end of prev track
- // pos2 is beginning of next track
- int ret;
- u_char *buf;
-
- /* GCS pos1 is byte position. Here we convert it into a "count". */
- pos1++;
-
- // I think pos can be zero if the silence is right at the beginning
- // i.e. it is a bug in s.r.
- buf = (u_char*) malloc (pos1);
-
- // pos1 is end of prev track
- // pos2 is beginning of next track
- // positions are relative to cbuf2->read_index
-
- // First, dump the part only in prev track
- ret = cbuf2_peek(&g_cbuf2, buf, pos1);
- if (ret != SR_SUCCESS) goto BAIL;
-
- // Let cbuf know about the start of the next track
- cbuf2_set_next_song (&g_cbuf2, pos2);
-
- // Write that out to the current file
- // GCS FIX: m_bytes_ripped is incorrect when there is padding
- if ((ret = rip_manager_put_data(buf, pos1)) != SR_SUCCESS)
- goto BAIL;
-
- /* This is id3v1 */
- if (m_add_id3v1) {
- ID3V1Tag id3;
- memset (&id3, '\000',sizeof(id3));
- strncpy (id3.tag, "TAG", strlen("TAG"));
- string_from_mstring (id3.artist, sizeof(id3.artist),
- ti->artist, CODESET_ID3);
- string_from_mstring (id3.songtitle, sizeof(id3.songtitle),
- ti->title, CODESET_ID3);
- string_from_mstring (id3.album, sizeof(id3.album),
- ti->album, CODESET_ID3);
- id3.genre = (char) 0xFF; // see http://www.id3.org/id3v2.3.0.html#secA
- ret = rip_manager_put_data ((char *)&id3, sizeof(id3));
- if (ret != SR_SUCCESS) {
- goto BAIL;
- }
- }
-
- // Only save this track if we've skipped over enough cruft
- // at the beginning of the stream
- debug_printf("Current track number %d (skipping if %d or less)\n",
- m_track_count, m_drop_count);
- if (m_track_count > m_drop_count)
- if ((ret = rip_manager_end_track (rmo, ti)) != SR_SUCCESS)
- goto BAIL;
-
- BAIL:
- free(buf);
- return ret;
-}
-
-static error_code
-start_track_mp3 (TRACK_INFO* ti)
-{
-#define HEADER_SIZE 1600
- int ret;
- int i;
- unsigned int secs;
-
- debug_printf ("calling rip_manager_start_track(#2)\n");
- ret = rip_manager_start_track (ti, m_track_count);
- if (ret != SR_SUCCESS) {
- debug_printf ("rip_manager_start_track failed(#2): %d\n",ret);
- return ret;
- }
-
- /* Dump to artist/title to cue sheet */
- secs = bytes_to_secs (m_cue_sheet_bytes);
- ret = filelib_write_cue (ti, secs);
- if (ret != SR_SUCCESS)
- return ret;
-
- /* Oddsock's ID3 stuff, (oddsock@oddsock.org) */
- if (m_add_id3v2) {
- int rc;
- char bigbuf[HEADER_SIZE] = "";
- int header_size = HEADER_SIZE;
- char header1[6] = "ID3\x03\0\0";
- ID3V2frame id3v2frame;
- char comment[1024] = "Ripped with Streamripper";
- unsigned long int framesize = 0;
- int sent = 0;
- int id3_charset;
-
- memset(bigbuf, '\000', sizeof(bigbuf));
-
- /* Write header */
- ret = rip_manager_put_data(header1, 6);
- if (ret != SR_SUCCESS) return ret;
- for (i = 0; i < 4; i++) {
- char x = (header_size >> (3-i)*7) & 0x7F;
- ret = rip_manager_put_data((char *)&x, 1);
- if (ret != SR_SUCCESS) return ret;
- }
-
- /* ID3 V2.3 is only defined for ISO-8859-1 and UCS-2
- If user specifies another codeset, we will use it, and
- report ISO-8859-1 in the encoding field */
- id3_charset = is_id3_unicode();
-
- /* Write ID3V2 TPE1 frame (Lead performer) */
- memset(&id3v2frame, '\000', sizeof(id3v2frame));
- strncpy(id3v2frame.id, "TPE1", 4);
- id3v2frame.pad[2] = id3_charset;
- rc = string_from_mstring (bigbuf, HEADER_SIZE, ti->artist,
- CODESET_ID3);
- framesize = htonl (rc+1);
- ret = rip_manager_put_data ((char *)&(id3v2frame.id), 4);
- if (ret != SR_SUCCESS) return ret;
- sent += 4;
- ret = rip_manager_put_data ((char *)&(framesize), sizeof(framesize));
- if (ret != SR_SUCCESS) return ret;
- sent += sizeof(framesize);
- ret = rip_manager_put_data ((char *)&(id3v2frame.pad), 3);
- if (ret != SR_SUCCESS) return ret;
- sent += 3;
- ret = rip_manager_put_data (bigbuf, rc);
- if (ret != SR_SUCCESS) return ret;
- sent += rc;
-
- /* Write ID3V2 TIT2 frame (Title) */
- memset(&id3v2frame, '\000', sizeof(id3v2frame));
- strncpy(id3v2frame.id, "TIT2", 4);
- id3v2frame.pad[2] = id3_charset;
- rc = string_from_mstring (bigbuf, HEADER_SIZE, ti->title,
- CODESET_ID3);
- framesize = htonl (rc+1);
- ret = rip_manager_put_data((char *)&(id3v2frame.id), 4);
- if (ret != SR_SUCCESS) return ret;
- sent += 4;
- ret = rip_manager_put_data((char *)&(framesize), sizeof(framesize));
- if (ret != SR_SUCCESS) return ret;
- sent += sizeof(framesize);
- ret = rip_manager_put_data((char *)&(id3v2frame.pad), 3);
- if (ret != SR_SUCCESS) return ret;
- sent += 3;
- ret = rip_manager_put_data (bigbuf, rc);
- if (ret != SR_SUCCESS) return ret;
- sent += rc;
-
- /* Write ID3V2 TENC frame (Encoded by) */
- memset(&id3v2frame, '\000', sizeof(id3v2frame));
- strncpy(id3v2frame.id, "TENC", 4);
- framesize = htonl(strlen(comment)+1);
- ret = rip_manager_put_data((char *)&(id3v2frame.id), 4);
- if (ret != SR_SUCCESS) return ret;
- sent += 4;
- ret = rip_manager_put_data((char *)&(framesize), sizeof(framesize));
- if (ret != SR_SUCCESS) return ret;
- sent += sizeof(framesize);
- ret = rip_manager_put_data((char *)&(id3v2frame.pad), 3);
- if (ret != SR_SUCCESS) return ret;
- sent += 3;
- ret = rip_manager_put_data(comment, strlen(comment));
- if (ret != SR_SUCCESS) return ret;
- sent += strlen (comment);
-
- /* Write ID3V2 TALB frame (Album) */
- memset(&id3v2frame, '\000', sizeof(id3v2frame));
- strncpy(id3v2frame.id, "TALB", 4);
- id3v2frame.pad[2] = id3_charset;
- rc = string_from_mstring (bigbuf, HEADER_SIZE, ti->album,
- CODESET_ID3);
- framesize = htonl (rc+1);
- ret = rip_manager_put_data((char *)&(id3v2frame.id), 4);
- if (ret != SR_SUCCESS) return ret;
- sent += 4;
- ret = rip_manager_put_data((char *)&(framesize), sizeof(framesize));
- if (ret != SR_SUCCESS) return ret;
- sent += sizeof(framesize);
- ret = rip_manager_put_data((char *)&(id3v2frame.pad), 3);
- if (ret != SR_SUCCESS) return ret;
- sent += 3;
- ret = rip_manager_put_data (bigbuf, rc);
- if (ret != SR_SUCCESS) return ret;
- sent += rc;
-
- /* Zero out padding */
- memset(bigbuf, '\000', sizeof(bigbuf));
-
- /* Pad up to header_size */
- ret = rip_manager_put_data(bigbuf, HEADER_SIZE-sent);
- if (ret != SR_SUCCESS) return ret;
- }
- m_track_count ++;
- debug_printf ("Changed track count to %d\n", m_track_count);
-
- return SR_SUCCESS;
-}
-
-// Only save this track if we've skipped over enough cruft
-// at the beginning of the stream
-static error_code
-end_track_ogg (RIP_MANAGER_OPTIONS* rmo, TRACK_INFO* ti)
-{
- error_code ret;
- debug_printf ("Current track number %d (skipping if %d or less)\n",
- m_track_count, m_drop_count);
- if (m_track_count > m_drop_count) {
- ret = rip_manager_end_track (rmo, ti);
- } else {
- ret = SR_SUCCESS;
- }
- m_track_count ++;
- return ret;
-}
-
-#if defined (commentout)
-/* GCS: This converts either positive or negative ms to blocks,
- and must work for rounding up and rounding down */
-static int
-ms_to_blocks (int ms, int bitrate, int round_up)
-{
- int ms_abs = ms > 0 ? ms : -ms;
- int ms_sign = ms > 0 ? 1 : 0;
- int bits = ms_abs * bitrate;
- int bits_per_block = 8 * m_buffersize;
- int blocks = bits / bits_per_block;
- if (bits % bits_per_block > 0) {
- if (!(round_up ^ ms_sign)) {
- blocks++;
- }
- }
- if (!ms_sign) {
- blocks = -blocks;
- }
- return blocks;
-}
-#endif
-
-/* Simpler routine, rounded toward zero */
-static int
-ms_to_bytes (int ms, int bitrate)
-{
- int bits = ms * bitrate;
- if (bits > 0)
- return bits / 8;
- else
- return -((-bits)/8);
-}
-
-/* Assume positive, round toward zero */
-static int
-bytes_to_secs (unsigned int bytes)
-{
- /* divided by 125 because 125 = 1000 / 8 */
- int secs = (bytes / m_bitrate) / 125;
- return secs;
-}
-
-/* --------------------------------------------------------------------------
- Buffering for silence splitting & padding
-
- We may flush the circular buffer as soon as anything that
- needs to go into the next song has passed. For simplicity,
- we also buffer up to the latest point that can go into the
- next song. This is called the "required window."
-
- The entire required window is decoded, even though
- we don't need the volume. We simply mark the frame boundaries
- so we don't chop any frames.
-
- The circular buffer is a bit bigger than the required window,
- because it contains an integer number of blocks which fall
-
- Some abbreviations:
- mic meta inf change
- cb cbuf2, aka circular buffer
- rw required window
- sw search window
-
- This is the complete picture:
-
- A---------A---------A----+----B---------B meta intervals
-
- /mic meta-inf change (A to B)
- +--->|
- /mi meta-inf point
- |
- |---+-----+------+---| search window
- | |
- | |
- |---+---| |---+---| silence length
- | |
- |-------------| |-----|
- prepad postpad
-
- |--------------------------------| required window
-
- |---------------------------------------| cbuf
-
-
- |<-------------+ mic_to_sw_start
- +---->| mic_to_sw_end
- |<-----------------------+ mic_to_rw_start
- +------>| mic_to_rw_end
- |<----------------------------+ mic_to_cb_start
- +-------->| mic_to_cb_end
-
- ------------------------------------------------------------------------*/
-static void
-compute_cbuf2_size (SPLITPOINT_OPTIONS *sp_opt, int bitrate,
- int meta_interval)
-{
- long sws, sl;
- long mi_to_mic;
- long prepad, postpad;
- long offset;
- long mic_to_sw_start, mic_to_sw_end;
- long mic_to_rw_start, mic_to_rw_end;
- long mic_to_cb_start, mic_to_cb_end;
-
- if(meta_interval == 0)
- return;
-
- debug_printf ("---------------------------------------------------\n");
- debug_printf ("xs_search_window: %d,%d\n",
- sp_opt->xs_search_window_1,sp_opt->xs_search_window_2);
- debug_printf ("xs_silence_length: %d\n", sp_opt->xs_silence_length);
- debug_printf ("xs_padding: %d,%d\n", sp_opt->xs_padding_1,
- sp_opt->xs_padding_2);
- debug_printf ("xs_offset: %d\n", sp_opt->xs_offset);
- debug_printf ("---------------------------------------------------\n");
- debug_printf ("bitrate = %d, meta_inf = %d\n", bitrate, meta_interval);
- debug_printf ("---------------------------------------------------\n");
-
- /* mi_to_mic is the "half of a meta-inf" from the meta inf
- change to the previous (non-changed) meta inf */
- mi_to_mic = meta_interval / 2;
- debug_printf ("mi_to_mic: %d\n", mi_to_mic);
-
- /* compute the search window size (sws) */
- sws = ms_to_bytes (sp_opt->xs_search_window_1, bitrate)
- + ms_to_bytes (sp_opt->xs_search_window_2, bitrate);
- debug_printf ("sws: %d\n", sws);
-
- /* compute the silence length (sl) */
- sl = ms_to_bytes (sp_opt->xs_silence_length, bitrate);
- debug_printf ("sl: %d\n", sl);
-
- /* compute padding */
- prepad = ms_to_bytes (sp_opt->xs_padding_1, bitrate);
- postpad = ms_to_bytes (sp_opt->xs_padding_2, bitrate);
- debug_printf ("padding: %d %d\n", prepad, postpad);
-
- /* compute offset */
- offset = ms_to_bytes(sp_opt->xs_offset,bitrate);
- debug_printf ("offset: %d\n", offset);
-
- /* compute interval from mi to search window */
- mic_to_sw_start = - mi_to_mic + offset
- - ms_to_bytes(sp_opt->xs_search_window_1,bitrate);
- mic_to_sw_end = - mi_to_mic + offset
- + ms_to_bytes(sp_opt->xs_search_window_2,bitrate);
- debug_printf ("mic_to_sw_start: %d\n", mic_to_sw_start);
- debug_printf ("mic_to_sw_end: %d\n", mic_to_sw_end);
-
- /* compute interval from mi to required window */
- mic_to_rw_start = mic_to_sw_start + sl / 2 - prepad;
- if (mic_to_rw_start > mic_to_sw_start) {
- mic_to_rw_start = mic_to_sw_start;
- }
- mic_to_rw_end = mic_to_sw_end - sl / 2 + postpad;
- if (mic_to_rw_end < mic_to_sw_end) {
- mic_to_rw_end = mic_to_sw_end;
- }
- debug_printf ("mic_to_rw_start: %d\n", mic_to_rw_start);
- debug_printf ("mic_to_rw_end: %d\n", mic_to_rw_end);
-
- /* This code replaces the 3 cases (see OBSOLETE in gcs_notes.txt) */
- mic_to_cb_start = mic_to_rw_start;
- mic_to_cb_end = mic_to_rw_end;
- if (mic_to_cb_start > -meta_interval) {
- mic_to_cb_start = -meta_interval;
- }
- if (mic_to_cb_end < 0) {
- mic_to_cb_end = 0;
- }
-
- /* Convert to chunks & compute cbuf size */
- mic_to_cb_end = (mic_to_cb_end + (meta_interval-1)) / meta_interval;
- mic_to_cb_start = -((-mic_to_cb_start + (meta_interval-1))
- / meta_interval);
- m_cbuf2_size = -mic_to_cb_start + mic_to_cb_end;
- if (m_cbuf2_size < 3) {
- m_cbuf2_size = 3;
- }
- debug_printf ("mic_to_cb_start: %d\n", mic_to_cb_start * meta_interval);
- debug_printf ("mic_to_cb_end: %d\n", mic_to_cb_end * meta_interval);
- debug_printf ("CBUF2 (BLOCKS): %d:%d -> %d\n", mic_to_cb_start,
- mic_to_cb_end, m_cbuf2_size);
-
- /* Set some global variables to be used by splitting algorithm */
- m_mic_to_cb_end = mic_to_cb_end;
- m_rw_start_to_cb_end = mic_to_cb_end * meta_interval - mic_to_rw_start;
- m_rw_end_to_cb_end = mic_to_cb_end * meta_interval - mic_to_rw_end;
- m_rw_start_to_sw_start = sp_opt->xs_padding_1 - sp_opt->xs_silence_length / 2;
- if (m_rw_start_to_sw_start < 0) {
- m_rw_start_to_sw_start = 0;
- }
- debug_printf ("m_mic_to_cb_end: %d\n", m_mic_to_cb_end);
- debug_printf ("m_rw_start_to_cb_end: %d\n", m_rw_start_to_cb_end);
- debug_printf ("m_rw_end_to_cb_end: %d\n", m_rw_end_to_cb_end);
- debug_printf ("m_rw_start_to_sw_start: %d\n", m_rw_start_to_sw_start);
-}
-
-/* GCS: This used to be myrecv in rip_manager.c */
-static int
-ripstream_recvall (char* buffer, int size)
-{
- int ret;
- /* GCS: Jun 5, 2004. Here is where I think we are getting aussie's
- problem with the SR_ERROR_INVALID_METADATA or SR_ERROR_NO_TRACK_INFO
- messages */
- ret = socklib_recvall(&m_sock, buffer, size, m_timeout);
- if (ret >= 0 && ret != size) {
- debug_printf ("rip_manager_recv: expected %d, got %d\n",size,ret);
- ret = SR_ERROR_RECV_FAILED;
- }
- return ret;
-}
-
-static error_code
-get_stream_data (char *data_buf, char *track_buf)
-{
- int ret = 0;
- char c;
- char newtrack[MAX_TRACK_LEN];
-
- *track_buf = 0;
- m_chunkcount++;
- if ((ret = ripstream_recvall (data_buf, m_buffersize)) <= 0)
- return ret;
-
- if (m_meta_interval == NO_META_INTERVAL) {
- return SR_SUCCESS;
- }
-
- if ((ret = ripstream_recvall (&c, 1)) <= 0)
- return ret;
-
- debug_printf ("METADATA LEN: %d\n",(int)c);
- if (c < 0) {
- debug_printf ("Got invalid metadata: %d\n",c);
- return SR_ERROR_INVALID_METADATA;
- } else if (c == 0) {
- // around christmas time 2001 someone noticed that 1.8.7 shoutcast
- // none-meta servers now just send a '0' if they have no meta data
- // anyway, bassicly if the first meta capture is null then we assume
- // that the stream does not have metadata
- return SR_SUCCESS;
- } else {
- if ((ret = get_track_from_metadata (c * 16, newtrack)) != SR_SUCCESS) {
- debug_printf("get_trackname had a bad return %d", ret);
- return ret;
- }
-
- // WolfFM is a station that does not stream meta-data, but is in that format anyway...
- // StreamTitle='', so we need to pretend this has no meta data.
- if (*newtrack == '\0') {
- return SR_SUCCESS;
- }
- /* This is the case where we got metadata. */
- strncpy(track_buf, newtrack, MAX_TRACK_LEN);
- }
- return SR_SUCCESS;
-}
-
-static error_code
-get_track_from_metadata (int size, char *newtrack)
-{
- int i;
- int ret;
- char *namebuf;
-
- if ((namebuf = malloc(size)) == NULL)
- return SR_ERROR_CANT_ALLOC_MEMORY;
-
- if ((ret = ripstream_recvall (namebuf, size)) <= 0) {
- free(namebuf);
- return ret;
- }
-
- debug_printf ("METADATA TITLE\n");
- for (i=0; i<size; i++) {
- debug_printf ("%2x ",(unsigned char)namebuf[i]);
- if (i % 20 == 19) {
- debug_printf ("\n");
- }
- }
- debug_printf ("\n");
- for (i=0; i<size; i++) {
- debug_printf ("%2c ",namebuf[i]);
- if (i % 20 == 19) {
- debug_printf ("\n");
- }
- }
- debug_printf ("\n");
-
- if(strstr(namebuf, "StreamTitle='") == NULL) {
- free(namebuf);
- return SR_ERROR_NO_TRACK_INFO;
- }
- subnstr_until(namebuf+strlen("StreamTitle='"), "';", newtrack, MAX_TRACK_LEN);
- trim(newtrack);
-
- free(namebuf);
- return SR_SUCCESS;
-}
diff --git a/xbmc/lib/libshout/ripstream.h b/xbmc/lib/libshout/ripstream.h
deleted file mode 100644
index a13344344d..0000000000
--- a/xbmc/lib/libshout/ripstream.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __RIPLIB_H__
-#define __RIPLIB_H__
-
-#include "rip_manager.h"
-#include "srtypes.h"
-#include "socklib.h"
-
-error_code
-ripstream_init (HSOCKET sock,
- int have_relay,
- int timeout,
- char *no_meta_name,
- int drop_count,
- SPLITPOINT_OPTIONS *sp_opt,
- int bitrate,
- int meta_interval,
- int content_type,
- BOOL add_id3v1,
- BOOL add_id3v2,
- External_Process* ep);
-error_code ripstream_rip(RIP_MANAGER_OPTIONS* rmo);
-void ripstream_destroy();
-
-
-#endif //__RIPLIB__
diff --git a/xbmc/lib/libshout/socklib.c b/xbmc/lib/libshout/socklib.c
deleted file mode 100644
index 6bb1f0dc69..0000000000
--- a/xbmc/lib/libshout/socklib.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/* socklib.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <time.h>
-#if WIN32
-#include <winsock2.h>
-#else
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <fcntl.h>
-#endif
-
-#if __UNIX__
-#include <arpa/inet.h>
-#elif __BEOS__
-#include <be/net/netdb.h>
-#endif
-
-#include "srtypes.h"
-#include "socklib.h"
-#include "threadlib.h"
-#include "compat.h"
-#include "debug.h"
-
-#define DEFAULT_TIMEOUT 15
-
-#if WIN32
-#define FIRST_READ_TIMEOUT (30 * 1000)
-#elif __UNIX__
-#define FIRST_READ_TIMEOUT 30
-#endif
-
-
-/****************************************************************************
- * Private Vars
- ****************************************************************************/
-static BOOL m_done_init = FALSE; // so we don't init the mutex twice.. arg.
-
-
-/****************************************************************************
- * Function definitions
- ****************************************************************************/
-error_code
-socklib_init()
-{
-#if WIN32
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
-#endif
-
- if (m_done_init)
- return SR_SUCCESS;
-
-#if WIN32
- wVersionRequested = MAKEWORD( 2, 2 );
- err = WSAStartup( wVersionRequested, &wsaData );
- if ( err != 0 )
- return SR_ERROR_WIN32_INIT_FAILURE;
-#endif
-
- m_done_init = TRUE;
- return SR_SUCCESS;
-}
-
-
-/* Try to find the local interface to bind to */
-error_code
-read_interface(char *if_name, uint32_t *addr)
-{
-#if defined (WIN32)
- return -1;
-#else
- int fd;
- struct ifreq ifr;
-
- memset(&ifr, 0, sizeof(struct ifreq));
- if((fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
- ifr.ifr_addr.sa_family = AF_INET;
- strcpy(ifr.ifr_name, if_name);
- if (ioctl(fd, SIOCGIFADDR, &ifr) == 0)
- *addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
- else {
- close(fd);
- return -2;
- }
- } else
- return -1;
- close(fd);
- return 0;
-#endif
-}
-
-/*
- * open's a tcp connection to host at port, host can be a dns name or IP,
- * socket_handle gets assigned to the handle for the connection
- */
-error_code
-socklib_open(HSOCKET *socket_handle, char *host, int port, char *if_name)
-{
- int rc;
- struct sockaddr_in address, local;
- struct hostent *hp;
- int len;
-
- if (!socket_handle || !host)
- return SR_ERROR_INVALID_PARAM;
-
- socket_handle->s = socket(AF_INET, SOCK_STREAM, 0);
-
- if (if_name) {
- if (read_interface(if_name,&local.sin_addr.s_addr) != 0)
- local.sin_addr.s_addr = htonl(INADDR_ANY);
- local.sin_family = AF_INET;
- local.sin_port = htons(0);
- if (bind(socket_handle->s, (struct sockaddr *)&local,
- sizeof(local)) == SOCKET_ERROR) {
- debug_printf ("Bind failed\n");
- WSACleanup();
- closesocket(socket_handle->s);
- return SR_ERROR_CANT_BIND_ON_INTERFACE;
- }
- }
-
- if ((address.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
- hp = gethostbyname(host);
- if (hp) {
- memcpy(&address.sin_addr, hp->h_addr_list[0], hp->h_length);
- } else {
- debug_printf("resolving hostname: %s failed\n", host);
- WSACleanup();
- return SR_ERROR_CANT_RESOLVE_HOSTNAME;
- }
- }
- address.sin_family = AF_INET;
- address.sin_port = htons((unsigned short)port);
- len = sizeof(address);
-
- rc = connect (socket_handle->s, (struct sockaddr *)&address, len);
- if (rc == SOCKET_ERROR) {
- debug_printf("connect failed\n");
- return SR_ERROR_CONNECT_FAILED;
- }
-
-#ifdef WIN32
- {
- struct timeval timeout = {DEFAULT_TIMEOUT*1000, 0};
- rc = setsockopt (socket_handle->s, SOL_SOCKET, SO_RCVTIMEO,
- (char *)&timeout, sizeof(timeout));
- if (rc == SOCKET_ERROR) {
- debug_printf("setsockopt failed\n");
- return SR_ERROR_CANT_SET_SOCKET_OPTIONS;
- }
- }
-#endif
-
- socket_handle->closed = FALSE;
- return SR_SUCCESS;
-}
-
-void socklib_cleanup()
-{
- WSACleanup();
- m_done_init = FALSE;
-}
-
-void socklib_close(HSOCKET *socket_handle)
-{
- closesocket(socket_handle->s);
- socket_handle->closed = TRUE;
-}
-
-error_code
-socklib_read_header(HSOCKET *socket_handle, char *buffer, int size,
- int (*recvall)(HSOCKET *socket_handle, char* buffer,
- int size, int timeout))
-{
- int i;
-#ifdef WIN32
- struct timeval timeout = {FIRST_READ_TIMEOUT, 0};
-#endif
- int ret;
- char *t;
- int (*myrecv)(HSOCKET *socket_handle, char* buffer, int size, int timeout);
-
- if (socket_handle->closed)
- return SR_ERROR_SOCKET_CLOSED;
-
- if (recvall)
- myrecv = recvall;
- else
- myrecv = socklib_recvall;
-#ifdef WIN32
- if (setsockopt(socket_handle->s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) == SOCKET_ERROR)
- return SR_ERROR_CANT_SET_SOCKET_OPTIONS;
-#endif
-
- memset(buffer, 0, size);
- for(i = 0; i < size; i++)
- {
- if ((ret = (*myrecv)(socket_handle, &buffer[i], 1, 0)) < 0)
- return ret;
-
- if (ret == 0) {
- debug_printf("http header:\n%s\n", buffer);
- return SR_ERROR_NO_HTTP_HEADER;
- }
-
- if (socket_handle->closed)
- return SR_ERROR_SOCKET_CLOSED;
-
- /* GCS: This patch is too restrictive. */
-#if defined (commentout)
- //look for the end of the icy-header
- if (!strstr(buffer, "icy-") && !strstr(buffer,"ice-"))
- continue;
-#endif
-
- t = buffer + (i > 3 ? i - 3: i);
-
- if (strncmp(t, "\r\n\r\n", 4) == 0)
- break;
-
- if (strncmp(t, "\n\0\r\n", 4) == 0) // wtf? live365 seems to do this
- break;
- }
-
- if (i == size) {
- debug_printf("http header:\n%s\n", buffer);
- return SR_ERROR_NO_HTTP_HEADER;
- }
-
- buffer[i] = '\0';
-
-#ifdef WIN32
- timeout.tv_sec = DEFAULT_TIMEOUT*1000;
- if (setsockopt(socket_handle->s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) == SOCKET_ERROR)
- return SR_ERROR_CANT_SET_SOCKET_OPTIONS;
-#endif
-
- return SR_SUCCESS;
-}
-
-int
-socklib_recvall (HSOCKET *socket_handle, char* buffer, int size, int timeout)
-{
- int ret = 0, read = 0;
- int sock;
- fd_set fds;
- struct timeval tv;
-#ifdef XBMC
- int local_timeout = 0;
-#endif
-
- sock = socket_handle->s;
- FD_ZERO(&fds);
- while(size) {
- if (socket_handle->closed)
- return SR_ERROR_SOCKET_CLOSED;
-
- if (timeout > 0) {
- /* Wait up to 'timeout' seconds for data on socket to be
- ready for read */
- FD_SET(sock, &fds);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- ret = select(sock + 1, &fds, NULL, NULL, &tv);
- if (ret == SOCKET_ERROR) {
- /* This happens when I kill winamp while ripping */
- return SR_ERROR_SELECT_FAILED;
- }
- if (ret != 1)
-#ifdef XBMC
- {
- local_timeout++;
- continue;
- }
- if (local_timeout >= timeout)
-#endif
- return SR_ERROR_TIMEOUT;
- }
-
- ret = recv(socket_handle->s, &buffer[read], size, 0);
- debug_printf ("RECV req %5d bytes, got %5d bytes\n", size, ret);
-
- if (ret == SOCKET_ERROR) {
- debug_printf ("RECV failed, errno = %d\n", errno);
- debug_printf ("Err = %s\n",strerror(errno));
- return SR_ERROR_RECV_FAILED;
- }
-
- /* Got zero bytes on blocking read. For unix this is an
- orderly shutdown. */
- if (ret == 0) {
- debug_printf ("recv received zero bytes!\n");
- break;
- }
-
- read += ret;
- size -= ret;
- }
-
- return read;
-}
-
-int
-socklib_sendall (HSOCKET *socket_handle, char* buffer, int size)
-{
- int ret = 0, sent = 0;
-
- while(size) {
- if (socket_handle->closed)
- return SR_ERROR_SOCKET_CLOSED;
-
- ret = send(socket_handle->s, &buffer[sent], size, 0);
- if (ret == SOCKET_ERROR)
- return SR_ERROR_SEND_FAILED;
-
- if (ret == 0)
- break;
-
- sent += ret;
- size -= ret;
- }
-
- return sent;
-}
diff --git a/xbmc/lib/libshout/socklib.h b/xbmc/lib/libshout/socklib.h
deleted file mode 100644
index 6dca0a334a..0000000000
--- a/xbmc/lib/libshout/socklib.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __socklib_h__
-#define __socklib_h__
-
-#include "srtypes.h"
-
-#ifndef INADDR_NONE
-#define INADDR_NONE (-1)
-#endif
-
-error_code socklib_init ();
-error_code socklib_open (HSOCKET *socket_handle, char *host, int port, char *if_name);
-void socklib_close (HSOCKET *socket_handle);
-void socklib_cleanup ();
-error_code socklib_read_header (HSOCKET *socket_handle, char *buffer, int size,
- int (*recvall)(HSOCKET *sock, char* buffer, int size, int timeout));
-int socklib_recvall (HSOCKET *socket_handle, char* buffer, int size, int timeout);
-int socklib_sendall (HSOCKET *socket_handle, char* buffer, int size);
-error_code read_interface (char *if_name, uint32_t *addr);
-
-#endif //__socklib_h__
diff --git a/xbmc/lib/libshout/srconfig.h b/xbmc/lib/libshout/srconfig.h
deleted file mode 100644
index edf98b7e0d..0000000000
--- a/xbmc/lib/libshout/srconfig.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __SRCONFIG_H__
-#define __SRCONFIG_H__
-
-#if defined (WIN32)
-#include "confw32.h"
-#elif defined (HAVE_CONFIG_H)
-#include "config.h"
-#else
-/* Do something */
-#define HAVE_INTTYPES_H 1
-#define HAVE_STDINT_H 1
-#define HAVE_UINT32_T 1
-#define HAVE_U_INT32_T 1
-#endif
-
-#endif /* __SRCONFIG_H__ */
diff --git a/xbmc/lib/libshout/srtypes.h b/xbmc/lib/libshout/srtypes.h
deleted file mode 100644
index 6f8478f46a..0000000000
--- a/xbmc/lib/libshout/srtypes.h
+++ /dev/null
@@ -1,286 +0,0 @@
-#ifndef __SRTYPES_H__
-#define __SRTYPES_H__
-
-////////////////////////////////////////////////
-// Types
-////////////////////////////////////////////////
-#include "srconfig.h"
-#if WIN32
-#include <windows.h>
-#else
-#include <sys/types.h>
-#endif
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#if HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>
-#endif
-
-/* Note: uint32_t is standardized in ISO C99, so let's use that one */
-#if !HAVE_UINT32_T
-# if HAVE_U_INT32_T
-typedef u_int32_t uint32_t;
-# else
-typedef unsigned int uint32_t;
-# endif
-#endif
-
-#if HAVE_WCHAR_SUPPORT
-#if HAVE_WCHAR_H
-#include <wchar.h>
-#endif
-#if HAVE_WCTYPE_H
-#include <wctype.h>
-#endif
-#endif
-#if STDC_HEADERS
-#include <stddef.h>
-#endif
-
-typedef int error_code;
-#define BOOL int
-#define TRUE 1
-#define FALSE 0
-
-#define NO_META_INTERVAL -1
-
-/* GCS - Grr. I don't care. Max path is 254 until I get around to
- fixing this for other platforms. */
-#define SR_MAX_PATH 254
-#define MAX_HOST_LEN 512
-#define MAX_IP_LEN 3+1+3+1+3+1+3+1
-#define MAX_HEADER_LEN 8192
-#define MAX_URL_LEN 8192
-#define MAX_ICY_STRING 4024
-#define MAX_SERVER_LEN 1024
-//#define MAX_TRACK_LEN MAX_PATH
-#define MAX_TRACK_LEN SR_MAX_PATH /* GCS - be careful here... */
-#define MAX_URI_STRING 1024
-#define MAX_ERROR_STR (4096)
-#define MAX_USERAGENT_STR 1024
-#define MAX_AUTH_LEN 255
-//#define MAX_DROPSTRING_LEN 255
-
-#define MAX_METADATA_LEN (127*16)
-
-
-#ifdef WIN32
- #ifndef _WINSOCKAPI_
- #define __DEFINE_TYPES__
- #endif
-#endif
-
-#ifdef __DEFINE_TYPES__
-typedef unsigned long u_long;
-typedef unsigned char u_char;
-typedef unsigned short u_short;
-#endif
-
-/* Different types of streams */
-#define CONTENT_TYPE_MP3 1
-#define CONTENT_TYPE_NSV 2
-#define CONTENT_TYPE_OGG 3
-#define CONTENT_TYPE_ULTRAVOX 4
-#define CONTENT_TYPE_AAC 5
-#define CONTENT_TYPE_PLS 6
-#define CONTENT_TYPE_M3U 7
-#define CONTENT_TYPE_UNKNOWN 99
-
-/*
- * IO_DATA_INPUT is a interface for socket input data, it has one
- * method 'get_data' and is called by a "ripper" which is effectivly
- * only ripshout.c (and the R.I.P. riplive365.c)
- */
-typedef struct IO_DATA_INPUTst{
- int (*get_input_data)(char* buffer, int size);
-} IO_DATA_INPUT;
-
-#define NO_TRACK_STR "No track info..."
-
-/*
- * IO_GET_STREAM is an interface for getting data and track info from
- * a better splite on the track seperation. it keeps a back buffer and
- * does the "find silent point" shit.
- */
-#if defined (commentout)
-typedef struct IO_GET_STREAMst{
- int (*get_stream_data)(char* data_buf, char *track_buf);
- u_long getsize;
-} IO_GET_STREAM;
-#endif
-
-/*
- * SPLITPOINT_OPTIONS are the options used to tweek how the silence
- * separation is done.
- */
-typedef struct SPLITPOINT_OPTIONSst
-{
- int xs;
- int xs_min_volume;
- int xs_silence_length;
- int xs_search_window_1;
- int xs_search_window_2;
- int xs_offset;
- //int xd_offset;
- //int xpadding_1;
- //int xpadding_2;
- int xs_padding_1;
- int xs_padding_2;
-} SPLITPOINT_OPTIONS;
-
-/*
- * CODESET_OPTIONS are the options used to decide how to parse
- * and convert the metadata
- */
-#define MAX_CODESET_STRING 128
-typedef struct CODESET_OPTIONSst
-{
- char codeset_locale[MAX_CODESET_STRING];
- char codeset_filesys[MAX_CODESET_STRING];
- char codeset_id3[MAX_CODESET_STRING];
- char codeset_metadata[MAX_CODESET_STRING];
- char codeset_relay[MAX_CODESET_STRING];
-} CODESET_OPTIONS;
-
-/*
- * Various CODESET types
- */
-#define CODESET_UTF8 1
-#define CODESET_LOCALE 2
-#define CODESET_FILESYS 3
-#define CODESET_ID3 4
-#define CODESET_METADATA 5
-#define CODESET_RELAY 6
-
-/*
- * Wide character support
- */
-#if HAVE_WCHAR_SUPPORT
-typedef wchar_t mchar;
-#else
-typedef char mchar;
-#endif
-
-/*
- * TRACK_INFO is the parsed metadata
- */
-typedef struct TRACK_INFOst
-{
- int have_track_info;
- char raw_metadata[MAX_TRACK_LEN];
- mchar w_raw_metadata[MAX_TRACK_LEN];
- mchar artist[MAX_TRACK_LEN];
- mchar title[MAX_TRACK_LEN];
- mchar album[MAX_TRACK_LEN];
- mchar track[MAX_TRACK_LEN];
- char composed_metadata[MAX_METADATA_LEN+1]; /* For relay stream */
- BOOL save_track;
-} TRACK_INFO;
-
-
-#ifndef WIN32
-typedef int SOCKET;
-#endif
-
-typedef struct HSOCKETst
-{
- SOCKET s;
- BOOL closed;
-} HSOCKET;
-
-/*
- * OverwriteOpt controls how files in complete directory are overwritten
- */
-enum OverwriteOpt {
- OVERWRITE_UNKNOWN, // Error case
- OVERWRITE_ALWAYS, // Always replace file in complete with newer
- OVERWRITE_NEVER, // Never replace file in complete with newer
- OVERWRITE_LARGER // Replace file in complete if newer is larger
-};
-
-
-////////////////////////////////////////////////
-// StreamRipper Codes
-////////////////////////////////////////////////
-// JCBUG -- no way to make custom error strings for http errors, also errors
-// are not organized at all, should have space to insert in places.
-//
-/* ************** IMPORTANT IF YOU ADD ERROR CODES!!!! ***********************/
-#define NUM_ERROR_CODES ((0x41)+1)
-/* ************** IMPORTANT IF YOU ADD ERROR CODES!!!! ***********************/
-#define SR_SUCCESS 0x00
-#define SR_SUCCESS_BUFFERING 0x01
-#define SR_ERROR_CANT_FIND_TRACK_SEPERATION - 0x01
-#define SR_ERROR_DECODE_FAILURE - 0x02
-#define SR_ERROR_INVALID_URL - 0x03
-#define SR_ERROR_WIN32_INIT_FAILURE - 0x04
-#define SR_ERROR_CONNECT_FAILED - 0x05
-#define SR_ERROR_CANT_RESOLVE_HOSTNAME - 0x06
-#define SR_ERROR_RECV_FAILED - 0x07
-#define SR_ERROR_SEND_FAILED - 0x08
-#define SR_ERROR_PARSE_FAILURE - 0x09
-#define SR_ERROR_NO_RESPOSE_HEADER - 0x0a
-#define SR_ERROR_NO_ICY_CODE - 0x0b
-#define SR_ERROR_NO_META_INTERVAL - 0x0c
-#define SR_ERROR_INVALID_PARAM - 0x0d
-#define SR_ERROR_NO_HTTP_HEADER - 0x0e
-#define SR_ERROR_CANT_GET_LIVE365_ID - 0x0f
-#define SR_ERROR_CANT_ALLOC_MEMORY - 0x10
-#define SR_ERROR_CANT_FIND_IP_PORT - 0x11
-#define SR_ERROR_CANT_FIND_MEMBERNAME - 0x12
-#define SR_ERROR_CANT_FIND_TRACK_NAME - 0x13
-#define SR_ERROR_NULL_MEMBER_NAME - 0x14
-#define SR_ERROR_CANT_FIND_TIME_TAG - 0x15
-#define SR_ERROR_BUFFER_EMPTY - 0x16
-#define SR_ERROR_BUFFER_FULL - 0x17
-#define SR_ERROR_CANT_INIT_XAUDIO - 0x18
-#define SR_ERROR_BUFFER_TOO_SMALL - 0x19
-#define SR_ERROR_CANT_CREATE_THREAD - 0x1A
-#define SR_ERROR_CANT_FIND_MPEG_HEADER - 0x1B
-#define SR_ERROR_INVALID_METADATA - 0x1C
-#define SR_ERROR_NO_TRACK_INFO - 0x1D
-#define SR_EEROR_CANT_FIND_SUBSTR - 0x1E
-#define SR_ERROR_CANT_BIND_ON_PORT - 0x1F
-#define SR_ERROR_HOST_NOT_CONNECTED - 0x20
-#define SR_ERROR_HTTP_404_ERROR - 0x21
-#define SR_ERROR_HTTP_401_ERROR - 0x22
-#define SR_ERROR_HTTP_502_ERROR - 0x23 // Connection Refused
-#define SR_ERROR_CANT_CREATE_FILE - 0x24
-#define SR_ERROR_CANT_WRITE_TO_FILE - 0x25
-#define SR_ERROR_CANT_CREATE_DIR - 0x26
-#define SR_ERROR_HTTP_400_ERROR - 0x27 // Server Full
-#define SR_ERROR_CANT_SET_SOCKET_OPTIONS - 0x28
-#define SR_ERROR_SOCK_BASE - 0x29
-#define SR_ERROR_INVALID_DIRECTORY - 0x2a
-#define SR_ERROR_FAILED_TO_MOVE_FILE - 0x2b
-#define SR_ERROR_CANT_LOAD_MPGLIB - 0x2c
-#define SR_ERROR_CANT_INIT_MPGLIB - 0x2d
-#define SR_ERROR_CANT_UNLOAD_MPGLIB - 0x2e
-#define SR_ERROR_PCM_BUFFER_TO_SMALL - 0x2f
-#define SR_ERROR_CANT_DECODE_MP3 - 0x30
-#define SR_ERROR_SOCKET_CLOSED - 0x31
-#define SR_ERROR_LIVE365 - 0x32
-#define SR_ERROR_MAX_BYTES_RIPPED - 0x33
-#define SR_ERROR_CANT_WAIT_ON_THREAD - 0x34
-#define SR_ERROR_CANT_CREATE_EVENT - 0x35
-#define SR_ERROR_NOT_SHOUTCAST_STREAM - 0x36
-#define SR_ERROR_HTTP_407_ERROR - 0x37
-#define SR_ERROR_HTTP_403_ERROR - 0x38
-#define SR_ERROR_DIR_PATH_TOO_LONG - 0x39
-#define SR_ERROR_PROGRAM_ERROR - 0x3a
-#define SR_ERROR_TIMEOUT - 0x3b
-#define SR_ERROR_SELECT_FAILED - 0x3c
-#define SR_ERROR_REQUIRED_WINDOW_EMPTY - 0x3d // Not an error
-#define SR_ERROR_CANT_BIND_ON_INTERFACE - 0x3e
-#define SR_ERROR_NO_OGG_PAGES_FOR_RELAY - 0x3f
-#define SR_ERROR_CANT_PARSE_PLS - 0x40
-#define SR_ERROR_CANT_PARSE_M3U - 0x41
-
-#endif //__SRIPPER_H__
diff --git a/xbmc/lib/libshout/threadlib.c b/xbmc/lib/libshout/threadlib.c
deleted file mode 100644
index 63241a1acf..0000000000
--- a/xbmc/lib/libshout/threadlib.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* threadlib.c - jonclegg@yahoo.com
- * really bad threading library from hell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#if WIN32
-#include <process.h>
-#include <windows.h>
-#elif __UNIX__
-#include <pthread.h>
-#elif __BEOS__
-#include <be/kernel/OS.h>
-#endif
-#include <stdio.h>
-#include <time.h>
-#include "srtypes.h"
-#include "threadlib.h"
-#include "debug.h"
-
-#if defined (commentout)
-#if WIN32
- #define beginthread(thread, callback) \
- _beginthread((void *)callback, 0, (void *)NULL)
-#elif __UNIX__
- #include <unistd.h>
- #define beginthread(thread, callback) \
- pthread_create(thread, NULL, \
- (void *)callback, (void *)NULL)
-#endif
-#endif
-
-/******************************************************************************
- * Public functions
- *****************************************************************************/
-error_code
-threadlib_beginthread (THREAD_HANDLE *thread, void (*callback)(void *), void* arg)
-{
- BeginThread (thread->thread_handle, callback, arg);
- //if (thread->thread_handle == NULL) // don't feel like porting this
- // return SR_ERROR_CANT_CREATE_THREAD;
-
- return SR_SUCCESS;
-}
-
-void
-threadlib_waitforclose(THREAD_HANDLE *thread)
-{
- WaitForThread(thread->thread_handle);
-}
-
-HSEM threadlib_create_sem()
-{
- HSEM s;
- SemInit(s);
- return s;
-}
-
-error_code threadlib_waitfor_sem(HSEM *e)
-{
- if (!e)
- return SR_ERROR_INVALID_PARAM;
- SemWait(*e);
- return SR_SUCCESS;
-}
-
-error_code
-threadlib_signal_sem(HSEM *e)
-{
- if (!e)
- return SR_ERROR_INVALID_PARAM;
- SemPost(*e);
- return SR_SUCCESS;
-}
-
-void threadlib_destroy_sem(HSEM *e)
-{
- DestroyThread(*e);
-}
diff --git a/xbmc/lib/libshout/threadlib.h b/xbmc/lib/libshout/threadlib.h
deleted file mode 100644
index a9fd7b10c2..0000000000
--- a/xbmc/lib/libshout/threadlib.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __THREADLIB_H__
-#define __THREADLIB_H__
-
-#include "srtypes.h"
-#include "compat.h"
-
-typedef struct THREAD_HANDLEst
-{
- THANDLE thread_handle;
-} THREAD_HANDLE;
-
-
-/*********************************************************************************
- * Public functions
- *********************************************************************************/
-error_code threadlib_beginthread (THREAD_HANDLE *thread, void (*callback)(void *), void* arg);
-extern BOOL threadlib_isrunning(THREAD_HANDLE *thread);
-extern void threadlib_waitforclose(THREAD_HANDLE *thread);
-extern void threadlib_endthread(THREAD_HANDLE *thread);
-extern BOOL threadlib_sem_signaled(HSEM *e);
-
-extern HSEM threadlib_create_sem();
-extern error_code threadlib_waitfor_sem(HSEM *e);
-extern error_code threadlib_signal_sem(HSEM *e);
-extern void threadlib_destroy_sem(HSEM *e);
-
-
-#endif //__THREADLIB__
diff --git a/xbmc/lib/libshout/uce_dirent.h b/xbmc/lib/libshout/uce_dirent.h
deleted file mode 100644
index 7d45116b47..0000000000
--- a/xbmc/lib/libshout/uce_dirent.h
+++ /dev/null
@@ -1,681 +0,0 @@
-/*
- * uce-dirent.h - operating system independent dirent implementation
- *
- * Copyright (C) 1998-2002 Toni Ronkko
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * ``Software''), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- * May 28 1998, Toni Ronkko <tronkko@messi.uku.fi>
- *
- * $Id: uce_dirent.h,v 1.1 2005/07/10 19:24:57 gregsharp Exp $
- *
- * $Log: uce_dirent.h,v $
- * Revision 1.1 2005/07/10 19:24:57 gregsharp
- * Add this cool dirent compatibility layer file.
- *
- * Revision 1.7 2002/05/13 10:48:35 tr
- * embedded some source code directly to the header so that no source
- * modules need to be included in the MS Visual C project using the
- * interface, removed all the dependencies to other headers of the `uce'
- * library so that the header can be made public
- *
- * Revision 1.6 2002/04/12 16:22:04 tr
- * Unified Compiling Environment (UCE) replaced `std' library
- *
- * Revision 1.5 2001/07/20 16:33:40 tr
- * moved to `std' library and re-named defines accordingly
- *
- * Revision 1.4 2001/07/10 16:47:18 tronkko
- * revised comments
- *
- * Revision 1.3 2001/01/11 13:16:43 tr
- * using ``uce-machine.h'' for finding out defines such as `FREEBSD'
- *
- * Revision 1.2 2000/10/08 16:00:41 tr
- * copy of FreeBSD man page
- *
- * Revision 1.1 2000/07/10 05:53:16 tr
- * Initial revision
- *
- * Revision 1.2 1998/07/19 18:29:14 tr
- * Added error reporting capabilities and some asserts.
- *
- * Revision 1.1 1998/07/04 16:27:51 tr
- * Initial revision
- *
- *
- * MSVC 1.0 scans automatic dependencies incorrectly when your project
- * contains this very header. The problem is that MSVC cannot handle
- * include directives inside #if..#endif block those are never entered.
- * Since this header ought to compile in many different operating systems,
- * there had to be several conditional blocks that are compiled only in
- * operating systems for what they were designed for. MSVC 1.0 cannot
- * handle inclusion of sys/dir.h in a part that is compiled only in Apollo
- * operating system. To fix the problem you need to insert DIR.H into
- * SYSINCL.DAT located in MSVC\BIN directory and restart visual C++.
- * Consult manuals for more informaton about the problem.
- *
- * Since many UNIX systems have dirent.h we assume to have one also.
- * However, if your UNIX system does not have dirent.h you can download one
- * for example at: http://ftp.uni-mannheim.de/ftp/GNU/dirent/dirent.tar.gz.
- * You can also see if you have one of dirent.h, direct.h, dir.h, ndir.h,
- * sys/dir.h and sys/ndir.h somewhere. Try defining HAVE_DIRENT_H,
- * HAVE_DIRECT_H, HAVE_DIR_H, HAVE_NDIR_H, HAVE_SYS_DIR_H and
- * HAVE_SYS_NDIR_H according to the files found.
- */
-#ifndef DIRENT_H
-#define DIRENT_H
-#define DIRENT_H_INCLUDED
-
-/* find out platform */
-#if defined(MSDOS) /* MS-DOS */
-#elif defined(__MSDOS__) /* Turbo C/Borland */
-# define MSDOS
-#elif defined(__DOS__) /* Watcom */
-# define MSDOS
-#endif
-
-#if defined(WIN32) /* MS-Windows */
-#elif defined(__NT__) /* Watcom */
-# define WIN32
-#elif defined(_WIN32) /* Microsoft */
-# define WIN32
-#elif defined(__WIN32__) /* Borland */
-# define WIN32
-#endif
-
-/*
- * See what kind of dirent interface we have unless autoconf has already
- * determinated that.
- */
-#if !defined(HAVE_DIRENT_H) && !defined(HAVE_DIRECT_H) && !defined(HAVE_SYS_DIR_H) && !defined(HAVE_NDIR_H) && !defined(HAVE_SYS_NDIR_H) && !defined(HAVE_DIR_H)
-# if defined(_MSC_VER) /* Microsoft C/C++ */
- /* no dirent.h */
-# elif defined(__BORLANDC__) /* Borland C/C++ */
-# define HAVE_DIRENT_H
-# define VOID_CLOSEDIR
-# elif defined(__TURBOC__) /* Borland Turbo C */
- /* no dirent.h */
-# elif defined(__WATCOMC__) /* Watcom C/C++ */
-# define HAVE_DIRECT_H
-# elif defined(__apollo) /* Apollo */
-# define HAVE_SYS_DIR_H
-# elif defined(__hpux) /* HP-UX */
-# define HAVE_DIRENT_H
-# elif defined(__alpha) || defined(__alpha__) /* Alpha OSF1 */
-# error "not implemented"
-# elif defined(__sgi) /* Silicon Graphics */
-# define HAVE_DIRENT_H
-# elif defined(sun) || defined(_sun) /* Sun Solaris */
-# define HAVE_DIRENT_H
-# elif defined(__FreeBSD__) /* FreeBSD */
-# define HAVE_DIRENT_H
-# elif defined(__linux__) /* Linux */
-# define HAVE_DIRENT_H
-# elif defined(__GNUC__) /* GNU C/C++ */
-# define HAVE_DIRENT_H
-# else
-# error "not implemented"
-# endif
-#endif
-
-/* include proper interface headers */
-#if defined(HAVE_DIRENT_H)
-# include <dirent.h>
-# ifdef FREEBSD
-# define NAMLEN(dp) ((int)((dp)->d_namlen))
-# else
-# define NAMLEN(dp) ((int)(strlen((dp)->d_name)))
-# endif
-
-#elif defined(HAVE_NDIR_H)
-# include <ndir.h>
-# define NAMLEN(dp) ((int)((dp)->d_namlen))
-
-#elif defined(HAVE_SYS_NDIR_H)
-# include <sys/ndir.h>
-# define NAMLEN(dp) ((int)((dp)->d_namlen))
-
-#elif defined(HAVE_DIRECT_H)
-# include <direct.h>
-# define NAMLEN(dp) ((int)((dp)->d_namlen))
-
-#elif defined(HAVE_DIR_H)
-# include <dir.h>
-# define NAMLEN(dp) ((int)((dp)->d_namlen))
-
-#elif defined(HAVE_SYS_DIR_H)
-# include <sys/types.h>
-# include <sys/dir.h>
-# ifndef dirent
-# define dirent direct
-# endif
-# define NAMLEN(dp) ((int)((dp)->d_namlen))
-
-#elif defined(MSDOS) || defined(WIN32)
-
- /* figure out type of underlaying directory interface to be used */
-# if defined(WIN32)
-# define DIRENT_WIN32_INTERFACE
-# elif defined(MSDOS)
-# define DIRENT_MSDOS_INTERFACE
-# else
-# error "missing native dirent interface"
-# endif
-
- /*** WIN32 specifics ***/
-# if defined(DIRENT_WIN32_INTERFACE)
-# include <windows.h>
-# if !defined(DIRENT_MAXNAMLEN)
-# define DIRENT_MAXNAMLEN (MAX_PATH)
-# endif
-
-
- /*** MS-DOS specifics ***/
-# elif defined(DIRENT_MSDOS_INTERFACE)
-# include <dos.h>
-
- /* Borland defines file length macros in dir.h */
-# if defined(__BORLANDC__)
-# include <dir.h>
-# if !defined(DIRENT_MAXNAMLEN)
-# define DIRENT_MAXNAMLEN ((MAXFILE)+(MAXEXT))
-# endif
-# if !defined(_find_t)
-# define _find_t find_t
-# endif
-
- /* Turbo C defines ffblk structure in dir.h */
-# elif defined(__TURBOC__)
-# include <dir.h>
-# if !defined(DIRENT_MAXNAMLEN)
-# define DIRENT_MAXNAMLEN ((MAXFILE)+(MAXEXT))
-# endif
-# define DIRENT_USE_FFBLK
-
- /* MSVC */
-# elif defined(_MSC_VER)
-# if !defined(DIRENT_MAXNAMLEN)
-# define DIRENT_MAXNAMLEN (12)
-# endif
-
- /* Watcom */
-# elif defined(__WATCOMC__)
-# if !defined(DIRENT_MAXNAMLEN)
-# if defined(__OS2__) || defined(__NT__)
-# define DIRENT_MAXNAMLEN (255)
-# else
-# define DIRENT_MAXNAMLEN (12)
-# endif
-# endif
-
-# endif
-# endif
-
- /*** generic MS-DOS and MS-Windows stuff ***/
-# if !defined(NAME_MAX) && defined(DIRENT_MAXNAMLEN)
-# define NAME_MAX DIRENT_MAXNAMLEN
-# endif
-# if NAME_MAX < DIRENT_MAXNAMLEN
-# error "assertion failed: NAME_MAX >= DIRENT_MAXNAMLEN"
-# endif
-
-
- /*
- * Substitute for real dirent structure. Note that `d_name' field is a
- * true character array although we have it copied in the implementation
- * dependent data. We could save some memory if we had declared `d_name'
- * as a pointer refering the name within implementation dependent data.
- * We have not done that since some code may rely on sizeof(d_name) to be
- * something other than four. Besides, directory entries are typically so
- * small that it takes virtually no time to copy them from place to place.
- */
- typedef struct dirent {
- char d_name[NAME_MAX + 1];
-
- /*** Operating system specific part ***/
-# if defined(DIRENT_WIN32_INTERFACE) /*WIN32*/
- WIN32_FIND_DATA data;
-# elif defined(DIRENT_MSDOS_INTERFACE) /*MSDOS*/
-# if defined(DIRENT_USE_FFBLK)
- struct ffblk data;
-# else
- struct _find_t data;
-# endif
-# endif
- } dirent;
-
- /* DIR substitute structure containing directory name. The name is
- * essential for the operation of ``rewinndir'' function. */
- typedef struct DIR {
- char *dirname; /* directory being scanned */
- dirent current; /* current entry */
- int dirent_filled; /* is current un-processed? */
-
- /*** Operating system specific part ***/
-# if defined(DIRENT_WIN32_INTERFACE)
- HANDLE search_handle;
-# elif defined(DIRENT_MSDOS_INTERFACE)
-# endif
- } DIR;
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-/* supply prototypes for dirent functions */
-static DIR *opendir (const char *dirname);
-static struct dirent *readdir (DIR *dirp);
-static int closedir (DIR *dirp);
-static void rewinddir (DIR *dirp);
-
-/*
- * Implement dirent interface as static functions so that the user does not
- * need to change his project in any way to use dirent function. With this
- * it is sufficient to include this very header from source modules using
- * dirent functions and the functions will be pulled in automatically.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-/* use ffblk instead of _find_t if requested */
-#if defined(DIRENT_USE_FFBLK)
-# define _A_ARCH (FA_ARCH)
-# define _A_HIDDEN (FA_HIDDEN)
-# define _A_NORMAL (0)
-# define _A_RDONLY (FA_RDONLY)
-# define _A_SUBDIR (FA_DIREC)
-# define _A_SYSTEM (FA_SYSTEM)
-# define _A_VOLID (FA_LABEL)
-# define _dos_findnext(dest) findnext(dest)
-# define _dos_findfirst(name,flags,dest) findfirst(name,dest,flags)
-#endif
-
-static int _initdir (DIR *p);
-static const char *_getdirname (const struct dirent *dp);
-static void _setdirname (struct DIR *dirp);
-
-/*
- * <function name="opendir">
- * <intro>open directory stream for reading
- * <syntax>DIR *opendir (const char *dirname);
- *
- * <desc>Open named directory stream for read and return pointer to the
- * internal working area that is used for retrieving individual directory
- * entries. The internal working area has no fields of your interest.
- *
- * <ret>Returns a pointer to the internal working area or NULL in case the
- * directory stream could not be opened. Global `errno' variable will set
- * in case of error as follows:
- *
- * <table>
- * [EACESS |Permission denied.
- * [EMFILE |Too many open files used by the process.
- * [ENFILE |Too many open files in system.
- * [ENOENT |Directory does not exist.
- * [ENOMEM |Insufficient memory.
- * [ENOTDIR |dirname does not refer to directory. This value is not
- * reliable on MS-DOS and MS-Windows platforms. Many
- * implementations return ENOENT even when the name refers to a
- * file.]
- * </table>
- * </function>
- */
-static DIR *
-opendir(
- const char *dirname)
-{
- DIR *dirp;
- assert (dirname != NULL);
-
- dirp = (DIR*)malloc (sizeof (struct DIR));
- if (dirp != NULL) {
- char *p;
-
- /* allocate room for directory name */
- dirp->dirname = (char*) malloc (strlen (dirname) + 1 + strlen ("\\*.*"));
- if (dirp->dirname == NULL) {
- /* failed to duplicate directory name. errno set by malloc() */
- free (dirp);
- return NULL;
- }
- /* Copy directory name while appending directory separator and "*.*".
- * Directory separator is not appended if the name already ends with
- * drive or directory separator. Directory separator is assumed to be
- * '/' or '\' and drive separator is assumed to be ':'. */
- strcpy (dirp->dirname, dirname);
- p = strchr (dirp->dirname, '\0');
- if (dirp->dirname < p &&
- *(p - 1) != '\\' && *(p - 1) != '/' && *(p - 1) != ':')
- {
- strcpy (p++, "\\");
- }
-# ifdef DIRENT_WIN32_INTERFACE
- strcpy (p, "*"); /*scan files with and without extension in win32*/
-# else
- strcpy (p, "*.*"); /*scan files with and without extension in DOS*/
-# endif
-
- /* open stream */
- if (_initdir (dirp) == 0) {
- /* initialization failed */
- free (dirp->dirname);
- free (dirp);
- return NULL;
- }
- }
- return dirp;
-}
-
-
-/*
- * <function name="readdir">
- * <intro>read a directory entry
- * <syntax>struct dirent *readdir (DIR *dirp);
- *
- * <desc>Read individual directory entry and return pointer to a structure
- * containing the name of the entry. Individual directory entries returned
- * include normal files, sub-directories, pseudo-directories "." and ".."
- * and also volume labels, hidden files and system files in MS-DOS and
- * MS-Windows. You might want to use stat(2) function to determinate which
- * one are you dealing with. Many dirent implementations already contain
- * equivalent information in dirent structure but you cannot depend on
- * this.
- *
- * The dirent structure contains several system dependent fields that
- * generally have no interest to you. The only interesting one is char
- * d_name[] that is also portable across different systems. The d_name
- * field contains the name of the directory entry without leading path.
- * While d_name is portable across different systems the actual storage
- * capacity of d_name varies from system to system and there is no portable
- * way to find out it at compile time as different systems define the
- * capacity of d_name with different macros and some systems do not define
- * capacity at all (besides actual declaration of the field). If you really
- * need to find out storage capacity of d_name then you might want to try
- * NAME_MAX macro. The NAME_MAX is defined in POSIX standard althought
- * there are many MS-DOS and MS-Windows implementations those do not define
- * it. There are also systems that declare d_name as "char d_name[1]" and
- * then allocate suitable amount of memory at run-time. Thanks to Alain
- * Decamps (Alain.Decamps@advalvas.be) for pointing it out to me.
- *
- * This all leads to the fact that it is difficult to allocate space
- * for the directory names when the very same program is being compiled on
- * number of operating systems. Therefore I suggest that you always
- * allocate space for directory names dynamically.
- *
- * <ret>
- * Returns a pointer to a structure containing name of the directory entry
- * in `d_name' field or NULL if there was an error. In case of an error the
- * global `errno' variable will set as follows:
- *
- * <table>
- * [EBADF |dir parameter refers to an invalid directory stream. This value
- * is not set reliably on all implementations.]
- * </table>
- * </function>
- */
-static struct dirent *
-readdir (DIR *dirp)
-{
- assert (dirp != NULL);
- if (dirp == NULL) {
- errno = EBADF;
- return NULL;
- }
-
-#if defined(DIRENT_WIN32_INTERFACE)
- if (dirp->search_handle == INVALID_HANDLE_VALUE) {
- /* directory stream was opened/rewound incorrectly or it ended normally */
- errno = EBADF;
- return NULL;
- }
-#endif
-
- if (dirp->dirent_filled != 0) {
- /*
- * Directory entry has already been retrieved and there is no need to
- * retrieve a new one. Directory entry will be retrieved in advance
- * when the user calls readdir function for the first time. This is so
- * because real dirent has separate functions for opening and reading
- * the stream whereas Win32 and DOS dirents open the stream
- * automatically when we retrieve the first file. Therefore, we have to
- * save the first file when opening the stream and later we have to
- * return the saved entry when the user tries to read the first entry.
- */
- dirp->dirent_filled = 0;
- } else {
- /* fill in entry and return that */
-#if defined(DIRENT_WIN32_INTERFACE)
- if (FindNextFile (dirp->search_handle, &dirp->current.data) == FALSE) {
- /* Last file has been processed or an error occured */
- FindClose (dirp->search_handle);
- dirp->search_handle = INVALID_HANDLE_VALUE;
- errno = ENOENT;
- return NULL;
- }
-
-# elif defined(DIRENT_MSDOS_INTERFACE)
- if (_dos_findnext (&dirp->current.data) != 0) {
- /* _dos_findnext and findnext will set errno to ENOENT when no
- * more entries could be retrieved. */
- return NULL;
- }
-# endif
-
- _setdirname (dirp);
- assert (dirp->dirent_filled == 0);
- }
- return &dirp->current;
-}
-
-
-/*
- * <function name="closedir">
- * <intro>close directory stream.
- * <syntax>int closedir (DIR *dirp);
- *
- * <desc>Close directory stream opened by the `opendir' function. Close of
- * directory stream invalidates the DIR structure as well as previously read
- * dirent entry.
- *
- * <ret>The function typically returns 0 on success and -1 on failure but
- * the function may be declared to return void on same systems. At least
- * Borland C/C++ and some UNIX implementations use void as a return type.
- * The dirent wrapper tries to define VOID_CLOSEDIR whenever closedir is
- * known to return nothing. The very same definition is made by the GNU
- * autoconf if you happen to use it.
- *
- * The global `errno' variable will set to EBADF in case of error.
- * </function>
- */
-static int
-closedir (DIR *dirp)
-{
- int retcode = 0;
-
- /* make sure that dirp points to legal structure */
- assert (dirp != NULL);
- if (dirp == NULL) {
- errno = EBADF;
- return -1;
- }
-
- /* free directory name and search handles */
- if (dirp->dirname != NULL) free (dirp->dirname);
-
-#if defined(DIRENT_WIN32_INTERFACE)
- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
- if (FindClose (dirp->search_handle) == FALSE) {
- /* Unknown error */
- retcode = -1;
- errno = EBADF;
- }
- }
-#endif
-
- /* clear dirp structure to make sure that it cannot be used anymore*/
- memset (dirp, 0, sizeof (*dirp));
-# if defined(DIRENT_WIN32_INTERFACE)
- dirp->search_handle = INVALID_HANDLE_VALUE;
-# endif
-
- free (dirp);
- return retcode;
-}
-
-
-/*
- * <function name="rewinddir">
- * <intro>rewind directory stream to the beginning
- * <syntax>void rewinddir (DIR *dirp);
- *
- * <desc>Rewind directory stream to the beginning so that the next call of
- * readdir() returns the very first directory entry again. However, note
- * that next call of readdir() may not return the same directory entry as it
- * did in first time. The directory stream may have been affected by newly
- * created files.
- *
- * Almost every dirent implementation ensure that rewinddir will update
- * the directory stream to reflect any changes made to the directory entries
- * since the previous ``opendir'' or ``rewinddir'' call. Keep an eye on
- * this if your program depends on the feature. I know at least one dirent
- * implementation where you are required to close and re-open the stream to
- * see the changes.
- *
- * <ret>Returns nothing. If something went wrong while rewinding, you will
- * notice it later when you try to retrieve the first directory entry.
- */
-static void
-rewinddir (DIR *dirp)
-{
- /* make sure that dirp is legal */
- assert (dirp != NULL);
- if (dirp == NULL) {
- errno = EBADF;
- return;
- }
- assert (dirp->dirname != NULL);
-
- /* close previous stream */
-#if defined(DIRENT_WIN32_INTERFACE)
- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
- if (FindClose (dirp->search_handle) == FALSE) {
- /* Unknown error */
- errno = EBADF;
- }
- }
-#endif
-
- /* re-open previous stream */
- if (_initdir (dirp) == 0) {
- /* initialization failed but we cannot deal with error. User will notice
- * error later when she tries to retrieve first directory enty. */
- /*EMPTY*/;
- }
-}
-
-
-/*
- * Open native directory stream object and retrieve first file.
- * Be sure to close previous stream before opening new one.
- */
-static int
-_initdir (DIR *dirp)
-{
- assert (dirp != NULL);
- assert (dirp->dirname != NULL);
- dirp->dirent_filled = 0;
-
-# if defined(DIRENT_WIN32_INTERFACE)
- /* Open stream and retrieve first file */
- dirp->search_handle = FindFirstFile (dirp->dirname, &dirp->current.data);
- if (dirp->search_handle == INVALID_HANDLE_VALUE) {
- /* something went wrong but we don't know what. GetLastError() could
- * give us more information about the error, but then we should map
- * the error code into errno. */
- errno = ENOENT;
- return 0;
- }
-
-# elif defined(DIRENT_MSDOS_INTERFACE)
- if (_dos_findfirst (dirp->dirname,
- _A_SUBDIR | _A_RDONLY | _A_ARCH | _A_SYSTEM | _A_HIDDEN,
- &dirp->current.data) != 0)
- {
- /* _dos_findfirst and findfirst will set errno to ENOENT when no
- * more entries could be retrieved. */
- return 0;
- }
-# endif
-
- /* initialize DIR and it's first entry */
- _setdirname (dirp);
- dirp->dirent_filled = 1;
- return 1;
-}
-
-
-/*
- * Return implementation dependent name of the current directory entry.
- */
-static const char *
-_getdirname (const struct dirent *dp)
-{
-#if defined(DIRENT_WIN32_INTERFACE)
- return dp->data.cFileName;
-
-#elif defined(DIRENT_USE_FFBLK)
- return dp->data.ff_name;
-
-#else
- return dp->data.name;
-#endif
-}
-
-
-/*
- * Copy name of implementation dependent directory entry to the d_name field.
- */
-static void
-_setdirname (struct DIR *dirp) {
- /* make sure that d_name is long enough */
- assert (strlen (_getdirname (&dirp->current)) <= NAME_MAX);
-
- strncpy (dirp->current.d_name,
- _getdirname (&dirp->current),
- NAME_MAX);
- dirp->current.d_name[NAME_MAX] = '\0'; /*char d_name[NAME_MAX+1]*/
-}
-
-# ifdef __cplusplus
-}
-# endif
-# define NAMLEN(dp) ((int)(strlen((dp)->d_name)))
-
-#else
-# error "missing dirent interface"
-#endif
-
-
-#endif /*DIRENT_H*/
diff --git a/xbmc/lib/libshout/utf8.c b/xbmc/lib/libshout/utf8.c
deleted file mode 100644
index 06a5727394..0000000000
--- a/xbmc/lib/libshout/utf8.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (C) 2001 Peter Harris <peter.harris@hummingbird.com>
- * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (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
- */
-
-/*
- * Convert a string between UTF-8 and the locale's charset.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "utf8.h"
-#include "charset.h"
-
-#ifdef _WIN32
-
- /* Thanks to Peter Harris <peter.harris@hummingbird.com> for this win32
- * code.
- */
-
-#include <stdio.h>
-#include <windows.h>
-
-static unsigned char *make_utf8_string(const wchar_t *unicode)
-{
- int size = 0, index = 0, out_index = 0;
- unsigned char *out;
- unsigned short c;
-
- /* first calculate the size of the target string */
- c = unicode[index++];
- while(c) {
- if(c < 0x0080) {
- size += 1;
- } else if(c < 0x0800) {
- size += 2;
- } else {
- size += 3;
- }
- c = unicode[index++];
- }
-
- out = malloc(size + 1);
- if (out == NULL)
- return NULL;
- index = 0;
-
- c = unicode[index++];
- while(c)
- {
- if(c < 0x080) {
- out[out_index++] = (unsigned char)c;
- } else if(c < 0x800) {
- out[out_index++] = 0xc0 | (c >> 6);
- out[out_index++] = 0x80 | (c & 0x3f);
- } else {
- out[out_index++] = 0xe0 | (c >> 12);
- out[out_index++] = 0x80 | ((c >> 6) & 0x3f);
- out[out_index++] = 0x80 | (c & 0x3f);
- }
- c = unicode[index++];
- }
- out[out_index] = 0x00;
-
- return out;
-}
-
-static wchar_t *make_unicode_string(const unsigned char *utf8)
-{
- int size = 0, index = 0, out_index = 0;
- wchar_t *out;
- unsigned char c;
-
- /* first calculate the size of the target string */
- c = utf8[index++];
- while(c) {
- if((c & 0x80) == 0) {
- index += 0;
- } else if((c & 0xe0) == 0xe0) {
- index += 2;
- } else {
- index += 1;
- }
- size += 1;
- c = utf8[index++];
- }
-
- out = malloc((size + 1) * sizeof(wchar_t));
- if (out == NULL)
- return NULL;
- index = 0;
-
- c = utf8[index++];
- while(c)
- {
- if((c & 0x80) == 0) {
- out[out_index++] = c;
- } else if((c & 0xe0) == 0xe0) {
- out[out_index] = (c & 0x1F) << 12;
- c = utf8[index++];
- out[out_index] |= (c & 0x3F) << 6;
- c = utf8[index++];
- out[out_index++] |= (c & 0x3F);
- } else {
- out[out_index] = (c & 0x3F) << 6;
- c = utf8[index++];
- out[out_index++] |= (c & 0x3F);
- }
- c = utf8[index++];
- }
- out[out_index] = 0;
-
- return out;
-}
-
-int utf8_encode(const char *from, char **to)
-{
- wchar_t *unicode;
- int wchars, err;
-
- wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from,
- strlen(from), NULL, 0);
-
- if(wchars == 0)
- {
- fprintf(stderr, "Unicode translation error %d\n", GetLastError());
- return -1;
- }
-
- unicode = calloc(wchars + 1, sizeof(unsigned short));
- if(unicode == NULL)
- {
- fprintf(stderr, "Out of memory processing string to UTF8\n");
- return -1;
- }
-
- err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from,
- strlen(from), unicode, wchars);
- if(err != wchars)
- {
- free(unicode);
- fprintf(stderr, "Unicode translation error %d\n", GetLastError());
- return -1;
- }
-
- /* On NT-based windows systems, we could use WideCharToMultiByte(), but
- * MS doesn't actually have a consistent API across win32.
- */
- *to = make_utf8_string(unicode);
-
- free(unicode);
- return 0;
-}
-
-int utf8_decode(const char *from, char **to)
-{
- wchar_t *unicode;
- int chars, err;
-
- /* On NT-based windows systems, we could use MultiByteToWideChar(CP_UTF8), but
- * MS doesn't actually have a consistent API across win32.
- */
- unicode = make_unicode_string(from);
- if(unicode == NULL)
- {
- fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n");
- return -1;
- }
-
- chars = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode,
- -1, NULL, 0, NULL, NULL);
-
- if(chars == 0)
- {
- fprintf(stderr, "Unicode translation error %d\n", GetLastError());
- free(unicode);
- return -1;
- }
-
- *to = calloc(chars + 1, sizeof(unsigned char));
- if(*to == NULL)
- {
- fprintf(stderr, "Out of memory processing string to local charset\n");
- free(unicode);
- return -1;
- }
-
- err = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode,
- -1, *to, chars, NULL, NULL);
- if(err != chars)
- {
- fprintf(stderr, "Unicode translation error %d\n", GetLastError());
- free(unicode);
- free(*to);
- *to = NULL;
- return -1;
- }
-
- free(unicode);
- return 0;
-}
-
-#else /* End win32. Rest is for real operating systems */
-
-
-#ifdef HAVE_LANGINFO_CODESET
-#include <langinfo.h>
-#endif
-
-int iconvert(const char *fromcode, const char *tocode,
- const char *from, size_t fromlen,
- char **to, size_t *tolen);
-
-static char *current_charset = 0; /* means "US-ASCII" */
-
-void convert_set_charset(const char *charset)
-{
-
- if (!charset)
- charset = getenv("CHARSET");
-
-#ifdef HAVE_LANGINFO_CODESET
- if (!charset)
- charset = nl_langinfo(CODESET);
-#endif
-
- free(current_charset);
- current_charset = 0;
- if (charset && *charset)
- current_charset = strdup(charset);
-}
-
-static int convert_buffer(const char *fromcode, const char *tocode,
- const char *from, size_t fromlen,
- char **to, size_t *tolen)
-{
- int ret = -1;
-
-#ifdef HAVE_ICONV
- ret = iconvert(fromcode, tocode, from, fromlen, to, tolen);
- if (ret != -1)
- return ret;
-#endif
-
-#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */
- ret = charset_convert(fromcode, tocode, from, fromlen, to, tolen);
- if (ret != -1)
- return ret;
-#endif
-
- return ret;
-}
-
-static int convert_string(const char *fromcode, const char *tocode,
- const char *from, char **to, char replace)
-{
- int ret;
- size_t fromlen;
- char *s;
-
- fromlen = strlen(from);
- ret = convert_buffer(fromcode, tocode, from, fromlen, to, 0);
- if (ret == -2)
- return -1;
- if (ret != -1)
- return ret;
-
- s = malloc(fromlen + 1);
- if (!s)
- return -1;
- strcpy(s, from);
- *to = s;
- for (; *s; s++)
- if (*s & ~0x7f)
- *s = replace;
- return 3;
-}
-
-int utf8_encode(const char *from, char **to)
-{
- char *charset;
-
- if (!current_charset)
- convert_set_charset(0);
- charset = current_charset ? current_charset : "US-ASCII";
- return convert_string(charset, "UTF-8", from, to, '#');
-}
-
-int utf8_decode(const char *from, char **to)
-{
- char *charset;
-
- if(*from == 0) {
- *to = malloc(1);
- **to = 0;
- return 1;
- }
-
- if (!current_charset)
- convert_set_charset(0);
- charset = current_charset ? current_charset : "US-ASCII";
- return convert_string("UTF-8", charset, from, to, '?');
-}
-
-#endif
diff --git a/xbmc/lib/libshout/utf8.h b/xbmc/lib/libshout/utf8.h
deleted file mode 100644
index f701319bdf..0000000000
--- a/xbmc/lib/libshout/utf8.h
+++ /dev/null
@@ -1,36 +0,0 @@
-
-/*
- * Convert a string between UTF-8 and the locale's charset.
- * Invalid bytes are replaced by '#', and characters that are
- * not available in the target encoding are replaced by '?'.
- *
- * If the locale's charset is not set explicitly then it is
- * obtained using nl_langinfo(CODESET), where available, the
- * environment variable CHARSET, or assumed to be US-ASCII.
- *
- * Return value of conversion functions:
- *
- * -1 : memory allocation failed
- * 0 : data was converted exactly
- * 1 : valid data was converted approximately (using '?')
- * 2 : input was invalid (but still converted, using '#')
- * 3 : unknown encoding (but still converted, using '?')
- */
-
-#ifndef __UTF8_H
-#define __UTF8_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void convert_set_charset(const char *charset);
-
-int utf8_encode(const char *from, char **to);
-int utf8_decode(const char *from, char **to);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __UTF8_H */