cmdline.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:14k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * cmdline.c: command line parsing
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2007 the VideoLAN team
  5.  * $Id: 264f84ed2f9670e21e734439c44b84aeb67b1ad1 $
  6.  *
  7.  * Authors: Gildas Bazin <gbazin@videolan.org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. #ifdef HAVE_CONFIG_H
  24. # include "config.h"
  25. #endif
  26. #include <vlc_common.h>
  27. #include "../libvlc.h"
  28. #include <vlc_keys.h>
  29. #include <vlc_charset.h>
  30. #ifdef HAVE_GETOPT_LONG
  31. #   ifdef HAVE_GETOPT_H
  32. #       include <getopt.h>                                       /* getopt() */
  33. #   endif
  34. #else
  35. #   include "../extras/getopt.h"
  36. #endif
  37. #include "configuration.h"
  38. #include "modules/modules.h"
  39. #include <assert.h>
  40. /*****************************************************************************
  41.  * config_LoadCmdLine: parse command line
  42.  *****************************************************************************
  43.  * Parse command line for configuration options.
  44.  * Now that the module_bank has been initialized, we can dynamically
  45.  * generate the longopts structure used by getops. We have to do it this way
  46.  * because we don't know (and don't want to know) in advance the configuration
  47.  * options used (ie. exported) by each module.
  48.  *****************************************************************************/
  49. int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc,
  50.                           const char *ppsz_argv[],
  51.                           bool b_ignore_errors )
  52. {
  53.     int i_cmd, i_index, i_opts, i_shortopts, flag, i_verbose = 0;
  54.     module_t *p_parser;
  55.     struct option *p_longopts;
  56.     const char **argv_copy = NULL;
  57.     /* Short options */
  58.     module_config_t *pp_shortopts[256];
  59.     char *psz_shortopts;
  60. #ifdef __APPLE__
  61.     /* When VLC.app is run by double clicking in Mac OS X, the 2nd arg
  62.      * is the PSN - process serial number (a unique PID-ish thingie)
  63.      * still ok for real Darwin & when run from command line */
  64.     if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
  65.                                         /* for example -psn_0_9306113 */
  66.     {
  67.         /* GDMF!... I can't do this or else the MacOSX window server will
  68.          * not pick up the PSN and not register the app and we crash...
  69.          * hence the following kludge otherwise we'll get confused w/ argv[1]
  70.          * being an input file name.
  71.          * As there won't be any more args to parse, just exit. */
  72.         assert( *pi_argc == 2 );
  73.         *pi_argc = 1;
  74.         return 0;
  75.     }
  76. #endif
  77.     /* List all modules */
  78.     module_t **list = module_list_get (NULL);
  79.     /*
  80.      * Generate the longopts and shortopts structures used by getopt_long
  81.      */
  82.     i_opts = 0;
  83.     for (size_t i = 0; (p_parser = list[i]) != NULL; i++)
  84.         /* count the number of exported configuration options (to allocate
  85.          * longopts). We also need to allocate space for two options when
  86.          * dealing with boolean to allow for --foo and --no-foo */
  87.         i_opts += p_parser->i_config_items + 2 * p_parser->i_bool_items;
  88.     p_longopts = malloc( sizeof(struct option) * (i_opts + 1) );
  89.     if( p_longopts == NULL )
  90.     {
  91.         module_list_free (list);
  92.         return -1;
  93.     }
  94.     psz_shortopts = malloc( sizeof( char ) * (2 * i_opts + 1) );
  95.     if( psz_shortopts == NULL )
  96.     {
  97.         free( p_longopts );
  98.         module_list_free (list);
  99.         return -1;
  100.     }
  101.     /* If we are requested to ignore errors, then we must work on a copy
  102.      * of the ppsz_argv array, otherwise getopt_long will reorder it for
  103.      * us, ignoring the arity of the options */
  104.     if( b_ignore_errors )
  105.     {
  106.         argv_copy = (const char**)malloc( *pi_argc * sizeof(char *) );
  107.         if( argv_copy == NULL )
  108.         {
  109.             free( psz_shortopts );
  110.             free( p_longopts );
  111.             module_list_free (list);
  112.             return -1;
  113.         }
  114.         memcpy( argv_copy, ppsz_argv, *pi_argc * sizeof(char *) );
  115.         ppsz_argv = argv_copy;
  116.     }
  117.     i_shortopts = 0;
  118.     for( i_index = 0; i_index < 256; i_index++ )
  119.     {
  120.         pp_shortopts[i_index] = NULL;
  121.     }
  122.     /* Fill the p_longopts and psz_shortopts structures */
  123.     i_index = 0;
  124.     for (size_t i = 0; (p_parser = list[i]) != NULL; i++)
  125.     {
  126.         module_config_t *p_item, *p_end;
  127.         if( !p_parser->i_config_items )
  128.             continue;
  129.         for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize;
  130.              p_item < p_end;
  131.              p_item++ )
  132.         {
  133.             /* Ignore hints */
  134.             if( p_item->i_type & CONFIG_HINT )
  135.                 continue;
  136.             /* Add item to long options */
  137.             p_longopts[i_index].name = strdup( p_item->psz_name );
  138.             if( p_longopts[i_index].name == NULL ) continue;
  139.             p_longopts[i_index].has_arg =
  140.                 (p_item->i_type == CONFIG_ITEM_BOOL) ? no_argument : 
  141. #ifndef __APPLE__
  142.                                                        required_argument;
  143. #else
  144. /* It seems that required_argument is broken on Darwin.
  145.  * Radar ticket #6113829 */
  146.                                                        optional_argument;
  147. #endif
  148.             p_longopts[i_index].flag = &flag;
  149.             p_longopts[i_index].val = 0;
  150.             i_index++;
  151.             /* When dealing with bools we also need to add the --no-foo
  152.              * option */
  153.             if( p_item->i_type == CONFIG_ITEM_BOOL )
  154.             {
  155.                 char *psz_name = malloc( strlen(p_item->psz_name) + 3 );
  156.                 if( psz_name == NULL ) continue;
  157.                 strcpy( psz_name, "no" );
  158.                 strcat( psz_name, p_item->psz_name );
  159.                 p_longopts[i_index].name = psz_name;
  160.                 p_longopts[i_index].has_arg = no_argument;
  161.                 p_longopts[i_index].flag = &flag;
  162.                 p_longopts[i_index].val = 1;
  163.                 i_index++;
  164.                 psz_name = malloc( strlen(p_item->psz_name) + 4 );
  165.                 if( psz_name == NULL ) continue;
  166.                 strcpy( psz_name, "no-" );
  167.                 strcat( psz_name, p_item->psz_name );
  168.                 p_longopts[i_index].name = psz_name;
  169.                 p_longopts[i_index].has_arg = no_argument;
  170.                 p_longopts[i_index].flag = &flag;
  171.                 p_longopts[i_index].val = 1;
  172.                 i_index++;
  173.             }
  174.             /* If item also has a short option, add it */
  175.             if( p_item->i_short )
  176.             {
  177.                 pp_shortopts[(int)p_item->i_short] = p_item;
  178.                 psz_shortopts[i_shortopts] = p_item->i_short;
  179.                 i_shortopts++;
  180.                 if( p_item->i_type != CONFIG_ITEM_BOOL )
  181.                 {
  182.                     psz_shortopts[i_shortopts] = ':';
  183.                     i_shortopts++;
  184.                     if( p_item->i_short == 'v' )
  185.                     {
  186.                         psz_shortopts[i_shortopts] = ':';
  187.                         i_shortopts++;
  188.                     }
  189.                 }
  190.             }
  191.         }
  192.     }
  193.     /* We don't need the module list anymore */
  194.     module_list_free( list );
  195.     /* Close the longopts and shortopts structures */
  196.     memset( &p_longopts[i_index], 0, sizeof(struct option) );
  197.     psz_shortopts[i_shortopts] = '';
  198.     /*
  199.      * Parse the command line options
  200.      */
  201.     opterr = 0;
  202.     optind = 0; /* set to 0 to tell GNU getopt to reinitialize */
  203.     while( ( i_cmd = getopt_long( *pi_argc, (char **)ppsz_argv, psz_shortopts,
  204.                                   p_longopts, &i_index ) ) != -1 )
  205.     {
  206.         /* A long option has been recognized */
  207.         if( i_cmd == 0 )
  208.         {
  209.             module_config_t *p_conf;
  210.             char *psz_name = (char *)p_longopts[i_index].name;
  211.             /* Check if we deal with a --nofoo or --no-foo long option */
  212.             if( flag ) psz_name += psz_name[2] == '-' ? 3 : 2;
  213.             /* Store the configuration option */
  214.             p_conf = config_FindConfig( p_this, psz_name );
  215.             if( p_conf )
  216.             {
  217.                 /* Check if the option is deprecated */
  218.                 if( p_conf->b_removed )
  219.                 {
  220.                     fprintf(stderr,
  221.                             "Warning: option --%s no longer exists.n",
  222.                             psz_name);
  223.                     continue;
  224.                 }
  225.                 if( p_conf->psz_oldname
  226.                  && !strcmp( p_conf->psz_oldname, psz_name) )
  227.                 {
  228.                     fprintf( stderr,
  229.                              "%s: option --%s is deprecated. Use --%s instead.n",
  230.                              b_ignore_errors ? "Warning" : "Error",
  231.                              psz_name, p_conf->psz_name );
  232.                     if( !b_ignore_errors )
  233.                     {
  234.                         /*free */
  235.                         for( i_index = 0; p_longopts[i_index].name; i_index++ )
  236.                              free( (char *)p_longopts[i_index].name );
  237.                         free( p_longopts );
  238.                         free( psz_shortopts );
  239.                         return -1;
  240.                     }
  241.                     psz_name = p_conf->psz_name;
  242.                 }
  243. #ifdef __APPLE__
  244.                 if( p_conf->i_type != CONFIG_ITEM_BOOL && !optarg )
  245.                 {
  246.                     fprintf( stderr, "Warning: missing argument for option --%sn", p_conf->psz_name );
  247.                     fprintf( stderr, "Try specifying options as '--optionname=value' instead of '--optionname value'n" );
  248.                     continue;
  249.                 }
  250. #endif
  251.                 switch( p_conf->i_type )
  252.                 {
  253.                     case CONFIG_ITEM_STRING:
  254.                     case CONFIG_ITEM_PASSWORD:
  255.                     case CONFIG_ITEM_FILE:
  256.                     case CONFIG_ITEM_DIRECTORY:
  257.                     case CONFIG_ITEM_MODULE:
  258.                     case CONFIG_ITEM_MODULE_LIST:
  259.                     case CONFIG_ITEM_MODULE_LIST_CAT:
  260.                     case CONFIG_ITEM_MODULE_CAT:
  261.                         config_PutPsz( p_this, psz_name, optarg );
  262.                         break;
  263.                     case CONFIG_ITEM_INTEGER:
  264.                         config_PutInt( p_this, psz_name, strtol(optarg, 0, 0));
  265.                         break;
  266.                     case CONFIG_ITEM_FLOAT:
  267.                         config_PutFloat( p_this, psz_name, us_atof(optarg) );
  268.                         break;
  269.                     case CONFIG_ITEM_KEY:
  270.                         config_PutInt( p_this, psz_name, ConfigStringToKey( optarg ) );
  271.                         break;
  272.                     case CONFIG_ITEM_BOOL:
  273.                         config_PutInt( p_this, psz_name, !flag );
  274.                         break;
  275.                 }
  276.                 continue;
  277.             }
  278.         }
  279.         /* A short option has been recognized */
  280.         if( pp_shortopts[i_cmd] != NULL )
  281.         {
  282.             switch( pp_shortopts[i_cmd]->i_type )
  283.             {
  284.                 case CONFIG_ITEM_STRING:
  285.                 case CONFIG_ITEM_PASSWORD:
  286.                 case CONFIG_ITEM_FILE:
  287.                 case CONFIG_ITEM_DIRECTORY:
  288.                 case CONFIG_ITEM_MODULE:
  289.                 case CONFIG_ITEM_MODULE_CAT:
  290.                 case CONFIG_ITEM_MODULE_LIST:
  291.                 case CONFIG_ITEM_MODULE_LIST_CAT:
  292.                     config_PutPsz( p_this, pp_shortopts[i_cmd]->psz_name, optarg );
  293.                     break;
  294.                 case CONFIG_ITEM_INTEGER:
  295.                     if( i_cmd == 'v' )
  296.                     {
  297.                         if( optarg )
  298.                         {
  299.                             if( *optarg == 'v' ) /* eg. -vvv */
  300.                             {
  301.                                 i_verbose++;
  302.                                 while( *optarg == 'v' )
  303.                                 {
  304.                                     i_verbose++;
  305.                                     optarg++;
  306.                                 }
  307.                             }
  308.                             else
  309.                             {
  310.                                 i_verbose += atoi( optarg ); /* eg. -v2 */
  311.                             }
  312.                         }
  313.                         else
  314.                         {
  315.                             i_verbose++; /* -v */
  316.                         }
  317.                         config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
  318.                                                i_verbose );
  319.                     }
  320.                     else
  321.                     {
  322.                         config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
  323.                                                strtol(optarg, 0, 0) );
  324.                     }
  325.                     break;
  326.                 case CONFIG_ITEM_BOOL:
  327.                     config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name, 1 );
  328.                     break;
  329.             }
  330.             continue;
  331.         }
  332.         /* Internal error: unknown option */
  333.         if( !b_ignore_errors )
  334.         {
  335.             fputs( "vlc: unknown option"
  336.                      " or missing mandatory argument ", stderr );
  337.             if( optopt )
  338.             {
  339.                 fprintf( stderr, "`-%c'n", optopt );
  340.             }
  341.             else
  342.             {
  343.                 fprintf( stderr, "`%s'n", ppsz_argv[optind-1] );
  344.             }
  345.             fputs( "Try `vlc --help' for more information.n", stderr );
  346.             for( i_index = 0; p_longopts[i_index].name; i_index++ )
  347.                 free( (char *)p_longopts[i_index].name );
  348.             free( p_longopts );
  349.             free( psz_shortopts );
  350.             return -1;
  351.         }
  352.     }
  353.     /* Free allocated resources */
  354.     for( i_index = 0; p_longopts[i_index].name; i_index++ )
  355.         free( (char *)p_longopts[i_index].name );
  356.     free( p_longopts );
  357.     free( psz_shortopts );
  358.     free( argv_copy );
  359.     return 0;
  360. }