diff options
author | theuni <theuni@svn> | 2010-11-27 17:47:16 +0000 |
---|---|---|
committer | theuni <theuni@svn> | 2010-11-27 17:47:16 +0000 |
commit | 3f19345ca330029b775395f28a5f476e26e19b6a (patch) | |
tree | d1e8983f52c0c8a5e1495419864df67ef11a39a8 | |
parent | b3b440aa7cce402cf73be601d57ef22293648e08 (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
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 (®exp, 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 (®exp); - 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 (®exp, 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 (®exp); - - 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 (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); - tree = parse_reg_exp (regexp, preg, ¤t_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 */ |