Update lcms (#544)
[openjpeg.git] / thirdparty / liblcms2 / src / cmscgats.c
index d41c15a23bd8d17f8ea8c27d250d63df1b0ff5b5..591e4caa0fcb6e38b3ae51e9fed316943694403f 100644 (file)
@@ -1,24 +1,24 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2010 Marti Maria Saguer
+//  Copyright (c) 1998-2016 Marti Maria Saguer
 //
-// Permission is hereby granted, free of charge, to any person obtaining 
-// a copy of this software and associated documentation files (the "Software"), 
-// to deal in the Software without restriction, including without limitation 
-// the rights to use, copy, modify, merge, publish, distribute, sublicense, 
-// and/or sell copies of the Software, and to permit persons to whom the Software 
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the Software
 // is furnished to do so, subject to the following conditions:
 //
-// The above copyright notice and this permission notice shall be included in 
+// The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
 //
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
-// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 //---------------------------------------------------------------------------------
@@ -30,8 +30,8 @@
 // IT8.7 / CGATS.17-200x handling -----------------------------------------------------------------------------
 
 
-#define MAXID        128     // Max lenght of identifier
-#define MAXSTR      1024     // Max lenght of string
+#define MAXID        128     // Max length of identifier
+#define MAXSTR      1024     // Max length of string
 #define MAXTABLES    255     // Max Number of tables in a single stream
 #define MAXINCLUDE    20     // Max number of nested includes
 
 #    define DIR_CHAR    '/'
 #endif
 
+
 // Symbols
-typedef enum { 
+typedef enum {
 
-        SNONE,
+        SUNDEFINED,
         SINUM,      // Integer
         SDNUM,      // Real
         SIDENT,     // Identifier
@@ -71,10 +72,10 @@ typedef enum {
 
 
 // How to write the value
-typedef enum { 
+typedef enum {
 
         WRITE_UNCOOKED,
-        WRITE_STRINGIFY,            
+        WRITE_STRINGIFY,
         WRITE_HEXADECIMAL,
         WRITE_BINARY,
         WRITE_PAIR
@@ -108,19 +109,21 @@ typedef struct _SubAllocator {
          cmsUInt8Number* Block;
          cmsUInt32Number BlockSize;
          cmsUInt32Number Used;
+
     } SUBALLOCATOR;
 
 // Table. Each individual table can hold properties and rows & cols
 typedef struct _Table {
-        
+
+        char SheetType[MAXSTR];               // The first row of the IT8 (the type)
+
         int            nSamples, nPatches;    // Cols, Rows
         int            SampleID;              // Pos of ID
-        
+
         KEYVALUE*      HeaderList;            // The properties
-        
+
         char**         DataFormat;            // The binary stream descriptor
-        char**         Data;                  // The binary stream        
+        char**         Data;                  // The binary stream
 
     } TABLE;
 
@@ -130,10 +133,9 @@ typedef struct _FileContext {
         FILE*          Stream;                   // File stream or NULL if holded in memory
     } FILECTX;
 
-// This struct hold all information about an open IT8 handler. 
+// This struct hold all information about an open IT8 handler.
 typedef struct {
 
-        char SheetType[MAXSTR];               // The first row of the IT8 (the type)
 
         cmsUInt32Number  TablesCount;                     // How many tables in this stream
         cmsUInt32Number  nTable;                          // The actual table
@@ -147,7 +149,7 @@ typedef struct {
         // Parser state machine
         SYMBOL         sy;                    // Current symbol
         int            ch;                    // Current character
-      
+
         int            inum;                  // integer value
         cmsFloat64Number         dnum;                  // real value
         char           id[MAXID];             // identifier
@@ -156,10 +158,10 @@ typedef struct {
         // Allowed keywords & datasets. They have visibility on whole stream
         KEYVALUE*     ValidKeywords;
         KEYVALUE*     ValidSampleID;
-              
+
         char*          Source;                // Points to loc. being parsed
         int            lineno;                // line counter for error reporting
-       
+
         FILECTX*       FileStack[MAXINCLUDE]; // Stack of files being parsed
         int            IncludeSP;             // Include Stack Pointer
 
@@ -198,7 +200,7 @@ typedef struct {
 
 // The keyword->symbol translation table. Sorting is required.
 static const KEYWORD TabKeys[] = {
+
         {"$INCLUDE",               SINCLUDE},   // This is an extension!
         {".INCLUDE",               SINCLUDE},   // This is an extension!
 
@@ -259,31 +261,31 @@ static PROPERTY PredefinedProperties[] = {
 
        // below properties are new in recent specs:
 
-        {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated 
-                               // along with details of the geometry and the aperture size and shape. For example, 
-                               // for transmission measurements it is important to identify 0/diffuse, diffuse/0, 
-                               // opal or integrating sphere, etc. For reflection it is important to identify 0/45, 
+        {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated
+                               // along with details of the geometry and the aperture size and shape. For example,
+                               // for transmission measurements it is important to identify 0/diffuse, diffuse/0,
+                               // opal or integrating sphere, etc. For reflection it is important to identify 0/45,
                                // 45/0, sphere (specular included or excluded), etc.
 
-       {"FILTER",            WRITE_STRINGIFY},   // Identifies the use of physical filter(s) during measurement. Typically used to 
+       {"FILTER",            WRITE_STRINGIFY},   // Identifies the use of physical filter(s) during measurement. Typically used to
                                // denote the use of filters such as none, D65, Red, Green or Blue.
 
-       {"POLARIZATION",      WRITE_STRINGIFY},   // Identifies the use of a physical polarization filter during measurement. Allowed 
+       {"POLARIZATION",      WRITE_STRINGIFY},   // Identifies the use of a physical polarization filter during measurement. Allowed
                                // values are {"yes�, �white�, �none� or �na�.
 
-       {"WEIGHTING_FUNCTION", WRITE_PAIR},   // Indicates such functions as: the CIE standard observer functions used in the 
-                               // calculation of various data parameters (2 degree and 10 degree), CIE standard 
+       {"WEIGHTING_FUNCTION", WRITE_PAIR},   // Indicates such functions as: the CIE standard observer functions used in the
+                               // calculation of various data parameters (2 degree and 10 degree), CIE standard
                                // illuminant functions used in the calculation of various data parameters (e.g., D50,
-                               // D65, etc.), density status response, etc. If used there shall be at least one 
-                               // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute 
+                               // D65, etc.), density status response, etc. If used there shall be at least one
+                               // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute
                                // in the set shall be {"name" and shall identify the particular parameter used.
-                               // The second shall be {"value" and shall provide the value associated with that name. 
-                               // For ASCII data, a string containing the Name and Value attribute pairs shall follow 
-                               // the weighting function keyword. A semi-colon separates attribute pairs from each 
+                               // The second shall be {"value" and shall provide the value associated with that name.
+                               // For ASCII data, a string containing the Name and Value attribute pairs shall follow
+                               // the weighting function keyword. A semi-colon separates attribute pairs from each
                                // other and within the attribute the name and value are separated by a comma.
 
-       {"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name 
-                               // of the calculation, parameter is the name of the parameter used in the calculation 
+       {"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name
+                               // of the calculation, parameter is the name of the parameter used in the calculation
                                // and value is the value of the parameter.
 
        {"TARGET_TYPE",        WRITE_STRINGIFY},  // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc.
@@ -301,7 +303,7 @@ static PROPERTY PredefinedProperties[] = {
 // Predefined sample types on dataset
 static const char* PredefinedSampleID[] = {
         "SAMPLE_ID",      // Identifies sample that data represents
-        "STRING",         // Identifies label, or other non-machine readable value. 
+        "STRING",         // Identifies label, or other non-machine readable value.
                           // Value must begin and end with a " symbol
 
         "CMYK_C",         // Cyan component of CMYK data expressed as a percentage
@@ -322,7 +324,7 @@ static const char* PredefinedSampleID[] = {
         "XYZ_X",          // X component of tristimulus data
         "XYZ_Y",          // Y component of tristimulus data
         "XYZ_Z",          // Z component of tristimulus data
-        "XYY_X"           // x component of chromaticity data
+        "XYY_X",          // x component of chromaticity data
         "XYY_Y",          // y component of chromaticity data
         "XYY_CAPY",       // Y component of tristimulus data
         "LAB_L",          // L* component of Lab data
@@ -349,31 +351,31 @@ static const char* PredefinedSampleID[] = {
 
 #define NUMPREDEFINEDSAMPLEID (sizeof(PredefinedSampleID)/sizeof(char *))
 
-//Forward declaration of some internal functions        
+//Forward declaration of some internal functions
 static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size);
 
-// Checks if c is a separator
+// Checks whatever c is a separator
 static
 cmsBool isseparator(int c)
 {
-        return (c == ' ') || (c == '\t') || (c == '\r');
+    return (c == ' ') || (c == '\t') ; 
 }
 
-// Checks whatever if c is a valid identifier char
-static 
+// Checks whatever c is a valid identifier char
+static
 cmsBool ismiddle(int c)
 {
    return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127));
 }
 
-// Checks whatsever if c is a valid identifier middle char.
+// Checks whatsever c is a valid identifier middle char.
 static
 cmsBool isidchar(int c)
 {
    return isalnum(c) || ismiddle(c);
 }
 
-// Checks whatsever if c is a valid identifier first char.
+// Checks whatsever c is a valid identifier first char.
 static
 cmsBool isfirstidchar(int c)
 {
@@ -388,7 +390,7 @@ cmsBool isabsolutepath(const char *path)
 
     if(path == NULL)
         return FALSE;
-    if (path[0] == 0) 
+    if (path[0] == 0)
         return FALSE;
 
     strncpy(ThreeChars, path, 3);
@@ -404,9 +406,10 @@ cmsBool isabsolutepath(const char *path)
     return FALSE;
 }
 
+
 // Makes a file path based on a given reference path
 // NOTE: this function doesn't check if the path exists or even if it's legal
-static 
+static
 cmsBool BuildAbsolutePath(const char *relPath, const char *basePath, char *buffer, cmsUInt32Number MaxLen)
 {
     char *tail;
@@ -420,8 +423,8 @@ cmsBool BuildAbsolutePath(const char *relPath, const char *basePath, char *buffe
         return TRUE;
     }
 
-    // No, search for last 
-    strncpy(buffer, basePath, MaxLen);  
+    // No, search for last
+    strncpy(buffer, basePath, MaxLen);
     buffer[MaxLen-1] = 0;
 
     tail = strrchr(buffer, DIR_CHAR);
@@ -431,9 +434,9 @@ cmsBool BuildAbsolutePath(const char *relPath, const char *basePath, char *buffe
     if (len >= MaxLen) return FALSE;
 
     // No need to assure zero terminator over here
-    strncpy(tail + 1, relPath, MaxLen - len);   
+    strncpy(tail + 1, relPath, MaxLen - len);
 
-    return TRUE;    
+    return TRUE;
 }
 
 
@@ -441,7 +444,7 @@ cmsBool BuildAbsolutePath(const char *relPath, const char *basePath, char *buffe
 static
 const char* NoMeta(const char* str)
 {
-    if (strchr(str, '%') != NULL) 
+    if (strchr(str, '%') != NULL)
         return "**** CORRUPTED FORMAT STRING ***";
 
     return str;
@@ -492,7 +495,7 @@ void NextCh(cmsIT8* it8)
 
             } else
                 it8 ->ch = 0;   // EOF
-        }              
+        }
     }
     else {
         it8->ch = *it8->Source;
@@ -518,7 +521,7 @@ SYMBOL BinSrchKey(const char *id)
         else l = x + 1;
     }
 
-    return SNONE;
+    return SUNDEFINED;
 }
 
 
@@ -545,7 +548,7 @@ void ReadReal(cmsIT8* it8, int inum)
     if (it8->ch == '.') {        // Decimal point
 
         cmsFloat64Number frac = 0.0;      // fraction
-        int prec = 0;           // precision
+        int prec = 0;                     // precision
 
         NextCh(it8);               // Eats dec. point
 
@@ -592,6 +595,84 @@ void ReadReal(cmsIT8* it8, int inum)
     }
 }
 
+// Parses a float number
+// This can not call directly atof because it uses locale dependant
+// parsing, while CCMX files always use . as decimal separator
+static
+cmsFloat64Number ParseFloatNumber(const char *Buffer)
+{
+    cmsFloat64Number dnum = 0.0;
+    int sign = 1;
+
+    // keep safe
+    if (Buffer == NULL) return 0.0;
+
+    if (*Buffer == '-' || *Buffer == '+') {
+
+         sign = (*Buffer == '-') ? -1 : 1;
+         Buffer++;
+    }
+
+
+    while (*Buffer && isdigit((int) *Buffer)) {
+
+        dnum = dnum * 10.0 + (*Buffer - '0');
+        if (*Buffer) Buffer++;
+    }
+
+    if (*Buffer == '.') {
+
+        cmsFloat64Number frac = 0.0;      // fraction
+        int prec = 0;                     // precission
+
+        if (*Buffer) Buffer++;
+
+        while (*Buffer && isdigit((int) *Buffer)) {
+
+            frac = frac * 10.0 + (*Buffer - '0');
+            prec++;
+            if (*Buffer) Buffer++;
+        }
+
+        dnum = dnum + (frac / xpow10(prec));
+    }
+
+    // Exponent, example 34.00E+20
+    if (*Buffer && toupper(*Buffer) == 'E') {
+
+        int e;
+        int sgn;
+
+        if (*Buffer) Buffer++;
+        sgn = 1;
+
+        if (*Buffer == '-') {
+
+            sgn = -1;
+            if (*Buffer) Buffer++;
+        }
+        else
+            if (*Buffer == '+') {
+
+                sgn = +1;
+                if (*Buffer) Buffer++;
+            }
+
+            e = 0;
+            while (*Buffer && isdigit((int) *Buffer)) {
+
+                if ((cmsFloat64Number) e * 10L < INT_MAX)
+                    e = e * 10 + (*Buffer - '0');
+
+                if (*Buffer) Buffer++;
+            }
+
+            e = sgn*e;
+            dnum = dnum * xpow10(e);
+    }
+
+    return sign * dnum;
+}
 
 
 // Reads next symbol
@@ -604,92 +685,92 @@ void InSymbol(cmsIT8* it8)
     int sng;
     
     do {
-        
+
         while (isseparator(it8->ch))
             NextCh(it8);
-        
+
         if (isfirstidchar(it8->ch)) {          // Identifier
-                        
+
             k = 0;
             idptr = it8->id;
-            
+
             do {
-                
+
                 if (++k < MAXID) *idptr++ = (char) it8->ch;
-                
+
                 NextCh(it8);
-                
+
             } while (isidchar(it8->ch));
-            
+
             *idptr = '\0';
-            
-            
+
+
             key = BinSrchKey(it8->id);
-            if (key == SNONE) it8->sy = SIDENT;
+            if (key == SUNDEFINED) it8->sy = SIDENT;
             else it8->sy = key;
-            
+
         }
         else                         // Is a number?
             if (isdigit(it8->ch) || it8->ch == '.' || it8->ch == '-' || it8->ch == '+')
             {
                 int sign = 1;
-                
+
                 if (it8->ch == '-') {
                     sign = -1;
                     NextCh(it8);
                 }
-                
+
                 it8->inum = 0;
                 it8->sy   = SINUM;
-                
+
                 if (it8->ch == '0') {          // 0xnnnn (Hexa) or 0bnnnn (Binary)
-                
+
                     NextCh(it8);
                     if (toupper(it8->ch) == 'X') {
 
                         int j;
-                        
+
                         NextCh(it8);
                         while (isxdigit(it8->ch))
                         {
                             it8->ch = toupper(it8->ch);
                             if (it8->ch >= 'A' && it8->ch <= 'F')  j = it8->ch -'A'+10;
                             else j = it8->ch - '0';
-                            
+
                             if ((long) it8->inum * 16L > (long) INT_MAX)
                             {
                                 SynError(it8, "Invalid hexadecimal number");
                                 return;
                             }
-                            
+
                             it8->inum = it8->inum * 16 + j;
                             NextCh(it8);
                         }
                         return;
                     }
-                    
+
                     if (toupper(it8->ch) == 'B') {  // Binary
-                    
+
                         int j;
-                        
+
                         NextCh(it8);
                         while (it8->ch == '0' || it8->ch == '1')
                         {
                             j = it8->ch - '0';
-                            
+
                             if ((long) it8->inum * 2L > (long) INT_MAX)
                             {
                                 SynError(it8, "Invalid binary number");
                                 return;
                             }
-                            
+
                             it8->inum = it8->inum * 2 + j;
                             NextCh(it8);
                         }
                         return;
                     }
                 }
-                
+
 
                 while (isdigit(it8->ch)) {
 
@@ -699,19 +780,19 @@ void InSymbol(cmsIT8* it8)
                         it8->dnum *= sign;
                         return;
                     }
-                    
+
                     it8->inum = it8->inum * 10 + (it8->ch - '0');
                     NextCh(it8);
                 }
-                
+
                 if (it8->ch == '.') {
-                    
+
                     ReadReal(it8, it8->inum);
                     it8->sy = SDNUM;
                     it8->dnum *= sign;
                     return;
                 }
-                
+
                 it8 -> inum *= sign;
 
                 // Special case. Numbers followed by letters are taken as identifiers
@@ -720,28 +801,28 @@ void InSymbol(cmsIT8* it8)
 
                     if (it8 ->sy == SINUM) {
 
-                        sprintf(it8->id, "%d", it8->inum);
+                        snprintf(it8->id, 127, "%d", it8->inum);
                     }
                     else {
 
-                        sprintf(it8->id, it8 ->DoubleFormatter, it8->dnum);
+                        snprintf(it8->id, 127, it8 ->DoubleFormatter, it8->dnum);
                     }
 
                     k = (int) strlen(it8 ->id);
                     idptr = it8 ->id + k;
                     do {
-                
+
                         if (++k < MAXID) *idptr++ = (char) it8->ch;
-                
+
                         NextCh(it8);
-                
+
                     } while (isidchar(it8->ch));
-            
-                    *idptr = '\0';                    
+
+                    *idptr = '\0';
                     it8->sy = SIDENT;
                 }
                 return;
-                
+
             }
             else
                 switch ((int) it8->ch) {
@@ -756,24 +837,32 @@ void InSymbol(cmsIT8* it8)
         case -1:
             it8->sy = SEOF;
             break;
-            
-            
-        // Next line            
+
+
+        // Next line
+        case '\r':
+            NextCh(it8);
+            if (it8 ->ch == '\n') 
+                NextCh(it8);
+            it8->sy = SEOLN;
+            it8->lineno++;
+            break;
+
         case '\n':
             NextCh(it8);
             it8->sy = SEOLN;
             it8->lineno++;
             break;
-            
+
         // Comment
         case '#':
             NextCh(it8);
-            while (it8->ch && it8->ch != '\n')
+            while (it8->ch && it8->ch != '\n' && it8->ch != '\r')
                 NextCh(it8);
-            
+
             it8->sy = SCOMMENT;
             break;
-            
+
         // String.
         case '\'':
         case '\"':
@@ -781,28 +870,28 @@ void InSymbol(cmsIT8* it8)
             sng = it8->ch;
             k = 0;
             NextCh(it8);
-            
+
             while (k < MAXSTR && it8->ch != sng) {
-                
+
                 if (it8->ch == '\n'|| it8->ch == '\r') k = MAXSTR+1;
-                else {                                    
+                else {
                     *idptr++ = (char) it8->ch;
                     NextCh(it8);
                     k++;
                 }
             }
-            
+
             it8->sy = SSTRING;
             *idptr = '\0';
             NextCh(it8);
             break;
-            
-            
+
+
         default:
-            SynError(it8, "Unrecognized character: 0x%x", it8 ->ch);            
-            return;            
+            SynError(it8, "Unrecognized character: 0x%x", it8 ->ch);
+            return;
             }
-            
+
     } while (it8->sy == SCOMMENT);
 
     // Handle the include special token
@@ -828,8 +917,8 @@ void InSymbol(cmsIT8* it8)
                     //  TODO: how to manage out-of-memory conditions?
                 }
 
-                if (BuildAbsolutePath(it8->str, 
-                                      it8->FileStack[it8->IncludeSP]->FileName, 
+                if (BuildAbsolutePath(it8->str,
+                                      it8->FileStack[it8->IncludeSP]->FileName,
                                       FileNest->FileName, cmsMAX_PATH-1) == FALSE) {
                     SynError(it8, "File path too long");
                     return;
@@ -844,9 +933,9 @@ void InSymbol(cmsIT8* it8)
                 it8->IncludeSP++;
 
                 it8 ->ch = ' ';
-                InSymbol(it8);    
+                InSymbol(it8);
     }
-                
+
 }
 
 // Checks end of line separator
@@ -886,12 +975,15 @@ cmsBool GetVal(cmsIT8* it8, char* Buffer, cmsUInt32Number max, const char* Error
 {
     switch (it8->sy) {
 
-    case SIDENT:  strncpy(Buffer, it8->id, max); 
+    case SEOLN:   // Empty value
+                  Buffer[0]=0;
+                  break;
+    case SIDENT:  strncpy(Buffer, it8->id, max);
                   Buffer[max-1]=0;
                   break;
     case SINUM:   snprintf(Buffer, max, "%d", it8 -> inum); break;
     case SDNUM:   snprintf(Buffer, max, it8->DoubleFormatter, it8 -> dnum); break;
-    case SSTRING: strncpy(Buffer, it8->str, max); 
+    case SSTRING: strncpy(Buffer, it8->str, max);
                   Buffer[max-1] = 0;
                   break;
 
@@ -908,12 +1000,12 @@ cmsBool GetVal(cmsIT8* it8, char* Buffer, cmsUInt32Number max, const char* Error
 
 static
 TABLE* GetTable(cmsIT8* it8)
-{        
+{
    if ((it8 -> nTable >= it8 ->TablesCount)) {
 
            SynError(it8, "Table %d out of sequence", it8 -> nTable);
            return it8 -> Tab;
-   }            
+   }
 
    return it8 ->Tab + it8 ->nTable;
 }
@@ -943,7 +1035,7 @@ void CMSEXPORT cmsIT8Free(cmsHANDLE hIT8)
     }
 
     if (it8->MemoryBlock)
-        _cmsFree(it8 ->ContextID, it8->MemoryBlock);    
+        _cmsFree(it8 ->ContextID, it8->MemoryBlock);
 
     _cmsFree(it8 ->ContextID, it8);
 }
@@ -982,7 +1074,7 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
     cmsUInt32Number Free = it8 ->Allocator.BlockSize - it8 ->Allocator.Used;
     cmsUInt8Number* ptr;
 
-    size = _cmsALIGNLONG(size);
+    size = _cmsALIGNMEM(size);
 
     if (size > Free) {
 
@@ -998,12 +1090,12 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
         it8 ->Allocator.Used = 0;
         it8 ->Allocator.Block = (cmsUInt8Number*)  AllocBigBlock(it8, it8 ->Allocator.BlockSize);
     }
-            
+
     ptr = it8 ->Allocator.Block + it8 ->Allocator.Used;
     it8 ->Allocator.Used += size;
 
     return (void*) ptr;
-    
+
 }
 
 
@@ -1019,7 +1111,7 @@ char *AllocString(cmsIT8* it8, const char* str)
     if (ptr) strncpy (ptr, str, Size-1);
 
     return ptr;
-}  
+}
 
 // Searches through linked list
 
@@ -1035,9 +1127,9 @@ cmsBool IsAvailableOnList(KEYVALUE* p, const char* Key, const char* Subkey, KEYV
         if (*Key != '#') { // Comments are ignored
 
             if (cmsstrcasecmp(Key, p->Keyword) == 0)
-                    break;
-        }
+                break;
         }
+    }
 
     if (p == NULL)
         return FALSE;
@@ -1047,11 +1139,13 @@ cmsBool IsAvailableOnList(KEYVALUE* p, const char* Key, const char* Subkey, KEYV
 
     for (; p != NULL; p = p->NextSubkey) {
 
+        if (p ->Subkey == NULL) continue;
+
         if (LastPtr) *LastPtr = p;
 
         if (cmsstrcasecmp(Subkey, p->Subkey) == 0)
-                    return TRUE;
-        }
+            return TRUE;
+    }
 
     return FALSE;
 }
@@ -1066,13 +1160,13 @@ KEYVALUE* AddToList(cmsIT8* it8, KEYVALUE** Head, const char *Key, const char *S
     KEYVALUE* last;
 
 
-    // Check if property is already in list 
+    // Check if property is already in list
 
     if (IsAvailableOnList(*Head, Key, Subkey, &p)) {
 
         // This may work for editing properties
 
-        //     return SynError(it8, "duplicate key <%s>", Key);                                        
+        //     return SynError(it8, "duplicate key <%s>", Key);
     }
     else {
 
@@ -1082,7 +1176,7 @@ KEYVALUE* AddToList(cmsIT8* it8, KEYVALUE** Head, const char *Key, const char *S
         p = (KEYVALUE*) AllocChunk(it8, sizeof(KEYVALUE));
         if (p == NULL)
         {
-            SynError(it8, "AddToList: out of memory");        
+            SynError(it8, "AddToList: out of memory");
             return NULL;
         }
 
@@ -1097,13 +1191,13 @@ KEYVALUE* AddToList(cmsIT8* it8, KEYVALUE** Head, const char *Key, const char *S
         else
         {
             if (Subkey != NULL && last != NULL) {
-            
+
                 last->NextSubkey = p;
 
                 // If Subkey is not null, then last is the last property with the same key,
                 // but not necessarily is the last property in the list, so we need to move
                 // to the actual list end
-                while (last->Next != NULL) 
+                while (last->Next != NULL)
                          last = last->Next;
             }
 
@@ -1151,7 +1245,7 @@ void AllocTable(cmsIT8* it8)
     t->HeaderList = NULL;
     t->DataFormat = NULL;
     t->Data       = NULL;
-   
+
     it8 ->TablesCount++;
 }
 
@@ -1174,7 +1268,7 @@ cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE  IT8, cmsUInt32Number nTable)
 
      it8 ->nTable = nTable;
 
-     return nTable;
+     return (cmsInt32Number) nTable;
 }
 
 
@@ -1183,27 +1277,27 @@ cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE  IT8, cmsUInt32Number nTable)
 cmsHANDLE  CMSEXPORT cmsIT8Alloc(cmsContext ContextID)
 {
     cmsIT8* it8;
-    int i;
+    cmsUInt32Number i;
 
     it8 = (cmsIT8*) _cmsMallocZero(ContextID, sizeof(cmsIT8));
     if (it8 == NULL) return NULL;
 
     AllocTable(it8);
-    
+
     it8->MemoryBlock = NULL;
     it8->MemorySink  = NULL;
-    
+
     it8 ->nTable = 0;
 
     it8->ContextID = ContextID;
     it8->Allocator.Used = 0;
     it8->Allocator.Block = NULL;
-    it8->Allocator.BlockSize = 0;  
+    it8->Allocator.BlockSize = 0;
 
     it8->ValidKeywords = NULL;
     it8->ValidSampleID = NULL;
 
-    it8 -> sy = SNONE;
+    it8 -> sy = SUNDEFINED;
     it8 -> ch = ' ';
     it8 -> Source = NULL;
     it8 -> inum = 0;
@@ -1214,10 +1308,10 @@ cmsHANDLE  CMSEXPORT cmsIT8Alloc(cmsContext ContextID)
     it8 -> lineno = 1;
 
     strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
-    strcpy(it8->SheetType, "CGATS.17");
+    cmsIT8SetSheetType((cmsHANDLE) it8, "CGATS.17");
 
     // Initialize predefined properties & data
-    
+
     for (i=0; i < NUMPREDEFINEDPROPS; i++)
             AddAvailableProperty(it8, PredefinedProperties[i].id, PredefinedProperties[i].as);
 
@@ -1231,18 +1325,15 @@ cmsHANDLE  CMSEXPORT cmsIT8Alloc(cmsContext ContextID)
 
 const char* CMSEXPORT cmsIT8GetSheetType(cmsHANDLE hIT8)
 {
-        cmsIT8* it8 = (cmsIT8*) hIT8;
-
-        return it8 ->SheetType;
-
+        return GetTable((cmsIT8*) hIT8)->SheetType;
 }
 
 cmsBool CMSEXPORT cmsIT8SetSheetType(cmsHANDLE hIT8, const char* Type)
 {
-        cmsIT8* it8 = (cmsIT8*) hIT8;
+        TABLE* t = GetTable((cmsIT8*) hIT8);
 
-        strncpy(it8 ->SheetType, Type, MAXSTR-1);
-        it8 ->SheetType[MAXSTR-1] = 0;
+        strncpy(t ->SheetType, Type, MAXSTR-1);
+        t ->SheetType[MAXSTR-1] = 0;
         return TRUE;
 }
 
@@ -1256,8 +1347,6 @@ cmsBool CMSEXPORT cmsIT8SetComment(cmsHANDLE hIT8, const char* Val)
     return AddToList(it8, &GetTable(it8)->HeaderList, "# ", NULL, Val, WRITE_UNCOOKED) != NULL;
 }
 
-
-
 // Sets a property
 cmsBool CMSEXPORT cmsIT8SetPropertyStr(cmsHANDLE hIT8, const char* Key, const char *Val)
 {
@@ -1269,31 +1358,30 @@ cmsBool CMSEXPORT cmsIT8SetPropertyStr(cmsHANDLE hIT8, const char* Key, const ch
     return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Val, WRITE_STRINGIFY) != NULL;
 }
 
-
 cmsBool CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFloat64Number Val)
 {
     cmsIT8* it8 = (cmsIT8*) hIT8;
     char Buffer[1024];
-   
-    sprintf(Buffer, it8->DoubleFormatter, Val);
 
-    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL;    
+    snprintf(Buffer, 1023, it8->DoubleFormatter, Val);
+
+    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL;
 }
 
 cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUInt32Number Val)
 {
     cmsIT8* it8 = (cmsIT8*) hIT8;
     char Buffer[1024];
-   
-    sprintf(Buffer, "%d", Val);
 
-    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL;    
+    snprintf(Buffer, 1023, "%u", Val);
+
+    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL;
 }
 
 cmsBool CMSEXPORT cmsIT8SetPropertyUncooked(cmsHANDLE hIT8, const char* Key, const char* Buffer)
 {
-    cmsIT8* it8 = (cmsIT8*) hIT8;    
-    
+    cmsIT8* it8 = (cmsIT8*) hIT8;
+
     return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Buffer, WRITE_UNCOOKED) != NULL;
 }
 
@@ -1322,8 +1410,9 @@ cmsFloat64Number CMSEXPORT cmsIT8GetPropertyDbl(cmsHANDLE hIT8, const char* cPro
 {
     const char *v = cmsIT8GetProperty(hIT8, cProp);
 
-    if (v) return atof(v);
-    else return 0.0;
+    if (v == NULL) return 0.0;
+
+    return ParseFloatNumber(v);
 }
 
 const char* CMSEXPORT cmsIT8GetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char *SubKey)
@@ -1355,7 +1444,7 @@ void AllocateDataFormat(cmsIT8* it8)
         t -> nSamples = 10;
         }
 
-    t -> DataFormat = (char**) AllocChunk (it8, (t->nSamples + 1) * sizeof(char *));
+    t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *));
     if (t->DataFormat == NULL) {
 
         SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array");
@@ -1386,8 +1475,8 @@ cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label)
         SynError(it8, "More than NUMBER_OF_FIELDS fields.");
         return FALSE;
     }
-    
-    if (t->DataFormat) {                
+
+    if (t->DataFormat) {
         t->DataFormat[n] = AllocString(it8, label);
     }
 
@@ -1411,7 +1500,7 @@ void AllocateDataSet(cmsIT8* it8)
     t-> nSamples   = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
     t-> nPatches   = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
 
-    t-> Data = (char**)AllocChunk (it8, (t->nSamples + 1) * (t->nPatches + 1) *sizeof (char*));
+    t-> Data = (char**)AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * ((cmsUInt32Number) t->nPatches + 1) *sizeof (char*));
     if (t->Data == NULL) {
 
         SynError(it8, "AllocateDataSet: Unable to allocate data array");
@@ -1425,7 +1514,7 @@ char* GetData(cmsIT8* it8, int nSet, int nField)
     TABLE* t = GetTable(it8);
     int  nSamples   = t -> nSamples;
     int  nPatches   = t -> nPatches;
-    
+
     if (nSet >= nPatches || nField >= nSamples)
         return NULL;
 
@@ -1445,14 +1534,14 @@ cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val)
 
     if (nSet > t -> nPatches || nSet < 0) {
 
-            return SynError(it8, "Patch %d out of range, there are %d patches", nSet, t -> nPatches);            
+            return SynError(it8, "Patch %d out of range, there are %d patches", nSet, t -> nPatches);
     }
 
     if (nField > t ->nSamples || nField < 0) {
             return SynError(it8, "Sample %d out of range, there are %d samples", nField, t ->nSamples);
-            
+
     }
-    
+
     t->Data [nSet * t -> nSamples + nField] = AllocString(it8, Val);
     return TRUE;
 }
@@ -1467,37 +1556,37 @@ void WriteStr(SAVESTREAM* f, const char *str)
 {
     cmsUInt32Number len;
 
-    if (str == NULL) 
+    if (str == NULL)
         str = " ";
-    
-    // Lenghth to write
+
+    // Length to write
     len = (cmsUInt32Number) strlen(str);
     f ->Used += len;
-    
+
 
     if (f ->stream) {   // Should I write it to a file?
 
         if (fwrite(str, 1, len, f->stream) != len) {
             cmsSignalError(0, cmsERROR_WRITE, "Write to file error in CGATS parser");
             return;
-        }          
-        
+        }
+
     }
     else {  // Or to a memory block?
-                        
+
         if (f ->Base) {   // Am I just counting the bytes?
-            
+
             if (f ->Used > f ->Max) {
 
                  cmsSignalError(0, cmsERROR_WRITE, "Write to memory overflows in CGATS parser");
                  return;
             }
-            
+
             memmove(f ->Ptr, str, len);
             f->Ptr += len;
         }
-                        
-    }   
+
+    }
 }
 
 
@@ -1524,24 +1613,27 @@ void WriteHeader(cmsIT8* it8, SAVESTREAM* fp)
     KEYVALUE* p;
     TABLE* t = GetTable(it8);
 
-    
+    // Writes the type
+    WriteStr(fp, t->SheetType);
+    WriteStr(fp, "\n");
+
     for (p = t->HeaderList; (p != NULL); p = p->Next)
     {
         if (*p ->Keyword == '#') {
 
             char* Pt;
-            
+
             WriteStr(fp, "#\n# ");
             for (Pt = p ->Value; *Pt; Pt++) {
 
 
-                Writef(fp, "%c", *Pt);                
+                Writef(fp, "%c", *Pt);
 
                 if (*Pt == '\n') {
                     WriteStr(fp, "# ");
                 }
             }
-        
+
             WriteStr(fp, "\n#\n");
             continue;
         }
@@ -1564,7 +1656,7 @@ void WriteHeader(cmsIT8* it8, SAVESTREAM* fp)
             switch (p ->WriteAs) {
 
             case WRITE_UNCOOKED:
-                    Writef(fp, "\t%s", p ->Value);                    
+                    Writef(fp, "\t%s", p ->Value);
                     break;
 
             case WRITE_STRINGIFY:
@@ -1663,7 +1755,7 @@ void WriteData(SAVESTREAM* fp, cmsIT8* it8)
 // Saves whole file
 cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName)
 {
-    SAVESTREAM sd;  
+    SAVESTREAM sd;
     cmsUInt32Number i;
     cmsIT8* it8 = (cmsIT8*) hIT8;
 
@@ -1671,9 +1763,7 @@ cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName)
 
     sd.stream = fopen(cFileName, "wt");
     if (!sd.stream) return FALSE;
-    
-    WriteStr(&sd, it8->SheetType);
-    WriteStr(&sd, "\n");
+
     for (i=0; i < it8 ->TablesCount; i++) {
 
             cmsIT8SetTable(hIT8, i);
@@ -1681,7 +1771,7 @@ cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName)
             WriteDataFormat(&sd, it8);
             WriteData(&sd, it8);
     }
-    
+
     if (fclose(sd.stream) != 0) return FALSE;
 
     return TRUE;
@@ -1691,7 +1781,7 @@ cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName)
 // Saves to memory
 cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* BytesNeeded)
 {
-    SAVESTREAM sd;  
+    SAVESTREAM sd;
     cmsUInt32Number i;
     cmsIT8* it8 = (cmsIT8*) hIT8;
 
@@ -1703,25 +1793,23 @@ cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number*
 
     sd.Used = 0;
 
-    if (sd.Base) 
+    if (sd.Base)
         sd.Max  = *BytesNeeded;     // Write to memory?
-    else 
+    else
         sd.Max  = 0;                // Just counting the needed bytes
-   
-    WriteStr(&sd, it8->SheetType);
-    WriteStr(&sd, "\n");
+
     for (i=0; i < it8 ->TablesCount; i++) {
 
-            cmsIT8SetTable(hIT8, i);
-            WriteHeader(it8, &sd);
-            WriteDataFormat(&sd, it8);
-            WriteData(&sd, it8);
+        cmsIT8SetTable(hIT8, i);
+        WriteHeader(it8, &sd);
+        WriteDataFormat(&sd, it8);
+        WriteData(&sd, it8);
     }
-    
+
     sd.Used++;  // The \0 at the very end
 
     if (sd.Base)
-        sd.Ptr = 0;
+        *sd.Ptr = 0;
 
     *BytesNeeded = sd.Used;
 
@@ -1734,7 +1822,7 @@ cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number*
 static
 cmsBool DataFormatSection(cmsIT8* it8)
 {
-    int iField = 0;    
+    int iField = 0;
     TABLE* t = GetTable(it8);
 
     InSymbol(it8);   // Eats "BEGIN_DATA_FORMAT"
@@ -1744,15 +1832,15 @@ cmsBool DataFormatSection(cmsIT8* it8)
         it8->sy != SEOLN &&
         it8->sy != SEOF &&
         it8->sy != SSYNERROR)  {
-        
+
             if (it8->sy != SIDENT) {
-            
-                return SynError(it8, "Sample type expected");                    
+
+                return SynError(it8, "Sample type expected");
             }
-        
+
             if (!SetDataFormat(it8, iField, it8->id)) return FALSE;
             iField++;
-                
+
             InSymbol(it8);
             SkipEOLN(it8);
        }
@@ -1764,7 +1852,7 @@ cmsBool DataFormatSection(cmsIT8* it8)
        if (iField != t ->nSamples) {
            SynError(it8, "Count mismatch. NUMBER_OF_FIELDS was %d, found %d\n", t ->nSamples, iField);
 
-           
+
        }
 
        return TRUE;
@@ -1791,7 +1879,7 @@ cmsBool DataSection (cmsIT8* it8)
         if (iField >= t -> nSamples) {
             iField = 0;
             iSet++;
-          
+
         }
 
         if (it8->sy != SEND_DATA && it8->sy != SEOF) {
@@ -1803,16 +1891,16 @@ cmsBool DataSection (cmsIT8* it8)
                 return FALSE;
 
             iField++;
-            
+
             InSymbol(it8);
-            SkipEOLN(it8);           
+            SkipEOLN(it8);
         }
     }
 
     SkipEOLN(it8);
     Skip(it8, SEND_DATA);
     SkipEOLN(it8);
+
     // Check for data completion.
 
     if ((iSet+1) != t -> nPatches)
@@ -1841,7 +1929,7 @@ cmsBool HeaderSection(cmsIT8* it8)
 
         case SKEYWORD:
                 InSymbol(it8);
-                if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE;                
+                if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE;
                 if (!AddAvailableProperty(it8, Buffer, WRITE_UNCOOKED)) return FALSE;
                 InSymbol(it8);
                 break;
@@ -1849,7 +1937,7 @@ cmsBool HeaderSection(cmsIT8* it8)
 
         case SDATA_FORMAT_ID:
                 InSymbol(it8);
-                if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE;                
+                if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE;
                 if (!AddAvailableSampleID(it8, Buffer)) return FALSE;
                 InSymbol(it8);
                 break;
@@ -1858,10 +1946,10 @@ cmsBool HeaderSection(cmsIT8* it8)
         case SIDENT:
                 strncpy(VarName, it8->id, MAXID-1);
                 VarName[MAXID-1] = 0;
-                
+
                 if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) {
 
-#ifdef CMS_STRICT_CGATS               
+#ifdef CMS_STRICT_CGATS
                  return SynError(it8, "Undefined keyword '%s'", VarName);
 #else
                     Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED);
@@ -1873,7 +1961,7 @@ cmsBool HeaderSection(cmsIT8* it8)
                 if (!GetVal(it8, Buffer, MAXSTR-1, "Property data expected")) return FALSE;
 
                 if(Key->WriteAs != WRITE_PAIR) {
-                    AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer, 
+                    AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
                                 (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
                 }
                 else {
@@ -1886,7 +1974,7 @@ cmsBool HeaderSection(cmsIT8* it8)
                     for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey)
                     {
                         char *Value, *temp;
-                
+
                         //  identify token pair boundary
                         Nextkey = (char*) strchr(Subkey, ';');
                         if(Nextkey)
@@ -1903,7 +1991,7 @@ cmsBool HeaderSection(cmsIT8* it8)
 
                         // gobble any space at the right
                         temp = Value + strlen(Value) - 1;
-                        while(*temp == ' ') *temp-- = '\0'; 
+                        while(*temp == ' ') *temp-- = '\0';
 
                         // trim the strings from the left
                         Subkey += strspn(Subkey, " ");
@@ -1914,11 +2002,11 @@ cmsBool HeaderSection(cmsIT8* it8)
                         AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR);
                     }
                 }
-                
+
                 InSymbol(it8);
                 break;
 
-        
+
         case SEOLN: break;
 
         default:
@@ -1934,27 +2022,34 @@ cmsBool HeaderSection(cmsIT8* it8)
 
 
 static
-cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
+void ReadType(cmsIT8* it8, char* SheetTypePtr)
 {
-    char* SheetTypePtr = it8 ->SheetType;
-
-    if (nosheet == 0) {
-
     // First line is a very special case.
 
     while (isseparator(it8->ch))
             NextCh(it8);
-    
+
     while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != -1) {
 
         *SheetTypePtr++= (char) it8 ->ch;
         NextCh(it8);
     }
-    }
 
     *SheetTypePtr = 0;
+}
+
+
+static
+cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
+{
+    char* SheetTypePtr = it8 ->Tab[0].SheetType;
+
+    if (nosheet == 0) {
+        ReadType(it8, SheetTypePtr);
+    }
+
     InSymbol(it8);
-   
+
     SkipEOLN(it8);
 
     while (it8-> sy != SEOF &&
@@ -1969,11 +2064,44 @@ cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
             case SBEGIN_DATA:
 
                     if (!DataSection(it8)) return FALSE;
-                    
+
                     if (it8 -> sy != SEOF) {
 
                             AllocTable(it8);
                             it8 ->nTable = it8 ->TablesCount - 1;
+
+                            // Read sheet type if present. We only support identifier and string.
+                            // <ident> <eoln> is a type string
+                            // anything else, is not a type string
+                            if (nosheet == 0) {
+
+                                if (it8 ->sy == SIDENT) {
+
+                                    // May be a type sheet or may be a prop value statement. We cannot use insymbol in
+                                    // this special case...
+                                     while (isseparator(it8->ch))
+                                         NextCh(it8);
+
+                                     // If a newline is found, then this is a type string
+                                    if (it8 ->ch == '\n' || it8->ch == '\r') {
+
+                                         cmsIT8SetSheetType(it8, it8 ->id);
+                                         InSymbol(it8);
+                                    }
+                                    else
+                                    {
+                                        // It is not. Just continue
+                                        cmsIT8SetSheetType(it8, "");
+                                    }
+                                }
+                                else
+                                    // Validate quoted strings
+                                    if (it8 ->sy == SSTRING) {
+                                        cmsIT8SetSheetType(it8, it8 ->str);
+                                        InSymbol(it8);
+                                    }
+                           }
+
                     }
                     break;
 
@@ -2007,7 +2135,7 @@ void CookPointers(cmsIT8* it8)
     TABLE* t = it8 ->Tab + j;
 
     t -> SampleID = 0;
-    it8 ->nTable = j;    
+    it8 ->nTable = j;
 
     for (idField = 0; idField < t -> nSamples; idField++)
     {
@@ -2022,41 +2150,41 @@ void CookPointers(cmsIT8* it8)
 
         if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) {
 
-                    t -> SampleID = idField;
-                
-        for (i=0; i < t -> nPatches; i++) {
+            t -> SampleID = idField;
+
+            for (i=0; i < t -> nPatches; i++) {
 
                 char *Data = GetData(it8, i, idField);
                 if (Data) {
                     char Buffer[256];
-                
+
                     strncpy(Buffer, Data, 255);
                     Buffer[255] = 0;
-                                       
+
                     if (strlen(Buffer) <= strlen(Data))
                         strcpy(Data, Buffer);
                     else
                         SetData(it8, i, idField, Buffer);
 
                 }
-                }
-        
+            }
+
         }
 
         // "LABEL" is an extension. It keeps references to forward tables
-         
+
         if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$' ) {
-                                        
+
                     // Search for table references...
                     for (i=0; i < t -> nPatches; i++) {
 
                             char *Label = GetData(it8, i, idField);
-                           
-                            if (Label) {                                
-                                
+
+                            if (Label) {
+
                                 cmsUInt32Number k;
 
-                                // This is the label, search for a table containing 
+                                // This is the label, search for a table containing
                                 // this property
 
                                 for (k=0; k < it8 ->TablesCount; k++) {
@@ -2070,10 +2198,10 @@ void CookPointers(cmsIT8* it8)
                                         char Buffer[256];
 
                                         char *Type  = p ->Value;
-                                        int  nTable = k;                                        
+                                        int  nTable = (int) k;
 
                                         snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type );
-                                                                                
+
                                         SetData(it8, i, idField, Buffer);
                                     }
                                 }
@@ -2094,14 +2222,14 @@ void CookPointers(cmsIT8* it8)
 
 // Try to infere if the file is a CGATS/IT8 file at all. Read first line
 // that should be something like some printable characters plus a \n
-
+// returns 0 if this is not like a CGATS, or an integer otherwise. This integer is the number of words in first line?
 static
 int IsMyBlock(cmsUInt8Number* Buffer, int n)
 {
-    int cols = 1, space = 0, quot = 0;
+    int words = 1, space = 0, quot = 0;
     int i;
 
-    if (n < 10) return FALSE;   // Too small
+    if (n < 10) return 0;   // Too small
 
     if (n > 132)
         n = 132;
@@ -2112,7 +2240,7 @@ int IsMyBlock(cmsUInt8Number* Buffer, int n)
         {
         case '\n':
         case '\r':
-            return quot == 1 || cols > 2 ? 0 : cols;
+            return ((quot == 1) || (words > 2)) ? 0 : words;
         case '\t':
         case ' ':
             if(!quot && !space)
@@ -2124,14 +2252,13 @@ int IsMyBlock(cmsUInt8Number* Buffer, int n)
         default:
             if (Buffer[i] < 32) return 0;
             if (Buffer[i] > 127) return 0;
-            cols += space;
+            words += space;
             space = 0;
             break;
         }
     }
 
-    return FALSE;
-
+    return 0;
 }
 
 
@@ -2150,8 +2277,8 @@ cmsBool IsMyFile(const char* FileName)
 
    Size = (cmsUInt32Number) fread(Ptr, 1, 132, fp);
 
-   if (fclose(fp) != 0) 
-          return FALSE;
+   if (fclose(fp) != 0)
+       return FALSE;
 
    Ptr[Size] = '\0';
 
@@ -2163,16 +2290,16 @@ cmsBool IsMyFile(const char* FileName)
 
 cmsHANDLE  CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len)
 {
-    cmsHANDLE hIT8; 
+    cmsHANDLE hIT8;
     cmsIT8*  it8;
-       int type;
+    int type;
 
-       _cmsAssert(Ptr != NULL);
-       _cmsAssert(len != 0);
+    _cmsAssert(Ptr != NULL);
+    _cmsAssert(len != 0);
 
     type = IsMyBlock((cmsUInt8Number*)Ptr, len);
     if (type == 0) return NULL;
-    
+
     hIT8 = cmsIT8Alloc(ContextID);
     if (!hIT8) return NULL;
 
@@ -2185,10 +2312,10 @@ cmsHANDLE  CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt3
     strncpy(it8->FileStack[0]->FileName, "", cmsMAX_PATH-1);
     it8-> Source = it8 -> MemoryBlock;
 
-    if (!ParseIT8(it8, type-1)) { 
-       
-        cmsIT8Free(hIT8); 
-        return FALSE; 
+    if (!ParseIT8(it8, type-1)) {
+
+        cmsIT8Free(hIT8);
+        return FALSE;
     }
 
     CookPointers(it8);
@@ -2206,45 +2333,45 @@ cmsHANDLE  CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt3
 cmsHANDLE  CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileName)
 {
 
-     cmsHANDLE hIT8; 
+     cmsHANDLE hIT8;
      cmsIT8*  it8;
-        int type;
-        
-        _cmsAssert(cFileName != NULL);
+     int type;
 
-        type = IsMyFile(cFileName);
+     _cmsAssert(cFileName != NULL);
+
+     type = IsMyFile(cFileName);
      if (type == 0) return NULL;
 
      hIT8 = cmsIT8Alloc(ContextID);
-     it8 = (cmsIT8*) hIT8;   
+     it8 = (cmsIT8*) hIT8;
      if (!hIT8) return NULL;
 
 
      it8 ->FileStack[0]->Stream = fopen(cFileName, "rt");
 
-     if (!it8 ->FileStack[0]->Stream) {         
+     if (!it8 ->FileStack[0]->Stream) {
          cmsIT8Free(hIT8);
          return NULL;
      }
-     
 
-    strncpy(it8->FileStack[0]->FileName, cFileName, cmsMAX_PATH-1);    
+
+    strncpy(it8->FileStack[0]->FileName, cFileName, cmsMAX_PATH-1);
     it8->FileStack[0]->FileName[cmsMAX_PATH-1] = 0;
 
-    if (!ParseIT8(it8, type-1)) { 
-    
+    if (!ParseIT8(it8, type-1)) {
+
             fclose(it8 ->FileStack[0]->Stream);
-            cmsIT8Free(hIT8); 
-            return NULL; 
+            cmsIT8Free(hIT8);
+            return NULL;
     }
 
     CookPointers(it8);
     it8 ->nTable = 0;
 
-       if (fclose(it8 ->FileStack[0]->Stream)!= 0) {
-                   cmsIT8Free(hIT8); 
-            return NULL; 
-       }
+    if (fclose(it8 ->FileStack[0]->Stream)!= 0) {
+            cmsIT8Free(hIT8);
+            return NULL;
+    }
 
     return hIT8;
 
@@ -2252,16 +2379,16 @@ cmsHANDLE  CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileN
 
 int CMSEXPORT cmsIT8EnumDataFormat(cmsHANDLE hIT8, char ***SampleNames)
 {
-       cmsIT8* it8 = (cmsIT8*) hIT8;
-       TABLE* t;
+    cmsIT8* it8 = (cmsIT8*) hIT8;
+    TABLE* t;
 
-       _cmsAssert(hIT8 != NULL);
+    _cmsAssert(hIT8 != NULL);
 
-       t = GetTable(it8);
+    t = GetTable(it8);
 
-       if (SampleNames) 
-               *SampleNames = t -> DataFormat;
-       return t -> nSamples;
+    if (SampleNames)
+        *SampleNames = t -> DataFormat;
+    return t -> nSamples;
 }
 
 
@@ -2272,10 +2399,10 @@ cmsUInt32Number CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyN
     cmsUInt32Number n;
     char **Props;
     TABLE* t;
-       
-       _cmsAssert(hIT8 != NULL);
 
-       t = GetTable(it8);
+    _cmsAssert(hIT8 != NULL);
+
+    t = GetTable(it8);
 
     // Pass#1 - count properties
 
@@ -2304,11 +2431,11 @@ cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cP
     cmsUInt32Number n;
     const char **Props;
     TABLE* t;
-       
-       _cmsAssert(hIT8 != NULL);
+
+    _cmsAssert(hIT8 != NULL);
 
 
-       t = GetTable(it8);
+    t = GetTable(it8);
 
     if(!IsAvailableOnList(t->HeaderList, cProp, NULL, &p)) {
         *SubpropertyNames = 0;
@@ -2347,7 +2474,7 @@ int LocatePatch(cmsIT8* it8, const char* cPatch)
     for (i=0; i < t-> nPatches; i++) {
 
         data = GetData(it8, i, t->SampleID);
-        
+
         if (data != NULL) {
 
                 if (cmsstrcasecmp(data, cPatch) == 0)
@@ -2355,7 +2482,7 @@ int LocatePatch(cmsIT8* it8, const char* cPatch)
                 }
         }
 
-        // SynError(it8, "Couldn't find patch '%s'\n", cPatch);                               
+        // SynError(it8, "Couldn't find patch '%s'\n", cPatch);
         return -1;
 }
 
@@ -2371,7 +2498,7 @@ int LocateEmptyPatch(cmsIT8* it8)
 
         data = GetData(it8, i, t->SampleID);
 
-        if (data == NULL) 
+        if (data == NULL)
             return i;
 
     }
@@ -2389,10 +2516,12 @@ int LocateSample(cmsIT8* it8, const char* cSample)
     for (i=0; i < t->nSamples; i++) {
 
         fld = GetDataFormat(it8, i);
-        if (cmsstrcasecmp(fld, cSample) == 0)
-            return i;
+        if (fld != NULL) {
+            if (cmsstrcasecmp(fld, cSample) == 0)
+                return i;
+        }
     }
-   
+
     return -1;
 
 }
@@ -2402,7 +2531,7 @@ int CMSEXPORT cmsIT8FindDataFormat(cmsHANDLE hIT8, const char* cSample)
 {
     cmsIT8* it8 = (cmsIT8*) hIT8;
 
-       _cmsAssert(hIT8 != NULL);
+    _cmsAssert(hIT8 != NULL);
 
     return LocateSample(it8, cSample);
 }
@@ -2413,7 +2542,7 @@ const char* CMSEXPORT cmsIT8GetDataRowCol(cmsHANDLE hIT8, int row, int col)
 {
     cmsIT8* it8 = (cmsIT8*) hIT8;
 
-       _cmsAssert(hIT8 != NULL);
+    _cmsAssert(hIT8 != NULL);
 
     return GetData(it8, row, col);
 }
@@ -2424,24 +2553,20 @@ cmsFloat64Number CMSEXPORT cmsIT8GetDataRowColDbl(cmsHANDLE hIT8, int row, int c
     const char* Buffer;
 
     Buffer = cmsIT8GetDataRowCol(hIT8, row, col);
-    
-    if (Buffer) {
 
-        return atof(Buffer);
-        
-    } else
-        return 0;
+    if (Buffer == NULL) return 0.0;
 
+    return ParseFloatNumber(Buffer);
 }
 
 
 cmsBool CMSEXPORT cmsIT8SetDataRowCol(cmsHANDLE hIT8, int row, int col, const char* Val)
 {
     cmsIT8* it8 = (cmsIT8*) hIT8;
-    
-       _cmsAssert(hIT8 != NULL);
 
-    return SetData(it8, row, col, Val);        
+    _cmsAssert(hIT8 != NULL);
+
+    return SetData(it8, row, col, Val);
 }
 
 
@@ -2450,29 +2575,29 @@ cmsBool CMSEXPORT cmsIT8SetDataRowColDbl(cmsHANDLE hIT8, int row, int col, cmsFl
     cmsIT8* it8 = (cmsIT8*) hIT8;
     char Buff[256];
 
-       _cmsAssert(hIT8 != NULL);
+    _cmsAssert(hIT8 != NULL);
 
-    sprintf(Buff, it8->DoubleFormatter, Val);
-    
-    return SetData(it8, row, col, Buff);        
+    snprintf(Buff, 255, it8->DoubleFormatter, Val);
+
+    return SetData(it8, row, col, Buff);
 }
 
 
 
-const char* CMSEXPORT cmsIT8GetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample)                        
+const char* CMSEXPORT cmsIT8GetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample)
 {
     cmsIT8* it8 = (cmsIT8*) hIT8;
     int iField, iSet;
 
-       _cmsAssert(hIT8 != NULL);
+    _cmsAssert(hIT8 != NULL);
 
     iField = LocateSample(it8, cSample);
-    if (iField < 0) {       
+    if (iField < 0) {
         return NULL;
     }
 
     iSet = LocatePatch(it8, cPatch);
-    if (iSet < 0) {          
+    if (iSet < 0) {
             return NULL;
     }
 
@@ -2485,15 +2610,8 @@ cmsFloat64Number CMSEXPORT cmsIT8GetDataDbl(cmsHANDLE  it8, const char* cPatch,
     const char* Buffer;
 
     Buffer = cmsIT8GetData(it8, cPatch, cSample);
-    
-    if (Buffer) {
 
-        return atof(Buffer);
-        
-    } else {
-        
-        return 0;
-    }
+    return ParseFloatNumber(Buffer);
 }
 
 
@@ -2503,14 +2621,14 @@ cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, const char*
     cmsIT8* it8 = (cmsIT8*) hIT8;
     int iField, iSet;
     TABLE* t;
-       
-       _cmsAssert(hIT8 != NULL);
 
-       t = GetTable(it8);
+    _cmsAssert(hIT8 != NULL);
+
+    t = GetTable(it8);
 
     iField = LocateSample(it8, cSample);
 
-    if (iField < 0) 
+    if (iField < 0)
         return FALSE;
 
     if (t-> nPatches == 0) {
@@ -2524,7 +2642,7 @@ cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, const char*
 
         iSet   = LocateEmptyPatch(it8);
         if (iSet < 0) {
-            return SynError(it8, "Couldn't add more patches '%s'\n", cPatch);                        
+            return SynError(it8, "Couldn't add more patches '%s'\n", cPatch);
         }
 
         iField = t -> SampleID;
@@ -2541,56 +2659,56 @@ cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, const char*
 
 
 cmsBool CMSEXPORT cmsIT8SetDataDbl(cmsHANDLE hIT8, const char* cPatch,
-                                                                  const char* cSample,
-                                                                  cmsFloat64Number Val)
+                                   const char* cSample,
+                                   cmsFloat64Number Val)
 {
-       cmsIT8* it8 = (cmsIT8*) hIT8;
-       char Buff[256];
+    cmsIT8* it8 = (cmsIT8*) hIT8;
+    char Buff[256];
 
-       _cmsAssert(hIT8 != NULL);
+    _cmsAssert(hIT8 != NULL);
 
-       snprintf(Buff, 255, it8->DoubleFormatter, Val);
-       return cmsIT8SetData(hIT8, cPatch, cSample, Buff);
+    snprintf(Buff, 255, it8->DoubleFormatter, Val);
+    return cmsIT8SetData(hIT8, cPatch, cSample, Buff);
 }
 
 // Buffer should get MAXSTR at least
 
 const char* CMSEXPORT cmsIT8GetPatchName(cmsHANDLE hIT8, int nPatch, char* buffer)
 {
-       cmsIT8* it8 = (cmsIT8*) hIT8;
-       TABLE* t;
-       char* Data;
+    cmsIT8* it8 = (cmsIT8*) hIT8;
+    TABLE* t;
+    char* Data;
 
-       _cmsAssert(hIT8 != NULL);
+    _cmsAssert(hIT8 != NULL);
 
-       t = GetTable(it8);
-       Data = GetData(it8, nPatch, t->SampleID);
+    t = GetTable(it8);
+    Data = GetData(it8, nPatch, t->SampleID);
 
-       if (!Data) return NULL;
-       if (!buffer) return Data;
+    if (!Data) return NULL;
+    if (!buffer) return Data;
 
-       strncpy(buffer, Data, MAXSTR-1);        
-       buffer[MAXSTR-1] = 0;
-       return buffer;
+    strncpy(buffer, Data, MAXSTR-1);
+    buffer[MAXSTR-1] = 0;
+    return buffer;
 }
 
 int CMSEXPORT cmsIT8GetPatchByName(cmsHANDLE hIT8, const char *cPatch)
 {
-       _cmsAssert(hIT8 != NULL);
+    _cmsAssert(hIT8 != NULL);
 
     return LocatePatch((cmsIT8*)hIT8, cPatch);
 }
 
 cmsUInt32Number CMSEXPORT cmsIT8TableCount(cmsHANDLE hIT8)
 {
-       cmsIT8* it8 = (cmsIT8*) hIT8;
+    cmsIT8* it8 = (cmsIT8*) hIT8;
 
-       _cmsAssert(hIT8 != NULL);
+    _cmsAssert(hIT8 != NULL);
 
-       return it8 ->TablesCount;
+    return it8 ->TablesCount;
 }
 
-// This handles the "LABEL" extension. 
+// This handles the "LABEL" extension.
 // Label, nTable, Type
 
 int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType)
@@ -2598,21 +2716,21 @@ int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char
     const char* cLabelFld;
     char Type[256], Label[256];
     int nTable;
-   
+
     _cmsAssert(hIT8 != NULL);
 
     if (cField != NULL && *cField == 0)
             cField = "LABEL";
 
-    if (cField == NULL) 
+    if (cField == NULL)
             cField = "LABEL";
 
-    cLabelFld = cmsIT8GetData(hIT8, cSet, cField); 
+    cLabelFld = cmsIT8GetData(hIT8, cSet, cField);
     if (!cLabelFld) return -1;
-    
+
     if (sscanf(cLabelFld, "%255s %d %255s", Label, &nTable, Type) != 3)
             return -1;
-    
+
     if (ExpectedType != NULL && *ExpectedType == 0)
         ExpectedType = NULL;
 
@@ -2621,23 +2739,23 @@ int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char
         if (cmsstrcasecmp(Type, ExpectedType) != 0) return -1;
     }
 
-    return cmsIT8SetTable(hIT8, nTable);    
+    return cmsIT8SetTable(hIT8, nTable);
 }
 
 
 cmsBool CMSEXPORT cmsIT8SetIndexColumn(cmsHANDLE hIT8, const char* cSample)
 {
-       cmsIT8* it8 = (cmsIT8*) hIT8;
-       int pos;
+    cmsIT8* it8 = (cmsIT8*) hIT8;
+    int pos;
 
-       _cmsAssert(hIT8 != NULL);
+    _cmsAssert(hIT8 != NULL);
 
-       pos = LocateSample(it8, cSample);
-       if(pos == -1)
-               return FALSE;
+    pos = LocateSample(it8, cSample);
+    if(pos == -1)
+        return FALSE;
 
-       it8->Tab[it8->nTable].SampleID = pos;
-       return TRUE;
+    it8->Tab[it8->nTable].SampleID = pos;
+    return TRUE;
 }
 
 
@@ -2650,6 +2768,8 @@ void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter)
     if (Formatter == NULL)
         strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
     else
-        strcpy(it8->DoubleFormatter, Formatter);
+        strncpy(it8->DoubleFormatter, Formatter, sizeof(it8->DoubleFormatter));
+
+    it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0;
 }