gnash-commit
[Top][All Lists]
Advanced

[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");
+    }
+    
+  
+    
+  };




reply via email to

[Prev in Thread] Current Thread [Next in Thread]