- extra spaces are removed
authorAndrey Pavlenko <no@email>
Tue, 17 May 2011 12:52:07 +0000 (12:52 +0000)
committerAndrey Pavlenko <no@email>
Tue, 17 May 2011 12:52:07 +0000 (12:52 +0000)
- static class member modifier processing is fixed (moved from 'rettype' to 'func_modlist')

modules/python/src2/gen2.py
modules/python/src2/hdr_parser.py

index 5e2e0b1..a86af9b 100644 (file)
@@ -749,8 +749,9 @@ class PythonWrapperGenerator(object):
 if __name__ == "__main__":
     srcfiles = hdr_parser.opencv_hdr_list
     dstdir = "/Users/vp/tmp"
-    if len(sys.argv) > 2:
+    if len(sys.argv) > 1:
         dstdir = sys.argv[1]
+    if len(sys.argv) > 2:
         srcfiles = sys.argv[2:]
     generator = PythonWrapperGenerator()
     generator.gen(srcfiles, dstdir)
index 4924d34..2433253 100755 (executable)
@@ -20,7 +20,7 @@ where each element of <list_of_arguments> is 4-element list itself:
 [argtype, argname, default_value /* or "" if none */, <list_of_modifiers>]
 where the list of modifiers is yet another nested list of strings
    (currently recognized are "/O" for output argument, "/S" for static (i.e. class) methods
-   and "/A value" for the plain C arrays with counters) 
+   and "/A value" for the plain C arrays with counters)
 """
 
 class CppHeaderParser(object):
@@ -31,18 +31,18 @@ class CppHeaderParser(object):
         self.PROCESS_FLAG = 2
         self.PUBLIC_SECTION = 3
         self.CLASS_DECL = 4
-    
+
     def batch_replace(self, s, pairs):
         for before, after in pairs:
             s = s.replace(before, after)
         return s
-    
+
     def get_macro_arg(self, arg_str, npos):
         npos2 = npos3 = arg_str.find("(", npos)
         if npos2 < 0:
             print "Error: no arguments for the macro at %d" % (self.lineno,)
             sys.exit(-1)
-        balance = 1        
+        balance = 1
         while 1:
             t, npos3 = self.find_next_token(arg_str, ['(', ')'], npos3+1)
             if npos3 < 0:
@@ -54,9 +54,9 @@ class CppHeaderParser(object):
                 balance -= 1
                 if balance == 0:
                     break
-                    
+
         return arg_str[npos2+1:npos3].strip(), npos3
-    
+
     def parse_arg(self, arg_str, argno):
         """
         Parses <arg_type> [arg_name]
@@ -67,12 +67,12 @@ class CppHeaderParser(object):
         "arg" + str(argno), and then argno is incremented.
         """
         modlist = []
-        
+
         # pass 0: extracts the modifiers
         if "CV_OUT" in arg_str:
             modlist.append("/O")
             arg_str = arg_str.replace("CV_OUT", "")
-            
+
         if "CV_IN_OUT" in arg_str:
             modlist.append("/IO")
             arg_str = arg_str.replace("CV_IN_OUT", "")
@@ -82,25 +82,25 @@ class CppHeaderParser(object):
         if npos >= 0:
             isarray = True
             macro_arg, npos3 = self.get_macro_arg(arg_str, npos)
-            
+
             modlist.append("/A " + macro_arg)
             arg_str = arg_str[:npos] + arg_str[npos3+1:]
-            
+
         npos = arg_str.find("CV_CUSTOM_CARRAY")
         if npos >= 0:
             isarray = True
             macro_arg, npos3 = self.get_macro_arg(arg_str, npos)
-            
+
             modlist.append("/CA " + macro_arg)
             arg_str = arg_str[:npos] + arg_str[npos3+1:]
-        
-        arg_str = arg_str.strip()        
+
+        arg_str = arg_str.strip()
         word_start = 0
         word_list = []
         npos = -1
-        
-        #print self.lineno, ":\t", arg_str 
-        
+
+        #print self.lineno, ":\t", arg_str
+
         # pass 1: split argument type into tokens
         while 1:
             npos += 1
@@ -121,9 +121,9 @@ class CppHeaderParser(object):
         arg_type = ""
         arg_name = ""
         angle_stack = []
-        
+
         #print self.lineno, ":\t", word_list
-        
+
         # pass 2: decrypt the list
         wi = -1
         prev_w = ""
@@ -160,7 +160,7 @@ class CppHeaderParser(object):
             else:
                 arg_type += w
             prev_w = w
-        
+
         counter_str = ""
         add_star = False
         if ("[" in arg_name) and not ("operator" in arg_str):
@@ -177,24 +177,24 @@ class CppHeaderParser(object):
                 modlist.append("/A " + counter_str.strip())
             arg_name = arg_name[:p1]
             add_star = True
-        
+
         if not arg_name:
             if arg_type.startswith("operator"):
                 arg_type, arg_name = "", arg_type
             else:
                 arg_name = "arg" + str(argno)
                 argno += 1
-            
+
         while arg_type.endswith("_end_"):
             arg_type = arg_type[:-len("_end_")]
-            
+
         if add_star:
             arg_type += "*"
-        
+
         arg_type = self.batch_replace(arg_type, [("std::", ""), ("cv::", "")])
-    
+
         return arg_type, arg_name, modlist, argno
-        
+
     def parse_enum(self, decl_str):
         l = decl_str
         ll = l.split(",")
@@ -214,7 +214,7 @@ class CppHeaderParser(object):
                 prev_val = val = pv[1].strip()
             decl.append(["const " + self.get_dotted_name(pv[0].strip()), val, [], []])
         return decl
-        
+
     def parse_class_decl(self, decl_str):
         """
         Parses class/struct declaration start in the form:
@@ -234,7 +234,7 @@ class CppHeaderParser(object):
             macro_arg, npos3 = self.get_macro_arg(l, npos)
             modlist.append("=" + macro_arg)
             l = l[:npos] + l[npos3+1:]
-            
+
         l = self.batch_replace(l, [("CV_EXPORTS_W", ""), ("CV_EXPORTS", ""), ("public ", " "), ("::", ".")]).strip()
         ll = re.split(r'\s*[,:]?\s*', l)
         ll = [le for le in ll if le]
@@ -249,18 +249,18 @@ class CppHeaderParser(object):
             [~]<function_name>
             (<arg_type1> <arg_name1>[=<default_value1>] [, <arg_type2> <arg_name2>[=<default_value2>] ...])
             [const] {; | <function_body>}
-        
+
         Returns the function declaration entry:
-        [<function_name>, <rettype>, <the_list_of_argument_descriptions>] (see above)
+        [<func name>, <return value C-type>, <list of modifiers>, <list of arguments>] (see above)
         """
-        
+
         if not (("CV_EXPORTS_AS" in decl_str) or ("CV_EXPORTS_W" in decl_str) or \
             ("CV_WRAP" in decl_str) or ("CV_WRAP_AS" in decl_str)):
             return []
-        
+
         top = self.block_stack[-1]
         func_modlist = []
-        
+
         npos = decl_str.find("CV_EXPORTS_AS")
         if npos >= 0:
             arg, npos3 = self.get_macro_arg(decl_str, npos)
@@ -271,7 +271,7 @@ class CppHeaderParser(object):
             arg, npos3 = self.get_macro_arg(decl_str, npos)
             func_modlist.append("="+arg)
             decl_str = decl_str[:npos] + decl_str[npos3+1:]
-            
+
         # filter off some common prefixes, which are meaningless for Python wrappers.
         # note that we do not strip "static" prefix, which does matter;
         # it means class methods, not instance methods
@@ -283,7 +283,7 @@ class CppHeaderParser(object):
         if decl_str.startswith("static") and (context == "class" or context == "struct"):
             decl_str = decl_str[len("static"):].lstrip()
             static_method = True
-            
+
         args_begin = decl_str.find("(")
         if decl_str.startswith("CVAPI"):
             rtype_end = decl_str.find(")", args_begin+1)
@@ -295,7 +295,7 @@ class CppHeaderParser(object):
         if args_begin < 0:
             print "Error at %d: no args in '%s'" % (self.lineno, decl_str)
             sys.exit(-1)
-            
+
         decl_start = decl_str[:args_begin].strip()
         # handle operator () case
         if decl_start.endswith("operator"):
@@ -304,9 +304,9 @@ class CppHeaderParser(object):
                 print "Error at %d: no args in '%s'" % (self.lineno, decl_str)
                 sys.exit(-1)
             decl_start = decl_str[:args_begin].strip()
-            
+
         rettype, funcname, modlist, argno = self.parse_arg(decl_start, -1)
-                
+
         if argno >= 0:
             classname = top[1]
             if rettype == classname or rettype == "~" + classname:
@@ -314,7 +314,7 @@ class CppHeaderParser(object):
             else:
                 print "Error at %d. the function/method name is missing: '%s'" % (self.lineno, decl_start)
                 sys.exit(-1)
-        
+
         if ("::" in funcname) or funcname.startswith("~"):
             # if there is :: in function name (and this is in the header file),
             # it means, this is inline implementation of a class method.
@@ -322,9 +322,9 @@ class CppHeaderParser(object):
             # declaration.
             # Also, skip the destructors, as they are always wrapped
             return []
-        
+
         funcname = self.get_dotted_name(funcname)
-        
+
         arg_start = args_begin+1
         npos = arg_start-1
         balance = 1
@@ -333,7 +333,7 @@ class CppHeaderParser(object):
         args_decls = []
         args = []
         argno = 1
-        
+
         while balance > 0:
             npos += 1
             t, npos = self.find_next_token(decl_str, ["(", ")", ",", "<", ">"], npos)
@@ -350,7 +350,7 @@ class CppHeaderParser(object):
                 balance += 1
             if t == ")":
                 balance -= 1
-                
+
             if (t == "," and balance == 1 and angle_balance == 0) or balance == 0:
                 # process next function argument
                 a = decl_str[arg_start:npos].strip()
@@ -390,31 +390,31 @@ class CppHeaderParser(object):
                                                          ("OutputArrayOfArrays", "vector<Mat>"),
                                                          ("InputArray", "Mat"),
                                                          ("InputOutputArray", "Mat"),
-                                                         ("OutputArray", "Mat")]).strip()  
+                                                         ("OutputArray", "Mat")]).strip()
                     args.append([arg_type, arg_name, defval, modlist])
                 npos = arg_start-1
-        
+
         npos = decl_str.replace(" ", "").find("=0", npos)
         if npos >= 0:
             # skip pure virtual functions
             return []
-            
+
         if static_method:
-            rettype = " ".join([rettype, "/S"])
-               
+            func_modlist.append("/S")
+
         return [funcname, rettype, func_modlist, args]
 
     def get_dotted_name(self, name):
         """
         adds the dot-separated container class/namespace names to the bare function/class name, e.g. when we have
-        
+
         namespace cv {
         class A {
         public:
             f(int);
         };
         }
-        
+
         the function will convert "A" to "cv.A" and "f" to "cv.A.f".
         """
         if not self.block_stack:
@@ -430,24 +430,24 @@ class CppHeaderParser(object):
             if block_name:
                 n += block_name + "."
         return n + name
-        
-    def parse_stmt(self, stmt, end_token):   
+
+    def parse_stmt(self, stmt, end_token):
         """
         parses the statement (ending with ';' or '}') or a block head (ending with '{')
-        
+
         The function calls parse_class_decl or parse_func_decl when necessary. It returns
         <block_type>, <block_name>, <parse_flag>, <declaration>
         where the first 3 values only make sense for blocks (i.e. code blocks, namespaces, classes, enums and such)
         """
         stack_top = self.block_stack[-1]
         context = stack_top[self.BLOCK_TYPE]
-    
+
         stmt_type = ""
         if end_token == "{":
             stmt_type = "block"
-    
+
         if context == "block":
-            print "Error at %d: should not call parse_stmt inside blocks" % (self.lineno,) 
+            print "Error at %d: should not call parse_stmt inside blocks" % (self.lineno,)
             sys.exit(-1)
 
         if context == "class" or context == "struct":
@@ -463,11 +463,11 @@ class CppHeaderParser(object):
                         stack_top[self.PUBLIC_SECTION] = False
                     stmt = stmt[colon_pos+1:].strip()
                 break
-    
+
         # do not process hidden class members and template classes/functions
         if not stack_top[self.PUBLIC_SECTION] or stmt.startswith("template"):
             return stmt_type, "", False, None
-            
+
         if end_token == "{":
             if stmt.startswith("class") or stmt.startswith("struct"):
                 stmt_type = stmt.split()[0]
@@ -478,16 +478,16 @@ class CppHeaderParser(object):
                     if bases:
                         decl[1] = ": " + " ".join(bases)
                 return stmt_type, classname, True, decl
-            
+
             if stmt.startswith("enum"):
                 return "enum", "", True, None
-            
+
             if stmt.startswith("namespace"):
                 stmt_list = stmt.split()
                 return stmt_list[0], stmt_list[1], True, None
             if stmt.startswith("extern") and "\"C\"" in stmt:
                 return "namespace", "", True, None
-                
+
         if end_token == "}" and context == "enum":
             decl = self.parse_enum(stmt)
             return "enum", "", False, decl
@@ -495,7 +495,7 @@ class CppHeaderParser(object):
         if end_token == ";" and stmt.startswith("typedef"):
             # TODO: handle typedef's more intelligently
             return stmt_type, "", False, None
-        
+
         paren_pos = stmt.find("(")
         if paren_pos >= 0:
             # assume it's function or method declaration,
@@ -518,18 +518,18 @@ class CppHeaderParser(object):
                 var_list = stmt.split(",")
                 var_type, var_name1, modlist, argno = self.parse_arg(var_list[0], -1)
                 var_list = [var_name1] + [i.strip() for i in var_list[1:]]
-                
+
                 for v in var_list:
                     class_decl[3].append([var_type, v, "", var_modlist])
             return stmt_type, "", False, None
-        
+
         # something unknown
         return stmt_type, "", False, None
-    
+
     def find_next_token(self, s, tlist, p=0):
         """
         Finds the next token from the 'tlist' in the input 's', starting from position 'p'.
-        Returns the first occured token and its position, or ("", len(s)) when no token is found 
+        Returns the first occured token and its position, or ("", len(s)) when no token is found
         """
         token = ""
         tpos = len(s)
@@ -551,55 +551,55 @@ class CppHeaderParser(object):
         f = open(hname, "rt")
         linelist = list(f.readlines())
         f.close()
-    
+
         # states:
         SCAN = 0 # outside of a comment or preprocessor directive
         COMMENT = 1 # inside a multi-line comment
         DIRECTIVE = 2 # inside a multi-line preprocessor directive
-    
+
         state = SCAN
-    
+
         self.block_stack = [["file", hname, True, True, None]]
         block_head = ""
         self.lineno = 0
-    
+
         for l0 in linelist:
             self.lineno += 1
             #print self.lineno
-            
+
             l = l0.strip()
-        
+
             if state == SCAN and l.startswith("#"):
                 state = DIRECTIVE
                 # fall through to the if state == DIRECTIVE check
-        
+
             if state == DIRECTIVE:
                 if not l.endswith("\\"):
                     state = SCAN
                 continue
-            
+
             if state == COMMENT:
                 pos = l.find("*/")
                 if pos < 0:
                     continue
                 l = l[pos+2:]
                 state = SCAN
-        
+
             if state != SCAN:
                 print "Error at %d: invlid state = %d" % (self.lineno, state)
                 sys.exit(-1)
-            
+
             while 1:
                 token, pos = self.find_next_token(l, [";", "\"", "{", "}", "//", "/*"])
-            
+
                 if not token:
                     block_head += " " + l
                     break
-                
+
                 if token == "//":
                     block_head += " " + l[:pos]
                     break
-                
+
                 if token == "/*":
                     block_head += " " + l[:pos]
                     pos = l.find("*/", pos+2)
@@ -608,7 +608,7 @@ class CppHeaderParser(object):
                         break
                     l = l[pos+2:]
                     continue
-                
+
                 if token == "\"":
                     pos2 = pos + 1
                     while 1:
@@ -619,15 +619,15 @@ class CppHeaderParser(object):
                         if t2 == "\"":
                             break
                         pos2 += 2
-                    
+
                     block_head += " " + l[:pos2+1]
                     l = l[pos2+1:]
                     continue
-            
+
                 stmt = (block_head + " " + l[:pos]).strip()
                 stmt = " ".join(stmt.split()) # normalize the statement
                 stack_top = self.block_stack[-1]
-            
+
                 decl = None
                 if stack_top[self.PROCESS_FLAG]:
                     # even if stack_top[PUBLIC_SECTION] is False, we still try to process the statement,
@@ -641,26 +641,26 @@ class CppHeaderParser(object):
                             decls.append(decl)
                 else:
                     stmt_type, name, parse_flag = "block", "", False
-            
+
                 if token == "{":
                     if stmt_type == "class":
                         public_section = False
                     else:
-                        public_section = True    
+                        public_section = True
                     self.block_stack.append([stmt_type, name, parse_flag, public_section, decl])
-                
+
                 if token == "}":
                     if not self.block_stack:
                         print "Error at %d: the block stack is empty" % (self.lineno,)
                     self.block_stack[-1:] = []
                     if pos+1 < len(l) and l[pos+1] == ';':
                         pos += 1
-                
+
                 block_head = ""
                 l = l[pos+1:]
-            
+
         return decls
-        
+
     def print_decls(self, decls):
         """
         Prints the list of declarations, retrieived by the parse() method
@@ -668,7 +668,7 @@ class CppHeaderParser(object):
         for d in decls:
             print d[0], d[1], ";".join(d[2])
             for a in d[3]:
-                print "   ", a[0], a[1], a[2], 
+                print "   ", a[0], a[1], a[2],
                 if a[3]:
                     print "; ".join(a[3])
                 else:
@@ -676,7 +676,7 @@ class CppHeaderParser(object):
 
 if __name__ == '__main__':
     parser = CppHeaderParser()
-    decls = [] 
+    decls = []
     for hname in opencv_hdr_list:
         decls += parser.parse(hname)
     parser.print_decls(decls)