diff options
Diffstat (limited to 'third_party/protobuf/3.2.0/objectivec/DevTools/pddm.py')
-rwxr-xr-x | third_party/protobuf/3.2.0/objectivec/DevTools/pddm.py | 686 |
1 files changed, 0 insertions, 686 deletions
diff --git a/third_party/protobuf/3.2.0/objectivec/DevTools/pddm.py b/third_party/protobuf/3.2.0/objectivec/DevTools/pddm.py deleted file mode 100755 index 9a11fec449..0000000000 --- a/third_party/protobuf/3.2.0/objectivec/DevTools/pddm.py +++ /dev/null @@ -1,686 +0,0 @@ -#! /usr/bin/python -# -# Protocol Buffers - Google's data interchange format -# Copyright 2015 Google Inc. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""PDDM - Poor Developers' Debug-able Macros - -A simple markup that can be added in comments of source so they can then be -expanded out into code. Most of this could be done with CPP macros, but then -developers can't really step through them in the debugger, this way they are -expanded to the same code, but you can debug them. - -Any file can be processed, but the syntax is designed around a C based compiler. -Processed lines start with "//%". There are three types of sections you can -create: Text (left alone), Macro Definitions, and Macro Expansions. There is -no order required between definitions and expansions, all definitions are read -before any expansions are processed (thus, if desired, definitions can be put -at the end of the file to keep them out of the way of the code). - -Macro Definitions are started with "//%PDDM-DEFINE Name(args)" and all lines -afterwards that start with "//%" are included in the definition. Multiple -macros can be defined in one block by just using a another "//%PDDM-DEFINE" -line to start the next macro. Optionally, a macro can be ended with -"//%PDDM-DEFINE-END", this can be useful when you want to make it clear that -trailing blank lines are included in the macro. You can also end a definition -with an expansion. - -Macro Expansions are started by single lines containing -"//%PDDM-EXPAND Name(args)" and then with "//%PDDM-EXPAND-END" or another -expansions. All lines in-between are replaced by the result of the expansion. -The first line of the expansion is always a blank like just for readability. - -Expansion itself is pretty simple, one macro can invoke another macro, but -you cannot nest the invoke of a macro in another macro (i.e. - can't do -"foo(bar(a))", but you can define foo(a) and bar(b) where bar invokes foo() -within its expansion. - -When macros are expanded, the arg references can also add "$O" suffix to the -name (i.e. - "NAME$O") to specify an option to be applied. The options are: - - $S - Replace each character in the value with a space. - $l - Lowercase the first letter of the value. - $L - Lowercase the whole value. - $u - Uppercase the first letter of the value. - $U - Uppercase the whole value. - -Within a macro you can use ## to cause things to get joined together after -expansion (i.e. - "a##b" within a macro will become "ab"). - -Example: - - int foo(MyEnum x) { - switch (x) { - //%PDDM-EXPAND case(Enum_Left, 1) - //%PDDM-EXPAND case(Enum_Center, 2) - //%PDDM-EXPAND case(Enum_Right, 3) - //%PDDM-EXPAND-END - } - - //%PDDM-DEFINE case(_A, _B) - //% case _A: - //% return _B; - - A macro ends at the start of the next one, or an optional %PDDM-DEFINE-END - can be used to avoid adding extra blank lines/returns (or make it clear when - it is desired). - - One macro can invoke another by simply using its name NAME(ARGS). You cannot - nest an invoke inside another (i.e. - NAME1(NAME2(ARGS)) isn't supported). - - Within a macro you can use ## to cause things to get joined together after - processing (i.e. - "a##b" within a macro will become "ab"). - - -""" - -import optparse -import os -import re -import sys - - -# Regex for macro definition. -_MACRO_RE = re.compile(r'(?P<name>\w+)\((?P<args>.*?)\)') -# Regex for macro's argument definition. -_MACRO_ARG_NAME_RE = re.compile(r'^\w+$') - -# Line inserted after each EXPAND. -_GENERATED_CODE_LINE = ( - '// This block of code is generated, do not edit it directly.' -) - - -def _MacroRefRe(macro_names): - # Takes in a list of macro names and makes a regex that will match invokes - # of those macros. - return re.compile(r'\b(?P<macro_ref>(?P<name>(%s))\((?P<args>.*?)\))' % - '|'.join(macro_names)) - -def _MacroArgRefRe(macro_arg_names): - # Takes in a list of macro arg names and makes a regex that will match - # uses of those args. - return re.compile(r'\b(?P<name>(%s))(\$(?P<option>.))?\b' % - '|'.join(macro_arg_names)) - - -class PDDMError(Exception): - """Error thrown by pddm.""" - pass - - -class MacroCollection(object): - """Hold a set of macros and can resolve/expand them.""" - - def __init__(self, a_file=None): - """Initializes the collection. - - Args: - a_file: The file like stream to parse. - - Raises: - PDDMError if there are any issues. - """ - self._macros = dict() - if a_file: - self.ParseInput(a_file) - - class MacroDefinition(object): - """Holds a macro definition.""" - - def __init__(self, name, arg_names): - self._name = name - self._args = tuple(arg_names) - self._body = '' - self._needNewLine = False - - def AppendLine(self, line): - if self._needNewLine: - self._body += '\n' - self._body += line - self._needNewLine = not line.endswith('\n') - - @property - def name(self): - return self._name - - @property - def args(self): - return self._args - - @property - def body(self): - return self._body - - def ParseInput(self, a_file): - """Consumes input extracting definitions. - - Args: - a_file: The file like stream to parse. - - Raises: - PDDMError if there are any issues. - """ - input_lines = a_file.read().splitlines() - self.ParseLines(input_lines) - - def ParseLines(self, input_lines): - """Parses list of lines. - - Args: - input_lines: A list of strings of input to parse (no newlines on the - strings). - - Raises: - PDDMError if there are any issues. - """ - current_macro = None - for line in input_lines: - if line.startswith('PDDM-'): - directive = line.split(' ', 1)[0] - if directive == 'PDDM-DEFINE': - name, args = self._ParseDefineLine(line) - if self._macros.get(name): - raise PDDMError('Attempt to redefine macro: "%s"' % line) - current_macro = self.MacroDefinition(name, args) - self._macros[name] = current_macro - continue - if directive == 'PDDM-DEFINE-END': - if not current_macro: - raise PDDMError('Got DEFINE-END directive without an active macro:' - ' "%s"' % line) - current_macro = None - continue - raise PDDMError('Hit a line with an unknown directive: "%s"' % line) - - if current_macro: - current_macro.AppendLine(line) - continue - - # Allow blank lines between macro definitions. - if line.strip() == '': - continue - - raise PDDMError('Hit a line that wasn\'t a directive and no open macro' - ' definition: "%s"' % line) - - def _ParseDefineLine(self, input_line): - assert input_line.startswith('PDDM-DEFINE') - line = input_line[12:].strip() - match = _MACRO_RE.match(line) - # Must match full line - if match is None or match.group(0) != line: - raise PDDMError('Failed to parse macro definition: "%s"' % input_line) - name = match.group('name') - args_str = match.group('args').strip() - args = [] - if args_str: - for part in args_str.split(','): - arg = part.strip() - if arg == '': - raise PDDMError('Empty arg name in macro definition: "%s"' - % input_line) - if not _MACRO_ARG_NAME_RE.match(arg): - raise PDDMError('Invalid arg name "%s" in macro definition: "%s"' - % (arg, input_line)) - if arg in args: - raise PDDMError('Arg name "%s" used more than once in macro' - ' definition: "%s"' % (arg, input_line)) - args.append(arg) - return (name, tuple(args)) - - def Expand(self, macro_ref_str): - """Expands the macro reference. - - Args: - macro_ref_str: String of a macro reference (i.e. foo(a, b)). - - Returns: - The text from the expansion. - - Raises: - PDDMError if there are any issues. - """ - match = _MACRO_RE.match(macro_ref_str) - if match is None or match.group(0) != macro_ref_str: - raise PDDMError('Failed to parse macro reference: "%s"' % macro_ref_str) - if match.group('name') not in self._macros: - raise PDDMError('No macro named "%s".' % match.group('name')) - return self._Expand(match, [], macro_ref_str) - - def _FormatStack(self, macro_ref_stack): - result = '' - for _, macro_ref in reversed(macro_ref_stack): - result += '\n...while expanding "%s".' % macro_ref - return result - - def _Expand(self, macro_ref_match, macro_stack, macro_ref_str=None): - if macro_ref_str is None: - macro_ref_str = macro_ref_match.group('macro_ref') - name = macro_ref_match.group('name') - for prev_name, prev_macro_ref in macro_stack: - if name == prev_name: - raise PDDMError('Found macro recusion, invoking "%s":%s' % - (macro_ref_str, self._FormatStack(macro_stack))) - macro = self._macros[name] - args_str = macro_ref_match.group('args').strip() - args = [] - if args_str or len(macro.args): - args = [x.strip() for x in args_str.split(',')] - if len(args) != len(macro.args): - raise PDDMError('Expected %d args, got: "%s".%s' % - (len(macro.args), macro_ref_str, - self._FormatStack(macro_stack))) - # Replace args usages. - result = self._ReplaceArgValues(macro, args, macro_ref_str, macro_stack) - # Expand any macro invokes. - new_macro_stack = macro_stack + [(name, macro_ref_str)] - while True: - eval_result = self._EvalMacrosRefs(result, new_macro_stack) - # Consume all ## directives to glue things together. - eval_result = eval_result.replace('##', '') - if eval_result == result: - break - result = eval_result - return result - - def _ReplaceArgValues(self, - macro, arg_values, macro_ref_to_report, macro_stack): - if len(arg_values) == 0: - # Nothing to do - return macro.body - assert len(arg_values) == len(macro.args) - args = dict(zip(macro.args, arg_values)) - def _lookupArg(match): - val = args[match.group('name')] - opt = match.group('option') - if opt: - if opt == 'S': # Spaces for the length - return ' ' * len(val) - elif opt == 'l': # Lowercase first character - if val: - return val[0].lower() + val[1:] - else: - return val - elif opt == 'L': # All Lowercase - return val.lower() - elif opt == 'u': # Uppercase first character - if val: - return val[0].upper() + val[1:] - else: - return val - elif opt == 'U': # All Uppercase - return val.upper() - else: - raise PDDMError('Unknown arg option "%s$%s" while expanding "%s".%s' - % (match.group('name'), match.group('option'), - macro_ref_to_report, - self._FormatStack(macro_stack))) - return val - # Let the regex do the work! - macro_arg_ref_re = _MacroArgRefRe(macro.args) - return macro_arg_ref_re.sub(_lookupArg, macro.body) - - def _EvalMacrosRefs(self, text, macro_stack): - macro_ref_re = _MacroRefRe(self._macros.keys()) - def _resolveMacro(match): - return self._Expand(match, macro_stack) - return macro_ref_re.sub(_resolveMacro, text) - - -class SourceFile(object): - """Represents a source file with PDDM directives in it.""" - - def __init__(self, a_file, import_resolver=None): - """Initializes the file reading in the file. - - Args: - a_file: The file to read in. - import_resolver: a function that given a path will return a stream for - the contents. - - Raises: - PDDMError if there are any issues. - """ - self._sections = [] - self._original_content = a_file.read() - self._import_resolver = import_resolver - self._processed_content = None - - class SectionBase(object): - - def __init__(self, first_line_num): - self._lines = [] - self._first_line_num = first_line_num - - def TryAppend(self, line, line_num): - """Try appending a line. - - Args: - line: The line to append. - line_num: The number of the line. - - Returns: - A tuple of (SUCCESS, CAN_ADD_MORE). If SUCCESS if False, the line - wasn't append. If SUCCESS is True, then CAN_ADD_MORE is True/False to - indicate if more lines can be added after this one. - """ - assert False, "sublcass should have overridden" - return (False, False) - - def HitEOF(self): - """Called when the EOF was reached for for a given section.""" - pass - - def BindMacroCollection(self, macro_collection): - """Binds the chunk to a macro collection. - - Args: - macro_collection: The collection to bind too. - """ - pass - - def Append(self, line): - self._lines.append(line) - - @property - def lines(self): - return self._lines - - @property - def num_lines_captured(self): - return len(self._lines) - - @property - def first_line_num(self): - return self._first_line_num - - @property - def first_line(self): - if not self._lines: - return '' - return self._lines[0] - - @property - def text(self): - return '\n'.join(self.lines) + '\n' - - class TextSection(SectionBase): - """Text section that is echoed out as is.""" - - def TryAppend(self, line, line_num): - if line.startswith('//%PDDM'): - return (False, False) - self.Append(line) - return (True, True) - - class ExpansionSection(SectionBase): - """Section that is the result of an macro expansion.""" - - def __init__(self, first_line_num): - SourceFile.SectionBase.__init__(self, first_line_num) - self._macro_collection = None - - def TryAppend(self, line, line_num): - if line.startswith('//%PDDM'): - directive = line.split(' ', 1)[0] - if directive == '//%PDDM-EXPAND': - self.Append(line) - return (True, True) - if directive == '//%PDDM-EXPAND-END': - assert self.num_lines_captured > 0 - return (True, False) - raise PDDMError('Ran into directive ("%s", line %d) while in "%s".' % - (directive, line_num, self.first_line)) - # Eat other lines. - return (True, True) - - def HitEOF(self): - raise PDDMError('Hit the end of the file while in "%s".' % - self.first_line) - - def BindMacroCollection(self, macro_collection): - self._macro_collection = macro_collection - - @property - def lines(self): - captured_lines = SourceFile.SectionBase.lines.fget(self) - directive_len = len('//%PDDM-EXPAND') - result = [] - for line in captured_lines: - result.append(line) - if self._macro_collection: - # Always add a blank line, seems to read better. (If need be, add an - # option to the EXPAND to indicate if this should be done.) - result.extend([_GENERATED_CODE_LINE, '']) - macro = line[directive_len:].strip() - try: - expand_result = self._macro_collection.Expand(macro) - # Since expansions are line oriented, strip trailing whitespace - # from the lines. - lines = [x.rstrip() for x in expand_result.split('\n')] - result.append('\n'.join(lines)) - except PDDMError as e: - raise PDDMError('%s\n...while expanding "%s" from the section' - ' that started:\n Line %d: %s' % - (e.message, macro, - self.first_line_num, self.first_line)) - - # Add the ending marker. - if len(captured_lines) == 1: - result.append('//%%PDDM-EXPAND-END %s' % - captured_lines[0][directive_len:].strip()) - else: - result.append('//%%PDDM-EXPAND-END (%s expansions)' % len(captured_lines)) - - return result - - class DefinitionSection(SectionBase): - """Section containing macro definitions""" - - def TryAppend(self, line, line_num): - if not line.startswith('//%'): - return (False, False) - if line.startswith('//%PDDM'): - directive = line.split(' ', 1)[0] - if directive == "//%PDDM-EXPAND": - return False, False - if directive not in ('//%PDDM-DEFINE', '//%PDDM-DEFINE-END'): - raise PDDMError('Ran into directive ("%s", line %d) while in "%s".' % - (directive, line_num, self.first_line)) - self.Append(line) - return (True, True) - - def BindMacroCollection(self, macro_collection): - if macro_collection: - try: - # Parse the lines after stripping the prefix. - macro_collection.ParseLines([x[3:] for x in self.lines]) - except PDDMError as e: - raise PDDMError('%s\n...while parsing section that started:\n' - ' Line %d: %s' % - (e.message, self.first_line_num, self.first_line)) - - class ImportDefinesSection(SectionBase): - """Section containing an import of PDDM-DEFINES from an external file.""" - - def __init__(self, first_line_num, import_resolver): - SourceFile.SectionBase.__init__(self, first_line_num) - self._import_resolver = import_resolver - - def TryAppend(self, line, line_num): - if not line.startswith('//%PDDM-IMPORT-DEFINES '): - return (False, False) - assert self.num_lines_captured == 0 - self.Append(line) - return (True, False) - - def BindMacroCollection(self, macro_colletion): - if not macro_colletion: - return - if self._import_resolver is None: - raise PDDMError('Got an IMPORT-DEFINES without a resolver (line %d):' - ' "%s".' % (self.first_line_num, self.first_line)) - import_name = self.first_line.split(' ', 1)[1].strip() - imported_file = self._import_resolver(import_name) - if imported_file is None: - raise PDDMError('Resolver failed to find "%s" (line %d):' - ' "%s".' % - (import_name, self.first_line_num, self.first_line)) - try: - imported_src_file = SourceFile(imported_file, self._import_resolver) - imported_src_file._ParseFile() - for section in imported_src_file._sections: - section.BindMacroCollection(macro_colletion) - except PDDMError as e: - raise PDDMError('%s\n...while importing defines:\n' - ' Line %d: %s' % - (e.message, self.first_line_num, self.first_line)) - - def _ParseFile(self): - self._sections = [] - lines = self._original_content.splitlines() - cur_section = None - for line_num, line in enumerate(lines, 1): - if not cur_section: - cur_section = self._MakeSection(line, line_num) - was_added, accept_more = cur_section.TryAppend(line, line_num) - if not was_added: - cur_section = self._MakeSection(line, line_num) - was_added, accept_more = cur_section.TryAppend(line, line_num) - assert was_added - if not accept_more: - cur_section = None - - if cur_section: - cur_section.HitEOF() - - def _MakeSection(self, line, line_num): - if not line.startswith('//%PDDM'): - section = self.TextSection(line_num) - else: - directive = line.split(' ', 1)[0] - if directive == '//%PDDM-EXPAND': - section = self.ExpansionSection(line_num) - elif directive == '//%PDDM-DEFINE': - section = self.DefinitionSection(line_num) - elif directive == '//%PDDM-IMPORT-DEFINES': - section = self.ImportDefinesSection(line_num, self._import_resolver) - else: - raise PDDMError('Unexpected line %d: "%s".' % (line_num, line)) - self._sections.append(section) - return section - - def ProcessContent(self, strip_expansion=False): - """Processes the file contents.""" - self._ParseFile() - if strip_expansion: - # Without a collection the expansions become blank, removing them. - collection = None - else: - collection = MacroCollection() - for section in self._sections: - section.BindMacroCollection(collection) - result = '' - for section in self._sections: - result += section.text - self._processed_content = result - - @property - def original_content(self): - return self._original_content - - @property - def processed_content(self): - return self._processed_content - - -def main(args): - usage = '%prog [OPTIONS] PATH ...' - description = ( - 'Processes PDDM directives in the given paths and write them back out.' - ) - parser = optparse.OptionParser(usage=usage, description=description) - parser.add_option('--dry-run', - default=False, action='store_true', - help='Don\'t write back to the file(s), just report if the' - ' contents needs an update and exit with a value of 1.') - parser.add_option('--verbose', - default=False, action='store_true', - help='Reports is a file is already current.') - parser.add_option('--collapse', - default=False, action='store_true', - help='Removes all the generated code.') - opts, extra_args = parser.parse_args(args) - - if not extra_args: - parser.error('Need atleast one file to process') - - result = 0 - for a_path in extra_args: - if not os.path.exists(a_path): - sys.stderr.write('ERROR: File not found: %s\n' % a_path) - return 100 - - def _ImportResolver(name): - # resolve based on the file being read. - a_dir = os.path.dirname(a_path) - import_path = os.path.join(a_dir, name) - if not os.path.exists(import_path): - return None - return open(import_path, 'r') - - with open(a_path, 'r') as f: - src_file = SourceFile(f, _ImportResolver) - - try: - src_file.ProcessContent(strip_expansion=opts.collapse) - except PDDMError as e: - sys.stderr.write('ERROR: %s\n...While processing "%s"\n' % - (e.message, a_path)) - return 101 - - if src_file.processed_content != src_file.original_content: - if not opts.dry_run: - print 'Updating for "%s".' % a_path - with open(a_path, 'w') as f: - f.write(src_file.processed_content) - else: - # Special result to indicate things need updating. - print 'Update needed for "%s".' % a_path - result = 1 - elif opts.verbose: - print 'No update for "%s".' % a_path - - return result - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) |