From de0c52d69e5d3525f5dd56e3554a06a19fd75a13 Mon Sep 17 00:00:00 2001
From: Joel Andersson <j.a.e.andersson@gmail.com>
Date: Fri, 9 Oct 2015 16:54:07 +0200
Subject: [PATCH] [MATLAB] Issue #58: Refactored error handling

---
 Lib/matlab/matlabrun.swg     | 34 +++++++++++++++++++---------------
 Lib/matlab/matlabruntime.swg |  1 +
 Source/Modules/matlab.cxx    | 35 +++++++++++++++--------------------
 3 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/Lib/matlab/matlabrun.swg b/Lib/matlab/matlabrun.swg
index 409ff1336b0..75f9406365c 100644
--- a/Lib/matlab/matlabrun.swg
+++ b/Lib/matlab/matlabrun.swg
@@ -1,11 +1,12 @@
-SWIGRUNTIME bool SWIG_check_num_args(const char *func_name, int num_args, int max_args, int min_args, int varargs) {
-  if (num_args > max_args && !varargs)
-    mexWarnMsgIdAndTxt("SWIG:RuntimeError","function %s takes at most %i arguments", func_name, max_args);
-  else if (num_args < min_args)
-    mexWarnMsgIdAndTxt("SWIG:RuntimeError","function %s requires at least %i arguments", func_name, min_args);
-  else
-    return true;
-  return false;
+/* Last error */
+static int SWIG_lasterror_code = 0;
+static char SWIG_lasterror_msg[1024];
+SWIGRUNTIME void SWIG_Error(int code, const char *format, ...) {
+  SWIG_lasterror_code = code;
+  va_list arg;
+  va_start(arg, format);
+  vsnprintf(SWIG_lasterror_msg, sizeof(SWIG_lasterror_msg), format, arg);
+  va_end(arg);
 }
 
 SWIGRUNTIME const char* SWIG_ErrorType(int code) {
@@ -36,8 +37,15 @@ SWIGRUNTIME const char* SWIG_ErrorType(int code) {
   return "SWIG:UnknownError";
 }
 
-SWIGRUNTIME void SWIG_Error(int code, const char *msg) {
-  mexWarnMsgIdAndTxt(SWIG_ErrorType(code),msg);
+SWIGRUNTIME bool SWIG_check_num_args(const char *func_name, int num_args, int max_args, int min_args, int varargs) {
+  if (num_args > max_args && !varargs) {
+    SWIG_Error(SWIG_RuntimeError, "function %s takes at most %i arguments", func_name, max_args);
+  } else if (num_args < min_args) {
+    SWIG_Error(SWIG_RuntimeError, "function %s requires at least %i arguments", func_name, min_args);
+  } else {
+    return true;
+  }
+  return false;
 }
 
 #define SWIG_fail                                       goto fail
@@ -80,7 +88,6 @@ typedef struct SwigPtr {
   void *self;
   struct SwigPtr* next;
 } SwigPtr;
-static char const * storagename = "swig" SWIG_name_d "directorstorage";
 static swig_module_info *saved_swig_module = 0;
 
 /* Add new pointer object to the memory allocator
@@ -217,10 +224,7 @@ SWIGRUNTIME int SWIG_Matlab_ConvertPtrAndOwn(mxArray* pm, void **ptr, swig_type_
   mxDestroyArray(pm_ptr);
 
   /* Get pointer object */
-  if (!swig_ptr) {
-    mexWarnMsgIdAndTxt("SWIG:ConvertPtrAndOwn", "No such element");
-    return SWIG_ERROR;
-  }
+  if (!swig_ptr) return SWIG_ERROR;
 
   swig_cast_info *tc;
   bool same_type = false;
diff --git a/Lib/matlab/matlabruntime.swg b/Lib/matlab/matlabruntime.swg
index 794f65b2e98..9585029bb61 100644
--- a/Lib/matlab/matlabruntime.swg
+++ b/Lib/matlab/matlabruntime.swg
@@ -2,6 +2,7 @@
 #include <mex.h>
 #include <math.h> /* need this for floor() */
 #include <string.h> /* need this for strcmp() */
+#include <stdarg.h> /* need this for SWIG_Error below */
 %}
 
 %insert(runtime) "swigrun.swg";
diff --git a/Source/Modules/matlab.cxx b/Source/Modules/matlab.cxx
index 909ad294d69..1468e566b6f 100644
--- a/Source/Modules/matlab.cxx
+++ b/Source/Modules/matlab.cxx
@@ -500,14 +500,14 @@ int MATLAB::top(Node *n) {
 
   // The first argument is always the ID
   Printf(f_begin,"  if (argc!=1 || !mxIsDouble(*argv) || mxGetNumberOfElements(*argv)!=1) {\n");
-  Printf(f_begin,"    mexWarnMsgIdAndTxt(\"SWIG:RuntimeError\", \"This mex file should only be called from "
+  Printf(f_begin,"    SWIG_Error(SWIG_RuntimeError, \"This mex file should only be called from "
          "inside the .m files generated by SWIG. The input should be the constant ID.\");\n");
   Printf(f_begin,"    return 1;\n");
   Printf(f_begin,"  }\n");
 
   // Make sure one output
   Printf(f_begin,"  if (resc!=1) {\n");
-  Printf(f_begin,"    mexWarnMsgIdAndTxt(\"SWIG:RuntimeError\", \"The function should have one output.\");\n");
+  Printf(f_begin,"    SWIG_Error(SWIG_RuntimeError, \"The function should have one output.\");\n");
   Printf(f_begin,"    return 1;\n");
   Printf(f_begin,"  }\n");
 
@@ -517,7 +517,7 @@ int MATLAB::top(Node *n) {
 
   // Make sure found
   Printf(f_begin,"  if (s==0) {\n");
-  Printf(f_begin,"    mexWarnMsgIdAndTxt(\"SWIG:RuntimeError\", \"No such constant ID.\");\n");
+  Printf(f_begin,"    SWIG_Error(SWIG_RuntimeError, \"No such constant ID.\");\n");
   Printf(f_begin,"    return 1;\n");
   Printf(f_begin,"  }\n");
 
@@ -552,14 +552,14 @@ int MATLAB::top(Node *n) {
 
   // The first argument is always the ID
   Printf(f_begin,"  if (argc!=1 || !mxIsDouble(*argv) || mxGetNumberOfElements(*argv)!=1) {\n");
-  Printf(f_begin,"    mexWarnMsgIdAndTxt(\"SWIG:RuntimeError\", \"This mex file should only be called from "
+  Printf(f_begin,"    SWIG_Error(SWIG_RuntimeError, \"This mex file should only be called from "
          "inside the .m files generated by SWIG. The input should be the function ID.\");\n");
   Printf(f_begin,"    return 1;\n");
   Printf(f_begin,"  }\n");
 
   // Make sure one output
   Printf(f_begin,"  if (resc!=1) {\n");
-  Printf(f_begin,"    mexWarnMsgIdAndTxt(\"SWIG:RuntimeError\", \"The function should have one output.\");\n");
+  Printf(f_begin,"    SWIG_Error(SWIG_RuntimeError, \"The function should have one output.\");\n");
   Printf(f_begin,"    return 1;\n");
   Printf(f_begin,"  }\n");
 
@@ -569,7 +569,7 @@ int MATLAB::top(Node *n) {
 
   // Make sure found
   Printf(f_begin,"  if (s==0) {\n");
-  Printf(f_begin,"    mexWarnMsgIdAndTxt(\"SWIG:RuntimeError\", \"No such function ID.\");\n");
+  Printf(f_begin,"    SWIG_Error(SWIG_RuntimeError, \"No such function ID.\");\n");
   Printf(f_begin,"    return 1;\n");
   Printf(f_begin,"  }\n");
 
@@ -583,14 +583,14 @@ int MATLAB::top(Node *n) {
 
   // Make sure only one input and max one output
   Printf(f_begin,"  if (argc!=1 || resc!=1) {\n");
-  Printf(f_begin,"    mexWarnMsgIdAndTxt(\"SWIG:RuntimeError\", \"swigThis should have one input and one output.\");\n");
+  Printf(f_begin,"    SWIG_Error(SWIG_RuntimeError, \"swigThis should have one input and one output.\");\n");
   Printf(f_begin,"    return 1;\n");
   Printf(f_begin,"  }\n");
 
   // Get the SwigPtr object
   Printf(f_begin,"  SwigPtr* swig_ptr = SWIG_Matlab_getSwigPtr(argv[0]);\n");
   Printf(f_begin,"  if (!swig_ptr) {\n");
-  Printf(f_begin,"    mexWarnMsgIdAndTxt(\"SWIG:RuntimeError\", \"The argument should be a SWIG class.\");\n");
+  Printf(f_begin,"    SWIG_Error(SWIG_RuntimeError, \"The argument should be a SWIG class.\");\n");
   Printf(f_begin,"    return 1;\n");
   Printf(f_begin,"  }\n");
 
@@ -605,7 +605,7 @@ int MATLAB::top(Node *n) {
 
   // Make sure no inputs or outputs
   Printf(f_begin,"  if (argc!=0 || resc!=0) {\n");
-  Printf(f_begin,"    mexWarnMsgIdAndTxt(\"SWIG:RuntimeError\", \"swigTouch should have no inputs or outputs.\");\n");
+  Printf(f_begin,"    SWIG_Error(SWIG_RuntimeError, \"swigTouch should have no inputs or outputs.\");\n");
   Printf(f_begin,"    return 1;\n");
   Printf(f_begin,"  }\n");
   Printf(f_begin,"  return 0;\n");
@@ -2249,7 +2249,7 @@ void MATLAB::initGateway() {
   }
 
   // Begin the switch:
-  Printf(f_gateway,"  int id_exists=1, flag=0;\n");
+  Printf(f_gateway,"  int flag=0;\n");
   Printf(f_gateway,"  switch (fcn_id) {\n");
 
   // List of function names
@@ -2291,7 +2291,7 @@ int MATLAB::toGateway(String *fullname, String *wname) {
 }
 
 void MATLAB::finalizeGateway() {
-  Printf(f_gateway,"  default: id_exists=0;\n");
+  Printf(f_gateway,"  default: flag=1, SWIG_Error(SWIG_RuntimeError, \"No function id %%d.\", fcn_id);\n");
   Printf(f_gateway,"  }\n");
 
   // Restore std::cout and std::cerr
@@ -2299,13 +2299,8 @@ void MATLAB::finalizeGateway() {
     Printf(f_gateway, "  std::cout.rdbuf(cout_backup);\n");
     Printf(f_gateway, "  std::cerr.rdbuf(cerr_backup);\n");
   }
-  
-  Printf(f_gateway,"  if (!id_exists) {\n");
-  Printf(f_gateway,"    mexErrMsgIdAndTxt(\"SWIG:RuntimeError\",\"No function id %%d.\",fcn_id);\n");
-  Printf(f_gateway,"  }\n");  
-  
   Printf(f_gateway,"  if (flag) {\n");
-  Printf(f_gateway,"    mexErrMsgIdAndTxt(\"SWIG:RuntimeError\",\"Fatal error.\");\n");
+  Printf(f_gateway,"    mexErrMsgIdAndTxt(SWIG_ErrorType(SWIG_lasterror_code), SWIG_lasterror_msg);\n");
   Printf(f_gateway,"  }\n");
   Printf(f_gateway,"}\n");
 }
@@ -2316,7 +2311,7 @@ void MATLAB::initConstant() {
   
   // The first argument is always the ID
   Printf(f_constants,"  if (--argc < 0 || !mxIsDouble(*argv) || mxGetNumberOfElements(*argv)!=1) {\n");
-  Printf(f_constants,"    mexWarnMsgIdAndTxt(\"SWIG:RuntimeError\",\"This function should only be called from inside the .m files generated by SWIG. First input should be the constant ID .\");\n");
+  Printf(f_constants,"    SWIG_Error(SWIG_RuntimeError, \"This function should only be called from inside the .m files generated by SWIG. First input should be the constant ID .\");\n");
   Printf(f_constants,"    return 1;\n");
   Printf(f_constants,"  }\n");
   Printf(f_constants,"  int con_id = (int)mxGetScalar(*argv++);\n");
@@ -2339,7 +2334,7 @@ int MATLAB::toConstant(String *constname, String *constdef) {
 
 void MATLAB::finalizeConstant() {
   Printf(f_constants,"  default:\n");
-  Printf(f_constants,"    mexWarnMsgIdAndTxt(\"SWIG:RuntimeError\",\"No such constant.\");\n");
+  Printf(f_constants,"    SWIG_Error(SWIG_RuntimeError, \"No such constant.\");\n");
   Printf(f_constants,"    return 1;\n");  
   Printf(f_constants,"  }\n");
   Printf(f_constants,"  return 0;\n");
@@ -2876,7 +2871,7 @@ void MATLAB::dispatchFunction(Node *n) {
 
   Printf(f->def, "int %s (int resc, mxArray *resv[], int argc, mxArray *argv[]) {", wname);
   Printv(f->code, dispatch, "\n", NIL);
-  Printf(f->code, "mexWarnMsgIdAndTxt(\"SWIG:OverloadError\",\"No matching function for overload function '%s'.\"\n", iname);
+  Printf(f->code, "SWIG_Error(SWIG_RuntimeError, \"No matching function for overload function '%s'.\"\n", iname);
   Printf(f->code, "   \"  Possible C/C++ prototypes are:\\n\"%s);\n",protoTypes);
   Printf(f->code, "return 1;\n");
   Printv(f->code, "}\n", NIL);