Xcos: proper detection and handling of IFTHEL_f and ESELECT_f blocks 68/16468/4
Paul Bignier [Tue, 12 May 2015 10:40:52 +0000 (12:40 +0200)]
 * These blocks are treated separately from the others because they have negative simulation function numbers (-1 and -2),
meaning their actual simulation function is defined in scicos.c (see synchro_nev())

 * Commit https://codereview.scilab.org/#/c/15883/ removes the possibility of easily detecting these 2 blocks,
so 'funtyp' needs to be altered when a magic value is found

 * Demos "Simple demo" and "Discrete controller" serve as tests for this commit,
because they use a "freq_div" superblock which has an "IFTHEL_f" inside

 * Used magic values for the simulation function numbers to clarify them

Change-Id: I0d7a7c3a48f4ab18e0ac123422635ac2599e3b80

scilab/modules/scicos/sci_gateway/cpp/sci_scicosim.cpp
scilab/modules/scicos/src/c/scicos.c

index 5af66da..8b3fe73 100644 (file)
@@ -1338,52 +1338,63 @@ types::Function::ReturnValue sci_scicosim(types::typed_list &in, int _iRetCount,
 
             wchar_t* w_str = funStr->get(0);
             char* c_str = wide_string_to_UTF8(w_str);
-            void* f = funnum2(c_str); // Search associated function number of function name
-            // Block is defined by a C or Fortran function
-            if (f != nullptr)
+            if (strcmp(c_str, "ifthel") == 0)
             {
-                // C interface from "tabsim" defined in blocks.h
-                lfunpt[i] = f;
-                if (l_sim_funtyp[i] < 0)
-                {
-                    // Keep 'l_sim_funtyp' positive for Fortran functions
-                    l_sim_funtyp[i] *= -1;
-                }
+                l_sim_funtyp[i] = 11; // Magic value for "if-then-else" block
+            }
+            else if (strcmp(c_str, "eselect") == 0)
+            {
+                l_sim_funtyp[i] = 12; // Magic value for "eselect" block
             }
-            // Block is defined by a predefined scilab function
             else
             {
-                ConfigVariable::EntryPointStr* pEP = ConfigVariable::getEntryPoint(w_str);
-                if (pEP)
+                void* f = funnum2(c_str); // Search associated function number of function name
+                // Block is defined by a C or Fortran function
+                if (f != nullptr)
                 {
-                    //linked functions
-                    lfunpt[i] = (void*)pEP->functionPtr;
+                    // C interface from "tabsim" defined in blocks.h
+                    lfunpt[i] = f;
+                    if (l_sim_funtyp[i] < 0)
+                    {
+                        // Keep 'l_sim_funtyp' positive for Fortran functions
+                        l_sim_funtyp[i] *= -1;
+                    }
                 }
+                // Block is defined by a predefined scilab function
                 else
                 {
-                    types::InternalType* pMacro = symbol::Context::getInstance()->get(symbol::Symbol(w_str));
-                    if (pMacro && pMacro->isCallable())
+                    ConfigVariable::EntryPointStr* pEP = ConfigVariable::getEntryPoint(w_str);
+                    if (pEP)
                     {
-                        //macros
-                        lfunpt[i] = (void*)pMacro;
-                        l_sim_funtyp[i] *= -1;
+                        //linked functions
+                        lfunpt[i] = (void*)pEP->functionPtr;
                     }
                     else
                     {
-                        Scierror(888, _("%s : unknown block : %s\n"), funname.data(), c_str);
-                        il_state->DecreaseRef();
-                        il_state->killMe();
-                        il_tcur->DecreaseRef();
-                        il_tcur->killMe();
-                        il_sim->DecreaseRef();
-                        il_sim->killMe();
-                        delete[] il_sim_labptr;
-                        delete[] l_sim_lab;
-                        delete[] il_sim_uidptr;
-                        delete[] l_sim_uid;
-                        delete[] lfunpt;
-                        FREE(c_str);
-                        return types::Function::Error;
+                        types::InternalType* pMacro = symbol::Context::getInstance()->get(symbol::Symbol(w_str));
+                        if (pMacro && pMacro->isCallable())
+                        {
+                            //macros
+                            lfunpt[i] = (void*)pMacro;
+                            l_sim_funtyp[i] *= -1;
+                        }
+                        else
+                        {
+                            Scierror(888, _("%s : unknown block : %s\n"), funname.data(), c_str);
+                            il_state->DecreaseRef();
+                            il_state->killMe();
+                            il_tcur->DecreaseRef();
+                            il_tcur->killMe();
+                            il_sim->DecreaseRef();
+                            il_sim->killMe();
+                            delete[] il_sim_labptr;
+                            delete[] l_sim_lab;
+                            delete[] il_sim_uidptr;
+                            delete[] l_sim_uid;
+                            delete[] lfunpt;
+                            FREE(c_str);
+                            return types::Function::Error;
+                        }
                     }
                 }
             }
index b8f515e..6266d4a 100644 (file)
@@ -159,6 +159,17 @@ enum Solver
 #define ONE   RCONST(1.0)
 #define ZERO  RCONST(0.0)
 #define T0    RCONST(0.0)
+
+// Special values for elements of 'funtyp'
+#define FORTRAN_GATEWAY   0
+#define UNUSED1           1
+#define UNUSED2           2
+#define SCIFUNC_BLOCK     3
+#define EXPRESSION_BLOCK  5
+#define IFTHEL_BLOCK      11
+#define ESELECT_BLOCK     12
+#define DEBUG_BLOCK       99
+#define OLD_SCI_BLOCK     10005
 /*--------------------------------------------------------------------------*/
 /* Table of constant values */
 static int c__90 = 90;
@@ -523,40 +534,48 @@ int C2F(scicos)(double *x_in, int *xptr_in, double *z__,
         void* p = funptr[kf];
         C2F(curblk).kfun = kf + 1;
         Blocks[kf].type = funtyp[kf + 1];
-        if (Blocks[kf].type < 0)
+        if (Blocks[kf].type == IFTHEL_BLOCK)
+        {
+            funtyp[kf + 1] = -1;
+        }
+        else if (Blocks[kf].type == ESELECT_BLOCK)
+        {
+            funtyp[kf + 1] = -2;
+        }
+        else if (Blocks[kf].type < 0)
         {
             //macros
             funtyp[kf + 1] *= -1; // Restore a positive 'funtyp' for later use
             switch (-Blocks[kf].type)
             {
-                case 0:
+                case FORTRAN_GATEWAY:
                     Blocks[kf].funpt = (voidg)F2C(sciblk);
                     break;
-                case 1:
+                case UNUSED1:
                     sciprint(_("type 1 function not allowed for scilab blocks\n"));
                     *ierr = 1000 + kf + 1;
                     FREE_blocks();
                     return 0;
-                case 2:
+                case UNUSED2:
                     sciprint(_("type 2 function not allowed for scilab blocks\n"));
                     *ierr = 1000 + kf + 1;
                     FREE_blocks();
                     return 0;
-                case 3:
+                case SCIFUNC_BLOCK:
                     Blocks[kf].funpt = (voidg)sciblk2;
                     Blocks[kf].type = 2;
                     break;
-                case 5:
+                case EXPRESSION_BLOCK:
                     Blocks[kf].funpt = (voidg)sciblk4;
                     Blocks[kf].type = 4;
                     break;
-                case 99: /* debugging block */
+                case DEBUG_BLOCK: /* debugging block */
                     Blocks[kf].funpt = (voidg)sciblk4;
                     /*Blocks[kf].type=4;*/
                     debug_block = kf;
                     break;
 
-                case 10005:
+                case OLD_SCI_BLOCK:
                     Blocks[kf].funpt = (voidg)sciblk4;
                     Blocks[kf].type = 10004;
                     break;
@@ -570,78 +589,12 @@ int C2F(scicos)(double *x_in, int *xptr_in, double *z__,
         }
         else
         {
-            //linked functions ( internal or external
+            //linked functions (internal or external)
             Blocks[kf].funpt = (voidf)p;
             Blocks[kf].scsptr = NULL;   /* this is done for being able to test if a block
                                         is a scilab block in the debugging phase when
                                         sciblk4 is called */
         }
-        //if (i < 0)
-        //{
-        //    switch (funtyp[kf + 1])
-        //    {
-        //        case 0:
-        //            Blocks[kf].funpt = (voidg) F2C(sciblk);
-        //            break;
-        //        case 1:
-        //            sciprint(_("type 1 function not allowed for scilab blocks\n"));
-        //            *ierr = 1000 + kf + 1;
-        //            FREE_blocks();
-        //            return 0;
-        //        case 2:
-        //            sciprint(_("type 2 function not allowed for scilab blocks\n"));
-        //            *ierr = 1000 + kf + 1;
-        //            FREE_blocks();
-        //            return 0;
-        //        case 3:
-        //            Blocks[kf].funpt = (voidg) sciblk2;
-        //            Blocks[kf].type = 2;
-        //            break;
-        //        case 5:
-        //            Blocks[kf].funpt = (voidg) sciblk4;
-        //            Blocks[kf].type = 4;
-        //            break;
-        //        case 99: /* debugging block */
-        //            Blocks[kf].funpt = (voidg) sciblk4;
-        //            /*Blocks[kf].type=4;*/
-        //            debug_block = kf;
-        //            break;
-
-        //        case 10005:
-        //            Blocks[kf].funpt = (voidg) sciblk4;
-        //            Blocks[kf].type = 10004;
-        //            break;
-        //        default :
-        //            sciprint(_("Undefined Function type\n"));
-        //            *ierr = 1000 + kf + 1;
-        //            FREE_blocks();
-        //            return 0;
-        //    }
-        //    Blocks[kf].scsptr = -i; /* set scilab function adress for sciblk */
-        //}
-        //else if (i <= ntabsim)
-        //{
-        //    Blocks[kf].funpt = (voidg) * (tabsim[i - 1].fonc);
-        //    Blocks[kf].scsptr = 0;     /* this is done for being able to test if a block
-        //      is a scilab block in the debugging phase when
-        //      sciblk4 is called */
-        //}
-        //else
-        //{
-        //    i -= (ntabsim + 1);
-        //    //TODO: see in dynamic_lin how to get funcptr from index
-        //    //GetDynFunc(i, &Blocks[kf].funpt);
-        //    if ( Blocks[kf].funpt == (voidf) 0)
-        //    {
-        //        sciprint(_("Function not found\n"));
-        //        *ierr = 1000 + kf + 1;
-        //        FREE_blocks();
-        //        return 0;
-        //    }
-        //    Blocks[kf].scsptr = 0;   /* this is done for being able to test if a block
-        //   is a scilab block in the debugging phase when
-        //   sciblk4 is called */
-        //}
 
         /* 2 : Dimension properties */
         Blocks[kf].ztyp = ztyp[kf + 1];