~ubuntu-branches/ubuntu/karmic/lcms/karmic-security

« back to all changes in this revision

Viewing changes to src/cmscgats.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2009-04-03 13:55:00 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20090403135500-psa3ox0my6u6a5cp
Tags: 1.18.dfsg-0ubuntu1
* New upstream release
* Remove 11_security_CVE-2009-0581_0723_0733.dpatch, security 
  issues fixed upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str);
48
48
LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val);
49
49
LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val);
 
50
LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char* cSubProp, const char *Val);
50
51
LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer);
51
52
 
52
53
LCMSAPI const char*     LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* cProp);
53
54
LCMSAPI double          LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp);
54
 
LCMSAPI int             LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, char ***PropertyNames);
 
55
LCMSAPI const char*     LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char *cSubProp);
 
56
LCMSAPI int             LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, const char ***PropertyNames);
 
57
LCMSAPI int             LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char*** SubpropertyNames);
55
58
 
56
59
// Datasets
57
60
 
97
100
// #define STRICT_CGATS  1
98
101
 
99
102
#define MAXID       128     // Max lenght of identifier
100
 
#define MAXSTR      255     // Max lenght of string
 
103
#define MAXSTR      1024     // Max lenght of string
101
104
#define MAXTABLES   255     // Max Number of tables in a single stream
102
105
#define MAXINCLUDE   20     // Max number of nested includes
103
106
 
108
111
 
109
112
#ifndef NON_WINDOWS
110
113
#include <io.h>
111
 
#define DIR_CHAR        '\\'
 
114
#define DIR_CHAR    '\\'
112
115
#else
113
 
#define DIR_CHAR        '/'
 
116
#define DIR_CHAR    '/'
114
117
#endif
115
118
 
116
119
// Symbols
134
137
        SEND_DATA,
135
138
        SEND_DATA_FORMAT,
136
139
        SKEYWORD,
 
140
        SDATA_FORMAT_ID,
137
141
        SINCLUDE
138
142
 
139
143
    } SYMBOL;
145
149
        WRITE_UNCOOKED,
146
150
        WRITE_STRINGIFY,            
147
151
        WRITE_HEXADECIMAL,
148
 
        WRITE_BINARY
 
152
        WRITE_BINARY,
 
153
        WRITE_PAIR
149
154
 
150
155
    } WRITEMODE;
151
156
 
155
160
 
156
161
        struct _KeyVal*  Next;
157
162
        char*            Keyword;       // Name of variable
 
163
        struct _KeyVal*  NextSubkey;    // If key is a dictionary, points to the next item
 
164
        char*            Subkey;        // If key is a dictionary, points to the subkey name
158
165
        char*            Value;         // Points to value
159
166
        WRITEMODE        WriteAs;       // How to write the value
160
167
 
199
206
typedef struct _FileContext {
200
207
        char           FileName[MAX_PATH];    // File name if being readed from file
201
208
        FILE*          Stream;                // File stream or NULL if holded in memory
202
 
        } FILECTX, *LPFILECTX;
 
209
    } FILECTX, *LPFILECTX;
203
210
 
204
211
// This struct hold all information about an openened
205
212
// IT8 handler. Only one dataset is allowed.
236
243
        char*          Source;                // Points to loc. being parsed
237
244
        int            lineno;                // line counter for error reporting
238
245
       
239
 
                LPFILECTX      FileStack[MAXINCLUDE]; // Stack of files being parsed
 
246
        LPFILECTX      FileStack[MAXINCLUDE]; // Stack of files being parsed
240
247
        int            IncludeSP;             // Include Stack Pointer
241
248
 
242
249
        char*          MemoryBlock;           // The stream if holded in memory
249
256
 
250
257
typedef struct {
251
258
 
252
 
                FILE* stream;   // For save-to-file behaviour
253
 
 
254
 
                LPBYTE Base;
255
 
                LPBYTE Ptr;             // For save-to-mem behaviour
256
 
                size_t Used;
257
 
                size_t Max;
258
 
 
259
 
        } SAVESTREAM, FAR* LPSAVESTREAM;
 
259
        FILE* stream;   // For save-to-file behaviour
 
260
 
 
261
        LPBYTE Base;
 
262
        LPBYTE Ptr;     // For save-to-mem behaviour
 
263
        size_t Used;
 
264
        size_t Max;
 
265
 
 
266
    } SAVESTREAM, FAR* LPSAVESTREAM;
260
267
 
261
268
 
262
269
// ------------------------------------------------------ IT8 parsing routines
277
284
        {".INCLUDE",            SINCLUDE},       
278
285
        {"BEGIN_DATA",          SBEGIN_DATA },
279
286
        {"BEGIN_DATA_FORMAT",   SBEGIN_DATA_FORMAT },
 
287
        {"DATA_FORMAT_IDENTIFIER", SDATA_FORMAT_ID},
280
288
        {"END_DATA",            SEND_DATA},
281
289
        {"END_DATA_FORMAT",     SEND_DATA_FORMAT},
282
290
        {"KEYWORD",             SKEYWORD}
283
 
        
284
291
        };
285
292
 
286
293
#define NUMKEYS (sizeof(TabKeys)/sizeof(KEYWORD))
287
294
 
288
295
// Predefined properties
289
296
 
290
 
static const char* PredefinedProperties[] = {
291
 
 
292
 
        "NUMBER_OF_FIELDS",    // Required - NUMBER OF FIELDS
293
 
        "NUMBER_OF_SETS",      // Required - NUMBER OF SETS
294
 
        "ORIGINATOR",          // Required - Identifies the specific system, organization or individual that created the data file.
295
 
        "FILE_DESCRIPTOR",     // Required - Describes the purpose or contents of the data file.
296
 
        "CREATED",             // Required - Indicates date of creation of the data file.
297
 
        "DESCRIPTOR",          // Required  - Describes the purpose or contents of the data file.
298
 
        "DIFFUSE_GEOMETRY",    // The diffuse geometry used. Allowed values are "sphere" or "opal".
299
 
        "MANUFACTURER",
300
 
        "MANUFACTURE",         // Some broken Fuji targets does store this value
301
 
        "PROD_DATE",           // Identifies year and month of production of the target in the form yyyy:mm.
302
 
        "SERIAL",              // Uniquely identifies individual physical target.
303
 
 
304
 
        "MATERIAL",            // Identifies the material on which the target was produced using a code
 
297
// A property
 
298
typedef struct {
 
299
        const char *id;
 
300
        WRITEMODE as;
 
301
    } PROPERTY;
 
302
 
 
303
static PROPERTY PredefinedProperties[] = {
 
304
 
 
305
        {"NUMBER_OF_FIELDS", WRITE_UNCOOKED},    // Required - NUMBER OF FIELDS
 
306
        {"NUMBER_OF_SETS",   WRITE_UNCOOKED},    // Required - NUMBER OF SETS
 
307
        {"ORIGINATOR",       WRITE_STRINGIFY},   // Required - Identifies the specific system, organization or individual that created the data file.
 
308
        {"FILE_DESCRIPTOR",  WRITE_STRINGIFY},   // Required - Describes the purpose or contents of the data file.
 
309
        {"CREATED",          WRITE_STRINGIFY},   // Required - Indicates date of creation of the data file.
 
310
        {"DESCRIPTOR",       WRITE_STRINGIFY},   // Required  - Describes the purpose or contents of the data file.
 
311
        {"DIFFUSE_GEOMETRY", WRITE_STRINGIFY},   // The diffuse geometry used. Allowed values are "sphere" or "opal".
 
312
        {"MANUFACTURER",     WRITE_STRINGIFY},
 
313
        {"MANUFACTURE",      WRITE_STRINGIFY},   // Some broken Fuji targets does store this value
 
314
        {"PROD_DATE",        WRITE_STRINGIFY},   // Identifies year and month of production of the target in the form yyyy:mm.
 
315
        {"SERIAL",           WRITE_STRINGIFY},   // Uniquely identifies individual physical target.
 
316
 
 
317
        {"MATERIAL",         WRITE_STRINGIFY},   // Identifies the material on which the target was produced using a code
305
318
                               // uniquely identifying th e material. This is intend ed to be used for IT8.7
306
319
                               // physical targets only (i.e . IT8.7/1 a nd IT8.7/2).
307
320
 
308
 
        "INSTRUMENTATION",     // Used to report the specific instrumentation used (manufacturer and
 
321
        {"INSTRUMENTATION",  WRITE_STRINGIFY},   // Used to report the specific instrumentation used (manufacturer and
309
322
                               // model number) to generate the data reported. This data will often
310
323
                               // provide more information about the particular data collected than an
311
324
                               // extensive list of specific details. This is particularly important for
312
325
                               // spectral data or data derived from spectrophotometry.
313
326
 
314
 
        "MEASUREMENT_SOURCE",  // Illumination used for spectral measurements. This data helps provide
 
327
        {"MEASUREMENT_SOURCE", WRITE_STRINGIFY}, // Illumination used for spectral measurements. This data helps provide
315
328
                               // a guide to the potential for issues of paper fluorescence, etc.
316
329
 
317
 
        "PRINT_CONDITIONS",    // Used to define the characteristics of the printed sheet being reported.
 
330
        {"PRINT_CONDITIONS", WRITE_STRINGIFY},   // Used to define the characteristics of the printed sheet being reported.
318
331
                               // Where standard conditions have been defined (e.g., SWOP at nominal)
319
332
                               // named conditions may suffice. Otherwise, detailed information is
320
333
                               // needed.
321
334
 
322
 
        "SAMPLE_BACKING",      // Identifies the backing material used behind the sample during
323
 
                               // measurement. Allowed values are �black�, �white�, or "na".
324
 
 
325
 
        "CHISQ_DOF"            // Degrees of freedom associated with the Chi squared statistic
 
335
        {"SAMPLE_BACKING",   WRITE_STRINGIFY},   // Identifies the backing material used behind the sample during
 
336
                               // measurement. Allowed values are �black�, �white�, or {"na".
 
337
 
 
338
        {"CHISQ_DOF",        WRITE_STRINGIFY},   // Degrees of freedom associated with the Chi squared statistic
 
339
 
 
340
//    new in recent specs:
 
341
        {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated 
 
342
                               // along with details of the geometry and the aperture size and shape. For example, 
 
343
                               // for transmission measurements it is important to identify 0/diffuse, diffuse/0, 
 
344
                               // opal or integrating sphere, etc. For reflection it is important to identify 0/45, 
 
345
                               // 45/0, sphere (specular included or excluded), etc.
 
346
 
 
347
       {"FILTER",            WRITE_STRINGIFY},   // Identifies the use of physical filter(s) during measurement. Typically used to 
 
348
                               // denote the use of filters such as none, D65, Red, Green or Blue.
 
349
 
 
350
       {"POLARIZATION",      WRITE_STRINGIFY},   // Identifies the use of a physical polarization filter during measurement. Allowed 
 
351
                               // values are {"yes�, �white�, �none� or �na�.
 
352
 
 
353
       {"WEIGHTING_FUNCTION", WRITE_PAIR},   // Indicates such functions as: the CIE standard observer functions used in the 
 
354
                               // calculation of various data parameters (2 degree and 10 degree), CIE standard 
 
355
                               // illuminant functions used in the calculation of various data parameters (e.g., D50,
 
356
                               // D65, etc.), density status response, etc. If used there shall be at least one 
 
357
                               // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute 
 
358
                               // in the set shall be {"name" and shall identify the particular parameter used.
 
359
                               // The second shall be {"value" and shall provide the value associated with that name. 
 
360
                               // For ASCII data, a string containing the Name and Value attribute pairs shall follow 
 
361
                               // the weighting function keyword. A semi-colon separates attribute pairs from each 
 
362
                               // other and within the attribute the name and value are separated by a comma.
 
363
 
 
364
       {"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name 
 
365
                               // of the calculation, parameter is the name of the parameter used in the calculation 
 
366
                               // and value is the value of the parameter.
 
367
 
 
368
       {"TARGET_TYPE",        WRITE_STRINGIFY},  // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc.
 
369
 
 
370
       {"COLORANT",           WRITE_STRINGIFY},  // Identifies the colorant(s) used in creating the target.
 
371
 
 
372
       {"TABLE_DESCRIPTOR",   WRITE_STRINGIFY},  // Describes the purpose or contents of a data table.
 
373
 
 
374
       {"TABLE_NAME",         WRITE_STRINGIFY}   // Provides a short name for a data table.
326
375
};
327
376
 
328
 
#define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(char *))
 
377
#define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(PROPERTY))
329
378
 
330
379
 
331
380
// Predefined sample types on dataset
332
381
static const char* PredefinedSampleID[] = {
 
382
        "SAMPLE_ID",      // Identifies sample that data represents
 
383
        "STRING",         // Identifies label, or other non-machine readable value. 
 
384
                          // Value must begin and end with a " symbol
333
385
 
334
386
        "CMYK_C",         // Cyan component of CMYK data expressed as a percentage
335
387
        "CMYK_M",         // Magenta component of CMYK data expressed as a percentage
357
409
        "LAB_B",          // b* component of Lab data
358
410
        "LAB_C",          // C*ab component of Lab data
359
411
        "LAB_H",          // hab component of Lab data
360
 
        "LAB_DE"          //  CIE dE
 
412
        "LAB_DE",         //  CIE dE
361
413
        "LAB_DE_94",      //  CIE dE using CIE 94
362
414
        "LAB_DE_CMC",     //  dE using CMC
363
415
        "LAB_DE_2000",    // CIE dE using CIE DE 2000
367
419
        "STDEV_Y",        // Standard deviation of Y (tristimulus data)
368
420
        "STDEV_Z",        // Standard deviation of Z (tristimulus data)
369
421
        "STDEV_L",        // Standard deviation of L*
370
 
        "STDEV_A"         // Standard deviation of a*
 
422
        "STDEV_A",        // Standard deviation of a*
371
423
        "STDEV_B",        // Standard deviation of b*
372
424
        "STDEV_DE",       // Standard deviation of CIE dE
373
425
        "CHI_SQD_PAR"};   // The average of the standard deviations of L*, a* and b*. It is
376
428
 
377
429
#define NUMPREDEFINEDSAMPLEID (sizeof(PredefinedSampleID)/sizeof(char *))
378
430
 
379
 
//Forward declaration of some internal functions                
380
 
static void* AllocChunk(LPIT8 it8, size_t size);
 
431
//Forward declaration of some internal functions        
 
432
static
 
433
void* AllocChunk(LPIT8 it8, size_t size);
381
434
 
382
435
// Checks if c is a separator
383
436
static
412
465
static
413
466
LCMSBOOL isabsolutepath(const char *path)
414
467
{
415
 
        if(path == NULL)
416
 
                return FALSE;
417
 
        
 
468
    if(path == NULL)
 
469
        return FALSE;
 
470
    
418
471
    if(path[0] == DIR_CHAR)
419
 
                return TRUE;
 
472
        return TRUE;
420
473
 
421
 
#ifndef NON_WINDOWS
422
 
        if(isalpha(path[0]) && path[1] == ':')
423
 
                return TRUE;
 
474
#ifndef NON_WINDOWS
 
475
    if(isalpha(path[0]) && path[1] == ':')
 
476
        return TRUE;
424
477
#endif
425
 
        return FALSE;
 
478
    return FALSE;
426
479
}
427
480
 
428
481
// Makes a file path based on a given reference path
432
485
static 
433
486
LCMSBOOL _cmsMakePath(const char *relPath, const char *basePath, char *buffer)
434
487
{
435
 
        if (!isabsolutepath(relPath)) {
 
488
    if (!isabsolutepath(relPath)) {
436
489
 
437
 
                char *tail;
438
 
                
 
490
        char *tail;
 
491
        
439
492
        strncpy(buffer, basePath, MAX_PATH-1);
440
 
                tail = strrchr(buffer, DIR_CHAR);
441
 
                if (tail != NULL) {
 
493
        tail = strrchr(buffer, DIR_CHAR);
 
494
        if (tail != NULL) {
442
495
 
443
 
                        size_t len = tail - buffer;
444
 
                        strncpy(tail + 1, relPath, MAX_PATH - len -1);
445
 
                        //      TODO: if combined path is longer than MAX_PATH, this should return FALSE!
446
 
                        return TRUE;
447
 
                }
448
 
        }
449
 
        strncpy(buffer, relPath, MAX_PATH - 1);
450
 
        return TRUE;
 
496
            size_t len = tail - buffer;
 
497
            strncpy(tail + 1, relPath, MAX_PATH - len -1);
 
498
            //  TODO: if combined path is longer than MAX_PATH, this should return FALSE!
 
499
            return TRUE;
 
500
        }
 
501
    }
 
502
    strncpy(buffer, relPath, MAX_PATH - 1);
 
503
        buffer[MAX_PATH-1] = 0;
 
504
    return TRUE;
451
505
}
452
506
 
453
507
 
840
894
 
841
895
                LPFILECTX FileNest;
842
896
 
843
 
                                if(it8 -> IncludeSP >= (MAXINCLUDE-1))
844
 
                                {
845
 
                                        SynError(it8, "Too many recursion levels");
846
 
                                        return;
847
 
                                }
 
897
                if(it8 -> IncludeSP >= (MAXINCLUDE-1))
 
898
                {
 
899
                    SynError(it8, "Too many recursion levels");
 
900
                    return;
 
901
                }
848
902
 
849
903
                InSymbol(it8);
850
904
                if (!Check(it8, SSTRING, "Filename expected")) return;
851
905
 
852
 
                                FileNest = it8 -> FileStack[it8 -> IncludeSP + 1];
853
 
                                if(FileNest == NULL)
854
 
                                {
855
 
                                        FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX));
856
 
                                        //if(FileNest == NULL)
857
 
                                                //      TODO: how to manage out-of-memory conditions?
858
 
                                }
 
906
                FileNest = it8 -> FileStack[it8 -> IncludeSP + 1];
 
907
                if(FileNest == NULL)
 
908
                {
 
909
                    FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX));
 
910
                    //if(FileNest == NULL)
 
911
                        //  TODO: how to manage out-of-memory conditions?
 
912
                }
859
913
 
860
 
                                if(_cmsMakePath(it8->str, it8->FileStack[it8->IncludeSP]->FileName, FileNest->FileName) == FALSE)
861
 
                                {
862
 
                                        SynError(it8, "File path too long");
863
 
                                        return;
864
 
                                }
 
914
                if(_cmsMakePath(it8->str, it8->FileStack[it8->IncludeSP]->FileName, FileNest->FileName) == FALSE)
 
915
                {
 
916
                    SynError(it8, "File path too long");
 
917
                    return;
 
918
                }
865
919
 
866
920
                FileNest->Stream = fopen(FileNest->FileName, "rt");
867
921
                if (FileNest->Stream == NULL) {
869
923
                        SynError(it8, "File %s not found", FileNest->FileName);
870
924
                        return;
871
925
                }
872
 
                                it8->IncludeSP++;
 
926
                it8->IncludeSP++;
873
927
 
874
928
                it8 ->ch = ' ';
875
929
                InSymbol(it8);    
914
968
{
915
969
    switch (it8->sy) {
916
970
 
917
 
    case SIDENT:  strncpy(Buffer, it8->id, max); break;
 
971
    case SIDENT:  strncpy(Buffer, it8->id, max); 
 
972
                  Buffer[max-1]=0;
 
973
                  break;
918
974
    case SINUM:   snprintf(Buffer, max, "%d", it8 -> inum); break;
919
975
    case SDNUM:   snprintf(Buffer, max, it8->DoubleFormatter, it8 -> dnum); break;
920
 
    case SSTRING: strncpy(Buffer, it8->str, max); break;
 
976
    case SSTRING: strncpy(Buffer, it8->str, max); 
 
977
                  Buffer[max-1] = 0;
 
978
                  break;
921
979
 
922
980
 
923
981
    default:
1053
1111
// Searches through linked list
1054
1112
 
1055
1113
static
1056
 
LCMSBOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, LPKEYVALUE* LastPtr)
 
1114
LCMSBOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, const char* Subkey, LPKEYVALUE* LastPtr)
1057
1115
{
 
1116
    if (LastPtr) *LastPtr = p;
1058
1117
 
1059
1118
    for (;  p != NULL; p = p->Next) {
1060
1119
 
1063
1122
        if (*Key != '#') { // Comments are ignored
1064
1123
 
1065
1124
            if (stricmp(Key, p->Keyword) == 0)
1066
 
                    return TRUE;
1067
 
        }
 
1125
                    break;
 
1126
        }
 
1127
        }
 
1128
 
 
1129
    if (p == NULL)
 
1130
        return FALSE;
 
1131
 
 
1132
    if (Subkey == 0)
 
1133
        return TRUE;
 
1134
 
 
1135
    for (; p != NULL; p = p->NextSubkey) {
 
1136
 
 
1137
        if (LastPtr) *LastPtr = p;
 
1138
 
 
1139
        if (stricmp(Subkey, p->Subkey) == 0)
 
1140
            return TRUE;
1068
1141
    }
1069
1142
 
1070
1143
    return FALSE;
1074
1147
 
1075
1148
// Add a property into a linked list
1076
1149
static
1077
 
LCMSBOOL AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char* xValue, WRITEMODE WriteAs)
 
1150
LPKEYVALUE AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char *Subkey, const char* xValue, WRITEMODE WriteAs)
1078
1151
{
1079
1152
    LPKEYVALUE p;
1080
 
    LPKEYVALUE last;
1081
 
 
1082
1153
 
1083
1154
    // Check if property is already in list (this is an error)
1084
1155
 
1085
 
    if (IsAvailableOnList(*Head, Key, &last)) {
1086
 
 
1087
 
                        // This may work for editing properties
1088
 
 
1089
 
                         last->Value   = AllocString(it8, xValue);
1090
 
                         last->WriteAs = WriteAs;
1091
 
                         return TRUE;                                               
 
1156
    if (IsAvailableOnList(*Head, Key, Subkey, &p)) {
 
1157
 
 
1158
            // This may work for editing properties
 
1159
 
 
1160
        //     return SynError(it8, "duplicate key <%s>", Key);                                        
1092
1161
    }
 
1162
    else {
 
1163
        LPKEYVALUE last = p;
1093
1164
 
1094
1165
    // Allocate the container
1095
1166
    p = (LPKEYVALUE) AllocChunk(it8, sizeof(KEYVALUE));
1096
1167
    if (p == NULL)
1097
1168
    {
1098
 
        return SynError(it8, "AddToList: out of memory");        
 
1169
            SynError(it8, "AddToList: out of memory");
 
1170
            return NULL;
1099
1171
    }
1100
1172
 
1101
1173
    // Store name and value
1102
1174
    p->Keyword = AllocString(it8, Key);
1103
 
 
 
1175
        p->Subkey = (Subkey == NULL) ? NULL : AllocString(it8, Subkey);
 
1176
 
 
1177
        // Keep the container in our list
 
1178
        if (*Head == NULL)
 
1179
            *Head = p;
 
1180
        else
 
1181
        {
 
1182
            if(Subkey != 0 && last != 0) {
 
1183
                last->NextSubkey = p;
 
1184
 
 
1185
                // If Subkey is not null, then last is the last property with the same key,
 
1186
                // but not necessarily is the last property in the list, so we need to move
 
1187
                // to the actual list end
 
1188
                while(last->Next != 0) 
 
1189
                    last = last->Next;
 
1190
    }
 
1191
            last->Next = p;
 
1192
    }
 
1193
 
 
1194
    p->Next    = NULL;
 
1195
        p->NextSubkey = NULL;
 
1196
    }
 
1197
 
 
1198
    p->WriteAs = WriteAs;
1104
1199
    if (xValue != NULL) {
1105
1200
 
1106
1201
        p->Value   = AllocString(it8, xValue);
1109
1204
        p->Value   = NULL;
1110
1205
    }
1111
1206
 
1112
 
    p->Next    = NULL;
1113
 
    p->WriteAs = WriteAs;
1114
 
 
1115
 
    // Keep the container in our list
1116
 
    if (*Head == NULL)
1117
 
        *Head = p;
1118
 
    else
1119
 
        last->Next = p;
1120
 
 
1121
 
    return TRUE;
1122
 
}
1123
 
 
1124
 
static
1125
 
LCMSBOOL AddAvailableProperty(LPIT8 it8, const char* Key)
1126
 
{
1127
 
        return AddToList(it8, &it8->ValidKeywords, Key, NULL, WRITE_UNCOOKED);
1128
 
}
1129
 
 
1130
 
 
1131
 
static
1132
 
LCMSBOOL AddAvailableSampleID(LPIT8 it8, const char* Key)
1133
 
{
1134
 
        return AddToList(it8, &it8->ValidSampleID, Key, NULL, WRITE_UNCOOKED);
 
1207
    return p;
 
1208
}
 
1209
 
 
1210
static
 
1211
LPKEYVALUE AddAvailableProperty(LPIT8 it8, const char* Key, WRITEMODE as)
 
1212
{
 
1213
        return AddToList(it8, &it8->ValidKeywords, Key, NULL, NULL, as);
 
1214
}
 
1215
 
 
1216
 
 
1217
static
 
1218
LPKEYVALUE AddAvailableSampleID(LPIT8 it8, const char* Key)
 
1219
{
 
1220
        return AddToList(it8, &it8->ValidSampleID, Key, NULL, NULL, WRITE_UNCOOKED);
1135
1221
}
1136
1222
 
1137
1223
 
1179
1265
    LPIT8 it8;
1180
1266
    int i;
1181
1267
 
1182
 
    it8 = (LPIT8) _cmsMalloc(sizeof(IT8));
 
1268
    it8 = (LPIT8) malloc(sizeof(IT8));
1183
1269
    if (it8 == NULL) return NULL;
1184
1270
 
1185
1271
    ZeroMemory(it8, sizeof(IT8));
1204
1290
    it8 -> inum = 0;
1205
1291
    it8 -> dnum = 0.0;
1206
1292
 
1207
 
        it8->FileStack[0] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX));
 
1293
    it8->FileStack[0] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX));
1208
1294
    it8->IncludeSP   = 0;
1209
1295
    it8 -> lineno = 1;
1210
1296
 
1214
1300
    // Initialize predefined properties & data
1215
1301
    
1216
1302
    for (i=0; i < NUMPREDEFINEDPROPS; i++)
1217
 
            AddAvailableProperty(it8, PredefinedProperties[i]);
 
1303
            AddAvailableProperty(it8, PredefinedProperties[i].id, PredefinedProperties[i].as);
1218
1304
 
1219
1305
    for (i=0; i < NUMPREDEFINEDSAMPLEID; i++)
1220
1306
            AddAvailableSampleID(it8, PredefinedSampleID[i]);
1237
1323
        LPIT8 it8 = (LPIT8) hIT8;
1238
1324
 
1239
1325
        strncpy(it8 ->SheetType, Type, MAXSTR-1);
 
1326
        it8 ->SheetType[MAXSTR-1] = 0;
1240
1327
        return TRUE;
1241
1328
}
1242
1329
 
1247
1334
    if (!Val) return FALSE;
1248
1335
    if (!*Val) return FALSE;
1249
1336
 
1250
 
    return AddToList(it8, &GetTable(it8)->HeaderList, "# ", Val, WRITE_UNCOOKED);
 
1337
    return AddToList(it8, &GetTable(it8)->HeaderList, "# ", NULL, Val, WRITE_UNCOOKED) != NULL;
1251
1338
}
1252
1339
 
1253
1340
 
1260
1347
    if (!Val) return FALSE;
1261
1348
    if (!*Val) return FALSE;
1262
1349
 
1263
 
    return AddToList(it8, &GetTable(it8)->HeaderList, Key, Val, WRITE_STRINGIFY);
 
1350
    return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Val, WRITE_STRINGIFY) != NULL;
1264
1351
}
1265
1352
 
1266
1353
 
1271
1358
   
1272
1359
    sprintf(Buffer, it8->DoubleFormatter, Val);
1273
1360
 
1274
 
    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, Buffer, WRITE_UNCOOKED);    
 
1361
    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL;    
1275
1362
}
1276
1363
 
1277
1364
LCMSBOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val)
1281
1368
   
1282
1369
    sprintf(Buffer, "%d", Val);
1283
1370
 
1284
 
    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, Buffer, WRITE_HEXADECIMAL);    
 
1371
    return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL;    
1285
1372
}
1286
1373
 
1287
1374
LCMSBOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer)
1288
1375
{
1289
1376
    LPIT8 it8 = (LPIT8) hIT8;    
1290
1377
    
1291
 
    return AddToList(it8, &GetTable(it8)->HeaderList, Key, Buffer, WRITE_UNCOOKED);
1292
 
}
1293
 
 
 
1378
    return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Buffer, WRITE_UNCOOKED) != NULL;
 
1379
}
 
1380
 
 
1381
LCMSBOOL LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer)
 
1382
{
 
1383
    LPIT8 it8 = (LPIT8) hIT8;
 
1384
 
 
1385
    return AddToList(it8, &GetTable(it8)->HeaderList, Key, SubKey, Buffer, WRITE_PAIR) != NULL;
 
1386
}
1294
1387
 
1295
1388
// Gets a property
1296
1389
const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* Key)
1298
1391
    LPIT8 it8 = (LPIT8) hIT8;
1299
1392
    LPKEYVALUE p;
1300
1393
 
1301
 
    if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, &p))
 
1394
    if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, NULL, &p))
1302
1395
    {
1303
1396
        return p -> Value;
1304
1397
    }
1314
1407
    else return 0.0;
1315
1408
}
1316
1409
 
 
1410
const char* LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char *SubKey)
 
1411
{
 
1412
    LPIT8 it8 = (LPIT8) hIT8;
 
1413
    LPKEYVALUE p;
 
1414
 
 
1415
    if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, SubKey, &p))
 
1416
    {
 
1417
        return p -> Value;
 
1418
    }
 
1419
    return NULL;
 
1420
}
 
1421
 
1317
1422
// ----------------------------------------------------------------- Datasets
1318
1423
 
1319
1424
 
1356
1461
{
1357
1462
    LPTABLE t = GetTable(it8);
1358
1463
 
 
1464
#ifdef  STRICT_CGATS
 
1465
    if (!IsAvailableOnList(it8-> ValidSampleID, label, NULL, NULL)) {
 
1466
        SynError(it8, "Invalid data format '%s'.", label);
 
1467
        return FALSE;
 
1468
    }
 
1469
#endif
 
1470
 
1359
1471
    if (!t->DataFormat)
1360
1472
        AllocateDataFormat(it8);
1361
1473
 
1447
1559
static
1448
1560
void WriteStr(LPSAVESTREAM f, const char *str)
1449
1561
{
1450
 
        
1451
 
        size_t len;
 
1562
    
 
1563
    size_t len;
1452
1564
 
1453
 
        if (str == NULL) 
1454
 
                str = " ";
1455
 
        
1456
 
        // Lenghth to write
1457
 
        len = strlen(str);
 
1565
    if (str == NULL) 
 
1566
        str = " ";
 
1567
    
 
1568
    // Lenghth to write
 
1569
    len = strlen(str);
1458
1570
    f ->Used += len;
1459
 
        
1460
 
 
1461
 
        if (f ->stream) {       // Should I write it to a file?
1462
 
 
1463
 
                fwrite(str, 1, len, f->stream);
1464
 
                
1465
 
        }
1466
 
        else {  // Or to a memory block?
1467
 
                                                
1468
 
 
1469
 
                if (f ->Base) {   // Am I just counting the bytes?
1470
 
                        
1471
 
                        if (f ->Used > f ->Max) {
1472
 
 
1473
 
                                cmsSignalError(LCMS_ERRC_ABORTED, "Write to memory overflows in CGATS parser");
1474
 
                                return;
1475
 
                        }
1476
 
                        
1477
 
                        CopyMemory(f ->Ptr, str, len);
1478
 
                        f->Ptr += len;
1479
 
                        
1480
 
                }
1481
 
                                                
1482
 
        }       
 
1571
    
 
1572
 
 
1573
    if (f ->stream) {   // Should I write it to a file?
 
1574
 
 
1575
        fwrite(str, 1, len, f->stream);
 
1576
        
 
1577
    }
 
1578
    else {  // Or to a memory block?
 
1579
                        
 
1580
 
 
1581
        if (f ->Base) {   // Am I just counting the bytes?
 
1582
            
 
1583
            if (f ->Used > f ->Max) {
 
1584
 
 
1585
                cmsSignalError(LCMS_ERRC_ABORTED, "Write to memory overflows in CGATS parser");
 
1586
                return;
 
1587
            }
 
1588
            
 
1589
            CopyMemory(f ->Ptr, str, len);
 
1590
            f->Ptr += len;
 
1591
            
 
1592
        }
 
1593
                        
 
1594
    }   
1483
1595
}
1484
1596
 
1485
1597
 
1517
1629
            for (Pt = p ->Value; *Pt; Pt++) {
1518
1630
 
1519
1631
 
1520
 
                                Writef(fp, "%c", *Pt);                
 
1632
                Writef(fp, "%c", *Pt);                
1521
1633
 
1522
1634
                if (*Pt == '\n') {
1523
1635
                    WriteStr(fp, "# ");
1529
1641
        }
1530
1642
 
1531
1643
 
1532
 
        if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL)) {
 
1644
        if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL, NULL)) {
1533
1645
 
1534
1646
#ifdef STRICT_CGATS
1535
1647
            WriteStr(fp, "KEYWORD\t\"");
1537
1649
            WriteStr(fp, "\"\n");
1538
1650
#endif
1539
1651
 
1540
 
            AddAvailableProperty(it8, p->Keyword);
 
1652
            AddAvailableProperty(it8, p->Keyword, WRITE_UNCOOKED);
1541
1653
 
1542
1654
        }
1543
1655
 
1562
1674
                    Writef(fp, "\t0x%B", atoi(p ->Value));
1563
1675
                    break;
1564
1676
 
 
1677
            case WRITE_PAIR:
 
1678
                    Writef(fp, "\t\"%s,%s\"", p->Subkey, p->Value);
 
1679
                    break;
 
1680
 
1565
1681
            default: SynError(it8, "Unknown write mode %d", p ->WriteAs);
1566
1682
                     return;
1567
1683
            }
1642
1758
// Saves whole file
1643
1759
LCMSBOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE hIT8, const char* cFileName)
1644
1760
{
1645
 
    SAVESTREAM sd;      
 
1761
    SAVESTREAM sd;  
1646
1762
    int i;
1647
1763
    LPIT8 it8 = (LPIT8) hIT8;
1648
1764
 
1649
 
        ZeroMemory(&sd, sizeof(SAVESTREAM));
 
1765
    ZeroMemory(&sd, sizeof(SAVESTREAM));
1650
1766
 
1651
1767
    sd.stream = fopen(cFileName, "wt");
1652
1768
    if (!sd.stream) return FALSE;
1661
1777
            WriteData(&sd, it8);
1662
1778
    }
1663
1779
    
1664
 
        fclose(sd.stream);
 
1780
    fclose(sd.stream);
1665
1781
 
1666
1782
    return TRUE;
1667
1783
}
1670
1786
// Saves to memory
1671
1787
LCMSBOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded)
1672
1788
{
1673
 
    SAVESTREAM sd;      
 
1789
    SAVESTREAM sd;  
1674
1790
    int i;
1675
1791
    LPIT8 it8 = (LPIT8) hIT8;
1676
1792
 
1677
 
        ZeroMemory(&sd, sizeof(SAVESTREAM));
 
1793
    ZeroMemory(&sd, sizeof(SAVESTREAM));
1678
1794
 
1679
1795
    sd.stream = NULL;
1680
 
        sd.Base   = (LPBYTE) MemPtr;
1681
 
        sd.Ptr    = sd.Base;
1682
 
 
1683
 
        sd.Used = 0;
1684
 
 
1685
 
        if (sd.Base) 
1686
 
                sd.Max  = *BytesNeeded;         // Write to memory?
1687
 
        else 
1688
 
                sd.Max  = 0;                            // Just counting the needed bytes
 
1796
    sd.Base   = (LPBYTE) MemPtr;
 
1797
    sd.Ptr    = sd.Base;
 
1798
 
 
1799
    sd.Used = 0;
 
1800
 
 
1801
    if (sd.Base) 
 
1802
        sd.Max  = *BytesNeeded;     // Write to memory?
 
1803
    else 
 
1804
        sd.Max  = 0;                // Just counting the needed bytes
1689
1805
   
1690
1806
    WriteStr(&sd, it8->SheetType);
1691
1807
    WriteStr(&sd, "\n");
1697
1813
            WriteData(&sd, it8);
1698
1814
    }
1699
1815
    
1700
 
        sd.Used++;      // The \0 at the very end
1701
 
 
1702
 
        if (sd.Base)
1703
 
                sd.Ptr = 0;
1704
 
 
1705
 
        *BytesNeeded = sd.Used;
 
1816
    sd.Used++;  // The \0 at the very end
 
1817
 
 
1818
    if (sd.Base)
 
1819
        sd.Ptr = 0;
 
1820
 
 
1821
    *BytesNeeded = sd.Used;
1706
1822
 
1707
1823
    return TRUE;
1708
1824
}
1756
1872
{
1757
1873
    int  iField = 0;
1758
1874
    int  iSet   = 0;
1759
 
    char Buffer[256];
 
1875
    char Buffer[MAXSTR];
1760
1876
    LPTABLE t = GetTable(it8);
1761
1877
 
1762
1878
    InSymbol(it8);   // Eats "BEGIN_DATA"
1808
1924
{
1809
1925
    char VarName[MAXID];
1810
1926
    char Buffer[MAXSTR];
 
1927
    LPKEYVALUE Key;
1811
1928
 
1812
1929
        while (it8->sy != SEOF &&
1813
1930
               it8->sy != SSYNERROR &&
1820
1937
        case SKEYWORD:
1821
1938
                InSymbol(it8);
1822
1939
                if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE;                
1823
 
                if (!AddAvailableProperty(it8, Buffer)) return FALSE;
 
1940
                if (!AddAvailableProperty(it8, Buffer, WRITE_UNCOOKED)) return FALSE;
 
1941
                InSymbol(it8);
 
1942
                break;
 
1943
 
 
1944
 
 
1945
        case SDATA_FORMAT_ID:
 
1946
                InSymbol(it8);
 
1947
                if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE;                
 
1948
                if (!AddAvailableSampleID(it8, Buffer)) return FALSE;
1824
1949
                InSymbol(it8);
1825
1950
                break;
1826
1951
 
1827
1952
 
1828
1953
        case SIDENT:
1829
1954
                strncpy(VarName, it8->id, MAXID-1);
 
1955
                VarName[MAXID-1] = 0;
1830
1956
                
1831
 
                if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL)) {
 
1957
                if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) {
1832
1958
 
1833
1959
#ifdef STRICT_CGATS               
1834
1960
                 return SynError(it8, "Undefined keyword '%s'", VarName);
1835
1961
#else
1836
 
                if (!AddAvailableProperty(it8, VarName)) return FALSE;
 
1962
                    Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED);
 
1963
                    if (Key == NULL) return FALSE;
1837
1964
#endif
1838
1965
                }
1839
1966
 
1840
1967
                InSymbol(it8);
1841
1968
                if (!GetVal(it8, Buffer, MAXSTR-1, "Property data expected")) return FALSE;
1842
1969
 
1843
 
                                
1844
 
                AddToList(it8, &GetTable(it8)->HeaderList, VarName, Buffer, 
1845
 
                                                                (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
1846
 
                                
 
1970
                if(Key->WriteAs != WRITE_PAIR) {
 
1971
                    AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer, 
 
1972
                                (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
 
1973
                }
 
1974
                else {
 
1975
                    const char *Subkey;
 
1976
                    char *Nextkey;
 
1977
                    if (it8->sy != SSTRING)
 
1978
                        return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName);
 
1979
 
 
1980
                    // chop the string as a list of "subkey, value" pairs, using ';' as a separator
 
1981
                    for(Subkey = Buffer; Subkey != NULL; Subkey = Nextkey)
 
1982
                    {
 
1983
                        char *Value, *temp;
 
1984
 
 
1985
                        //  identify token pair boundary
 
1986
                        Nextkey = (char*) strchr(Subkey, ';');
 
1987
                        if(Nextkey)
 
1988
                            *Nextkey++ = '\0';
 
1989
 
 
1990
                        // for each pair, split the subkey and the value
 
1991
                        Value = (char*) strrchr(Subkey, ',');
 
1992
                        if(Value == NULL)
 
1993
                            return SynError(it8, "Invalid value for property '%s'.", VarName);
 
1994
 
 
1995
                        // gobble the spaces before the coma, and the coma itself
 
1996
                        temp = Value++;
 
1997
                        do *temp-- = '\0'; while(temp >= Subkey && *temp == ' ');
 
1998
 
 
1999
                        // gobble any space at the right
 
2000
                        temp = Value + strlen(Value) - 1;
 
2001
                        while(*temp == ' ') *temp-- = '\0'; 
 
2002
 
 
2003
                        // trim the strings from the left
 
2004
                        Subkey += strspn(Subkey, " ");
 
2005
                        Value += strspn(Value, " ");
 
2006
 
 
2007
                        if(Subkey[0] == 0 || Value[0] == 0)
 
2008
                            return SynError(it8, "Invalid value for property '%s'.", VarName);
 
2009
                        AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR);
 
2010
                    }
 
2011
                }
 
2012
                
1847
2013
                InSymbol(it8);
1848
2014
                break;
1849
2015
 
1863
2029
 
1864
2030
 
1865
2031
static
1866
 
LCMSBOOL ParseIT8(LPIT8 it8)
 
2032
LCMSBOOL ParseIT8(LPIT8 it8, LCMSBOOL nosheet)
1867
2033
{
1868
 
    char* SheetTypePtr;
 
2034
    char* SheetTypePtr = it8 ->SheetType;
 
2035
 
 
2036
    if (nosheet == 0) {
1869
2037
 
1870
2038
    // First line is a very special case.
1871
2039
 
1872
2040
    while (isseparator(it8->ch))
1873
2041
            NextCh(it8);
1874
2042
    
1875
 
    SheetTypePtr = it8 ->SheetType;
1876
 
 
1877
2043
    while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != -1) {
1878
2044
 
1879
2045
        *SheetTypePtr++= (char) it8 ->ch;
1880
2046
        NextCh(it8);
1881
2047
    }
 
2048
    }
1882
2049
 
1883
2050
    *SheetTypePtr = 0;
1884
2051
    InSymbol(it8);
1960
2127
                    char Buffer[256];
1961
2128
                
1962
2129
                    strncpy(Buffer, Data, 255);
 
2130
                    Buffer[255] = 0;
1963
2131
                                       
1964
2132
                    if (strlen(Buffer) <= strlen(Data))
1965
2133
                        strcpy(Data, Buffer);
1992
2160
                                    LPTABLE Table = it8 ->Tab + k;
1993
2161
                                    LPKEYVALUE p;
1994
2162
 
1995
 
                                    if (IsAvailableOnList(Table->HeaderList, Label, &p)) {
 
2163
                                    if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) {
1996
2164
 
1997
2165
                                        // Available, keep type and table
1998
2166
                                        char Buffer[256];
2024
2192
// that should be something like some printable characters plus a \n
2025
2193
 
2026
2194
static
2027
 
LCMSBOOL IsMyBlock(LPBYTE Buffer, size_t n)
 
2195
int IsMyBlock(LPBYTE Buffer, size_t n)
2028
2196
{
 
2197
    int cols = 1, space = 0, quot = 0;
2029
2198
    size_t i;
2030
2199
 
2031
2200
    if (n < 10) return FALSE;   // Too small
2035
2204
 
2036
2205
    for (i = 1; i < n; i++) {
2037
2206
 
2038
 
        if (Buffer[i] == '\n' || Buffer[i] == '\r' || Buffer[i] == '\t') return TRUE;
2039
 
        if (Buffer[i] < 32) return FALSE;
2040
 
        if (Buffer[i] > 127) return FALSE;
 
2207
        switch(Buffer[i])
 
2208
        {
 
2209
        case '\n':
 
2210
        case '\r':
 
2211
            return quot == 1 || cols > 2 ? 0 : cols;
 
2212
        case '\t':
 
2213
        case ' ':
 
2214
            if(!quot && !space)
 
2215
                space = 1;
 
2216
            break;
 
2217
        case '\"':
 
2218
            quot = !quot;
 
2219
            break;
 
2220
        default:
 
2221
            if (Buffer[i] < 32) return 0;
 
2222
            if (Buffer[i] > 127) return 0;
 
2223
            cols += space;
 
2224
            space = 0;
 
2225
            break;
 
2226
        }
2041
2227
    }
2042
2228
 
2043
2229
    return FALSE;
2046
2232
 
2047
2233
 
2048
2234
static
2049
 
LCMSBOOL IsMyFile(const char* FileName)
 
2235
int IsMyFile(const char* FileName)
2050
2236
{
2051
2237
   FILE *fp;
2052
2238
   size_t Size;
2074
2260
    LCMSHANDLE hIT8; 
2075
2261
    LPIT8  it8;
2076
2262
 
2077
 
    if (!IsMyBlock((LPBYTE) Ptr, len)) return NULL;
 
2263
    int type = IsMyBlock((LPBYTE) Ptr, len);
 
2264
    if (type == 0) return NULL;
2078
2265
    
2079
2266
    hIT8 = cmsIT8Alloc();
2080
2267
    if (!hIT8) return NULL;
2088
2275
    strncpy(it8->FileStack[0]->FileName, "", MAX_PATH-1);
2089
2276
    it8-> Source = it8 -> MemoryBlock;
2090
2277
 
2091
 
    if (!ParseIT8(it8)) { 
 
2278
    if (!ParseIT8(it8, type-1)) { 
2092
2279
       
2093
2280
        cmsIT8Free(hIT8); 
2094
2281
        return FALSE; 
2112
2299
     LCMSHANDLE hIT8; 
2113
2300
     LPIT8  it8;
2114
2301
 
2115
 
     if (!IsMyFile(cFileName)) return NULL;
 
2302
     int type = IsMyFile(cFileName);
 
2303
     if (type == 0) return NULL;
2116
2304
 
2117
2305
     hIT8 = cmsIT8Alloc();
2118
2306
     it8 = (LPIT8) hIT8;   
2128
2316
     
2129
2317
 
2130
2318
    strncpy(it8->FileStack[0]->FileName, cFileName, MAX_PATH-1);    
 
2319
    it8->FileStack[0]->FileName[MAX_PATH-1] = 0;
2131
2320
 
2132
 
    if (!ParseIT8(it8)) { 
 
2321
    if (!ParseIT8(it8, type-1)) { 
2133
2322
    
2134
2323
            fclose(it8 ->FileStack[0]->Stream);
2135
2324
            cmsIT8Free(hIT8); 
2154
2343
}
2155
2344
 
2156
2345
 
2157
 
int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, char ***PropertyNames)
 
2346
int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, const char ***PropertyNames)
2158
2347
{
2159
2348
    LPIT8 it8 = (LPIT8) hIT8;
2160
2349
    LPKEYVALUE p;
2161
2350
    int n;
2162
 
    char **Props;
 
2351
    const char **Props;
2163
2352
    LPTABLE t = GetTable(it8);
2164
2353
 
2165
2354
    // Pass#1 - count properties
2170
2359
    }
2171
2360
 
2172
2361
 
2173
 
    Props = (char **) AllocChunk(it8, sizeof(char *) * n);
 
2362
    Props = (const char **) AllocChunk(it8, sizeof(char *) * n);
2174
2363
 
2175
2364
    // Pass#2 - Fill pointers
2176
2365
    n = 0;
2182
2371
    return n;
2183
2372
}
2184
2373
 
 
2374
int LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char ***SubpropertyNames)
 
2375
{
 
2376
    LPIT8 it8 = (LPIT8) hIT8;
 
2377
    LPKEYVALUE p, tmp;
 
2378
    int n;
 
2379
    const char **Props;
 
2380
    LPTABLE t = GetTable(it8);
 
2381
 
 
2382
    if(!IsAvailableOnList(t->HeaderList, cProp, NULL, &p)) {
 
2383
        *SubpropertyNames = 0;
 
2384
        return 0;
 
2385
    }
 
2386
 
 
2387
    // Pass#1 - count properties
 
2388
 
 
2389
    n = 0;
 
2390
    for (tmp = p;  tmp != NULL; tmp = tmp->NextSubkey) {
 
2391
        if(tmp->Subkey != NULL)
 
2392
            n++;
 
2393
    }
 
2394
 
 
2395
 
 
2396
    Props = (const char **) AllocChunk(it8, sizeof(char *) * n);
 
2397
 
 
2398
    // Pass#2 - Fill pointers
 
2399
    n = 0;
 
2400
    for (tmp = p;  tmp != NULL; tmp = tmp->NextSubkey) {
 
2401
        if(tmp->Subkey != NULL)
 
2402
            Props[n++] = p ->Subkey;
 
2403
    }
 
2404
 
 
2405
    *SubpropertyNames = Props;
 
2406
    return n;
 
2407
}
 
2408
 
2185
2409
static
2186
2410
int LocatePatch(LPIT8 it8, const char* cPatch)
2187
2411
{
2405
2629
        if (!buffer) return Data;
2406
2630
 
2407
2631
        strncpy(buffer, Data, MAXSTR-1);        
 
2632
        buffer[MAXSTR-1] = 0;
2408
2633
        return buffer;
2409
2634
}
2410
2635
 
 
2636
int LCMSEXPORT cmsIT8GetPatchByName(LCMSHANDLE hIT8, const char *cPatch)
 
2637
{
 
2638
    return LocatePatch((LPIT8)hIT8, cPatch);
 
2639
}
 
2640
 
2411
2641
int LCMSEXPORT cmsIT8TableCount(LCMSHANDLE hIT8)
2412
2642
{
2413
2643
        LPIT8 it8 = (LPIT8) hIT8;
2448
2678
}
2449
2679
 
2450
2680
 
 
2681
LCMSBOOL LCMSEXPORT cmsIT8SetIndexColumn(LCMSHANDLE hIT8, const char* cSample)
 
2682
{
 
2683
    LPIT8 it8 = (LPIT8) hIT8;
 
2684
 
 
2685
    int pos = LocateSample(it8, cSample);
 
2686
    if(pos == -1)
 
2687
        return FALSE;
 
2688
 
 
2689
    it8->Tab[it8->nTable].SampleID = pos;
 
2690
    return TRUE;
 
2691
}
 
2692
 
 
2693
 
2451
2694
void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE hIT8, const char* Formatter)
2452
2695
{
2453
2696
    LPIT8 it8 = (LPIT8) hIT8;