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

📄 mkclass.py

📁 convert C programs for use in C++ compiler environment
💻 PY
字号:
#!/usr/bin/env python

"""
     Make Class
     C to C++ tools (c) 2001 by D.G. Sureau

     This tools transforms C header files
     into C++ files, each holding a C++ class declaration.

     You may change the class name before to run mkcpp.py,
     this is specially required if a function has the same
     identifier that the class.

     Header files that have not corresponding .c source
     are ignored (they will be further copied as .hpp files).

     Processing:
     - Only .hpp files are processed. They are created by
       the mkheader.py script.
     - A Class is created with the name of the file.
     - Functions' declaration becomes methods' declaration.
     - Variables declared as static remain global variables.
       (This is a convention from mine.)
       The "static" modifier is no longer useful for global
       variables and removed.
     - Other C variables become attributes of the C++ class.


    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

"""


import os
import string
import wstring
import lexer
import re
import sys
import pattern


FALSE = 0
TRUE = 1

# Process an old header file and make a new one

def processheader(headername):        # Old header, .h or .hpp
 global classname

 node, dummy = os.path.splitext(headername)
 hpath  = node + ".hpp"                # Path of the new header .hpp
 dummy, classname = os.path.split(node)
 hname = classname + ".hpp"            # Name of the new header

 print "mkclass - processing" , headername

 # Reading the file and removing end of file code if exists

 header = []

 if os.path.exists(headername):
   hfile = open(headername, "rb")
   header = hfile.readlines()
   hfile.close

 # Removing EOF   0x1a  ctrl-z is presents
 if len(header) != 0:
   l = header[-1]
   l = wstring.strip(l)
   if l < ' ':       
     header = header[:-1]

 tmpheader = []     # For rebuilding the file
 sttname = ""
 COMMENT = FALSE    # This flag is true inside a multiline comment
 INSDEF = FALSE     # This one inside a define declaration
 INSBLK = FALSE     # This one inside a compound block
 INSSTT = FALSE     # this one inside a struct decl.
 INSTYP = FALSE     # this one inside a typedef decl.
 TYPSTT = FALSE     # inside a typedef of struct or enum

 # The first loop copies all defines, multiline macros, blocks
 # plus static vars and function

 for o in header:
  line = o
  if line == os.linesep: continue
  line = wstring.chop(line)

  # If we are inside a comment block, skip it
  if not COMMENT: COMMENT = lexer.opencomment(line)
  if COMMENT:
    COMMENT = lexer.closecomment(line)
    continue

  # macro statements are memorized
  if not INSDEF: INSDEF = lexer.opendef(line)
  if INSDEF:
    #print "opend def", line
    tmpheader.append(line)
    INSDEF = lexer.closedef(line)
    continue

  # instances of enum, struct are outside class
  if lexer.recordinstance(line):
    #print "record", line
    tmpheader.append(line)
    continue

  # Processing simple typedef
  if lexer.newtype(line):
    name = lexer.lastword(line)
    if name is None:
      print "Error no name in", line
    else:
      lexer.types.append(name)
      #print "typedef:", name
      #print "line", line
    tmpheader.append(line)
    continue

  # processing typdef of struct
  if not TYPSTT:
    if lexer.typedefstruct(line):
      TYPSTT = lexer.opentypedef(line)
      if TYPSTT:
        #print "inside typedef of struct", line
        name = None
        if lexer.typelevel == 0:    # first line
          name = lexer.getident(line)
        if name != None:
          lexer.types.append(name)
          lexer.typstruct.append(name)
          #print "new type 1:", name,  lexer.typstruct, line
  if TYPSTT:
    tmpheader.append(line)
    TYPSTT = lexer.closetypedef(line)
    if not TYPSTT:
      name = lexer.typename(line)
      if name != None:
        lexer.types.append(name)
        lexer.typstruct.append(name)
        #print "new type 2:" ,name, lexer.typstruct, line
    continue


  # processing compound typedef
  if not INSTYP:
    INSTYP = lexer.opentypedef(line)
    if INSTYP:
      #print "inside typedef", line
      name = None
      if lexer.typelevel == 0:    # first line
        name = lexer.getident(line)
      if name != None:
        lexer.types.append(name)
        #print "new type 3:", name, line
  if INSTYP:
    tmpheader.append(line)
    INSTYP = lexer.closetypedef(line)
    if not INSTYP:
      name = lexer.typename(line)
      if name != None:
        lexer.types.append(name)
        #lexer.typstruct.append(name)
        #print "new type 4:" ,name, line
    continue

  # structs declarations and instances are kept outside class
  # as I consider they are ancestors of classes and objects

  if not INSSTT:
    INSSTT = lexer.openstruct(line)       # test for start of struct
    if INSSTT:                             # found
      #print "inside struct", line
      name = None
      if lexer.structlevel == 0:
        name = lexer.structname(line)     # get name
      if name != None:
        lexer.types.append(name)          # add to types for good parsing
        lexer.typstruct.append(name)
        #print "new type 5:", name
        #print "line", line
  if INSSTT:                               # always inside struct
    INSSTT = lexer.closestruct(line)      # test for end
    tmpheader.append(line)
    continue

  # Define are memorized

  if lexer.isdefine(line):
    tmpheader.append(line)
    continue

  # instances of typedef of struct are outside the class also
  # static vars remain global and are added to this list
  # the static modifier should be removed for C++

  if lexer.isvardecl(line):
    #print "pass I - isvardecl", line
    if lexer.isglobal(line):
      line = lexer.removeglobal(line)
      tmpheader.append(lexer.addextern(line))
      #print "global added", lexer.addextern(line)
      continue
    if lexer.istypstruct(line):
      tmpheader.append(line)
      continue

  # static function added to list
  if lexer.isglobal(line):
    if lexer.isprototype(line):
       tmpheader.append(line)


 # end of for

# Second pass

 tmpheader.append("")
 tmpheader.append("class " + classname)
 tmpheader.append("{")
 tmpheader.append("public:")

 COMMENT = FALSE
 INSDEF  = FALSE
 INSBLK  = FALSE
 INSSTT  = FALSE
 INSTYP  = FALSE
 INUNION = FALSE

 # The second loop build a class and
 # copies all variables, functions, comments

 for o in header:
   line = wstring.chop(o)
   if line == None: break

   # Empty lines are kept
   if wstring.strip(line) == "":
     tmpheader.append("")
     continue

   # If we enter a comment block, append it and process other code

   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
         tmpheader.append(line)
         continue
   # Inside comment, this is 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)
       tmpheader.append(line[:i+2])
       line = line[i + 2:]                 # Keeping the code is exists

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

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

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

   if lexer.isdefine(line): continue

   # struct declaration  are now ignored

   if not INSSTT: INSSTT = lexer.openstruct(line)
   if INSSTT:                             # inside block
     sttname = ""
     #print "(inside struct)", line
     #if lexer.structlevel == 0:          # start or decl.
     #  name = lexer.structname(line)     # get name of structure
     #  if name != None: sttname = name
       #print "structname", sttname
     INSSTT = lexer.closestruct(line)    # end of block?
     # if INSSTT: continue                 
     continue                             # while in struct continue


   # typedef are now ignored
   if not INSTYP: INSTYP = lexer.opentypedef(line)
   if INSTYP:
     #print "(in typedef)", line
     INSTYP = lexer.closetypedef(line)
     continue

   # union are stored without change

   if not INUNION:
      INUNION = lexer.openunion(line)
   if INUNION:
     #print "in union", line
     INUNION = lexer.closeunion(line)
     tmpheader.append(line)
     continue

   #print "(mkclass, test for func or var)", line

   # prototype is kept, remove extern if present
   if lexer.isprototype(line):
     if lexer.isglobal(line):
       continue
     line = lexer.removextern(line)
     pass
   elif lexer.isvardecl(line):
     # static vars remain global in C++ (convention)
     #print "pass II - var", line
     if lexer.isglobal(line):
       #print "global, pass"
       continue
     # ignore an instance of struct
     if lexer.istypstruct(line):
       #print "mkclass (detect inst. of typedef struct)", line
       continue   # "struct" found
     # ignore an user's type of struct
     name = lexer.getident(line)
     #print "getident", name
     if name is None: continue
     if name in lexer.typstruct:
        #print "in struct", name
        continue
     # normal variable becomes attribute
     # inside class, remove "extern"
     line = lexer.removextern(line)
     #print "mkclass (new line):", line
   else: pass

   tmpheader.append(line)
   #print line
 # End of loop

 tmpheader.append("};")

 # Creating the new C++ header file with .hpp extension

 nh = open(hpath, "wb")
 for str in tmpheader:
  nh.write(str + "\n")
 nh.write("\n")
 nh.close()
 print "class", classname, "created into", hname


# --------- Main

def main():
 global shortened

 argnum = len(sys.argv)
 if argnum != 2:
  print "Make Class - C to C++ tools - Scriptet.com"
  print "Make a class from a .cpp header file: a file = a class"
  print "Usage:  mkclass headerfile"
  print "   or:  mkclass pattern   (uses the * wildcard code)"
  print "   or:  mkclass @filelist"
  sys.exit(0)

 cfile = sys.argv[1]
 hlist = []

 # Below, I make the list of headers

 if cfile[0] == '@':
   # Making a list from the project (a simple list of C source files)
   project = cfile[1:]
   print "mkclass - processing the list of files", project
   hlist = lexer.readproject(project)

 else:
   # Makeing a list of the single file
   if not '*' in cfile:
     hlist.append(cfile)
   else:
     # Make a list of files matching a pattern
     path, name = os.path.split(cfile)
     if path == "": path = os.getcwd()
     dlist = os.listdir(path)
     for fname in dlist:
       if not os.path.isfile(fname): continue
       if pattern.matching(name, fname, FALSE) == TRUE:
         f = os.path.join(path, fname)
         hlist.append(f)

 # Now processing each header file
 # filename with .c extension are converted to .h
 # otherwise processed as is

 for f in hlist:
   node, ext = os.path.splitext(f)
   if lexer.oscase(ext) == ".c":
     f = node + ".hpp"
   processheader(f)
 return 0

main()



⌨️ 快捷键说明

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