Blame doc/translator.py

Packit Service 50c9f2
"""Script to generate reports on translator classes from Doxygen sources.
Packit Service 50c9f2

Packit Service 50c9f2
  The main purpose of the script is to extract the information from sources
Packit Service 50c9f2
  related to internationalization (the translator classes). It uses the
Packit Service 50c9f2
  information to generate documentation (language.doc,
Packit Service 50c9f2
  translator_report.txt) from templates (language.tpl, maintainers.txt).
Packit Service 50c9f2

Packit Service 50c9f2
  Simply run the script without parameters to get the reports and
Packit Service 50c9f2
  documentation for all supported languages. If you want to generate the
Packit Service 50c9f2
  translator report only for some languages, pass their codes as arguments
Packit Service 50c9f2
  to the script. In that case, the language.doc will not be generated.
Packit Service 50c9f2
  Example:
Packit Service 50c9f2

Packit Service 50c9f2
    python translator.py en nl cz
Packit Service 50c9f2

Packit Service 50c9f2
  Originally, the script was written in Perl and was known as translator.pl.
Packit Service 50c9f2
  The last Perl version was dated 2002/05/21 (plus some later corrections)
Packit Service 50c9f2

Packit Service 50c9f2
                                         Petr Prikryl (prikryl at atlas dot cz)
Packit Service 50c9f2

Packit Service 50c9f2
  History:
Packit Service 50c9f2
  --------
Packit Service 50c9f2
  2002/05/21 - This was the last Perl version.
Packit Service 50c9f2
  2003/05/16 - List of language marks can be passed as arguments.
Packit Service 50c9f2
  2004/01/24 - Total reimplementation started: classes TrManager, and Transl.
Packit Service 50c9f2
  2004/02/05 - First version that produces translator report. No language.doc yet.
Packit Service 50c9f2
  2004/02/10 - First fully functional version that generates both the translator
Packit Service 50c9f2
               report and the documentation. It is a bit slower than the
Packit Service 50c9f2
               Perl version, but is much less tricky and much more flexible.
Packit Service 50c9f2
               It also solves some problems that were not solved by the Perl
Packit Service 50c9f2
               version. The translator report content should be more useful
Packit Service 50c9f2
               for developers.
Packit Service 50c9f2
  2004/02/11 - Some tuning-up to provide more useful information.
Packit Service 50c9f2
  2004/04/16 - Added new tokens to the tokenizer (to remove some warnings).
Packit Service 50c9f2
  2004/05/25 - Added from __future__ import generators not to force Python 2.3.
Packit Service 50c9f2
  2004/06/03 - Removed dependency on textwrap module.
Packit Service 50c9f2
  2004/07/07 - Fixed the bug in the fill() function.
Packit Service 50c9f2
  2004/07/21 - Better e-mail mangling for HTML part of language.doc.
Packit Service 50c9f2
             - Plural not used for reporting a single missing method.
Packit Service 50c9f2
             - Removal of not used translator adapters is suggested only
Packit Service 50c9f2
               when the report is not restricted to selected languages
Packit Service 50c9f2
               explicitly via script arguments.
Packit Service 50c9f2
  2004/07/26 - Better reporting of not-needed adapters.
Packit Service 50c9f2
  2004/10/04 - Reporting of not called translator methods added.
Packit Service 50c9f2
  2004/10/05 - Modified to check only doxygen/src sources for the previous report.
Packit Service 50c9f2
  2005/02/28 - Slight modification to generate "mailto.txt" auxiliary file.
Packit Service 50c9f2
  2005/08/15 - Doxygen's root directory determined primarily from DOXYGEN
Packit Service 50c9f2
               environment variable. When not found, then relatively to the script.
Packit Service 50c9f2
  2007/03/20 - The "translate me!" searched in comments and reported if found.
Packit Service 50c9f2
  2008/06/09 - Warning when the MAX_DOT_GRAPH_HEIGHT is still part of trLegendDocs().
Packit Service 50c9f2
  2009/05/09 - Changed HTML output to fit it with XHTML DTD
Packit Service 50c9f2
  2009/09/02 - Added percentage info to the report (implemented / to be implemented).
Packit Service 50c9f2
  2010/02/09 - Added checking/suggestion 'Reimplementation using UTF-8 suggested.
Packit Service 50c9f2
  2010/03/03 - Added [unreachable] prefix used in maintainers.txt.
Packit Service 50c9f2
  2010/05/28 - BOM skipped; minor code cleaning.
Packit Service 50c9f2
  2010/05/31 - e-mail mangled already in maintainers.txt
Packit Service 50c9f2
  2010/08/20 - maintainers.txt to UTF-8, related processing of unicode strings
Packit Service 50c9f2
             - [any mark] introduced instead of [unreachable] only
Packit Service 50c9f2
             - marks highlighted in HTML
Packit Service 50c9f2
  2010/08/30 - Highlighting in what will be the table in langhowto.html modified.
Packit Service 50c9f2
  2010/09/27 - The underscore in \latexonly part of the generated language.doc
Packit Service 50c9f2
               was prefixed by backslash (was LaTeX related error).
Packit Service 50c9f2
  2013/02/19 - Better diagnostics when translator_xx.h is too crippled.
Packit Service 50c9f2
  2013/06/25 - TranslatorDecoder checks removed after removing the class.
Packit Service 50c9f2
  2013/09/04 - Coloured status in langhowto. *ALMOST up-to-date* category
Packit Service 50c9f2
               of translators introduced.
Packit Service 50c9f2
  2014/06/16 - unified for Python 2.6+ and 3.0+
Packit Service 50c9f2
  """
Packit Service 50c9f2

Packit Service 50c9f2
from __future__ import print_function
Packit Service 50c9f2

Packit Service 50c9f2
import os
Packit Service 50c9f2
import platform
Packit Service 50c9f2
import re
Packit Service 50c9f2
import sys
Packit Service 50c9f2
import textwrap
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
def xopen(fname, mode='r', encoding='utf-8-sig'):
Packit Service 50c9f2
    '''Unified file opening for Python 2 an Python 3.
Packit Service 50c9f2

Packit Service 50c9f2
    Python 2 does not have the encoding argument. Python 3 has one, and
Packit Service 50c9f2
    the default 'utf-8-sig' is used (skips the BOM automatically).
Packit Service 50c9f2
    '''
Packit Service 50c9f2

Packit Service 50c9f2
    if sys.version_info[0] == 2:
Packit Service 50c9f2
        return open(fname, mode=mode) # Python 2 without encoding
Packit Service 50c9f2
    else:
Packit Service 50c9f2
        return open(fname, mode=mode, encoding=encoding) # Python 3 with encoding
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
def fill(s):
Packit Service 50c9f2
    """Returns string formatted to the wrapped paragraph multiline string.
Packit Service 50c9f2

Packit Service 50c9f2
    Replaces whitespaces by one space and then uses he textwrap.fill()."""
Packit Service 50c9f2

Packit Service 50c9f2
    # Replace all whitespace by spaces, remove whitespaces that are not
Packit Service 50c9f2
    # necessary, strip the left and right whitespaces, and break the string
Packit Service 50c9f2
    # to list of words.
Packit Service 50c9f2
    rexWS = re.compile(r'\s+')
Packit Service 50c9f2
    lst = rexWS.sub(' ', s).strip().split()
Packit Service 50c9f2

Packit Service 50c9f2
    # If the list is not empty, put the words together and form the lines
Packit Service 50c9f2
    # of maximum 70 characters. Build the list of lines.
Packit Service 50c9f2
    lines = []
Packit Service 50c9f2
    if lst:
Packit Service 50c9f2
        line = lst.pop(0)   # no separation space in front of the first word
Packit Service 50c9f2
        for word in lst:
Packit Service 50c9f2
            if len(line) + len(word) < 70:
Packit Service 50c9f2
                line += ' ' + word
Packit Service 50c9f2
            else:
Packit Service 50c9f2
                lines.append(line)  # another full line formed
Packit Service 50c9f2
                line = word         # next line started
Packit Service 50c9f2
        lines.append(line)          # the last line
Packit Service 50c9f2
    return '\n'.join(lines)
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
class Transl:
Packit Service 50c9f2
    """One instance is build for each translator.
Packit Service 50c9f2

Packit Service 50c9f2
    The abbreviation of the source file--part after 'translator_'--is used as
Packit Service 50c9f2
    the identification of the object. The empty string is used for the
Packit Service 50c9f2
    abstract Translator class from translator.h. The other information is
Packit Service 50c9f2
    extracted from inside the source file."""
Packit Service 50c9f2

Packit Service 50c9f2
    def __init__(self, fname, manager):
Packit Service 50c9f2
        """Bind to the manager and initialize."""
Packit Service 50c9f2

Packit Service 50c9f2
        # Store the filename and the reference to the manager object.
Packit Service 50c9f2
        self.fname = fname
Packit Service 50c9f2
        self.manager = manager
Packit Service 50c9f2

Packit Service 50c9f2
        # The instance is responsible for loading the source file, so it checks
Packit Service 50c9f2
        # for its existence and quits if something goes wrong.
Packit Service 50c9f2
        if not os.path.isfile(fname):
Packit Service 50c9f2
            sys.stderr.write("\a\nFile '%s' not found!\n" % fname)
Packit Service 50c9f2
            sys.exit(1)
Packit Service 50c9f2

Packit Service 50c9f2
        # Initialize the other collected information.
Packit Service 50c9f2
        self.classId = None
Packit Service 50c9f2
        self.baseClassId = None
Packit Service 50c9f2
        self.readableStatus = None   # 'up-to-date', '1.2.3', '1.3', etc.
Packit Service 50c9f2
        self.status = None           # '', '1.2.03', '1.3.00', etc.
Packit Service 50c9f2
        self.lang = None             # like 'Brasilian'
Packit Service 50c9f2
        self.langReadable = None     # like 'Brasilian Portuguese'
Packit Service 50c9f2
        self.note = None             # like 'should be cleaned up'
Packit Service 50c9f2
        self.prototypeDic = {}       # uniPrototype -> prototype
Packit Service 50c9f2
        self.translateMeText = 'translate me!'
Packit Service 50c9f2
        self.translateMeFlag = False # comments with "translate me!" found
Packit Service 50c9f2
        self.txtMAX_DOT_GRAPH_HEIGHT_flag = False # found in string in trLegendDocs()
Packit Service 50c9f2
        self.obsoleteMethods = None  # list of prototypes to be removed
Packit Service 50c9f2
        self.missingMethods = None   # list of prototypes to be implemented
Packit Service 50c9f2
        self.implementedMethods = None  # list of implemented required methods
Packit Service 50c9f2
        self.adaptMinClass = None    # The newest adapter class that can be used
Packit Service 50c9f2

Packit Service 50c9f2
    def __tokenGenerator(self):
Packit Service 50c9f2
        """Generator that reads the file and yields tokens as 4-tuples.
Packit Service 50c9f2

Packit Service 50c9f2
        The tokens have the form (tokenId, tokenString, lineNo). The
Packit Service 50c9f2
        last returned token has the form ('eof', None, None). When trying
Packit Service 50c9f2
        to access next token after that, the exception would be raised."""
Packit Service 50c9f2

Packit Service 50c9f2
        # Set the dictionary for recognizing tokenId for keywords, separators
Packit Service 50c9f2
        # and the similar categories. The key is the string to be recognized,
Packit Service 50c9f2
        # the value says its token identification.
Packit Service 50c9f2
        tokenDic = { 'class':     'class',
Packit Service 50c9f2
                     'const':     'const',
Packit Service 50c9f2
                     'public':    'public',
Packit Service 50c9f2
                     'protected': 'protected',
Packit Service 50c9f2
                     'private':   'private',
Packit Service 50c9f2
                     'static':    'static',
Packit Service 50c9f2
                     'virtual':   'virtual',
Packit Service 50c9f2
                     ':':         'colon',
Packit Service 50c9f2
                     ';':         'semic',
Packit Service 50c9f2
                     ',':         'comma',
Packit Service 50c9f2
                     '[':         'lsqbra',
Packit Service 50c9f2
                     ']':         'rsqbra',
Packit Service 50c9f2
                     '(':         'lpar',
Packit Service 50c9f2
                     ')':         'rpar',
Packit Service 50c9f2
                     '{':         'lcurly',
Packit Service 50c9f2
                     '}':         'rcurly',
Packit Service 50c9f2
                     '=':         'assign',
Packit Service 50c9f2
                     '*':         'star',
Packit Service 50c9f2
                     '&':         'amp',
Packit Service 50c9f2
                     '+':         'plus',
Packit Service 50c9f2
                     '-':         'minus',
Packit Service 50c9f2
                     '!':         'excl',
Packit Service 50c9f2
                     '?':         'qmark',
Packit Service 50c9f2
                     '<':         'lt',
Packit Service 50c9f2
                     '>':         'gt',
Packit Service 50c9f2
                     "'":         'quot',
Packit Service 50c9f2
                     '"':         'dquot',
Packit Service 50c9f2
                     '.':         'dot',
Packit Service 50c9f2
                     '%':         'perc',
Packit Service 50c9f2
                     '~':         'tilde',
Packit Service 50c9f2
                     '^':         'caret',
Packit Service 50c9f2
                   }
Packit Service 50c9f2

Packit Service 50c9f2
        # Regular expression for recognizing identifiers.
Packit Service 50c9f2
        rexId = re.compile(r'^[a-zA-Z]\w*$')
Packit Service 50c9f2

Packit Service 50c9f2
        # Open the file for reading and extracting tokens until the eof.
Packit Service 50c9f2
        # Initialize the finite automaton.
Packit Service 50c9f2
        f = xopen(self.fname)
Packit Service 50c9f2
        lineNo = 0
Packit Service 50c9f2
        line = ''         # init -- see the pos initialization below
Packit Service 50c9f2
        linelen = 0       # init
Packit Service 50c9f2
        pos = 100         # init -- pos after the end of line
Packit Service 50c9f2
        status = 0
Packit Service 50c9f2

Packit Service 50c9f2
        tokenId = None    # init
Packit Service 50c9f2
        tokenStr = ''     # init -- the characters will be appended.
Packit Service 50c9f2
        tokenLineNo = 0
Packit Service 50c9f2

Packit Service 50c9f2
        while status != 777:
Packit Service 50c9f2

Packit Service 50c9f2
            # Get the next character. Read next line first, if necessary.
Packit Service 50c9f2
            if pos < linelen:
Packit Service 50c9f2
                c = line[pos]
Packit Service 50c9f2
            else:
Packit Service 50c9f2
                lineNo += 1
Packit Service 50c9f2
                line = f.readline()
Packit Service 50c9f2
                linelen = len(line)
Packit Service 50c9f2
                pos = 0
Packit Service 50c9f2
                if line == '':         # eof
Packit Service 50c9f2
                    status = 777
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    c = line[pos]
Packit Service 50c9f2

Packit Service 50c9f2
            # Consume the character based on the status
Packit Service 50c9f2

Packit Service 50c9f2
            if status == 0:     # basic status
Packit Service 50c9f2

Packit Service 50c9f2
                # This is the initial status. If tokenId is set, yield the
Packit Service 50c9f2
                # token here and only here (except when eof is found).
Packit Service 50c9f2
                # Initialize the token variables after the yield.
Packit Service 50c9f2
                if tokenId:
Packit Service 50c9f2
                    # If it is an unknown item, it can still be recognized
Packit Service 50c9f2
                    # here. Keywords and separators are the example.
Packit Service 50c9f2
                    if tokenId == 'unknown':
Packit Service 50c9f2
                        if tokenStr in tokenDic:
Packit Service 50c9f2
                            tokenId = tokenDic[tokenStr]
Packit Service 50c9f2
                        elif tokenStr.isdigit():
Packit Service 50c9f2
                            tokenId = 'num'
Packit Service 50c9f2
                        elif rexId.match(tokenStr):
Packit Service 50c9f2
                            tokenId = 'id'
Packit Service 50c9f2
                        else:
Packit Service 50c9f2
                            msg = '\aWarning: unknown token "' + tokenStr + '"'
Packit Service 50c9f2
                            msg += '\tfound on line %d' % tokenLineNo
Packit Service 50c9f2
                            msg += ' in "' + self.fname + '".\n'
Packit Service 50c9f2
                            sys.stderr.write(msg)
Packit Service 50c9f2

Packit Service 50c9f2
                    yield (tokenId, tokenStr, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
                    # If it is a comment that contains the self.translateMeText
Packit Service 50c9f2
                    # string, set the flag -- the situation will be reported.
Packit Service 50c9f2
                    if tokenId == 'comment' and tokenStr.find(self.translateMeText) >= 0:
Packit Service 50c9f2
                        self.translateMeFlag = True
Packit Service 50c9f2

Packit Service 50c9f2
                    tokenId = None
Packit Service 50c9f2
                    tokenStr = ''
Packit Service 50c9f2
                    tokenLineNo = 0
Packit Service 50c9f2

Packit Service 50c9f2
                # Now process the character. When we just skip it (spaces),
Packit Service 50c9f2
                # stay in this status. All characters that will be part of
Packit Service 50c9f2
                # some token cause moving to the specific status. And only
Packit Service 50c9f2
                # when moving to the status == 0 (or the final state 777),
Packit Service 50c9f2
                # the token is yielded. With respect to that the automaton
Packit Service 50c9f2
                # behaves as Moore's one (output bound to status). When
Packit Service 50c9f2
                # collecting tokens, the automaton is the Mealy's one
Packit Service 50c9f2
                # (actions bound to transitions).
Packit Service 50c9f2
                if c.isspace():
Packit Service 50c9f2
                    pass                 # just skip whitespace characters
Packit Service 50c9f2
                elif c == '/':           # Possibly comment starts here, but
Packit Service 50c9f2
                    tokenId = 'unknown'  # it could be only a slash in code.
Packit Service 50c9f2
                    tokenStr = c
Packit Service 50c9f2
                    tokenLineNo = lineNo
Packit Service 50c9f2
                    status = 1
Packit Service 50c9f2
                elif c == '#':
Packit Service 50c9f2
                    tokenId = 'preproc'  # preprocessor directive
Packit Service 50c9f2
                    tokenStr = c
Packit Service 50c9f2
                    tokenLineNo = lineNo
Packit Service 50c9f2
                    status = 5
Packit Service 50c9f2
                elif c == '"':           # string starts here
Packit Service 50c9f2
                    tokenId = 'string'
Packit Service 50c9f2
                    tokenStr = c
Packit Service 50c9f2
                    tokenLineNo = lineNo
Packit Service 50c9f2
                    status = 6
Packit Service 50c9f2
                elif c == "'":           # char literal starts here
Packit Service 50c9f2
                    tokenId = 'charlit'
Packit Service 50c9f2
                    tokenStr = c
Packit Service 50c9f2
                    tokenLineNo = lineNo
Packit Service 50c9f2
                    status = 8
Packit Service 50c9f2
                elif c in tokenDic:  # known one-char token
Packit Service 50c9f2
                    tokenId = tokenDic[c]
Packit Service 50c9f2
                    tokenStr = c
Packit Service 50c9f2
                    tokenLineNo = lineNo
Packit Service 50c9f2
                    # stay in this state to yield token immediately
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    tokenId = 'unknown'  # totally unknown
Packit Service 50c9f2
                    tokenStr = c
Packit Service 50c9f2
                    tokenLineNo = lineNo
Packit Service 50c9f2
                    status = 333
Packit Service 50c9f2

Packit Service 50c9f2
                pos += 1                 # move position in any case
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 1:            # possibly a comment
Packit Service 50c9f2
                if c == '/':             # ... definitely the C++ comment
Packit Service 50c9f2
                    tokenId = 'comment'
Packit Service 50c9f2
                    tokenStr += c
Packit Service 50c9f2
                    pos += 1
Packit Service 50c9f2
                    status = 2
Packit Service 50c9f2
                elif c == '*':           # ... definitely the C comment
Packit Service 50c9f2
                    tokenId = 'comment'
Packit Service 50c9f2
                    tokenStr += c
Packit Service 50c9f2
                    pos += 1
Packit Service 50c9f2
                    status = 3
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    status = 0           # unrecognized, don't move pos
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 2:            # inside the C++ comment
Packit Service 50c9f2
                if c == '\n':            # the end of C++ comment
Packit Service 50c9f2
                    status = 0           # yield the token
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    tokenStr += c        # collect the C++ comment
Packit Service 50c9f2
                pos += 1
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 3:            # inside the C comment
Packit Service 50c9f2
                if c == '*':             # possibly the end of the C comment
Packit Service 50c9f2
                    tokenStr += c
Packit Service 50c9f2
                    status = 4
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    tokenStr += c        # collect the C comment
Packit Service 50c9f2
                pos += 1
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 4:            # possibly the end of the C comment
Packit Service 50c9f2
                if c == '/':             # definitely the end of the C comment
Packit Service 50c9f2
                    tokenStr += c
Packit Service 50c9f2
                    status = 0           # yield the token
Packit Service 50c9f2
                elif c == '*':           # more stars inside the comment
Packit Service 50c9f2
                    tokenStr += c
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    tokenStr += c        # this cannot be the end of comment
Packit Service 50c9f2
                    status = 3
Packit Service 50c9f2
                pos += 1
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 5:            # inside the preprocessor directive
Packit Service 50c9f2
                if c == '\n':            # the end of the preproc. command
Packit Service 50c9f2
                    status = 0           # yield the token
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    tokenStr += c        # collect the preproc
Packit Service 50c9f2
                pos += 1
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 6:            # inside the string
Packit Service 50c9f2
                if c == '\\':            # escaped char inside the string
Packit Service 50c9f2
                    tokenStr += c
Packit Service 50c9f2
                    status = 7
Packit Service 50c9f2
                elif c == '"':           # end of the string
Packit Service 50c9f2
                    tokenStr += c
Packit Service 50c9f2
                    status = 0
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    tokenStr += c        # collect the chars of the string
Packit Service 50c9f2
                pos += 1
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 7:            # escaped char inside the string
Packit Service 50c9f2
                tokenStr += c            # collect the char of the string
Packit Service 50c9f2
                status = 6
Packit Service 50c9f2
                pos += 1
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 8:            # inside the char literal
Packit Service 50c9f2
                tokenStr += c            # collect the char of the literal
Packit Service 50c9f2
                status = 9
Packit Service 50c9f2
                pos += 1
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 9:            # end of char literal expected
Packit Service 50c9f2
                if c == "'":             # ... and found
Packit Service 50c9f2
                    tokenStr += c
Packit Service 50c9f2
                    status = 0
Packit Service 50c9f2
                    pos += 1
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    tokenId = 'error'    # end of literal was expected
Packit Service 50c9f2
                    tokenStr += c
Packit Service 50c9f2
                    status = 0
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 333:          # start of the unknown token
Packit Service 50c9f2
                if c.isspace():
Packit Service 50c9f2
                    pos += 1
Packit Service 50c9f2
                    status = 0           # tokenId may be determined later
Packit Service 50c9f2
                elif c in tokenDic:  # separator, don't move pos
Packit Service 50c9f2
                    status = 0
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    tokenStr += c        # collect
Packit Service 50c9f2
                    pos += 1
Packit Service 50c9f2

Packit Service 50c9f2
        # We should have finished in the final status. If some token
Packit Service 50c9f2
        # have been extracted, yield it first.
Packit Service 50c9f2
        assert(status == 777)
Packit Service 50c9f2
        if tokenId:
Packit Service 50c9f2
            yield (tokenId, tokenStr, tokenLineNo)
Packit Service 50c9f2
            tokenId = None
Packit Service 50c9f2
            tokenStr = ''
Packit Service 50c9f2
            tokenLineNo = 0
Packit Service 50c9f2

Packit Service 50c9f2
        # The file content is processed. Close the file. Then always yield
Packit Service 50c9f2
        # the eof token.
Packit Service 50c9f2
        f.close()
Packit Service 50c9f2
        yield ('eof', None, None)
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def __collectClassInfo(self, tokenIterator):
Packit Service 50c9f2
        """Collect the information about the class and base class.
Packit Service 50c9f2

Packit Service 50c9f2
        The tokens including the opening left curly brace of the class are
Packit Service 50c9f2
        consumed."""
Packit Service 50c9f2

Packit Service 50c9f2
        status = 0  # initial state
Packit Service 50c9f2

Packit Service 50c9f2
        while status != 777:   # final state
Packit Service 50c9f2

Packit Service 50c9f2
            # Always assume that the previous tokens were processed. Get
Packit Service 50c9f2
            # the next one.
Packit Service 50c9f2
            tokenId, tokenStr, tokenLineNo = next(tokenIterator)
Packit Service 50c9f2

Packit Service 50c9f2
            # Process the token and never return back.
Packit Service 50c9f2
            if status == 0:    # waiting for the 'class' keyword.
Packit Service 50c9f2
                if tokenId == 'class':
Packit Service 50c9f2
                    status = 1
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 1:  # expecting the class identification
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    self.classId = tokenStr
Packit Service 50c9f2
                    status = 2
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 2:  # expecting the curly brace or base class info
Packit Service 50c9f2
                if tokenId == 'lcurly':
Packit Service 50c9f2
                    status = 777        # correctly finished
Packit Service 50c9f2
                elif tokenId == 'colon':
Packit Service 50c9f2
                    status = 3
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 3:  # expecting the 'public' in front of base class id
Packit Service 50c9f2
                if tokenId == 'public':
Packit Service 50c9f2
                    status = 4
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 4:  # expecting the base class id
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    self.baseClassId = tokenStr
Packit Service 50c9f2
                    status = 5
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 5:  # expecting the curly brace and quitting
Packit Service 50c9f2
                if tokenId == 'lcurly':
Packit Service 50c9f2
                    status = 777        # correctly finished
Packit Service 50c9f2
                elif tokenId == 'comment':
Packit Service 50c9f2
                    pass
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
        # Extract the status of the TranslatorXxxx class. The readable form
Packit Service 50c9f2
        # will be used in reports the status form is a string that can be
Packit Service 50c9f2
        # compared lexically (unified length, padding with zeros, etc.).
Packit Service 50c9f2
        if self.baseClassId:
Packit Service 50c9f2
            lst = self.baseClassId.split('_')
Packit Service 50c9f2
            if lst[0] == 'Translator':
Packit Service 50c9f2
                self.readableStatus = 'up-to-date'
Packit Service 50c9f2
                self.status = ''
Packit Service 50c9f2
            elif lst[0] == 'TranslatorAdapter':
Packit Service 50c9f2
                self.status = lst[1] + '.' + lst[2]
Packit Service 50c9f2
                self.readableStatus = self.status
Packit Service 50c9f2
                if len(lst) > 3:        # add the last part of the number
Packit Service 50c9f2
                    self.status += '.' + ('%02d' % int(lst[3]))
Packit Service 50c9f2
                    self.readableStatus += '.' + lst[3]
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.status += '.00'
Packit Service 50c9f2
            elif lst[0] == 'TranslatorEnglish':
Packit Service 50c9f2
                # Obsolete or Based on English.
Packit Service 50c9f2
                if self.classId[-2:] == 'En':
Packit Service 50c9f2
                    self.readableStatus = 'English based'
Packit Service 50c9f2
                    self.status = 'En'
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.readableStatus = 'obsolete'
Packit Service 50c9f2
                    self.status = '0.0.00'
Packit Service 50c9f2

Packit Service 50c9f2
            # Check whether status was set, or set 'strange'.
Packit Service 50c9f2
            if self.status == None:
Packit Service 50c9f2
                self.status = 'strange'
Packit Service 50c9f2
            if not self.readableStatus:
Packit Service 50c9f2
                self.readableStatus = 'strange'
Packit Service 50c9f2

Packit Service 50c9f2
            # Extract the name of the language and the readable form.
Packit Service 50c9f2
            self.lang = self.classId[10:]  # without 'Translator'
Packit Service 50c9f2
            if self.lang == 'Brazilian':
Packit Service 50c9f2
                self.langReadable = 'Brazilian Portuguese'
Packit Service 50c9f2
            elif self.lang == 'Chinesetraditional':
Packit Service 50c9f2
                self.langReadable = 'Chinese Traditional'
Packit Service 50c9f2
            else:
Packit Service 50c9f2
                self.langReadable = self.lang
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def __unexpectedToken(self, status, tokenId, tokenLineNo):
Packit Service 50c9f2
        """Reports unexpected token and quits with exit code 1."""
Packit Service 50c9f2

Packit Service 50c9f2
        import inspect
Packit Service 50c9f2
        calledFrom = inspect.stack()[1][3]
Packit Service 50c9f2
        msg = "\a\nUnexpected token '%s' on the line %d in '%s'.\n"
Packit Service 50c9f2
        msg = msg % (tokenId, tokenLineNo, self.fname)
Packit Service 50c9f2
        msg += 'status = %d in %s()\n' % (status, calledFrom)
Packit Service 50c9f2
        sys.stderr.write(msg)
Packit Service 50c9f2
        sys.exit(1)
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def collectPureVirtualPrototypes(self):
Packit Service 50c9f2
        """Returns dictionary 'unified prototype' -> 'full prototype'.
Packit Service 50c9f2

Packit Service 50c9f2
        The method is expected to be called only for the translator.h. It
Packit Service 50c9f2
        extracts only the pure virtual method and build the dictionary where
Packit Service 50c9f2
        key is the unified prototype without argument identifiers."""
Packit Service 50c9f2

Packit Service 50c9f2
        # Prepare empty dictionary that will be returned.
Packit Service 50c9f2
        resultDic = {}
Packit Service 50c9f2

Packit Service 50c9f2
        # Start the token generator which parses the class source file.
Packit Service 50c9f2
        tokenIterator = self.__tokenGenerator()
Packit Service 50c9f2

Packit Service 50c9f2
        # Collect the class and the base class identifiers.
Packit Service 50c9f2
        self.__collectClassInfo(tokenIterator)
Packit Service 50c9f2
        assert(self.classId == 'Translator')
Packit Service 50c9f2

Packit Service 50c9f2
        # Let's collect readable form of the public virtual pure method
Packit Service 50c9f2
        # prototypes in the readable form -- as defined in translator.h.
Packit Service 50c9f2
        # Let's collect also unified form of the same prototype that omits
Packit Service 50c9f2
        # everything that can be omitted, namely 'virtual' and argument
Packit Service 50c9f2
        # identifiers.
Packit Service 50c9f2
        prototype = ''    # readable prototype (with everything)
Packit Service 50c9f2
        uniPrototype = '' # unified prototype (without arg. identifiers)
Packit Service 50c9f2

Packit Service 50c9f2
        # Collect the pure virtual method prototypes. Stop on the closing
Packit Service 50c9f2
        # curly brace followed by the semicolon (end of class).
Packit Service 50c9f2
        status = 0
Packit Service 50c9f2
        curlyCnt = 0      # counter for the level of curly braces
Packit Service 50c9f2

Packit Service 50c9f2
        # Loop until the final state 777 is reached. The errors are processed
Packit Service 50c9f2
        # immediately. In this implementation, it always quits the application.
Packit Service 50c9f2
        while status != 777:
Packit Service 50c9f2

Packit Service 50c9f2
            # Get the next token.
Packit Service 50c9f2
            tokenId, tokenStr, tokenLineNo = next(tokenIterator)
Packit Service 50c9f2

Packit Service 50c9f2
            if status == 0:      # waiting for 'public:'
Packit Service 50c9f2
                if tokenId == 'public':
Packit Service 50c9f2
                    status = 1
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 1:    # colon after the 'public'
Packit Service 50c9f2
                if tokenId == 'colon':
Packit Service 50c9f2
                    status = 2
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 2:    # waiting for 'virtual'
Packit Service 50c9f2
                if tokenId == 'virtual':
Packit Service 50c9f2
                    prototype = tokenStr  # but not to unified prototype
Packit Service 50c9f2
                    status = 3
Packit Service 50c9f2
                elif tokenId == 'comment':
Packit Service 50c9f2
                    pass
Packit Service 50c9f2
                elif tokenId == 'rcurly':
Packit Service 50c9f2
                    status = 11         # expected end of class
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 3:    # return type of the method expected
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    uniPrototype = tokenStr  # start collecting the unified prototype
Packit Service 50c9f2
                    status = 4
Packit Service 50c9f2
                elif tokenId == 'tilde':
Packit Service 50c9f2
                    status = 4
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 4:    # method identifier expected
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    uniPrototype += ' ' + tokenStr
Packit Service 50c9f2
                    status = 5
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 5:    # left bracket of the argument list expected
Packit Service 50c9f2
                if tokenId == 'lpar':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 6
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 6:    # collecting arguments of the method
Packit Service 50c9f2
                if tokenId == 'rpar':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 7
Packit Service 50c9f2
                elif tokenId == 'const':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 12
Packit Service 50c9f2
                elif tokenId == 'id':           # type identifier
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 13
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 7:    # assignment expected or left curly brace
Packit Service 50c9f2
                if tokenId == 'assign':
Packit Service 50c9f2
                    status = 8
Packit Service 50c9f2
                elif tokenId == 'lcurly':
Packit Service 50c9f2
                    curlyCnt = 1      # method body entered
Packit Service 50c9f2
                    status = 10
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 8:    # zero expected
Packit Service 50c9f2
                if tokenId == 'num' and tokenStr == '0':
Packit Service 50c9f2
                    status = 9
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 9:    # after semicolon, produce the dic item
Packit Service 50c9f2
                if tokenId == 'semic':
Packit Service 50c9f2
                    assert(uniPrototype not in resultDic)
Packit Service 50c9f2
                    resultDic[uniPrototype] = prototype
Packit Service 50c9f2
                    status = 2
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 10:   # consuming the body of the method
Packit Service 50c9f2
                if tokenId == 'rcurly':
Packit Service 50c9f2
                    curlyCnt -= 1
Packit Service 50c9f2
                    if curlyCnt == 0:
Packit Service 50c9f2
                        status = 2     # body consumed
Packit Service 50c9f2
                elif tokenId == 'lcurly':
Packit Service 50c9f2
                    curlyCnt += 1
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 11:   # probably the end of class
Packit Service 50c9f2
                if tokenId == 'semic':
Packit Service 50c9f2
                    status = 777
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 12:   # type id for argument expected
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    uniPrototype += ' ' + tokenStr
Packit Service 50c9f2
                    status = 13
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 13:   # namespace qualification or * or & expected
Packit Service 50c9f2
                if tokenId == 'colon':        # was namespace id
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 14
Packit Service 50c9f2
                elif tokenId == 'star' or tokenId == 'amp':  # pointer or reference
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    uniPrototype += ' ' + tokenStr
Packit Service 50c9f2
                    status = 16
Packit Service 50c9f2
                elif tokenId == 'id':         # argument identifier
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    # don't put this into unified prototype
Packit Service 50c9f2
                    status = 17
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 14:   # second colon for namespace:: expected
Packit Service 50c9f2
                if tokenId == 'colon':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 15
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 15:   # type after namespace:: expected
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 13
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 16:   # argument identifier expected
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    # don't put this into unified prototype
Packit Service 50c9f2
                    status = 17
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 17:   # comma or ')' after argument identifier expected
Packit Service 50c9f2
                if tokenId == 'comma':
Packit Service 50c9f2
                    prototype += ', '
Packit Service 50c9f2
                    uniPrototype += ', '
Packit Service 50c9f2
                    status = 6
Packit Service 50c9f2
                elif tokenId == 'rpar':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 7
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
        # Eat the rest of the source to cause closing the file.
Packit Service 50c9f2
        while tokenId != 'eof':
Packit Service 50c9f2
            tokenId, tokenStr, tokenLineNo = next(tokenIterator)
Packit Service 50c9f2

Packit Service 50c9f2
        # Return the resulting dictionary with 'uniPrototype -> prototype'.
Packit Service 50c9f2
        return resultDic
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def __collectPublicMethodPrototypes(self, tokenIterator):
Packit Service 50c9f2
        """Collects prototypes of public methods and fills self.prototypeDic.
Packit Service 50c9f2

Packit Service 50c9f2
        The dictionary is filled by items: uniPrototype -> prototype.
Packit Service 50c9f2
        The method is expected to be called only for TranslatorXxxx classes,
Packit Service 50c9f2
        i.e. for the classes that implement translation to some language.
Packit Service 50c9f2
        It assumes that the opening curly brace of the class was already
Packit Service 50c9f2
        consumed. The source is consumed until the end of the class.
Packit Service 50c9f2
        The caller should consume the source until the eof to cause closing
Packit Service 50c9f2
        the source file."""
Packit Service 50c9f2

Packit Service 50c9f2
        assert(self.classId != 'Translator')
Packit Service 50c9f2
        assert(self.baseClassId != None)
Packit Service 50c9f2

Packit Service 50c9f2
        # The following finite automaton slightly differs from the one
Packit Service 50c9f2
        # inside self.collectPureVirtualPrototypes(). It produces the
Packit Service 50c9f2
        # dictionary item just after consuming the body of the method
Packit Service 50c9f2
        # (transition from state 10 to state 2). It also does not allow
Packit Service 50c9f2
        # definitions of public pure virtual methods, except for
Packit Service 50c9f2
        # TranslatorAdapterBase (states 8 and 9). Argument identifier inside
Packit Service 50c9f2
        # method argument lists can be omitted or commented.
Packit Service 50c9f2
        #
Packit Service 50c9f2
        # Let's collect readable form of all public method prototypes in
Packit Service 50c9f2
        # the readable form -- as defined in the source file.
Packit Service 50c9f2
        # Let's collect also unified form of the same prototype that omits
Packit Service 50c9f2
        # everything that can be omitted, namely 'virtual' and argument
Packit Service 50c9f2
        # identifiers.
Packit Service 50c9f2
        prototype = ''    # readable prototype (with everything)
Packit Service 50c9f2
        uniPrototype = '' # unified prototype (without arg. identifiers)
Packit Service 50c9f2
        warning = ''      # warning message -- if something special detected
Packit Service 50c9f2
        methodId = None   # processed method id
Packit Service 50c9f2

Packit Service 50c9f2
        # Collect the method prototypes. Stop on the closing
Packit Service 50c9f2
        # curly brace followed by the semicolon (end of class).
Packit Service 50c9f2
        status = 0
Packit Service 50c9f2
        curlyCnt = 0      # counter for the level of curly braces
Packit Service 50c9f2

Packit Service 50c9f2
        # Loop until the final state 777 is reached. The errors are processed
Packit Service 50c9f2
        # immediately. In this implementation, it always quits the application.
Packit Service 50c9f2
        while status != 777:
Packit Service 50c9f2

Packit Service 50c9f2
            # Get the next token.
Packit Service 50c9f2
            tokenId, tokenStr, tokenLineNo = next(tokenIterator)
Packit Service 50c9f2

Packit Service 50c9f2
            if status == 0:      # waiting for 'public:'
Packit Service 50c9f2
                if tokenId == 'public':
Packit Service 50c9f2
                    status = 1
Packit Service 50c9f2
                elif tokenId == 'eof':  # non-public things until the eof
Packit Service 50c9f2
                    status = 777
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 1:    # colon after the 'public'
Packit Service 50c9f2
                if tokenId == 'colon':
Packit Service 50c9f2
                    status = 2
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 2:    # waiting for 'virtual' (can be omitted)
Packit Service 50c9f2
                if tokenId == 'virtual':
Packit Service 50c9f2
                    prototype = tokenStr  # but not to unified prototype
Packit Service 50c9f2
                    status = 3
Packit Service 50c9f2
                elif tokenId == 'id':     # 'virtual' was omitted
Packit Service 50c9f2
                    prototype = tokenStr
Packit Service 50c9f2
                    uniPrototype = tokenStr  # start collecting the unified prototype
Packit Service 50c9f2
                    status = 4
Packit Service 50c9f2
                elif tokenId == 'comment':
Packit Service 50c9f2
                    pass
Packit Service 50c9f2
                elif tokenId == 'protected' or tokenId == 'private':
Packit Service 50c9f2
                    status = 0
Packit Service 50c9f2
                elif tokenId == 'rcurly':
Packit Service 50c9f2
                    status = 11         # expected end of class
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 3:    # return type of the method expected
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    uniPrototype = tokenStr  # start collecting the unified prototype
Packit Service 50c9f2
                    status = 4
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 4:    # method identifier expected
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    uniPrototype += ' ' + tokenStr
Packit Service 50c9f2
                    methodId = tokenStr    # for reporting
Packit Service 50c9f2
                    status = 5
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 5:    # left bracket of the argument list expected
Packit Service 50c9f2
                if tokenId == 'lpar':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 6
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 6:    # collecting arguments of the method
Packit Service 50c9f2
                if tokenId == 'rpar':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 7
Packit Service 50c9f2
                elif tokenId == 'const':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 12
Packit Service 50c9f2
                elif tokenId == 'id':           # type identifier
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 13
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 7:    # left curly brace expected
Packit Service 50c9f2
                if tokenId == 'lcurly':
Packit Service 50c9f2
                    curlyCnt = 1      # method body entered
Packit Service 50c9f2
                    status = 10
Packit Service 50c9f2
                elif tokenId == 'comment':
Packit Service 50c9f2
                    pass
Packit Service 50c9f2
                elif tokenId == 'assign': # allowed only for TranslatorAdapterBase
Packit Service 50c9f2
                    assert(self.classId == 'TranslatorAdapterBase')
Packit Service 50c9f2
                    status = 8
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 8:    # zero expected (TranslatorAdapterBase)
Packit Service 50c9f2
                assert(self.classId == 'TranslatorAdapterBase')
Packit Service 50c9f2
                if tokenId == 'num' and tokenStr == '0':
Packit Service 50c9f2
                    status = 9
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 9:    # after semicolon (TranslatorAdapterBase)
Packit Service 50c9f2
                assert(self.classId == 'TranslatorAdapterBase')
Packit Service 50c9f2
                if tokenId == 'semic':
Packit Service 50c9f2
                    status = 2
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 10:   # consuming the body of the method, then dic item
Packit Service 50c9f2
                if tokenId == 'rcurly':
Packit Service 50c9f2
                    curlyCnt -= 1
Packit Service 50c9f2
                    if curlyCnt == 0:
Packit Service 50c9f2
                        # Check for possible copy/paste error when name
Packit Service 50c9f2
                        # of the method was not corrected (i.e. the same
Packit Service 50c9f2
                        # name already exists).
Packit Service 50c9f2
                        if uniPrototype in self.prototypeDic:
Packit Service 50c9f2
                            msg = "'%s' prototype found again (duplicity)\n"
Packit Service 50c9f2
                            msg += "in '%s'.\n" % self.fname
Packit Service 50c9f2
                            msg = msg % uniPrototype
Packit Service 50c9f2
                            sys.stderr.write(msg)
Packit Service 50c9f2
                            assert False
Packit Service 50c9f2

Packit Service 50c9f2
                        assert(uniPrototype not in self.prototypeDic)
Packit Service 50c9f2
                        # Insert new dictionary item.
Packit Service 50c9f2
                        self.prototypeDic[uniPrototype] = prototype
Packit Service 50c9f2
                        status = 2      # body consumed
Packit Service 50c9f2
                        methodId = None # outside of any method
Packit Service 50c9f2
                elif tokenId == 'lcurly':
Packit Service 50c9f2
                    curlyCnt += 1
Packit Service 50c9f2

Packit Service 50c9f2
                # Warn in special case.
Packit Service 50c9f2
                elif methodId == 'trLegendDocs' and tokenId == 'string' \
Packit Service 50c9f2
                    and tokenStr.find('MAX_DOT_GRAPH_HEIGHT') >= 0:
Packit Service 50c9f2
                        self.txtMAX_DOT_GRAPH_HEIGHT_flag = True
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 11:   # probably the end of class
Packit Service 50c9f2
                if tokenId == 'semic':
Packit Service 50c9f2
                    status = 777
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 12:   # type id for argument expected
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    uniPrototype += ' ' + tokenStr
Packit Service 50c9f2
                    status = 13
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 13:   # :: or * or & or id or ) expected
Packit Service 50c9f2
                if tokenId == 'colon':        # was namespace id
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 14
Packit Service 50c9f2
                elif tokenId == 'star' or tokenId == 'amp':  # pointer or reference
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    uniPrototype += ' ' + tokenStr
Packit Service 50c9f2
                    status = 16
Packit Service 50c9f2
                elif tokenId == 'id':         # argument identifier
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    # don't put this into unified prototype
Packit Service 50c9f2
                    status = 17
Packit Service 50c9f2
                elif tokenId == 'comment':    # probably commented-out identifier
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                elif tokenId == 'rpar':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 7
Packit Service 50c9f2
                elif tokenId == 'comma':
Packit Service 50c9f2
                    prototype += ', '
Packit Service 50c9f2
                    uniPrototype += ', '
Packit Service 50c9f2
                    status = 6
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 14:   # second colon for namespace:: expected
Packit Service 50c9f2
                if tokenId == 'colon':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 15
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 15:   # type after namespace:: expected
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 13
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 16:   # argument identifier or ) expected
Packit Service 50c9f2
                if tokenId == 'id':
Packit Service 50c9f2
                    prototype += ' ' + tokenStr
Packit Service 50c9f2
                    # don't put this into unified prototype
Packit Service 50c9f2
                    status = 17
Packit Service 50c9f2
                elif tokenId == 'rpar':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 7
Packit Service 50c9f2
                elif tokenId == 'comment':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2
            elif status == 17:   # comma or ')' after argument identifier expected
Packit Service 50c9f2
                if tokenId == 'comma':
Packit Service 50c9f2
                    prototype += ', '
Packit Service 50c9f2
                    uniPrototype += ', '
Packit Service 50c9f2
                    status = 6
Packit Service 50c9f2
                elif tokenId == 'rpar':
Packit Service 50c9f2
                    prototype += tokenStr
Packit Service 50c9f2
                    uniPrototype += tokenStr
Packit Service 50c9f2
                    status = 7
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    self.__unexpectedToken(status, tokenId, tokenLineNo)
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def collectAdapterPrototypes(self):
Packit Service 50c9f2
        """Returns the dictionary of prototypes implemented by adapters.
Packit Service 50c9f2

Packit Service 50c9f2
        It is created to process the translator_adapter.h. The returned
Packit Service 50c9f2
        dictionary has the form: unifiedPrototype -> (version, classId)
Packit Service 50c9f2
        thus by looking for the prototype, we get the information what is
Packit Service 50c9f2
        the newest (least adapting) adapter that is sufficient for
Packit Service 50c9f2
        implementing the method."""
Packit Service 50c9f2

Packit Service 50c9f2
        # Start the token generator which parses the class source file.
Packit Service 50c9f2
        assert(os.path.split(self.fname)[1] == 'translator_adapter.h')
Packit Service 50c9f2
        tokenIterator = self.__tokenGenerator()
Packit Service 50c9f2

Packit Service 50c9f2
        # Get the references to the involved dictionaries.
Packit Service 50c9f2
        reqDic = self.manager.requiredMethodsDic
Packit Service 50c9f2

Packit Service 50c9f2
        # Create the empty dictionary that will be returned.
Packit Service 50c9f2
        adaptDic = {}
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
        # Loop through the source of the adapter file until no other adapter
Packit Service 50c9f2
        # class is found.
Packit Service 50c9f2
        while True:
Packit Service 50c9f2
            try:
Packit Service 50c9f2
                # Collect the class and the base class identifiers.
Packit Service 50c9f2
                self.__collectClassInfo(tokenIterator)
Packit Service 50c9f2

Packit Service 50c9f2
                # Extract the comparable version of the adapter class.
Packit Service 50c9f2
                # Note: The self.status as set by self.__collectClassInfo()
Packit Service 50c9f2
                # contains similar version, but is related to the base class,
Packit Service 50c9f2
                # not to the class itself.
Packit Service 50c9f2
                lst = self.classId.split('_')
Packit Service 50c9f2
                version = ''
Packit Service 50c9f2
                if lst[0] == 'TranslatorAdapter': # TranslatorAdapterBase otherwise
Packit Service 50c9f2
                    version = lst[1] + '.' + lst[2]
Packit Service 50c9f2
                    if len(lst) > 3:        # add the last part of the number
Packit Service 50c9f2
                        version += '.' + ('%02d' % int(lst[3]))
Packit Service 50c9f2
                    else:
Packit Service 50c9f2
                        version += '.00'
Packit Service 50c9f2

Packit Service 50c9f2
                # Collect the prototypes of implemented public methods.
Packit Service 50c9f2
                self.__collectPublicMethodPrototypes(tokenIterator)
Packit Service 50c9f2

Packit Service 50c9f2
                # For the required methods, update the dictionary of methods
Packit Service 50c9f2
                # implemented by the adapter.
Packit Service 50c9f2
                for protoUni in self.prototypeDic:
Packit Service 50c9f2
                    if protoUni in reqDic:
Packit Service 50c9f2
                        # This required method will be marked as implemented
Packit Service 50c9f2
                        # by this adapter class. This implementation assumes
Packit Service 50c9f2
                        # that newer adapters do not reimplement any required
Packit Service 50c9f2
                        # methods already implemented by older adapters.
Packit Service 50c9f2
                        assert(protoUni not in adaptDic)
Packit Service 50c9f2
                        adaptDic[protoUni] = (version, self.classId)
Packit Service 50c9f2

Packit Service 50c9f2
                # Clear the dictionary object and the information related
Packit Service 50c9f2
                # to the class as the next adapter class is to be processed.
Packit Service 50c9f2
                self.prototypeDic.clear()
Packit Service 50c9f2
                self.classId = None
Packit Service 50c9f2
                self.baseClassId = None
Packit Service 50c9f2

Packit Service 50c9f2
            except StopIteration:
Packit Service 50c9f2
                break
Packit Service 50c9f2

Packit Service 50c9f2
        # Return the result dictionary.
Packit Service 50c9f2
        return adaptDic
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def processing(self):
Packit Service 50c9f2
        """Processing of the source file -- only for TranslatorXxxx classes."""
Packit Service 50c9f2

Packit Service 50c9f2
        # Start the token generator which parses the class source file.
Packit Service 50c9f2
        tokenIterator = self.__tokenGenerator()
Packit Service 50c9f2

Packit Service 50c9f2
        # Collect the class and the base class identifiers.
Packit Service 50c9f2
        self.__collectClassInfo(tokenIterator)
Packit Service 50c9f2
        assert(self.classId != 'Translator')
Packit Service 50c9f2
        assert(self.classId[:17] != 'TranslatorAdapter')
Packit Service 50c9f2

Packit Service 50c9f2
        # Collect the prototypes of implemented public methods.
Packit Service 50c9f2
        self.__collectPublicMethodPrototypes(tokenIterator)
Packit Service 50c9f2

Packit Service 50c9f2
        # Eat the rest of the source to cause closing the file.
Packit Service 50c9f2
        while True:
Packit Service 50c9f2
            try:
Packit Service 50c9f2
                t = next(tokenIterator)
Packit Service 50c9f2
            except StopIteration:
Packit Service 50c9f2
                break
Packit Service 50c9f2

Packit Service 50c9f2
        # Shorthands for the used dictionaries.
Packit Service 50c9f2
        reqDic = self.manager.requiredMethodsDic
Packit Service 50c9f2
        adaptDic = self.manager.adaptMethodsDic
Packit Service 50c9f2
        myDic = self.prototypeDic
Packit Service 50c9f2

Packit Service 50c9f2
        # Build the list of obsolete methods.
Packit Service 50c9f2
        self.obsoleteMethods = []
Packit Service 50c9f2
        for p in myDic:
Packit Service 50c9f2
            if p not in reqDic:
Packit Service 50c9f2
                self.obsoleteMethods.append(p)
Packit Service 50c9f2
        self.obsoleteMethods.sort()
Packit Service 50c9f2

Packit Service 50c9f2
        # Build the list of missing methods and the list of implemented
Packit Service 50c9f2
        # required methods.
Packit Service 50c9f2
        self.missingMethods = []
Packit Service 50c9f2
        self.implementedMethods = []
Packit Service 50c9f2
        for p in reqDic:
Packit Service 50c9f2
            if p in myDic:
Packit Service 50c9f2
                self.implementedMethods.append(p)
Packit Service 50c9f2
            else:
Packit Service 50c9f2
                self.missingMethods.append(p)
Packit Service 50c9f2
        self.missingMethods.sort()
Packit Service 50c9f2
        self.implementedMethods.sort()
Packit Service 50c9f2

Packit Service 50c9f2
        # Check whether adapter must be used or suggest the newest one.
Packit Service 50c9f2
        # Change the status and set the note accordingly.
Packit Service 50c9f2
        if self.baseClassId != 'Translator':
Packit Service 50c9f2
            if not self.missingMethods:
Packit Service 50c9f2
                self.note = 'Change the base class to Translator.'
Packit Service 50c9f2
                self.status = ''
Packit Service 50c9f2
                self.readableStatus = 'almost up-to-date'
Packit Service 50c9f2
            elif self.baseClassId != 'TranslatorEnglish':
Packit Service 50c9f2
                # The translator uses some of the adapters.
Packit Service 50c9f2
                # Look at the missing methods and check what adapter
Packit Service 50c9f2
                # implements them. Remember the one with the lowest version.
Packit Service 50c9f2
                adaptMinVersion = '9.9.99'
Packit Service 50c9f2
                adaptMinClass = 'TranslatorAdapter_9_9_99'
Packit Service 50c9f2
                for uniProto in self.missingMethods:
Packit Service 50c9f2
                    if uniProto in adaptDic:
Packit Service 50c9f2
                        version, cls = adaptDic[uniProto]
Packit Service 50c9f2
                        if version < adaptMinVersion:
Packit Service 50c9f2
                            adaptMinVersion = version
Packit Service 50c9f2
                            adaptMinClass = cls
Packit Service 50c9f2

Packit Service 50c9f2
                # Test against the current status -- preserve the self.status.
Packit Service 50c9f2
                # Possibly, the translator implements enough methods to
Packit Service 50c9f2
                # use some newer adapter.
Packit Service 50c9f2
                status = self.status
Packit Service 50c9f2

Packit Service 50c9f2
                # If the version of the used adapter is smaller than
Packit Service 50c9f2
                # the required, set the note and update the status as if
Packit Service 50c9f2
                # the newer adapter was used.
Packit Service 50c9f2
                if adaptMinVersion > status:
Packit Service 50c9f2
                    self.note = 'Change the base class to %s.' % adaptMinClass
Packit Service 50c9f2
                    self.status = adaptMinVersion
Packit Service 50c9f2
                    self.adaptMinClass = adaptMinClass
Packit Service 50c9f2
                    self.readableStatus = adaptMinVersion # simplified
Packit Service 50c9f2

Packit Service 50c9f2
        # If everything seems OK, some explicit warning flags still could
Packit Service 50c9f2
        # be set.
Packit Service 50c9f2
        if not self.note and self.status == '' and \
Packit Service 50c9f2
           (self.translateMeFlag or self.txtMAX_DOT_GRAPH_HEIGHT_flag):
Packit Service 50c9f2
           self.note = ''
Packit Service 50c9f2
           if self.translateMeFlag:
Packit Service 50c9f2
               self.note += 'The "%s" found in a comment.' % self.translateMeText
Packit Service 50c9f2
           if self.note != '':
Packit Service 50c9f2
               self.note += '\n\t\t'
Packit Service 50c9f2
           if self.txtMAX_DOT_GRAPH_HEIGHT_flag:
Packit Service 50c9f2
               self.note += 'The MAX_DOT_GRAPH_HEIGHT found in trLegendDocs()'
Packit Service 50c9f2

Packit Service 50c9f2
        # If everything seems OK, but there are obsolete methods, set
Packit Service 50c9f2
        # the note to clean-up source. This note will be used only when
Packit Service 50c9f2
        # the previous code did not set another note (priority).
Packit Service 50c9f2
        if not self.note and self.status == '' and self.obsoleteMethods:
Packit Service 50c9f2
            self.note = 'Remove the obsolete methods (never used).'
Packit Service 50c9f2

Packit Service 50c9f2
        # If there is at least some note but the status suggests it is
Packit Service 50c9f2
        # otherwise up-to-date, mark is as ALMOST up-to-date.
Packit Service 50c9f2
        if self.note and self.status == '':
Packit Service 50c9f2
            self.readableStatus = 'almost up-to-date'
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def report(self, fout):
Packit Service 50c9f2
        """Returns the report part for the source as a multiline string.
Packit Service 50c9f2

Packit Service 50c9f2
        No output for up-to-date translators without problem."""
Packit Service 50c9f2

Packit Service 50c9f2
        # If there is nothing to report, return immediately.
Packit Service 50c9f2
        if self.status == '' and not self.note:
Packit Service 50c9f2
            return
Packit Service 50c9f2

Packit Service 50c9f2
        # Report the number of not implemented methods.
Packit Service 50c9f2
        fout.write('\n\n\n')
Packit Service 50c9f2
        fout.write(self.classId + '   (' + self.baseClassId + ')')
Packit Service 50c9f2
        percentImplemented = 100    # init
Packit Service 50c9f2
        allNum = len(self.manager.requiredMethodsDic)
Packit Service 50c9f2
        if self.missingMethods:
Packit Service 50c9f2
            num = len(self.missingMethods)
Packit Service 50c9f2
            percentImplemented = 100 * (allNum - num) / allNum
Packit Service 50c9f2
            fout.write('  %d' % num)
Packit Service 50c9f2
            fout.write(' method')
Packit Service 50c9f2
            if num > 1:
Packit Service 50c9f2
                fout.write('s')
Packit Service 50c9f2
            fout.write(' to implement (%d %%)' % (100 * num / allNum))
Packit Service 50c9f2
        fout.write('\n' + '-' * len(self.classId))
Packit Service 50c9f2

Packit Service 50c9f2
        # Write the info about the implemented required methods.
Packit Service 50c9f2
        fout.write('\n\n  Implements %d' % len(self.implementedMethods))
Packit Service 50c9f2
        fout.write(' of the required methods (%d %%).' % percentImplemented)
Packit Service 50c9f2

Packit Service 50c9f2
        # Report the missing method, but only when it is not English-based
Packit Service 50c9f2
        # translator.
Packit Service 50c9f2
        if self.missingMethods and self.status != 'En':
Packit Service 50c9f2
            fout.write('\n\n  Missing methods (should be implemented):\n')
Packit Service 50c9f2
            reqDic = self.manager.requiredMethodsDic
Packit Service 50c9f2
            for p in self.missingMethods:
Packit Service 50c9f2
                fout.write('\n    ' + reqDic[p])
Packit Service 50c9f2

Packit Service 50c9f2
        # Always report obsolete methods.
Packit Service 50c9f2
        if self.obsoleteMethods:
Packit Service 50c9f2
            fout.write('\n\n  Obsolete methods (should be removed, never used):\n')
Packit Service 50c9f2
            myDic = self.prototypeDic
Packit Service 50c9f2
            for p in self.obsoleteMethods:
Packit Service 50c9f2
                fout.write('\n    ' + myDic[p])
Packit Service 50c9f2

Packit Service 50c9f2
        # For English-based translator, report the implemented methods.
Packit Service 50c9f2
        if self.status == 'En' and self.implementedMethods:
Packit Service 50c9f2
            fout.write('\n\n  This English-based translator implements ')
Packit Service 50c9f2
            fout.write('the following methods:\n')
Packit Service 50c9f2
            reqDic = self.manager.requiredMethodsDic
Packit Service 50c9f2
            for p in self.implementedMethods:
Packit Service 50c9f2
                fout.write('\n    ' + reqDic[p])
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def getmtime(self):
Packit Service 50c9f2
        """Returns the last modification time of the source file."""
Packit Service 50c9f2
        assert(os.path.isfile(self.fname))
Packit Service 50c9f2
        return os.path.getmtime(self.fname)
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
class TrManager:
Packit Service 50c9f2
    """Collects basic info and builds subordinate Transl objects."""
Packit Service 50c9f2

Packit Service 50c9f2
    def __init__(self):
Packit Service 50c9f2
        """Determines paths, creates and initializes structures.
Packit Service 50c9f2

Packit Service 50c9f2
        The arguments of the script may explicitly say what languages should
Packit Service 50c9f2
        be processed. Write the two letter identifications that are used
Packit Service 50c9f2
        for composing the source filenames, so...
Packit Service 50c9f2

Packit Service 50c9f2
            python translator.py cz
Packit Service 50c9f2

Packit Service 50c9f2
        this will process only translator_cz.h source.
Packit Service 50c9f2
        """
Packit Service 50c9f2

Packit Service 50c9f2
        # Determine the path to the script and its name.
Packit Service 50c9f2
        self.script = os.path.abspath(sys.argv[0])
Packit Service 50c9f2
        self.script_path, self.script_name = os.path.split(self.script)
Packit Service 50c9f2
        self.script_path = os.path.abspath(self.script_path)
Packit Service 50c9f2

Packit Service 50c9f2
        # Determine the absolute path to the Doxygen's root subdirectory.
Packit Service 50c9f2
        # If DOXYGEN environment variable is not found, the directory is
Packit Service 50c9f2
        # determined from the path of the script.
Packit Service 50c9f2
        doxy_default = os.path.join(self.script_path, '..')
Packit Service 50c9f2
        self.doxy_path = os.path.abspath(os.getenv('DOXYGEN', doxy_default))
Packit Service 50c9f2

Packit Service 50c9f2
        # Get the explicit arguments of the script.
Packit Service 50c9f2
        self.script_argLst = sys.argv[1:]
Packit Service 50c9f2

Packit Service 50c9f2
        # Build the path names based on the Doxygen's root knowledge.
Packit Service 50c9f2
        self.doc_path = os.path.join(self.doxy_path, 'doc')
Packit Service 50c9f2
        self.src_path = os.path.join(self.doxy_path, 'src')
Packit Service 50c9f2

Packit Service 50c9f2
        # Create the empty dictionary for Transl object identified by the
Packit Service 50c9f2
        # class identifier of the translator.
Packit Service 50c9f2
        self.__translDic = {}
Packit Service 50c9f2

Packit Service 50c9f2
        # Create the None dictionary of required methods. The key is the
Packit Service 50c9f2
        # unified prototype, the value is the full prototype. Set inside
Packit Service 50c9f2
        # the self.__build().
Packit Service 50c9f2
        self.requiredMethodsDic = None
Packit Service 50c9f2

Packit Service 50c9f2
        # Create the empty dictionary that says what method is implemented
Packit Service 50c9f2
        # by what adapter.
Packit Service 50c9f2
        self.adaptMethodsDic = {}
Packit Service 50c9f2

Packit Service 50c9f2
        # The last modification time will capture the modification of this
Packit Service 50c9f2
        # script, of the translator.h, of the translator_adapter.h (see the
Packit Service 50c9f2
        # self.__build() for the last two) of all the translator_xx.h files
Packit Service 50c9f2
        # and of the template for generating the documentation. So, this
Packit Service 50c9f2
        # time can be compared with modification time of the generated
Packit Service 50c9f2
        # documentation to decide, whether the doc should be re-generated.
Packit Service 50c9f2
        self.lastModificationTime = os.path.getmtime(self.script)
Packit Service 50c9f2

Packit Service 50c9f2
        # Set the names of the translator report text file, of the template
Packit Service 50c9f2
        # for generating "Internationalization" document, for the generated
Packit Service 50c9f2
        # file itself, and for the maintainers list.
Packit Service 50c9f2
        self.translatorReportFileName = 'translator_report.txt'
Packit Service 50c9f2
        self.maintainersFileName = 'maintainers.txt'
Packit Service 50c9f2
        self.languageTplFileName = 'language.tpl'
Packit Service 50c9f2
        self.languageDocFileName = 'language.doc'
Packit Service 50c9f2

Packit Service 50c9f2
        # The information about the maintainers will be stored
Packit Service 50c9f2
        # in the dictionary with the following name.
Packit Service 50c9f2
        self.__maintainersDic = None
Packit Service 50c9f2

Packit Service 50c9f2
        # Define the other used structures and variables for information.
Packit Service 50c9f2
        self.langLst = None                   # including English based
Packit Service 50c9f2
        self.supportedLangReadableStr = None  # coupled En-based as a note
Packit Service 50c9f2
        self.numLang = None                   # excluding coupled En-based
Packit Service 50c9f2
        self.doxVersion = None                # Doxygen version
Packit Service 50c9f2

Packit Service 50c9f2
        # Build objects where each one is responsible for one translator.
Packit Service 50c9f2
        self.__build()
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def __build(self):
Packit Service 50c9f2
        """Find the translator files and build the objects for translators."""
Packit Service 50c9f2

Packit Service 50c9f2
        # The translator.h must exist (the Transl object will check it),
Packit Service 50c9f2
        # create the object for it and let it build the dictionary of
Packit Service 50c9f2
        # required methods.
Packit Service 50c9f2
        tr = Transl(os.path.join(self.src_path, 'translator.h'), self)
Packit Service 50c9f2
        self.requiredMethodsDic = tr.collectPureVirtualPrototypes()
Packit Service 50c9f2
        tim = tr.getmtime()
Packit Service 50c9f2
        if tim > self.lastModificationTime:
Packit Service 50c9f2
            self.lastModificationTime = tim
Packit Service 50c9f2

Packit Service 50c9f2
        # The translator_adapter.h must exist (the Transl object will check it),
Packit Service 50c9f2
        # create the object for it and store the reference in the dictionary.
Packit Service 50c9f2
        tr = Transl(os.path.join(self.src_path, 'translator_adapter.h'), self)
Packit Service 50c9f2
        self.adaptMethodsDic = tr.collectAdapterPrototypes()
Packit Service 50c9f2
        tim = tr.getmtime()
Packit Service 50c9f2
        if tim > self.lastModificationTime:
Packit Service 50c9f2
            self.lastModificationTime = tim
Packit Service 50c9f2

Packit Service 50c9f2
        # Create the list of the filenames with language translator sources.
Packit Service 50c9f2
        # If the explicit arguments of the script were typed, process only
Packit Service 50c9f2
        # those files.
Packit Service 50c9f2
        if self.script_argLst:
Packit Service 50c9f2
            lst = ['translator_' + x + '.h' for x in self.script_argLst]
Packit Service 50c9f2
            for fname in lst:
Packit Service 50c9f2
                if not os.path.isfile(os.path.join(self.src_path, fname)):
Packit Service 50c9f2
                    sys.stderr.write("\a\nFile '%s' not found!\n" % fname)
Packit Service 50c9f2
                    sys.exit(1)
Packit Service 50c9f2
        else:
Packit Service 50c9f2
            lst = os.listdir(self.src_path)
Packit Service 50c9f2
            lst = [x for x in lst if x[:11] == 'translator_'
Packit Service 50c9f2
                                   and x[-2:] == '.h'
Packit Service 50c9f2
                                   and x != 'translator_adapter.h']
Packit Service 50c9f2

Packit Service 50c9f2
        # Build the object for the translator_xx.h files, and process the
Packit Service 50c9f2
        # content of the file. Then insert the object to the dictionary
Packit Service 50c9f2
        # accessed via classId.
Packit Service 50c9f2
        for fname in lst:
Packit Service 50c9f2
            fullname = os.path.join(self.src_path, fname)
Packit Service 50c9f2
            tr = Transl(fullname, self)
Packit Service 50c9f2
            tr.processing()
Packit Service 50c9f2
            assert(tr.classId != 'Translator')
Packit Service 50c9f2
            self.__translDic[tr.classId] = tr
Packit Service 50c9f2

Packit Service 50c9f2
        # Extract the global information of the processed info.
Packit Service 50c9f2
        self.__extractProcessedInfo()
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def __extractProcessedInfo(self):
Packit Service 50c9f2
        """Build lists and strings of the processed info."""
Packit Service 50c9f2

Packit Service 50c9f2
        # Build the auxiliary list with strings compound of the status,
Packit Service 50c9f2
        # readable form of the language, and classId.
Packit Service 50c9f2
        statLst = []
Packit Service 50c9f2
        for obj in list(self.__translDic.values()):
Packit Service 50c9f2
            assert(obj.classId != 'Translator')
Packit Service 50c9f2
            s = obj.status + '|' + obj.langReadable + '|' + obj.classId
Packit Service 50c9f2
            statLst.append(s)
Packit Service 50c9f2

Packit Service 50c9f2
        # Sort the list and extract the object identifiers (classId's) for
Packit Service 50c9f2
        # the up-to-date translators and English-based translators.
Packit Service 50c9f2
        statLst.sort()
Packit Service 50c9f2
        self.upToDateIdLst = [x.split('|')[2] for x in statLst if x[0] == '|']
Packit Service 50c9f2
        self.EnBasedIdLst = [x.split('|')[2] for x in statLst if x[:2] == 'En']
Packit Service 50c9f2

Packit Service 50c9f2
        # Reverse the list and extract the TranslatorAdapter based translators.
Packit Service 50c9f2
        statLst.reverse()
Packit Service 50c9f2
        self.adaptIdLst = [x.split('|')[2] for x in statLst if x[0].isdigit()]
Packit Service 50c9f2

Packit Service 50c9f2
        # Build the list of tuples that contain (langReadable, obj).
Packit Service 50c9f2
        # Sort it by readable name.
Packit Service 50c9f2
        self.langLst = []
Packit Service 50c9f2
        for obj in list(self.__translDic.values()):
Packit Service 50c9f2
            self.langLst.append((obj.langReadable, obj))
Packit Service 50c9f2

Packit Service 50c9f2
        self.langLst.sort(key=lambda x: x[0])
Packit Service 50c9f2

Packit Service 50c9f2
        # Create the list with readable language names. If the language has
Packit Service 50c9f2
        # also the English-based version, modify the item by appending
Packit Service 50c9f2
        # the note. Number of the supported languages is equal to the length
Packit Service 50c9f2
        # of the list.
Packit Service 50c9f2
        langReadableLst = []
Packit Service 50c9f2
        for name, obj in self.langLst:
Packit Service 50c9f2
            if obj.status == 'En': continue
Packit Service 50c9f2

Packit Service 50c9f2
            # Append the 'En' to the classId to possibly obtain the classId
Packit Service 50c9f2
            # of the English-based object. If the object exists, modify the
Packit Service 50c9f2
            # name for the readable list of supported languages.
Packit Service 50c9f2
            classIdEn = obj.classId + 'En'
Packit Service 50c9f2
            if classIdEn in self.__translDic:
Packit Service 50c9f2
                name += ' (+En)'
Packit Service 50c9f2

Packit Service 50c9f2
            # Append the result name of the language, possibly with note.
Packit Service 50c9f2
            langReadableLst.append(name)
Packit Service 50c9f2

Packit Service 50c9f2
        # Create the multiline string of readable language names,
Packit Service 50c9f2
        # with punctuation, wrapped to paragraph.
Packit Service 50c9f2
        if len(langReadableLst) == 1:
Packit Service 50c9f2
            s = langReadableLst[0]
Packit Service 50c9f2
        elif len(langReadableLst) == 2:
Packit Service 50c9f2
            s = ' and '.join(langReadableLst)
Packit Service 50c9f2
        else:
Packit Service 50c9f2
            s = ', '.join(langReadableLst[:-1]) + ', and '
Packit Service 50c9f2
            s += langReadableLst[-1]
Packit Service 50c9f2

Packit Service 50c9f2
        self.supportedLangReadableStr = fill(s + '.')
Packit Service 50c9f2

Packit Service 50c9f2
        # Find the number of the supported languages. The English based
Packit Service 50c9f2
        # languages are not counted if the non-English based also exists.
Packit Service 50c9f2
        self.numLang = len(self.langLst)
Packit Service 50c9f2
        for name, obj in self.langLst:
Packit Service 50c9f2
            if obj.status == 'En':
Packit Service 50c9f2
                classId = obj.classId[:-2]
Packit Service 50c9f2
                if classId in self.__translDic:
Packit Service 50c9f2
                    self.numLang -= 1    # the couple will be counted as one
Packit Service 50c9f2

Packit Service 50c9f2
        # Extract the version of Doxygen.
Packit Service 50c9f2
        f = xopen(os.path.join(self.doxy_path, 'VERSION'))
Packit Service 50c9f2
        self.doxVersion = f.readline().strip()
Packit Service 50c9f2
        f.close()
Packit Service 50c9f2

Packit Service 50c9f2
        # Update the last modification time.
Packit Service 50c9f2
        for tr in list(self.__translDic.values()):
Packit Service 50c9f2
            tim = tr.getmtime()
Packit Service 50c9f2
            if tim > self.lastModificationTime:
Packit Service 50c9f2
                self.lastModificationTime = tim
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def __getNoTrSourceFilesLst(self):
Packit Service 50c9f2
        """Returns the list of sources to be checked.
Packit Service 50c9f2

Packit Service 50c9f2
        All .cpp files and also .h files that do not declare or define
Packit Service 50c9f2
        the translator methods are included in the list. The file names
Packit Service 50c9f2
        are searched in doxygen/src directory.
Packit Service 50c9f2
        """
Packit Service 50c9f2
        files = []
Packit Service 50c9f2
        for item in os.listdir(self.src_path):
Packit Service 50c9f2
            # Split the bare name to get the extension.
Packit Service 50c9f2
            name, ext = os.path.splitext(item)
Packit Service 50c9f2
            ext = ext.lower()
Packit Service 50c9f2

Packit Service 50c9f2
            # Include only .cpp and .h files (case independent) and exclude
Packit Service 50c9f2
            # the files where the checked identifiers are defined.
Packit Service 50c9f2
            if ext == '.cpp' or (ext == '.h' and name.find('translator') == -1):
Packit Service 50c9f2
                fname = os.path.join(self.src_path, item)
Packit Service 50c9f2
                assert os.path.isfile(fname) # assumes no directory with the ext
Packit Service 50c9f2
                files.append(fname)          # full name
Packit Service 50c9f2
        return files
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def __removeUsedInFiles(self, fname, dic):
Packit Service 50c9f2
        """Removes items for method identifiers that are found in fname.
Packit Service 50c9f2

Packit Service 50c9f2
        The method reads the content of the file as one string and searches
Packit Service 50c9f2
        for all identifiers from dic. The identifiers that were found in
Packit Service 50c9f2
        the file are removed from the dictionary.
Packit Service 50c9f2

Packit Service 50c9f2
        Note: If more files is to be checked, the files where most items are
Packit Service 50c9f2
        probably used should be checked first and the resulting reduced
Packit Service 50c9f2
        dictionary should be used for checking the next files (speed up).
Packit Service 50c9f2
        """
Packit Service 50c9f2
        lst_in = list(dic.keys())   # identifiers to be searched for
Packit Service 50c9f2

Packit Service 50c9f2
        # Read content of the file as one string.
Packit Service 50c9f2
        assert os.path.isfile(fname)
Packit Service 50c9f2
        f = xopen(fname)
Packit Service 50c9f2
        cont = f.read()
Packit Service 50c9f2
        f.close()
Packit Service 50c9f2

Packit Service 50c9f2
        # Remove the items for identifiers that were found in the file.
Packit Service 50c9f2
        while lst_in:
Packit Service 50c9f2
            item = lst_in.pop(0)
Packit Service 50c9f2
            if cont.find(item) != -1:
Packit Service 50c9f2
                del dic[item]
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def __checkForNotUsedTrMethods(self):
Packit Service 50c9f2
        """Returns the dictionary of not used translator methods.
Packit Service 50c9f2

Packit Service 50c9f2
        The method can be called only after self.requiredMethodsDic has been
Packit Service 50c9f2
        built. The stripped prototypes are the values, the method identifiers
Packit Service 50c9f2
        are the keys.
Packit Service 50c9f2
        """
Packit Service 50c9f2
        # Build the dictionary of the required method prototypes with
Packit Service 50c9f2
        # method identifiers used as keys.
Packit Service 50c9f2
        trdic = {}
Packit Service 50c9f2
        for prototype in list(self.requiredMethodsDic.keys()):
Packit Service 50c9f2
            ri = prototype.split('(')[0]
Packit Service 50c9f2
            identifier = ri.split()[1].strip()
Packit Service 50c9f2
            trdic[identifier] = prototype
Packit Service 50c9f2

Packit Service 50c9f2
        # Build the list of source files where translator method identifiers
Packit Service 50c9f2
        # can be used.
Packit Service 50c9f2
        files = self.__getNoTrSourceFilesLst()
Packit Service 50c9f2

Packit Service 50c9f2
        # Loop through the files and reduce the dictionary of id -> proto.
Packit Service 50c9f2
        for fname in files:
Packit Service 50c9f2
            self.__removeUsedInFiles(fname, trdic)
Packit Service 50c9f2

Packit Service 50c9f2
        # Return the dictionary of not used translator methods.
Packit Service 50c9f2
        return trdic
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def __emails(self, classId):
Packit Service 50c9f2
        """Returns the list of maintainer emails.
Packit Service 50c9f2

Packit Service 50c9f2
        The method returns the list of e-mail addresses for the translator
Packit Service 50c9f2
        class, but only the addresses that were not marked as [xxx]."""
Packit Service 50c9f2
        lst = []
Packit Service 50c9f2
        for m in self.__maintainersDic[classId]:
Packit Service 50c9f2
            if not m[1].startswith('['):
Packit Service 50c9f2
                email = m[1]
Packit Service 50c9f2
                email = email.replace(' at ', '@') # Unmangle the mangled e-mail
Packit Service 50c9f2
                email = email.replace(' dot ', '.')
Packit Service 50c9f2
                lst.append(email)
Packit Service 50c9f2
        return lst
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def getBgcolorByReadableStatus(self, readableStatus):
Packit Service 50c9f2
        if readableStatus == 'up-to-date':
Packit Service 50c9f2
            color = '#ccffcc'    # green
Packit Service 50c9f2
        elif readableStatus.startswith('almost'):
Packit Service 50c9f2
            color = '#ffffff'    # white
Packit Service 50c9f2
        elif readableStatus.startswith('English'):
Packit Service 50c9f2
            color = '#ccffcc'    # green
Packit Service 50c9f2
        elif readableStatus.startswith('1.8'):
Packit Service 50c9f2
            color = '#ffffcc'    # yellow
Packit Service 50c9f2
        elif readableStatus.startswith('1.7'):
Packit Service 50c9f2
            color = '#ffcccc'    # pink
Packit Service 50c9f2
        elif readableStatus.startswith('1.6'):
Packit Service 50c9f2
            color = '#ffcccc'    # pink
Packit Service 50c9f2
        else:
Packit Service 50c9f2
            color = '#ff5555'    # red
Packit Service 50c9f2
        return color
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def generateTranslatorReport(self):
Packit Service 50c9f2
        """Generates the translator report."""
Packit Service 50c9f2

Packit Service 50c9f2
        output = os.path.join(self.doc_path, self.translatorReportFileName)
Packit Service 50c9f2

Packit Service 50c9f2
        # Open the textual report file for the output.
Packit Service 50c9f2
        f = xopen(output, 'w')
Packit Service 50c9f2

Packit Service 50c9f2
        # Output the information about the version.
Packit Service 50c9f2
        f.write('(' + self.doxVersion + ')\n\n')
Packit Service 50c9f2

Packit Service 50c9f2
        # Output the information about the number of the supported languages
Packit Service 50c9f2
        # and the list of the languages, or only the note about the explicitly
Packit Service 50c9f2
        # given languages to process.
Packit Service 50c9f2
        if self.script_argLst:
Packit Service 50c9f2
            f.write('The report was generated for the following, explicitly')
Packit Service 50c9f2
            f.write(' identified languages:\n\n')
Packit Service 50c9f2
            f.write(self.supportedLangReadableStr + '\n\n')
Packit Service 50c9f2
        else:
Packit Service 50c9f2
            f.write('Doxygen supports the following ')
Packit Service 50c9f2
            f.write(str(self.numLang))
Packit Service 50c9f2
            f.write(' languages (sorted alphabetically):\n\n')
Packit Service 50c9f2
            f.write(self.supportedLangReadableStr + '\n\n')
Packit Service 50c9f2

Packit Service 50c9f2
            # Write the summary about the status of language translators (how
Packit Service 50c9f2
            # many translators) are up-to-date, etc.
Packit Service 50c9f2
            s = 'Of them, %d translators are up-to-date, ' % len(self.upToDateIdLst)
Packit Service 50c9f2
            s += '%d translators are based on some adapter class, ' % len(self.adaptIdLst)
Packit Service 50c9f2
            s += 'and %d are English based.' % len(self.EnBasedIdLst)
Packit Service 50c9f2
            f.write(fill(s) + '\n\n')
Packit Service 50c9f2

Packit Service 50c9f2
        # The e-mail addresses of the maintainers will be collected to
Packit Service 50c9f2
        # the auxiliary file in the order of translator classes listed
Packit Service 50c9f2
        # in the translator report.
Packit Service 50c9f2
        fmail = xopen('mailto.txt', 'w')
Packit Service 50c9f2

Packit Service 50c9f2
        # Write the list of "up-to-date" translator classes.
Packit Service 50c9f2
        if self.upToDateIdLst:
Packit Service 50c9f2
            s = '''The following translator classes are up-to-date (sorted
Packit Service 50c9f2
                alphabetically). This means that they derive from the
Packit Service 50c9f2
                Translator class, they implement all %d of the required
Packit Service 50c9f2
                methods, and even minor problems were not spotted by the script:'''
Packit Service 50c9f2
            s = s % len(self.requiredMethodsDic)
Packit Service 50c9f2
            f.write('-' * 70 + '\n')
Packit Service 50c9f2
            f.write(fill(s) + '\n\n')
Packit Service 50c9f2

Packit Service 50c9f2
            mailtoLst = []
Packit Service 50c9f2
            for x in self.upToDateIdLst:
Packit Service 50c9f2
                obj = self.__translDic[x]
Packit Service 50c9f2
                if obj.note is None:
Packit Service 50c9f2
                    f.write('  ' + obj.classId + '\n')
Packit Service 50c9f2
                    mailtoLst.extend(self.__emails(obj.classId))
Packit Service 50c9f2

Packit Service 50c9f2
            fmail.write('up-to-date\n')
Packit Service 50c9f2
            fmail.write('; '.join(mailtoLst))
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
            # Write separately the list of "ALMOST up-to-date" translator classes.
Packit Service 50c9f2
            s = '''The following translator classes are ALMOST up-to-date (sorted
Packit Service 50c9f2
                alphabetically). This means that they derive from the
Packit Service 50c9f2
                Translator class, but there still may be some minor problems
Packit Service 50c9f2
                listed for them:'''
Packit Service 50c9f2
            f.write('\n' + ('-' * 70) + '\n')
Packit Service 50c9f2
            f.write(fill(s) + '\n\n')
Packit Service 50c9f2
            mailtoLst = []
Packit Service 50c9f2
            for x in self.upToDateIdLst:
Packit Service 50c9f2
                obj = self.__translDic[x]
Packit Service 50c9f2
                if obj.note is not None:
Packit Service 50c9f2
                    f.write('  ' + obj.classId + '\t-- ' + obj.note + '\n')
Packit Service 50c9f2
                    mailtoLst.extend(self.__emails(obj.classId))
Packit Service 50c9f2

Packit Service 50c9f2
            fmail.write('\n\nalmost up-to-date\n')
Packit Service 50c9f2
            fmail.write('; '.join(mailtoLst))
Packit Service 50c9f2

Packit Service 50c9f2
        # Write the list of the adapter based classes. The very obsolete
Packit Service 50c9f2
        # translators that derive from TranslatorEnglish are included.
Packit Service 50c9f2
        if self.adaptIdLst:
Packit Service 50c9f2
            s = '''The following translator classes need maintenance
Packit Service 50c9f2
                (the most obsolete at the end). The other info shows the
Packit Service 50c9f2
                estimation of Doxygen version when the class was last
Packit Service 50c9f2
                updated and number of methods that must be implemented to
Packit Service 50c9f2
                become up-to-date:'''
Packit Service 50c9f2
            f.write('\n' + '-' * 70 + '\n')
Packit Service 50c9f2
            f.write(fill(s) + '\n\n')
Packit Service 50c9f2

Packit Service 50c9f2
            # Find also whether some adapter classes may be removed.
Packit Service 50c9f2
            adaptMinVersion = '9.9.99'
Packit Service 50c9f2

Packit Service 50c9f2
            mailtoLst = []
Packit Service 50c9f2
            numRequired = len(self.requiredMethodsDic)
Packit Service 50c9f2
            for x in self.adaptIdLst:
Packit Service 50c9f2
                obj = self.__translDic[x]
Packit Service 50c9f2
                f.write('  %-30s' % obj.classId)
Packit Service 50c9f2
                f.write('  %-6s' % obj.readableStatus)
Packit Service 50c9f2
                numimpl = len(obj.missingMethods)
Packit Service 50c9f2
                pluralS = ''
Packit Service 50c9f2
                if numimpl > 1: pluralS = 's'
Packit Service 50c9f2
                percent = 100 * numimpl / numRequired
Packit Service 50c9f2
                f.write('\t%2d method%s to implement (%d %%)' % (
Packit Service 50c9f2
                        numimpl, pluralS, percent))
Packit Service 50c9f2
                if obj.note:
Packit Service 50c9f2
                    f.write('\n\tNote: ' + obj.note + '\n')
Packit Service 50c9f2
                f.write('\n')
Packit Service 50c9f2
                mailtoLst.extend(self.__emails(obj.classId)) # to maintainer
Packit Service 50c9f2

Packit Service 50c9f2
                # Check the level of required adapter classes.
Packit Service 50c9f2
                if obj.status != '0.0.00' and obj.status < adaptMinVersion:
Packit Service 50c9f2
                    adaptMinVersion = obj.status
Packit Service 50c9f2

Packit Service 50c9f2
            fmail.write('\n\ntranslator based\n')
Packit Service 50c9f2
            fmail.write('; '.join(mailtoLst))
Packit Service 50c9f2

Packit Service 50c9f2
            # Set the note if some old translator adapters are not needed
Packit Service 50c9f2
            # any more. Do it only when the script is called without arguments,
Packit Service 50c9f2
            # i.e. all languages were checked against the needed translator
Packit Service 50c9f2
            # adapters.
Packit Service 50c9f2
            if not self.script_argLst:
Packit Service 50c9f2
                to_remove = {}
Packit Service 50c9f2
                for version, adaptClassId in list(self.adaptMethodsDic.values()):
Packit Service 50c9f2
                    if version < adaptMinVersion:
Packit Service 50c9f2
                        to_remove[adaptClassId] = True
Packit Service 50c9f2

Packit Service 50c9f2
                if to_remove:
Packit Service 50c9f2
                    lst = list(to_remove.keys())
Packit Service 50c9f2
                    lst.sort()
Packit Service 50c9f2
                    plural = len(lst) > 1
Packit Service 50c9f2
                    note = 'Note: The adapter class'
Packit Service 50c9f2
                    if plural: note += 'es'
Packit Service 50c9f2
                    note += ' ' + ', '.join(lst)
Packit Service 50c9f2
                    if not plural:
Packit Service 50c9f2
                        note += ' is'
Packit Service 50c9f2
                    else:
Packit Service 50c9f2
                        note += ' are'
Packit Service 50c9f2
                    note += ' not used and can be removed.'
Packit Service 50c9f2
                    f.write('\n' + fill(note) + '\n')
Packit Service 50c9f2

Packit Service 50c9f2
        # Write the list of the English-based classes.
Packit Service 50c9f2
        if self.EnBasedIdLst:
Packit Service 50c9f2
            s = '''The following translator classes derive directly from the
Packit Service 50c9f2
                TranslatorEnglish. The class identifier has the suffix 'En'
Packit Service 50c9f2
                that says that this is intentional. Usually, there is also
Packit Service 50c9f2
                a non-English based version of the translator for
Packit Service 50c9f2
                the language:'''
Packit Service 50c9f2
            f.write('\n' + '-' * 70 + '\n')
Packit Service 50c9f2
            f.write(fill(s) + '\n\n')
Packit Service 50c9f2

Packit Service 50c9f2
            for x in self.EnBasedIdLst:
Packit Service 50c9f2
                obj = self.__translDic[x]
Packit Service 50c9f2
                f.write('  ' + obj.classId)
Packit Service 50c9f2
                f.write('\timplements %d methods' % len(obj.implementedMethods))
Packit Service 50c9f2
                if obj.note:
Packit Service 50c9f2
                    f.write(' -- ' + obj.note)
Packit Service 50c9f2
                f.write('\n')
Packit Service 50c9f2

Packit Service 50c9f2
        # Check for not used translator methods and generate warning if found.
Packit Service 50c9f2
        # The check is rather time consuming, so it is not done when report
Packit Service 50c9f2
        # is restricted to explicitly given language identifiers.
Packit Service 50c9f2
        if not self.script_argLst:
Packit Service 50c9f2
            dic = self.__checkForNotUsedTrMethods()
Packit Service 50c9f2
            if dic:
Packit Service 50c9f2
                s = '''WARNING: The following translator methods are declared
Packit Service 50c9f2
                    in the Translator class but their identifiers do not appear
Packit Service 50c9f2
                    in source files. The situation should be checked. The .cpp
Packit Service 50c9f2
                    files and .h files excluding the '*translator*' files
Packit Service 50c9f2
                    in doxygen/src directory were simply searched for occurrence
Packit Service 50c9f2
                    of the method identifiers:'''
Packit Service 50c9f2
                f.write('\n' + '=' * 70 + '\n')
Packit Service 50c9f2
                f.write(fill(s) + '\n\n')
Packit Service 50c9f2

Packit Service 50c9f2
                keys = list(dic.keys())
Packit Service 50c9f2
                keys.sort()
Packit Service 50c9f2
                for key in keys:
Packit Service 50c9f2
                    f.write('  ' + dic[key] + '\n')
Packit Service 50c9f2
                f.write('\n')
Packit Service 50c9f2

Packit Service 50c9f2
        # Write the details for the translators.
Packit Service 50c9f2
        f.write('\n' + '=' * 70)
Packit Service 50c9f2
        f.write('\nDetails for translators (classes sorted alphabetically):\n')
Packit Service 50c9f2

Packit Service 50c9f2
        cls = list(self.__translDic.keys())
Packit Service 50c9f2
        cls.sort()
Packit Service 50c9f2

Packit Service 50c9f2
        for c in cls:
Packit Service 50c9f2
            obj = self.__translDic[c]
Packit Service 50c9f2
            assert(obj.classId != 'Translator')
Packit Service 50c9f2
            obj.report(f)
Packit Service 50c9f2

Packit Service 50c9f2
        # Close the report file and the auxiliary file with e-mails.
Packit Service 50c9f2
        f.close()
Packit Service 50c9f2
        fmail.close()
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def __loadMaintainers(self):
Packit Service 50c9f2
        """Load and process the file with the maintainers.
Packit Service 50c9f2

Packit Service 50c9f2
        Fills the dictionary classId -> [(name, e-mail), ...]."""
Packit Service 50c9f2

Packit Service 50c9f2
        fname = os.path.join(self.doc_path, self.maintainersFileName)
Packit Service 50c9f2

Packit Service 50c9f2
        # Include the maintainers file to the group of files checked with
Packit Service 50c9f2
        # respect to the modification time.
Packit Service 50c9f2
        tim = os.path.getmtime(fname)
Packit Service 50c9f2
        if tim > self.lastModificationTime:
Packit Service 50c9f2
            self.lastModificationTime = tim
Packit Service 50c9f2

Packit Service 50c9f2
        # Process the content of the maintainers file.
Packit Service 50c9f2
        f = xopen(fname)
Packit Service 50c9f2
        inside = False  # inside the record for the language
Packit Service 50c9f2
        lineReady = True
Packit Service 50c9f2
        classId = None
Packit Service 50c9f2
        maintainersLst = None
Packit Service 50c9f2
        self.__maintainersDic = {}
Packit Service 50c9f2
        while lineReady:
Packit Service 50c9f2
            line = f.readline()            # next line
Packit Service 50c9f2
            lineReady = line != ''         # when eof, then line == ''
Packit Service 50c9f2

Packit Service 50c9f2
            line = line.strip()            # eof should also behave as separator
Packit Service 50c9f2
            if line != '' and line[0] == '%':    # skip the comment line
Packit Service 50c9f2
                continue
Packit Service 50c9f2

Packit Service 50c9f2
            if not inside:                 # if outside of the record
Packit Service 50c9f2
                if line != '':            # should be language identifier
Packit Service 50c9f2
                    classId = line
Packit Service 50c9f2
                    maintainersLst = []
Packit Service 50c9f2
                    inside = True
Packit Service 50c9f2
                # Otherwise skip empty line that do not act as separator.
Packit Service 50c9f2

Packit Service 50c9f2
            else:                          # if inside the record
Packit Service 50c9f2
                if line == '':            # separator found
Packit Service 50c9f2
                    inside = False
Packit Service 50c9f2
                else:
Packit Service 50c9f2
                    # If it is the first maintainer, create the empty list.
Packit Service 50c9f2
                    if classId not in self.__maintainersDic:
Packit Service 50c9f2
                        self.__maintainersDic[classId] = []
Packit Service 50c9f2

Packit Service 50c9f2
                    # Split the information about the maintainer and append
Packit Service 50c9f2
                    # the tuple. The address may be prefixed '[unreachable]'
Packit Service 50c9f2
                    # or whatever '[xxx]'. This will be processed later.
Packit Service 50c9f2
                    lst = line.split(':', 1)
Packit Service 50c9f2
                    assert(len(lst) == 2)
Packit Service 50c9f2
                    t = (lst[0].strip(), lst[1].strip())
Packit Service 50c9f2
                    self.__maintainersDic[classId].append(t)
Packit Service 50c9f2
        f.close()
Packit Service 50c9f2

Packit Service 50c9f2

Packit Service 50c9f2
    def generateLanguageDoc(self):
Packit Service 50c9f2
        """Checks the modtime of files and generates language.doc."""
Packit Service 50c9f2
        self.__loadMaintainers()
Packit Service 50c9f2

Packit Service 50c9f2
        # Check the last modification time of the template file. It is the
Packit Service 50c9f2
        # last file from the group that decide whether the documentation
Packit Service 50c9f2
        # should or should not be generated.
Packit Service 50c9f2
        fTplName = os.path.join(self.doc_path, self.languageTplFileName)
Packit Service 50c9f2
        tim = os.path.getmtime(fTplName)
Packit Service 50c9f2
        if tim > self.lastModificationTime:
Packit Service 50c9f2
            self.lastModificationTime = tim
Packit Service 50c9f2

Packit Service 50c9f2
        # If the generated documentation exists and is newer than any of
Packit Service 50c9f2
        # the source files from the group, do not generate it and quit
Packit Service 50c9f2
        # quietly.
Packit Service 50c9f2
        fDocName = os.path.join(self.doc_path, self.languageDocFileName)
Packit Service 50c9f2
        if os.path.isfile(fDocName):
Packit Service 50c9f2
            if os.path.getmtime(fDocName) > self.lastModificationTime:
Packit Service 50c9f2
                return
Packit Service 50c9f2

Packit Service 50c9f2
        # The document or does not exist or is older than some of the
Packit Service 50c9f2
        # sources. It must be generated again.
Packit Service 50c9f2
        #
Packit Service 50c9f2
        # Read the template of the documentation, and remove the first
Packit Service 50c9f2
        # attention lines.
Packit Service 50c9f2
        f = xopen(fTplName)
Packit Service 50c9f2
        doctpl = f.read()
Packit Service 50c9f2
        f.close()
Packit Service 50c9f2

Packit Service 50c9f2
        pos = doctpl.find('/***')
Packit Service 50c9f2
        assert pos != -1
Packit Service 50c9f2
        doctpl = doctpl[pos:]
Packit Service 50c9f2

Packit Service 50c9f2
        # Fill the tplDic by symbols that will be inserted into the
Packit Service 50c9f2
        # document template.
Packit Service 50c9f2
        tplDic = {}
Packit Service 50c9f2

Packit Service 50c9f2
        s = ('Do not edit this file. It was generated by the %s script.\n' +\
Packit Service 50c9f2
             ' * Edit the %s and %s files instead.') % (
Packit Service 50c9f2
             self.script_name, self.languageTplFileName, self.maintainersFileName)
Packit Service 50c9f2
        tplDic['editnote'] = s
Packit Service 50c9f2

Packit Service 50c9f2
        tplDic['doxVersion'] = self.doxVersion
Packit Service 50c9f2
        tplDic['supportedLangReadableStr'] = self.supportedLangReadableStr
Packit Service 50c9f2
        tplDic['translatorReportFileName'] = self.translatorReportFileName
Packit Service 50c9f2

Packit Service 50c9f2
        ahref = '
Packit Service 50c9f2
        ahref += '"\n>doxygen/doc/'  + self.translatorReportFileName
Packit Service 50c9f2
        ahref += ''
Packit Service 50c9f2
        tplDic['translatorReportLink'] = ahref
Packit Service 50c9f2
        tplDic['numLangStr'] = str(self.numLang)
Packit Service 50c9f2

Packit Service 50c9f2
        # Define templates for HTML table parts of the documentation.
Packit Service 50c9f2
        htmlTableTpl = '''\
Packit Service 50c9f2
            \\htmlonly
Packit Service 50c9f2
			

Packit Service 50c9f2
            
Packit Service 50c9f2
            
Packit Service 50c9f2
            
Packit Service 50c9f2
              
Packit Service 50c9f2
              
Packit Service 50c9f2
              <font size="+1" color="#ffffff"> Language </font>
Packit Service 50c9f2
              <font size="+1" color="#ffffff"> Maintainer </font>
Packit Service 50c9f2
              <font size="+1" color="#ffffff"> Contact address </font>
Packit Service 50c9f2
                      <font size="-2" color="#ffffff">(replace the at and dot)</font>
Packit Service 50c9f2
              <font size="+1" color="#ffffff"> Status </font>
Packit Service 50c9f2
              
Packit Service 50c9f2
              
Packit Service 50c9f2
            %s
Packit Service 50c9f2
              
Packit Service 50c9f2
              
Packit Service 50c9f2
            
Packit Service 50c9f2
            
Packit Service 50c9f2
            
Packit Service 50c9f2
			

Packit Service 50c9f2
            \\endhtmlonly
Packit Service 50c9f2
            '''
Packit Service 50c9f2
        htmlTableTpl = textwrap.dedent(htmlTableTpl)
Packit Service 50c9f2
        htmlTrTpl = '\n  %s\n  '
Packit Service 50c9f2
        htmlTdTpl = '\n    %s'
Packit Service 50c9f2
        htmlTdStatusColorTpl = '\n    %s'
Packit Service 50c9f2

Packit Service 50c9f2
        # Loop through transl objects in the order of sorted readable names
Packit Service 50c9f2
        # and add generate the content of the HTML table.
Packit Service 50c9f2
        trlst = []
Packit Service 50c9f2
        for name, obj in self.langLst:
Packit Service 50c9f2
            # Fill the table data elements for one row. The first element
Packit Service 50c9f2
            # contains the readable name of the language. Only the oldest
Packit Service 50c9f2
            # translator are colour marked in the language column. Less
Packit Service 50c9f2
            # "heavy" color is used (when compared with the Status column).
Packit Service 50c9f2
            if obj.readableStatus.startswith('1.4'):
Packit Service 50c9f2
                bkcolor = self.getBgcolorByReadableStatus('1.4')
Packit Service 50c9f2
            else:
Packit Service 50c9f2
                bkcolor = '#ffffff'
Packit Service 50c9f2

Packit Service 50c9f2
            lst = [ htmlTdStatusColorTpl % (bkcolor, obj.langReadable) ]
Packit Service 50c9f2

Packit Service 50c9f2
            # The next two elements contain the list of maintainers
Packit Service 50c9f2
            # and the list of their mangled e-mails. For English-based
Packit Service 50c9f2
            # translators that are coupled with the non-English based,
Packit Service 50c9f2
            # insert the 'see' note.
Packit Service 50c9f2
            mm = None  # init -- maintainer
Packit Service 50c9f2
            ee = None  # init -- e-mail address
Packit Service 50c9f2
            if obj.status == 'En':
Packit Service 50c9f2
                # Check whether there is the coupled non-English.
Packit Service 50c9f2
                classId = obj.classId[:-2]
Packit Service 50c9f2
                if classId in self.__translDic:
Packit Service 50c9f2
                    lang = self.__translDic[classId].langReadable
Packit Service 50c9f2
                    mm = 'see the %s language' % lang
Packit Service 50c9f2
                    ee = ' '
Packit Service 50c9f2

Packit Service 50c9f2
            if not mm and obj.classId in self.__maintainersDic:
Packit Service 50c9f2
                # Build a string of names separated by the HTML break element.
Packit Service 50c9f2
                # Special notes used instead of names are highlighted.
Packit Service 50c9f2
                lm = []
Packit Service 50c9f2
                for maintainer in self.__maintainersDic[obj.classId]:
Packit Service 50c9f2
                    name = maintainer[0]
Packit Service 50c9f2
                    if name.startswith('--'):
Packit Service 50c9f2
                        name = ''\
Packit Service 50c9f2
                               + name + ''
Packit Service 50c9f2
                    lm.append(name)
Packit Service 50c9f2
                mm = '
'.join(lm)
Packit Service 50c9f2

Packit Service 50c9f2
                # The marked addresses (they start with the mark '[unreachable]',
Packit Service 50c9f2
                # '[resigned]', whatever '[xxx]') will not be displayed at all.
Packit Service 50c9f2
                # Only the mark will be used instead.
Packit Service 50c9f2
                rexMark = re.compile('(?P<mark>\\[.*?\\])')
Packit Service 50c9f2
                le = []
Packit Service 50c9f2
                for maintainer in self.__maintainersDic[obj.classId]:
Packit Service 50c9f2
                    address = maintainer[1]
Packit Service 50c9f2
                    m = rexMark.search(address)
Packit Service 50c9f2
                    if m is not None:
Packit Service 50c9f2
                        address = ''\
Packit Service 50c9f2
                                  + m.group('mark') + ''
Packit Service 50c9f2
                    le.append(address)
Packit Service 50c9f2
                ee = '
'.join(le)
Packit Service 50c9f2

Packit Service 50c9f2
            # Append the maintainer and e-mail elements.
Packit Service 50c9f2
            lst.append(htmlTdTpl % mm)
Packit Service 50c9f2
            lst.append(htmlTdTpl % ee)
Packit Service 50c9f2

Packit Service 50c9f2
            # The last element contains the readable form of the status.
Packit Service 50c9f2
            bgcolor = self.getBgcolorByReadableStatus(obj.readableStatus)
Packit Service 50c9f2
            lst.append(htmlTdStatusColorTpl % (bgcolor, obj.readableStatus))
Packit Service 50c9f2

Packit Service 50c9f2
            # Join the table data to one table row.
Packit Service 50c9f2
            trlst.append(htmlTrTpl % (''.join(lst)))
Packit Service 50c9f2

Packit Service 50c9f2
        # Join the table rows and insert into the template.
Packit Service 50c9f2
        htmlTable = htmlTableTpl % (''.join(trlst))
Packit Service 50c9f2

Packit Service 50c9f2
        # Define templates for LaTeX table parts of the documentation.
Packit Service 50c9f2
        latexTableTpl = r'''
Packit Service 50c9f2
            \latexonly
Packit Service 50c9f2
            \footnotesize
Packit Service 50c9f2
            \begin{longtable}{|l|l|l|l|}
Packit Service 50c9f2
              \hline
Packit Service 50c9f2
              {\bf Language} & {\bf Maintainer} & {\bf Contact address} & {\bf Status} \\
Packit Service 50c9f2
              \hline
Packit Service 50c9f2
            %s
Packit Service 50c9f2
              \hline
Packit Service 50c9f2
            \end{longtable}
Packit Service 50c9f2
            \normalsize
Packit Service 50c9f2
            \endlatexonly
Packit Service 50c9f2
            '''
Packit Service 50c9f2
        latexTableTpl = textwrap.dedent(latexTableTpl)
Packit Service 50c9f2
        latexLineTpl = '\n' + r'  %s & %s & {\tt\tiny %s} & %s \\'
Packit Service 50c9f2

Packit Service 50c9f2
        # Loop through transl objects in the order of sorted readable names
Packit Service 50c9f2
        # and add generate the content of the LaTeX table.
Packit Service 50c9f2
        trlst = []
Packit Service 50c9f2
        for name, obj in self.langLst:
Packit Service 50c9f2
            # For LaTeX, more maintainers for the same language are
Packit Service 50c9f2
            # placed on separate rows in the table.  The line separator
Packit Service 50c9f2
            # in the table is placed explicitly above the first
Packit Service 50c9f2
            # maintainer. Prepare the arguments for the LaTeX row template.
Packit Service 50c9f2
            maintainers = []
Packit Service 50c9f2
            if obj.classId in self.__maintainersDic:
Packit Service 50c9f2
                maintainers = self.__maintainersDic[obj.classId]
Packit Service 50c9f2

Packit Service 50c9f2
            lang = obj.langReadable
Packit Service 50c9f2
            maintainer = None  # init
Packit Service 50c9f2
            email = None       # init
Packit Service 50c9f2
            if obj.status == 'En':
Packit Service 50c9f2
                # Check whether there is the coupled non-English.
Packit Service 50c9f2
                classId = obj.classId[:-2]
Packit Service 50c9f2
                if classId in self.__translDic:
Packit Service 50c9f2
                    langNE = self.__translDic[classId].langReadable
Packit Service 50c9f2
                    maintainer = 'see the %s language' % langNE
Packit Service 50c9f2
                    email = '~'
Packit Service 50c9f2

Packit Service 50c9f2
            if not maintainer and (obj.classId in self.__maintainersDic):
Packit Service 50c9f2
                lm = [ m[0] for m in self.__maintainersDic[obj.classId] ]
Packit Service 50c9f2
                maintainer = maintainers[0][0]
Packit Service 50c9f2
                email = maintainers[0][1]
Packit Service 50c9f2

Packit Service 50c9f2
            status = obj.readableStatus
Packit Service 50c9f2

Packit Service 50c9f2
            # Use the template to produce the line of the table and insert
Packit Service 50c9f2
            # the hline plus the constructed line into the table content.
Packit Service 50c9f2
            # The underscore character must be escaped.
Packit Service 50c9f2
            trlst.append('\n  \\hline')
Packit Service 50c9f2
            s = latexLineTpl % (lang, maintainer, email, status)
Packit Service 50c9f2
            s = s.replace('_', '\\_')
Packit Service 50c9f2
            trlst.append(s)
Packit Service 50c9f2

Packit Service 50c9f2
            # List the other maintainers for the language. Do not set
Packit Service 50c9f2
            # lang and status for them.
Packit Service 50c9f2
            lang = '~'
Packit Service 50c9f2
            status = '~'
Packit Service 50c9f2
            for m in maintainers[1:]:
Packit Service 50c9f2
                maintainer = m[0]
Packit Service 50c9f2
                email = m[1]
Packit Service 50c9f2
                s = latexLineTpl % (lang, maintainer, email, status)
Packit Service 50c9f2
                s = s.replace('_', '\\_')
Packit Service 50c9f2
                trlst.append(s)
Packit Service 50c9f2

Packit Service 50c9f2
        # Join the table lines and insert into the template.
Packit Service 50c9f2
        latexTable = latexTableTpl % (''.join(trlst))
Packit Service 50c9f2

Packit Service 50c9f2
        # Put the HTML and LaTeX parts together and define the dic item.
Packit Service 50c9f2
        tplDic['informationTable'] = htmlTable + '\n' + latexTable
Packit Service 50c9f2

Packit Service 50c9f2
        # Insert the symbols into the document template and write it down.
Packit Service 50c9f2
        f = xopen(fDocName, 'w')
Packit Service 50c9f2
        f.write(doctpl % tplDic)
Packit Service 50c9f2
        f.close()
Packit Service 50c9f2

Packit Service 50c9f2
if __name__ == '__main__':
Packit Service 50c9f2

Packit Service 50c9f2
    # The Python 2.6+ or 3.3+ is required.
Packit Service 50c9f2
    major = sys.version_info[0]
Packit Service 50c9f2
    minor = sys.version_info[1]
Packit Service 50c9f2
    if (major == 2 and minor < 6) or (major == 3 and minor < 0):
Packit Service 50c9f2
        print('Python 2.6+ or Python 3.0+ are required for the script')
Packit Service 50c9f2
        sys.exit(1)
Packit Service 50c9f2

Packit Service 50c9f2
    # The translator manager builds the Transl objects, parses the related
Packit Service 50c9f2
    # sources, and keeps them in memory.
Packit Service 50c9f2
    trMan = TrManager()
Packit Service 50c9f2

Packit Service 50c9f2
    # Process the Transl objects and generate the output files.
Packit Service 50c9f2
    trMan.generateLanguageDoc()
Packit Service 50c9f2
    trMan.generateTranslatorReport()