diff --git a/src/options.cc b/src/options.cc
index 4e01d69..9085cc6 100644
--- a/src/options.cc
+++ b/src/options.cc
@@ -211,7 +211,7 @@ Options::long_usage (FILE * stream)
            "Algorithm employed by gperf:\n");
   fprintf (stream,
            "  -k, --key-positions=KEYS\n"
-           "                         Select the key positions used in the hash function.\n"
+           "                         Specify the key positions to use in the hash function.\n"
            "                         The allowable choices range between 1-%d, inclusive.\n"
            "                         The positions are separated by commas, ranges may be\n"
            "                         used, and key positions may occur in any order.\n"
@@ -221,6 +221,11 @@ Options::long_usage (FILE * stream)
            "                         $,1,2,4,6-10.\n",
            Positions::MAX_KEY_POS);
   fprintf (stream,
+           "  -A, --allow-position-subset\n"
+           "                         If the --key-positions option is used, then key\n"
+           "                         positions used in the hash function will be chosen\n"
+           "                         only from among those given\n");
+  fprintf (stream,
            "  -D, --duplicates       Handle keywords that hash to duplicate values. This\n"
            "                         is useful for certain highly redundant keyword sets.\n");
   fprintf (stream,
@@ -504,6 +509,7 @@ Options::~Options ()
                "\nDUP is.........: %s"
                "\nNOLENGTH is....: %s"
                "\nRANDOM is......: %s"
+               "\nSUBSET is......: %s"
                "\nDEBUG is.......: %s"
                "\nlookup function name = %s"
                "\nhash function name = %s"
@@ -538,6 +544,7 @@ Options::~Options ()
                _option_word & DUP ? "enabled" : "disabled",
                _option_word & NOLENGTH ? "enabled" : "disabled",
                _option_word & RANDOM ? "enabled" : "disabled",
+               _option_word & SUBSET ? "enabled" : "disabled",
                _option_word & DEBUG ? "enabled" : "disabled",
                _function_name, _hash_name, _wordlist_name, _lengthtable_name,
                _stringpool_name, _slot_name, _initializer_suffix,
@@ -709,6 +716,7 @@ static const struct option long_options[] =
   { "switch", required_argument, NULL, 'S' },
   { "omit-struct-type", no_argument, NULL, 'T' },
   { "key-positions", required_argument, NULL, 'k' },
+  { "allow-position-subset", no_argument, NULL, 'A' },
   { "compare-strlen", no_argument, NULL, 'l' }, /* backward compatibility */
   { "compare-lengths", no_argument, NULL, 'l' },
   { "duplicates", no_argument, NULL, 'D' },
@@ -741,7 +749,7 @@ Options::parse_options (int argc, char *argv[])
 
   while ((option_char =
             getopt_long (_argument_count, _argument_vector,
-                         "acCdDe:Ef:F:gGhH:i:Ij:k:K:lL:m:nN:oOpPQ:rs:S:tTvW:Z:7",
+                         "aAcCdDe:Ef:F:gGhH:i:Ij:k:K:lL:m:nN:oOpPQ:rs:S:tTvW:Z:7",
                          long_options, NULL))
          != -1)
     {
@@ -749,6 +757,11 @@ Options::parse_options (int argc, char *argv[])
         {
         case 'a':               /* Generated code uses the ANSI prototype format.  */
           break;                /* This is now the default.  */
+        case 'A':               /* Allow a subset choice of specified key positions. */
+          {
+            _option_word |= SUBSET;
+            break;
+          }
         case 'c':               /* Generate strncmp rather than strcmp.  */
           {
             _option_word |= COMP;
diff --git a/src/options.h b/src/options.h
index 2ac53b8..7098b9c 100644
--- a/src/options.h
+++ b/src/options.h
@@ -106,10 +106,13 @@ enum Option_Type
   /* Randomly initialize the associated values table.  */
   RANDOM       = 1 << 20,
 
+  /* Allow a subset choice of specified key positions.  */
+  SUBSET       = 1 << 21,
+
   /* --- Informative output --- */
 
   /* Enable debugging (prints diagnostics to stderr).  */
-  DEBUG        = 1 << 21
+  DEBUG        = 1 << 22
 };
 
 /* Class manager for gperf program Options.  */
diff --git a/src/search.cc b/src/search.cc
index 9c8879a..40dad39 100644
--- a/src/search.cc
+++ b/src/search.cc
@@ -262,11 +262,22 @@ Search::count_duplicates_tuple (const Positions& positions, const unsigned int *
 void
 Search::find_positions ()
 {
-  /* If the user gave the key positions, we use them.  */
+  /* If the user gave the key positions, we use them, or else allow a
+     subset of them to be chosen.  */
+  Positions allowed;
   if (option[POSITIONS])
     {
-      _key_positions = option.get_key_positions();
-      return;
+      if (!option[SUBSET])
+        {
+          _key_positions = option.get_key_positions();
+          return;
+        }
+      allowed = option.get_key_positions();
+    }
+  else
+    {
+      allowed.set_useall(true);
+      allowed.add(Positions::LASTCHAR);
     }
 
   /* Compute preliminary alpha_unify table.  */
@@ -326,7 +337,16 @@ Search::find_positions ()
                         {
                           /* Position i is mandatory.  */
                           if (!mandatory.contains (i))
-                            mandatory.add (i);
+                            {
+                              if (!allowed.contains (i))
+                                {
+                                  fprintf (stderr, "Position %d is mandatory for this keyword list,\n"
+                                                   "but was disallowed via the -k option.\n",
+                                                   i + 1);
+                                  exit (1);
+                                }
+                              mandatory.add (i);
+                            }
                         }
                     }
                 }
@@ -346,7 +366,7 @@ Search::find_positions ()
       unsigned int best_duplicates_count = UINT_MAX;
 
       for (int i = imax; i >= -1; i--)
-        if (!current.contains (i))
+        if (!current.contains (i) && allowed.contains (i))
           {
             Positions tryal = current;
             tryal.add (i);
@@ -420,7 +440,7 @@ Search::find_positions ()
               if (current.contains (i2) && !mandatory.contains (i2))
                 {
                   for (int i3 = imax; i3 >= 0; i3--)
-                    if (!current.contains (i3))
+                    if (!current.contains (i3) && allowed.contains (i3))
                       {
                         Positions tryal = current;
                         tryal.remove (i1);
diff --git a/tests/test-6.exp b/tests/test-6.exp
index dd6ea72..2f22307 100644
--- a/tests/test-6.exp
+++ b/tests/test-6.exp
@@ -93,7 +93,7 @@ Details in the output code:
 
 Algorithm employed by gperf:
   -k, --key-positions=KEYS
-                         Select the key positions used in the hash function.
+                         Specify the key positions to use in the hash function.
                          The allowable choices range between 1-255, inclusive.
                          The positions are separated by commas, ranges may be
                          used, and key positions may occur in any order.
@@ -101,6 +101,10 @@ Algorithm employed by gperf:
                          hash function to consider ALL key positions, and $
                          indicates the "final character" of a key, e.g.,
                          $,1,2,4,6-10.
+  -A, --allow-position-subset
+                         If the --key-positions option is used, then key
+                         positions used in the hash function will be chosen
+                         only from among those given
   -D, --duplicates       Handle keywords that hash to duplicate values. This
                          is useful for certain highly redundant keyword sets.
   -m, --multiple-iterations=ITERATIONS
