Add tag for "versioned=API".

This adds the `versioned=API` tag. This should be a very uncommonly
needed tag, and is really only needed to fix versioning mistakes that
are already out in the wild.

For example, some of libc's __aeabi_* functions were originally placed
in the private version, but that was incorrect. They are now in
LIBC_N, but when building against any version prior to N we need the
symbol to be unversioned (otherwise it won't resolve on M where it is
private).

Test: make ndk
Change-Id: I0cd2f80cf4b32356356914cf7ff4119e67f15032
diff --git a/cc/gen_stub_libs.py b/cc/gen_stub_libs.py
index 4b7c244..ae8b17b 100755
--- a/cc/gen_stub_libs.py
+++ b/cc/gen_stub_libs.py
@@ -71,6 +71,19 @@
     return re.split(r'\s+', all_tags)
 
 
+def get_tag_value(tag):
+    """Returns the value of a key/value tag.
+
+    Raises:
+        ValueError: Tag is not a key/value type tag.
+
+    Returns: Value part of tag as a string.
+    """
+    if '=' not in tag:
+        raise ValueError('Not a key/value tag: ' + tag)
+    return tag.partition('=')[2]
+
+
 def version_is_private(version):
     """Returns True if the version name should be treated as private."""
     return version.endswith('_PRIVATE') or version.endswith('_PLATFORM')
@@ -87,7 +100,7 @@
         return True
     if not symbol_in_arch(tags, arch):
         return True
-    if not symbol_in_version(tags, arch, api):
+    if not symbol_in_api(tags, arch, api):
         return True
     return False
 
@@ -178,8 +191,8 @@
     return not has_arch_tags
 
 
-def symbol_in_version(tags, arch, version):
-    """Returns true if the symbol is present for the given version."""
+def symbol_in_api(tags, arch, api):
+    """Returns true if the symbol is present for the given API level."""
     introduced_tag = None
     arch_specific = False
     for tag in tags:
@@ -191,7 +204,7 @@
             arch_specific = True
         elif tag == 'future':
             # This symbol is not in any released API level.
-            # TODO(danalbert): These need to be emitted for version == current.
+            # TODO(danalbert): These need to be emitted for api == current.
             # That's not a construct we have yet, so just skip it for now.
             return False
 
@@ -200,9 +213,28 @@
         # available.
         return True
 
-    # The tag is a key=value pair, and we only care about the value now.
-    _, _, version_str = introduced_tag.partition('=')
-    return version >= int(version_str)
+    return api >= int(get_tag_value(introduced_tag))
+
+
+def symbol_versioned_in_api(tags, api):
+    """Returns true if the symbol should be versioned for the given API.
+
+    This models the `versioned=API` tag. This should be a very uncommonly
+    needed tag, and is really only needed to fix versioning mistakes that are
+    already out in the wild.
+
+    For example, some of libc's __aeabi_* functions were originally placed in
+    the private version, but that was incorrect. They are now in LIBC_N, but
+    when building against any version prior to N we need the symbol to be
+    unversioned (otherwise it won't resolve on M where it is private).
+    """
+    for tag in tags:
+        if tag.startswith('versioned='):
+            return api >= int(get_tag_value(tag))
+    # If there is no "versioned" tag, the tag has been versioned for as long as
+    # it was introduced.
+    return True
+
 
 
 def handle_global_scope(scope, line, src_file, version_file, arch, api):
@@ -221,19 +253,21 @@
 
     # Line is now in the format "<symbol-name>; # tags"
     # Tags are whitespace separated.
-    symbol_name, _, rest = line.strip().partition(';')
+    symbol_name, _, _ = line.strip().partition(';')
     tags = get_tags(line)
 
     if not symbol_in_arch(tags, arch):
         return
-    if not symbol_in_version(tags, arch, api):
+    if not symbol_in_api(tags, arch, api):
         return
 
     if 'var' in tags:
         src_file.write('int {} = 0;\n'.format(symbol_name))
     else:
         src_file.write('void {}() {{}}\n'.format(symbol_name))
-    version_file.write(line)
+
+    if symbol_versioned_in_api(tags, api):
+        version_file.write(line)
 
 
 def generate(symbol_file, src_file, version_file, arch, api):