⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mkcpp.py

📁 convert C programs for use in C++ compiler environment
💻 PY
📖 第 1 页 / 共 3 页
字号:
#!/usr/bin/env python

"""
    Make C++
    C to C++ tools - (c) 2001 by D.G. Sureau
    Convert C sources to C++ ones, from classes in header files


    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    webmaster@scriptol.org
    http://www.scriptol.org

    This program requires a list of all headers files in the
    project, that you can create with allhead.py

    Processing:
    - Functions are defined now as methods.
    - Global variable are unchanged. The "static" modifier
      is removed for any variable in source file.
    - Variables previously defined without initializer
      in the C source, are removed from the C++ source.
    - Variable defined with an initializer are declared
      as static in the new header file. In the source,
      they get the class:: prefix.
    - Calls to functions become references to methods inside
      any function, but the class. prefix is not added inside
      other methods of the same class.
    - An instance of the class is defined into the source
      and declared into the header.
    - #include statements are updated for .hpp extensions.
    - Missing #include are inserted into the source, any function
      now refers to a class, whose the declaration is required.

"""

import os
import sys
import string
import wstring
import lexer

FALSE = 0
TRUE = 1

DEBUG = 0

counter = 0
linenumber = 0
lastinclude = 0    # Set position of the last include statement

vclass   = {}     # Dictionary of variables and their class
fclass   = {}     # Dictionary of functions and their class
dclass   = {}     # Dictionary of all above
locals   = []     # List of local idents of vars in the current block

included = []     # List of external included header files
omitted  = []     # List of external used classes (and therefore header)
allclasses = {}   # Dictionary of each class and file that contains it
allheaders = {}   # Dictionary of each header and class it contains
withoutpath = {}  # I need the dict above with filenames only

#---------------------------------- Step 1: make dictionaries

def build(classfile):
  global dclass
  global vclass
  global fclass
  global allclasses
  global allheaders
  global withoutpath

  #print "adding", classfile +  "'s members to dictionary"
  # Reading the header file
  f = open(classfile, 'r')
  lines = f.readlines()
  f.close()

  vlist = []     # List of members and methods
  classname = ""
  COMMENT  = FALSE
  INMACRO  = FALSE
  INRECORD = FALSE
  INCLASS  = FALSE

  for line in lines:
    line = wstring.chop(line)        # Remove line separators
    if wstring.strip(line) == "": continue

    if not INCLASS: INCLASS = lexer.openclass(line)
    if not INCLASS: continue
    INCLASS = lexer.closeclass(line)
    if not INCLASS: continue

    # Skip typedef and struct blocks
    if not INRECORD: INRECORD = lexer.openrecord(line)
    if INRECORD:
      INRECORD = lexer.closerecord(line)
      continue

    # If we are inside a macro or pragma block, skip it
    if not INMACRO: INMACRO = lexer.opendef(line)
    if INMACRO:
      INMACRO = lexer.closedef(line)
      continue

    words = string.split(line)
    if len(words) > 1:
      w = words[0]
      if w == "class":       # First of new class found
        if len(vlist) > 0:
          if classname == "":
            print "Error, members without class", vlist
            sys.exit(0)
        classname = words[1]
	if classname not in allclasses:
          allclasses[classname] = classfile
	  if classfile not in allheaders:  
            allheaders[classfile] = classname
            dummy, fname = os.path.split(classfile)
            withoutpath[fname] = classname
            print "class", classname, "in", classfile
        INCLASS = TRUE
        continue

    # Processing comment block
    if not COMMENT:
      if not lexer.embeddedcomment(line):
        COMMENT = lexer.opencomment(line)
      else:
        test = lexer.removecomment(line)
        if wstring.strip(test) == "": continue
    # Inside a multi-line comment
    if COMMENT:                             # Comment opened
      COMMENT = lexer.closecomment(line)    # Always inside comment?
      # End of multi-line comment
      if not COMMENT:                       # Terminator reached
        i = string.find(line, "*/")
        if i == -1:
          print "Error in parsing header"
          sys.exit(0)
        line = line[i + 2:]          # Keeping the code is exists

      # Start of multi-line comment
      if COMMENT:
        i = string.find(line, "/*")
        if i != -1:
          line = line[:i]
        else:
          continue

    line = wstring.strip(line)
    if line == "": continue

    # Define statement are ignored
    if line[0:7] == "#define": continue

    if lexer.isdeclaration(line):

      # Processing simple var declarations
      if lexer.isvardecl(line):
        nlist = lexer.splitvardecl(line)
        for n in nlist:
         vlist.append(n)
         n = lexer.getident(n)
         vclass[n] = classname
         dclass[n] = classname
         #print "append var", n
        continue

      # Processing function declaration
      if lexer.isprototype(line):
        f = lexer.prototype
        vlist.append(f)
        fkey = lexer.getident(f)
        fclass[fkey] = classname
        dclass[fkey] = classname
        #print "append function", f
        continue

  # End for


#-------------------- Step 2: move variables'name, transform functions

# Creates a method name from a function interface
# Input: interface of a function in a string with format: type function()
# Output: same line with the format: type class::function()

def setmethod(line):
  id = lexer.getident(line)
  # Is it in the dictionary of classes as a method?
  if not fclass.has_key(id):
     print "* method", id, "not in directory"
     return line, ""
  classname = fclass[id]

  # Is it a function?
  if not lexer.isfunction(line):
     print "Error,", line, "not a function"
     sys.exit(0)

  method = lexer.makemethod(line, classname)
  #print "line", line
  if DEBUG: print "method:", method
  method = lexer.removestatic(method)
  return method, classname    # Adding tail part, returning also class


# this is for the "main" function only

def getclass(name):
  # Is it in the dictionary of classes as a method?
  if not fclass.has_key(name):
     print "* method \"" + name + "\" not in directory"
     return ""
  classname = fclass[name]
  return classname


# Make a definition of member, from a variable

def setmember(line):
  id = lexer.getident(line)
  if not vclass.has_key(id):
     # either a global (static) variable or an error
     if not lexer.isstatic(line):
        print "* member", id, "not in directory"
     return line
  classname = vclass[id]

  member = lexer.makemethod(line, classname)
  #print "line", line
  j = string.find(member, "=")
  if j != -1:
    id = member[:j] + ";"
  else:
    id = member
  if DEBUG: print "definition:", id
  return member    # A definition of an attribute


# Change a C reference to a C++ one, for a line
# for methods and attributes (functions and variables)
# subline is the part of the line inside a block
# and without comment

def cppreference(line, subline, classname):
  global omitted

  start = string.find(line, subline)
  if start == -1:
     print "Error,", subline, "not found in", line
     sys.exit(0)
  end = start + len(subline)
  words = wstring.getidents(subline)     # get idents but labels
  #if "goto" in words: print words

  #already = []
  gotoflag = FALSE
  for id in words:
    if gotoflag:         # this id is skipped, it follows a goto
       gotoflag = FALSE
       #print id
       continue
    if id == "goto":
       #print id
       gotoflag = TRUE   # this will skip the following ident
       continue
    #if id in already: continue     # all replacements already done
    #already.append(id)
    #if not lexer.isident(id):  continue
    #print "id=", id, "old=", line
    if id in locals:
       #print id, "in locals"
       continue
    if dclass.has_key(id):
       cname = dclass[id]
       # if not inside a method of the class that is referenced
       if cname != classname:
         #print id, "in", cname
         newident = cname + "Obj" + '.' + id
         subline = wstring.replaceident(subline, id, newident, TRUE)

         if not cname in omitted:
            omitted.append(cname)
         #print ">>>", newident, cname, " (in" + classname +")"

  line = line[:start] + subline + line[end:]
  # if flag: print "ref updated", line
  return line


# Process local variables inside functions

def processlocals(blocklist):
 global locals

 COMMENT = FALSE      # This flag is true inside a comment
 INSBLK  = FALSE      # This one inside a function's body
 INSMAC  = FALSE

 #print "processlocals"

 for line in blocklist:
   line = wstring.chop(line)    # Removing line separators
   line = wstring.strip(line)   # Removing spaces (with better strip)
   if len(line) == 0: continue  # Empty line ignored

   # If we enter a comment block, append it and
   # process other code on the same line

   if not COMMENT:
     if not lexer.embeddedcomment(line):
       COMMENT = lexer.opencomment(line)
     else:
       test = lexer.removecomment(line)
       if wstring.strip(test) == "":       # Simple one-line comment
         continue
   # Inside a comment block if multi-lines
   if COMMENT:                             # Comment opened
     COMMENT = lexer.closecomment(line)   # Always inside comment?
     # End of multi-line comment
     if not COMMENT:                       # Terminator reached
       i = string.find(line, "*/")
       if i == -1:
         print "Error in parsing header"
         sys.exit(0)
       line = line[i + 2:]                 # Keeping the code is exists

     # Start of multi-line comment
     if COMMENT:
       i = string.find(line, "/*")
       if i != -1: line = line[:i]
       else:        continue

   if line is None: continue
   line = wstring.strip(line)
   if line == "": continue

   # If we are inside a macro or pragma block, skip it
   if not INSMAC: INSMAC = lexer.opendef(line)
   if INSMAC:
     INSMAC = lexer.closedef(line)
     continue

   # A declaration
   if lexer.islocalvar(line):
     nlist = []
     if lexer.multivar(line):
       nlist = lexer.splitvardef(line)
     else:
       nlist.append(line)
     for n in nlist:
       id = lexer.getident(n)
       locals.append(id)
       #print "is local", id
     continue
   if lexer.isarray(line):
     id = lexer.getident(line)
     locals.append(id)
     #print "is array local", id
     continue
   if lexer.isprototype(line):
     continue

   # end of the main for loop
 # end of processlocals

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -