Browse Source

interrogate should support long long

David Rose 21 years ago
parent
commit
e2a27fabda

+ 7 - 2
direct/src/ffi/FFIOverload.py

@@ -20,6 +20,7 @@ AT_bool = 4
 AT_char = 5
 AT_char = 5
 AT_void = 6
 AT_void = 6
 AT_string = 7
 AT_string = 7
+AT_longlong = 8
 
 
 def cullOverloadedMethods(fullMethodDict):
 def cullOverloadedMethods(fullMethodDict):
     """
     """
@@ -65,6 +66,9 @@ def getTypeName(classTypeDesc, typeDesc):
             (typeDesc.atomicType == AT_double)):
             (typeDesc.atomicType == AT_double)):
             return 'types.FloatType'
             return 'types.FloatType'
 
 
+        elif ((typeDesc.atomicType == AT_longlong)):
+            return 'types.LongType'
+
         # Strings are treated as Python strings
         # Strings are treated as Python strings
         elif ((typeDesc.atomicType == AT_string)):
         elif ((typeDesc.atomicType == AT_string)):
             return 'types.StringType'
             return 'types.StringType'
@@ -416,8 +420,9 @@ class FFIMethodArgumentTree:
                     # Otherwise, we'll check the particular type of
                     # Otherwise, we'll check the particular type of
                     # the object.
                     # the object.
                     condition = '(isinstance(_args[' + `level` + '], ' + typeName + '))'
                     condition = '(isinstance(_args[' + `level` + '], ' + typeName + '))'
-                    # If it is looking for a float, make it accept an integer too
-                    if (typeName == 'types.FloatType'):
+                    # If it is looking for a float or a long, make it
+                    # accept an integer too
+                    if (typeName == 'types.FloatType' or typeName == 'types.LongType'):
                         condition += (' or (isinstance(_args[' + `level` + '], '
                         condition += (' or (isinstance(_args[' + `level` + '], '
                                       + 'types.IntType'
                                       + 'types.IntType'
                                       + '))')
                                       + '))')

+ 6 - 1
direct/src/ffi/FFISpecs.py

@@ -41,13 +41,18 @@ class FunctionSpecification:
                 typeName = FFIOverload.getTypeName(methodClass, typeDesc)
                 typeName = FFIOverload.getTypeName(methodClass, typeDesc)
 
 
                 # Special case:
                 # Special case:
-                # If it is looking for a float, accept an int as well
+                # If it is looking for a float or a long, accept an int as well
                 # C++ will cast it properly, and it is much more convenient
                 # C++ will cast it properly, and it is much more convenient
                 if (typeName == 'types.FloatType'):
                 if (typeName == 'types.FloatType'):
                     indent(file, nesting, 'assert((isinstance(' +
                     indent(file, nesting, 'assert((isinstance(' +
                            methodArgSpec.name + ', types.FloatType) or isinstance(' +
                            methodArgSpec.name + ', types.FloatType) or isinstance(' +
                            methodArgSpec.name + ', types.IntType)))\n')
                            methodArgSpec.name + ', types.IntType)))\n')
 
 
+                elif (typeName == 'types.LongType'):
+                    indent(file, nesting, 'assert((isinstance(' +
+                           methodArgSpec.name + ', types.LongType) or isinstance(' +
+                           methodArgSpec.name + ', types.IntType)))\n')
+
                 elif typeDesc.__class__ != FFITypes.PyObjectTypeDescriptor:
                 elif typeDesc.__class__ != FFITypes.PyObjectTypeDescriptor:
                     # Get the real return type (not derived)
                     # Get the real return type (not derived)
                     if ((not typeDesc.isNested) and
                     if ((not typeDesc.isNested) and

+ 1 - 0
direct/src/ffi/FFITypes.py

@@ -56,6 +56,7 @@ class BaseTypeDescriptor:
         # AT_char = 5
         # AT_char = 5
         # AT_void = 6
         # AT_void = 6
         # AT_string = 7
         # AT_string = 7
+        # AT_longlong = 8
         # By default this type is not atomic
         # By default this type is not atomic
         self.atomicType = 0
         self.atomicType = 0
 
 

+ 63 - 0
dtool/src/interrogate/interfaceMakerPythonObj.cxx

@@ -321,6 +321,9 @@ write_function_instance(ostream &out, int indent_level,
   string format_specifiers;
   string format_specifiers;
   string parameter_list;
   string parameter_list;
   vector_string pexprs;
   vector_string pexprs;
+  string extra_convert;
+  string extra_param_check;
+  string extra_cleanup;
 
 
   // Make one pass through the parameter list.  We will output a
   // Make one pass through the parameter list.  We will output a
   // one-line temporary variable definition for each parameter, while
   // one-line temporary variable definition for each parameter, while
@@ -371,6 +374,26 @@ write_function_instance(ostream &out, int indent_level,
       pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
       pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
       expected_params += "bool";
       expected_params += "bool";
 
 
+    } else if (TypeManager::is_unsigned_longlong(type)) {
+      out << "PyObject *" << param_name;
+      format_specifiers += "O";
+      parameter_list += ", &" + param_name;
+      extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
+      extra_param_check += "|| (" + param_name + "_long == NULL)";
+      pexpr_string = "PyLong_AsUnsignedLongLong(" + param_name + "_long)";
+      extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
+      expected_params += "long";
+
+    } else if (TypeManager::is_longlong(type)) {
+      out << "PyObject *" << param_name;
+      format_specifiers += "O";
+      parameter_list += ", &" + param_name;
+      extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
+      extra_param_check += "|| (" + param_name + "_long == NULL)";
+      pexpr_string = "PyLong_AsLongLong(" + param_name + "_long)";
+      extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
+      expected_params += "long";
+
     } else if (TypeManager::is_integer(type)) {
     } else if (TypeManager::is_integer(type)) {
       out << "int " << param_name;
       out << "int " << param_name;
       format_specifiers += "i";
       format_specifiers += "i";
@@ -417,6 +440,26 @@ write_function_instance(ostream &out, int indent_level,
     << "if (PyArg_ParseTuple(args, \"" << format_specifiers
     << "if (PyArg_ParseTuple(args, \"" << format_specifiers
     << "\"" << parameter_list << ")) {\n";
     << "\"" << parameter_list << ")) {\n";
 
 
+  if (!extra_convert.empty()) {
+    indent(out, indent_level + 3)
+      << extra_convert << "\n";
+  }
+
+  if (!extra_param_check.empty()) {
+    indent(out, indent_level + 4)
+      << "if (" << extra_param_check.substr(3) << ") {\n";
+    if (!extra_cleanup.empty()) {
+      indent(out, indent_level + 5)
+        << extra_cleanup << "\n";
+    }
+    indent(out, indent_level + 6)
+      << "PyErr_SetString(PyExc_TypeError, \"Invalid parameters.\");\n";
+    indent(out, indent_level + 6)
+      << "return (PyObject *)NULL;\n";
+    indent(out, indent_level + 4)
+      << "}\n";
+  }
+
   if (track_interpreter) {
   if (track_interpreter) {
     indent(out, indent_level + 4)
     indent(out, indent_level + 4)
       << "in_interpreter = 0;\n";
       << "in_interpreter = 0;\n";
@@ -438,6 +481,10 @@ write_function_instance(ostream &out, int indent_level,
       indent(out, indent_level + 4)
       indent(out, indent_level + 4)
         << "in_interpreter = 1;\n";
         << "in_interpreter = 1;\n";
     }
     }
+    if (!extra_cleanup.empty()) {
+      indent(out, indent_level + 3)
+        << extra_cleanup << "\n";
+    }
 
 
     return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
     return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
     test_assert(out, indent_level + 4);
     test_assert(out, indent_level + 4);
@@ -451,6 +498,10 @@ write_function_instance(ostream &out, int indent_level,
         indent(out, indent_level + 4)
         indent(out, indent_level + 4)
           << "in_interpreter = 1;\n";
           << "in_interpreter = 1;\n";
       }
       }
+      if (!extra_cleanup.empty()) {
+        indent(out, indent_level + 3)
+          << extra_cleanup << "\n";
+      }
       test_assert(out, indent_level + 4);
       test_assert(out, indent_level + 4);
       indent(out, indent_level + 4)
       indent(out, indent_level + 4)
         << "return Py_BuildValue(\"\");\n";
         << "return Py_BuildValue(\"\");\n";
@@ -464,6 +515,10 @@ write_function_instance(ostream &out, int indent_level,
         indent(out, indent_level + 4)
         indent(out, indent_level + 4)
           << "in_interpreter = 1;\n";
           << "in_interpreter = 1;\n";
       }
       }
+      if (!extra_cleanup.empty()) {
+        indent(out, indent_level + 3)
+          << extra_cleanup << "\n";
+      }
 
 
       return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
       return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
       test_assert(out, indent_level + 4);
       test_assert(out, indent_level + 4);
@@ -501,6 +556,14 @@ pack_return_value(ostream &out, int indent_level,
         << return_expr << ".data(), " << return_expr << ".length());\n";
         << return_expr << ".data(), " << return_expr << ".length());\n";
     }
     }
 
 
+  } else if (TypeManager::is_unsigned_longlong(type)) {
+    indent(out, indent_level)
+      << "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n";
+
+  } else if (TypeManager::is_longlong(type)) {
+    indent(out, indent_level)
+      << "return PyLong_FromLongLong(" << return_expr << ");\n";
+
   } else if (TypeManager::is_integer(type)) {
   } else if (TypeManager::is_integer(type)) {
     indent(out, indent_level)
     indent(out, indent_level)
       << "return PyInt_FromLong(" << return_expr << ");\n";
       << "return PyInt_FromLong(" << return_expr << ");\n";

+ 53 - 2
dtool/src/interrogate/interfaceMakerPythonSimple.cxx

@@ -242,6 +242,9 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
   string parameter_list;
   string parameter_list;
   string container;
   string container;
   vector_string pexprs;
   vector_string pexprs;
+  string extra_convert;
+  string extra_param_check;
+  string extra_cleanup;
 
 
   // Make one pass through the parameter list.  We will output a
   // Make one pass through the parameter list.  We will output a
   // one-line temporary variable definition for each parameter, while
   // one-line temporary variable definition for each parameter, while
@@ -283,6 +286,24 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
       parameter_list += ", &" + param_name;
       parameter_list += ", &" + param_name;
       pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
       pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
 
 
+    } else if (TypeManager::is_unsigned_longlong(type)) {
+      out << "PyObject *" << param_name;
+      format_specifiers += "O";
+      parameter_list += ", &" + param_name;
+      extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
+      extra_param_check += "|| (" + param_name + "_long == NULL)";
+      pexpr_string = "PyLong_AsUnsignedLongLong(" + param_name + "_long)";
+      extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
+
+    } else if (TypeManager::is_longlong(type)) {
+      out << "PyObject *" << param_name;
+      format_specifiers += "O";
+      parameter_list += ", &" + param_name;
+      extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
+      extra_param_check += "|| (" + param_name + "_long == NULL)";
+      pexpr_string = "PyLong_AsLongLong(" + param_name + "_long)";
+      extra_cleanup += " Py_XDECREF(" + param_name + "_long);";
+
     } else if (TypeManager::is_integer(type)) {
     } else if (TypeManager::is_integer(type)) {
       out << "int " << param_name;
       out << "int " << param_name;
       format_specifiers += "i";
       format_specifiers += "i";
@@ -326,17 +347,30 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
 
 
   out << "  if (PyArg_ParseTuple(args, \"" << format_specifiers
   out << "  if (PyArg_ParseTuple(args, \"" << format_specifiers
       << "\"" << parameter_list << ")) {\n";
       << "\"" << parameter_list << ")) {\n";
+
+  if (!extra_convert.empty()) {
+    out << "   " << extra_convert << "\n";
+  }
+
+  if (!extra_param_check.empty()) {
+    out << "    if (" << extra_param_check.substr(3) << ") {\n";
+    if (!extra_cleanup.empty()) {
+      out << "     " << extra_cleanup << "\n";
+    }
+    out << "      PyErr_SetString(PyExc_TypeError, \"Invalid parameters.\");\n"
+        << "      return (PyObject *)NULL;\n"
+        << "    }\n";
+  }
   
   
   if (track_interpreter) {
   if (track_interpreter) {
     out << "    in_interpreter = 0;\n";
     out << "    in_interpreter = 0;\n";
   }
   }
-  
+
   if (!remap->_void_return && 
   if (!remap->_void_return && 
       remap->_return_type->new_type_is_atomic_string()) {
       remap->_return_type->new_type_is_atomic_string()) {
     // Treat strings as a special case.  We don't want to format the
     // Treat strings as a special case.  We don't want to format the
     // return expression.
     // return expression.
     string return_expr = remap->call_function(out, 4, false, container, pexprs);
     string return_expr = remap->call_function(out, 4, false, container, pexprs);
-    
     CPPType *type = remap->_return_type->get_orig_type();
     CPPType *type = remap->_return_type->get_orig_type();
     out << "    ";
     out << "    ";
     type->output_instance(out, "return_value", &parser);
     type->output_instance(out, "return_value", &parser);
@@ -345,6 +379,9 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
     if (track_interpreter) {
     if (track_interpreter) {
       out << "    in_interpreter = 1;\n";
       out << "    in_interpreter = 1;\n";
     }
     }
+    if (!extra_cleanup.empty()) {
+      out << "   " << extra_cleanup << "\n";
+    }
     
     
     return_expr = manage_return_value(out, 4, remap, "return_value");
     return_expr = manage_return_value(out, 4, remap, "return_value");
     test_assert(out, 4);
     test_assert(out, 4);
@@ -356,6 +393,9 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
       if (track_interpreter) {
       if (track_interpreter) {
         out << "    in_interpreter = 1;\n";
         out << "    in_interpreter = 1;\n";
       }
       }
+      if (!extra_cleanup.empty()) {
+        out << "   " << extra_cleanup << "\n";
+      }
       test_assert(out, 4);
       test_assert(out, 4);
       out << "    return Py_BuildValue(\"\");\n";
       out << "    return Py_BuildValue(\"\");\n";
       
       
@@ -367,6 +407,9 @@ write_function_instance(ostream &out, InterfaceMaker::Function *func,
       if (track_interpreter) {
       if (track_interpreter) {
         out << "    in_interpreter = 1;\n";
         out << "    in_interpreter = 1;\n";
       }
       }
+      if (!extra_cleanup.empty()) {
+        out << "   " << extra_cleanup << "\n";
+      }
       
       
       return_expr = manage_return_value(out, 4, remap, "return_value");
       return_expr = manage_return_value(out, 4, remap, "return_value");
       test_assert(out, 4);
       test_assert(out, 4);
@@ -403,6 +446,14 @@ pack_return_value(ostream &out, int indent_level,
         << return_expr << ".data(), " << return_expr << ".length());\n";
         << return_expr << ".data(), " << return_expr << ".length());\n";
     }
     }
 
 
+  } else if (TypeManager::is_unsigned_longlong(type)) {
+    indent(out, indent_level)
+      << "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n";
+
+  } else if (TypeManager::is_longlong(type)) {
+    indent(out, indent_level)
+      << "return PyLong_FromLongLong(" << return_expr << ");\n";
+
   } else if (TypeManager::is_integer(type)) {
   } else if (TypeManager::is_integer(type)) {
     indent(out, indent_level)
     indent(out, indent_level)
       << "return PyInt_FromLong(" << return_expr << ");\n";
       << "return PyInt_FromLong(" << return_expr << ");\n";

+ 5 - 1
dtool/src/interrogate/interrogateBuilder.cxx

@@ -1787,7 +1787,11 @@ define_atomic_type(InterrogateType &itype, CPPSimpleType *cpptype) {
     break;
     break;
 
 
   case CPPSimpleType::T_int:
   case CPPSimpleType::T_int:
-    itype._atomic_token = AT_int;
+    if ((cpptype->_flags & CPPSimpleType::F_longlong) != 0) {
+      itype._atomic_token = AT_longlong;
+    } else {
+      itype._atomic_token = AT_int;
+    }
     break;
     break;
 
 
   case CPPSimpleType::T_float:
   case CPPSimpleType::T_float:

+ 67 - 1
dtool/src/interrogate/typeManager.cxx

@@ -489,6 +489,7 @@ is_bool(CPPType *type) {
           simple_type->_type == CPPSimpleType::T_bool;
           simple_type->_type == CPPSimpleType::T_bool;
       }
       }
     }
     }
+    break;
 
 
   default:
   default:
     break;
     break;
@@ -523,6 +524,67 @@ is_integer(CPPType *type) {
            simple_type->_type == CPPSimpleType::T_int);
            simple_type->_type == CPPSimpleType::T_int);
       }
       }
     }
     }
+    break;
+
+  default:
+    break;
+  }
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TypeManager::is_unsigned_longlong
+//       Access: Public, Static
+//  Description: Returns true if the indicated type is an unsigned
+//               "long long" type or larger, or at least a 64-bit
+//               unsigned integer.
+////////////////////////////////////////////////////////////////////
+bool TypeManager::
+is_unsigned_longlong(CPPType *type) {
+  switch (type->get_subtype()) {
+  case CPPDeclaration::ST_const:
+    return is_unsigned_longlong(type->as_const_type()->_wrapped_around);
+
+  case CPPDeclaration::ST_simple:
+    {
+      CPPSimpleType *simple_type = type->as_simple_type();
+      if (simple_type != (CPPSimpleType *)NULL) {
+        return (simple_type->_type == CPPSimpleType::T_int && 
+                (simple_type->_flags & (CPPSimpleType::F_longlong | CPPSimpleType::F_unsigned)) == (CPPSimpleType::F_longlong | CPPSimpleType::F_unsigned));
+      }
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TypeManager::is_longlong
+//       Access: Public, Static
+//  Description: Returns true if the indicated type is the "long long"
+//               type or larger, or at least a 64-bit integer, whether
+//               signed or unsigned.
+////////////////////////////////////////////////////////////////////
+bool TypeManager::
+is_longlong(CPPType *type) {
+  switch (type->get_subtype()) {
+  case CPPDeclaration::ST_const:
+    return is_longlong(type->as_const_type()->_wrapped_around);
+
+  case CPPDeclaration::ST_simple:
+    {
+      CPPSimpleType *simple_type = type->as_simple_type();
+      if (simple_type != (CPPSimpleType *)NULL) {
+        return (simple_type->_type == CPPSimpleType::T_int && 
+                (simple_type->_flags & CPPSimpleType::F_longlong) != 0);
+      }
+    }
+    break;
 
 
   default:
   default:
     break;
     break;
@@ -553,6 +615,7 @@ is_float(CPPType *type) {
            simple_type->_type == CPPSimpleType::T_double);
            simple_type->_type == CPPSimpleType::T_double);
       }
       }
     }
     }
+    break;
 
 
   default:
   default:
     break;
     break;
@@ -609,10 +672,13 @@ is_reference_count(CPPType *type) {
         }
         }
       }
       }
     }
     }
+    break;
 
 
   default:
   default:
-    return false;
+    break;
   }
   }
+
+  return false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
dtool/src/interrogate/typeManager.h

@@ -70,6 +70,8 @@ public:
   static bool is_const_ref_to_basic_string_char(CPPType *type);
   static bool is_const_ref_to_basic_string_char(CPPType *type);
   static bool is_bool(CPPType *type);
   static bool is_bool(CPPType *type);
   static bool is_integer(CPPType *type);
   static bool is_integer(CPPType *type);
+  static bool is_unsigned_longlong(CPPType *type);
+  static bool is_longlong(CPPType *type);
   static bool is_float(CPPType *type);
   static bool is_float(CPPType *type);
   static bool is_void(CPPType *type);
   static bool is_void(CPPType *type);
   static bool is_reference_count(CPPType *type);
   static bool is_reference_count(CPPType *type);

+ 3 - 1
dtool/src/interrogatedb/interrogate_interface.h

@@ -85,7 +85,9 @@ enum AtomicToken {
   // convention wrappers, atomic string means (const char *); for
   // convention wrappers, atomic string means (const char *); for
   // other calling convention wrappers, atomic string means whatever
   // other calling convention wrappers, atomic string means whatever
   // the native string representation is.
   // the native string representation is.
-  AT_string = 7
+  AT_string = 7,
+
+  AT_longlong = 8
 };
 };
 
 
 EXPCL_DTOOLCONFIG void interrogate_add_search_directory(const char *dirname);
 EXPCL_DTOOLCONFIG void interrogate_add_search_directory(const char *dirname);