[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog libbase/Makefile.am gui/gnash.c...
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] gnash ChangeLog libbase/Makefile.am gui/gnash.c... |
Date: |
Sat, 15 Mar 2008 10:39:16 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Benjamin Wolsey <bwy> 08/03/15 10:39:16
Modified files:
. : ChangeLog
libbase : Makefile.am
gui : gnash.cpp
Added files:
libbase : arg_parser.cpp arg_parser.h
Log message:
* libbase/arg_parser.{cpp,h}: add slightly modified version of
Antonio Diaz Diaz's C++ GPLv3 Arg_parser class.
* libbase/Makefile: build arg_parser.
* gui/gnash.cpp: use Arg_parser to add long options. Make --help
more concise (we have a manual), abolish printf where it's not
useful for translation (which is almost everywhere).
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5927&r2=1.5928
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/Makefile.am?cvsroot=gnash&r1=1.98&r2=1.99
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/arg_parser.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/arg_parser.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/gui/gnash.cpp?cvsroot=gnash&r1=1.106&r2=1.107
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.5927
retrieving revision 1.5928
diff -u -b -r1.5927 -r1.5928
--- ChangeLog 15 Mar 2008 09:40:22 -0000 1.5927
+++ ChangeLog 15 Mar 2008 10:39:14 -0000 1.5928
@@ -1,3 +1,12 @@
+2008-03-15 Benjamin Wolsey <address@hidden>
+
+ * libbase/arg_parser.{cpp,h}: add slightly modified version of
+ Antonio Diaz Diaz's C++ Arg_parser class.
+ * libbase/Makefile: build arg_parser.
+ * gui/gnash.cpp: use Arg_parser to add long options. Make --help
+ more concise (we have a manual), abolish printf where it's not
+ useful for translation (which is almost everywhere).
+
2008-03-15 Sandro Santilli <address@hidden>
* server/debugger.cpp: fix compilation.
Index: libbase/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/libbase/Makefile.am,v
retrieving revision 1.98
retrieving revision 1.99
diff -u -b -r1.98 -r1.99
--- libbase/Makefile.am 7 Mar 2008 02:10:40 -0000 1.98
+++ libbase/Makefile.am 15 Mar 2008 10:39:15 -0000 1.99
@@ -105,6 +105,7 @@
FLVParser.cpp \
GC.cpp \
BitsReader.cpp \
+ arg_parser.cpp \
$(NULL)
noinst_HEADERS = \
@@ -147,6 +148,7 @@
FLVParser.h \
GC.h \
BitsReader.h \
+ arg_parser.h \
$(NULL)
libgnashbase_la_LDFLAGS = -release $(VERSION)
Index: gui/gnash.cpp
===================================================================
RCS file: /sources/gnash/gnash/gui/gnash.cpp,v
retrieving revision 1.106
retrieving revision 1.107
diff -u -b -r1.106 -r1.107
--- gui/gnash.cpp 10 Mar 2008 20:36:39 -0000 1.106
+++ gui/gnash.cpp 15 Mar 2008 10:39:16 -0000 1.107
@@ -25,6 +25,7 @@
#include "log.h"
#include "rc.h" // for use of rcfile
#include "debugger.h"
+#include "arg_parser.h"
#ifdef HAVE_FFMPEG_AVCODEC_H
extern "C" {
@@ -37,22 +38,6 @@
# include "gst/gstversion.h"
#endif
-#if defined(_WIN32) || defined(WIN32)
- #include "getopt_win32.h"
-#else
-extern "C"{
- #include <unistd.h>
-#ifdef HAVE_GETOPT_H
- #include <getopt.h>
-#endif
-#ifndef __GNUC__
- extern int optind, getopt(int, char *const *, const char *);
- extern char *optarg; // global argument pointer
-#endif
-}
-#endif // ! Win32
-
-
#include <string>
#include <iostream>
@@ -72,10 +57,12 @@
using namespace gnash; // for log_*
-using namespace std;
+using std::cerr;
+using std::endl;
+using std::cout;
-char* infile = NULL;
-char* url = NULL;
+std::vector<std::string> infiles;
+const char* url = NULL;
namespace {
gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
@@ -90,152 +77,157 @@
static void
usage()
{
-#ifdef GNASH_FPS_DEBUG
- printf("%s%s%s%s%s%s%s%s%s",
-#else
- printf("%s%s%s%s%s%s%s%s",
-#endif
- _(
- "usage: gnash [options] movie_file.swf\n"
- "\n"
- "Plays a SWF (Shockwave Flash) movie\n"
- "options:\n"
- "\n"), _(
- " -h, --help Print this info.\n"
- " -s <factor> Scale the movie up/down by the specified factor\n"
- " -c Produce a core file instead of letting SDL trap it\n"
- " -d num Number of milliseconds to delay in main loop\n"
- " -v Be verbose; i.e. print log messages to stdout\n"
- ),
+
+cout << _("Usage: gnash [options] movie_file.swf") << endl
+ << endl
+ << _("Plays a SWF (Shockwave Flash) movie") << endl
+ << _("Options:") << endl
+ << endl
+ << _(" -h, --help Print this help and exit") << endl
+ << _(" -s, --scale <factor> Scale the movie by the specified factor")
<< endl
+ << _(" -c Produce a core file instead of letting
SDL trap it") << endl
+ << _(" -d, --delay num Number of milliseconds to delay in main
loop") << endl
+ << _(" -v, --verbose Be verbose") << endl
#if VERBOSE_ACTION
- _(" -va Be (very) verbose about action execution\n"),
-#else
- "",
+ << _(" -va Be (very) verbose about action
execution") << endl
#endif
#if VERBOSE_PARSE
- _(" -vp Be (very) verbose about parsing\n"),
-#else
- "",
+ << _(" -vp Be (very) verbose about parsing") << endl
#endif
- _(
- " -x <ID> X11 Window ID for display\n"
- " -v Produce verbose output\n"
- " -w Produce the disk based debug log\n"
- " -j <width > Set window width\n"
- " -k <height> Set window height\n"
- " -1 Play once; exit when/if movie reaches the last
frame\n"
- ), _(
- " -g Turn on the Flash debugger\n"
- " -r <0|1|2|3>\n"
- " 0 disables both rendering & sound (good for batch
tests)\n"
- " 1 enables rendering & disables sound\n"
- " 2 enables sound & disables rendering\n"
- " 3 enables both rendering & sound (default)\n"
- ), _(
- " -t <sec> Timeout and exit after the specified number of
seconds\n"
- " -u <url> Set \"real\" url of the movie\n"
- " (useful for downloaded movies)\n"
- " -U <url> Set \"base\" url for this run\n"
- " (used to resolve relative urls, defaults to movie
url)\n"
- " -P <param> Set parameter (ie. \"FlashVars=A=1&b=2\")\n"
- " -V, --version Print gnash's version number and exit\n"
- " -F <fd> Set filedescriptor to use for external
communications\n"
- ), _(
+ << _(" -x, --xid <ID> X11 Window ID for display") << endl
+ << _(" -v, --verbose Produce verbose output") << endl
+ << _(" -w, --writelog Produce the disk based debug log") << endl
+ << _(" -j, --width <width> Set window width") << endl
+ << _(" -k, --height <height> Set window height") << endl
+ << _(" -1, --once Exit when/if movie reaches the last
frame") << endl
+ << _(" -g, --debugger Turn on the Flash debugger") << endl
+ << _(" -r, --render-mode <0|1|2|3>") << endl
+ << _(" 0 disable rendering and sound") << endl
+ << _(" 1 enable rendering, disable sound") <<
endl
+ << _(" 2 enable sound, disable rendering") <<
endl
+ << _(" 3 enable rendering and sound (default)")
<< endl
+ << _(" -t, --timeout <sec> Exit after the specified number of
seconds") << endl
+ << _(" -u, --real-url <url> Set \"real\" URL of the movie") << endl
+ << _(" -U, --base-url <url> Set \"base\" URL for resolving relative
URLs") << endl
+ << _(" -P, --pass-vars <param> Set parameter (e.g.
\"FlashVars=A=1&b=2\")") << endl
+ << _(" -V, --version Print gnash's version number and exit")
<< endl
+ << _(" -F, --fd <fd> Filedescriptor to use for external
communications") << endl
#ifdef GNASH_FPS_DEBUG
- " -f num Print FPS every num seconds (float)."
- ), _(
+ << _(" -f, --debug-fps num Print FPS every num seconds (float)." <<
endl
#endif // def GNASH_FPS_DEBUG
- "\n"
- "keys:\n"
- "\n"
- " CTRL-Q, CTRL-W Quit/Exit\n"
- " CTRL-P Toggle Pause\n"
- " CTRL-R Restart the movie\n"
+ << endl
+ << _("Keys:") << endl
+ << endl
+ << _(" CTRL-Q, CTRL-W Quit/Exit") << endl
+ << _(" CTRL-P Toggle Pause") << endl
+ << _(" CTRL-R Restart the movie") << endl
#if 0 // Currently disabled
- " CTRL-[ or kp- Step back one frame\n"
- " CTRL-] or kp+ Step forward one frame\n"
+ << _(" CTRL-[ or kp- Step back one frame") << endl
+ << _(" CTRL-] or kp+ Step forward one frame") << endl
#endif
- " CTRL-L Force immediate redraw\n"
-/*
- " CTRL-A Toggle antialiasing (doesn't work)\n"
- " CTRL-T Debug. Test the set_variable() function\n"
- " CTRL-G Debug. Test the get_variable() function\n"
- " CTRL-M Debug. Test the call_method() function\n"
-*/
- ));
+ << _(" CTRL-L Force immediate redraw") << endl
+
+// << _(" CTRL-A Toggle antialiasing (doesn't work)") << endl
+// << _(" CTRL-T Debug. Test the set_variable() function") <<
endl
+// << _(" CTRL-G Debug. Test the get_variable() function") <<
endl
+// << _(" CTRL-M Debug. Test the call_method() function") << endl
+
+ << endl;
}
static void version_and_copyright()
{
- printf (_(
-"Gnash " VERSION "\n"
-"Copyright (C) 2005-2008 Free Software Foundation, Inc.\n"
-"Gnash comes with NO WARRANTY, to the extent permitted by law.\n"
-"You may redistribute copies of Gnash under the terms of the GNU General\n"
-"Public License. For more information, see the file named COPYING.\n"
- ));
+ cout << _(
+ "Gnash " VERSION "\n"
+ "Copyright (C) 2005-2008 Free Software Foundation, Inc.\n"
+ "Gnash comes with NO WARRANTY, to the extent permitted by law.\n"
+ "You may redistribute copies of Gnash under the terms of the GNU
General\n"
+ "Public License. For more information, see the file named COPYING.\n")
+ << endl;
}
-
static void build_options()
{
- printf (_("Build options %s\n"
- " Target: %s\n"
- " Renderer: %s - GUI: %s - Media handler: %s\n"
- " Configured with: %s\n"
- " CXXFLAGS: %s\n"),
- VERSION, TARGET_CONFIG, RENDERER_CONFIG, GUI_CONFIG,
- MEDIA_CONFIG, CONFIG_CONFIG, CXXFLAGS);
+ cout << _("Build options ") << VERSION << endl
+ << _(" Target: ") << TARGET_CONFIG << endl
+
+ << _(" Renderer: ") << RENDERER_CONFIG
+ << _(" - GUI: ") << GUI_CONFIG
+ << _(" - Media handler: ") << MEDIA_CONFIG << endl
+
+ << _(" Configured with: ") << CONFIG_CONFIG << endl
+ << _(" CXXFLAGS: ") << CXXFLAGS << endl;
+
#ifdef HAVE_FFMPEG_AVCODEC_H
- printf(_("Ffmpeg version is: %s\n"), LIBAVCODEC_IDENT);
+ cout << _("Ffmpeg version is: ") << LIBAVCODEC_IDENT << endl;
#endif
#ifdef HAVE_GST_GST_H
- printf(_("Gstreamer version is: %d.%d.%d.\n"), GST_VERSION_MAJOR,
- GST_VERSION_MINOR, GST_VERSION_MICRO);
+ cout << _("Gstreamer version is: ") << GST_VERSION_MAJOR << "."
+ << GST_VERSION_MINOR << "." << GST_VERSION_MICRO << endl;
#endif
}
-
static void
parseCommandLine(int argc, char* argv[], gnash::Player& player)
{
- bool specified_rendering_flag=false;
- bool called_by_plugin=false;
- bool width_given=false, height_given=false;
-
- int c = 0;
- // scan for the two main long GNU options
- for (; c < argc; c++) {
- if (strcmp("--help", argv[c]) == 0) {
- version_and_copyright();
- printf("\n");
- usage();
- build_options();
- exit(EXIT_SUCCESS);
- }
- if (strcmp("--version", argv[c]) == 0) {
- version_and_copyright();
- build_options();
- exit(EXIT_SUCCESS);
- }
+
+ const Arg_parser::Option opts[] =
+ {
+ { 'h', "help", Arg_parser::no },
+ { 'v', "verbose", Arg_parser::no },
+ { 'a', 0, Arg_parser::no },
+ { 'p', 0, Arg_parser::no },
+ { 's', "scale", Arg_parser::yes },
+ { 256, "max-advances", Arg_parser::yes },
+ { 'c', 0, Arg_parser::no },
+ { 'd', "delay", Arg_parser::yes },
+ { 'x', "xid", Arg_parser::yes },
+ { 'r', "render-mode", Arg_parser::yes },
+ { 't', "timeout", Arg_parser::yes },
+ { '1', "once", Arg_parser::no },
+ { 'w', "writelog", Arg_parser::no },
+ { 'j', "width", Arg_parser::yes },
+ { 'k', "height", Arg_parser::yes },
+ { 'u', "real-url", Arg_parser::yes },
+ { 'P', "pass-vars", Arg_parser::yes },
+ { 'U', "base-url", Arg_parser::yes },
+ { 'g', "debugger", Arg_parser::no },
+ { 'V', "version", Arg_parser::no },
+ { 'f', "debug-fps", Arg_parser::yes },
+ { 'F', "fd", Arg_parser::yes },
+ { 0, 0, Arg_parser::no }
+ };
+
+ Arg_parser parser(argc, argv, opts);
+ if( ! parser.error().empty() )
+ {
+ cout << parser.error() << endl;
+ exit(EXIT_FAILURE);
}
- while ((c = getopt (argc, argv, "hvaps:m:cd:x:r:t:1wj:k:u:P:U:gVf:F:")) !=
-1)
+
+ bool renderflag = false;
+ bool plugin = false;
+ bool widthGiven = false, heightGiven = false;
+
+
+ for( int i = 0; i < parser.arguments(); ++i )
+ {
+ const int code = parser.code(i);
+ try
+ {
+ switch( code )
{
- switch (c) {
- // case 'c' (Disable SDL core dumps) is decoded in sdl.cpp:init()
- // case 'm' (Set LOD bias) is decoded in various GUIs (grep getopt)
case 'h':
version_and_copyright();
- printf("\n");
usage ();
- build_options();
exit(EXIT_SUCCESS);
case 'v':
dbglogfile.setVerbosity();
- log_debug (_("Verbose output turned on"));
+ // This happens once per 'v' flag
+ log_debug(_("Verbose output turned on"));
break;
case 'V':
version_and_copyright();
@@ -243,13 +235,13 @@
exit(EXIT_SUCCESS);
case 'w':
rcfile.useWriteLog(true); // dbglogfile.setWriteDisk(true);
- log_debug (_("Logging to disk enabled"));
+ log_debug(_("Logging to disk enabled"));
break;
case 'a':
#if VERBOSE_ACTION
dbglogfile.setActionDump(true); //gnash::set_verbose_action(true);
#else
- log_error (_("No verbose actions; disabled at compile time"));
+ log_error(_("No verbose actions; disabled at compile
time"));
#endif
break;
case 'p':
@@ -259,26 +251,28 @@
log_error (_("No verbose parsing; disabled at compile time"));
#endif
break;
- case 'm':
- player.setMaxAdvances( strtoul(optarg, NULL, 0) );
+ case 256:
+ player.setMaxAdvances( parser.argument<unsigned long>(i));
break;
case 's':
- player.setScale( fclamp((float) atof(optarg), 0.01f, 100.f) );
+ player.setScale( fclamp(
+ parser.argument<float>(i),
+ 0.01f, 100.f) );
break;
case 'd':
- player.setDelay( strtol(optarg, NULL, 0) );
+ player.setDelay( parser.argument<long>(i) );
break;
case 'u':
- url = optarg;
+ url = parser.argument(i).c_str();
log_debug (_("Setting root URL to %s"), url);
break;
case 'U': // Set base URL
- player.setBaseUrl(optarg);
- log_debug (_("Setting base URL to %s"), optarg);
+ player.setBaseUrl(parser.argument(i));
+ log_debug (_("Setting base URL to %s"),
parser.argument(i));
break;
case 'F':
{
- int fd = strtol(optarg, NULL, 0);
+ int fd = parser.argument<long>(i);
if ( fd < 1 )
{
printf(_("Invalid host communication filedescriptor %d\n"), fd);
@@ -288,129 +282,121 @@
break;
}
case 'j':
- width_given = true;
- player.setWidth ( strtol(optarg, NULL, 0) );
+ widthGiven = true;
+ player.setWidth ( parser.argument<long>(i));
log_debug (_("Setting width to " SIZET_FMT), player.getWidth());
break;
case 'g':
-#ifdef USE_DEBUGGER
+ #ifdef USE_DEBUGGER
log_debug (_("Setting debugger ON"));
debugger.enabled(true);
-// debugger.startServer(&debugger);
+ // debugger.startServer(&debugger);
debugger.console();
-#else
- printf(_("No debugger; disabled at compile time, -g is
invalid\n"));
+ #else
+ log_error (_("No debugger; disabled at compile time, -g is
invalid"));
exit(EXIT_FAILURE);
-#endif
+ #endif
break;
case 'k':
- height_given = true;
- player.setHeight ( strtol(optarg, NULL, 0) );
+ heightGiven = true;
+ player.setHeight ( parser.argument<long>(i));
log_debug (_("Setting height to " SIZET_FMT),
player.getHeight());
break;
case 'x':
- called_by_plugin = true;
- player.setWindowId(strtol(optarg, NULL, 0));
+ plugin = true;
+ player.setWindowId(parser.argument<long>(i));
break;
case '1':
player.setDoLoop(false);
break;
case 'r':
- specified_rendering_flag=true;
-
- switch (strtol(optarg, NULL, 0)) {
- case 0:
+ renderflag = true;
+ switch (parser.argument<char>(i))
+ {
+ case '0':
// Disable both
player.setDoRender(false);
player.setDoSound(false);
break;
- case 1:
+ case '1':
// Enable rendering, disable sound
player.setDoRender(true);
player.setDoSound(false);
break;
- case 2:
+ case '2':
// Enable sound, disable rendering
player.setDoRender(false);
player.setDoSound(true);
break;
- case 3:
+ case '3':
// Enable render & sound
player.setDoRender(true);
player.setDoSound(true);
break;
default:
- log_error (_("-r must be followed by 0, 1, 2 or 3 "));
+ log_error(_("ERROR: -r must be followed by 0, 1, 2
or 3 "));
break;
}
break;
case 't':
- player.setExitTimeout( (float) atof(optarg) );
+ player.setExitTimeout( parser.argument<float>(i) );
break;
case 'f':
-#ifdef GNASH_FPS_DEBUG
- player.setFpsPrintTime((float)strtod(optarg, NULL));
-#else // ndef GNASH_FPS_DEBUG
- printf(_("FPS debugging disabled at compile time, -f is
invalid\n"));
+ #ifdef GNASH_FPS_DEBUG
+ player.setFpsPrintTime(parser.argument<float>(i));
+ #else
+ cout << _("FPS debugging disabled at compile time, -f
is invalid") << endl;
exit(EXIT_FAILURE);
-#endif // ndef GNASH_FPS_DEBUG
+ #endif // ndef GNASH_FPS_DEBUG
break;
case 'P':
{
- string param = optarg;
+ std::string param = parser.argument(i);
size_t eq = param.find("=");
- string name, value;
- if ( eq == string::npos ) {
+ std::string name, value;
+ if ( eq == std::string::npos )
+ {
name = param;
value = "true";
- } else {
+ }
+ else
+ {
name = param.substr(0, eq);
- value = param.substr(eq+1);
+ value = param.substr(eq + 1);
}
- //cerr << "Param name = "<<name<<" val="<<value<<std::endl;
player.setParam(name, value);
- //params[name] = value;
break;
}
+ case 0:
+ infiles.push_back(parser.argument(i));
+ break;
+ }
+ }
+ catch (Arg_parser::ArgParserException &e)
+ {
+ cerr << _("Error parsing command line options: ") << e.what()
<< endl;
+ cerr << _("This is a Gnash bug.") << endl;
}
}
- if ( ! specified_rendering_flag ) {
+ if ( ! renderflag ) {
log_debug (_("No rendering flags specified, using rcfile"));
- if ( called_by_plugin ) {
+ if ( plugin ) {
player.setDoSound( rcfile.usePluginSound() );
} else {
player.setDoSound( rcfile.useSound() );
}
}
- if (called_by_plugin && height_given && width_given
+ if (plugin && heightGiven && widthGiven
&& !player.getHeight() && !player.getWidth()) {
// We were given dimensions of 0x0 to render to (probably the
plugin
// is playing an "invisible" movie. Disable video rendering.
player.setDoRender(false);
}
- // get the file name from the command line
- while (optind < argc) {
-
-#if 0 // Options setting variables should use the getopt style!
- // Some options set variables, like ip=127.0.0.1
- if (argc > 2 && strchr(argv[optind], '=')) {
- log_error (_("Got variable option (%s) on command line"),
- argv[optind]);
- } else {
-#endif
- infile = argv[optind];
- break;
-#if 0 // see above
- }
-#endif
- optind++;
- }
}
-
int
gnash_main(int argc, char *argv[])
{
@@ -437,11 +423,11 @@
}
// No file name was supplied
- if (!infile) {
- std::cerr << "Error: no input file was specified." << endl << endl;
+ if (infiles.empty()) {
+ cerr << "Error: no input file was specified." << endl;
usage();
return EXIT_FAILURE;
}
- return player.run(argc, argv, infile, url);
+ return player.run(argc, argv, infiles.front().c_str(), url);
}
Index: libbase/arg_parser.cpp
===================================================================
RCS file: libbase/arg_parser.cpp
diff -N libbase/arg_parser.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libbase/arg_parser.cpp 15 Mar 2008 10:39:15 -0000 1.1
@@ -0,0 +1,193 @@
+// Arg_parser - A POSIX/GNU command line argument parser.
+// Copyright (C) 2006, 2007, 2008 Antonio Diaz Diaz.
+
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+
+
+#include <cstring>
+#include <string>
+#include <vector>
+
+#include "arg_parser.h"
+
+
+bool Arg_parser::parse_long_option( const char * const opt, const char * const
arg,
+ const Option options[], int & argind )
throw()
+ {
+ unsigned int len;
+ int index = -1;
+ bool exact = false, ambig = false;
+
+ for( len = 0; opt[len+2] && opt[len+2] != '='; ++len ) ;
+
+ // Test all long options for either exact match or abbreviated matches.
+ for( int i = 0; options[i].code != 0; ++i )
+ if( options[i].name && !std::strncmp( options[i].name, &opt[2], len ) )
+ {
+ if( std::strlen( options[i].name ) == len ) // Exact match found
+ { index = i; exact = true; break; }
+ else if( index < 0 ) index = i; // First nonexact match found
+ else if( options[index].code != options[i].code ||
+ options[index].has_arg != options[i].has_arg )
+ ambig = true; // Second or later nonexact match found
+ }
+
+ if( ambig && !exact )
+ {
+ _error = "option `"; _error += opt; _error += "' is ambiguous";
+ return false;
+ }
+
+ if( index < 0 ) // nothing found
+ {
+ _error = "unrecognized option `"; _error += opt; _error += '\'';
+ return false;
+ }
+
+ ++argind;
+ data.push_back( Record( options[index].code ) );
+
+ if( opt[len+2] ) // `--<long_option>=<argument>' syntax
+ {
+ if( options[index].has_arg == no )
+ {
+ _error = "option `--"; _error += options[index].name;
+ _error += "' doesn't allow an argument";
+ return false;
+ }
+ if( options[index].has_arg == yes && !opt[len+3] )
+ {
+ _error = "option `--"; _error += options[index].name;
+ _error += "' requires an argument";
+ return false;
+ }
+ data.back().argument = &opt[len+3];
+ return true;
+ }
+
+ if( options[index].has_arg == yes )
+ {
+ if( !arg )
+ {
+ _error = "option `--"; _error += options[index].name;
+ _error += "' requires an argument";
+ return false;
+ }
+ ++argind; data.back().argument = arg;
+ return true;
+ }
+
+ return true;
+ }
+
+
+bool Arg_parser::parse_short_option( const char * const opt, const char *
const arg,
+ const Option options[], int & argind )
throw()
+ {
+ int cind = 1; // character index in opt
+
+ while( cind > 0 )
+ {
+ int index = -1;
+ const unsigned char code = opt[cind];
+
+ if( code != 0 )
+ for( int i = 0; options[i].code; ++i )
+ if( code == options[i].code )
+ { index = i; break; }
+
+ if( index < 0 )
+ {
+ _error = "invalid option -- "; _error += code;
+ return false;
+ }
+
+ data.push_back( Record( code ) );
+ if( opt[++cind] == 0 ) { ++argind; cind = 0; } // opt finished
+
+ if( options[index].has_arg != no && cind > 0 && opt[cind] )
+ {
+ data.back().argument = &opt[cind]; ++argind; cind = 0;
+ }
+ else if( options[index].has_arg == yes )
+ {
+ if( !arg || !arg[0] )
+ {
+ _error = "option requires an argument -- "; _error += code;
+ return false;
+ }
+ data.back().argument = arg; ++argind; cind = 0;
+ }
+ }
+ return true;
+ }
+
+
+Arg_parser::Arg_parser( const int argc, const char * const argv[],
+ const Option options[], const bool in_order ) throw()
+ {
+ if( argc < 2 || !argv || !options ) return;
+
+ std::vector< std::string > non_options; // skipped non-options
+ int argind = 1; // index in argv
+
+ while( argind < argc )
+ {
+ const unsigned char ch1 = argv[argind][0];
+ const unsigned char ch2 = ( ch1 ? argv[argind][1] : 0 );
+
+ if( ch1 == '-' && ch2 ) // we found an option
+ {
+ const char * const opt = argv[argind];
+ const char * const arg = (argind + 1 < argc) ? argv[argind+1] : 0;
+ if( ch2 == '-' )
+ {
+ if( !argv[argind][2] ) { ++argind; break; } // we found "--"
+ else if( !parse_long_option( opt, arg, options, argind ) ) break;
+ }
+ else if( !parse_short_option( opt, arg, options, argind ) ) break;
+ }
+ else
+ {
+ if( !in_order ) non_options.push_back( argv[argind++] );
+ else { data.push_back( Record() ); data.back().argument =
argv[argind++]; }
+ }
+ }
+ if(! _error.empty() ) data.clear();
+ else
+ {
+ for( unsigned int i = 0; i < non_options.size(); ++i )
+ { data.push_back( Record() ); data.back().argument.swap( non_options[i]
); }
+ while( argind < argc )
+ { data.push_back( Record() ); data.back().argument = argv[argind++]; }
+ }
+ }
+
+
+Arg_parser::Arg_parser( const char * const opt, const char * const arg,
+ const Option options[] ) throw()
+ {
+ if( !opt || !opt[0] || !options ) return;
+
+ if( opt[0] == '-' && opt[1] ) // we found an option
+ {
+ int argind = 1; // dummy
+ if( opt[1] == '-' )
+ { if( opt[2] ) parse_long_option( opt, arg, options, argind ); }
+ else
+ parse_short_option( opt, arg, options, argind );
+ if(! _error.empty() ) data.clear();
+ }
+ else { data.push_back( Record() ); data.back().argument = opt; }
+ }
Index: libbase/arg_parser.h
===================================================================
RCS file: libbase/arg_parser.h
diff -N libbase/arg_parser.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libbase/arg_parser.h 15 Mar 2008 10:39:15 -0000 1.1
@@ -0,0 +1,135 @@
+// Arg_parser - A POSIX/GNU command line argument parser.
+// Copyright (C) 2006, 2007, 2008 Antonio Diaz Diaz.
+
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+
+
+// Arg_parser reads the arguments in `argv' and creates a number of
+// option codes, option arguments and non-option arguments.
+
+// In case of error, `error' returns a non-empty error message.
+
+// `options' is an array of `struct Option' terminated by an element
+// containing a code which is zero. A null name means a short-only
+// option. A code value outside the unsigned char range means a
+// long-only option.
+
+// Arg_parser normally makes it appear as if all the option arguments
+// were specified before all the non-option arguments for the purposes
+// of parsing, even if the user of your program intermixed option and
+// non-option arguments. If you want the arguments in the exact order
+// the user typed them, call `Arg_parser' with `in_order' = true.
+
+// The argument `--' terminates all options; any following arguments are
+// treated as non-option arguments, even if they begin with a hyphen.
+
+// The syntax for optional option arguments is `-<short_option><argument>'
+// (without whitespace), or `--<long_option>=<argument>'.
+
+// This class has been modified with a templated parser.argument<> method,
allowing
+// typesafe handling of different return types, and saving using strto* on the
user
+// side. I've added an exception class because I'd like to know if we call an
argument
+// outside the range of argument - there's no reasonable situation in which
that would
+// happen. <bwy>
+
+#include <sstream>
+
+class Arg_parser
+ {
+public:
+ enum Has_arg { no, yes, maybe };
+
+ struct Option
+ {
+ int code; // Short option letter or code ( code != 0 )
+ const char * name; // Long option name (maybe null)
+ Has_arg has_arg;
+ };
+
+ class ArgParserException : public std::exception
+ {
+ public:
+ ArgParserException(const std::string& s)
+ :
+ _msg(s)
+ {}
+
+ virtual ~ArgParserException() throw() {}
+
+ const char* what() const throw() { return _msg.c_str(); }
+
+ private:
+
+ std::string _msg;
+ };
+
+private:
+ struct Record
+ {
+ int code;
+ std::string argument;
+ Record( const int c = 0 ) : code( c ) {}
+ };
+
+ std::string _error;
+ std::vector< Record > data;
+
+ bool parse_long_option( const char * const opt, const char * const arg,
+ const Option options[], int & argind ) throw();
+ bool parse_short_option( const char * const opt, const char * const arg,
+ const Option options[], int & argind ) throw();
+
+public:
+ Arg_parser( const int argc, const char * const argv[],
+ const Option options[], const bool in_order = false ) throw();
+
+ // Restricted constructor. Parses a single token and argument (if any)
+ Arg_parser( const char * const opt, const char * const arg,
+ const Option options[] ) throw();
+
+ const std::string & error() const throw() { return _error; }
+
+ // The number of arguments parsed (may be different from argc)
+ int arguments() const throw() { return data.size(); }
+
+ // If code( i ) is 0, argument( i ) is a non-option.
+ // Else argument( i ) is the option's argument (or empty).
+ int code( const int i ) const throw()
+ {
+ if( i >= 0 && i < arguments() ) return data[i].code;
+ else return 0;
+ }
+
+ std::string argument(const int i) const throw(ArgParserException)
+ {
+ if( i >= 0 && i < arguments() ) return data[i].argument;
+ else return _error;
+ }
+
+ template<typename T>
+ T argument(const int i) const throw (ArgParserException)
+ {
+ T t = 0;
+ if( i >= 0 && i < arguments() )
+ {
+ std::istringstream in(data[i].argument);
+ in >> t;
+ return t;
+ }
+ else throw ArgParserException("Code out of range");
+ }
+
+
+
+ };
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash ChangeLog libbase/Makefile.am gui/gnash.c...,
Benjamin Wolsey <=