Revert "libmojo: Uprev the library to r456626 from Chromium"
This reverts commit 8ac9103e05b66812c25348943383f9365d1ce3e0.
Reason for revert: Broke the mac_sdk
Exempt-From-Owner-Approval: Fixing mac_sdk
Change-Id: I0b74d1abaa66933a93fd6f82ff018e8948c1204e
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py
index 7b2f48d..371ad90 100644
--- a/build/android/gyp/util/build_utils.py
+++ b/build/android/gyp/util/build_utils.py
@@ -23,16 +23,12 @@
sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
from pylib.constants import host_paths
-sys.path.append(os.path.join(os.path.dirname(__file__),
- os.pardir, os.pardir, os.pardir))
-import gn_helpers
-
COLORAMA_ROOT = os.path.join(host_paths.DIR_SOURCE_ROOT,
'third_party', 'colorama', 'src')
# aapt should ignore OWNERS files in addition the default ignore pattern.
AAPT_IGNORE_PATTERN = ('!OWNERS:!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:' +
'!CVS:!thumbs.db:!picasa.ini:!*~:!*.d.stamp')
-HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0)
+_HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0)
_HERMETIC_FILE_ATTR = (0644 << 16L)
@@ -82,23 +78,31 @@
def ParseGnList(gn_string):
- """Converts a command-line parameter into a list.
+ # TODO(brettw) bug 573132: This doesn't handle GN escaping properly, so any
+ # weird characters like $ or \ in the strings will be corrupted.
+ #
+ # The code should import build/gn_helpers.py and then do:
+ # parser = gn_helpers.GNValueParser(gn_string)
+ # return return parser.ParseList()
+ # As of this writing, though, there is a CastShell build script that sends
+ # JSON through this function, and using correct GN parsing corrupts that.
+ #
+ # We need to be consistent about passing either JSON or GN lists through
+ # this function.
+ return ast.literal_eval(gn_string)
- If the input starts with a '[' it is assumed to be a GN-formatted list and
- it will be parsed accordingly. When empty an empty list will be returned.
- Otherwise, the parameter will be treated as a single raw string (not
- GN-formatted in that it's not assumed to have literal quotes that must be
- removed) and a list will be returned containing that string.
- The common use for this behavior is in the Android build where things can
- take lists of @FileArg references that are expanded via ExpandFileArgs.
- """
- if gn_string.startswith('['):
- parser = gn_helpers.GNValueParser(gn_string)
- return parser.ParseList()
- if len(gn_string):
- return [ gn_string ]
- return []
+def ParseGypList(gyp_string):
+ # The ninja generator doesn't support $ in strings, so use ## to
+ # represent $.
+ # TODO(cjhopman): Remove when
+ # https://code.google.com/p/gyp/issues/detail?id=327
+ # is addressed.
+ gyp_string = gyp_string.replace('##', '$')
+
+ if gyp_string.startswith('['):
+ return ParseGnList(gyp_string)
+ return shlex.split(gyp_string)
def CheckOptions(options, parser, required=None):
@@ -224,7 +228,6 @@
if not zipfile.is_zipfile(zip_path):
raise Exception('Invalid zip file: %s' % zip_path)
- extracted = []
with zipfile.ZipFile(zip_path) as z:
for name in z.namelist():
if name.endswith('/'):
@@ -245,12 +248,8 @@
dest = os.path.join(path, name)
MakeDirectory(os.path.dirname(dest))
os.symlink(z.read(name), dest)
- extracted.append(dest)
else:
z.extract(name, path)
- extracted.append(os.path.join(path, name))
-
- return extracted
def AddToZipHermetic(zip_file, zip_path, src_path=None, data=None,
@@ -268,7 +267,7 @@
assert (src_path is None) != (data is None), (
'|src_path| and |data| are mutually exclusive.')
CheckZipPath(zip_path)
- zipinfo = zipfile.ZipInfo(filename=zip_path, date_time=HERMETIC_TIMESTAMP)
+ zipinfo = zipfile.ZipInfo(filename=zip_path, date_time=_HERMETIC_TIMESTAMP)
zipinfo.external_attr = _HERMETIC_FILE_ATTR
if src_path and os.path.islink(src_path):
@@ -333,14 +332,7 @@
path_transform = path_transform or (lambda p, z: p)
added_names = set()
- output_is_already_open = not isinstance(output, basestring)
- if output_is_already_open:
- assert isinstance(output, zipfile.ZipFile)
- out_zip = output
- else:
- out_zip = zipfile.ZipFile(output, 'w')
-
- try:
+ with zipfile.ZipFile(output, 'w') as out_zip:
for in_file in inputs:
with zipfile.ZipFile(in_file, 'r') as in_zip:
in_zip._expected_crc = None
@@ -351,12 +343,8 @@
dst_name = path_transform(info.filename, in_file)
already_added = dst_name in added_names
if not already_added and not MatchesGlob(dst_name, exclude_patterns):
- AddToZipHermetic(out_zip, dst_name, data=in_zip.read(info),
- compress=info.compress_type != zipfile.ZIP_STORED)
+ AddToZipHermetic(out_zip, dst_name, data=in_zip.read(info))
added_names.add(dst_name)
- finally:
- if not output_is_already_open:
- out_zip.close()
def PrintWarning(message):
@@ -411,7 +399,8 @@
A path is assumed to be a "system" import if it is outside of chromium's
src/. The paths will be relative to the current directory.
"""
- module_paths = GetModulePaths()
+ module_paths = (m.__file__ for m in sys.modules.itervalues()
+ if m is not None and hasattr(m, '__file__'))
abs_module_paths = map(os.path.abspath, module_paths)
@@ -428,30 +417,6 @@
return sorted(set(non_system_module_paths))
-def GetModulePaths():
- """Returns the paths to all of the modules in sys.modules."""
- ForceLazyModulesToLoad()
- return (m.__file__ for m in sys.modules.itervalues()
- if m is not None and hasattr(m, '__file__'))
-
-
-def ForceLazyModulesToLoad():
- """Forces any lazily imported modules to fully load themselves.
-
- Inspecting the modules' __file__ attribute causes lazily imported modules
- (e.g. from email) to get fully imported and update sys.modules. Iterate
- over the values until sys.modules stabilizes so that no modules are missed.
- """
- while True:
- num_modules_before = len(sys.modules.keys())
- for m in sys.modules.values():
- if m is not None and hasattr(m, '__file__'):
- _ = m.__file__
- num_modules_after = len(sys.modules.keys())
- if num_modules_before == num_modules_after:
- break
-
-
def AddDepfileOption(parser):
# TODO(agrieve): Get rid of this once we've moved to argparse.
if hasattr(parser, 'add_option'):
@@ -459,20 +424,14 @@
else:
func = parser.add_argument
func('--depfile',
- help='Path to depfile (refer to `gn help depfile`)')
+ help='Path to depfile. Must be specified as the action\'s first output.')
-def WriteDepfile(depfile_path, first_gn_output, inputs=None, add_pydeps=True):
- assert depfile_path != first_gn_output # http://crbug.com/646165
- inputs = inputs or []
- if add_pydeps:
- inputs = GetPythonDependencies() + inputs
- MakeDirectory(os.path.dirname(depfile_path))
- # Ninja does not support multiple outputs in depfiles.
- with open(depfile_path, 'w') as depfile:
- depfile.write(first_gn_output.replace(' ', '\\ '))
+def WriteDepfile(path, dependencies):
+ with open(path, 'w') as depfile:
+ depfile.write(path)
depfile.write(': ')
- depfile.write(' '.join(i.replace(' ', '\\ ') for i in inputs))
+ depfile.write(' '.join(dependencies))
depfile.write('\n')
@@ -510,25 +469,11 @@
for k in lookup_path[1:]:
expansion = expansion[k]
- # This should match ParseGNList. The output is either a GN-formatted list
- # or a literal (with no quotes).
- if isinstance(expansion, list):
- new_args[i] = arg[:match.start()] + gn_helpers.ToGNString(expansion)
- else:
- new_args[i] = arg[:match.start()] + str(expansion)
+ new_args[i] = arg[:match.start()] + str(expansion)
return new_args
-def ReadSourcesList(sources_list_file_name):
- """Reads a GN-written file containing list of file names and returns a list.
-
- Note that this function should not be used to parse response files.
- """
- with open(sources_list_file_name) as f:
- return [file_name.strip() for file_name in f]
-
-
def CallAndWriteDepfileIfStale(function, options, record_path=None,
input_paths=None, input_strings=None,
output_paths=None, force=False,
@@ -568,8 +513,7 @@
all_depfile_deps = list(python_deps)
if depfile_deps:
all_depfile_deps.extend(depfile_deps)
- WriteDepfile(options.depfile, output_paths[0], all_depfile_deps,
- add_pydeps=False)
+ WriteDepfile(options.depfile, all_depfile_deps)
if stamp_file:
Touch(stamp_file)
diff --git a/build/android/pylib/__init__.py b/build/android/pylib/__init__.py
index b93eb4f..16ee312 100644
--- a/build/android/pylib/__init__.py
+++ b/build/android/pylib/__init__.py
@@ -5,27 +5,9 @@
import os
import sys
-
-_CATAPULT_PATH = os.path.abspath(os.path.join(
- os.path.dirname(__file__), '..', '..', '..', 'third_party', 'catapult'))
-
-_DEVIL_PATH = os.path.join(_CATAPULT_PATH, 'devil')
-
-_PYTRACE_PATH = os.path.join(_CATAPULT_PATH, 'common', 'py_trace_event')
-
-_PY_UTILS_PATH = os.path.join(_CATAPULT_PATH, 'common', 'py_utils')
-
-_TRACE2HTML_PATH = os.path.join(_CATAPULT_PATH, 'tracing')
-
+_DEVIL_PATH = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), '..', '..', '..', 'third_party', 'catapult',
+ 'devil'))
if _DEVIL_PATH not in sys.path:
sys.path.append(_DEVIL_PATH)
-
-if _PYTRACE_PATH not in sys.path:
- sys.path.append(_PYTRACE_PATH)
-
-if _PY_UTILS_PATH not in sys.path:
- sys.path.append(_PY_UTILS_PATH)
-
-if _TRACE2HTML_PATH not in sys.path:
- sys.path.append(_TRACE2HTML_PATH)
diff --git a/build/android/pylib/constants/__init__.py b/build/android/pylib/constants/__init__.py
index 916ee27..9b25dcd 100644
--- a/build/android/pylib/constants/__init__.py
+++ b/build/android/pylib/constants/__init__.py
@@ -37,28 +37,28 @@
'chromecast_shell': chrome.PackageInfo(
'com.google.android.apps.mediashell',
'com.google.android.apps.mediashell.MediaShellActivity',
- 'castshell-command-line',
+ '/data/local/tmp/castshell-command-line',
None),
'android_webview_shell': chrome.PackageInfo(
'org.chromium.android_webview.shell',
'org.chromium.android_webview.shell.AwShellActivity',
- 'android-webview-command-line',
+ '/data/local/tmp/android-webview-command-line',
None),
'gtest': chrome.PackageInfo(
'org.chromium.native_test',
'org.chromium.native_test.NativeUnitTestActivity',
- 'chrome-native-tests-command-line',
+ '/data/local/tmp/chrome-native-tests-command-line',
None),
'components_browsertests': chrome.PackageInfo(
'org.chromium.components_browsertests_apk',
('org.chromium.components_browsertests_apk' +
'.ComponentsBrowserTestsActivity'),
- 'chrome-native-tests-command-line',
+ '/data/local/tmp/chrome-native-tests-command-line',
None),
'content_browsertests': chrome.PackageInfo(
'org.chromium.content_browsertests_apk',
'org.chromium.content_browsertests_apk.ContentBrowserTestsActivity',
- 'chrome-native-tests-command-line',
+ '/data/local/tmp/chrome-native-tests-command-line',
None),
'chromedriver_webview_shell': chrome.PackageInfo(
'org.chromium.chromedriver_webview_shell',
@@ -96,7 +96,7 @@
SCREENSHOTS_DIR = os.path.join(DIR_SOURCE_ROOT, 'out_screenshots')
ANDROID_SDK_VERSION = version_codes.MARSHMALLOW
-ANDROID_SDK_BUILD_TOOLS_VERSION = '24.0.2'
+ANDROID_SDK_BUILD_TOOLS_VERSION = '23.0.1'
ANDROID_SDK_ROOT = os.path.join(DIR_SOURCE_ROOT,
'third_party', 'android_tools', 'sdk')
ANDROID_SDK_TOOLS = os.path.join(ANDROID_SDK_ROOT,
@@ -140,9 +140,9 @@
}
LOCAL_MACHINE_TESTS = ['junit', 'python']
-VALID_ENVIRONMENTS = ['local']
+VALID_ENVIRONMENTS = ['local', 'remote_device']
VALID_TEST_TYPES = ['gtest', 'instrumentation', 'junit', 'linker', 'monkey',
- 'perf', 'python']
+ 'perf', 'python', 'uirobot']
VALID_DEVICE_TYPES = ['Android', 'iOS']
diff --git a/build/build_config.h b/build/build_config.h
index fd5489f..c3d82d0 100644
--- a/build/build_config.h
+++ b/build/build_config.h
@@ -6,7 +6,6 @@
// Operating System:
// OS_WIN / OS_MACOSX / OS_LINUX / OS_POSIX (MACOSX or LINUX) /
// OS_NACL (NACL_SFI or NACL_NONSFI) / OS_NACL_SFI / OS_NACL_NONSFI
-// OS_CHROMEOS is set by the build system
// Compiler:
// COMPILER_MSVC / COMPILER_GCC
// Processor:
@@ -49,10 +48,9 @@
#endif
#elif defined(_WIN32)
#define OS_WIN 1
+#define TOOLKIT_VIEWS 1
#elif defined(__FreeBSD__)
#define OS_FREEBSD 1
-#elif defined(__NetBSD__)
-#define OS_NETBSD 1
#elif defined(__OpenBSD__)
#define OS_OPENBSD 1
#elif defined(__sun)
@@ -69,16 +67,15 @@
// For access to standard BSD features, use OS_BSD instead of a
// more specific macro.
-#if defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD)
+#if defined(OS_FREEBSD) || defined(OS_OPENBSD)
#define OS_BSD 1
#endif
// For access to standard POSIXish features, use OS_POSIX instead of a
// more specific macro.
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD) || \
- defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_SOLARIS) || \
- defined(OS_ANDROID) || defined(OS_OPENBSD) || defined(OS_SOLARIS) || \
- defined(OS_ANDROID) || defined(OS_NACL) || defined(OS_QNX)
+ defined(OS_OPENBSD) || defined(OS_SOLARIS) || defined(OS_ANDROID) || \
+ defined(OS_NACL) || defined(OS_QNX)
#define OS_POSIX 1
#endif
@@ -111,31 +108,6 @@
#define ARCH_CPU_X86 1
#define ARCH_CPU_32_BITS 1
#define ARCH_CPU_LITTLE_ENDIAN 1
-#elif defined(__s390x__)
-#define ARCH_CPU_S390_FAMILY 1
-#define ARCH_CPU_S390X 1
-#define ARCH_CPU_64_BITS 1
-#define ARCH_CPU_BIG_ENDIAN 1
-#elif defined(__s390__)
-#define ARCH_CPU_S390_FAMILY 1
-#define ARCH_CPU_S390 1
-#define ARCH_CPU_31_BITS 1
-#define ARCH_CPU_BIG_ENDIAN 1
-#elif defined(__PPC64__) && defined(__BIG_ENDIAN__)
-#define ARCH_CPU_PPC64_FAMILY 1
-#define ARCH_CPU_PPC64 1
-#define ARCH_CPU_64_BITS 1
-#define ARCH_CPU_BIG_ENDIAN 1
-#elif defined(__PPC64__) && defined(__LITTLE_ENDIAN__)
-#define ARCH_CPU_PPC64_FAMILY 1
-#define ARCH_CPU_PPC64 1
-#define ARCH_CPU_64_BITS 1
-#define ARCH_CPU_LITTLE_ENDIAN 1
-#elif defined(__PPC__)
-#define ARCH_CPU_PPC_FAMILY 1
-#define ARCH_CPU_PPC 1
-#define ARCH_CPU_32_BITS 1
-#define ARCH_CPU_BIG_ENDIAN 1
#elif defined(__ARMEL__)
#define ARCH_CPU_ARM_FAMILY 1
#define ARCH_CPU_ARMEL 1
diff --git a/build/gn_helpers.py b/build/gn_helpers.py
deleted file mode 100644
index 33cc578..0000000
--- a/build/gn_helpers.py
+++ /dev/null
@@ -1,351 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Helper functions useful when writing scripts that integrate with GN.
-
-The main functions are ToGNString and FromGNString which convert between
-serialized GN veriables and Python variables.
-
-To use in a random python file in the build:
-
- import os
- import sys
-
- sys.path.append(os.path.join(os.path.dirname(__file__),
- os.pardir, os.pardir, "build"))
- import gn_helpers
-
-Where the sequence of parameters to join is the relative path from your source
-file to the build directory."""
-
-class GNException(Exception):
- pass
-
-
-def ToGNString(value, allow_dicts = True):
- """Returns a stringified GN equivalent of the Python value.
-
- allow_dicts indicates if this function will allow converting dictionaries
- to GN scopes. This is only possible at the top level, you can't nest a
- GN scope in a list, so this should be set to False for recursive calls."""
- if isinstance(value, basestring):
- if value.find('\n') >= 0:
- raise GNException("Trying to print a string with a newline in it.")
- return '"' + \
- value.replace('\\', '\\\\').replace('"', '\\"').replace('$', '\\$') + \
- '"'
-
- if isinstance(value, unicode):
- return ToGNString(value.encode('utf-8'))
-
- if isinstance(value, bool):
- if value:
- return "true"
- return "false"
-
- if isinstance(value, list):
- return '[ %s ]' % ', '.join(ToGNString(v) for v in value)
-
- if isinstance(value, dict):
- if not allow_dicts:
- raise GNException("Attempting to recursively print a dictionary.")
- result = ""
- for key in sorted(value):
- if not isinstance(key, basestring):
- raise GNException("Dictionary key is not a string.")
- result += "%s = %s\n" % (key, ToGNString(value[key], False))
- return result
-
- if isinstance(value, int):
- return str(value)
-
- raise GNException("Unsupported type when printing to GN.")
-
-
-def FromGNString(input_string):
- """Converts the input string from a GN serialized value to Python values.
-
- For details on supported types see GNValueParser.Parse() below.
-
- If your GN script did:
- something = [ "file1", "file2" ]
- args = [ "--values=$something" ]
- The command line would look something like:
- --values="[ \"file1\", \"file2\" ]"
- Which when interpreted as a command line gives the value:
- [ "file1", "file2" ]
-
- You can parse this into a Python list using GN rules with:
- input_values = FromGNValues(options.values)
- Although the Python 'ast' module will parse many forms of such input, it
- will not handle GN escaping properly, nor GN booleans. You should use this
- function instead.
-
-
- A NOTE ON STRING HANDLING:
-
- If you just pass a string on the command line to your Python script, or use
- string interpolation on a string variable, the strings will not be quoted:
- str = "asdf"
- args = [ str, "--value=$str" ]
- Will yield the command line:
- asdf --value=asdf
- The unquoted asdf string will not be valid input to this function, which
- accepts only quoted strings like GN scripts. In such cases, you can just use
- the Python string literal directly.
-
- The main use cases for this is for other types, in particular lists. When
- using string interpolation on a list (as in the top example) the embedded
- strings will be quoted and escaped according to GN rules so the list can be
- re-parsed to get the same result."""
- parser = GNValueParser(input_string)
- return parser.Parse()
-
-
-def FromGNArgs(input_string):
- """Converts a string with a bunch of gn arg assignments into a Python dict.
-
- Given a whitespace-separated list of
-
- <ident> = (integer | string | boolean | <list of the former>)
-
- gn assignments, this returns a Python dict, i.e.:
-
- FromGNArgs("foo=true\nbar=1\n") -> { 'foo': True, 'bar': 1 }.
-
- Only simple types and lists supported; variables, structs, calls
- and other, more complicated things are not.
-
- This routine is meant to handle only the simple sorts of values that
- arise in parsing --args.
- """
- parser = GNValueParser(input_string)
- return parser.ParseArgs()
-
-
-def UnescapeGNString(value):
- """Given a string with GN escaping, returns the unescaped string.
-
- Be careful not to feed with input from a Python parsing function like
- 'ast' because it will do Python unescaping, which will be incorrect when
- fed into the GN unescaper."""
- result = ''
- i = 0
- while i < len(value):
- if value[i] == '\\':
- if i < len(value) - 1:
- next_char = value[i + 1]
- if next_char in ('$', '"', '\\'):
- # These are the escaped characters GN supports.
- result += next_char
- i += 1
- else:
- # Any other backslash is a literal.
- result += '\\'
- else:
- result += value[i]
- i += 1
- return result
-
-
-def _IsDigitOrMinus(char):
- return char in "-0123456789"
-
-
-class GNValueParser(object):
- """Duplicates GN parsing of values and converts to Python types.
-
- Normally you would use the wrapper function FromGNValue() below.
-
- If you expect input as a specific type, you can also call one of the Parse*
- functions directly. All functions throw GNException on invalid input. """
- def __init__(self, string):
- self.input = string
- self.cur = 0
-
- def IsDone(self):
- return self.cur == len(self.input)
-
- def ConsumeWhitespace(self):
- while not self.IsDone() and self.input[self.cur] in ' \t\n':
- self.cur += 1
-
- def Parse(self):
- """Converts a string representing a printed GN value to the Python type.
-
- See additional usage notes on FromGNString above.
-
- - GN booleans ('true', 'false') will be converted to Python booleans.
-
- - GN numbers ('123') will be converted to Python numbers.
-
- - GN strings (double-quoted as in '"asdf"') will be converted to Python
- strings with GN escaping rules. GN string interpolation (embedded
- variables preceeded by $) are not supported and will be returned as
- literals.
-
- - GN lists ('[1, "asdf", 3]') will be converted to Python lists.
-
- - GN scopes ('{ ... }') are not supported."""
- result = self._ParseAllowTrailing()
- self.ConsumeWhitespace()
- if not self.IsDone():
- raise GNException("Trailing input after parsing:\n " +
- self.input[self.cur:])
- return result
-
- def ParseArgs(self):
- """Converts a whitespace-separated list of ident=literals to a dict.
-
- See additional usage notes on FromGNArgs, above.
- """
- d = {}
-
- self.ConsumeWhitespace()
- while not self.IsDone():
- ident = self._ParseIdent()
- self.ConsumeWhitespace()
- if self.input[self.cur] != '=':
- raise GNException("Unexpected token: " + self.input[self.cur:])
- self.cur += 1
- self.ConsumeWhitespace()
- val = self._ParseAllowTrailing()
- self.ConsumeWhitespace()
- d[ident] = val
-
- return d
-
- def _ParseAllowTrailing(self):
- """Internal version of Parse that doesn't check for trailing stuff."""
- self.ConsumeWhitespace()
- if self.IsDone():
- raise GNException("Expected input to parse.")
-
- next_char = self.input[self.cur]
- if next_char == '[':
- return self.ParseList()
- elif _IsDigitOrMinus(next_char):
- return self.ParseNumber()
- elif next_char == '"':
- return self.ParseString()
- elif self._ConstantFollows('true'):
- return True
- elif self._ConstantFollows('false'):
- return False
- else:
- raise GNException("Unexpected token: " + self.input[self.cur:])
-
- def _ParseIdent(self):
- ident = ''
-
- next_char = self.input[self.cur]
- if not next_char.isalpha() and not next_char=='_':
- raise GNException("Expected an identifier: " + self.input[self.cur:])
-
- ident += next_char
- self.cur += 1
-
- next_char = self.input[self.cur]
- while next_char.isalpha() or next_char.isdigit() or next_char=='_':
- ident += next_char
- self.cur += 1
- next_char = self.input[self.cur]
-
- return ident
-
- def ParseNumber(self):
- self.ConsumeWhitespace()
- if self.IsDone():
- raise GNException('Expected number but got nothing.')
-
- begin = self.cur
-
- # The first character can include a negative sign.
- if not self.IsDone() and _IsDigitOrMinus(self.input[self.cur]):
- self.cur += 1
- while not self.IsDone() and self.input[self.cur].isdigit():
- self.cur += 1
-
- number_string = self.input[begin:self.cur]
- if not len(number_string) or number_string == '-':
- raise GNException("Not a valid number.")
- return int(number_string)
-
- def ParseString(self):
- self.ConsumeWhitespace()
- if self.IsDone():
- raise GNException('Expected string but got nothing.')
-
- if self.input[self.cur] != '"':
- raise GNException('Expected string beginning in a " but got:\n ' +
- self.input[self.cur:])
- self.cur += 1 # Skip over quote.
-
- begin = self.cur
- while not self.IsDone() and self.input[self.cur] != '"':
- if self.input[self.cur] == '\\':
- self.cur += 1 # Skip over the backslash.
- if self.IsDone():
- raise GNException("String ends in a backslash in:\n " +
- self.input)
- self.cur += 1
-
- if self.IsDone():
- raise GNException('Unterminated string:\n ' + self.input[begin:])
-
- end = self.cur
- self.cur += 1 # Consume trailing ".
-
- return UnescapeGNString(self.input[begin:end])
-
- def ParseList(self):
- self.ConsumeWhitespace()
- if self.IsDone():
- raise GNException('Expected list but got nothing.')
-
- # Skip over opening '['.
- if self.input[self.cur] != '[':
- raise GNException("Expected [ for list but got:\n " +
- self.input[self.cur:])
- self.cur += 1
- self.ConsumeWhitespace()
- if self.IsDone():
- raise GNException("Unterminated list:\n " + self.input)
-
- list_result = []
- previous_had_trailing_comma = True
- while not self.IsDone():
- if self.input[self.cur] == ']':
- self.cur += 1 # Skip over ']'.
- return list_result
-
- if not previous_had_trailing_comma:
- raise GNException("List items not separated by comma.")
-
- list_result += [ self._ParseAllowTrailing() ]
- self.ConsumeWhitespace()
- if self.IsDone():
- break
-
- # Consume comma if there is one.
- previous_had_trailing_comma = self.input[self.cur] == ','
- if previous_had_trailing_comma:
- # Consume comma.
- self.cur += 1
- self.ConsumeWhitespace()
-
- raise GNException("Unterminated list:\n " + self.input)
-
- def _ConstantFollows(self, constant):
- """Returns true if the given constant follows immediately at the current
- location in the input. If it does, the text is consumed and the function
- returns true. Otherwise, returns false and the current position is
- unchanged."""
- end = self.cur + len(constant)
- if end > len(self.input):
- return False # Not enough room.
- if self.input[self.cur:end] == constant:
- self.cur = end
- return True
- return False