From 3e30b94615d64cf02713b23060f985f953751bb8 Mon Sep 17 00:00:00 2001 From: Carsten Kuebler Date: Thu, 19 Apr 2018 09:49:44 +0200 Subject: [PATCH 1/3] Bugfix and new features Include changes from University of California. Separate statement and comments to treat both parts different (remove bugs regarding string modifications). Remove "option" statements. Add support for "extend" statements. Change "repeat" from Template to standard member. --> Better collaboration diagrams. Fix problems with references of nested messages (replace "." with "::"). --- proto2cpp.py | 95 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 21 deletions(-) diff --git a/proto2cpp.py b/proto2cpp.py index 96506aa..c3a5ffd 100644 --- a/proto2cpp.py +++ b/proto2cpp.py @@ -1,9 +1,10 @@ +#!/usr/bin/env python ## # Doxygen filter for Google Protocol Buffers .proto files. # This script converts .proto files into C++ style ones # and prints the output to standard output. # -# version 0.6-beta +# version 0.7-beta OSI # # How to enable this filter in Doxygen: # 1. Generate Doxygen configuration file with command 'doxygen -g ' @@ -12,7 +13,7 @@ # JAVADOC_AUTOBRIEF = YES # 3. In the Doxygen configuration file, find FILE_PATTERNS and add *.proto # FILE_PATTERNS = *.proto -# 4. In the Doxygen configuration file, find EXTENSION_MAPPING and add proto=C +# 4. In the Doxygen configuration file, find EXTENSION_MAPPING and add proto=C++ # EXTENSION_MAPPING = proto=C # 5. In the Doxygen configuration file, find INPUT_FILTER and add this script # INPUT_FILTER = "python proto2cpp.py" @@ -20,7 +21,9 @@ # doxygen doxyfile # # -# Copyright (C) 2012-2015 Timo Marjoniemi +# Version 0.7 2018 Bugfix and extensions have been made by Open Simulation Interface (OSI) Carsten Kuebler https://github.com/OpenSimulationInterface +# Copyright (C) 2016 Regents of the University of California https://github.com/vgteam/vg +# Copyright (C) 2012-2015 Timo Marjoniemi https://sourceforge.net/p/proto2cpp/wiki/Home/ # All rights reserved. # # This library is free software; you can redistribute it and/or @@ -72,7 +75,7 @@ def __init__(self): self.logFile = "proto2cpp.log" ## Error log file name. self.errorLogFile = "proto2cpp.error.log" - ## Logging level. + ## Logging level. self.logLevel = self.logNone ## Handles a file. @@ -88,7 +91,7 @@ def handleFile(self, fileName): self.log('\nXXXXXXXXXX\nXX ' + filename + '\nXXXXXXXXXX\n\n') # Open the file. Use try to detect whether or not we have an actual file. try: - with open(filename, 'r') as inputFile: + with open(filename, 'r', encoding='utf8') as inputFile: self.parseFile(inputFile) pass except IOError as e: @@ -97,7 +100,7 @@ def handleFile(self, fileName): elif not fnmatch.fnmatch(filename, os.path.basename(inspect.getfile(inspect.currentframe()))): self.log('\nXXXXXXXXXX\nXX ' + filename + '\nXXXXXXXXXX\n\n') try: - with open(filename, 'r') as theFile: + with open(filename, 'r', encoding='utf8') as theFile: output = '' for theLine in theFile: output += theLine @@ -120,6 +123,7 @@ def handleFile(self, fileName): def parseFile(self, inputFile): # Go through the input file line by line. isEnum = False + inPackage = False # This variable is here as a workaround for not getting extra line breaks (each line # ends with a line separator and print() method will add another one). # We will be adding lines into this var and then print the var out at the end. @@ -129,24 +133,54 @@ def parseFile(self, inputFile): # block to make Doxygen detect it. matchComment = re.search("//", line) # Search for semicolon and if one is found before comment, add a third slash character - # ("/") and a smaller than ("<") chracter to the comment to make Doxygen detect it. + # ("/") and a smaller than ("<") character to the comment to make Doxygen detect it. matchSemicolon = re.search(";", line) if matchSemicolon is not None and (matchComment is not None and matchSemicolon.start() < matchComment.start()): - line = line[:matchComment.start()] + "///<" + line[matchComment.end():] + comment = "///<" + line[matchComment.end():] + # Replace '.' in nested message references with '::' + # don't work for multi-nested references and generates problems with URLs and acronyms + #comment = re.sub(r'\s(\w+)\.(\w+)\s', r' \1::\2 ', comment) + line = line[:matchComment.start()] elif matchComment is not None: - line = line[:matchComment.start()] + "///" + line[matchComment.end():] + comment = "///" + line[matchComment.end():] + # replace '.' in nested message references with '::' + # don't work for multi-nested references and generates problems with URLs and acronyms + #comment = re.sub(r'\s(\w+)\.(\w+)\s', r' \1::\2 ', comment) + line = line[:matchComment.start()] + else: + comment = "" + + # line = line.replace(".", "::") but not in quoted strings (Necessary for import statement) + line = re.sub(r'\.(?=(?:[^"]*"[^"]*")*[^"]*$)',r'::',line) - # Search for "enum" and if one is found before comment, - # start changing all semicolons (";") to commas (","). - matchEnum = re.search("enum", line) - if matchEnum is not None and (matchComment is None or matchEnum.start() < matchComment.start()): + # Search for " option ...;", remove it + line = re.sub(r'\boption\b[^;]+;', r'', line) + + # Search for " package ", make a namespace + matchPackage = re.search(r"\bpackage\b", line) + if matchPackage is not None: + isPackage = True + # Convert to C++-style separator and block instead of statement + line = "namespace" + line[:matchPackage.start()] + line[matchPackage.end():].replace(";", " {") + + # Search for " repeated " fields and make them ... + #matchRepeated = re.search(r"\brepeated\b", line) + #if matchRepeated is not None: + # # Convert + # line = re.sub(r'\brepeated\s+(\S+)', r' repeated \1', line) + + # Search for "enum", start changing all semicolons (";") to commas (","). + matchEnum = re.search(r"\benum\b", line) + if matchEnum is not None: isEnum = True + # Search again for semicolon if we have detected an enum, and replace semicolon with comma. if isEnum is True and re.search(";", line) is not None: matchSemicolon = re.search(";", line) line = line[:matchSemicolon.start()] + "," + line[matchSemicolon.end():] + # Search for a closing brace. - matchClosingBrace = re.search("}", line[:matchComment.start()] if matchComment else line) + matchClosingBrace = re.search("}", line) if isEnum is True and matchClosingBrace is not None: line = line[:matchClosingBrace.start()] + "};" + line[matchClosingBrace.end():] isEnum = False @@ -154,13 +188,32 @@ def parseFile(self, inputFile): # Message (to be struct) ends => add semicolon so that it'll # be a proper C(++) struct and Doxygen will handle it correctly. line = line[:matchClosingBrace.start()] + "};" + line[matchClosingBrace.end():] - # Search for 'message' and replace it with 'struct' unless 'message' is behind a comment. - matchMsg = re.search("message", line) - if matchMsg is not None and (matchComment is None or matchMsg.start() < matchComment.start()): - output = "struct" + line[:matchMsg.start()] + line[matchMsg.end():] - theOutput += output - else: - theOutput += line + + # Replacements change start of comment... + matchMsg = re.search(r"\bmessage\b", line) + if matchMsg is not None: + line = line[:matchMsg.start()] + "struct" + line[matchMsg.end():] + + # Replacements change start of comment... + matchExt = re.search(r"\bextend\b", line) + if matchExt is not None: + a_extend = line[matchExt.end():] + matchName = re.search(r"\b\w[\S:]+\b", a_extend) + if matchName is not None: + name = a_extend[matchName.start():matchName.end()] + name = re.sub(r'\w+::',r'',name) + a_extend = a_extend[:matchName.start()] + name + ": public " + a_extend[matchName.start():] + else: + a_extend = "_Dummy: public " + a_extend; + line = line[:matchExt.start()] + "struct " + a_extend + + theOutput += line + comment + + if isPackage: + # Close the package namespace + theOutput += "}" + isPackage = False + # Now that we've got all lines in the string let's split the lines and print out # one by one. # This is a workaround to get rid of extra empty line at the end which print() method adds. From 7c75d7dc7beb49f9ad679e6af08338fd3b9de64b Mon Sep 17 00:00:00 2001 From: Carsten Kuebler Date: Thu, 19 Apr 2018 09:58:45 +0200 Subject: [PATCH 2/3] Update documentation --- README | 14 +++++++++++++- doxyfile | 4 ++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README b/README index 647dc8d..7929291 100644 --- a/README +++ b/README @@ -47,4 +47,16 @@ Version history: not moving member comments before the member but keeping it after the member instead * these changes lead into need of enabling JAVADOC_AUTOBRIEF - - added steps for enabling the filter in Doxygen in this file \ No newline at end of file + - added steps for enabling the filter in Doxygen in this file +-------------------- + 0.7-beta (2018-04-19) OSI + - Include changes from University of California. + - Support for all OSI *.proto files. + - Separate statement and comments totreat both parts different (remove bugs + regarding string modifications). + - Remove "option" statements. + - Add support for "extend" statements. + - Change "repeat" from Template to standard member. --> Better collaboration + diagrams. + - Fix problems with references of nested messages (replace "." with "::"). + - Change mapping from C to C++. diff --git a/doxyfile b/doxyfile index ad14802..5a89ee2 100644 --- a/doxyfile +++ b/doxyfile @@ -32,7 +32,7 @@ PROJECT_NAME = "Protocol Buffers demo project" # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 0.6-beta +PROJECT_NUMBER = 0.7-beta # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer @@ -238,7 +238,7 @@ OPTIMIZE_OUTPUT_VHDL = NO # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. -EXTENSION_MAPPING = proto=C +EXTENSION_MAPPING = proto=C++ # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should From 4d5b26ca912f855f2f8a97d7fcf1401ed9d1ae9d Mon Sep 17 00:00:00 2001 From: Carlo van Driesten Date: Fri, 20 Apr 2018 14:15:48 +0200 Subject: [PATCH 3/3] Fixed Typo --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 7929291..0994dc3 100644 --- a/README +++ b/README @@ -52,7 +52,7 @@ Version history: 0.7-beta (2018-04-19) OSI - Include changes from University of California. - Support for all OSI *.proto files. - - Separate statement and comments totreat both parts different (remove bugs + - Separate statement and comments to treat both parts differently (remove bugs regarding string modifications). - Remove "option" statements. - Add support for "extend" statements.