OSDN Git Service

Support options set by preferences assigned within profile.xml
authorKeith Marshall <keithmarshall@users.sourceforge.net>
Tue, 1 May 2012 20:01:41 +0000 (20:01 +0000)
committerKeith Marshall <keithmarshall@users.sourceforge.net>
Tue, 1 May 2012 20:01:41 +0000 (20:01 +0000)
ChangeLog
Makefile.in
src/climain.cpp
src/clistub.c
src/pkgbase.h
src/pkgopts.cpp [new file with mode: 0644]
src/pkgopts.h
xml/profile.xml

index a0b94cc..5344ab6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2012-05-01  Keith Marshall  <keithmarshall@users.sourceforge.net>
+
+       Support options set by preferences assigned within profile.xml
+
+       * xml/profile.xml (preferences): New element; add defaults.
+
+       * src/pkgopts.h (OPTION_ASSIGNED_FLAGS, OPTION_DESKTOP_ARGS):
+       (OPTION_START_MENU_ARGS): New enumerated constants; define them.
+       (OPTION_DESKTOP, OPTION_START_MENU): New manifest constants.
+       (OPTION_ASSIGNED, mark_option_as_set): New macros; define them.
+       (pkgOpts::GetValue, pkgOpts::GetString): Restrict look-up index to
+       least significant 12-bits of full-range index value.
+       (pkgOpts::IsSet): New inline method; implement it.
+
+       * src/clistub.c (main): Reimplement --desktop and --start-menu
+       options; each now becomes an OPTION_GENERIC optarg string store.
+       (set_script_hook): Function no longer used; delete it; delegate to...
+       * src/pkgbase.h (pkgXmlDocument::EstablishPreferences): ...this new
+       method; declare it, providing its implementation in...
+       * src/pkgopts.cpp: ...this new file; invoke it...
+       * src/climain.cpp (climain): ...here.
+
+       * Makefile.in (CORE_DLL_OBJECTS): Add pkgopts.$OBJEXT
+
 2012-04-30  Keith Marshall  <keithmarshall@users.sourceforge.net>
 
        Correct sequence of installation/removal progress reporting.
index 7458161..15e9df0 100644 (file)
@@ -60,11 +60,11 @@ LIBS = -Wl,-Bstatic -llua -lz -lbz2 -llzma -Wl,-Bdynamic -lwininet
 CORE_DLL_OBJECTS  =  climain.$(OBJEXT) pkgshow.$(OBJEXT) dmh.$(OBJEXT) \
    pkgbind.$(OBJEXT) pkginet.$(OBJEXT) pkgstrm.$(OBJEXT) pkgname.$(OBJEXT) \
    pkgexec.$(OBJEXT) pkgfind.$(OBJEXT) pkginfo.$(OBJEXT) pkgspec.$(OBJEXT) \
-   sysroot.$(OBJEXT) pkghash.$(OBJEXT) pkgkeys.$(OBJEXT) pkgdeps.$(OBJEXT) \
-   mkpath.$(OBJEXT)  pkgreqs.$(OBJEXT) pkginst.$(OBJEXT) pkgunst.$(OBJEXT) \
+   pkgopts.$(OBJEXT) sysroot.$(OBJEXT) pkghash.$(OBJEXT) pkgkeys.$(OBJEXT) \
+   pkgdeps.$(OBJEXT) pkgreqs.$(OBJEXT) pkginst.$(OBJEXT) pkgunst.$(OBJEXT) \
    tarproc.$(OBJEXT) xmlfile.$(OBJEXT) keyword.$(OBJEXT) vercmp.$(OBJEXT) \
-   tinyxml.$(OBJEXT) tinyxmlparser.$(OBJEXT) \
-   tinystr.$(OBJEXT) tinyxmlerror.$(OBJEXT)
+   tinyxml.$(OBJEXT) tinystr.$(OBJEXT) tinyxmlparser.$(OBJEXT) \
+   mkpath.$(OBJEXT)  tinyxmlerror.$(OBJEXT)
 
 script_srcdir = ${srcdir}/scripts/libexec
 
index 8d575db..c2f1f16 100644 (file)
@@ -220,6 +220,11 @@ EXTERN_C int climain( int argc, char **argv )
         */
        dbase.LoadSystemMap();
 
+       /* ...initialise any preferences which the user may
+        * have specified within profile.xml...
+        */
+       dbase.EstablishPreferences();
+
        /* ...and invoke the appropriate action handler.
         */
        switch( action )
index b0e593e..4220aa2 100644 (file)
@@ -396,62 +396,6 @@ static int xatoi( const char *input )
   return result;
 }
 
-static void set_script_hook( const char *hook, const char *optarg )
-{
-  /* Helper function to initialise the environment variables which
-   * are associated with Lua scripting hooks, when the user specifies
-   * the appropriate activation options on the command line.
-   */
-  if( optarg != NULL )
-  {
-    /* An optional argument was assigned for the hook...
-     */
-    int arglen = strlen( optarg );
-    const char *all_users = "all-users";
-    const char *value_none = "none";
-    if( strncmp( optarg, all_users, arglen ) == 0 )
-    {
-      /* When this is the "all-users" qualifier, we append it to
-       * the value to be assigned to the environment variable.
-       */
-      const char *fmt = "%s --%s";
-      char tmp[1 + snprintf( NULL, 0, fmt, hook, all_users )];
-      snprintf( tmp, sizeof( tmp ), fmt, hook, all_users );
-      putenv( tmp );
-    }
-    else if( strncmp( optarg, value_none, arglen ) == 0 )
-    {
-      /* When it is the "none" qualifier, we remove any prior
-       * assignment to the respective environment variable.
-       *
-       * FIXME: to support assignment from within profile.xml,
-       * we will eventually need additional coding here, to
-       * override any profile.xml assignment.
-       */
-      char tmp[strlen( hook )];
-      char *p = tmp;
-      do { *p++ = *hook;
-        } while( *hook++ != '=' );
-      *p = '\0';
-      putenv( tmp );
-    }
-    else
-    { /* No other qualifier is supported; diagnose and ignore.
-       */
-      while( *hook++ != '=' ) /* advance pointer; no other action */;
-      fprintf( stderr,
-         "%s: *** WARNING *** invalid argument '%s' to option %s ignored\n",
-         progname, optarg, hook
-       );
-    }
-  }
-  else
-    /* No qualifying option argument specified; simply assign the
-     * hook variable value, as passed from the getopts() handler.
-     */
-    putenv( hook );
-}
-
 #define atmost( lim, val )             ((lim) < (val)) ? (lim) : (val)
 
 int main( int argc, char **argv )
@@ -491,8 +435,8 @@ int main( int argc, char **argv )
 
       { "all-related",    no_argument,         &optref,   OPTION_ALL_RELATED },
 
-      { "desktop",        optional_argument,   NULL,      'D'                },
-      { "start-menu",     optional_argument,   NULL,      'M'                },
+      { "desktop",        optional_argument,   &optref,   OPTION_DESKTOP     },
+      { "start-menu",     optional_argument,   &optref,   OPTION_START_MENU  },
 
 #     if DEBUG_ENABLED( DEBUG_TRACE_DYNAMIC )
        /* The "--trace" option is supported only when dynamic tracing
@@ -556,20 +500,6 @@ int main( int argc, char **argv )
            ++parsed_options.flags[OPTION_FLAGS].numeric;
          break;
 
-       case 'D':
-         /* This is a request to enable, or disable, the Lua scripting
-          * hook for installation of desktop shortcuts.
-          */
-         set_script_hook( "MINGW_GET_DESKTOP_HOOK=--desktop", optarg );
-         break;
-
-       case 'M':
-         /* This is a request to enable, or disable, the Lua scripting
-          * hook for installation of start menu shortcuts.
-          */
-         set_script_hook( "MINGW_GET_START_MENU_HOOK=--start-menu", optarg );
-         break;
-
        case OPTION_GENERIC:
          switch( optref & OPTION_STORAGE_CLASS )
          {
@@ -583,6 +513,7 @@ int main( int argc, char **argv )
              /* This is a simple store of a option argument
               * which represents a character string.
               */
+             mark_option_as_set( parsed_options, optref );
              parsed_options.flags[optref & 0xfff].string = optarg;
              break;
 
@@ -590,6 +521,7 @@ int main( int argc, char **argv )
              /* This is also a simple store of the argument value,
               * in this case interpreted as a number.
               */
+             mark_option_as_set( parsed_options, optref );
              parsed_options.flags[optref & 0xfff].numeric = xatoi( optarg );
              break;
 
@@ -599,6 +531,7 @@ int main( int argc, char **argv )
               * stored in the option slot, forming the bitwise logical
               * .OR. of the pair of values.
               */
+             mark_option_as_set( parsed_options, optref );
              parsed_options.flags[optref & 0xfff].numeric |= xatoi( optarg );
              break;
 
index c40a36b..be89802 100644 (file)
@@ -388,6 +388,12 @@ class pkgXmlDocument : public TiXmlDocument
     pkgActionItem* actions;
 
   public:
+    /* Method to interpret user preferences for mingw-get processing
+     * options, which are specified within profile.xml rather than on
+     * the command line.
+     */
+    void EstablishPreferences();
+
     /* Method to synchronise the state of the local package manifest
      * with the master copy held on the distribution server.
      */
diff --git a/src/pkgopts.cpp b/src/pkgopts.cpp
new file mode 100644 (file)
index 0000000..269db24
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * pkgopts.cpp
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2012, MinGW Project
+ *
+ *
+ * Implementation of XML interpreter for configuation of preferences.
+ *
+ *
+ * This is free software.  Permission is granted to copy, modify and
+ * redistribute this software, under the provisions of the GNU General
+ * Public License, Version 3, (or, at your option, any later version),
+ * as published by the Free Software Foundation; see the file COPYING
+ * for licensing details.
+ *
+ * Note, in particular, that this software is provided "as is", in the
+ * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not
+ * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY
+ * PARTICULAR PURPOSE.  Under no circumstances will the author, or the
+ * MinGW Project, accept liability for any damages, however caused,
+ * arising from the use of this software.
+ *
+ */
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "dmh.h"
+
+#include "pkgbase.h"
+#include "pkgkeys.h"
+#include "pkgopts.h"
+
+#define STATIC_INLINE  static __inline__ __attribute__((__always_inline__))
+
+#define declare_hook(NAME)      initialise_hook(MINGW_GET_##NAME##_HOOK)
+#define initialise_hook(NAME)   static const char *NAME = stringify_hook(NAME)
+#define stringify_hook(NAME)    #NAME
+
+declare_hook(DESKTOP);
+declare_hook(START_MENU);
+
+#define PKG_DESKTOP_HOOK       MINGW_GET_DESKTOP_HOOK, desktop_options
+#define PKG_START_MENU_HOOK    MINGW_GET_START_MENU_HOOK, start_menu_options
+
+#define desktop_options        desktop_option, all_users_option
+#define start_menu_options     start_menu_option, all_users_option
+
+static const char *desktop_option = "--desktop";
+static const char *start_menu_option = "--start-menu";
+static const char *all_users_option = "--all-users";
+
+#define opt_strcmp(OPT,KEY)    strcmp( OPT, KEY + 2 )
+
+class pkgPreferenceEvaluator
+{
+  /* A locally implemented class, providing the interpreter for
+   * the content of any <preferences>...</preferences> sections
+   * found within the XML profile database.
+   */
+  public:
+    pkgPreferenceEvaluator( pkgXmlNode *opt ):ref( opt ){}
+    void GetNext( const char *key ){ ref = ref->FindNextAssociate( key ); }
+    const char *SetName(){ return optname = ref->GetPropVal( name_key, NULL ); }
+    const char *SetName( const char *name ){ return optname = name; }
+    void PresetScriptHook( int, const char *, ... );
+    void SetScriptHook( const char *, ... );
+    pkgXmlNode *Current(){ return ref; }
+
+  private:
+    pkgXmlNode *ref;
+    const char *optname;
+
+    inline const char *SetOptions( const char *, va_list, const char * );
+    inline const char *ValidatedOption( const char *, va_list );
+    inline const char *AttributeError( unsigned, const char * );
+};
+
+/* XML tag/attribute key names, used exclusively within this module.
+ */
+static const char *prefs_key = "preferences";
+static const char *option_key = "option";
+static const char *value_key = "value";
+
+STATIC_INLINE int pkg_setenv( const char *varname, const char *value )
+{
+  /* A helper function, approximating the effect of POSIX' setenv(),
+   * (which Windows lacks), when invoked as setenv( varname, value, 1 )
+   */
+  char assignment[2 + strlen( varname ) + strlen( value )];
+  sprintf( assignment, "%s=%s", varname, value );
+  return putenv( assignment );
+}
+
+const char *pkgPreferenceEvaluator::ValidatedOption
+( const char *keyword, va_list valid_opts )
+{
+  /* A private helper method, used by the SetOptions() method
+   * to filter out any value assignment, which may not be valid
+   * for the option being processed.
+   */
+  unsigned matched = 0;
+  const char *retval = NULL, *chkval;
+  while( (chkval = va_arg( valid_opts, const char * )) != NULL )
+  {
+    /* For each permitted matching keyword in turn...
+     */
+    const char *chk = chkval;
+    while( *chk == '-' )
+      /*
+       * ...and NOT considering leading hyphens...
+       */
+      ++chk;
+
+    /* ...capture the first permitted keyword with initial substring
+     * matching the option under test; continue to check for, and count
+     * any further possible matches.
+     */
+    if( (strncmp( chk, keyword, strlen( keyword ) ) == 0) && (++matched == 1) )
+      retval = chkval;
+  }
+  /* Exactly one match is a successful outcome; otherwise punt.
+   */
+  return (matched == 1) ? retval : AttributeError( matched, keyword );
+}
+
+const char *pkgPreferenceEvaluator::AttributeError
+( unsigned why_failed, const char *keyword_not_validated )
+{
+  /* Private helper method, used by ValidatedOption() to diagnose
+   * ambiguous, or simply failed, keyword matches.
+   */
+  dmh_notify( DMH_WARNING,
+      "option '%s': %s attribute '%s' ignored\n", optname,
+      why_failed ? "ambiguous" : "invalid", keyword_not_validated
+    );
+
+  /* ValidatedOption() uses this NULL return value, as its own
+   * failed status return value.
+   */
+return NULL;
+}
+
+const char *pkgPreferenceEvaluator::SetOptions
+( const char *value, va_list valid_opts, const char *extra )
+{
+  /* A private helper method to generate the list of attribute
+   * values to be appended to the environment variable assignment,
+   * when creating an IPC hook for use by the lua interpreter.
+   *
+   * Note that the resultant attribute list is specified on the
+   * heap, and the caller must free the associated memory.
+   */
+  if( (extra != NULL) && (strncmp( extra, value_none, strlen( extra )) == 0) )
+    /*
+     * Passing an extra attribute of "none" is a special case;
+     * it overrides all automatic attribute settings.
+     */
+    value = strdup( value_none );
+
+  else if( ((value = strdup( value )) != NULL) && (extra != NULL) )
+  {
+    /* This is the normal case.  The extra attribute string represents
+     * a comma or space separated list of attributes to be appended to
+     * the automatic attribute settings; we must decompose it, so that
+     * we may validate each specified attribute.
+     */
+    char extlist[1 + strlen( extra )];
+    char *next = strcpy( extlist, extra );
+    while( *next )
+    {
+      /* We may still have unparsed extra attributes...
+       */
+      while( (*next == ',') || isspace( *next ) )
+       /*
+        * ...so, first strip away any leading separators...
+        */
+       ++next;
+      if( *next )
+      {
+       /* ...and, when any further potential attribute remains...
+        */
+       const char *attribute = next;
+       while( *next && (*next != ',') && (! isspace( *next )) )
+         /*
+          * ...mark and collect the unvalidated attribute name...
+          */
+         ++next;
+       if( *next )
+         /*
+          * ...NUL terminate it, and prepare to process the following
+          * attribute, if any.
+          */
+         *next++ = '\0';
+
+       /* Validate the collected attribute, expanding any abbreviation
+        * to the fully qualified, unabridged attribute name; when valid...
+        */
+       if( (attribute = ValidatedOption( attribute, valid_opts )) != NULL )
+       {
+         /* ...create additional space within the dynamically allocated
+          * heap block, in which the validated attribute list is to be
+          * returned...
+          */
+         void *tmp_value = (void *)(value);
+         size_t realloc_len = 2 + strlen( attribute ) + strlen( value );
+         if( (tmp_value = realloc( tmp_value, realloc_len )) != NULL )
+         {
+           /* ...and append the last validated attribute.
+            */
+           sprintf( (char *)(tmp_value), "%s %s", tmp_value, attribute );
+           value = (const char *)(tmp_value);
+         }
+       }
+      }
+    }
+  }
+  /* Return the resultant validated attribute list.
+   */
+  return value;
+}
+
+void pkgPreferenceEvaluator::PresetScriptHook( int index, const char *key, ... )
+{
+  /* Method to interpret options specified on the command line,
+   * and initialise associated environment variable hooks, such
+   * that they override XML preference settings.
+   */
+  if( pkgOptions()->IsSet( index ) && (key != NULL) && (*key != '\0') )
+  {
+    /* The indexed command line option has been specified, and
+     * it is associated with a viable environment variable name;
+     * validate any option arguments against the variadic list
+     * of valid attribute values...
+     */
+    va_list argv;
+    va_start( argv, key );
+    const char *value = va_arg( argv, const char * );
+    const char *preset = pkgOptions()->GetString( index );
+    if( (value = SetOptions( SetName( value ), argv, preset )) != NULL )
+    {
+      /* ...initialise the environment variable accordingly,
+       * and release the temporary heap memory block returned
+       * by the validation routine.
+       */
+      pkg_setenv( key, value );
+      free( (void *)(value) );
+    }
+    va_end( argv );
+  }
+}
+
+void pkgPreferenceEvaluator::SetScriptHook( const char *key, ... )
+{
+  /* Method to interpret options specified as XML preferences,
+   * and assign values to their associated environment variable
+   * hooks, provided no prior assignment based on command line
+   * settings is in place.
+   */
+  if( (key != NULL) && (*key != '\0') )
+  {
+    /* The environment variable name is viable; provided there
+     * is no prior assignment to it, validate the content of any
+     * specified preferences attribute against the variadic list
+     * of valid attribute values...
+     */
+    va_list argv;
+    va_start( argv, key );
+    const char *value = va_arg( argv, const char * );
+    const char *old_value = getenv( key );
+    if( old_value == NULL )
+    {
+      /* ...i.e. there is no prior assignment...
+       */
+      if( value != NULL )
+      {
+       /* ...and there is at least one qualifying attribute...
+        */
+       value = SetOptions( value, argv, ref->GetPropVal( value_key, NULL ) );
+       if( value != NULL )
+       {
+         /* ...populate the environment variable accordingly,
+          * and release the temporary heap memory block returned
+          * by the validation routine.
+          */
+         pkg_setenv( key, value );
+         free( (void *)(value) );
+       }
+      }
+    }
+    else if( (value == NULL) && (strcmp( old_value, value_none ) == 0) )
+      /*
+       * This is a special case, in which the environment variable
+       * hook has been explicitly initialised to "none", and there
+       * is an explicitly NULL qualifying attribute; this is used
+       * to explicitly request that the environment variable hook
+       * should be deleted.
+       */
+      pkg_setenv( key, "" );
+
+    va_end( argv );
+  }
+}
+
+void pkgXmlDocument::EstablishPreferences()
+{
+  /* Method to interpret the content of any "preferences" sections
+   * appearing within the XML database.
+   */
+  pkgXmlNode *dbase_root;
+  if( (dbase_root = GetRoot()) != NULL )
+  {
+    /* Initialise preferences set by command line options.
+     */
+    pkgPreferenceEvaluator opt( dbase_root );
+    opt.PresetScriptHook( OPTION_DESKTOP, PKG_DESKTOP_HOOK, NULL );
+    opt.PresetScriptHook( OPTION_START_MENU, PKG_START_MENU_HOOK, NULL );
+
+    /* Locate the first of any XML "preferences" elements...
+     */
+    pkgXmlNode *prefs = dbase_root->FindFirstAssociate( prefs_key );
+    while( prefs != NULL )
+    {
+      /* ...and interpret any contained "enable" specifications.
+       */
+      pkgPreferenceEvaluator opt( prefs->FindFirstAssociate( option_key ));
+      while( opt.Current() != NULL )
+      {
+       const char *optname;
+       if( (optname = opt.SetName()) != NULL )
+       {
+         if( opt_strcmp( optname, desktop_option ) == 0 )
+           /*
+            * Enable post-install hook for creation of desktop shortcuts;
+            * by default, these are defined for current user only, but may
+            * optionally be provided for all users.
+            */
+           opt.SetScriptHook( PKG_DESKTOP_HOOK, NULL );
+
+         else if( opt_strcmp( optname, start_menu_option ) == 0 )
+           /*
+            * Similarly, enable hook for creation of start menu shortcuts.
+            */
+           opt.SetScriptHook( PKG_START_MENU_HOOK, NULL );
+
+         else
+           /* Any unrecognised option specification is simply ignored,
+            * after posting an appropriate diagnostic message.
+            */
+           dmh_notify( DMH_WARNING, "unknown option '%s' ignored\n", optname );
+       }
+       /* Repeat for any further "enable" specifations...
+        */
+       opt.GetNext( option_key );
+      }
+      /* ...and for any additional "preferences" sections.
+       */
+      prefs = prefs->FindNextAssociate( prefs_key );
+    }
+
+    /* Finally, remove any environment variable hooks which have been
+     * created for options which are to be explicitly disabled.
+     */
+    opt.SetScriptHook( MINGW_GET_DESKTOP_HOOK, NULL );
+    opt.SetScriptHook( MINGW_GET_START_MENU_HOOK, NULL );
+  }
+}
+
+/* $RCSfile$: end of file */
index 7ea3bdf..0446bd6 100644 (file)
@@ -38,6 +38,9 @@ enum
    */
   OPTION_FLAGS,
   OPTION_EXTRA_FLAGS,
+  OPTION_ASSIGNED_FLAGS,
+  OPTION_DESKTOP_ARGS,
+  OPTION_START_MENU_ARGS,
   OPTION_DEBUGLEVEL,
 
   /* This final entry specifies the size of the parameter array which
@@ -63,6 +66,13 @@ struct pkgopts
   flags[OPTION_TABLE_SIZE];
 };
 
+/* The following macro provides a mechanism for recording when
+ * any string or numeric value option is assigned, even in the
+ * event that the assignment reproduces the default value.
+ */
+#define mark_option_as_set( options, index )  \
+  (options).flags[OPTION_ASSIGNED_FLAGS].numeric |= OPTION_ASSIGNED(index)
+
 /* Bit-mapped control tags used by the CLI options parsing code...
  */
 #define OPTION_SHIFT_MASK      (0x0000000f << 24)
@@ -75,9 +85,12 @@ struct pkgopts
 #define OPTION_STORE_NUMBER    (0x00000002 << 28)
 #define OPTION_MERGE_NUMBER    (0x00000003 << 28)
 /*
- * ...with specific handling for individual options.
+ * ...with specific handling for individual options, when set (as
+ * indicated by evaluation of...
  */
-#define OPTION_TRACE  (OPTION_MERGE_NUMBER | OPTION_DEBUGLEVEL)
+#define OPTION_ASSIGNED(N)     (1 << (((N) & 0x1F) - OPTION_ASSIGNED_FLAGS -1))
+
+#define OPTION_TRACE           (OPTION_MERGE_NUMBER | OPTION_DEBUGLEVEL)
 
 /* Options controlled by bit-mapped flags within OPTION_FLAGS...
  */
@@ -93,6 +106,9 @@ struct pkgopts
 #define OPTION_ALL_DEPS        (0x00000090)
 #define OPTION_ALL_RELATED     (0x00000100)
 
+#define OPTION_DESKTOP         (OPTION_STORE_STRING | OPTION_DESKTOP_ARGS)
+#define OPTION_START_MENU      (OPTION_STORE_STRING | OPTION_START_MENU_ARGS)
+
 #if __cplusplus
 /*
  * We provide additional features for use in C++ modules.
@@ -111,17 +127,23 @@ class pkgOpts : protected pkgopts
    * of utility methods with the pkgopts structure.
    */
   public:
+    inline unsigned IsSet( int index )
+    {
+      return this
+       ? flags[OPTION_ASSIGNED_FLAGS].numeric & OPTION_ASSIGNED(index)
+       : 0;
+    }
     inline unsigned GetValue( int index )
     {
       /* Retrieve the value of a numeric data entry.
        */
-      return this ? (flags[index].numeric) : 0;
+      return this ? (flags[index & 0xFFF].numeric) : 0;
     }
     inline const char *GetString( int index )
     {
       /* Retrieve a pointer to a string data entry.
        */
-      return this ? (flags[index].string) : NULL;
+      return this ? (flags[index & 0xFFF].string) : NULL;
     }
     inline unsigned Test( unsigned mask, int index = OPTION_FLAGS )
     {
index 11d0cc9..e76b7e1 100644 (file)
@@ -4,7 +4,7 @@
     $Id$
 
     Written by Keith Marshall  <keithmarshall@users.sourceforge.net>
-    Copyright (C) 2009, 2010, MinGW Project
+    Copyright (C) 2009, 2010, 2012, MinGW Project
 
 
     Master configuration profile for mingw-get.
     arising from the use of this software.
   -->
 
+  <preferences>
+    <!--
+      "preferences" specifications provide a mechanism for defining
+      user specified default attributes for command line options such
+      as the "desktop" and "start-menu" short-cut creation controls.
+
+      Each of these options is disabled by default.  By uncommenting
+      any one of the following declarations, for each option, you may
+      change that default.  Note that you may still override settings
+      you establish here, by also specifying the option on the command
+      line as before; you may also disable an option enabled here, by
+      assigning an attribute value of "none" on the command line.
+    -->
+
+    <!--option name="desktop" /-->
+    <!--option name="desktop" value="all-users" /-->
+
+    <!--option name="start-menu" /-->
+    <!--option name="start-menu" value="all-users" /-->
+  </preferences>
+
   <repository uri="http://prdownloads.sourceforge.net/mingw/%F.xml.lzma?download">
     <!--
       The "repository" specification identifies the URI where package