-
-/* following functions are local */
-
-static void LocaleInit( void )
-{
- char *psz_charset;
-
- if( !vlc_current_charset( &psz_charset ) )
- {
- char *psz_conv = psz_charset;
-
- /*
- * Still allow non-ASCII characters when the locale is not set.
- * Western Europeans are being favored for historical reasons.
- */
- psz_conv = strcmp( psz_charset, "ASCII" )
- ? psz_charset
- : "ISO-8859-15";
-
- vlc_mutex_init( p_libvlc, &libvlc.from_locale_lock );
- vlc_mutex_init( p_libvlc, &libvlc.to_locale_lock );
- libvlc.from_locale = vlc_iconv_open( "UTF-8", psz_charset );
- libvlc.to_locale = vlc_iconv_open( psz_charset, "UTF-8" );
- if( !libvlc.to_locale )
- {
- /* Not sure it is the right thing to do, but at least it
- doesn't make vlc crash with msvc ! */
- libvlc.to_locale = (vlc_iconv_t)(-1);
- }
- }
- else
- libvlc.from_locale = libvlc.to_locale = (vlc_iconv_t)(-1);
- free( psz_charset );
-}
-
-static void LocaleDeinit( void )
-{
- if( libvlc.to_locale != (vlc_iconv_t)(-1) )
- {
- vlc_mutex_destroy( &libvlc.from_locale_lock );
- vlc_mutex_destroy( &libvlc.to_locale_lock );
- vlc_iconv_close( libvlc.from_locale );
- vlc_iconv_close( libvlc.to_locale );
- }
-}
-
-/*****************************************************************************
- * SetLanguage: set the interface language.
- *****************************************************************************
- * We set the LC_MESSAGES locale category for interface messages and buttons,
- * as well as the LC_CTYPE category for string sorting and possible wide
- * character support.
- *****************************************************************************/
-static void SetLanguage ( char const *psz_lang )
-{
-#if defined( ENABLE_NLS ) \
- && ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
-
- char * psz_path;
-#if defined( SYS_DARWIN ) || defined ( WIN32 ) || defined( SYS_BEOS )
- char psz_tmp[1024];
-#endif
-
- if( psz_lang && !*psz_lang )
- {
-# if defined( HAVE_LC_MESSAGES )
- setlocale( LC_MESSAGES, psz_lang );
-# endif
- setlocale( LC_CTYPE, psz_lang );
- }
- else if( psz_lang )
- {
-#ifdef SYS_DARWIN
- /* I need that under Darwin, please check it doesn't disturb
- * other platforms. --Meuuh */
- setenv( "LANG", psz_lang, 1 );
-
-#elif defined( SYS_BEOS ) || defined( WIN32 )
- /* We set LC_ALL manually because it is the only way to set
- * the language at runtime under eg. Windows. Beware that this
- * makes the environment unconsistent when libvlc is unloaded and
- * should probably be moved to a safer place like vlc.c. */
- static char psz_lcall[20];
- snprintf( psz_lcall, 19, "LC_ALL=%s", psz_lang );
- psz_lcall[19] = '\0';
- putenv( psz_lcall );
-#endif
-
- setlocale( LC_ALL, psz_lang );
- /* many code paths assume that float numbers are formatted according
- * to the US standard (ie. with dot as decimal point), so we keep
- * C for LC_NUMERIC. */
- setlocale(LC_NUMERIC, "C" );
- }
-
- /* Specify where to find the locales for current domain */
-#if !defined( SYS_DARWIN ) && !defined( WIN32 ) && !defined( SYS_BEOS )
- psz_path = LOCALEDIR;
-#else
- snprintf( psz_tmp, sizeof(psz_tmp), "%s/%s", libvlc.psz_vlcpath,
- "locale" );
- psz_path = psz_tmp;
-#endif
- if( !bindtextdomain( PACKAGE_NAME, psz_path ) )
- {
- fprintf( stderr, "warning: no domain %s in directory %s\n",
- PACKAGE_NAME, psz_path );
- }
-
- /* Set the default domain */
- textdomain( PACKAGE_NAME );
- bind_textdomain_codeset( PACKAGE_NAME, "UTF-8" );
-#endif
-}
-
-/*****************************************************************************
- * GetFilenames: parse command line options which are not flags
- *****************************************************************************
- * Parse command line for input files as well as their associated options.
- * An option always follows its associated input and begins with a ":".
- *****************************************************************************/
-static int GetFilenames( vlc_t *p_vlc, int i_argc, char *ppsz_argv[] )
-{
- int i_opt, i_options;
-
- /* We assume that the remaining parameters are filenames
- * and their input options */
- for( i_opt = i_argc - 1; i_opt >= optind; i_opt-- )
- {
- const char *psz_target;
- i_options = 0;
-
- /* Count the input options */
- while( *ppsz_argv[ i_opt ] == ':' && i_opt > optind )
- {
- i_options++;
- i_opt--;
- }
-
- /* TODO: write an internal function of this one, to avoid
- * unnecessary lookups. */
- /* FIXME: should we convert options to UTF-8 as well ?? */
- psz_target = FromLocale( ppsz_argv[ i_opt ] );
- VLC_AddTarget( p_vlc->i_object_id, psz_target,
- (char const **)( i_options ? &ppsz_argv[i_opt + 1] :
- NULL ), i_options,
- PLAYLIST_INSERT, 0 );
- LocaleFree( psz_target );
- }
-
- return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Help: print program help
- *****************************************************************************
- * Print a short inline help. Message interface is initialized at this stage.
- *****************************************************************************/
-static void Help( vlc_t *p_this, char const *psz_help_name )
-{
-#ifdef WIN32
- ShowConsole();
-#endif
-
- if( psz_help_name && !strcmp( psz_help_name, "help" ) )
- {
- fprintf( stdout, VLC_USAGE, p_this->psz_object_name );
- Usage( p_this, "help" );
- Usage( p_this, "main" );
- }
- else if( psz_help_name && !strcmp( psz_help_name, "longhelp" ) )
- {
- fprintf( stdout, VLC_USAGE, p_this->psz_object_name );
- Usage( p_this, NULL );
- }
- else if( psz_help_name )
- {
- Usage( p_this, psz_help_name );
- }
-
-#ifdef WIN32 /* Pause the console because it's destroyed when we exit */
- PauseConsole();
-#endif
-}
-
-/*****************************************************************************
- * Usage: print module usage
- *****************************************************************************
- * Print a short inline help. Message interface is initialized at this stage.
- *****************************************************************************/
-static void Usage( vlc_t *p_this, char const *psz_module_name )
-{
-#define FORMAT_STRING " %s --%s%s%s%s%s%s%s "
- /* short option ------' | | | | | | |
- * option name ------------' | | | | | |
- * <bra -------------------------' | | | | |
- * option type or "" --------------' | | | |
- * ket> -----------------------------' | | |
- * padding spaces ---------------------' | |
- * comment -------------------------------' |
- * comment suffix --------------------------'
- *
- * The purpose of having bra and ket is that we might i18n them as well.
- */
-#define LINE_START 8
-#define PADDING_SPACES 25
- vlc_list_t *p_list;
- module_t *p_parser;
- module_config_t *p_item;
- char psz_spaces_text[PADDING_SPACES+LINE_START+1];
- char psz_spaces_longtext[LINE_START+3];
- char psz_format[sizeof(FORMAT_STRING)];
- char psz_buffer[10000];
- char psz_short[4];
- int i_index;
- int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1);
- vlc_bool_t b_advanced = config_GetInt( p_this, "advanced" );
- vlc_bool_t b_description;
-
- memset( psz_spaces_text, ' ', PADDING_SPACES+LINE_START );
- psz_spaces_text[PADDING_SPACES+LINE_START] = '\0';
- memset( psz_spaces_longtext, ' ', LINE_START+2 );
- psz_spaces_longtext[LINE_START+2] = '\0';
-
- strcpy( psz_format, FORMAT_STRING );
-
- /* List all modules */
- p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
-
- /* Enumerate the config for each module */
- for( i_index = 0; i_index < p_list->i_count; i_index++ )
- {
- vlc_bool_t b_help_module;
-
- p_parser = (module_t *)p_list->p_values[i_index].p_object ;
-
- if( psz_module_name && strcmp( psz_module_name,
- p_parser->psz_object_name ) )
- {
- continue;
- }
-
- /* Ignore modules without config options */
- if( !p_parser->i_config_items )
- {
- continue;
- }
-
- /* Ignore modules with only advanced config options if requested */
- if( !b_advanced )
- {
- for( p_item = p_parser->p_config;
- p_item->i_type != CONFIG_HINT_END;
- p_item++ )
- {
- if( (p_item->i_type & CONFIG_ITEM) &&
- !p_item->b_advanced ) break;
- }
- if( p_item->i_type == CONFIG_HINT_END ) continue;
- }
-
- /* Print name of module */
- if( strcmp( "main", p_parser->psz_object_name ) )
- fprintf( stdout, "\n %s\n", p_parser->psz_longname );
-
- b_help_module = !strcmp( "help", p_parser->psz_object_name );
-
- /* Print module options */
- for( p_item = p_parser->p_config;
- p_item->i_type != CONFIG_HINT_END;
- p_item++ )
- {
- char *psz_text, *psz_spaces = psz_spaces_text;
- char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
- char *psz_suf = "", *psz_prefix = NULL;
- signed int i;
-
- /* Skip deprecated options */
- if( p_item->psz_current )
- {
- continue;
- }
- /* Skip advanced options if requested */
- if( p_item->b_advanced && !b_advanced )
- {
- continue;
- }
-
- switch( p_item->i_type )
- {
- case CONFIG_HINT_CATEGORY:
- case CONFIG_HINT_USAGE:
- if( !strcmp( "main", p_parser->psz_object_name ) )
- fprintf( stdout, "\n %s\n", p_item->psz_text );
- break;
-
- case CONFIG_ITEM_STRING:
- case CONFIG_ITEM_FILE:
- case CONFIG_ITEM_DIRECTORY:
- case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
- case CONFIG_ITEM_MODULE_CAT:
- case CONFIG_ITEM_MODULE_LIST:
- case CONFIG_ITEM_MODULE_LIST_CAT:
- psz_bra = " <"; psz_type = _("string"); psz_ket = ">";
-
- if( p_item->ppsz_list )
- {
- psz_bra = " {";
- psz_type = psz_buffer;
- psz_type[0] = '\0';
- for( i = 0; p_item->ppsz_list[i]; i++ )
- {
- if( i ) strcat( psz_type, "," );
- strcat( psz_type, p_item->ppsz_list[i] );
- }
- psz_ket = "}";
- }
- break;
- case CONFIG_ITEM_INTEGER:
- case CONFIG_ITEM_KEY: /* FIXME: do something a bit more clever */
- psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";
-
- if( p_item->i_list )
- {
- psz_bra = " {";
- psz_type = psz_buffer;
- psz_type[0] = '\0';
- for( i = 0; p_item->ppsz_list_text[i]; i++ )
- {
- if( i ) strcat( psz_type, ", " );
- sprintf( psz_type + strlen(psz_type), "%i (%s)",
- p_item->pi_list[i],
- p_item->ppsz_list_text[i] );
- }
- psz_ket = "}";
- }
- break;
- case CONFIG_ITEM_FLOAT:
- psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
- break;
- case CONFIG_ITEM_BOOL:
- psz_bra = ""; psz_type = ""; psz_ket = "";
- if( !b_help_module )
- {
- psz_suf = p_item->i_value ? _(" (default enabled)") :
- _(" (default disabled)");
- }
- break;
- }
-
- if( !psz_type )
- {
- continue;
- }
-
- /* Add short option if any */
- if( p_item->i_short )
- {
- sprintf( psz_short, "-%c,", p_item->i_short );
- }
- else
- {
- strcpy( psz_short, " " );
- }
-
- i = PADDING_SPACES - strlen( p_item->psz_name )
- - strlen( psz_bra ) - strlen( psz_type )
- - strlen( psz_ket ) - 1;
-
- if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
- {
- psz_prefix = ", --no-";
- i -= strlen( p_item->psz_name ) + strlen( psz_prefix );
- }
-
- if( i < 0 )
- {
- psz_spaces[0] = '\n';
- i = 0;
- }
- else
- {
- psz_spaces[i] = '\0';
- }
-
- if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
- {
- fprintf( stdout, psz_format, psz_short, p_item->psz_name,
- psz_prefix, p_item->psz_name, psz_bra, psz_type,
- psz_ket, psz_spaces );
- }
- else
- {
- fprintf( stdout, psz_format, psz_short, p_item->psz_name,
- "", "", psz_bra, psz_type, psz_ket, psz_spaces );
- }
-
- psz_spaces[i] = ' ';
-
- /* We wrap the rest of the output */
- sprintf( psz_buffer, "%s%s", p_item->psz_text, psz_suf );
- b_description = config_GetInt( p_this, "help-verbose" );
-
- description:
- psz_text = psz_buffer;
- while( *psz_text )
- {
- char *psz_parser, *psz_word;
- size_t i_end = strlen( psz_text );
-
- /* If the remaining text fits in a line, print it. */
- if( i_end <= (size_t)i_width )
- {
- fprintf( stdout, "%s\n", psz_text );
- break;
- }
-
- /* Otherwise, eat as many words as possible */
- psz_parser = psz_text;
- do
- {
- psz_word = psz_parser;
- psz_parser = strchr( psz_word, ' ' );
- /* If no space was found, we reached the end of the text
- * block; otherwise, we skip the space we just found. */
- psz_parser = psz_parser ? psz_parser + 1
- : psz_text + i_end;
-
- } while( psz_parser - psz_text <= i_width );
-
- /* We cut a word in one of these cases:
- * - it's the only word in the line and it's too long.
- * - we used less than 80% of the width and the word we are
- * going to wrap is longer than 40% of the width, and even
- * if the word would have fit in the next line. */
- if( psz_word == psz_text
- || ( psz_word - psz_text < 80 * i_width / 100
- && psz_parser - psz_word > 40 * i_width / 100 ) )
- {
- char c = psz_text[i_width];
- psz_text[i_width] = '\0';
- fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
- psz_text += i_width;
- psz_text[0] = c;
- }
- else
- {
- psz_word[-1] = '\0';
- fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
- psz_text = psz_word;
- }
- }
-
- if( b_description && p_item->psz_longtext )
- {
- sprintf( psz_buffer, "%s%s", p_item->psz_longtext, psz_suf );
- b_description = VLC_FALSE;
- psz_spaces = psz_spaces_longtext;
- fprintf( stdout, "%s", psz_spaces );
- goto description;
- }
- }
- }
-
- /* Release the module list */
- vlc_list_release( p_list );
-}
-
-/*****************************************************************************
- * ListModules: list the available modules with their description
- *****************************************************************************
- * Print a list of all available modules (builtins and plugins) and a short
- * description for each one.
- *****************************************************************************/
-static void ListModules( vlc_t *p_this )
-{
- vlc_list_t *p_list;
- module_t *p_parser;
- char psz_spaces[22];
- int i_index;
-
- memset( psz_spaces, ' ', 22 );
-
-#ifdef WIN32
- ShowConsole();
-#endif
-
- /* List all modules */
- p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
-
- /* Enumerate each module */
- for( i_index = 0; i_index < p_list->i_count; i_index++ )
- {
- int i;
-
- p_parser = (module_t *)p_list->p_values[i_index].p_object ;
-
- /* Nasty hack, but right now I'm too tired to think about a nice
- * solution */
- i = 22 - strlen( p_parser->psz_object_name ) - 1;
- if( i < 0 ) i = 0;
- psz_spaces[i] = 0;
-
- fprintf( stdout, " %s%s %s\n", p_parser->psz_object_name,
- psz_spaces, p_parser->psz_longname );
-
- psz_spaces[i] = ' ';
- }
-
- vlc_list_release( p_list );
-
-#ifdef WIN32 /* Pause the console because it's destroyed when we exit */
- PauseConsole();
-#endif
-}
-
-/*****************************************************************************
- * Version: print complete program version
- *****************************************************************************
- * Print complete program version and build number.
- *****************************************************************************/
-static void Version( void )
-{
-#ifdef WIN32
- ShowConsole();
-#endif
-
- fprintf( stdout, _("VLC version %s\n"), VLC_Version() );
- fprintf( stdout, _("Compiled by %s@%s.%s\n"),
- VLC_CompileBy(), VLC_CompileHost(), VLC_CompileDomain() );
- fprintf( stdout, _("Compiler: %s\n"), VLC_Compiler() );
- if( strcmp( VLC_Changeset(), "exported" ) )
- fprintf( stdout, _("Based upon svn changeset [%s]\n"),
- VLC_Changeset() );
- fprintf( stdout,
- _("This program comes with NO WARRANTY, to the extent permitted by "
- "law.\nYou may redistribute it under the terms of the GNU General "
- "Public License;\nsee the file named COPYING for details.\n"
- "Written by the VideoLAN team; see the AUTHORS file.\n") );
-
-#ifdef WIN32 /* Pause the console because it's destroyed when we exit */
- PauseConsole();
-#endif
-}
-
-/*****************************************************************************
- * ShowConsole: On Win32, create an output console for debug messages
- *****************************************************************************
- * This function is useful only on Win32.
- *****************************************************************************/
-#ifdef WIN32 /* */
-static void ShowConsole( void )
-{
-# ifndef UNDER_CE
- FILE *f_help;
-
- if( getenv( "PWD" ) && getenv( "PS1" ) ) return; /* cygwin shell */
-
- AllocConsole();
-
- freopen( "CONOUT$", "w", stderr );
- freopen( "CONIN$", "r", stdin );
-
- if( (f_help = fopen( "vlc-help.txt", "wt" )) )
- {
- fclose( f_help );
- freopen( "vlc-help.txt", "wt", stdout );
- fprintf( stderr, _("\nDumped content to vlc-help.txt file.\n") );
- }
-
- else freopen( "CONOUT$", "w", stdout );
-
-# endif
-}
-#endif
-
-/*****************************************************************************
- * PauseConsole: On Win32, wait for a key press before closing the console
- *****************************************************************************
- * This function is useful only on Win32.
- *****************************************************************************/
-#ifdef WIN32 /* */
-static void PauseConsole( void )
-{
-# ifndef UNDER_CE
-
- if( getenv( "PWD" ) && getenv( "PS1" ) ) return; /* cygwin shell */
-
- fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
- getchar();
- fclose( stdout );
-
-# endif
-}
-#endif
-
-/*****************************************************************************
- * ConsoleWidth: Return the console width in characters
- *****************************************************************************
- * We use the stty shell command to get the console width; if this fails or
- * if the width is less than 80, we default to 80.
- *****************************************************************************/
-static int ConsoleWidth( void )
-{
- int i_width = 80;
-
-#ifndef WIN32
- char buf[20], *psz_parser;
- FILE *file;
- int i_ret;
-
- file = popen( "stty size 2>/dev/null", "r" );
- if( file )
- {
- i_ret = fread( buf, 1, 20, file );
- if( i_ret > 0 )
- {
- buf[19] = '\0';
- psz_parser = strchr( buf, ' ' );
- if( psz_parser )
- {
- i_ret = atoi( psz_parser + 1 );
- if( i_ret >= 80 )
- {
- i_width = i_ret;
- }
- }
- }
-
- pclose( file );
- }
-#endif
-
- return i_width;
-}
-
-static int VerboseCallback( vlc_object_t *p_this, const char *psz_variable,
- vlc_value_t old_val, vlc_value_t new_val, void *param)
-{
- vlc_t *p_vlc = (vlc_t *)p_this;
-
- if( new_val.i_int >= -1 )
- {
- p_vlc->p_libvlc->i_verbose = __MIN( new_val.i_int, 2 );
- }
- return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * InitDeviceValues: initialize device values
- *****************************************************************************
- * This function inits the dvd, vcd and cd-audio values
- *****************************************************************************/
-static void InitDeviceValues( vlc_t *p_vlc )
-{
-#ifdef HAVE_HAL
- LibHalContext * ctx;
- int i, i_devices;
- char **devices;
- char *block_dev;
- dbus_bool_t b_dvd;
-
- if( ( ctx = hal_initialize( NULL, FALSE ) ) )
- {
- if( ( devices = hal_get_all_devices( ctx, &i_devices ) ) )
- {
- for( i = 0; i < i_devices; i++ )
- {
- if( !hal_device_property_exists( ctx, devices[ i ],
- "storage.cdrom.dvd" ) )
- {
- continue;
- }
-
- b_dvd = hal_device_get_property_bool( ctx, devices[ i ],
- "storage.cdrom.dvd" );
- block_dev = hal_device_get_property_string( ctx, devices[ i ],
- "block.device" );
-
- if( b_dvd )
- {
- config_PutPsz( p_vlc, "dvd", block_dev );
- }
-
- config_PutPsz( p_vlc, "vcd", block_dev );
- config_PutPsz( p_vlc, "cd-audio", block_dev );
-
- hal_free_string( block_dev );
- }
- hal_free_string_array( devices );
- }
-
- hal_shutdown( ctx );
- }
-#endif
-}
-
-/*****************************************************************************
- * FromLocale: converts a locale string to UTF-8
- *****************************************************************************/
-char *FromLocale( const char *locale )
-{
- if( locale == NULL )
- return NULL;
-
- if( libvlc.from_locale != (vlc_iconv_t)(-1) )
- {
- char *iptr = (char *)locale, *output, *optr;
- size_t inb, outb;
-
- /*
- * We are not allowed to modify the locale pointer, even if we cast it
- * to non-const.
- */
- inb = strlen( locale );
- outb = inb * 6 + 1;
-
- /* FIXME: I'm not sure about the value for the multiplication
- * (for western people, multiplication by 3 (Latin9) is sufficient) */
- optr = output = calloc( outb , 1);
-
- vlc_mutex_lock( &libvlc.from_locale_lock );
- vlc_iconv( libvlc.from_locale, NULL, NULL, NULL, NULL );
-
- while( vlc_iconv( libvlc.from_locale, &iptr, &inb, &optr, &outb )
- == (size_t)-1 )
- {
- *optr = '?';
- optr++;
- iptr++;
- vlc_iconv( libvlc.from_locale, NULL, NULL, NULL, NULL );
- }
- vlc_mutex_unlock( &libvlc.from_locale_lock );
-
- return realloc( output, strlen( output ) + 1 );
- }
- return (char *)locale;
-}
-
-/*****************************************************************************
- * ToLocale: converts an UTF-8 string to locale
- *****************************************************************************/
-char *ToLocale( const char *utf8 )
-{
- if( utf8 == NULL )
- return NULL;
-
- if( libvlc.to_locale != (vlc_iconv_t)(-1) )
- {
- char *iptr = (char *)utf8, *output, *optr;
- size_t inb, outb;
-
- /*
- * We are not allowed to modify the locale pointer, even if we cast it
- * to non-const.
- */
- inb = strlen( utf8 );
- /* FIXME: I'm not sure about the value for the multiplication
- * (for western people, multiplication is not needed) */
- outb = inb * 2 + 1;
-
- optr = output = calloc( outb, 1 );
- vlc_mutex_lock( &libvlc.to_locale_lock );
- vlc_iconv( libvlc.to_locale, NULL, NULL, NULL, NULL );
-
- while( vlc_iconv( libvlc.to_locale, &iptr, &inb, &optr, &outb )
- == (size_t)-1 )
- {
- *optr = '?'; /* should not happen, and yes, it sucks */
- optr++;
- iptr++;
- vlc_iconv( libvlc.to_locale, NULL, NULL, NULL, NULL );
- }
- vlc_mutex_unlock( &libvlc.to_locale_lock );
-
- return realloc( output, strlen( output ) + 1 );
- }
- return (char *)utf8;
-}
-
-void LocaleFree( const char *str )
-{
- if( ( str != NULL ) && ( libvlc.to_locale != (vlc_iconv_t)(-1) ) )
- free( (char *)str );
-}