File: rt_logging.c

    1   /* 
    2    *
    3    * Copyright 1994-2012 The MathWorks, Inc.
    4    *
    5    * File: rt_logging.c
    6    *
    7    * Abstract:
    8    *	Real-Time Workshop data logging routines using circular buffers of
    9    *      fixed size.  The buffers are allocated at start, filled in at each
   10    *      major time step and finally written to a MAT-file at the end of the
   11    *      simulation.
   12    *
   13    *      This file handles redefining the following standard MathWorks types
   14    *      (see tmwtypes.h):
   15    *         [u]int8_T     to be int32_T (logged as Matlab [u]int32)
   16    *         [u]int16_T    to be int32_T (logged as Matlab [u]int32)
   17    *         real_T        to be real32_T (logged as Matlab single)
   18    *
   19    */
   20   
   21   #define PUBLIC
   22   #define BEGIN_PUBLIC
   23   #define END_PUBLIC
   24   
   25   #include <stdlib.h>
   26   #include <string.h>
   27   #include <stdio.h>
   28   #include <math.h>
   29   
   30   BEGIN_PUBLIC
   31   #if !defined(MAT_FILE) || (defined(MAT_FILE) && MAT_FILE == 1)
   32   
   33   #include <stddef.h>                     /* size_t */
   34   #include "rtwtypes.h"
   35   #include "rt_mxclassid.h"
   36   #include "rtw_matlogging.h"
   37   
   38   #ifndef TMW_NAME_LENGTH_MAX
   39   #define TMW_NAME_LENGTH_MAX 64
   40   #endif
   41   #define mxMAXNAM  TMW_NAME_LENGTH_MAX	/* maximum name length */
   42   
   43   /*=========*
   44    * Defines *
   45    *=========*/
   46   
   47   /*
   48    * Logging related functions and data structures
   49    */
   50   typedef double MatReal;                /* "real" data type used in model.mat  */
   51   typedef struct LogVar_Tag LogVar;
   52   typedef struct StructLogVar_Tag StructLogVar;
   53   
   54   typedef struct MatrixData_Tag {
   55     char_T         name[mxMAXNAM];     /* Name of the variable                  */
   56     int_T          nRows;              /* number of rows                        */
   57     int_T          nCols;              /* number of columns                     */
   58     int_T          nDims;              /* number of dimensions                  */
   59     int_T          _dims[2];           /* most cases, dimensions are 2          */
   60     int_T          *dims;              /* dimensions of the log variable we 
   61                                           write to at each simulation time step.
   62                                           E.g: (1) Non-frame data - 
   63                                                    Signal dimension = [2 X 3]
   64                                                    numDims = 2
   65                                                    dims[0] = 2, dims[1] = 3
   66                                                (2) Frame data - 
   67                                                    Signal dimension = [2 X 3]
   68                                                    numDims = 1
   69                                                    dims[0] = 3                  */
   70     void           *re;                /* pointer to real part of the data      */
   71     void           *im;                /* pointer to imaginary part, if complex */
   72     DTypeId        dTypeID;            /* data type id                          */
   73     size_t         elSize;             /* element size in bytes                 */
   74   
   75     RTWLogDataTypeConvert dataTypeConvertInfo;
   76   
   77     mxClassID      mxID;               /* mxId corresponding to this dTypeID    */
   78     uint32_T       logical;            /* is this a logical array ?             */
   79     uint32_T       complex;            /* is this a complex matrix?             */
   80     uint32_T       frameData;          /* is this data frame based?             */
   81     uint32_T       frameSize;          /* is this data frame based?             */
   82   } MatrixData;
   83   
   84   typedef struct ValDimsData_Tag {
   85     char_T         name[mxMAXNAM];     /* Name of the variable                  */
   86     int_T          nRows;              /* number of rows                        */
   87     int_T          nCols;              /* number of columns                     */
   88     void           **currSigDims;      /* dimensions of current output          */
   89     int_T          *currSigDimsSize;   /* size in bytes of current sig dims     */
   90     real_T         *dimsData;          /* pointer to the value of dimension     */
   91   } ValDimsData;
   92   
   93   struct LogVar_Tag {
   94       MatrixData  data;                 /* Container for name, data etc.,       */
   95       ValDimsData *valDims;             /* field of valueDimensions
   96                                          1. If all logging signals are fixed-size,
   97                                             then we set this field to NULL;
   98                                          2. If any logging signal is variable-size,
   99                                             then this field will be needed:
  100                                            1) For fixed-size signal, this field is
  101                                               an empty matrix;
  102                                            2) Otherwise, it contains the dimension
  103                                               information of the logging signal.
  104                                         */
  105       int_T      rowIdx;                /* current row index                    */
  106       int_T      wrapped;               /* number of times the circular buffer
  107                                          * has wrapped around                   */
  108       int_T     nDataPoints;            /* total number of data points logged   */
  109       int_T     usingDefaultBufSize;    /* used to print a message at end       */
  110       int_T     okayToRealloc;          /* reallocate during sim?               */
  111       int_T     decimation;             /* decimation factor                    */
  112       int_T     numHits;                /* decimation hit count                 */
  113   
  114       int_T     *coords;
  115       int_T     *strides;
  116       int_T     *currStrides;           /* coords, strides and currStrides will be
  117                                            needed when logging variable-size 
  118                                            signal to calculate whether the 
  119                                            currently logging value is in the range.
  120                                            If the current signal is fixed-size,
  121                                            these pointers will be set to NULLs;
  122                                            otherwise, we allocate memory for them.
  123                                            (the size will be nDims in this case)
  124                                         */
  125   
  126       LogVar    *next;
  127   };
  128   
  129   typedef struct SignalsStruct_Tag {
  130       int_T        numActiveFields;   /* number of active fields                */
  131       const char_T *fieldNames;
  132       int_T        numSignals;
  133       LogVar       *values;
  134       MatrixData   *dimensions;
  135       MatrixData   *labels;
  136       MatrixData   *plotStyles;
  137       MatrixData   *titles;
  138       MatrixData   *blockNames;
  139       MatrixData   *stateNames;
  140       MatrixData   *crossMdlRef;
  141   
  142       boolean_T    logValueDimensions; /* If there's any variable-size signal 
  143                                            we also should log 'valueDimensions'
  144                                            field                                 */
  145       boolean_T    *isVarDims;         /* is this signal a variable-size signal? */
  146   } SignalsStruct;
  147   
  148   struct StructLogVar_Tag {
  149       char_T        name[mxMAXNAM];    /* Name of the ML Struct variable         */
  150       int_T         numActiveFields;   /* number of active fields                */
  151       boolean_T     logTime;
  152       void          *time;
  153       SignalsStruct signals;
  154       MatrixData    *blockName;
  155   
  156       StructLogVar  *next;
  157   };
  158   
  159   #define matUNKNOWN                  0
  160   #define	matINT8                     1
  161   #define	matUINT8                    2
  162   #define	matINT16                    3
  163   #define	matUINT16                   4
  164   #define	matINT32                    5
  165   #define	matUINT32                   6
  166   #define	matFLOAT                    7
  167   #define	matDOUBLE                   9
  168   #define matINT64                   12
  169   #define matUINT64                  13
  170   #define	matMATRIX                  14
  171   
  172   /* status of logging "valueDimensions" field */
  173   /* 
  174     NO_LOGVALDIMS: 
  175                    No need to log valueDimensions: 
  176                    All signals are fixed-sized.
  177   
  178     LOGVALDIMS_EMPTYMX: 
  179                    Signals with mixed dimension modes,
  180                    and the signal logged currently
  181                    is fixed-sized. So set valueDimensions
  182                    field to an empty matrix.
  183   
  184     LOGVALDIMS_VARDIMS:
  185                    Signal logged currently is variable-sized.
  186   */
  187   typedef enum {
  188       NO_LOGVALDIMS,      
  189       LOGVALDIMS_EMPTYMX,
  190       LOGVALDIMS_VARDIMS
  191   } LogValDimsStat;
  192   
  193   END_PUBLIC
  194   
  195   #define matLOGICAL_BIT          0x200
  196   #define matCOMPLEX_BIT          0x800
  197   
  198   #define matKEY                 0x4D49
  199   #define matVERSION             0x0100
  200   #define matVERSION_INFO_OFFSET   124L
  201   
  202   #define matINT64_ALIGN(e)      ( ( ((unsigned)(e))+7 ) & (~7) )
  203   #define matTAG_SIZE            (sizeof(int32_T) << 1)
  204   
  205   #ifndef DEFAULT_BUFFER_SIZE
  206   #define DEFAULT_BUFFER_SIZE      1024  /* used if maxRows=0 and Tfinal=0.0    */
  207   #endif
  208   
  209   #define FREE(m) if (m != NULL) free(m)
  210   
  211   /*==========*
  212    * typedefs *
  213    *==========*/
  214   
  215   typedef struct LogInfo_Tag {
  216       LogVar       *t;                   /* Time log variable                   */
  217       void         *x;                   /* State log variable                  */
  218       void         *sl;                  /* SigLog log variable                 */
  219       int_T        ny;                   /* Length of "y" log variables         */
  220       void         **y;                  /* Output log vars                     */
  221       void         *xFinal;              /* Final state log variable            */
  222   
  223       LogVar       *logVarsList;         /* Linked list of all LogVars          */
  224       StructLogVar *structLogVarsList;   /* Linked list of all StructLogVars    */
  225   
  226       boolean_T   haveLogVars;           /* Are logging one or more vars?       */
  227   } LogInfo;
  228   
  229   typedef struct MatItem_tag {
  230     int32_T    type;
  231     int32_T    nbytes;
  232     const void *data;
  233   } MatItem;
  234   
  235   typedef enum {
  236       DATA_ITEM,
  237       MATRIX_ITEM,
  238       STRUCT_LOG_VAR_ITEM,
  239       SIGNALS_STRUCT_ITEM
  240   } ItemDataKind;
  241   
  242   /*===========*
  243    * Constants *
  244    *===========*/
  245   
  246   static const char_T rtMemAllocError[] = "Memory allocation error";
  247   
  248   #define ZEROS32 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  249   
  250   #if mxMAXNAM==32
  251   
  252   #define ZERO_PAD
  253   
  254   #elif mxMAXNAM==64
  255   
  256   #define ZERO_PAD ZEROS32
  257   
  258   #elif mxMAXNAM==128
  259   
  260   #define ZERO_PAD   ZEROS32  ZEROS32  ZEROS32
  261   
  262   #else
  263   
  264   #error "Cannot Handle mxMAXNAM other than 32,64, and 128"
  265   
  266   #endif
  267   /* field names: for variable-size signal logging */
  268   static const char_T rtStructLogVarFieldNames[] =
  269                     "time\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  270                     "signals\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  271                     "blockName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD;
  272   static const char_T rtLocalLoggingSignalsStructFieldNames[] =
  273                     "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  274                     "valueDimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  275                     "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  276                     "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  277                     "title\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  278                     "plotStyle\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD;
  279   static const char_T rtGlobalLoggingSignalsStructFieldNames[] =
  280                     "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  281                     "valueDimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  282                     "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  283                     "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  284                     "blockName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  285                     "stateName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  286                     "inReferencedModel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD;
  287   #define TIME_FIELD_NAME      (rtStructLogVarFieldNames[0*mxMAXNAM])
  288   #define SIGNALS_FIELD_NAME   (rtStructLogVarFieldNames[1*mxMAXNAM])
  289   #define BLOCKNAME_FIELD_NAME (rtStructLogVarFieldNames[2*mxMAXNAM])
  290   
  291   #define VALUES_FIELD_NAME    (rtLocalLoggingSignalsStructFieldNames[0*mxMAXNAM])
  292   #define VALUEDIMENSIONS_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[1*mxMAXNAM])
  293   #define DIMENSION_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[2*mxMAXNAM])
  294   #define LABEL_FIELD_NAME     (rtLocalLoggingSignalsStructFieldNames[3*mxMAXNAM])
  295   #define TITLE_FIELD_NAME     (rtLocalLoggingSignalsStructFieldNames[4*mxMAXNAM])
  296   #define PLOTSTYLE_FIELD_NAME (rtLocalLoggingSignalsStructFieldNames[5*mxMAXNAM])
  297   
  298   #define STATENAME_FIELD_NAME (rtGlobalLoggingSignalsStructFieldNames[5*mxMAXNAM])
  299   #define CROSS_MDL_REF_FIELD_NAME (rtGlobalLoggingSignalsStructFieldNames[6*mxMAXNAM])
  300   
  301   /* field names: for fixed-size signal logging */
  302   static const char_T rtLocalLoggingSignalsStructFieldNames_noValDims[] =
  303                     "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  304                     "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  305                     "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  306                     "title\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  307                     "plotStyle\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD;
  308   static const char_T rtGlobalLoggingSignalsStructFieldNames_noValDims[] =
  309                     "values\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  310                     "dimensions\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  311                     "label\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  312                     "blockName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  313                     "stateName\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD
  314                     "inReferencedModel\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ZERO_PAD;
  315   
  316   extern real_T rtInf; /* declared by rt_nonfinite.c */
  317   extern real_T rtNaN;
  318   extern real32_T rtNaNF;
  319   
  320   /*================*
  321    * Local routines *
  322    *================*/
  323   
  324   /* Forward declaration */
  325   LogVar *rt_CreateLogVarWithConvert(RTWLogInfo        *li,
  326                                      const real_T      startTime,
  327                                      const real_T      finalTime,
  328                                      const real_T      inStepSize,
  329                                      const char_T      **errStatus,
  330                                      const char_T      *varName,
  331                                      BuiltInDTypeId    inpDataTypeID,
  332                                      const RTWLogDataTypeConvert *pDataTypeConvertInfo,
  333                                      int_T             logical,
  334                                      int_T             complex,
  335                                      int_T             frameData,
  336                                      int_T             nCols,
  337                                      int_T             nDims,
  338                                      const int_T       *dims,
  339                                      LogValDimsStat    logVarDimsStat,
  340                                      void              **currSigDims,
  341                                      int_T             *currSigDimsSize,
  342                                      int_T             maxRows,
  343                                      int_T             decimation,
  344                                      real_T            sampleTime,
  345                                      int_T             appendToLogVarsList);
  346   
  347   
  348   /* Function: rt_GetSizeofDataType ==============================================
  349    * Abstract:
  350    *      Get the element size in bytes given the data type id.
  351    */
  352   static size_t rt_GetSizeofDataType(BuiltInDTypeId dTypeID)
  353   {
  354       size_t elSz = 0; /* unknown */
  355   
  356       switch (dTypeID) {
  357         case SS_DOUBLE:
  358           elSz = sizeof(real_T);
  359           break;
  360         case SS_SINGLE:
  361           elSz = sizeof(real32_T);
  362           break;
  363         case SS_INT8:
  364           elSz = sizeof(int8_T);
  365           break;
  366         case SS_UINT8:
  367           elSz = sizeof(uint8_T);
  368           break;
  369         case SS_INT16:
  370           elSz = sizeof(int16_T);
  371           break;
  372         case SS_UINT16:
  373           elSz = sizeof(uint16_T);
  374           break;
  375         case SS_INT32:
  376           elSz = sizeof(int32_T);
  377           break;
  378         case SS_UINT32:
  379           elSz = sizeof(uint32_T);
  380           break;
  381         case SS_BOOLEAN:
  382           elSz = sizeof(boolean_T);
  383           break;
  384       }
  385       return(elSz);
  386   
  387   } /* end rt_GetSizeofDataType */
  388   
  389   
  390   /* Function: rt_GetSizeofComplexType ===========================================
  391    * Abstract:
  392    *      Get the element size in bytes given the data type id.
  393    */
  394   static size_t rt_GetSizeofComplexType(BuiltInDTypeId dTypeID)
  395   {
  396       size_t elSz = 2*rt_GetSizeofDataType(dTypeID);
  397   
  398       switch (dTypeID) {
  399         case SS_DOUBLE:
  400         #ifdef CREAL_T
  401           elSz = sizeof(creal_T);
  402         #endif
  403           break;
  404         case SS_SINGLE:
  405         #ifdef CREAL_T
  406           elSz = sizeof(creal32_T);
  407         #endif
  408           break;
  409         case SS_INT8:
  410         #ifdef _CINT8_T
  411           elSz = sizeof(cint8_T);
  412         #endif
  413           break;
  414         case SS_UINT8:
  415         #ifdef _CUINT8_T
  416           elSz = sizeof(cuint8_T);
  417         #endif
  418           break;
  419         case SS_INT16:
  420         #ifdef _CINT16_T
  421           elSz = sizeof(cint16_T);
  422         #endif
  423           break;
  424         case SS_UINT16:
  425         #ifdef _CUINT16_T
  426           elSz = sizeof(cuint16_T);
  427         #endif
  428           break;
  429         case SS_INT32:
  430         #ifdef _CINT32_T
  431           elSz = sizeof(cint32_T);
  432         #endif
  433           break;
  434         case SS_UINT32:
  435         #ifdef _CUINT32_T
  436           elSz = sizeof(cuint32_T);
  437         #endif
  438           break;
  439         case SS_BOOLEAN:
  440           elSz = sizeof(boolean_T);
  441           break;
  442       }
  443   
  444       return(elSz);
  445   
  446   } /* end rt_GetSizeofComplexType */
  447   
  448   
  449   /* Function: rt_GetDataTypeConvertInfo =========================================
  450    * Abstract:
  451    *      Directly copy if pointer to structure is non-NULL, otherwise set to
  452    *      default.
  453    */
  454   static RTWLogDataTypeConvert rt_GetDataTypeConvertInfo(
  455       const RTWLogDataTypeConvert *pDataTypeConvertInfo,
  456       BuiltInDTypeId dTypeID
  457       )
  458   {
  459       RTWLogDataTypeConvert dataTypeConvertInfoCopy;
  460   
  461       if (pDataTypeConvertInfo == NULL) {
  462           dataTypeConvertInfoCopy.conversionNeeded = 0;
  463           dataTypeConvertInfoCopy.dataTypeIdLoggingTo = dTypeID;
  464           dataTypeConvertInfoCopy.dataTypeIdOriginal  = (DTypeId)dTypeID;
  465           dataTypeConvertInfoCopy.bitsPerChunk = 0;
  466           dataTypeConvertInfoCopy.numOfChunk = 0;
  467           dataTypeConvertInfoCopy.isSigned = 0;
  468           dataTypeConvertInfoCopy.fracSlope = 1.0;
  469           dataTypeConvertInfoCopy.fixedExp = 0;
  470           dataTypeConvertInfoCopy.bias = 0.0;
  471       } else {
  472           dataTypeConvertInfoCopy = *pDataTypeConvertInfo;
  473       }
  474   
  475       return dataTypeConvertInfoCopy;
  476   
  477   } /* end rt_GetDataTypeConvertInfo */
  478   
  479   
  480   /* Function: rt_GetDblValueFromOverSizedData ===================================
  481    * Abstract:
  482    */
  483   static double rt_GetDblValueFromOverSizedData(
  484       const void *pVoid, 
  485       int bitsPerChunk, 
  486       int numOfChunk,
  487       unsigned int isSigned, 
  488       double fracSlope, 
  489       int fixedExp, 
  490       double bias)
  491   {
  492       double retValue = 0;
  493   
  494       double *dblValue = (double *) calloc(numOfChunk, sizeof(double));
  495   
  496       int i;    
  497       double isSignedNeg;
  498   
  499       if(isSigned) {
  500           const chunk_T *pData = (const chunk_T *) (pVoid);
  501           for (i = 0; i <numOfChunk; i++) {
  502               dblValue[i] = (double)(pData[i]);
  503           }
  504       } else  {
  505           const uchunk_T *pData = (const uchunk_T *) (pVoid);
  506           for (i = 0; i <numOfChunk; i++) {
  507               dblValue[i] = (double)(pData[i]);
  508           }
  509       }
  510   
  511       /* 
  512          Assuming multi chunks b_n ... b_2 b_1 b_0, and the length of each chunk is N.
  513          Suppose b_i is the i-th chunk's value.
  514          Then for unsigned data or data with one chunk: we have
  515          retValue = b_n * 2^(n*N) + ... + b_1 * 2^N + b_0 * 2^0;
  516          But for signed data, we have
  517          retValue = b_n * 2^(n*N) + ... + b_1 * 2^N + b_0 * 2^0+ (b_0<0) * 2^N + 
  518          ... (b_(n-1) <0) * 2^(n*N) 
  519          = (b_n + (b_(n-1)<0)) * 2^(n*N) +... + (b_1 + (b_0<0)) * 2^N + b_0 * 2^0;
  520          Together:
  521          retValue = 
  522          (b_n + isSigned * (b_(n-1)<0)) * 2^(n*N) +... + (b_1 + isSigned * (b_0<0)) * 2^N + b_0 * 2^0;
  523       */
  524   
  525       retValue = dblValue[numOfChunk - 1];
  526       
  527       for(i = numOfChunk - 1; i > 0; i--) {
  528           isSignedNeg = dblValue[i - 1] < 0 ? (double)isSigned : 0;
  529           retValue = retValue + isSignedNeg;
  530   
  531           retValue = ldexp(retValue, bitsPerChunk)+ dblValue[i-1];
  532       }
  533       retValue = ldexp( fracSlope * retValue, fixedExp ) + bias;
  534   
  535       FREE(dblValue);
  536       return (retValue);
  537   
  538   } /* end rt_GetDblValueFromOverSizedData */
  539   
  540   
  541   /* Function: rt_GetNonBoolMxIdFromDTypeId ======================================
  542    * Abstract:
  543    *      Get the mx???_CLASS given the simulink builtin data type id.
  544    */
  545   mxClassID rt_GetNonBoolMxIdFromDTypeId(BuiltInDTypeId dTypeID)
  546   {
  547       mxClassID mxID;
  548   
  549       switch (dTypeID) {
  550         case SS_DOUBLE:
  551           mxID = (sizeof(real_T)==4? mxSINGLE_CLASS: mxDOUBLE_CLASS);
  552           break;
  553         case SS_SINGLE:
  554           mxID = mxSINGLE_CLASS;
  555           break;
  556         case SS_INT8:
  557           mxID = (sizeof(int8_T)==4? mxINT32_CLASS: mxINT8_CLASS);
  558           break;
  559         case SS_UINT8:
  560           mxID = (sizeof(uint8_T)==4? mxUINT32_CLASS: mxUINT8_CLASS);
  561           break;
  562         case SS_INT16:
  563           mxID = (sizeof(int16_T)==4? mxINT32_CLASS: mxINT16_CLASS);
  564           break;
  565         case SS_UINT16:
  566           mxID = (sizeof(uint16_T)==4? mxUINT32_CLASS: mxUINT16_CLASS);
  567           break;
  568         case SS_INT32:
  569           mxID = mxINT32_CLASS;
  570           break;
  571         case SS_UINT32:
  572           mxID = mxUINT32_CLASS;
  573           break;
  574           /*case SS_BOOLEAN:
  575             mxID = (sizeof(boolean_T)==4? mxUINT32_CLASS: mxLOGICAL_CLASS);
  576             break;*/
  577         default:
  578           mxID = mxUNKNOWN_CLASS;
  579           break;
  580       }
  581   
  582       return(mxID);
  583   
  584   } /* end rt_GetNonBoolMxIdFromDTypeId */
  585   
  586   
  587   BEGIN_PUBLIC
  588   #ifdef __cplusplus
  589   extern "C" {
  590   #endif
  591   END_PUBLIC
  592   
  593   /* Function: rt_GetMxIdFromDTypeIdForRSim ======================================
  594    * Abstract:
  595    *      Get the mx???_CLASS given the simulink builtin data type id.
  596    */
  597   PUBLIC mxClassID rt_GetMxIdFromDTypeIdForRSim(BuiltInDTypeId dTypeID)
  598   {
  599       mxClassID mxID;
  600   
  601       if (dTypeID == SS_BOOLEAN) {
  602           mxID = (sizeof(boolean_T)==4? mxUINT32_CLASS: mxLOGICAL_CLASS);
  603       } else {
  604           mxID = rt_GetNonBoolMxIdFromDTypeId(dTypeID);
  605       }
  606   
  607       return(mxID);
  608   
  609   } /* end rt_GetMxIdFromDTypeIdForRSim */
  610   
  611   BEGIN_PUBLIC
  612   #ifdef __cplusplus
  613   }
  614   #endif
  615   END_PUBLIC
  616   
  617   
  618   BEGIN_PUBLIC
  619   #ifdef __cplusplus
  620   extern "C" {
  621   #endif
  622   END_PUBLIC
  623   
  624   /* Function: rt_GetMxIdFromDTypeId =============================================
  625    * Abstract:
  626    *      Get the mx???_CLASS given the simulink builtin data type id.
  627    */
  628   PUBLIC mxClassID rt_GetMxIdFromDTypeId(BuiltInDTypeId dTypeID)
  629   {
  630       mxClassID mxID;
  631   
  632       if (dTypeID == SS_BOOLEAN) {
  633           mxID = (sizeof(boolean_T)==4? mxUINT32_CLASS: mxUINT8_CLASS);
  634       } else {
  635           mxID = rt_GetNonBoolMxIdFromDTypeId(dTypeID);
  636       }
  637       return(mxID);
  638   
  639   } /* end rt_GetMxIdFromDTypeId */
  640   
  641   BEGIN_PUBLIC
  642   #ifdef __cplusplus
  643   }
  644   #endif
  645   END_PUBLIC
  646   
  647   
  648   /* Function: rt_GetMatIdFromMxId ===============================================
  649    * Abstract:
  650    *      Get the MatId given the mxClassID.
  651    */
  652   static int_T rt_GetMatIdFromMxId(mxClassID mxID)
  653   {
  654       int_T matID;
  655   
  656       switch (mxID) {
  657         case mxCELL_CLASS:
  658         case mxSTRUCT_CLASS:
  659         case mxOBJECT_CLASS:
  660           matID = -1;
  661           break;
  662         case mxCHAR_CLASS:
  663           matID = matUINT16;
  664           break;
  665         case mxDOUBLE_CLASS:
  666           matID = matDOUBLE;
  667           break;
  668         case mxSINGLE_CLASS:
  669           matID = matFLOAT;
  670           break;
  671         case mxINT8_CLASS:
  672           matID = matINT8;
  673           break;
  674         case mxUINT8_CLASS:
  675           matID = matUINT8;
  676           break;
  677         case mxINT16_CLASS:
  678           matID = matINT16;
  679           break;
  680         case mxUINT16_CLASS:
  681           matID = matUINT16;
  682           break;
  683         case mxINT32_CLASS:
  684           matID = matINT32;
  685           break;
  686         case mxUINT32_CLASS:
  687           matID = matUINT32;
  688           break;
  689         case mxINT64_CLASS:
  690           matID = matINT64;
  691           break;
  692         case mxUINT64_CLASS:
  693           matID = matUINT64;
  694           break;
  695         default:
  696           matID = matUNKNOWN;
  697           break;
  698       }
  699       return(matID);
  700   
  701   } /* end rt_GetMatIdFromMxId */
  702   
  703   
  704   /* Forward declaration */
  705   static int_T rt_WriteItemToMatFile(FILE         *fp,
  706                                      MatItem      *pItem,
  707                                      ItemDataKind dataKind);
  708   
  709   
  710   /* Function: rt_ProcessMatItem =================================================
  711    * Abstract:
  712    *      This routine along with rt_WriteItemToMatFile() write out a specified
  713    *      mat-item the .mat file. Note that if the input argument
  714    *          cmd == 0, then this function just calculates the size of the item.
  715    *          cmd <> 0, this function writes the mat-item to the file.
  716    *      Return values is
  717    *           -1 : coding/logic error
  718    *            0 : upon success
  719    *          > 0 : upon write failure (1)
  720    */
  721   static int_T rt_ProcessMatItem(FILE         *fp,
  722                                  MatItem      *pItem,
  723                                  ItemDataKind itemKind,
  724                                  int_T        cmd)
  725   {
  726       mxClassID    mxID          = mxUNKNOWN_CLASS;
  727       uint32_T     arrayFlags[2] = {0, 0};
  728       int32_T      *dims         = NULL;
  729       int32_T      _dims[3]      = {0, 0, 0};
  730       int32_T      nDims         = 2;
  731       int32_T      nBytesInItem  = 0;
  732       const char_T *itemName;
  733       MatItem      item;
  734       int_T        retStat       = 0;
  735   
  736       switch (itemKind) {
  737         case DATA_ITEM: {
  738             (void)fprintf(stderr,"Unexpected itemKind = DATA_ITEM in "
  739                                  "rt_ProcessMatItem @A\n");
  740             retStat = -1;
  741             goto EXIT_POINT;
  742         }
  743         case MATRIX_ITEM: {
  744             const MatrixData *var = (const MatrixData *) pItem->data;
  745   
  746             mxID           = var->mxID;
  747             arrayFlags[0]  = mxID;
  748             arrayFlags[0] |= var->logical;
  749             arrayFlags[0] |= var->complex;
  750             if (var->nDims < 2) {
  751                 dims         = _dims;
  752                 dims[0]      = var->nRows;
  753                 dims[1]      = var->nCols;
  754                 nDims        = 2;
  755             } else if (var->nDims >= 2) {
  756                 int32_T k;
  757                 dims = (int32_T*)malloc(sizeof(int32_T)*(var->nDims+1));
  758                 for (k = 0; k < var->nDims; k++) {
  759                     dims[k] = var->dims[k];
  760                 }
  761                 dims[var->nDims] = var->nRows;
  762                 nDims = var->nDims + 1;
  763             }
  764             itemName = var->name;
  765             break;
  766         }
  767         case STRUCT_LOG_VAR_ITEM: {
  768             const StructLogVar *var = (const StructLogVar *) pItem->data;
  769   
  770             mxID          = mxSTRUCT_CLASS;
  771             arrayFlags[0] = mxID;
  772             dims          = _dims;
  773             dims[0]       = 1;
  774             dims[1]       = 1;
  775             itemName      = var->name;
  776             break;
  777         }
  778         case SIGNALS_STRUCT_ITEM: {
  779             const SignalsStruct *var = (const SignalsStruct *) pItem->data;
  780   
  781             mxID          = mxSTRUCT_CLASS;
  782             arrayFlags[0] = mxID;
  783             dims          = _dims;
  784             dims[0]       = 1;
  785             dims[1]       = var->numSignals;
  786             itemName      = &SIGNALS_FIELD_NAME;
  787             break;
  788         }
  789         default:
  790           (void)fprintf(stderr,"Unexpected itemKind=%d in rt_ProcessMatItem @B\n",
  791                         itemKind);
  792           retStat = -1;
  793           goto EXIT_POINT;
  794       }
  795   
  796       /* array flags */
  797       item.nbytes = 2*sizeof(uint32_T);
  798       if (cmd) {
  799           item.type = matUINT32;
  800           item.data = arrayFlags;
  801           if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) {
  802               retStat = 1;
  803               goto EXIT_POINT;
  804           }
  805       } else {
  806           /*LINTED E_CAST_INT_TO_SMALL_INT*/
  807           nBytesInItem += matINT64_ALIGN(matTAG_SIZE + item.nbytes);
  808       }
  809       /* dimensions */
  810       /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
  811       item.nbytes = nDims*sizeof(int32_T);
  812       if (cmd) {
  813           item.type = matINT32;
  814           item.data = dims;
  815           if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) {
  816               retStat = 1;
  817               goto EXIT_POINT;            
  818           }
  819       } else {
  820           /*LINTED E_CAST_INT_TO_SMALL_INT*/
  821           nBytesInItem += matINT64_ALIGN(matTAG_SIZE + item.nbytes);
  822       }
  823       /* name */
  824       item.nbytes = (int32_T)strlen(itemName);
  825       if (cmd) {
  826           item.type = matINT8;
  827           item.data = (const char_T*) itemName;
  828           if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) {
  829               retStat = 1;
  830               goto EXIT_POINT;
  831           }
  832       } else {
  833           nBytesInItem += (item.nbytes <= 4) ? /*LINTED E_CAST_INT_TO_SMALL_INT*/
  834                           matTAG_SIZE : matINT64_ALIGN(matTAG_SIZE + item.nbytes);
  835       }
  836   
  837       if (itemKind == MATRIX_ITEM) {
  838           const MatrixData *var   = (const MatrixData*) pItem->data;
  839           int_T            matID  = rt_GetMatIdFromMxId(mxID);
  840           size_t           elSize = var->elSize;
  841   
  842           /* data */
  843           item.nbytes = (int32_T)(var->nRows * var->nCols * elSize);
  844           if (cmd) {
  845               item.type = matID;
  846               item.data = var->re;
  847               if (rt_WriteItemToMatFile(fp, &item, DATA_ITEM)) {
  848                   retStat = 1;
  849                   goto EXIT_POINT;
  850               }
  851           } else {
  852               nBytesInItem += (item.nbytes <= 4) ? /*LINTED*/
  853                           matTAG_SIZE : matINT64_ALIGN(matTAG_SIZE + item.nbytes);
  854           }
  855           /* imaginary part */
  856           if (var->complex) {
  857               item.nbytes = (int32_T)(var->nRows * var->nCols * elSize);
  858               if (cmd) {
  859                   item.type = matID;
  860                   item.data = var->im;
  861                   if (rt_WriteItemToMatFile(fp, &item, DATA_ITEM)) {
  862                       retStat = 1;
  863                       goto EXIT_POINT;
  864                   }
  865               } else {
  866                   nBytesInItem += (item.nbytes <= 4) ? /*LINTED*/
  867                           matTAG_SIZE : matINT64_ALIGN(matTAG_SIZE + item.nbytes);
  868               }
  869           }
  870       } else {  /* some type of structure item */
  871           const char_T *fieldNames;
  872           int_T        sizeofFieldNames;
  873   
  874           /* field names */
  875           switch (itemKind) {
  876             case STRUCT_LOG_VAR_ITEM: {
  877                 const StructLogVar *var = (const StructLogVar *) pItem->data;
  878                 fieldNames        = rtStructLogVarFieldNames;
  879                 sizeofFieldNames  = var->numActiveFields * mxMAXNAM;
  880                 break;
  881             }
  882             case SIGNALS_STRUCT_ITEM: {
  883                 const SignalsStruct *var = (const SignalsStruct *) pItem->data;
  884                 fieldNames        = var->fieldNames;
  885                 sizeofFieldNames  = var->numActiveFields * mxMAXNAM;
  886                 break;
  887             }
  888             default:
  889               (void)fprintf(stderr, "Unexpected itemKind=%d in "
  890                             "rt_ProcessMatItem @C\n", itemKind);
  891               retStat = -1;
  892               goto EXIT_POINT;
  893           }
  894   
  895           /* write field names */
  896           if (cmd) {
  897               int32_T tmpInt = mxMAXNAM;
  898   
  899               item.nbytes = sizeof(int32_T);
  900               item.type   = matINT32;
  901               item.data   = &tmpInt;
  902               if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) {
  903                   retStat = 1;
  904                   goto EXIT_POINT;
  905               }
  906   
  907               item.nbytes = sizeofFieldNames;
  908               item.type   = matINT8;
  909               item.data   = (const char_T*) fieldNames;
  910               if (rt_WriteItemToMatFile(fp,&item, DATA_ITEM)) {
  911                   retStat = 1;
  912                   goto EXIT_POINT;
  913               }
  914           } else {
  915               /*LINTED E_CAST_INT_TO_SMALL_INT*/
  916               nBytesInItem += matINT64_ALIGN( matTAG_SIZE + matTAG_SIZE +
  917                                               sizeofFieldNames );
  918           }
  919   
  920           /* process each field of the structure */
  921           switch (itemKind) {
  922             case STRUCT_LOG_VAR_ITEM: {
  923                 const StructLogVar *var = pItem->data;
  924   
  925                 /* time */
  926                 {
  927                     const void *data = var->time;
  928   
  929                     if (var->logTime) { /* time is a LogVar, get the MatrixData */
  930                         data = &(((const LogVar*) (var->time))->data);
  931                     }
  932   
  933                     item.type = matMATRIX;
  934                     item.data = data;
  935                     if (cmd) {
  936                         if (rt_WriteItemToMatFile(fp,&item,MATRIX_ITEM)){
  937                             retStat = 1;
  938                             goto EXIT_POINT;
  939                         }
  940                     } else {
  941                         if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM,0)){
  942                             retStat = 1;
  943                             goto EXIT_POINT;
  944                         }
  945                         nBytesInItem += item.nbytes + matTAG_SIZE;
  946                     }
  947                 }
  948   
  949                 /* signals */
  950                 item.type = matMATRIX;
  951                 item.data = &(var->signals);
  952                 if (cmd) {
  953                     if (rt_WriteItemToMatFile(fp,&item,SIGNALS_STRUCT_ITEM)) {
  954                         retStat = 1;
  955                         goto EXIT_POINT;
  956                     }
  957                 } else {
  958                     if (rt_ProcessMatItem(fp, &item, SIGNALS_STRUCT_ITEM,0)) {
  959                         retStat = 1;
  960                         goto EXIT_POINT;
  961                     }
  962                     nBytesInItem += item.nbytes + matTAG_SIZE;
  963                 }
  964   
  965                 /* block name */
  966                 if (var->blockName != NULL) {
  967                     item.type = matMATRIX;
  968                     item.data = var->blockName;
  969                     if (cmd) {
  970                         if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) {
  971                             retStat = 1;
  972                             goto EXIT_POINT;
  973                         }
  974                     } else {
  975                         if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) {
  976                             retStat = 1;
  977                             goto EXIT_POINT;
  978                         }
  979                         nBytesInItem += item.nbytes + matTAG_SIZE;
  980                     }
  981                 }
  982                 break;
  983             }
  984             case SIGNALS_STRUCT_ITEM: {
  985                 const SignalsStruct *var        = pItem->data;
  986                 const LogVar        *values     = var->values;
  987                 const MatrixData    *dimensions = var->dimensions;
  988                 const MatrixData    *labels     = var->labels;
  989                 const MatrixData    *plotStyles = var->plotStyles;
  990                 const MatrixData    *titles     = var->titles;
  991                 const MatrixData    *blockNames = var->blockNames;
  992                 const MatrixData    *stateNames = var->stateNames;
  993                 const MatrixData    *crossMdlRef = var->crossMdlRef;
  994                 const boolean_T logValueDimensions = var->logValueDimensions;
  995                 int_T               i;
  996   
  997                 for (i = 0; i < var->numSignals; i++) {
  998                     /* values */
  999                     item.type = matMATRIX;
 1000                     item.data = &(values->data);
 1001                     if (cmd) {
 1002                         if (rt_WriteItemToMatFile(fp, &item,MATRIX_ITEM)) {
 1003                             retStat = 1;
 1004                             goto EXIT_POINT;
 1005                         }
 1006                     } else {
 1007                         if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) {
 1008                             retStat = 1;
 1009                             goto EXIT_POINT;
 1010                         }
 1011                         nBytesInItem += item.nbytes + matTAG_SIZE;
 1012                     }
 1013   
 1014                     if(logValueDimensions)
 1015                     {
 1016                         /* valueDimensions */
 1017                         /* Since the functions rt_WriteItemToMatFile and 
 1018                            rt_ProcessMatItem deal with MatrixData, 
 1019                            convert valDims to tempData, and fill up the
 1020                            necessary fields.
 1021                         */
 1022                         MatrixData  tempData;
 1023                         (void)memcpy(tempData.name, &VALUEDIMENSIONS_FIELD_NAME, mxMAXNAM);
 1024                         tempData.nRows = values->valDims->nRows;
 1025                         tempData.nCols = values->valDims->nCols;
 1026                         tempData.nDims = 1;
 1027                         tempData._dims[0] = values->valDims->nCols;
 1028                         tempData.re = values->valDims->dimsData;
 1029                         tempData.im = NULL;
 1030                         tempData.dTypeID = SS_DOUBLE;
 1031                         tempData.elSize =  sizeof(real_T);
 1032                         tempData.mxID = mxDOUBLE_CLASS;
 1033                         tempData.logical = 0;
 1034                         tempData.complex = 0;
 1035                         tempData.frameData = 0;
 1036                         tempData.frameSize = 1;
 1037   
 1038                         item.type = matMATRIX;                    
 1039                         item.data = &tempData; /*values->valDims;*/
 1040   
 1041                         if (cmd) {
 1042                             if (rt_WriteItemToMatFile(fp, &item,MATRIX_ITEM)) {
 1043                                 retStat = 1;
 1044                                 goto EXIT_POINT;
 1045                             }
 1046                         } else {
 1047                             if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) {
 1048                                 retStat = 1;
 1049                                 goto EXIT_POINT;
 1050                             }
 1051                             nBytesInItem += item.nbytes + matTAG_SIZE;
 1052                         }
 1053                     }
 1054                     values = values->next;
 1055   
 1056                     /* dimensions */
 1057                     if (dimensions != NULL) {
 1058                         item.type = matMATRIX;
 1059                         item.data = &(dimensions[i]);
 1060                         if (cmd) {
 1061                             if (rt_WriteItemToMatFile(fp,&item, MATRIX_ITEM)) {
 1062                                 retStat = 1;
 1063                                 goto EXIT_POINT;
 1064                             }
 1065                         } else {
 1066                             if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) {
 1067                                 retStat = 1;
 1068                                 goto EXIT_POINT;
 1069                             }
 1070                             nBytesInItem += item.nbytes + matTAG_SIZE;
 1071                         }
 1072                     }
 1073   
 1074                     /* label */
 1075                     item.type = matMATRIX;
 1076                     item.data = &(labels[i]);
 1077                     if (cmd) {
 1078                         if (rt_WriteItemToMatFile(fp, &item,MATRIX_ITEM)) {
 1079                             retStat = 1;
 1080                             goto EXIT_POINT;
 1081                         }
 1082                     } else {
 1083                         if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) {
 1084                             retStat = 1;
 1085                             goto EXIT_POINT;
 1086                         }
 1087                         nBytesInItem += item.nbytes + matTAG_SIZE;
 1088                     }
 1089                     /* title */
 1090                     if (titles != NULL) {
 1091                         item.type = matMATRIX;
 1092                         item.data = &(titles[i]);
 1093                         if (cmd) {
 1094                             if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) {
 1095                                 retStat = 1;
 1096                                 goto EXIT_POINT;
 1097                             }
 1098                         } else {
 1099                             if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) {
 1100                                 retStat = 1;
 1101                                 goto EXIT_POINT;
 1102                             }
 1103                             nBytesInItem += item.nbytes + matTAG_SIZE;
 1104                         }
 1105                     }
 1106                     /* plot style */
 1107                     if (plotStyles != NULL) {
 1108                         item.type = matMATRIX;
 1109                         item.data = &(plotStyles[i]);
 1110                         if (cmd) {
 1111                             if (rt_WriteItemToMatFile(fp,&item, MATRIX_ITEM)) {
 1112                                 retStat = 1;
 1113                                 goto EXIT_POINT;
 1114                             }
 1115                         } else {
 1116                             if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) {
 1117                                 retStat = 1;
 1118                                 goto EXIT_POINT;
 1119                             }
 1120                             nBytesInItem += item.nbytes + matTAG_SIZE;
 1121                         }
 1122                     }
 1123                     /* block name */
 1124                     if (blockNames != NULL) {
 1125                         item.type = matMATRIX;
 1126                         item.data = &(blockNames[i]);
 1127                         if (cmd) {
 1128                             if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) {
 1129                                 retStat = 1;
 1130                                 goto EXIT_POINT;
 1131                             }
 1132                         } else {
 1133                             if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) {
 1134                                 retStat = 1;
 1135                                 goto EXIT_POINT;
 1136                             }
 1137                             nBytesInItem += item.nbytes + matTAG_SIZE;
 1138                         }
 1139                     }
 1140                     /* state name */
 1141                     if (stateNames != NULL) {
 1142                         item.type = matMATRIX;
 1143                         item.data = &(stateNames[i]);
 1144                         if (cmd) {
 1145                             if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) {
 1146                                 retStat = 1;
 1147                                 goto EXIT_POINT;
 1148                             }
 1149                         } else {
 1150                             if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) {
 1151                                 retStat = 1;
 1152                                 goto EXIT_POINT;
 1153                             }
 1154                             nBytesInItem += item.nbytes + matTAG_SIZE;
 1155                         }
 1156                     }
 1157                     /* crossMdlRef */
 1158                     if (crossMdlRef != NULL) {
 1159                         item.type = matMATRIX;
 1160                         item.data = &(crossMdlRef[i]);
 1161                         if (cmd) {
 1162                             if (rt_WriteItemToMatFile(fp, &item, MATRIX_ITEM)) {
 1163                                 retStat = 1;
 1164                                 goto EXIT_POINT;
 1165                             }
 1166                         } else {
 1167                             if (rt_ProcessMatItem(fp, &item, MATRIX_ITEM, 0)) {
 1168                                 retStat = 1;
 1169                                 goto EXIT_POINT;
 1170                             }
 1171                             nBytesInItem += item.nbytes + matTAG_SIZE;
 1172                         }
 1173                     }
 1174                 } /* for i=1:numSignals */
 1175                 break;
 1176             }
 1177             default:
 1178               (void)fprintf(stderr, "Unexpected itemKind=%d in "
 1179                             "rt_ProcessMatItem @D\n", itemKind);
 1180               retStat = -1;
 1181               goto EXIT_POINT;
 1182           }
 1183       } /* end struct item */
 1184   
 1185       if (!cmd) {
 1186           pItem->nbytes = nBytesInItem;
 1187       }
 1188   
 1189     EXIT_POINT:
 1190       if (dims != _dims) {
 1191           FREE(dims);
 1192       }
 1193       return(retStat);
 1194   
 1195   } /* end rt_ProcessMatItem */
 1196   
 1197   
 1198   /* Function: rt_WriteItemToMatFile =============================================
 1199    * Abstract:
 1200    *      Entry function for writing out a mat item to the mat file.
 1201    *
 1202    *      Return values is
 1203    *          == 0 : upon success
 1204    *          <> 0 : upon failure
 1205    */
 1206   static int_T rt_WriteItemToMatFile(FILE         *fp,
 1207                                      MatItem      *pItem,
 1208                                      ItemDataKind itemKind)
 1209   {
 1210       /* Determine the item size */
 1211       if (pItem->type == matMATRIX) {
 1212           if (rt_ProcessMatItem(fp, pItem, itemKind, 0)) return(1);
 1213       }
 1214   
 1215       /* Write the item tag and data */
 1216       if (pItem->nbytes > 4) {
 1217           int32_T nAlignBytes;
 1218   
 1219           if (fwrite(pItem, 1, matTAG_SIZE, fp) != matTAG_SIZE) return(1);
 1220   
 1221           if (pItem->type == matMATRIX) {
 1222               if (rt_ProcessMatItem(fp, pItem, itemKind, 1)) return(1);
 1223           } else {
 1224               if ( fwrite(pItem->data, 1, pItem->nbytes, fp) !=
 1225                                                       ((size_t) pItem->nbytes) ) {
 1226                   return(1);
 1227               }
 1228           }
 1229   
 1230           /* Add offset for 8-byte alignment */
 1231           nAlignBytes = matINT64_ALIGN(pItem->nbytes) - pItem->nbytes;
 1232           if (nAlignBytes > 0) {
 1233               int pad[2] = {0, 0};
 1234               if ( fwrite(pad,1,nAlignBytes,fp) != ((size_t) nAlignBytes) ) {
 1235                   return(1);
 1236               }
 1237           }
 1238       } else {
 1239           MatItem item = {0, 0, NULL};
 1240           item.type = ((uint32_T)(pItem->type))|(((uint32_T)(pItem->nbytes))<<16);
 1241           (void)memcpy(&item.nbytes, pItem->data, pItem->nbytes);
 1242           if (fwrite(&item, 1, matTAG_SIZE, fp) != matTAG_SIZE) return(1);
 1243       }
 1244   
 1245       return(0);
 1246   
 1247   } /* end rt_WriteItemToMatFile */
 1248   
 1249   
 1250   /* Function: rt_WriteMat5FileHeader ============================================
 1251    * Abstract:
 1252    *      Function to write the mat file header.
 1253    *      Return values is
 1254    *          == 0 : upon success
 1255    *          <> 0 : upon failure
 1256    */
 1257   static int_T rt_WriteMat5FileHeader(FILE *fp)
 1258   {
 1259       int_T        nbytes;
 1260       int_T        nspaces;
 1261       int_T        i, n;
 1262       unsigned short ver[2];
 1263       char_T       spaces[16];
 1264       const char_T *matversion = "MATLAB 5.0 MAT-file";
 1265   
 1266       (void)memset(spaces, ' ', sizeof(spaces));
 1267   
 1268       n = (int_T)strlen(matversion);
 1269       nbytes = (int_T)fwrite(matversion, 1, n, fp);
 1270       /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 1271       nspaces = matVERSION_INFO_OFFSET - nbytes;
 1272       /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 1273       n = nspaces % sizeof(spaces);
 1274       nbytes += (int_T)fwrite(spaces, 1, n, fp);
 1275       /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 1276       n = nspaces / sizeof(spaces);
 1277       for (i = 0; i < n; ++i) {
 1278           nbytes += (int_T)fwrite(spaces, 1, sizeof(spaces), fp);
 1279       }
 1280       if (nbytes == matVERSION_INFO_OFFSET) {
 1281           ver[0] = matVERSION;
 1282           ver[1] = matKEY;
 1283           nbytes += (int_T)fwrite(ver, 1, sizeof(ver), fp);
 1284       }
 1285       return(nbytes != matVERSION_INFO_OFFSET + sizeof(ver));
 1286   
 1287   } /* end rt_WriteMat5FileHeader */
 1288   
 1289   
 1290   /* Function: rt_FixupLogVar ====================================================
 1291    * Abstract:
 1292    *	Make the logged variable suitable for MATLAB.
 1293    */
 1294   static const char_T *rt_FixupLogVar(LogVar *var,int verbose)
 1295   {
 1296       int_T  nCols   = var->data.nCols;
 1297       int_T  maxRows = var->data.nRows;
 1298       int_T  nDims   = var->data.nDims;
 1299       size_t elSize  = var->data.elSize;
 1300       int_T  nRows   = (var->wrapped ?  maxRows : var->rowIdx);
 1301   
 1302       var->nDataPoints = var->rowIdx + var->wrapped * maxRows;
 1303   
 1304       if (var->wrapped > 1 || (var->wrapped == 1 && var->rowIdx != 0)) {
 1305           /*
 1306            * Warn the user the circular buffer has wrapped, implying that
 1307            * some data has been lost.
 1308            */
 1309           if( verbose) {
 1310               (void)fprintf(stdout,
 1311                             "*** Log variable %s has wrapped %d times\n"
 1312                             "    using a circular buffer of size %d\n",
 1313                             var->data.name, var->wrapped, var->data.nRows);
 1314           }
 1315           if (var->usingDefaultBufSize) {
 1316               /*
 1317                * If wrapping occurred using the default buffer size,
 1318                * let the user know what size buffer to use in the
 1319                * future to avoid wrapping.  If the default buffer
 1320                * size was not used, the user has no control to specify
 1321                * the correct value.  Wrapping may occur when not using
 1322                * the default buffer if we allocated too small a buffer
 1323                * size for this logvar.  One common case is a toWorkspace
 1324                * block inside of an iterative subsystem - we can not take
 1325                * the number of iterations into account (they may be
 1326                * variable) when allocating the buffer.  In this case,
 1327                * just warn the buffer wrapped and don't tell user they
 1328                * can override the buffer size.
 1329                */
 1330               if( verbose ) {
 1331                   (void)fprintf(stdout,
 1332                                 "*** To avoid wrapping, explicitly specify a\n"
 1333                                 "    buffer size of %d in your Simulink model\n"
 1334                                 "    by adding OPTS=\"-DDEFAULT_BUFFER_SIZE=%d\"\n"
 1335                                 "    as an argument to the ConfigSet MakeCommand\n"
 1336                                 "    parameter\n",
 1337                                 var->nDataPoints, var->nDataPoints);
 1338               }
 1339           }
 1340       }
 1341   
 1342       if (nDims < 2 && nCols > 1) {  /* Transpose? */
 1343           /* Don't need to transpose valueDimensions */
 1344           int_T  nEl    = nRows*nCols;
 1345           char   *src   = var->data.re;
 1346           char   *pmT;
 1347           int_T  k;
 1348   
 1349           /**********************************
 1350            * If memory cannot be allocated, *
 1351            * write to a temporary buffer    *
 1352            **********************************/
 1353           if ((pmT = malloc(nEl*elSize)) == NULL) {
 1354               FILE  *fptr;
 1355               char  fName[mxMAXNAM];
 1356   
 1357               (void)sprintf(fName, "%s%s", var->data.name, "_rtw_tmw.tmw");
 1358               if ((fptr=fopen(fName,"w+b")) == NULL) {
 1359                   (void)fprintf(stderr,"*** Error opening %s",fName);
 1360                   return("unable to open data file\n");
 1361               }
 1362   
 1363               /****************************
 1364                * Write the data to a file *
 1365                ****************************/
 1366               for (k=0; k<nEl; k++) {
 1367                   int_T kT   = nCols*(k%nRows) + (k/nRows);
 1368                   char  *dst = src + kT*elSize;
 1369                   (void)fwrite(dst, elSize, 1, fptr);
 1370               }
 1371               if (var->data.complex) {
 1372                   char *pmiT = var->data.re;
 1373                   src  = var->data.im;
 1374                   for (k=0; k<nEl; k++) {
 1375                       int_T kT   = nRows*(k%nCols) + (k/nCols);
 1376                       char  *dst = pmiT + kT*elSize;
 1377                       (void)memcpy(dst, src, elSize);
 1378                       src += elSize;
 1379                   }
 1380                   var->data.re = var->data.im;
 1381                   var->data.im = pmiT;
 1382               }
 1383   
 1384               /*******************************
 1385                * Read the data from the file *
 1386                *******************************/
 1387               (void)rewind(fptr);
 1388               (void)fread(var->data.re, elSize, nEl, fptr);
 1389               (void)fclose(fptr);
 1390               (void)remove(fName);
 1391           } else {
 1392               for (k=0; k<nEl; k++) {
 1393                   int_T kT   = nRows*(k%nCols) + (k/nCols);
 1394                   char  *dst = pmT + kT*elSize;
 1395                   (void)memcpy(dst, src, elSize);
 1396                   src += elSize;
 1397               }
 1398               if (var->data.complex) {
 1399                   char *pmiT = var->data.re;
 1400                   src  = var->data.im;
 1401                   for (k=0; k<nEl; k++) {
 1402                       int_T kT   = nRows*(k%nCols) + (k/nCols);
 1403                       char  *dst = pmiT + kT*elSize;
 1404                       (void)memcpy(dst, src, elSize);
 1405                       src += elSize;
 1406                   }
 1407                   var->data.re = var->data.im;
 1408                   var->data.im = pmiT;
 1409               }
 1410               FREE(var->data.re);
 1411               var->data.re = pmT;
 1412           }
 1413       } /* Transpose? */
 1414   
 1415       if (var->wrapped > 0 && var->rowIdx != 0 ) {  /* Rotate? */
 1416           char_T *buffer    = var->data.re;
 1417           int_T  done       = 0; /* done: 0 (1) rotate real (imag) part. */
 1418   
 1419           do {
 1420               char_T *col       = buffer;
 1421               int_T  rowOffset  = (int_T)((nDims == 1) ? (elSize) : (elSize * nCols));
 1422               int_T  colOffset  = (int_T)((nDims == 1)?  (nRows*elSize) : elSize);
 1423               int_T  zeroIdx    = var->rowIdx;
 1424               int_T  j;
 1425   
 1426               for (j = 0 ; j < nCols; ++j, col += colOffset) {
 1427                   int_T   swapCount;
 1428                   int_T   srcIdx;
 1429                   int_T   dstIdx;
 1430                   int_T   tmpIdx;
 1431                   MatReal tmp;
 1432   
 1433                   for (tmpIdx=0, swapCount=0; swapCount < nRows; tmpIdx++) {
 1434                       (void)memcpy(&tmp, col + tmpIdx*rowOffset, elSize);
 1435   
 1436                       dstIdx=tmpIdx; 
 1437                       srcIdx = ((dstIdx + zeroIdx) % nRows);
 1438                       while (srcIdx != tmpIdx) {
 1439                           (void)memcpy(col + dstIdx*rowOffset,
 1440                                        col + srcIdx*rowOffset,
 1441                                        elSize);
 1442                           ++swapCount;
 1443                           dstIdx = srcIdx;
 1444                           srcIdx = ((dstIdx + zeroIdx) % nRows);
 1445                           
 1446                       }
 1447                       (void)memcpy(col + dstIdx*rowOffset, &tmp, elSize);
 1448                       ++swapCount;
 1449                   }
 1450               }
 1451               done ++;
 1452               /* need to rotate the imaginary part */
 1453           } while ((done == 1) && ((buffer = var->data.im) != NULL));
 1454   
 1455           var->rowIdx = 0;
 1456       } /* Rotate? */
 1457   
 1458       /*
 1459        * We might have allocated more number of rows than the number of data
 1460        * points that have been logged, in which case set nRows to nDataPoints
 1461        * so that only these values get saved.
 1462        */
 1463       if (var->nDataPoints < var->data.nRows) {
 1464           var->data.nRows = var->nDataPoints;
 1465           if(var->valDims != NULL){
 1466               size_t elSizeValDims = sizeof(real_T);
 1467               int_T  k;
 1468               real_T *dimsData = var->valDims->dimsData + nRows;
 1469               /* 
 1470                  Keep nRows of values and that of valueDimensions consistent 
 1471                  for variable-size signals.
 1472               */
 1473               var->valDims->nRows = var->data.nRows;
 1474               /*
 1475                  Also need to move data when shrinking the array size,
 1476                  because valueDimensions data is stored in array format. 
 1477                  e.g. maxRows = 4; nRows = 2; nDims = 3;
 1478                  Before fixing up the logVar, the locations of data are as below:
 1479                  (x, y, z -- useful data / o -- junk)
 1480                  a[0] = x    a[4] = y    a[8] = z
 1481                  a[1] = x    a[5] = y    a[9] = z
 1482                  a[2] = o    a[6] = o    a[10]= o
 1483                  a[3] = o    a[7] = o    a[11]= o
 1484                  After fixing up the logVar, we want the data to be stored as:
 1485                  a[0] = x    a[4] = z    a[8] = o
 1486                  a[1] = x    a[5] = z    a[9] = o
 1487                  a[2] = y    a[6] = o    a[10]= o
 1488                  a[3] = y    a[7] = o    a[11]= o
 1489               */
 1490               for(k = 1; k < nDims; k++){
 1491                   (void) memcpy(dimsData, 
 1492                                 var->valDims->dimsData + k*maxRows,
 1493                                 elSizeValDims * nRows);
 1494                   dimsData += nRows;
 1495               }
 1496           }
 1497       }
 1498       return(NULL);
 1499   
 1500   } /* end rt_FixupLogVar */
 1501   
 1502   
 1503   /* Function: rt_LoadModifiedLogVarName =========================================
 1504    * Abstract:
 1505    *      The name of the logged variable is obtained from the input argument
 1506    *      varName and the nameModifier which is obtained from the simstruct. If
 1507    *      the nameModifier begins with an '_', then nameModifier is post-pended to
 1508    *      varName to obtain the name of the logged variable. If the first
 1509    *      character does not begin with an '_', then the nameModifier is
 1510    *      pre-pended to varName.
 1511    *
 1512    * Examples:
 1513    *     a)  varName = "tout" & nameModifier = "_rt"  => logVarName = "tout_rt"
 1514    *     b)  varName = "tout" & nameModifier = "rt_"  => logVarName = "rt_tout"
 1515    *     c)  varName = "tout" & nameModifier = "none" => logVarName = "tout"
 1516    */
 1517   static void rt_LoadModifiedLogVarName(const RTWLogInfo *li,         /* in  */
 1518                                         const char       *varName,    /* in  */
 1519                                         char             *logVarName) /* out */
 1520   {
 1521       int_T        nameLen;
 1522       const char_T *nameModifier = rtliGetLogVarNameModifier(li);
 1523   
 1524       if (nameModifier != NULL && strcmp(nameModifier,"none")==0) {
 1525           nameModifier = NULL;
 1526       }
 1527   
 1528       logVarName[mxMAXNAM-1] = '\0';
 1529       if (nameModifier == NULL) {
 1530           (void)strncpy(logVarName, varName, mxMAXNAM-1);
 1531       } else if (nameModifier[0] == '_') {
 1532           (void)strncpy(logVarName, varName, mxMAXNAM-1);
 1533           nameLen = (int_T)strlen(logVarName);
 1534           (void)strncat(logVarName, nameModifier, mxMAXNAM-1-nameLen);
 1535       } else {
 1536           (void)strncpy(logVarName, nameModifier, mxMAXNAM-1);
 1537           nameLen = (int_T)strlen(logVarName);
 1538           (void)strncat(logVarName, varName, mxMAXNAM-1-nameLen);
 1539       }
 1540   
 1541   } /* end rt_LoadModifiedLogVarName */
 1542   
 1543   
 1544   /* Function: rt_GetActualDTypeID ===============================================
 1545    * Abstract:
 1546    *	Given a built-in data type id, return the actual data type id.
 1547    *	The only time these are different is when real_T has been mapped
 1548    *	to a single.
 1549    */
 1550   static BuiltInDTypeId rt_GetActualDTypeID(BuiltInDTypeId dTypeID)
 1551   {
 1552       /*LINTED E_FALSE_LOGICAL_EXPR*/
 1553       if (dTypeID == SS_DOUBLE && sizeof(real_T) != 8) {
 1554           return(SS_SINGLE);
 1555       } else {
 1556           return(dTypeID);
 1557       }
 1558   
 1559   } /* end rt_GetActualDTypeID */
 1560   
 1561   
 1562   /* Function: rt_DestroyLogVar ==================================================
 1563    * Abstract:
 1564    *      Destroy the log var linked list.
 1565    */
 1566   static void rt_DestroyLogVar(LogVar *head)
 1567   {
 1568       while(head) {
 1569           LogVar *var = head;
 1570           head = var->next;
 1571           FREE(var->data.re);
 1572           FREE(var->data.im);
 1573           if (var->data.dims != var->data._dims) {
 1574               FREE(var->data.dims);
 1575           }
 1576           /* free valDims if necessary */
 1577           if(var->valDims != NULL) {
 1578               FREE(var->valDims->dimsData);
 1579               FREE(var->valDims);
 1580           }
 1581           /* free coords, strides and currStrides if necessary */
 1582           FREE(var->coords);
 1583           FREE(var->strides);
 1584           FREE(var->currStrides);
 1585   
 1586           FREE(var);
 1587       }
 1588   
 1589   } /* end rt_DestroyLogVar */
 1590   
 1591   
 1592   /* Function: rt_DestroyStructLogVar ============================================
 1593    * Abstract:
 1594    *      Destroy the struct log var linked list.
 1595    */
 1596   static void rt_DestroyStructLogVar(StructLogVar *head)
 1597   {
 1598       while(head) {
 1599           StructLogVar *var = head;
 1600   
 1601           head = var->next;
 1602   
 1603           if (var->logTime) { /* time is LogVar */
 1604               rt_DestroyLogVar(var->time);
 1605           } else {        /* time is MatrixData */
 1606               FREE(var->time);
 1607           }
 1608           rt_DestroyLogVar(var->signals.values);
 1609           FREE(var->signals.labels);
 1610           FREE(var->signals.plotStyles);
 1611           FREE(var->signals.dimensions);
 1612           FREE(var->signals.titles);
 1613           FREE(var->signals.blockNames);
 1614           FREE(var->signals.stateNames);
 1615           FREE(var->signals.crossMdlRef);
 1616           FREE(var->blockName);
 1617           FREE(var);
 1618       }
 1619   
 1620   } /* end rt_DestroyStructLogVar */
 1621   
 1622   
 1623   /* Function: rt_InitSignalsStruct ==============================================
 1624    * Abstract:
 1625    *      Initialize the signals structure in the struct log variable.
 1626    *
 1627    * Returns:
 1628    *	== NULL  => success.
 1629    *	~= NULL  => failure, the return value is a pointer to the error
 1630    *                           message, which is also set in the simstruct.
 1631    */
 1632   static const char_T *rt_InitSignalsStruct(RTWLogInfo             *li,
 1633                                             const real_T           startTime,
 1634                                             const real_T           finalTime,
 1635                                             const real_T           inStepSize,
 1636                                             const char_T           **errStatus,
 1637                                             StructLogVar           *var,
 1638                                             int_T                  maxRows,
 1639                                             int_T                  decimation,
 1640                                             real_T                 sampleTime,
 1641                                             const RTWLogSignalInfo *sigInfo)
 1642   {
 1643       int_T                i, sigIdx;
 1644       SignalsStruct        *sig          = &(var->signals);
 1645       int_T                nSignals      = sigInfo->numSignals;
 1646       const int_T          *numCols      = sigInfo->numCols;
 1647       const int_T          *numDims      = sigInfo->numDims;
 1648       const int_T          *dims         = sigInfo->dims;
 1649       const BuiltInDTypeId *dTypes       = sigInfo->dataTypes;
 1650       const int_T          *cSgnls       = sigInfo->complexSignals;
 1651       const int_T          *fData        = sigInfo->frameData;
 1652       const char_T         **labels      = sigInfo->labels.cptr;
 1653       const int_T          *plotStyles   = sigInfo->plotStyles;
 1654       const char_T         *titles       = sigInfo->titles;
 1655       const int_T          *titleLen     = sigInfo->titleLengths;
 1656       const char_T         **blockNames  = sigInfo->blockNames.cptr;
 1657       const char_T         **stateNames  = sigInfo->stateNames.cptr;
 1658       const boolean_T      *crossMdlRef  = sigInfo->crossMdlRef;
 1659   
 1660       void                 **currSigDims = sigInfo->currSigDims;
 1661       int_T                *currSigDimsSize = sigInfo->currSigDimsSize;
 1662       LogVar               *prevValues   = NULL;
 1663       int_T                dimsOffset    = 0;
 1664       boolean_T            *isVarDims    = sigInfo->isVarDims;
 1665       /* if any signal is variable-size, the field 'valueDimensions' is needed */
 1666       boolean_T            logValueDimensions = false;
 1667       const RTWLogDataTypeConvert *pDTConvInfo = sigInfo->dataTypeConvert;
 1668   
 1669       /* reset error status */
 1670       *errStatus = NULL;
 1671   
 1672       sig->numActiveFields = 1;
 1673       sig->numSignals      = nSignals;
 1674   
 1675       sig->isVarDims = isVarDims;
 1676       /* check whether we need valueDimensions field*/
 1677       for (i=0; i<nSignals; i++){
 1678           if(isVarDims[i]){
 1679               logValueDimensions = true;
 1680               break;
 1681           }
 1682       }
 1683   
 1684       /* values */
 1685       dimsOffset = 0;
 1686       for (i = 0; i < nSignals; i++) {
 1687           BuiltInDTypeId dt = (dTypes) ? dTypes[i] : SS_DOUBLE;
 1688           int_T          cs = (cSgnls) ? cSgnls[i] : 0;
 1689           int_T          fd = (fData)  ? fData[i]  : 0;
 1690           int_T          nd = (numDims) ? numDims[i] : 1;
 1691   
 1692           const RTWLogDataTypeConvert *pDTConvInfoCur =
 1693                          (pDTConvInfo)  ? (pDTConvInfo+i)  : 0;
 1694   
 1695           LogVar *values = NULL;
 1696           LogValDimsStat logValDimsStat;
 1697   
 1698           if(!logValueDimensions){
 1699               logValDimsStat = NO_LOGVALDIMS;
 1700           }
 1701           else{
 1702               logValDimsStat = isVarDims[i] ? LOGVALDIMS_VARDIMS :  
 1703                                               LOGVALDIMS_EMPTYMX;
 1704           }
 1705   
 1706           values = rt_CreateLogVarWithConvert(li, startTime, finalTime,
 1707                                               inStepSize, errStatus,
 1708                                               &VALUES_FIELD_NAME,
 1709                                               dt, 
 1710                                               pDTConvInfoCur,
 1711                                               0, cs, fd,
 1712                                               numCols[i],nd,
 1713                                               dims + dimsOffset,
 1714                                               logValDimsStat,
 1715                                               currSigDims + dimsOffset,
 1716                                               currSigDimsSize + dimsOffset,
 1717                                               maxRows,decimation,sampleTime, 0);
 1718   
 1719           if (values == NULL) goto ERROR_EXIT;
 1720   
 1721           if (sig->values == NULL) {
 1722               sig->values = values;
 1723           } else {
 1724               prevValues->next = values;
 1725           }
 1726           prevValues = values;
 1727           dimsOffset += nd;
 1728       }
 1729   
 1730       if(logValueDimensions){
 1731           ++sig->numActiveFields;
 1732           sig->logValueDimensions = true;
 1733       }
 1734       else{
 1735           sig->logValueDimensions = false;
 1736       }
 1737   
 1738       /* Dimensions */
 1739       {
 1740           real_T         *data;
 1741           size_t	       nbytes;
 1742           int_T          dataLen    = 0;
 1743           BuiltInDTypeId dTypeId    = rt_GetActualDTypeID(SS_DOUBLE);
 1744           size_t         dataOffset = nSignals*sizeof(MatrixData);
 1745           uint_T         overhang   = (uint_T)(dataOffset % sizeof(real_T));
 1746   
 1747           if (overhang) {
 1748               dataOffset += (sizeof(real_T) - overhang);
 1749           }
 1750           for (i=0; i< nSignals; i++) {
 1751               int_T nd = (numDims) ? numDims[i] : 1;
 1752               dataLen += nd;
 1753           }
 1754           nbytes = dataOffset + dataLen*sizeof(real_T);
 1755   
 1756           if ( (sig->dimensions = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT;
 1757   
 1758           data = (real_T*) (((char_T*) (sig->dimensions)) + dataOffset);
 1759   
 1760           for (i = 0; i < dataLen; i++) {
 1761             data[i] = dims[i]; /* cannot memcpy double <- int */
 1762           }
 1763   
 1764           for (i = 0; i < nSignals; i++) {
 1765               MatrixData *mtxData = &(sig->dimensions[i]);
 1766               int_T nd = (numDims) ? numDims[i] : 1;
 1767   
 1768               (void)memcpy(mtxData->name, &DIMENSION_FIELD_NAME, mxMAXNAM);
 1769   
 1770               mtxData->nRows   = 1;
 1771               mtxData->nCols   = nd;
 1772   
 1773               mtxData->nDims   = 1; /* assume */
 1774               mtxData->dims    = mtxData->_dims;
 1775               mtxData->dims[0] = mtxData->nCols;
 1776   
 1777               mtxData->re      = data;
 1778               mtxData->im      = NULL;
 1779               mtxData->dTypeID = dTypeId;
 1780               mtxData->mxID    = rt_GetMxIdFromDTypeId(dTypeId);
 1781               mtxData->elSize  = rt_GetSizeofDataType(dTypeId);
 1782               mtxData->logical = 0U;
 1783               mtxData->complex = 0U;
 1784   
 1785               data += nd;
 1786           }
 1787           ++sig->numActiveFields;
 1788       }
 1789   
 1790       /* labels */
 1791       if (labels != NULL) {
 1792           short   *data;
 1793           size_t  nbytes;
 1794           int_T   dataLen    = 0;
 1795           size_t  dataOffset = nSignals * sizeof(MatrixData);
 1796           uint_T  overhang   = (uint_T)(dataOffset % sizeof(short));
 1797           int_T dataIdx = 0;
 1798   
 1799           for (i=0;i<nSignals;i++) {
 1800               if (labels[i] != NULL){
 1801                   dataLen = dataLen + (int_T)strlen(labels[i]);
 1802               }
 1803           }
 1804   
 1805           if (overhang) {
 1806               dataOffset += (sizeof(short) - overhang);
 1807           }
 1808           nbytes = dataOffset + dataLen*sizeof(short);
 1809   
 1810           if ( (sig->labels = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT;
 1811   
 1812           data = (short*) (((char_T*) (sig->labels)) + dataOffset);
 1813           for(sigIdx=0;sigIdx<nSignals;sigIdx++) {
 1814               int_T labelLen = (labels[sigIdx]==NULL) ? 0 : (int_T)strlen(labels[sigIdx]);
 1815               for (i = 0; i < labelLen; i++) {
 1816                   data[dataIdx++] = labels[sigIdx][i];
 1817               }
 1818           }
 1819   
 1820           for (i = 0; i < nSignals; i++) {
 1821               MatrixData *mtxData = &(sig->labels[i]);
 1822               int_T labelLen = (int_T)strlen(labels[i]);
 1823   
 1824               (void)memcpy(mtxData->name, &LABEL_FIELD_NAME, mxMAXNAM);
 1825               mtxData->nRows   = (labelLen) ? 1 : 0;
 1826               mtxData->nCols   = labelLen;
 1827   
 1828               mtxData->re      = data;
 1829               mtxData->im      = NULL;
 1830   
 1831               mtxData->nDims   = 1; /* assume */
 1832               mtxData->dims    = mtxData->_dims;
 1833               mtxData->dims[0] = mtxData->nCols;
 1834   
 1835               mtxData->dTypeID = SS_INT16;
 1836               mtxData->mxID    = mxCHAR_CLASS;
 1837               mtxData->elSize  = sizeof(short);
 1838               mtxData->logical = 0U;
 1839               mtxData->complex = 0U;
 1840   
 1841               data += labelLen;
 1842           }
 1843           ++sig->numActiveFields;
 1844       }
 1845   
 1846       /* plot styles */
 1847       if (plotStyles != NULL) {
 1848           real_T         *data;
 1849           size_t	       nbytes;
 1850           int_T          dataLen    = 0;
 1851           BuiltInDTypeId dTypeId    = rt_GetActualDTypeID(SS_DOUBLE);
 1852           /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 1853           size_t         dataOffset = nSignals*sizeof(MatrixData);
 1854           /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 1855           uint_T         overhang   = (uint_T)(dataOffset % sizeof(real_T));
 1856   
 1857           if (overhang) {
 1858               dataOffset += (sizeof(real_T) - overhang);
 1859           }
 1860           for (i=0; i< nSignals; i++) {
 1861               dataLen += numCols[i];
 1862           }
 1863           /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 1864           nbytes = dataOffset + dataLen*sizeof(real_T);
 1865   
 1866           if ( (sig->plotStyles = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT;
 1867   
 1868           /*LINTED E_BAD_PTR_CAST_ALIGN*/
 1869           data = (real_T*) (((char_T*) (sig->plotStyles)) + dataOffset);
 1870   
 1871           for (i = 0; i < dataLen; i++) {
 1872               data[i] = plotStyles[i];
 1873           }
 1874   
 1875           dimsOffset = 0;
 1876           for (i = 0; i < nSignals; i++) {
 1877               MatrixData *mtxData = &(sig->plotStyles[i]);
 1878               
 1879               (void)memcpy(mtxData->name, &PLOTSTYLE_FIELD_NAME, mxMAXNAM);
 1880   
 1881               mtxData->nRows   = (numCols[i]) ? 1 : 0;
 1882               mtxData->nCols   = numCols[i];
 1883   
 1884               mtxData->nDims   = numDims[i];
 1885               
 1886               if(mtxData->nDims > 2) {
 1887                   if ((mtxData->dims = calloc(mtxData->nDims, sizeof(int_T))) == NULL) goto ERROR_EXIT;
 1888               } else {
 1889                   mtxData->dims    = mtxData->_dims;
 1890               }
 1891               
 1892               mtxData->dims[0] = *(dims + dimsOffset);
 1893               if(mtxData->nDims >= 2) {
 1894                   int32_T j;
 1895                   for (j=1; j<mtxData->nDims; j++) {
 1896                       mtxData->dims[j] = *(dims + dimsOffset + j);
 1897                   }
 1898               }
 1899   
 1900               mtxData->re      = data;
 1901               mtxData->im      = NULL;
 1902               mtxData->dTypeID = dTypeId;
 1903               mtxData->mxID    = rt_GetMxIdFromDTypeId(dTypeId);
 1904               mtxData->elSize  = rt_GetSizeofDataType(dTypeId);
 1905               mtxData->logical = 0U;
 1906               mtxData->complex = 0U;
 1907   
 1908               data       += numCols[i];
 1909               dimsOffset += numDims[i];
 1910           }
 1911           ++sig->numActiveFields;
 1912       }
 1913   
 1914       /* titles */
 1915       if (titles != NULL) {
 1916           short  *data;
 1917           size_t nbytes;
 1918           int_T  dataLen    = (int_T)strlen(titles);
 1919           /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 1920           size_t  dataOffset = nSignals * sizeof(MatrixData);
 1921           /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 1922           uint_T  overhang   = (uint_T)(dataOffset % sizeof(short));
 1923   
 1924           if (overhang) {
 1925               dataOffset += (sizeof(short) - overhang);
 1926           }
 1927           /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 1928           nbytes = dataOffset + dataLen*sizeof(short);
 1929   
 1930           if ( (sig->titles = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT;
 1931   
 1932           /*LINTED E_BAD_PTR_CAST_ALIGN*/
 1933           data = (short*) (((char_T*) (sig->titles)) + dataOffset);
 1934           for (i = 0; i < dataLen; i++) {
 1935               data[i] = titles[i];
 1936           }
 1937   
 1938           for (i = 0; i < nSignals; i++) {
 1939               MatrixData *mtxData = &(sig->titles[i]);
 1940   
 1941               (void)memcpy(mtxData->name, &TITLE_FIELD_NAME, mxMAXNAM);
 1942               if (titleLen) {
 1943                   mtxData->nRows   = (titleLen[i]) ? 1 : 0;
 1944                   mtxData->nCols   = titleLen[i];
 1945               } else {
 1946                   mtxData->nRows   = (dataLen) ? 1 : 0;
 1947                   mtxData->nCols   = dataLen;
 1948               }
 1949   
 1950               mtxData->nDims   = 1; /* assume */
 1951               mtxData->dims    = mtxData->_dims;
 1952               mtxData->dims[0] = mtxData->nCols;
 1953   
 1954               mtxData->re      = data;
 1955               mtxData->im      = NULL;
 1956               mtxData->dTypeID = SS_INT16;
 1957               mtxData->mxID    = mxCHAR_CLASS;
 1958               mtxData->elSize  = sizeof(short);
 1959               mtxData->logical = 0U;
 1960               mtxData->complex = 0U;
 1961   
 1962               data += ((titleLen) ? titleLen[i] : dataLen);
 1963           }
 1964           ++sig->numActiveFields;
 1965       }
 1966   
 1967       /* block names */
 1968       if (blockNames != NULL)     {
 1969           short  *data;
 1970           size_t nbytes;
 1971           int_T  dataLen = 0;
 1972           size_t dataOffset = nSignals * sizeof(MatrixData);
 1973           uint_T overhang   = (uint_T)(dataOffset % sizeof(short));
 1974           int_T  dataIdx = 0;
 1975   
 1976           for (i=0;i<nSignals;i++) {
 1977               if (blockNames[i] != NULL) {
 1978                   dataLen = dataLen + (int_T)strlen(blockNames[i]);
 1979               }
 1980           }
 1981   
 1982           if (overhang) {
 1983               dataOffset += (sizeof(short) - overhang);
 1984           }
 1985   
 1986           nbytes = dataOffset + dataLen*sizeof(short);
 1987   
 1988           if ( (sig->blockNames = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT;
 1989   
 1990           data = (short*) (((char_T*) (sig->blockNames)) + dataOffset);
 1991   
 1992           for(sigIdx=0;sigIdx<nSignals;sigIdx++) {
 1993               int_T nameLen = (blockNames[sigIdx]==NULL) ? 0 : 
 1994                   (int_T)strlen(blockNames[sigIdx]);
 1995               for (i = 0; i < nameLen; i++) {
 1996                   data[dataIdx++] = blockNames[sigIdx][i];
 1997               }
 1998           }
 1999   
 2000           for (i = 0; i < nSignals; i++) {
 2001               MatrixData *mtxData = &(sig->blockNames[i]);
 2002               int_T blockNameLen = (int_T)strlen(blockNames[i]);
 2003   
 2004               (void)memcpy(mtxData->name, &BLOCKNAME_FIELD_NAME, mxMAXNAM);
 2005               mtxData->nRows   = (blockNameLen) ? 1 : 0;
 2006               mtxData->nCols   = blockNameLen;
 2007   
 2008               mtxData->nDims   = 1; /* assume */
 2009               mtxData->dims    = mtxData->_dims;
 2010               mtxData->dims[0] = mtxData->nCols;
 2011   
 2012               mtxData->re      = data;
 2013               mtxData->im      = NULL;
 2014               mtxData->dTypeID = SS_INT16;
 2015               mtxData->mxID    = mxCHAR_CLASS;
 2016               mtxData->elSize  = sizeof(short);
 2017               mtxData->logical = 0U;
 2018               mtxData->complex = 0U;
 2019   
 2020               data += blockNameLen;
 2021           }
 2022           ++sig->numActiveFields;
 2023           if(logValueDimensions){
 2024               sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames;
 2025           }
 2026           else{
 2027               sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames_noValDims;
 2028           }
 2029   
 2030       } else {
 2031           if(logValueDimensions){
 2032               sig->fieldNames = rtLocalLoggingSignalsStructFieldNames;
 2033           }
 2034           else{
 2035               sig->fieldNames = rtLocalLoggingSignalsStructFieldNames_noValDims;
 2036           }
 2037   
 2038       }
 2039   
 2040       /* state names */
 2041       if (stateNames != NULL) {
 2042           short  *data;
 2043           size_t nbytes;
 2044           int_T  dataLen = 0;
 2045           size_t dataOffset = nSignals * sizeof(MatrixData);
 2046           uint_T overhang   = (uint_T)(dataOffset % sizeof(short));
 2047           int_T  dataIdx = 0;
 2048   
 2049           for (i=0;i<nSignals;i++) {
 2050               if (stateNames[i] != NULL) {
 2051                   dataLen = dataLen + (int_T)strlen(stateNames[i]);
 2052               }
 2053           }
 2054   
 2055           if (overhang) {
 2056               dataOffset += (sizeof(short) - overhang);
 2057           }
 2058   
 2059           nbytes = dataOffset + dataLen*sizeof(short);
 2060   
 2061           if ( (sig->stateNames = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT;
 2062   
 2063           data = (short*) (((char_T*) (sig->stateNames)) + dataOffset);
 2064   
 2065           for(sigIdx=0;sigIdx<nSignals;sigIdx++) {
 2066               int_T nameLen = (stateNames[sigIdx]==NULL) ? 0 : 
 2067                   (int_T)strlen(stateNames[sigIdx]);
 2068               for (i = 0; i < nameLen; i++) {
 2069                   data[dataIdx++] = stateNames[sigIdx][i];
 2070               }
 2071           }
 2072   
 2073           for (i = 0; i < nSignals; i++) {
 2074               MatrixData *mtxData = &(sig->stateNames[i]);
 2075               int_T stateNameLen = (int_T)strlen(stateNames[i]);
 2076   
 2077               (void)memcpy(mtxData->name, &STATENAME_FIELD_NAME, mxMAXNAM);
 2078               mtxData->nRows   = (stateNameLen) ? 1 : 0;
 2079               mtxData->nCols   = stateNameLen;
 2080   
 2081               mtxData->nDims   = 1; /* assume */
 2082               mtxData->dims    = mtxData->_dims;
 2083               mtxData->dims[0] = mtxData->nCols;
 2084   
 2085               mtxData->re      = data;
 2086               mtxData->im      = NULL;
 2087               mtxData->dTypeID = SS_INT16;
 2088               mtxData->mxID    = mxCHAR_CLASS;
 2089               mtxData->elSize  = sizeof(short);
 2090               mtxData->logical = 0U;
 2091               mtxData->complex = 0U;
 2092   
 2093               data += stateNameLen;
 2094           }
 2095           ++sig->numActiveFields;
 2096   
 2097           if(logValueDimensions){
 2098               sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames;
 2099           }
 2100           else{
 2101               sig->fieldNames = rtGlobalLoggingSignalsStructFieldNames_noValDims;
 2102           }
 2103   
 2104       }
 2105   
 2106       /* CrossMdlRef */
 2107       if (crossMdlRef != NULL) {
 2108           real_T  *data;
 2109           size_t nbytes;
 2110           size_t dataOffset = nSignals * sizeof(MatrixData);
 2111           uint_T overhang   = (uint_T)(dataOffset % sizeof(real_T));
 2112   
 2113           if (overhang) {
 2114               dataOffset += (sizeof(real_T) - overhang);
 2115           }
 2116   
 2117           nbytes = dataOffset + nSignals*sizeof(real_T);
 2118   
 2119           if ( (sig->crossMdlRef = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT;
 2120   
 2121           data = (real_T*) (((char_T*) (sig->crossMdlRef)) + dataOffset);
 2122   
 2123           for(sigIdx=0;sigIdx<nSignals;sigIdx++) {
 2124               data[sigIdx] = crossMdlRef[sigIdx];
 2125           }
 2126   
 2127           for (i = 0; i < nSignals; i++) {
 2128               MatrixData *mtxData = &(sig->crossMdlRef[i]);
 2129   
 2130               (void)memcpy(mtxData->name, &CROSS_MDL_REF_FIELD_NAME, mxMAXNAM);
 2131               mtxData->nRows   = 1;
 2132               mtxData->nCols   = 1;
 2133               mtxData->nDims   = 1; /* => matlab scalar */
 2134   
 2135               mtxData->re      = &data[i];
 2136               mtxData->im      = NULL;
 2137               mtxData->dTypeID = SS_DOUBLE;
 2138               mtxData->mxID    = rt_GetMxIdFromDTypeId(SS_DOUBLE);
 2139               mtxData->elSize  = sizeof(real_T);
 2140               mtxData->logical = matLOGICAL_BIT;
 2141               mtxData->complex = 0U;
 2142               mtxData->frameData = 0;
 2143               mtxData->frameSize = 1;
 2144           }
 2145           ++sig->numActiveFields;
 2146       }
 2147       
 2148       return(NULL); /* NORMAL_EXIT */
 2149   
 2150     ERROR_EXIT:
 2151   
 2152       (void)fprintf(stderr, "*** Error creating signals structure "
 2153                     "in the struct log variable %s\n", var->name);
 2154       if (*errStatus == NULL) {
 2155           *errStatus = rtMemAllocError;
 2156       }
 2157       rt_DestroyLogVar(sig->values);
 2158       FREE(sig->labels);
 2159       FREE(sig->plotStyles);
 2160       FREE(sig->dimensions);
 2161       FREE(sig->titles);
 2162       FREE(sig->blockNames);
 2163       FREE(sig->stateNames);
 2164       FREE(sig->crossMdlRef);
 2165   
 2166       return(*errStatus);
 2167   
 2168   } /* end rt_InitSignalsStruct */
 2169   
 2170   
 2171   /* Function: local_CreateStructLogVar ==========================================
 2172    * Abstract:
 2173    *      Create a logging variable in the structure format.
 2174    *
 2175    * Returns:
 2176    *      ~= NULL  => success, returns the log variable created.
 2177    *      == NULL  => failure, error message set in the simstruct.
 2178    */
 2179   static StructLogVar *local_CreateStructLogVar(
 2180       RTWLogInfo              *li,
 2181       const real_T            startTime,
 2182       const real_T            finalTime,
 2183       const real_T            inStepSize,
 2184       const char_T            **errStatus,
 2185       const char_T            *varName,
 2186       boolean_T               logTime,
 2187       int_T                   maxRows,
 2188       int_T                   decimation,
 2189       real_T                  sampleTime,
 2190       const RTWLogSignalInfo  *sigInfo,
 2191       const char_T            *blockName)
 2192   {
 2193       StructLogVar *var;
 2194       LogInfo      *logInfo = rtliGetLogInfo(li);
 2195   
 2196       /* reset error status */
 2197       *errStatus = NULL;
 2198   
 2199       if ( (var = calloc(1, sizeof(StructLogVar))) == NULL ) goto ERROR_EXIT;
 2200   
 2201       var->numActiveFields = 2;
 2202   
 2203       /* Setup the structure name using varName and nameModifier */
 2204       rt_LoadModifiedLogVarName(li,varName,var->name);
 2205   
 2206       /* time field */
 2207       if (logTime) {
 2208           /* need to create a LogVar to log time */
 2209           int_T dims = 1;
 2210           var->time = rt_CreateLogVarWithConvert(li, startTime, finalTime,
 2211                                                  inStepSize, errStatus,
 2212                                                  &TIME_FIELD_NAME, SS_DOUBLE, 
 2213                                                  NULL,
 2214                                                  0, 0, 0, 1,
 2215                                                  1, &dims, NO_LOGVALDIMS, 
 2216                                                  NULL, NULL, maxRows,
 2217                                                  decimation, sampleTime, 0);
 2218           if (var->time == NULL) goto ERROR_EXIT;
 2219       } else {
 2220           /* create a dummy MatrixData to write out time as an empty matrix */
 2221           BuiltInDTypeId dt     = rt_GetActualDTypeID(SS_DOUBLE);
 2222           size_t         nbytes = sizeof(MatrixData);
 2223           MatrixData     *time;
 2224   
 2225           if ( (var->time = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT;
 2226           time = var->time;
 2227   
 2228           (void)memcpy(time->name, &TIME_FIELD_NAME, mxMAXNAM);
 2229           time->nRows   = 0;
 2230           time->nCols   = 0;
 2231           time->nDims   = 0;
 2232           time->re      = NULL;
 2233           time->im      = NULL;
 2234           time->dTypeID = dt;
 2235           time->mxID    = rt_GetMxIdFromDTypeId(dt);
 2236           time->elSize  = rt_GetSizeofDataType(dt);
 2237           time->logical = 0U;
 2238           time->complex = 0U;
 2239       }
 2240       var->logTime = logTime;
 2241   
 2242       /* signals field */
 2243       if (sigInfo) {
 2244           if (rt_InitSignalsStruct(li,startTime,finalTime,inStepSize,errStatus,
 2245                                    var,maxRows,decimation,sampleTime,sigInfo)) {
 2246               goto ERROR_EXIT;
 2247           }
 2248       }
 2249   
 2250       /* blockName Field */
 2251       if (blockName != NULL) {
 2252           int_T  dataLen = (int_T)strlen(blockName);
 2253           size_t nbytes;
 2254           size_t dataOffset = sizeof(MatrixData);
 2255           /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 2256           uint_T overhang   = (uint_T)(dataOffset % sizeof(short));
 2257   
 2258           if (overhang) {
 2259               dataOffset += (sizeof(short) - overhang);
 2260           }
 2261           /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 2262           nbytes = dataOffset + dataLen*sizeof(short);
 2263   
 2264           if ( (var->blockName = calloc(nbytes, 1)) == NULL ) goto ERROR_EXIT;
 2265   
 2266           (void)memcpy(var->blockName->name, &BLOCKNAME_FIELD_NAME, mxMAXNAM);
 2267           var->blockName->nRows   = (dataLen) ? 1 : 0;
 2268           var->blockName->nCols   = dataLen;
 2269   
 2270           var->blockName->nDims   = 1;
 2271           var->blockName->dims    = var->blockName->_dims;
 2272           var->blockName->dims[0] = dataLen;
 2273           {
 2274               /*LINTED E_BAD_PTR_CAST_ALIGN*/
 2275               short *data = (short*)(((char_T*) (var->blockName))+dataOffset);
 2276               int_T   i;
 2277   
 2278               for (i=0; i<dataLen; i++) {
 2279                   data[i] = blockName[i];
 2280               }
 2281               var->blockName->re  = data;
 2282           }
 2283           var->blockName->im      = NULL;
 2284           var->blockName->dTypeID = SS_INT16;
 2285           var->blockName->mxID    = mxCHAR_CLASS;
 2286           var->blockName->elSize  = sizeof(short);
 2287           var->blockName->logical = 0U;
 2288           var->blockName->complex = 0U;
 2289   
 2290           ++var->numActiveFields;
 2291       }
 2292   
 2293       /* Add this struct log var to the linked list in log info */
 2294       {
 2295           StructLogVar *list = logInfo->structLogVarsList;
 2296   
 2297           if (list != NULL) {
 2298               while (list->next != NULL) {
 2299                   list = list->next;
 2300               }
 2301               list->next = var;
 2302           } else {
 2303               logInfo->structLogVarsList = var;
 2304           }
 2305       }
 2306   
 2307       return(var); /* NORMAL_EXIT */
 2308   
 2309    ERROR_EXIT:
 2310       (void)fprintf(stderr, "*** Error creating log variable %s\n", varName);
 2311       if (*errStatus == NULL) {
 2312           *errStatus = rtMemAllocError;
 2313       }
 2314       rt_DestroyStructLogVar(var);
 2315       return(NULL);
 2316   
 2317   } /* end local_CreateStructLogVar */
 2318   
 2319   
 2320   /* Function: rt_StartDataLoggingForOutput ======================================
 2321    * Abstract:
 2322    */
 2323   const char_T *rt_StartDataLoggingForOutput(RTWLogInfo   *li,
 2324                                              const real_T startTime,
 2325                                              const real_T finalTime,
 2326                                              const real_T stepSize,
 2327                                              const char_T **errStatus)
 2328   {
 2329       const char_T   *varName;
 2330       real_T         sampleTime = stepSize;
 2331       int_T          maxRows    = rtliGetLogMaxRows(li);
 2332       int_T          decimation = rtliGetLogDecimation(li);
 2333       int_T          logFormat  = rtliGetLogFormat(li);
 2334       boolean_T      logTime    = (logFormat==2) ? 1 : 0;
 2335   
 2336       LogInfo *       logInfo;
 2337       logInfo = rtliGetLogInfo(li);
 2338   
 2339       /* reset error status */
 2340       *errStatus = NULL;
 2341   
 2342       /* outputs */
 2343       varName = rtliGetLogY(li);
 2344       if (varName[0] != '\0') {
 2345           int_T                  i;
 2346           int_T                  ny;
 2347           int_T                  yIdx;
 2348           char_T                 name[mxMAXNAM];
 2349           const char_T           *cp        = strchr(varName,',');
 2350           LogSignalPtrsType      ySigPtrs   = rtliGetLogYSignalPtrs(li);
 2351           const RTWLogSignalInfo *yInfo     = rtliGetLogYSignalInfo(li);
 2352   
 2353           /* count the number of variables (matrices or structures) to create */
 2354           for (ny=1; cp != NULL; ny++) {
 2355               cp = strchr(cp+1,',');
 2356           }
 2357           logInfo->ny = ny;
 2358   
 2359           if (logFormat==0) {
 2360               if ( (logInfo->y = calloc(ny,sizeof(LogVar*))) == NULL ) {
 2361                   *errStatus = rtMemAllocError;
 2362                   goto ERROR_EXIT;
 2363               }
 2364           } else {
 2365               if ( (logInfo->y = calloc(ny,sizeof(StructLogVar*))) == NULL ) {
 2366                   *errStatus = rtMemAllocError;
 2367                   goto ERROR_EXIT;
 2368               }
 2369           }
 2370   
 2371           for (i = yIdx = 0, cp = varName; i < ny; i++) {
 2372               int_T        len;
 2373               const char_T *cp1 = strchr(cp+1,',');
 2374   
 2375               if (cp1 != NULL) {
 2376                   /*LINTED E_ASSIGN_INT_TO_SMALL_INT*/
 2377                   len = (int_T)(cp1 - cp);
 2378                   if (len >= mxMAXNAM) len = mxMAXNAM - 1;
 2379               } else {
 2380                   len = mxMAXNAM - 1;
 2381               }
 2382               (void)strncpy(name, cp, len);
 2383               name[len] = '\0';
 2384   
 2385               if (ny > 1 && ySigPtrs[i] == NULL) {
 2386                   goto NEXT_NAME;
 2387               }
 2388   
 2389               if (logFormat == 0) {
 2390                   int            numCols;
 2391                   int            nDims;
 2392                   const int      *dims;
 2393                   BuiltInDTypeId dataType;
 2394                   int            isComplex;
 2395   
 2396                   if (ny == 1) {
 2397                       int_T op;
 2398   
 2399                       numCols = yInfo[0].numCols[0];
 2400                       for (op = 1; op < yInfo[0].numSignals; op++) {
 2401                           numCols += yInfo[0].numCols[op];
 2402                       }
 2403                       /*
 2404                        * If we have only one "matrix" outport,
 2405                        * we can still log it as a matrix
 2406                        */
 2407                       if (yInfo[0].numSignals == 1) {
 2408                           nDims = yInfo[0].numDims[0];
 2409                           dims  = yInfo[0].dims;
 2410                       } else {
 2411                           nDims = 1;
 2412                           dims  = &numCols;
 2413                       }
 2414   
 2415                       dataType  = yInfo[0].dataTypes[0];
 2416                       isComplex = yInfo[0].complexSignals[0];
 2417                   } else {
 2418                       numCols   = yInfo[yIdx].numCols[0];
 2419                       nDims     = yInfo[yIdx].numDims[0];
 2420                       dims      = yInfo[yIdx].dims;
 2421                       dataType  = yInfo[yIdx].dataTypes[0];
 2422                       isComplex = yInfo[yIdx].complexSignals[0];
 2423                   }
 2424   
 2425                   logInfo->y[yIdx] = rt_CreateLogVarWithConvert(
 2426                       li, startTime, finalTime,
 2427                       stepSize, errStatus,
 2428                       name,
 2429                       dataType,
 2430                       yInfo[yIdx].dataTypeConvert,
 2431                       0,isComplex,
 2432                       0,numCols,nDims,dims,
 2433                       NO_LOGVALDIMS, NULL, NULL,
 2434                       maxRows,decimation,
 2435                       sampleTime,1);
 2436                   if (logInfo->y[yIdx] == NULL)  goto ERROR_EXIT;
 2437               } else {
 2438                   logInfo->y[yIdx] = local_CreateStructLogVar(li, startTime,
 2439                                                               finalTime, stepSize,
 2440                                                               errStatus, name,
 2441                                                               logTime, maxRows,
 2442                                                               decimation, sampleTime,
 2443                                                               &yInfo[yIdx], NULL);
 2444                   if (logInfo->y[yIdx] == NULL) goto ERROR_EXIT;
 2445               }
 2446               ++yIdx;
 2447           NEXT_NAME:
 2448               cp = cp1;
 2449               if (cp != NULL && *cp == ',') cp++;
 2450           }
 2451       }
 2452   
 2453       return(NULL); /* NORMAL_EXIT */
 2454   
 2455    ERROR_EXIT:
 2456       (void)fprintf(stderr, "*** Errors occurred when starting data logging.\n");
 2457       if (*errStatus == NULL) {
 2458           *errStatus = rtMemAllocError;
 2459       }
 2460       if (logInfo) {
 2461           rt_DestroyLogVar(logInfo->logVarsList);
 2462           logInfo->logVarsList = NULL;
 2463           rt_DestroyStructLogVar(logInfo->structLogVarsList);
 2464           logInfo->structLogVarsList = NULL;
 2465           FREE(logInfo->y);
 2466           logInfo->y = NULL;
 2467       }
 2468       return(*errStatus);
 2469   
 2470   } /* end rt_StartDataLoggingForOutput */
 2471   
 2472   
 2473   /* Function: rt_ReallocLogVar ==================================================
 2474    * Abstract:
 2475    *   Allocate more memory for the data buffers in the log variable.
 2476    *   Exit if unable to allocate more memory.
 2477    */
 2478   void rt_ReallocLogVar(LogVar *var, boolean_T isVarDims)
 2479   {
 2480       void *tmp;
 2481       int_T nCols = var->data.nCols;
 2482       int_T nRows = var->data.nRows + DEFAULT_BUFFER_SIZE;
 2483       size_t elSize = var->data.elSize;
 2484       
 2485       tmp = realloc(var->data.re, nRows*nCols*elSize);
 2486       if (tmp == NULL) {
 2487           (void)fprintf(stderr,
 2488                         "*** Memory allocation error.\n");
 2489           (void)fprintf(stderr, ""
 2490                         "    varName          = %s%s\n"
 2491                         "    nRows            = %d\n"
 2492                         "    nCols            = %d\n"
 2493                         "    elementSize      = %lu\n"
 2494                         "    Current Size     = %.16g\n"
 2495                         "    Failed resize    = %.16g\n\n",
 2496                         var->data.name,
 2497                         var->data.complex ? " (real part)" : "",
 2498                         var->data.nRows,
 2499                         var->data.nCols,
 2500                         (long)  var->data.elSize,
 2501                         (double)nRows*nCols*elSize,
 2502                         (double)(nRows+DEFAULT_BUFFER_SIZE)*nCols*elSize);
 2503           exit(1);
 2504       }
 2505       var->data.re = tmp;
 2506   
 2507       if (var->data.complex) {
 2508           tmp = realloc(var->data.im, nRows*nCols*elSize);
 2509           if (tmp == NULL) {
 2510               (void)fprintf(stderr,
 2511                             "*** Memory allocation error.\n");
 2512               (void)fprintf(stderr, ""
 2513                             "    varName          = %s (complex part)\n"
 2514                             "    nRows            = %d\n"
 2515                             "    nCols            = %d\n"
 2516                             "    elementSize      = %lu\n"
 2517                             "    Current Size     = %.16g\n"
 2518                             "    Failed resize    = %.16g\n\n",
 2519                             var->data.name,
 2520                             var->data.nRows,
 2521                             var->data.nCols,
 2522                             (long)  var->data.elSize,
 2523                             (double)nRows*nCols*elSize,
 2524                             (double)(nRows+DEFAULT_BUFFER_SIZE)*nCols*elSize);
 2525               exit(1);
 2526           }
 2527           var->data.im = tmp;
 2528       }
 2529       var->data.nRows = nRows;
 2530   
 2531       /* Also reallocate memory for "valueDimensions" 
 2532          when logging the variable-size signal
 2533       */
 2534       if(isVarDims){
 2535           int_T k;
 2536           
 2537           nCols = var->valDims->nCols;
 2538           nRows = var->valDims->nRows + DEFAULT_BUFFER_SIZE;
 2539           elSize = sizeof(real_T);
 2540           tmp = realloc(var->valDims->dimsData, nRows*nCols*elSize);
 2541           if (tmp == NULL) {
 2542               (void)fprintf(stderr,
 2543                             "*** Memory allocation error.\n");
 2544               (void)fprintf(stderr, ""
 2545                             "    varName          = %s\n"
 2546                             "    nRows            = %d\n"
 2547                             "    nCols            = %d\n"
 2548                             "    elementSize      = %lu\n"
 2549                             "    Current Size     = %.16g\n"
 2550                             "    Failed resize    = %.16g\n\n",
 2551                             var->valDims->name,
 2552                             var->valDims->nRows,
 2553                             var->valDims->nCols,
 2554                             (long)  elSize,
 2555                             (double)nRows*nCols*elSize,
 2556                             (double)(nRows+DEFAULT_BUFFER_SIZE)*nCols*elSize);
 2557               exit(1);
 2558           }
 2559   
 2560           /*
 2561            * valueDimensions data is stored in array format and must be
 2562            * adjusted after reallocation (see also rt_FixupLogVar())
 2563            *
 2564            * Example: maxRows = 4; nRows = 4; nDims = 3;
 2565            * Before realloc of the logVar, the locations of data are as below:
 2566            * (x, y, z -- useful data / o -- junk, don't care)
 2567            * a[0] = x    a[4] = y    a[8] = z
 2568            * a[1] = x    a[5] = y    a[9] = z
 2569            * a[2] = x    a[6] = y    a[10]= z
 2570            * a[3] = x    a[7] = y    a[11]= z
 2571            *
 2572            * After realloc of the logVar (suppose 2 extra rows are added),
 2573            * the locations of data are as below:
 2574            * a[0] = x    a[6] = y    a[12]= o
 2575            * a[1] = x    a[7] = y    a[13]= o
 2576            * a[2] = x    a[8] = z    a[14]= o
 2577            * a[3] = x    a[9] = z    a[15]= o
 2578            * a[4] = y    a[10]= z    a[16]= o
 2579            * a[5] = y    a[11]= z    a[17]= o
 2580            *
 2581            * The data must be adjusted as below:
 2582            * a[0] = x    a[6] = y    a[12]= z
 2583            * a[1] = x    a[7] = y    a[13]= z
 2584            * a[2] = x    a[8] = y    a[14]= z
 2585            * a[3] = x    a[9] = y    a[15]= z
 2586            * a[4] = o    a[10]= o    a[16]= o
 2587            * a[5] = o    a[11]= o    a[17]= o
 2588            */
 2589           for(k = var->data.nDims-1; k > 0; k--){
 2590               (void) memcpy((real_T*)tmp + k*nRows, 
 2591                             (real_T*)tmp + k*var->valDims->nRows,
 2592                             elSize * var->valDims->nRows);
 2593           }
 2594   
 2595           var->valDims->dimsData = tmp;
 2596           var->valDims->nRows = nRows;
 2597       }
 2598   
 2599   } /* end rt_ReallocLogVar */
 2600   
 2601   
 2602   /* Function: rt_UpdateLogVarWithDiscontiguousData ==============================
 2603    * Abstract:
 2604    *      Log one row of the LogVar with data that is not contiguous.
 2605    */
 2606   void rt_UpdateLogVarWithDiscontiguousData(LogVar            *var,
 2607                                             LogSignalPtrsType data,
 2608                                             const int_T       *segmentLengths,
 2609                                             int_T             nSegments)
 2610   {
 2611       size_t elSize = 0;
 2612       int_T  offset = 0;
 2613       int    segIdx = 0;
 2614   
 2615       if (++var->numHits % var->decimation) return;
 2616       var->numHits = 0;
 2617   
 2618       /*
 2619        * Reallocate or wrap the LogVar
 2620        */
 2621       if (var->rowIdx == var->data.nRows) {
 2622           if (var->okayToRealloc == 1) {
 2623               rt_ReallocLogVar(var, false);
 2624           } else {
 2625               /* Circular buffer */
 2626               var->rowIdx = 0;
 2627               ++(var->wrapped); /* increment the wrap around counter */
 2628           }
 2629       }
 2630   
 2631       /* This function is only used to log states, there's no var-dims issue. */
 2632       elSize = var->data.elSize;
 2633       offset = (int_T)(elSize * var->rowIdx * var->data.nCols);
 2634   
 2635       if (var->data.complex) {
 2636           char_T *dstRe = (char_T*)(var->data.re) + offset;
 2637           char_T *dstIm = (char_T*)(var->data.im) + offset;
 2638   
 2639           for (segIdx = 0; segIdx < nSegments; segIdx++) {
 2640               int_T         nEl  = segmentLengths[segIdx];
 2641               const  char_T *src = (void *)data[segIdx];
 2642               int_T         el;
 2643   
 2644               for (el = 0; el < nEl; el++) {
 2645                   (void)memcpy(dstRe, src, elSize);
 2646                   dstRe += elSize;   src += elSize;
 2647                   (void)memcpy(dstIm, src, elSize);
 2648                   dstIm += elSize;   src += elSize;
 2649               }
 2650           }
 2651       } else {
 2652           char_T *dst = (char_T*)(var->data.re) + offset;
 2653   
 2654           for (segIdx = 0; segIdx < nSegments; segIdx++) {
 2655               size_t      segSize = elSize*segmentLengths[segIdx];
 2656               const  void *src    = data[segIdx];
 2657   
 2658               (void)memcpy(dst, src, segSize);
 2659               dst += segSize;
 2660           }
 2661       }
 2662   
 2663       ++var->rowIdx;
 2664       return;
 2665   
 2666   } /* end rt_UpdateLogVarWithDiscontiguousData */
 2667   
 2668   
 2669   /*==================*
 2670    * Visible routines *
 2671    *==================*/
 2672   
 2673   
 2674   BEGIN_PUBLIC
 2675   #ifdef __cplusplus
 2676   extern "C" {
 2677   #endif
 2678   END_PUBLIC
 2679    
 2680   /* Function: rt_CreateLogVarWithConvert ========================================
 2681    * Abstract:
 2682    *	Create a logging variable.
 2683    *
 2684    * Returns:
 2685    *	~= NULL  => success, returns the log variable created.
 2686    *	== NULL  => failure, error message set in the simstruct.
 2687    */
 2688   PUBLIC LogVar *rt_CreateLogVarWithConvert(
 2689       RTWLogInfo        *li,
 2690       const real_T      startTime,
 2691       const real_T      finalTime,
 2692       const real_T      inStepSize,
 2693       const char_T      **errStatus,
 2694       const char_T      *varName,
 2695       BuiltInDTypeId    inpDataTypeID,
 2696       const RTWLogDataTypeConvert *pDataTypeConvertInfo,
 2697       int_T             logical,
 2698       int_T             complex,
 2699       int_T             frameData,
 2700       int_T             nCols,
 2701       int_T             nDims,
 2702       const int_T       *dims,
 2703       LogValDimsStat    logValDimsStat,
 2704       void              **currSigDims,
 2705       int_T             *currSigDimsSize,
 2706       int_T             maxRows,
 2707       int_T             decimation,
 2708       real_T            sampleTime,
 2709       int_T             appendToLogVarsList)
 2710   {
 2711       int_T          usingDefaultBufSize = 0;
 2712   #ifdef NO_LOGGING_REALLOC
 2713       int_T          okayToRealloc       = 0;
 2714   #else
 2715       int_T          okayToRealloc       = 1;
 2716   #endif
 2717       LogVar         *var                = NULL;
 2718       /*inpDataTypeID is the rt_LoggedOutputDataTypeId*/
 2719       BuiltInDTypeId dTypeID             = (BuiltInDTypeId)inpDataTypeID; 
 2720       size_t         elementSize         = rt_GetSizeofDataType(dTypeID);
 2721       int_T          frameSize;
 2722       int_T          nRows;
 2723       int_T          nColumns;
 2724   
 2725       /*===================================================================*
 2726        * Determine the frame size if the data is frame based               *
 2727        *===================================================================*/
 2728       frameSize = frameData ? dims[0] : 1;
 2729   
 2730       /*===================================================================*
 2731        * Calculate maximum number of rows needed in the buffer             *
 2732        *===================================================================*/
 2733   
 2734       if (finalTime > startTime && finalTime != rtInf) {
 2735           real_T nPoints;            /* Tfinal is finite  ===>  nRows can be  */
 2736           real_T stepSize;           /* computed since the StepSize is fixed  */
 2737   
 2738           if (sampleTime == -2.0) {  /* The signal being logged is constant,  *
 2739                                       * Hence, only one data point is logged. */
 2740               stepSize = finalTime;
 2741           } else if (sampleTime == -1.0 || sampleTime == 0.0) {
 2742                                   /* Signal being logged is either inside a    *
 2743                                    * triggered sub-system or it is continuous. */
 2744               stepSize = inStepSize;
 2745           } else {                /* Discrete signal */
 2746               stepSize = sampleTime;
 2747           }
 2748   
 2749           if (stepSize == 0.0) {
 2750               /* small initial value, so as to exercise the realloc code */
 2751               nRows = maxRows+1;
 2752               okayToRealloc = 1;
 2753           } else {
 2754               nPoints = 1.0 + floor((finalTime-startTime)/stepSize);
 2755   
 2756               /*
 2757                * Add one more data point if needed.
 2758                */
 2759               if ( stepSize*(nPoints-1.0) < (finalTime-startTime) ) {
 2760                   nPoints += 1.0;
 2761               }
 2762   
 2763               /*
 2764                * Actual number of points to log = nPoints * size of
 2765                * each frame if data is frame-based
 2766                */
 2767               nPoints = frameData ? (nPoints * frameSize) : nPoints;
 2768   
 2769               nPoints /= decimation;
 2770               if (nPoints != floor(nPoints)) {
 2771                   nPoints += 1.0;
 2772               }
 2773               nRows = (nPoints <= INT_MAX) ? ((int_T) nPoints) : INT_MAX;
 2774           }
 2775           /*
 2776            * If maxRows is specified, and if this number is less
 2777            * than the number we computed (nRows) then use maxRows.
 2778            */
 2779           if ((maxRows > 0) && (maxRows < nRows)) {
 2780               nRows = maxRows;
 2781               okayToRealloc = 0;
 2782           }
 2783       } else if (finalTime == startTime) {
 2784           /*
 2785            * Number of rows to log is equal to 1 if not frame-based and
 2786            * equal to frame size if frame-based
 2787            */
 2788           nRows = frameData ? frameSize : 1;
 2789   
 2790           /*
 2791            * If maxRows is specified, and if this number is less
 2792            * than the number we computed (nRows) then use maxRows.
 2793            */
 2794           if ((maxRows > 0) && (maxRows < nRows)) {
 2795               nRows = maxRows;
 2796               okayToRealloc = 0;
 2797           }
 2798       } else if (maxRows > 0) {     /* maxRows is specified => nRows=maxRows  */
 2799           nRows = maxRows;
 2800           okayToRealloc = 0;
 2801       } else {
 2802   
 2803           if (inStepSize == 0) {
 2804               /* small initial value, so as to exercise the realloc code */
 2805               nRows = maxRows+1;
 2806               okayToRealloc = 1;
 2807           } else {                    /* Use a default value for nRows          */
 2808               usingDefaultBufSize = 1;
 2809               nRows = DEFAULT_BUFFER_SIZE;
 2810               okayToRealloc = 0;  /* No realloc with infinite stop time */
 2811               (void)fprintf(stdout, "*** Using a default buffer of size %d for "
 2812                             "logging variable %s\n", nRows, varName);
 2813           }
 2814       }
 2815   
 2816       /*
 2817        * Figure out the number of columns that the log variable should have.
 2818        * If the data is not frame based, then number of columns should equal
 2819        * nCols that is provided as input to the function. If the data is
 2820        * frame-based, then the number of columns should be equal to the
 2821        * number of channels = nCols/frameSize = dims[1];
 2822        */
 2823       nColumns = frameData ? dims[1] : nCols;
 2824   
 2825       /*
 2826        * Error out if the size of the circular buffer is absurdly large, this
 2827        * error message is more informative than the one we get when we try to
 2828        * malloc this many number of bytes in one fell swoop.
 2829        */
 2830       {
 2831           double tmpDbl = ((double)elementSize)*((double)nRows)*
 2832                                                 ((double)nColumns);
 2833   
 2834           if (tmpDbl >= UINT_MAX) {
 2835               (void)fprintf(stderr,
 2836                             "\n*** Memory required to log variable '%s' is too"
 2837                             "\n    big. Use the 'Limit rows to last:' and (or)"
 2838                             "\n    'Decimation:' options to reduce the required"
 2839                             "\n    memory size.\n", varName);
 2840               (void)fprintf(stderr, "*** Details:\n"
 2841                             "       varName         = %s\n"
 2842                             "       nRows           = %d\n"
 2843                             "       nCols           = %d\n"
 2844                             "       elementSize     = %lu\n"
 2845                             "       Bytes Required  = %.16g\n\n",
 2846                             varName, nRows, nColumns, (unsigned long)
 2847                             elementSize, tmpDbl);
 2848               goto ERROR_EXIT;
 2849           }
 2850       }
 2851   
 2852       /* Allocate memory for the log variable */
 2853       if ( (var = calloc(1, sizeof(LogVar))) == NULL ) {
 2854           (void)fprintf(stderr, "*** Error allocating memory for logging %s\n",
 2855                         varName);
 2856           goto ERROR_EXIT;
 2857       }
 2858   
 2859       /* Allocate memory for the circular buffer (real part) */
 2860       if ( (var->data.re = malloc(nRows*nColumns*elementSize)) == NULL ) {
 2861           (void)fprintf(stderr,
 2862                         "*** Error allocating memory for the circular buffer\n");
 2863           (void)fprintf(stderr, "*** Details:\n"
 2864                         "       varName         = %s\n"
 2865                         "       nRows           = %d\n"
 2866                         "       nCols           = %d\n"
 2867                         "       elementSize     = %lu\n"
 2868                         "       Bytes Requested = %.16g\n\n",
 2869                         varName, nRows, nColumns, (unsigned long) elementSize,
 2870                         ((double)elementSize)*((double)nRows)*((double)nColumns));
 2871           goto ERROR_EXIT;
 2872       }
 2873   
 2874       /* Allocate memory for the circular buffer for the imaginary part */
 2875       if (complex) {
 2876           if ( (var->data.im = malloc(nRows*nColumns*elementSize)) == NULL ) {
 2877               (void)fprintf(stderr,
 2878                             "*** Error allocating memory for the circular buffer "
 2879                             "for logging the imaginary part of %s\n", varName);
 2880               (void)fprintf(stderr, "*** Details:\n"
 2881                             "       varName         = %s\n"
 2882                             "       nRows           = %d\n"
 2883                             "       nCols           = %d\n"
 2884                             "       elementSize     = %lu\n"
 2885                             "       Bytes Requested = %.16g\n\n",
 2886                             varName, nRows, nColumns, (unsigned long) elementSize,
 2887                             ((double)elementSize)*((double)nRows)*
 2888                                                    ((double)nColumns));
 2889               goto ERROR_EXIT;
 2890           }
 2891       }
 2892       /*
 2893        * Initialize the fields in LogVar structure.
 2894        */
 2895       if (appendToLogVarsList) {
 2896           rt_LoadModifiedLogVarName(li,varName,var->data.name);
 2897       } else {
 2898           var->data.name[mxMAXNAM-1] = '\0';
 2899           (void)strncpy(var->data.name,varName,mxMAXNAM-1);
 2900       }
 2901       var->data.nCols           = nColumns;
 2902       var->data.nRows           = nRows;
 2903   
 2904       var->data.nDims           = frameData ? 1 : nDims;
 2905       if (var->data.nDims > 2) {
 2906           var->data.dims = (int_T*)malloc(sizeof(int_T)*var->data.nDims);
 2907       } else {
 2908           var->data.dims = var->data._dims;
 2909       }
 2910       if (frameData) {
 2911           var->data.dims[0] = nColumns;
 2912       } else {
 2913           /*LINTED E_CAST_INT_TO_SMALL_INT*/
 2914           (void)memcpy(var->data.dims, dims, (size_t)(nDims*sizeof(int_T)));
 2915       }
 2916   
 2917       var->data.dTypeID         = dTypeID;
 2918       var->data.elSize          = elementSize;
 2919   
 2920       var->data.dataTypeConvertInfo = rt_GetDataTypeConvertInfo(
 2921           pDataTypeConvertInfo, dTypeID);
 2922   
 2923       var->data.mxID            = rt_GetMxIdFromDTypeId(dTypeID);
 2924       /* over-ride logical bit if data type is boolean */
 2925       logical = dTypeID == SS_BOOLEAN ? 1 : 0;
 2926       var->data.logical         = (logical)   ? matLOGICAL_BIT : 0x0;
 2927       var->data.complex         = (complex)   ? matCOMPLEX_BIT : 0x0;
 2928       var->data.frameData       = frameData;
 2929       var->data.frameSize       = (frameData) ? frameSize : 1;
 2930   
 2931       /* fill up valDims field */
 2932       if(logValDimsStat == NO_LOGVALDIMS){
 2933           /* All signals are fixed-size, no need to log valueDimensions field */
 2934           var->valDims     = NULL;
 2935           /* Set these pointers to NULLs in this case */
 2936           var->coords      = NULL;
 2937           var->strides     = NULL;
 2938           var->currStrides = NULL;
 2939       }
 2940       else{
 2941           if ( (var->valDims = calloc(1, sizeof(ValDimsData))) == NULL ) {
 2942               goto ERROR_EXIT;
 2943           }
 2944   
 2945           (void)memcpy(var->valDims->name, &VALUEDIMENSIONS_FIELD_NAME, mxMAXNAM);
 2946   
 2947           if (logValDimsStat == LOGVALDIMS_EMPTYMX) {
 2948               /* At least one signal is variable-size, 
 2949                  but the current signal is fixed-size. 
 2950                  Therefore, create a dummy MatrixData to write out valueDimensions 
 2951                  as an empty matrix. 
 2952               */
 2953               var->valDims->nRows = 0;
 2954               var->valDims->nCols = 0;
 2955               var->valDims->currSigDims = NULL;
 2956               var->valDims->currSigDimsSize = NULL;
 2957               var->valDims->dimsData = NULL;
 2958               /* Set these pointers to NULLs in this case */
 2959               var->coords      = NULL;
 2960               var->strides     = NULL;
 2961               var->currStrides = NULL;
 2962           } else { /* The current signal is a variable-size signal. */
 2963               /* The "valueDimensions" must be double, so re-assign element size */
 2964               elementSize = sizeof(real_T);
 2965   
 2966               /* When signals are frame-based, 'valueDimensions' has 1 column */
 2967               if(frameData){
 2968                   /* When signal is frame-based, the first dimension is always fixed, 
 2969                      so we only need to record the second dimension.
 2970                      e.g. Two frame-based signals [10x4] and [10x3], 
 2971                      'valueDimensions' and 'currSigDims'
 2972                      only record 4 or 3.
 2973                   */
 2974                   nColumns = 1;
 2975                   var->valDims->currSigDims = (void**) (currSigDims + 1);
 2976                   var->valDims->currSigDimsSize = (int_T*) (currSigDimsSize + 1);
 2977               } else { /* non-frame based */
 2978                   nColumns = nDims;
 2979                   var->valDims->currSigDims = (void**) currSigDims;
 2980                   var->valDims->currSigDimsSize = (int_T*) currSigDimsSize;
 2981               }
 2982               
 2983               /* Allocate memory for the circular buffer */
 2984               if ( (var->valDims->dimsData = malloc(nRows*nColumns*elementSize)) == NULL ) {
 2985                   (void)fprintf(stderr,
 2986                                 "*** Error allocating memory for the circular buffer\n");
 2987                   (void)fprintf(stderr, "*** Details:\n"
 2988                                 "       varName         = %s\n"
 2989                                 "       nRows           = %d\n"
 2990                                 "       nCols           = %d\n"
 2991                                 "       elementSize     = %lu\n"
 2992                                 "       Bytes Requested = %.16g\n\n",
 2993                                 var->valDims->name, nRows, nColumns, (unsigned long) elementSize,
 2994                                 ((double)elementSize)*((double)nRows)*((double)nColumns));
 2995                   goto ERROR_EXIT;
 2996               }
 2997               var->valDims->nRows = nRows;
 2998               var->valDims->nCols = nColumns;
 2999   
 3000               /* Allocate memory for these dynamic arrays */
 3001               {
 3002                   size_t nbytes = var->data.nDims*sizeof(int_T);
 3003                   if( ((var->coords = calloc(nbytes, 1)) == NULL)
 3004                       ||((var->strides = calloc(nbytes, 1)) == NULL)
 3005                       ||((var->currStrides = calloc(nbytes, 1)) == NULL) )
 3006                       goto ERROR_EXIT;
 3007               }
 3008           }
 3009       }
 3010   
 3011       var->rowIdx               = 0;
 3012       var->wrapped              = 0;
 3013       var->nDataPoints          = 0;
 3014       var->usingDefaultBufSize  = usingDefaultBufSize;
 3015       var->okayToRealloc        = okayToRealloc;
 3016       var->decimation           = decimation;
 3017       var->numHits              = -1;  /* so first point gets logged */
 3018   
 3019       /* Add this log var to list in log info, if necessary */
 3020       if (appendToLogVarsList) {
 3021           LogInfo *logInfo = (LogInfo*) rtliGetLogInfo(li);
 3022           LogVar  *varList = logInfo->logVarsList;
 3023   
 3024           if (varList != NULL) {
 3025               while (varList->next != NULL) {
 3026                   varList = varList->next;
 3027               }
 3028               varList->next = var;
 3029           } else {
 3030               logInfo->logVarsList = var;
 3031           }
 3032       }
 3033   
 3034       return(var); /* NORMAL_EXIT */
 3035   
 3036    ERROR_EXIT:
 3037       
 3038       *errStatus = rtMemAllocError;
 3039       rt_DestroyLogVar(var);
 3040       return(NULL);
 3041   
 3042   } /* end rt_CreateLogVarWithConvert */
 3043   
 3044   BEGIN_PUBLIC
 3045   #ifdef __cplusplus
 3046   }
 3047   #endif
 3048   END_PUBLIC
 3049   
 3050   
 3051   BEGIN_PUBLIC
 3052   #ifdef __cplusplus
 3053   extern "C" {
 3054   #endif
 3055   END_PUBLIC
 3056   
 3057   /* Function: rt_CreateLogVar ===================================================
 3058    * Abstract:
 3059    *	Create a logging variable.
 3060    *
 3061    * Returns:
 3062    *	~= NULL  => success, returns the log variable created.
 3063    *	== NULL  => failure, error message set in the simstruct.
 3064    */
 3065   PUBLIC LogVar *rt_CreateLogVar(RTWLogInfo        *li,
 3066                                  const real_T      startTime,
 3067                                  const real_T      finalTime,
 3068                                  const real_T      inStepSize,
 3069                                  const char_T      **errStatus,
 3070                                  const char_T      *varName,
 3071                                  BuiltInDTypeId    inpDataTypeID,
 3072                                  int_T             logical,
 3073                                  int_T             complex,
 3074                                  int_T             frameData,
 3075                                  int_T             nCols,
 3076                                  int_T             nDims,
 3077                                  const int_T       *dims,
 3078                                  LogValDimsStat    logValDimsStat,
 3079                                  void              **currSigDims,
 3080                                  int_T             *currSigDimsSize,
 3081                                  int_T             maxRows,
 3082                                  int_T             decimation,
 3083                                  real_T            sampleTime,
 3084                                  int_T             appendToLogVarsList)
 3085   {
 3086       const RTWLogDataTypeConvert *pDataTypeConvertInfo = NULL;
 3087   
 3088       return rt_CreateLogVarWithConvert(li,
 3089                                         startTime,
 3090                                         finalTime,
 3091                                         inStepSize,
 3092                                         errStatus,
 3093                                         varName,
 3094                                         inpDataTypeID,
 3095                                         pDataTypeConvertInfo,
 3096                                         logical,
 3097                                         complex,
 3098                                         frameData,
 3099                                         nCols,
 3100                                         nDims,
 3101                                         dims,
 3102                                         logValDimsStat,
 3103                                         currSigDims,
 3104                                         currSigDimsSize,
 3105                                         maxRows,
 3106                                         decimation,
 3107                                         sampleTime,
 3108                                         appendToLogVarsList);
 3109   
 3110   } /* end rt_CreateLogVar */
 3111   
 3112   BEGIN_PUBLIC
 3113   #ifdef __cplusplus
 3114   }
 3115   #endif
 3116   END_PUBLIC
 3117   
 3118   
 3119   BEGIN_PUBLIC
 3120   #ifdef __cplusplus
 3121   extern "C" {
 3122   #endif
 3123   END_PUBLIC
 3124   
 3125   /* Function: rt_CreateStructLogVar =============================================
 3126    * Abstract:
 3127    *	Create a logging variable in the structure format.
 3128    *
 3129    * Returns:
 3130    *	~= NULL  => success, returns the log variable created.
 3131    *	== NULL  => failure, error message set in the simstruct.
 3132    */
 3133   PUBLIC StructLogVar *rt_CreateStructLogVar(RTWLogInfo              *li,
 3134                                              const real_T            startTime,
 3135                                              const real_T            finalTime,
 3136                                              const real_T            inStepSize,
 3137                                              const char_T            **errStatus,
 3138                                              const char_T            *varName,
 3139                                              boolean_T               logTime,
 3140                                              int_T                   maxRows,
 3141                                              int_T                   decimation,
 3142                                              real_T                  sampleTime,
 3143                                              const RTWLogSignalInfo  *sigInfo,
 3144                                              const char_T            *blockName)
 3145   {
 3146   
 3147       return( local_CreateStructLogVar(li,
 3148                                        startTime,
 3149                                        finalTime,
 3150                                        inStepSize,
 3151                                        errStatus,
 3152                                        varName,
 3153                                        logTime,
 3154                                        maxRows,
 3155                                        decimation,
 3156                                        sampleTime,
 3157                                        sigInfo,
 3158                                        blockName));
 3159   
 3160   } /* end rt_CreateStructLogVar */
 3161   
 3162   BEGIN_PUBLIC
 3163   #ifdef __cplusplus
 3164   }
 3165   #endif
 3166   END_PUBLIC
 3167   
 3168   
 3169   BEGIN_PUBLIC
 3170   #ifdef __cplusplus
 3171   extern "C" {
 3172   #endif
 3173   END_PUBLIC
 3174    
 3175   /* Function: rt_StartDataLoggingWithStartTime ==================================
 3176    * Abstract:
 3177    *      Initialize data logging info based upon the following settings cached
 3178    *      in the RTWLogging data structure of the SimStruct.
 3179    *
 3180    * Return value is:
 3181    *	== NULL  => success
 3182    *	!= NULL  => failure (the return value is a pointer that points to the
 3183    *                           error message, which is also set in the simstruct)
 3184    */
 3185   PUBLIC const char_T *rt_StartDataLoggingWithStartTime(RTWLogInfo   *li,
 3186                                                         const real_T startTime,
 3187                                                         const real_T finalTime,
 3188                                                         const real_T stepSize,
 3189                                                         const char_T **errStatus)
 3190   {
 3191       const char_T   *varName;
 3192       LogInfo        *logInfo;
 3193       real_T         sampleTime = stepSize;
 3194       int_T          maxRows    = rtliGetLogMaxRows(li);
 3195       int_T          decimation = rtliGetLogDecimation(li);
 3196       int_T          logFormat  = rtliGetLogFormat(li);
 3197       boolean_T      logTime    = (logFormat==2) ? 1 : 0;
 3198   
 3199       /* reset error status */
 3200       *errStatus = NULL;
 3201   
 3202       if ((logInfo=calloc(1,sizeof(LogInfo))) == NULL) {
 3203           *errStatus = rtMemAllocError;
 3204           goto ERROR_EXIT;
 3205       }
 3206       rtliSetLogInfo(li, (void*)logInfo);
 3207   
 3208       /* time */
 3209       varName = rtliGetLogT(li);
 3210       if (varName[0] != '\0') {
 3211           int_T dims = 1;
 3212           logInfo->t = rt_CreateLogVarWithConvert(li, startTime, finalTime,
 3213                                                   stepSize, errStatus,
 3214                                                   varName,SS_DOUBLE,
 3215                                                   NULL,
 3216                                                   0,0,0,1,1,
 3217                                                   &dims, NO_LOGVALDIMS, NULL, NULL,
 3218                                                   maxRows,decimation,
 3219                                                   sampleTime,1);
 3220           if (logInfo->t == NULL) goto ERROR_EXIT;
 3221       }
 3222   
 3223       /* states */
 3224       if ( rtliGetLogX(li)[0] != '\0' ||  rtliGetLogXFinal(li)[0] != '\0' ) {
 3225           const RTWLogSignalInfo  *xInfo = rtliGetLogXSignalInfo(li);
 3226   
 3227           if (logFormat == 0) {                                /* Matrix Format */
 3228               int            numCols;
 3229               int            nDims;
 3230               const int      *dims;
 3231               BuiltInDTypeId dataType;
 3232               int            isComplex;
 3233               int_T          sIdx;
 3234   
 3235               const RTWLogDataTypeConvert *pDTConvInfo;
 3236   
 3237               numCols = xInfo[0].numCols[0];
 3238               for (sIdx = 1; sIdx < xInfo[0].numSignals; sIdx++) {
 3239                   numCols += xInfo[0].numCols[sIdx];
 3240               }
 3241               /* If we have only one "matrix" state, we can log as a matrix */
 3242               if (xInfo[0].numSignals == 1) {
 3243                   nDims     = xInfo[0].numDims[0];
 3244                   dims      = xInfo[0].dims;
 3245               } else {
 3246                   nDims     = 1;
 3247                   dims      = &numCols;
 3248               }
 3249               dataType  = xInfo[0].dataTypes[0];
 3250               isComplex = xInfo[0].complexSignals[0];
 3251   
 3252               pDTConvInfo = xInfo[0].dataTypeConvert;
 3253   
 3254               if (rtliGetLogX(li)[0] != '\0') {
 3255                   logInfo->x = rt_CreateLogVarWithConvert(li, startTime, finalTime,
 3256                                                           stepSize, errStatus,
 3257                                                           rtliGetLogX(li),dataType,
 3258                                                           pDTConvInfo,
 3259                                                           0,
 3260                                                           isComplex,0,numCols,nDims,dims,
 3261                                                           NO_LOGVALDIMS, NULL, NULL,
 3262                                                           maxRows,decimation,sampleTime,1);
 3263                   if (logInfo->x == NULL)  goto ERROR_EXIT;
 3264               }
 3265               if (rtliGetLogXFinal(li)[0] != '\0') {
 3266                   logInfo->xFinal = rt_CreateLogVarWithConvert(li, startTime, finalTime,
 3267                                                                stepSize, errStatus,
 3268                                                                rtliGetLogXFinal(li),dataType,
 3269                                                                pDTConvInfo,
 3270                                                                0,isComplex,0,numCols,nDims,
 3271                                                                dims, NO_LOGVALDIMS, NULL, 
 3272                                                                NULL, 1,decimation,
 3273                                                                sampleTime,1);
 3274                   if (logInfo->xFinal == NULL)  goto ERROR_EXIT;
 3275               }
 3276           } else {                                          /* Structure Format */
 3277               if (rtliGetLogX(li)[0] != '\0') {
 3278                   logInfo->x = local_CreateStructLogVar(li, startTime, finalTime,
 3279                                                         stepSize, errStatus,
 3280                                                         rtliGetLogX(li), logTime,
 3281                                                         maxRows, decimation,
 3282                                                         sampleTime, xInfo, NULL);
 3283                   if (logInfo->x == NULL) goto ERROR_EXIT;
 3284               }
 3285               if (rtliGetLogXFinal(li)[0] != '\0') {
 3286                   logInfo->xFinal = local_CreateStructLogVar(li, startTime, finalTime,
 3287                                                              stepSize, errStatus,
 3288                                                              rtliGetLogXFinal(li),
 3289                                                              logTime,1,decimation,
 3290                                                              sampleTime,xInfo,NULL);
 3291                   if (logInfo->xFinal == NULL) goto ERROR_EXIT;
 3292               }
 3293           }
 3294       }
 3295   
 3296       /* signal logging */
 3297       if ( rtliGetSigLog(li)[0] != '\0' ) {
 3298           const RTWLogSignalInfo  *slInfo = rtliGetSigLogSignalInfo(li);
 3299   
 3300           /* log using structure format */
 3301           logInfo->sl = local_CreateStructLogVar(li, startTime, finalTime, 
 3302                                                  stepSize, errStatus,
 3303                                                  rtliGetSigLog(li), logTime,
 3304                                                  maxRows, decimation,
 3305                                                  sampleTime, slInfo, NULL);
 3306           if (logInfo->sl == NULL) goto ERROR_EXIT;
 3307       }
 3308   
 3309       /* outputs */
 3310       *errStatus = rt_StartDataLoggingForOutput(li,startTime,finalTime,
 3311                                                 stepSize,errStatus);
 3312       if (*errStatus != NULL)  goto ERROR_EXIT;
 3313   
 3314       return(NULL); /* NORMAL_EXIT */
 3315   
 3316    ERROR_EXIT:
 3317       (void)fprintf(stderr, "*** Errors occurred when starting data logging.\n");
 3318       if (*errStatus == NULL) {
 3319           *errStatus = rtMemAllocError;
 3320       }
 3321       if (logInfo) {
 3322           rt_DestroyLogVar(logInfo->logVarsList);
 3323           logInfo->logVarsList = NULL;
 3324           rt_DestroyStructLogVar(logInfo->structLogVarsList);
 3325           logInfo->structLogVarsList = NULL;
 3326       }
 3327       return(*errStatus);
 3328   
 3329   } /* end rt_StartDataLoggingWithStartTime */
 3330   
 3331   BEGIN_PUBLIC
 3332   #ifdef __cplusplus
 3333   }
 3334   #endif
 3335   END_PUBLIC
 3336   
 3337   
 3338   BEGIN_PUBLIC
 3339   #ifdef __cplusplus
 3340   extern "C" {
 3341   #endif
 3342   END_PUBLIC
 3343   
 3344   /* Function: rt_StartDataLogging ===============================================
 3345    * Abstract:
 3346    */
 3347   PUBLIC const char_T *rt_StartDataLogging(RTWLogInfo   *li,
 3348                                            const real_T finalTime,
 3349                                            const real_T stepSize,
 3350                                            const char_T **errStatus)
 3351   {
 3352       return rt_StartDataLoggingWithStartTime(li,
 3353                                               0.0,
 3354                                               finalTime,
 3355                                               stepSize,
 3356                                               errStatus);
 3357   }
 3358   
 3359   BEGIN_PUBLIC
 3360   #ifdef __cplusplus
 3361   }
 3362   #endif
 3363   END_PUBLIC
 3364   
 3365   
 3366   BEGIN_PUBLIC
 3367   #ifdef __cplusplus
 3368   extern "C" {
 3369   #endif
 3370   END_PUBLIC
 3371    
 3372   /* Function: rt_UpdateLogVar ===================================================
 3373    * Abstract:
 3374    *	Called to log data for a log variable.
 3375    */
 3376   PUBLIC void rt_UpdateLogVar(LogVar *var, const void *data, boolean_T isVarDims)
 3377   {
 3378       size_t        elSize    = var->data.elSize;
 3379       const  char_T *cData    = data;
 3380       const  int_T  frameData = var->data.frameData;
 3381       const  int_T  frameSize = frameData ? (var->data.frameSize) : 1;
 3382       const  int_T  logWidth  = var->data.nCols;
 3383       BuiltInDTypeId dTypeID  = var->data.dTypeID;
 3384   
 3385       int_T  offset        = 0;
 3386       char_T *currRealRow  = NULL;
 3387       char_T *currImagRow  = NULL;
 3388       int_T  pointSize     = (int_T)((var->data.complex) ? rt_GetSizeofComplexType(dTypeID) : elSize);
 3389   
 3390       int    i, j, k;
 3391   
 3392       /* The following variables will be used for 
 3393          logging variable-size signals */
 3394       const  int_T  nDims = var->data.nDims;
 3395       const  int_T  *dims = var->data.dims;
 3396       const  void   **currDimsPtr = NULL;
 3397       const  int_T  *currDimsSizePtr = NULL;
 3398   
 3399       /* The following variables will be used for 
 3400          logging "valueDimensions" field */
 3401       int_T  offset_valDims   = 0;
 3402       char_T *currValDimsRow  = NULL;
 3403       size_t elSize_valDims   = sizeof(real_T);
 3404       real_T currentSigDims   = 0;
 3405       int_T  nRows_valDims    = 0;
 3406       int_T  logWidth_valDims = 0;
 3407   
 3408       for (i = 0; i < frameSize; i++) {
 3409           if (++var->numHits % var->decimation) continue;
 3410           var->numHits = 0;
 3411   
 3412           if (var->rowIdx == var->data.nRows) {
 3413               if (var->okayToRealloc == 1) {
 3414                   rt_ReallocLogVar(var, isVarDims);
 3415               } else {
 3416                   /* Circular buffer */
 3417                   var->rowIdx = 0;
 3418                   ++(var->wrapped); /* increment the wrap around counter */
 3419               }
 3420           }
 3421   
 3422           if(isVarDims){
 3423               currDimsPtr = (const void**) var->valDims->currSigDims;
 3424               currDimsSizePtr = (const int_T*) var->valDims->currSigDimsSize;
 3425               logWidth_valDims = frameData ? 1 : var->valDims->nCols;
 3426               nRows_valDims = var->valDims->nRows;
 3427   
 3428               var->strides[0] = 1;
 3429               var->currStrides[0] = 1;
 3430   
 3431               for (k = 1; k < nDims; k++){
 3432                   int32_T currDimsVal=0;
 3433                   switch (currDimsSizePtr[k-1]) {
 3434                     case 1:
 3435                       currDimsVal = (**(((const uint8_T**) currDimsPtr)+(k-1)));
 3436                       break;
 3437                     case 2:
 3438                       currDimsVal = (**(((const uint16_T**) currDimsPtr)+(k-1)));
 3439                       break;
 3440                     case 4:
 3441                       currDimsVal = (**(((const uint32_T**) currDimsPtr)+(k-1)));
 3442                       break;
 3443                   }
 3444                   var->strides[k] = var->strides[k-1] * dims[k-1];
 3445                   var->currStrides[k] = var->currStrides[k-1] * currDimsVal;
 3446               }
 3447           }
 3448   
 3449           offset       = (int_T)(elSize * var->rowIdx * logWidth);
 3450           currRealRow  = ((char_T*) (var->data.re)) + offset;
 3451           currImagRow  = (var->data.complex) ?
 3452                          ((char_T*) (var->data.im)) + offset :  NULL;
 3453   
 3454           /* update logging data */
 3455           for (j = 0; j < logWidth; j++) {
 3456   
 3457               boolean_T inRange = true;
 3458               int idx = j;
 3459   
 3460               /* Check whether the currently logged value is in range or not.
 3461                  For fixed-size signal logging, always inRange = true; idx = j;
 3462                  For variable-size signal logging, use strides, coordinates
 3463                  and current strides to decide whether the currently logged
 3464                  data is in range or not and its location in the logging 
 3465                  matrix.
 3466                */
 3467               if(isVarDims){
 3468                   int rem = j;
 3469                   idx = 0;
 3470                   for(k = nDims-1; k>=0; k--){
 3471                       int32_T currDimsVal=0;
 3472                       switch (currDimsSizePtr[k]) {
 3473                         case 1:
 3474                           currDimsVal = (**(((const uint8_T**) currDimsPtr)+k));
 3475                           break;
 3476                         case 2:
 3477                           currDimsVal = (**(((const uint16_T**) currDimsPtr)+k));
 3478                           break;
 3479                         case 4:
 3480                           currDimsVal = (**(((const uint32_T**) currDimsPtr)+k));
 3481                           break;
 3482                       }
 3483                       var->coords[k] = rem / var->strides[k];
 3484                       if( var->coords[k] >= currDimsVal ){
 3485                           inRange = false;
 3486                           break;
 3487                       }
 3488                       rem = rem - var->coords[k] * var->strides[k];
 3489                   }
 3490                   if(inRange){
 3491                       idx = var->coords[0];
 3492                       for (k = 1; k < nDims; k++){
 3493                           idx += var->coords[k] * var->currStrides[k];
 3494                       }
 3495                   }
 3496               }
 3497               
 3498               if (!var->data.dataTypeConvertInfo.conversionNeeded) {
 3499                   /* NO  conversion needed
 3500                    */ 
 3501                   if (inRange) {
 3502                       /* If in range, fill in data */
 3503                       const char *cDataPoint = cData + (i+frameSize*idx) * pointSize;
 3504   
 3505                       (void) memcpy(currRealRow, cDataPoint, elSize);
 3506                       currRealRow += elSize;
 3507                       if (var->data.complex) {
 3508                           (void) memcpy(currImagRow, cDataPoint + pointSize/2, elSize);
 3509                           currImagRow += elSize;
 3510                       }
 3511                   } else {
 3512                       /* If out of range, fill in NaN or 0:
 3513                          1) For bool, int32, uint32, int16, uint16, etc,
 3514                             memset to zeros;
 3515                          2) For fixed-point data type, NaN conversion is not
 3516                             allowed, memset to zeros.
 3517                       */
 3518                       if (dTypeID == SS_DOUBLE) {
 3519                           (void) memcpy(currRealRow, &rtNaN, elSize);
 3520                       } else if (dTypeID == SS_SINGLE){
 3521                           (void) memcpy(currRealRow, &rtNaNF, elSize);
 3522                       } else {
 3523                           (void) memset(currRealRow, 0, elSize);
 3524                       }
 3525                       
 3526                       currRealRow += elSize;
 3527                       if (var->data.complex) {
 3528                           /* For imaginary part, fill in 0 */
 3529                           (void) memset(currImagRow, 0, elSize);
 3530                           currImagRow += elSize;
 3531                       }
 3532                   }
 3533               }
 3534               else
 3535               {
 3536                   /* YES conversion needed
 3537                    */ 
 3538                   DTypeId dataTypeIdOriginal = 
 3539                       var->data.dataTypeConvertInfo.dataTypeIdOriginal;
 3540                   int_T DpSize = (int_T)((var->data.complex) ? 
 3541                                          rt_GetSizeofComplexType(dataTypeIdOriginal) : 
 3542                                          rt_GetSizeofDataType(dataTypeIdOriginal));
 3543   
 3544                   DTypeId dataTypeIdLoggingTo = 
 3545                       var->data.dataTypeConvertInfo.dataTypeIdLoggingTo;
 3546   
 3547                   int bitsPerChunk = var->data.dataTypeConvertInfo.bitsPerChunk;
 3548                   int numOfChunk =  var->data.dataTypeConvertInfo.numOfChunk;
 3549                   unsigned int isSigned = var->data.dataTypeConvertInfo.isSigned;
 3550   
 3551                   double fracSlope = var->data.dataTypeConvertInfo.fracSlope;
 3552                   int    fixedExp  = var->data.dataTypeConvertInfo.fixedExp;
 3553                   double bias      = var->data.dataTypeConvertInfo.bias;
 3554   
 3555                   double curRealValue = -0.12345678987654;
 3556                   double curImagValue = -0.12345678987654;
 3557   
 3558                   int_T adjIndexIfComplex = (var->data.complex) ? 2 : 1;
 3559   
 3560                   if(inRange){
 3561                       if(numOfChunk > 1)
 3562                       {
 3563                           /* For multiword */
 3564                           const char *pInData = (const char *)(cData);
 3565                           int dtSize = bitsPerChunk*numOfChunk/8;
 3566                           pInData += ((i+frameSize*idx) * adjIndexIfComplex) * dtSize;
 3567                           
 3568                           curRealValue = rt_GetDblValueFromOverSizedData(pInData, bitsPerChunk, numOfChunk, 
 3569                                                                          isSigned, fracSlope, fixedExp, bias);
 3570                           if (var->data.complex) {
 3571                               curImagValue = rt_GetDblValueFromOverSizedData((pInData+dtSize), bitsPerChunk, numOfChunk, 
 3572                                                                              isSigned, fracSlope, fixedExp, bias);
 3573                           }
 3574                       }
 3575                       else
 3576                       {
 3577                           /* if in range, fill in data that is converted first */
 3578                           switch ( dataTypeIdOriginal )
 3579                           {
 3580                             case SS_DOUBLE:
 3581                               {
 3582                                   const real_T *pInData = (const real_T *)(cData + (i+frameSize*idx)* DpSize);
 3583                                   
 3584                                   curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3585                                   if (var->data.complex) {
 3586                                       pInData = (const real_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2);
 3587                                       curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3588                                   }
 3589                               }
 3590                               break;
 3591                             case SS_SINGLE:
 3592                               {
 3593                                   const real32_T *pInData = (const real32_T *)(cData + (i+frameSize*idx)* DpSize);
 3594   
 3595                                   curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3596                                   if (var->data.complex) {
 3597                                       pInData = (const real32_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2);
 3598                                       curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3599                                   }
 3600                               }
 3601                               break;
 3602                             case SS_INT8:
 3603                               {
 3604                                   const int8_T *pInData = (const int8_T *)(cData + (i+frameSize*idx)* DpSize);
 3605                                   
 3606                                   curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3607                                   if (var->data.complex) {
 3608                                       pInData = (const int8_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2);
 3609                                       curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3610                                   }
 3611                               }
 3612                               break;
 3613                             case SS_UINT8:
 3614                               {
 3615                                   const uint8_T *pInData = (const uint8_T *)(cData + (i+frameSize*idx)* DpSize);
 3616                                   
 3617                                   curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3618                                   if (var->data.complex) {
 3619                                       pInData = (const uint8_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2);
 3620                                       curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3621                                   }
 3622                               }
 3623                               break;
 3624                             case SS_INT16:
 3625                               {
 3626                                   const int16_T *pInData = (const int16_T *)(cData + (i+frameSize*idx)* DpSize);
 3627                                   
 3628                                   curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3629                                   if (var->data.complex) {
 3630                                       pInData = (const int16_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2);
 3631                                       curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3632                                   }
 3633                               }
 3634                               break;
 3635                             case SS_UINT16:
 3636                               {
 3637                                   const uint16_T *pInData = (const uint16_T *)(cData + (i+frameSize*idx)* DpSize);
 3638                                   
 3639                                   curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3640                                   if (var->data.complex) {
 3641                                       pInData = (const uint16_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2);
 3642                                       curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3643                                   }
 3644                               }
 3645                               break;
 3646                             case SS_INT32:
 3647                               {
 3648                                   const int32_T *pInData = (const int32_T *)(cData + (i+frameSize*idx)* DpSize);
 3649   
 3650                                   curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3651                                   if (var->data.complex) {
 3652                                       pInData = (const int32_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2);
 3653                                       curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3654                                   }
 3655                               }
 3656                               break;
 3657                             case SS_UINT32:
 3658                               {
 3659                                   const uint32_T *pInData = (const uint32_T *)(cData + (i+frameSize*idx)* DpSize);
 3660                                   
 3661                                   curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3662                                   if (var->data.complex) {
 3663                                       pInData = (const uint32_T *)(cData + (i+frameSize*idx)* DpSize + DpSize/2);
 3664                                       curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3665                                   }
 3666                               }
 3667                               break;
 3668                             case SS_BOOLEAN:
 3669                               {
 3670                                   const boolean_T *pInData = ((const boolean_T *)(cData));
 3671                                   
 3672                                   pInData += (i+frameSize*idx) * adjIndexIfComplex;
 3673                                   
 3674                                   curRealValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3675                                   if (var->data.complex) {
 3676                                       curImagValue = ldexp( fracSlope * (double)(*pInData), fixedExp ) + bias;
 3677                                   }
 3678                               }
 3679                               break;
 3680                             default: 
 3681                               {
 3682                                   /* For biglong */
 3683                                   const char *pInData = (const char *)(cData);
 3684                                   int dtSize = bitsPerChunk*numOfChunk/8;
 3685                                   pInData += ((i+frameSize*idx) * adjIndexIfComplex) * dtSize;
 3686                                   
 3687                                   curRealValue = rt_GetDblValueFromOverSizedData(pInData, bitsPerChunk, numOfChunk, 
 3688                                                                                  isSigned, fracSlope, fixedExp, bias);
 3689                                   if (var->data.complex) {
 3690                                       curImagValue = rt_GetDblValueFromOverSizedData((pInData+dtSize), bitsPerChunk, numOfChunk, 
 3691                                                                                      isSigned, fracSlope, fixedExp, bias);
 3692                                   }
 3693                               }
 3694                               break;
 3695                           } /* -- end of switch -- */
 3696                       }
 3697                   } else {
 3698                       /* if out of range, just fill NaN or 0 */
 3699                       if(dTypeID == SS_DOUBLE || dTypeID == SS_SINGLE){
 3700                           curRealValue = ldexp( rtNaN, fixedExp ) + bias;
 3701                       }
 3702                       else{
 3703                           curRealValue = ldexp( 0, fixedExp ) + bias;
 3704                       }
 3705                       if (var->data.complex) {
 3706                           /* fill 0 in imaginary part*/
 3707                           curImagValue = ldexp( 0, fixedExp ) + bias;
 3708                       }
 3709                   }
 3710   
 3711                   switch ( dataTypeIdLoggingTo )
 3712                   {
 3713                     case SS_DOUBLE:
 3714                       {
 3715                           *((real_T *)currRealRow) = (real_T)curRealValue;
 3716   
 3717                           if (var->data.complex) {
 3718   
 3719                               *((real_T *)currImagRow) = (real_T)curImagValue;
 3720                           }
 3721                       }
 3722                       break;
 3723                     case SS_SINGLE:
 3724                       {
 3725                           *((real32_T *)currRealRow) = (real32_T)curRealValue;
 3726   
 3727                           if (var->data.complex) {
 3728   
 3729                               *((real32_T *)currImagRow) = (real32_T)curImagValue;
 3730                           }
 3731                       }
 3732                       break;
 3733                     case SS_INT8:
 3734                       {
 3735                           *((int8_T *)currRealRow) = (int8_T)curRealValue;
 3736   
 3737                           if (var->data.complex) {
 3738   
 3739                               *((int8_T *)currImagRow) = (int8_T)curImagValue;
 3740                           }
 3741                       }
 3742                       break;
 3743                     case SS_UINT8:
 3744                       {
 3745                           *((uint8_T *)currRealRow) = (uint8_T)curRealValue;
 3746   
 3747                           if (var->data.complex) {
 3748   
 3749                               *((uint8_T *)currImagRow) = (uint8_T)curImagValue;
 3750                           }
 3751                       }
 3752                       break;
 3753                     case SS_INT16:
 3754                       {
 3755                           *((int16_T *)currRealRow) = (int16_T)curRealValue;
 3756   
 3757                           if (var->data.complex) {
 3758   
 3759                               *((int16_T *)currImagRow) = (int16_T)curImagValue;
 3760                           }
 3761                       }
 3762                       break;
 3763                     case SS_UINT16:
 3764                       {
 3765                           *((uint16_T *)currRealRow) = (uint16_T)curRealValue;
 3766   
 3767                           if (var->data.complex) {
 3768   
 3769                               *((uint16_T *)currImagRow) = (uint16_T)curImagValue;
 3770                           }
 3771                       }
 3772                       break;
 3773                     case SS_INT32:
 3774                       {
 3775                           *((int32_T *)currRealRow) = (int32_T)curRealValue;
 3776   
 3777                           if (var->data.complex) {
 3778   
 3779                               *((int32_T *)currImagRow) = (int32_T)curImagValue;
 3780                           }
 3781                       }
 3782                       break;
 3783                     case SS_UINT32:
 3784                       {
 3785                           *((uint32_T *)currRealRow) = (uint32_T)curRealValue;
 3786   
 3787                           if (var->data.complex) {
 3788   
 3789                               *((uint32_T *)currImagRow) = (uint32_T)curImagValue;
 3790                           }
 3791                       }
 3792                       break;
 3793                     case SS_BOOLEAN:
 3794                       {
 3795                           *((boolean_T *)currRealRow) = (boolean_T)(curRealValue != 0.0);
 3796   
 3797                           if (var->data.complex) {
 3798   
 3799                               *((boolean_T *)currImagRow) = (boolean_T)(curImagValue != 0.0);
 3800                           }
 3801                       }
 3802                       break;
 3803                   } /* -- end of switch -- */
 3804   
 3805                   currRealRow += elSize;
 3806                   if (var->data.complex) {
 3807                       currImagRow += elSize;
 3808                   }
 3809               }
 3810           }
 3811   
 3812           if(isVarDims){ /* update "valueDimensions" field */
 3813               for(j = 0; j < logWidth_valDims; j ++){
 3814                   int32_T currDimsVal=0;
 3815                   switch (currDimsSizePtr[j]) {
 3816                     case 1:
 3817                       currDimsVal = (**(((const uint8_T**) currDimsPtr)+j));
 3818                       break;
 3819                     case 2:
 3820                       currDimsVal = (**(((const uint16_T**) currDimsPtr)+j));
 3821                       break;
 3822                     case 4:
 3823                       currDimsVal = (**(((const uint32_T**) currDimsPtr)+j));
 3824                       break;
 3825                   }
 3826                   offset_valDims  = (int_T)(elSize_valDims *( var->rowIdx + nRows_valDims * j));
 3827                   currValDimsRow  = ((char_T*) (var->valDims->dimsData)) + offset_valDims;
 3828   
 3829                   /* convert int_T to real_T */
 3830                   currentSigDims = (real_T) currDimsVal;
 3831                   (void) memcpy(currValDimsRow, &currentSigDims, elSize_valDims);
 3832                   currValDimsRow += elSize_valDims;
 3833               }
 3834           }
 3835           
 3836           ++var->rowIdx;
 3837       }
 3838   
 3839       return;
 3840   
 3841   } /* end rt_UpdateLogVar */
 3842   
 3843   BEGIN_PUBLIC
 3844   #ifdef __cplusplus
 3845   }
 3846   #endif
 3847   END_PUBLIC
 3848   
 3849   
 3850   BEGIN_PUBLIC
 3851   #ifdef __cplusplus
 3852   extern "C" {
 3853   #endif
 3854   END_PUBLIC 
 3855    
 3856   /* Function: rt_UpdateStructLogVar =============================================
 3857    * Abstract:
 3858    *      Called to log data for a structure log variable.
 3859    */
 3860   PUBLIC void rt_UpdateStructLogVar(StructLogVar *var, const real_T *t, const void *data)
 3861   {
 3862       LogVar       *values = var->signals.values;
 3863       const char_T *signal = data;
 3864       boolean_T *isVarDims = var->signals.isVarDims;
 3865       int i = 0;
 3866   
 3867       /* time */
 3868       if (var->logTime) {
 3869           rt_UpdateLogVar(var->time, t, false);
 3870       }
 3871   
 3872       /* signals */
 3873       while (values) {
 3874           size_t elSz = values->data.elSize;
 3875   
 3876           rt_UpdateLogVar(values, signal, isVarDims[i]);
 3877   
 3878           if (values->data.complex) elSz *= 2;
 3879           signal += elSz * values->data.nCols;
 3880   
 3881           values = values->next;
 3882           i++;
 3883       }
 3884   
 3885   } /* end rt_UpdateStructLogVar */
 3886   
 3887   BEGIN_PUBLIC
 3888   #ifdef __cplusplus
 3889   }
 3890   #endif
 3891   END_PUBLIC
 3892   
 3893   
 3894   BEGIN_PUBLIC
 3895   #ifdef __cplusplus
 3896   extern "C" {
 3897   #endif
 3898   END_PUBLIC 
 3899    
 3900   /* Function: rt_UpdateTXYLogVars ===============================================
 3901    * Abstract:
 3902    *	Update the T,X,Y variables that are being logged.
 3903    */
 3904   PUBLIC const char_T *rt_UpdateTXYLogVars(RTWLogInfo *li, time_T *tPtr)
 3905   {
 3906       LogInfo *logInfo     = rtliGetLogInfo(li);
 3907       int_T   matrixFormat = (rtliGetLogFormat(li) == 0);
 3908   
 3909       /* time */
 3910       if (logInfo->t != NULL) {
 3911           rt_UpdateLogVar(logInfo->t, tPtr, false);
 3912       }
 3913   
 3914       if (matrixFormat) {                                      /* MATRIX_FORMAT */
 3915           /* states */
 3916           if (logInfo->x != NULL || logInfo->xFinal != NULL) {
 3917               const RTWLogSignalInfo *xInfo      = rtliGetLogXSignalInfo(li);
 3918               LogSignalPtrsType      segAddr     = rtliGetLogXSignalPtrs(li);
 3919               const int_T            *segLengths = xInfo->numCols;
 3920               int_T                  nSegments   = xInfo->numSignals;
 3921               if (logInfo->x != NULL) {
 3922                   rt_UpdateLogVarWithDiscontiguousData(logInfo->x, segAddr,
 3923                                                        segLengths, nSegments);
 3924               }
 3925               if (logInfo->xFinal != NULL) {
 3926                   rt_UpdateLogVarWithDiscontiguousData(logInfo->xFinal, segAddr,
 3927                                                        segLengths, nSegments);
 3928               }
 3929           }
 3930           /* outputs */
 3931           if (logInfo->y != NULL) {
 3932               LogVar **var = (LogVar**) (logInfo->y);
 3933               int_T  ny    = logInfo->ny;
 3934               int_T  i;
 3935               int    yIdx;
 3936               LogSignalPtrsType data = rtliGetLogYSignalPtrs(li);
 3937   
 3938               for (i = 0, yIdx = 0; i < ny; i++) {
 3939                   if (data[i] != NULL) {
 3940                       /* 
 3941                          When outputs are logged in Matrix format, 
 3942                          no variable-size signal logging is allowed.
 3943                       */
 3944                       rt_UpdateLogVar(var[yIdx++], data[i], false);
 3945                   }
 3946               }
 3947           }
 3948       } else {                                              /* STRUCTURE_FORMAT */
 3949           /* states */
 3950           if (logInfo->x != NULL) {
 3951               int_T             i;
 3952               StructLogVar      *var = logInfo->x;
 3953               LogVar            *val = var->signals.values;
 3954               int_T             nsig = var->signals.numSignals;
 3955               LogSignalPtrsType data = rtliGetLogXSignalPtrs(li);
 3956   
 3957               /* time */
 3958               if (var->logTime) {
 3959                   rt_UpdateLogVar(var->time, tPtr, false);
 3960               }
 3961   
 3962               /* signals */
 3963               for (i = 0; i < nsig; i++) {
 3964                   rt_UpdateLogVar(val, data[i], false);
 3965                   val = val->next;
 3966               }
 3967           }
 3968   
 3969           /* outputs */
 3970           if (logInfo->y != NULL) {
 3971               int_T             ny      = logInfo->ny;
 3972               LogSignalPtrsType data    = rtliGetLogYSignalPtrs(li);
 3973               StructLogVar      **var   = (StructLogVar**) (logInfo->y);
 3974   
 3975               if (ny == 1) {
 3976                   int_T  i;
 3977                   int_T  dataIdx;
 3978                   LogVar *val = var[0]->signals.values;
 3979                   int_T  nsig = var[0]->signals.numSignals;
 3980                   boolean_T   *isVarDims = var[0]->signals.isVarDims;
 3981   
 3982                   /* time */
 3983                   if (var[0]->logTime) {
 3984                       rt_UpdateLogVar(var[0]->time, tPtr, false);
 3985                   }
 3986   
 3987                   /* signals */
 3988                   for (i = 0, dataIdx = 0; i < nsig; i++) {
 3989                       while (data[dataIdx] == NULL) {
 3990                           ++dataIdx;
 3991                       }
 3992                       rt_UpdateLogVar(val,  data[dataIdx], isVarDims[i]);
 3993                       val = val->next;
 3994                       ++dataIdx;
 3995                   }
 3996               } else {
 3997                   int_T  i;
 3998                   int_T  dataIdx;
 3999   
 4000                   for (i = 0, dataIdx = 0; i < ny && var[i] != NULL; i++) {
 4001                       LogVar *val = var[i]->signals.values;
 4002                       boolean_T   *isVarDims = var[i]->signals.isVarDims;
 4003   
 4004                       /* time */
 4005                       if (var[i]->logTime) {
 4006                           rt_UpdateLogVar(var[i]->time, tPtr, false);
 4007                       }
 4008   
 4009                       /* signals */
 4010                       while (data[dataIdx] == NULL) {
 4011                           ++dataIdx;
 4012                       }
 4013                       rt_UpdateLogVar(val,  data[dataIdx], isVarDims[0]);
 4014                       val = val->next;
 4015                       ++dataIdx;
 4016                   }
 4017               }
 4018           }
 4019           /* final state */
 4020           if (logInfo->xFinal != NULL) {
 4021               StructLogVar *xf  = logInfo->xFinal;
 4022               LogVar       *val = xf->signals.values;
 4023               int_T        nsig = xf->signals.numSignals;
 4024               int_T        i;
 4025   
 4026               /* time */
 4027               if (xf->logTime) {
 4028                   rt_UpdateLogVar(xf->time, tPtr, false);
 4029               }
 4030   
 4031               /* signals */
 4032               for (i = 0; i < nsig; i++) {
 4033                   LogSignalPtrsType data = rtliGetLogXSignalPtrs(li);
 4034   
 4035                   rt_UpdateLogVar(val, data[i], false);
 4036                   val = val->next;
 4037               }
 4038           }
 4039       }
 4040       return(NULL);
 4041   
 4042   } /* end rt_UpdateTXYLogVars */
 4043   
 4044   BEGIN_PUBLIC
 4045   #ifdef __cplusplus
 4046   }
 4047   #endif
 4048   END_PUBLIC          
 4049   
 4050             
 4051   BEGIN_PUBLIC
 4052   #ifdef __cplusplus
 4053   extern "C" {
 4054   #endif
 4055   END_PUBLIC
 4056   
 4057   /* Function: rt_UpdateSigLogVars ===============================================
 4058    * Abstract:
 4059    *	Update the Signal Logging testpoint variables that are being logged.
 4060    *
 4061    */
 4062   PUBLIC void rt_UpdateSigLogVars(RTWLogInfo *li, time_T *tPtr)
 4063   {
 4064       LogInfo   *logInfo     = rtliGetLogInfo(li);
 4065   
 4066       if (logInfo->sl != NULL) {
 4067           int_T             i;
 4068           StructLogVar      *var = logInfo->sl;
 4069           LogVar            *val = var->signals.values;
 4070           int_T             nsig = var->signals.numSignals;
 4071           LogSignalPtrsType data = rtliGetSigLogSignalPtrs(li);
 4072   
 4073           /* time */
 4074           if (var->logTime) {
 4075               rt_UpdateLogVar(var->time, tPtr, false);
 4076           }
 4077   
 4078           /* signals */
 4079           for (i = 0; i < nsig; i++) {
 4080               /* currently, SigLog doesn't support variable-size signals */
 4081               rt_UpdateLogVar(val, data[i], false);
 4082               val = val->next;
 4083           }
 4084       }
 4085   
 4086   } /* end rt_UpdateSigLogVars */
 4087   
 4088   BEGIN_PUBLIC
 4089   #ifdef __cplusplus
 4090   }
 4091   #endif
 4092   END_PUBLIC
 4093   
 4094   
 4095   BEGIN_PUBLIC
 4096   #ifdef __cplusplus
 4097   extern "C" {
 4098   #endif
 4099   END_PUBLIC
 4100   
 4101   /* Function: rt_StopDataLoggingForRaccel =======================================
 4102    * Abstract:
 4103    *	Write logged data to model.mat and free memory.
 4104    */
 4105   PUBLIC void rt_StopDataLoggingForRaccel(const char_T *file, RTWLogInfo *li, int verbose)
 4106   {
 4107       FILE          *fptr;
 4108       LogInfo       *logInfo     = (LogInfo*) rtliGetLogInfo(li);
 4109       LogVar        *var         = logInfo->logVarsList;
 4110       StructLogVar  *svar        = logInfo->structLogVarsList;
 4111   
 4112       boolean_T     emptyFile    = 1; /* assume */
 4113       boolean_T     errFlag      = 0;
 4114       const char_T  *msg;
 4115   
 4116       /*******************************
 4117        * Create MAT file with header *
 4118        *******************************/
 4119       if ((fptr=fopen(file,"w+b")) == NULL) {
 4120           (void)fprintf(stderr,"*** Error opening %s",file);
 4121           goto EXIT_POINT;
 4122       }
 4123       if (rt_WriteMat5FileHeader(fptr)) {
 4124           (void)fprintf(stderr,"*** Error writing to %s",file);
 4125           goto EXIT_POINT;
 4126       }
 4127   
 4128       /**************************************************
 4129        * First log all the variables in the LogVar list *
 4130        **************************************************/
 4131       while (var != NULL) {
 4132           if ( (msg = rt_FixupLogVar(var,verbose)) != NULL ) {
 4133               (void)fprintf(stderr,"*** Error writing %s due to: %s\n",file,msg);
 4134               errFlag = 1;
 4135               break;
 4136           }
 4137           if (var->nDataPoints > 0) {
 4138               MatItem item;
 4139   
 4140               item.type   = matMATRIX;
 4141               item.nbytes = 0; /* not yet known */
 4142               item.data   = &(var->data);
 4143               if (rt_WriteItemToMatFile(fptr, &item, MATRIX_ITEM)) {
 4144                   (void)fprintf(stderr,"*** Error writing log variable %s to "
 4145                                 "file %s",var->data.name, file);
 4146                   errFlag = 1;
 4147                   break;
 4148               }
 4149               emptyFile = 0;
 4150           }
 4151           var = var->next;
 4152       }
 4153       /* free up some memory by destroying the log var list here */
 4154       rt_DestroyLogVar(logInfo->logVarsList);
 4155       logInfo->logVarsList = NULL;
 4156   
 4157       /*******************************************************
 4158        * Next log all the variables in the StrcutLogVar list *
 4159        *******************************************************/
 4160       while (svar != NULL) {
 4161           MatItem item;
 4162   
 4163           if (svar->logTime) {
 4164               var = svar->time;
 4165               if ( (msg = rt_FixupLogVar(var,verbose)) != NULL ) {
 4166                   (void)fprintf(stderr, "*** Error writing %s due to: %s\n",
 4167                                 file, msg);
 4168                   errFlag = 1;
 4169                   break;
 4170               }
 4171           }
 4172   
 4173           var = svar->signals.values;
 4174           while (var) {
 4175               if ( (msg = rt_FixupLogVar(var,verbose)) != NULL ) {
 4176                   (void)fprintf(stderr, "*** Error writing %s due to: %s\n",
 4177                                 file, msg);
 4178                   errFlag = 1;
 4179                   break;
 4180               }
 4181               var = var->next;
 4182           }
 4183   
 4184           item.type   = matMATRIX;
 4185           item.nbytes = 0; /* not yet known */
 4186           item.data   = svar;
 4187   
 4188           if (rt_WriteItemToMatFile(fptr, &item, STRUCT_LOG_VAR_ITEM)) {
 4189               (void)fprintf(stderr,"*** Error writing structure log variable "
 4190                             "%s to file %s",svar->name, file);
 4191               errFlag = 1;
 4192               break;
 4193           }
 4194           emptyFile = 0;
 4195   
 4196           svar = svar->next;
 4197       }
 4198   
 4199       /******************
 4200        * Close the file *
 4201        ******************/
 4202       (void)fclose(fptr);
 4203       if (emptyFile || errFlag) {
 4204           (void)remove(file);
 4205       } else {
 4206           if( verbose ) {
 4207               (void)printf("** created %s **\n\n", file);
 4208           }
 4209       }
 4210   
 4211    EXIT_POINT:
 4212   
 4213       /****************
 4214        * free logInfo *
 4215        ****************/
 4216       rt_DestroyLogVar(logInfo->logVarsList);
 4217       logInfo->logVarsList = NULL;
 4218       rt_DestroyStructLogVar(logInfo->structLogVarsList);
 4219       logInfo->structLogVarsList = NULL;
 4220       FREE(logInfo);
 4221       rtliSetLogInfo(li,NULL);
 4222   
 4223   } /* end rt_StopDataLoggingForRaccel */
 4224   
 4225   BEGIN_PUBLIC
 4226   #ifdef __cplusplus
 4227   }
 4228   #endif
 4229   END_PUBLIC
 4230   
 4231   
 4232   BEGIN_PUBLIC
 4233   #ifdef __cplusplus
 4234   extern "C" {
 4235   #endif
 4236   END_PUBLIC
 4237   
 4238   /* Function: rt_StopDataLogging ================================================
 4239    * Abstract:
 4240    *	Write logged data to model.mat and free memory.
 4241    */
 4242   PUBLIC void rt_StopDataLogging(const char_T *file, RTWLogInfo *li)
 4243   {
 4244       rt_StopDataLoggingForRaccel(file,li,1);
 4245   
 4246   } /* end rt_StopDataLogging */
 4247   
 4248   BEGIN_PUBLIC
 4249   #ifdef __cplusplus
 4250   }
 4251   #endif
 4252   END_PUBLIC
 4253   
 4254   BEGIN_PUBLIC
 4255   #else /*!defined(MAT_FILE) || (defined(MAT_FILE) && MAT_FILE == 1)*/
 4256   
 4257   #define rt_StartDataLogging(li, finalTime, stepSize, errStatus) NULL /* do nothing */
 4258   #define rt_UpdateTXYLogVars(li, tPtr) NULL /* do nothing */
 4259   #define rt_UpdateSigLogVars(li, tPtr); /* do nothing */
 4260   #define rt_StopDataLogging(file, li); /* do nothing */
 4261   
 4262   #endif /*!defined(MAT_FILE) || (defined(MAT_FILE) && MAT_FILE == 1)*/
 4263   END_PUBLIC
 4264   
 4265   
 4266   /* [eof] rt_logging.c */
 4267