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