Bug Summary

File:jdk/src/java.desktop/share/native/liblcms/cmscgats.c
Warning:line 450, column 9
Null pointer passed to 1st parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name cmscgats.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -D LIBC=gnu -D _GNU_SOURCE -D _REENTRANT -D _LARGEFILE64_SOURCE -D LINUX -D DEBUG -D _LITTLE_ENDIAN -D ARCH="amd64" -D amd64 -D _LP64=1 -D CMS_DONT_USE_FAST_FLOOR -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/headers/java.desktop -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt/debug -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/libawt/java2d -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/java2d -D _FORTIFY_SOURCE=2 -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-unused -Wno-format-nonliteral -Wno-type-limits -Wno-misleading-indentation -Wno-undef -Wno-unused-function -Wno-stringop-truncation -std=c99 -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c /home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c
1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25// This file is available under and governed by the GNU General Public
26// License version 2 only, as published by the Free Software Foundation.
27// However, the following notice accompanied the original version of this
28// file:
29//
30//---------------------------------------------------------------------------------
31//
32// Little Color Management System
33// Copyright (c) 1998-2020 Marti Maria Saguer
34//
35// Permission is hereby granted, free of charge, to any person obtaining
36// a copy of this software and associated documentation files (the "Software"),
37// to deal in the Software without restriction, including without limitation
38// the rights to use, copy, modify, merge, publish, distribute, sublicense,
39// and/or sell copies of the Software, and to permit persons to whom the Software
40// is furnished to do so, subject to the following conditions:
41//
42// The above copyright notice and this permission notice shall be included in
43// all copies or substantial portions of the Software.
44//
45// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
46// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
47// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
48// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
49// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
50// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
51// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
52//
53//---------------------------------------------------------------------------------
54//
55
56#include "lcms2_internal.h"
57
58
59// IT8.7 / CGATS.17-200x handling -----------------------------------------------------------------------------
60
61
62#define MAXID128 128 // Max length of identifier
63#define MAXSTR1024 1024 // Max length of string
64#define MAXTABLES255 255 // Max Number of tables in a single stream
65#define MAXINCLUDE20 20 // Max number of nested includes
66
67#define DEFAULT_DBL_FORMAT"%.10g" "%.10g" // Double formatting
68
69#ifdef CMS_IS_WINDOWS_
70# include <io.h>
71# define DIR_CHAR'/' '\\'
72#else
73# define DIR_CHAR'/' '/'
74#endif
75
76
77// Symbols
78typedef enum {
79
80 SUNDEFINED,
81 SINUM, // Integer
82 SDNUM, // Real
83 SIDENT, // Identifier
84 SSTRING, // string
85 SCOMMENT, // comment
86 SEOLN, // End of line
87 SEOF, // End of stream
88 SSYNERROR, // Syntax error found on stream
89
90 // Keywords
91
92 SBEGIN_DATA,
93 SBEGIN_DATA_FORMAT,
94 SEND_DATA,
95 SEND_DATA_FORMAT,
96 SKEYWORD,
97 SDATA_FORMAT_ID,
98 SINCLUDE
99
100 } SYMBOL;
101
102
103// How to write the value
104typedef enum {
105
106 WRITE_UNCOOKED,
107 WRITE_STRINGIFY,
108 WRITE_HEXADECIMAL,
109 WRITE_BINARY,
110 WRITE_PAIR
111
112 } WRITEMODE;
113
114// Linked list of variable names
115typedef struct _KeyVal {
116
117 struct _KeyVal* Next;
118 char* Keyword; // Name of variable
119 struct _KeyVal* NextSubkey; // If key is a dictionary, points to the next item
120 char* Subkey; // If key is a dictionary, points to the subkey name
121 char* Value; // Points to value
122 WRITEMODE WriteAs; // How to write the value
123
124 } KEYVALUE;
125
126
127// Linked list of memory chunks (Memory sink)
128typedef struct _OwnedMem {
129
130 struct _OwnedMem* Next;
131 void * Ptr; // Point to value
132
133 } OWNEDMEM;
134
135// Suballocator
136typedef struct _SubAllocator {
137
138 cmsUInt8Number* Block;
139 cmsUInt32Number BlockSize;
140 cmsUInt32Number Used;
141
142 } SUBALLOCATOR;
143
144// Table. Each individual table can hold properties and rows & cols
145typedef struct _Table {
146
147 char SheetType[MAXSTR1024]; // The first row of the IT8 (the type)
148
149 int nSamples, nPatches; // Cols, Rows
150 int SampleID; // Pos of ID
151
152 KEYVALUE* HeaderList; // The properties
153
154 char** DataFormat; // The binary stream descriptor
155 char** Data; // The binary stream
156
157 } TABLE;
158
159// File stream being parsed
160typedef struct _FileContext {
161 char FileName[cmsMAX_PATH256]; // File name if being read from file
162 FILE* Stream; // File stream or NULL if holded in memory
163 } FILECTX;
164
165// This struct hold all information about an open IT8 handler.
166typedef struct {
167
168
169 cmsUInt32Number TablesCount; // How many tables in this stream
170 cmsUInt32Number nTable; // The actual table
171
172 TABLE Tab[MAXTABLES255];
173
174 // Memory management
175 OWNEDMEM* MemorySink; // The storage backend
176 SUBALLOCATOR Allocator; // String suballocator -- just to keep it fast
177
178 // Parser state machine
179 SYMBOL sy; // Current symbol
180 int ch; // Current character
181
182 cmsInt32Number inum; // integer value
183 cmsFloat64Number dnum; // real value
184
185 char id[MAXID128]; // identifier
186 char str[MAXSTR1024]; // string
187
188 // Allowed keywords & datasets. They have visibility on whole stream
189 KEYVALUE* ValidKeywords;
190 KEYVALUE* ValidSampleID;
191
192 char* Source; // Points to loc. being parsed
193 cmsInt32Number lineno; // line counter for error reporting
194
195 FILECTX* FileStack[MAXINCLUDE20]; // Stack of files being parsed
196 cmsInt32Number IncludeSP; // Include Stack Pointer
197
198 char* MemoryBlock; // The stream if holded in memory
199
200 char DoubleFormatter[MAXID128];// Printf-like 'cmsFloat64Number' formatter
201
202 cmsContext ContextID; // The threading context
203
204 } cmsIT8;
205
206
207// The stream for save operations
208typedef struct {
209
210 FILE* stream; // For save-to-file behaviour
211
212 cmsUInt8Number* Base;
213 cmsUInt8Number* Ptr; // For save-to-mem behaviour
214 cmsUInt32Number Used;
215 cmsUInt32Number Max;
216
217 } SAVESTREAM;
218
219
220// ------------------------------------------------------ cmsIT8 parsing routines
221
222
223// A keyword
224typedef struct {
225
226 const char *id;
227 SYMBOL sy;
228
229 } KEYWORD;
230
231// The keyword->symbol translation table. Sorting is required.
232static const KEYWORD TabKeys[] = {
233
234 {"$INCLUDE", SINCLUDE}, // This is an extension!
235 {".INCLUDE", SINCLUDE}, // This is an extension!
236
237 {"BEGIN_DATA", SBEGIN_DATA },
238 {"BEGIN_DATA_FORMAT", SBEGIN_DATA_FORMAT },
239 {"DATA_FORMAT_IDENTIFIER", SDATA_FORMAT_ID},
240 {"END_DATA", SEND_DATA},
241 {"END_DATA_FORMAT", SEND_DATA_FORMAT},
242 {"KEYWORD", SKEYWORD}
243 };
244
245#define NUMKEYS(sizeof(TabKeys)/sizeof(KEYWORD)) (sizeof(TabKeys)/sizeof(KEYWORD))
246
247// Predefined properties
248
249// A property
250typedef struct {
251 const char *id; // The identifier
252 WRITEMODE as; // How is supposed to be written
253 } PROPERTY;
254
255static PROPERTY PredefinedProperties[] = {
256
257 {"NUMBER_OF_FIELDS", WRITE_UNCOOKED}, // Required - NUMBER OF FIELDS
258 {"NUMBER_OF_SETS", WRITE_UNCOOKED}, // Required - NUMBER OF SETS
259 {"ORIGINATOR", WRITE_STRINGIFY}, // Required - Identifies the specific system, organization or individual that created the data file.
260 {"FILE_DESCRIPTOR", WRITE_STRINGIFY}, // Required - Describes the purpose or contents of the data file.
261 {"CREATED", WRITE_STRINGIFY}, // Required - Indicates date of creation of the data file.
262 {"DESCRIPTOR", WRITE_STRINGIFY}, // Required - Describes the purpose or contents of the data file.
263 {"DIFFUSE_GEOMETRY", WRITE_STRINGIFY}, // The diffuse geometry used. Allowed values are "sphere" or "opal".
264 {"MANUFACTURER", WRITE_STRINGIFY},
265 {"MANUFACTURE", WRITE_STRINGIFY}, // Some broken Fuji targets does store this value
266 {"PROD_DATE", WRITE_STRINGIFY}, // Identifies year and month of production of the target in the form yyyy:mm.
267 {"SERIAL", WRITE_STRINGIFY}, // Uniquely identifies individual physical target.
268
269 {"MATERIAL", WRITE_STRINGIFY}, // Identifies the material on which the target was produced using a code
270 // uniquely identifying th e material. This is intend ed to be used for IT8.7
271 // physical targets only (i.e . IT8.7/1 a nd IT8.7/2).
272
273 {"INSTRUMENTATION", WRITE_STRINGIFY}, // Used to report the specific instrumentation used (manufacturer and
274 // model number) to generate the data reported. This data will often
275 // provide more information about the particular data collected than an
276 // extensive list of specific details. This is particularly important for
277 // spectral data or data derived from spectrophotometry.
278
279 {"MEASUREMENT_SOURCE", WRITE_STRINGIFY}, // Illumination used for spectral measurements. This data helps provide
280 // a guide to the potential for issues of paper fluorescence, etc.
281
282 {"PRINT_CONDITIONS", WRITE_STRINGIFY}, // Used to define the characteristics of the printed sheet being reported.
283 // Where standard conditions have been defined (e.g., SWOP at nominal)
284 // named conditions may suffice. Otherwise, detailed information is
285 // needed.
286
287 {"SAMPLE_BACKING", WRITE_STRINGIFY}, // Identifies the backing material used behind the sample during
288 // measurement. Allowed values are "black", "white", or {"na".
289
290 {"CHISQ_DOF", WRITE_STRINGIFY}, // Degrees of freedom associated with the Chi squared statistic
291 // below properties are new in recent specs:
292
293 {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated
294 // along with details of the geometry and the aperture size and shape. For example,
295 // for transmission measurements it is important to identify 0/diffuse, diffuse/0,
296 // opal or integrating sphere, etc. For reflection it is important to identify 0/45,
297 // 45/0, sphere (specular included or excluded), etc.
298
299 {"FILTER", WRITE_STRINGIFY}, // Identifies the use of physical filter(s) during measurement. Typically used to
300 // denote the use of filters such as none, D65, Red, Green or Blue.
301
302 {"POLARIZATION", WRITE_STRINGIFY}, // Identifies the use of a physical polarization filter during measurement. Allowed
303 // values are {"yes", "white", "none" or "na".
304
305 {"WEIGHTING_FUNCTION", WRITE_PAIR}, // Indicates such functions as: the CIE standard observer functions used in the
306 // calculation of various data parameters (2 degree and 10 degree), CIE standard
307 // illuminant functions used in the calculation of various data parameters (e.g., D50,
308 // D65, etc.), density status response, etc. If used there shall be at least one
309 // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute
310 // in the set shall be {"name" and shall identify the particular parameter used.
311 // The second shall be {"value" and shall provide the value associated with that name.
312 // For ASCII data, a string containing the Name and Value attribute pairs shall follow
313 // the weighting function keyword. A semi-colon separates attribute pairs from each
314 // other and within the attribute the name and value are separated by a comma.
315
316 {"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name
317 // of the calculation, parameter is the name of the parameter used in the calculation
318 // and value is the value of the parameter.
319
320 {"TARGET_TYPE", WRITE_STRINGIFY}, // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc.
321
322 {"COLORANT", WRITE_STRINGIFY}, // Identifies the colorant(s) used in creating the target.
323
324 {"TABLE_DESCRIPTOR", WRITE_STRINGIFY}, // Describes the purpose or contents of a data table.
325
326 {"TABLE_NAME", WRITE_STRINGIFY} // Provides a short name for a data table.
327};
328
329#define NUMPREDEFINEDPROPS(sizeof(PredefinedProperties)/sizeof(PROPERTY)) (sizeof(PredefinedProperties)/sizeof(PROPERTY))
330
331
332// Predefined sample types on dataset
333static const char* PredefinedSampleID[] = {
334 "SAMPLE_ID", // Identifies sample that data represents
335 "STRING", // Identifies label, or other non-machine readable value.
336 // Value must begin and end with a " symbol
337
338 "CMYK_C", // Cyan component of CMYK data expressed as a percentage
339 "CMYK_M", // Magenta component of CMYK data expressed as a percentage
340 "CMYK_Y", // Yellow component of CMYK data expressed as a percentage
341 "CMYK_K", // Black component of CMYK data expressed as a percentage
342 "D_RED", // Red filter density
343 "D_GREEN", // Green filter density
344 "D_BLUE", // Blue filter density
345 "D_VIS", // Visual filter density
346 "D_MAJOR_FILTER", // Major filter d ensity
347 "RGB_R", // Red component of RGB data
348 "RGB_G", // Green component of RGB data
349 "RGB_B", // Blue com ponent of RGB data
350 "SPECTRAL_NM", // Wavelength of measurement expressed in nanometers
351 "SPECTRAL_PCT", // Percentage reflectance/transmittance
352 "SPECTRAL_DEC", // Reflectance/transmittance
353 "XYZ_X", // X component of tristimulus data
354 "XYZ_Y", // Y component of tristimulus data
355 "XYZ_Z", // Z component of tristimulus data
356 "XYY_X", // x component of chromaticity data
357 "XYY_Y", // y component of chromaticity data
358 "XYY_CAPY", // Y component of tristimulus data
359 "LAB_L", // L* component of Lab data
360 "LAB_A", // a* component of Lab data
361 "LAB_B", // b* component of Lab data
362 "LAB_C", // C*ab component of Lab data
363 "LAB_H", // hab component of Lab data
364 "LAB_DE", // CIE dE
365 "LAB_DE_94", // CIE dE using CIE 94
366 "LAB_DE_CMC", // dE using CMC
367 "LAB_DE_2000", // CIE dE using CIE DE 2000
368 "MEAN_DE", // Mean Delta E (LAB_DE) of samples compared to batch average
369 // (Used for data files for ANSI IT8.7/1 and IT8.7/2 targets)
370 "STDEV_X", // Standard deviation of X (tristimulus data)
371 "STDEV_Y", // Standard deviation of Y (tristimulus data)
372 "STDEV_Z", // Standard deviation of Z (tristimulus data)
373 "STDEV_L", // Standard deviation of L*
374 "STDEV_A", // Standard deviation of a*
375 "STDEV_B", // Standard deviation of b*
376 "STDEV_DE", // Standard deviation of CIE dE
377 "CHI_SQD_PAR"}; // The average of the standard deviations of L*, a* and b*. It is
378 // used to derive an estimate of the chi-squared parameter which is
379 // recommended as the predictor of the variability of dE
380
381#define NUMPREDEFINEDSAMPLEID(sizeof(PredefinedSampleID)/sizeof(char *)) (sizeof(PredefinedSampleID)/sizeof(char *))
382
383//Forward declaration of some internal functions
384static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size);
385
386// Checks whatever c is a separator
387static
388cmsBool isseparator(int c)
389{
390 return (c == ' ') || (c == '\t') ;
391}
392
393// Checks whatever c is a valid identifier char
394static
395cmsBool ismiddle(int c)
396{
397 return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127));
398}
399
400// Checks whatsever c is a valid identifier middle char.
401static
402cmsBool isidchar(int c)
403{
404 return isalnum(c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISalnum
)
|| ismiddle(c);
405}
406
407// Checks whatsever c is a valid identifier first char.
408static
409cmsBool isfirstidchar(int c)
410{
411 return !isdigit(c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISdigit
)
&& ismiddle(c)
;
3
Assuming the condition is false
4
Returning zero, which participates in a condition later
412}
413
414// Guess whether the supplied path looks like an absolute path
415static
416cmsBool isabsolutepath(const char *path)
417{
418 char ThreeChars[4];
419
420 if(path
30.1
'path' is not equal to NULL
== NULL((void*)0))
31
Taking false branch
421 return FALSE0;
422 if (path[0] == 0)
32
Assuming the condition is false
33
Taking false branch
423 return FALSE0;
424
425 strncpy(ThreeChars, path, 3);
426 ThreeChars[3] = 0;
427
428 if(ThreeChars[0] == DIR_CHAR'/')
34
Assuming the condition is true
35
Taking true branch
429 return TRUE1;
36
Returning the value 1, which participates in a condition later
430
431#ifdef CMS_IS_WINDOWS_
432 if (isalpha((int) ThreeChars[0])((*__ctype_b_loc ())[(int) (((int) ThreeChars[0]))] & (unsigned
short int) _ISalpha)
&& ThreeChars[1] == ':')
433 return TRUE1;
434#endif
435 return FALSE0;
436}
437
438
439// Makes a file path based on a given reference path
440// NOTE: this function doesn't check if the path exists or even if it's legal
441static
442cmsBool BuildAbsolutePath(const char *relPath, const char *basePath, char *buffer, cmsUInt32Number MaxLen)
443{
444 char *tail;
445 cmsUInt32Number len;
446
447 // Already absolute?
448 if (isabsolutepath(relPath)) {
30
Calling 'isabsolutepath'
37
Returning from 'isabsolutepath'
38
Taking true branch
449
450 strncpy(buffer, relPath, MaxLen);
39
Null pointer passed to 1st parameter expecting 'nonnull'
451 buffer[MaxLen-1] = 0;
452 return TRUE1;
453 }
454
455 // No, search for last
456 strncpy(buffer, basePath, MaxLen);
457 buffer[MaxLen-1] = 0;
458
459 tail = strrchr(buffer, DIR_CHAR'/');
460 if (tail == NULL((void*)0)) return FALSE0; // Is not absolute and has no separators??
461
462 len = (cmsUInt32Number) (tail - buffer);
463 if (len >= MaxLen) return FALSE0;
464
465 // No need to assure zero terminator over here
466 strncpy(tail + 1, relPath, MaxLen - len);
467
468 return TRUE1;
469}
470
471
472// Make sure no exploit is being even tried
473static
474const char* NoMeta(const char* str)
475{
476 if (strchr(str, '%') != NULL((void*)0))
477 return "**** CORRUPTED FORMAT STRING ***";
478
479 return str;
480}
481
482// Syntax error
483static
484cmsBool SynError(cmsIT8* it8, const char *Txt, ...)
485{
486 char Buffer[256], ErrMsg[1024];
487 va_list args;
488
489 va_start(args, Txt)__builtin_va_start(args, Txt);
490 vsnprintf(Buffer, 255, Txt, args);
491 Buffer[255] = 0;
492 va_end(args)__builtin_va_end(args);
493
494 snprintf(ErrMsg, 1023, "%s: Line %d, %s", it8->FileStack[it8 ->IncludeSP]->FileName, it8->lineno, Buffer)__builtin___snprintf_chk (ErrMsg, 1023, 2 - 1, __builtin_object_size
(ErrMsg, 2 > 1), "%s: Line %d, %s", it8->FileStack[it8
->IncludeSP]->FileName, it8->lineno, Buffer)
;
495 ErrMsg[1023] = 0;
496 it8->sy = SSYNERROR;
497 cmsSignalError(it8 ->ContextID, cmsERROR_CORRUPTION_DETECTED12, "%s", ErrMsg);
498 return FALSE0;
499}
500
501// Check if current symbol is same as specified. issue an error else.
502static
503cmsBool Check(cmsIT8* it8, SYMBOL sy, const char* Err)
504{
505 if (it8 -> sy != sy)
21
Assuming 'sy' is equal to field 'sy'
22
Taking false branch
506 return SynError(it8, NoMeta(Err));
507 return TRUE1;
23
Returning the value 1, which participates in a condition later
508}
509
510// Read Next character from stream
511static
512void NextCh(cmsIT8* it8)
513{
514 if (it8 -> FileStack[it8 ->IncludeSP]->Stream) {
515
516 it8 ->ch = fgetc(it8 ->FileStack[it8 ->IncludeSP]->Stream);
517
518 if (feof(it8 -> FileStack[it8 ->IncludeSP]->Stream)) {
519
520 if (it8 ->IncludeSP > 0) {
521
522 fclose(it8 ->FileStack[it8->IncludeSP--]->Stream);
523 it8 -> ch = ' '; // Whitespace to be ignored
524
525 } else
526 it8 ->ch = 0; // EOF
527 }
528 }
529 else {
530 it8->ch = *it8->Source;
531 if (it8->ch) it8->Source++;
532 }
533}
534
535
536// Try to see if current identifier is a keyword, if so return the referred symbol
537static
538SYMBOL BinSrchKey(const char *id)
539{
540 int l = 1;
541 int r = NUMKEYS(sizeof(TabKeys)/sizeof(KEYWORD));
542 int x, res;
543
544 while (r >= l)
545 {
546 x = (l+r)/2;
547 res = cmsstrcasecmp(id, TabKeys[x-1].id);
548 if (res == 0) return TabKeys[x-1].sy;
549 if (res < 0) r = x - 1;
550 else l = x + 1;
551 }
552
553 return SUNDEFINED;
554}
555
556
557// 10 ^n
558static
559cmsFloat64Number xpow10(int n)
560{
561 return pow(10, (cmsFloat64Number) n);
562}
563
564
565// Reads a Real number, tries to follow from integer number
566static
567void ReadReal(cmsIT8* it8, cmsInt32Number inum)
568{
569 it8->dnum = (cmsFloat64Number)inum;
570
571 while (isdigit(it8->ch)((*__ctype_b_loc ())[(int) ((it8->ch))] & (unsigned short
int) _ISdigit)
) {
572
573 it8->dnum = (cmsFloat64Number)it8->dnum * 10.0 + (cmsFloat64Number)(it8->ch - '0');
574 NextCh(it8);
575 }
576
577 if (it8->ch == '.') { // Decimal point
578
579 cmsFloat64Number frac = 0.0; // fraction
580 int prec = 0; // precision
581
582 NextCh(it8); // Eats dec. point
583
584 while (isdigit(it8->ch)((*__ctype_b_loc ())[(int) ((it8->ch))] & (unsigned short
int) _ISdigit)
) {
585
586 frac = frac * 10.0 + (cmsFloat64Number)(it8->ch - '0');
587 prec++;
588 NextCh(it8);
589 }
590
591 it8->dnum = it8->dnum + (frac / xpow10(prec));
592 }
593
594 // Exponent, example 34.00E+20
595 if (toupper(it8->ch)(__extension__ ({ int __res; if (sizeof (it8->ch) > 1) {
if (__builtin_constant_p (it8->ch)) { int __c = (it8->
ch); __res = __c < -128 || __c > 255 ? __c : (*__ctype_toupper_loc
())[__c]; } else __res = toupper (it8->ch); } else __res =
(*__ctype_toupper_loc ())[(int) (it8->ch)]; __res; }))
== 'E') {
596
597 cmsInt32Number e;
598 cmsInt32Number sgn;
599
600 NextCh(it8); sgn = 1;
601
602 if (it8->ch == '-') {
603
604 sgn = -1; NextCh(it8);
605 }
606 else
607 if (it8->ch == '+') {
608
609 sgn = +1;
610 NextCh(it8);
611 }
612
613 e = 0;
614 while (isdigit(it8->ch)((*__ctype_b_loc ())[(int) ((it8->ch))] & (unsigned short
int) _ISdigit)
) {
615
616 cmsInt32Number digit = (it8->ch - '0');
617
618 if ((cmsFloat64Number)e * 10.0 + (cmsFloat64Number)digit < (cmsFloat64Number)+2147483647.0)
619 e = e * 10 + digit;
620
621 NextCh(it8);
622 }
623
624 e = sgn*e;
625 it8->dnum = it8->dnum * xpow10(e);
626 }
627}
628
629// Parses a float number
630// This can not call directly atof because it uses locale dependent
631// parsing, while CCMX files always use . as decimal separator
632static
633cmsFloat64Number ParseFloatNumber(const char *Buffer)
634{
635 cmsFloat64Number dnum = 0.0;
636 int sign = 1;
637
638 // keep safe
639 if (Buffer == NULL((void*)0)) return 0.0;
640
641 if (*Buffer == '-' || *Buffer == '+') {
642
643 sign = (*Buffer == '-') ? -1 : 1;
644 Buffer++;
645 }
646
647
648 while (*Buffer && isdigit((int)*Buffer)((*__ctype_b_loc ())[(int) (((int)*Buffer))] & (unsigned short
int) _ISdigit)
) {
649
650 dnum = dnum * 10.0 + (*Buffer - '0');
651 if (*Buffer) Buffer++;
652 }
653
654 if (*Buffer == '.') {
655
656 cmsFloat64Number frac = 0.0; // fraction
657 int prec = 0; // precision
658
659 if (*Buffer) Buffer++;
660
661 while (*Buffer && isdigit((int)*Buffer)((*__ctype_b_loc ())[(int) (((int)*Buffer))] & (unsigned short
int) _ISdigit)
) {
662
663 frac = frac * 10.0 + (*Buffer - '0');
664 prec++;
665 if (*Buffer) Buffer++;
666 }
667
668 dnum = dnum + (frac / xpow10(prec));
669 }
670
671 // Exponent, example 34.00E+20
672 if (*Buffer && toupper(*Buffer)(__extension__ ({ int __res; if (sizeof (*Buffer) > 1) { if
(__builtin_constant_p (*Buffer)) { int __c = (*Buffer); __res
= __c < -128 || __c > 255 ? __c : (*__ctype_toupper_loc
())[__c]; } else __res = toupper (*Buffer); } else __res = (
*__ctype_toupper_loc ())[(int) (*Buffer)]; __res; }))
== 'E') {
673
674 int e;
675 int sgn;
676
677 if (*Buffer) Buffer++;
678 sgn = 1;
679
680 if (*Buffer == '-') {
681
682 sgn = -1;
683 if (*Buffer) Buffer++;
684 }
685 else
686 if (*Buffer == '+') {
687
688 sgn = +1;
689 if (*Buffer) Buffer++;
690 }
691
692 e = 0;
693 while (*Buffer && isdigit((int)*Buffer)((*__ctype_b_loc ())[(int) (((int)*Buffer))] & (unsigned short
int) _ISdigit)
) {
694
695 cmsInt32Number digit = (*Buffer - '0');
696
697 if ((cmsFloat64Number)e * 10.0 + digit < (cmsFloat64Number)+2147483647.0)
698 e = e * 10 + digit;
699
700 if (*Buffer) Buffer++;
701 }
702
703 e = sgn*e;
704 dnum = dnum * xpow10(e);
705 }
706
707 return sign * dnum;
708}
709
710
711// Reads next symbol
712static
713void InSymbol(cmsIT8* it8)
714{
715 CMSREGISTERregister char *idptr;
716 CMSREGISTERregister int k;
717 SYMBOL key;
718 int sng;
719
720 do {
15
Loop condition is false. Exiting loop
721
722 while (isseparator(it8->ch))
1
Loop condition is false. Execution continues on line 725
723 NextCh(it8);
724
725 if (isfirstidchar(it8->ch)) { // Identifier
2
Calling 'isfirstidchar'
5
Returning from 'isfirstidchar'
6
Taking false branch
726
727 k = 0;
728 idptr = it8->id;
729
730 do {
731
732 if (++k < MAXID128) *idptr++ = (char) it8->ch;
733
734 NextCh(it8);
735
736 } while (isidchar(it8->ch));
737
738 *idptr = '\0';
739
740
741 key = BinSrchKey(it8->id);
742 if (key == SUNDEFINED) it8->sy = SIDENT;
743 else it8->sy = key;
744
745 }
746 else // Is a number?
747 if (isdigit(it8->ch)((*__ctype_b_loc ())[(int) ((it8->ch))] & (unsigned short
int) _ISdigit)
|| it8->ch == '.' || it8->ch == '-' || it8->ch == '+')
7
Assuming the condition is false
8
Assuming the condition is false
9
Assuming the condition is false
10
Assuming the condition is false
11
Taking false branch
748 {
749 int sign = 1;
750
751 if (it8->ch == '-') {
752 sign = -1;
753 NextCh(it8);
754 }
755
756 it8->inum = 0;
757 it8->sy = SINUM;
758
759 if (it8->ch == '0') { // 0xnnnn (Hexa) or 0bnnnn (Binary)
760
761 NextCh(it8);
762 if (toupper(it8->ch)(__extension__ ({ int __res; if (sizeof (it8->ch) > 1) {
if (__builtin_constant_p (it8->ch)) { int __c = (it8->
ch); __res = __c < -128 || __c > 255 ? __c : (*__ctype_toupper_loc
())[__c]; } else __res = toupper (it8->ch); } else __res =
(*__ctype_toupper_loc ())[(int) (it8->ch)]; __res; }))
== 'X') {
763
764 int j;
765
766 NextCh(it8);
767 while (isxdigit(it8->ch)((*__ctype_b_loc ())[(int) ((it8->ch))] & (unsigned short
int) _ISxdigit)
)
768 {
769 it8->ch = toupper(it8->ch)(__extension__ ({ int __res; if (sizeof (it8->ch) > 1) {
if (__builtin_constant_p (it8->ch)) { int __c = (it8->
ch); __res = __c < -128 || __c > 255 ? __c : (*__ctype_toupper_loc
())[__c]; } else __res = toupper (it8->ch); } else __res =
(*__ctype_toupper_loc ())[(int) (it8->ch)]; __res; }))
;
770 if (it8->ch >= 'A' && it8->ch <= 'F') j = it8->ch -'A'+10;
771 else j = it8->ch - '0';
772
773 if ((cmsFloat64Number) it8->inum * 16.0 + (cmsFloat64Number) j > (cmsFloat64Number)+2147483647.0)
774 {
775 SynError(it8, "Invalid hexadecimal number");
776 return;
777 }
778
779 it8->inum = it8->inum * 16 + j;
780 NextCh(it8);
781 }
782 return;
783 }
784
785 if (toupper(it8->ch)(__extension__ ({ int __res; if (sizeof (it8->ch) > 1) {
if (__builtin_constant_p (it8->ch)) { int __c = (it8->
ch); __res = __c < -128 || __c > 255 ? __c : (*__ctype_toupper_loc
())[__c]; } else __res = toupper (it8->ch); } else __res =
(*__ctype_toupper_loc ())[(int) (it8->ch)]; __res; }))
== 'B') { // Binary
786
787 int j;
788
789 NextCh(it8);
790 while (it8->ch == '0' || it8->ch == '1')
791 {
792 j = it8->ch - '0';
793
794 if ((cmsFloat64Number) it8->inum * 2.0 + j > (cmsFloat64Number)+2147483647.0)
795 {
796 SynError(it8, "Invalid binary number");
797 return;
798 }
799
800 it8->inum = it8->inum * 2 + j;
801 NextCh(it8);
802 }
803 return;
804 }
805 }
806
807
808 while (isdigit(it8->ch)((*__ctype_b_loc ())[(int) ((it8->ch))] & (unsigned short
int) _ISdigit)
) {
809
810 cmsInt32Number digit = (it8->ch - '0');
811
812 if ((cmsFloat64Number) it8->inum * 10.0 + (cmsFloat64Number) digit > (cmsFloat64Number) +2147483647.0) {
813 ReadReal(it8, it8->inum);
814 it8->sy = SDNUM;
815 it8->dnum *= sign;
816 return;
817 }
818
819 it8->inum = it8->inum * 10 + digit;
820 NextCh(it8);
821 }
822
823 if (it8->ch == '.') {
824
825 ReadReal(it8, it8->inum);
826 it8->sy = SDNUM;
827 it8->dnum *= sign;
828 return;
829 }
830
831 it8 -> inum *= sign;
832
833 // Special case. Numbers followed by letters are taken as identifiers
834
835 if (isidchar(it8 ->ch)) {
836
837 if (it8 ->sy == SINUM) {
838
839 snprintf(it8->id, 127, "%d", it8->inum)__builtin___snprintf_chk (it8->id, 127, 2 - 1, __builtin_object_size
(it8->id, 2 > 1), "%d", it8->inum)
;
840 }
841 else {
842
843 snprintf(it8->id, 127, it8 ->DoubleFormatter, it8->dnum)__builtin___snprintf_chk (it8->id, 127, 2 - 1, __builtin_object_size
(it8->id, 2 > 1), it8 ->DoubleFormatter, it8->dnum
)
;
844 }
845
846 k = (int) strlen(it8 ->id);
847 idptr = it8 ->id + k;
848 do {
849
850 if (++k < MAXID128) *idptr++ = (char) it8->ch;
851
852 NextCh(it8);
853
854 } while (isidchar(it8->ch));
855
856 *idptr = '\0';
857 it8->sy = SIDENT;
858 }
859 return;
860
861 }
862 else
863 switch ((int) it8->ch) {
12
Control jumps to 'case 26:' at line 866
864
865 // EOF marker -- ignore it
866 case '\x1a':
867 NextCh(it8);
868 break;
13
Execution continues on line 930
869
870 // Eof stream markers
871 case 0:
872 case -1:
873 it8->sy = SEOF;
874 break;
875
876
877 // Next line
878 case '\r':
879 NextCh(it8);
880 if (it8 ->ch == '\n')
881 NextCh(it8);
882 it8->sy = SEOLN;
883 it8->lineno++;
884 break;
885
886 case '\n':
887 NextCh(it8);
888 it8->sy = SEOLN;
889 it8->lineno++;
890 break;
891
892 // Comment
893 case '#':
894 NextCh(it8);
895 while (it8->ch && it8->ch != '\n' && it8->ch != '\r')
896 NextCh(it8);
897
898 it8->sy = SCOMMENT;
899 break;
900
901 // String.
902 case '\'':
903 case '\"':
904 idptr = it8->str;
905 sng = it8->ch;
906 k = 0;
907 NextCh(it8);
908
909 while (k < (MAXSTR1024-1) && it8->ch != sng) {
910
911 if (it8->ch == '\n'|| it8->ch == '\r') k = MAXSTR1024+1;
912 else {
913 *idptr++ = (char) it8->ch;
914 NextCh(it8);
915 k++;
916 }
917 }
918
919 it8->sy = SSTRING;
920 *idptr = '\0';
921 NextCh(it8);
922 break;
923
924
925 default:
926 SynError(it8, "Unrecognized character: 0x%x", it8 ->ch);
927 return;
928 }
929
930 } while (it8->sy == SCOMMENT);
14
Assuming field 'sy' is not equal to SCOMMENT
931
932 // Handle the include special token
933
934 if (it8 -> sy == SINCLUDE) {
16
Assuming field 'sy' is equal to SINCLUDE
17
Taking true branch
935
936 FILECTX* FileNest;
937
938 if(it8 -> IncludeSP >= (MAXINCLUDE20-1)) {
18
Assuming the condition is false
19
Taking false branch
939
940 SynError(it8, "Too many recursion levels");
941 return;
942 }
943
944 InSymbol(it8);
945 if (!Check(it8, SSTRING, "Filename expected")) return;
20
Calling 'Check'
24
Returning from 'Check'
25
Taking false branch
946
947 FileNest = it8 -> FileStack[it8 -> IncludeSP + 1];
948 if(FileNest == NULL((void*)0)) {
26
Assuming 'FileNest' is equal to NULL
27
Taking true branch
949
950 FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX));
951 //if(FileNest == NULL)
952 // TODO: how to manage out-of-memory conditions?
953 }
954
955 if (BuildAbsolutePath(it8->str,
29
Calling 'BuildAbsolutePath'
956 it8->FileStack[it8->IncludeSP]->FileName,
957 FileNest->FileName, cmsMAX_PATH256-1) == FALSE0) {
28
Passing null pointer value via 3rd parameter 'buffer'
958 SynError(it8, "File path too long");
959 return;
960 }
961
962 FileNest->Stream = fopen(FileNest->FileName, "rt");
963 if (FileNest->Stream == NULL((void*)0)) {
964
965 SynError(it8, "File %s not found", FileNest->FileName);
966 return;
967 }
968 it8->IncludeSP++;
969
970 it8 ->ch = ' ';
971 InSymbol(it8);
972 }
973
974}
975
976// Checks end of line separator
977static
978cmsBool CheckEOLN(cmsIT8* it8)
979{
980 if (!Check(it8, SEOLN, "Expected separator")) return FALSE0;
981 while (it8 -> sy == SEOLN)
982 InSymbol(it8);
983 return TRUE1;
984
985}
986
987// Skip a symbol
988
989static
990void Skip(cmsIT8* it8, SYMBOL sy)
991{
992 if (it8->sy == sy && it8->sy != SEOF)
993 InSymbol(it8);
994}
995
996
997// Skip multiple EOLN
998static
999void SkipEOLN(cmsIT8* it8)
1000{
1001 while (it8->sy == SEOLN) {
1002 InSymbol(it8);
1003 }
1004}
1005
1006
1007// Returns a string holding current value
1008static
1009cmsBool GetVal(cmsIT8* it8, char* Buffer, cmsUInt32Number max, const char* ErrorTitle)
1010{
1011 switch (it8->sy) {
1012
1013 case SEOLN: // Empty value
1014 Buffer[0]=0;
1015 break;
1016 case SIDENT: strncpy(Buffer, it8->id, max);
1017 Buffer[max-1]=0;
1018 break;
1019 case SINUM: snprintf(Buffer, max, "%d", it8 -> inum)__builtin___snprintf_chk (Buffer, max, 2 - 1, __builtin_object_size
(Buffer, 2 > 1), "%d", it8 -> inum)
; break;
1020 case SDNUM: snprintf(Buffer, max, it8->DoubleFormatter, it8 -> dnum)__builtin___snprintf_chk (Buffer, max, 2 - 1, __builtin_object_size
(Buffer, 2 > 1), it8->DoubleFormatter, it8 -> dnum)
; break;
1021 case SSTRING: strncpy(Buffer, it8->str, max);
1022 Buffer[max-1] = 0;
1023 break;
1024
1025
1026 default:
1027 return SynError(it8, "%s", ErrorTitle);
1028 }
1029
1030 Buffer[max] = 0;
1031 return TRUE1;
1032}
1033
1034// ---------------------------------------------------------- Table
1035
1036static
1037TABLE* GetTable(cmsIT8* it8)
1038{
1039 if ((it8 -> nTable >= it8 ->TablesCount)) {
1040
1041 SynError(it8, "Table %d out of sequence", it8 -> nTable);
1042 return it8 -> Tab;
1043 }
1044
1045 return it8 ->Tab + it8 ->nTable;
1046}
1047
1048// ---------------------------------------------------------- Memory management
1049
1050
1051// Frees an allocator and owned memory
1052void CMSEXPORT cmsIT8Free(cmsHANDLE hIT8)
1053{
1054 cmsIT8* it8 = (cmsIT8*) hIT8;
1055
1056 if (it8 == NULL((void*)0))
1057 return;
1058
1059 if (it8->MemorySink) {
1060
1061 OWNEDMEM* p;
1062 OWNEDMEM* n;
1063
1064 for (p = it8->MemorySink; p != NULL((void*)0); p = n) {
1065
1066 n = p->Next;
1067 if (p->Ptr) _cmsFree(it8 ->ContextID, p->Ptr);
1068 _cmsFree(it8 ->ContextID, p);
1069 }
1070 }
1071
1072 if (it8->MemoryBlock)
1073 _cmsFree(it8 ->ContextID, it8->MemoryBlock);
1074
1075 _cmsFree(it8 ->ContextID, it8);
1076}
1077
1078
1079// Allocates a chunk of data, keep linked list
1080static
1081void* AllocBigBlock(cmsIT8* it8, cmsUInt32Number size)
1082{
1083 OWNEDMEM* ptr1;
1084 void* ptr = _cmsMallocZero(it8->ContextID, size);
1085
1086 if (ptr != NULL((void*)0)) {
1087
1088 ptr1 = (OWNEDMEM*) _cmsMallocZero(it8 ->ContextID, sizeof(OWNEDMEM));
1089
1090 if (ptr1 == NULL((void*)0)) {
1091
1092 _cmsFree(it8 ->ContextID, ptr);
1093 return NULL((void*)0);
1094 }
1095
1096 ptr1-> Ptr = ptr;
1097 ptr1-> Next = it8 -> MemorySink;
1098 it8 -> MemorySink = ptr1;
1099 }
1100
1101 return ptr;
1102}
1103
1104
1105// Suballocator.
1106static
1107void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
1108{
1109 cmsUInt32Number Free = it8 ->Allocator.BlockSize - it8 ->Allocator.Used;
1110 cmsUInt8Number* ptr;
1111
1112 size = _cmsALIGNMEM(size)(((size)+(sizeof(void *) - 1)) & ~(sizeof(void *) - 1));
1113
1114 if (size > Free) {
1115
1116 if (it8 -> Allocator.BlockSize == 0)
1117
1118 it8 -> Allocator.BlockSize = 20*1024;
1119 else
1120 it8 ->Allocator.BlockSize *= 2;
1121
1122 if (it8 ->Allocator.BlockSize < size)
1123 it8 ->Allocator.BlockSize = size;
1124
1125 it8 ->Allocator.Used = 0;
1126 it8 ->Allocator.Block = (cmsUInt8Number*) AllocBigBlock(it8, it8 ->Allocator.BlockSize);
1127 }
1128
1129 ptr = it8 ->Allocator.Block + it8 ->Allocator.Used;
1130 it8 ->Allocator.Used += size;
1131
1132 return (void*) ptr;
1133
1134}
1135
1136
1137// Allocates a string
1138static
1139char *AllocString(cmsIT8* it8, const char* str)
1140{
1141 cmsUInt32Number Size = (cmsUInt32Number) strlen(str)+1;
1142 char *ptr;
1143
1144
1145 ptr = (char *) AllocChunk(it8, Size);
1146 if (ptr) strncpy (ptr, str, Size-1);
1147
1148 return ptr;
1149}
1150
1151// Searches through linked list
1152
1153static
1154cmsBool IsAvailableOnList(KEYVALUE* p, const char* Key, const char* Subkey, KEYVALUE** LastPtr)
1155{
1156 if (LastPtr) *LastPtr = p;
1157
1158 for (; p != NULL((void*)0); p = p->Next) {
1159
1160 if (LastPtr) *LastPtr = p;
1161
1162 if (*Key != '#') { // Comments are ignored
1163
1164 if (cmsstrcasecmp(Key, p->Keyword) == 0)
1165 break;
1166 }
1167 }
1168
1169 if (p == NULL((void*)0))
1170 return FALSE0;
1171
1172 if (Subkey == 0)
1173 return TRUE1;
1174
1175 for (; p != NULL((void*)0); p = p->NextSubkey) {
1176
1177 if (p ->Subkey == NULL((void*)0)) continue;
1178
1179 if (LastPtr) *LastPtr = p;
1180
1181 if (cmsstrcasecmp(Subkey, p->Subkey) == 0)
1182 return TRUE1;
1183 }
1184
1185 return FALSE0;
1186}
1187
1188
1189
1190// Add a property into a linked list
1191static
1192KEYVALUE* AddToList(cmsIT8* it8, KEYVALUE** Head, const char *Key, const char *Subkey, const char* xValue, WRITEMODE WriteAs)
1193{
1194 KEYVALUE* p;
1195 KEYVALUE* last;
1196
1197
1198 // Check if property is already in list
1199
1200 if (IsAvailableOnList(*Head, Key, Subkey, &p)) {
1201
1202 // This may work for editing properties
1203
1204 // return SynError(it8, "duplicate key <%s>", Key);
1205 }
1206 else {
1207
1208 last = p;
1209
1210 // Allocate the container
1211 p = (KEYVALUE*) AllocChunk(it8, sizeof(KEYVALUE));
1212 if (p == NULL((void*)0))
1213 {
1214 SynError(it8, "AddToList: out of memory");
1215 return NULL((void*)0);
1216 }
1217
1218 // Store name and value
1219 p->Keyword = AllocString(it8, Key);
1220 p->Subkey = (Subkey == NULL((void*)0)) ? NULL((void*)0) : AllocString(it8, Subkey);
1221
1222 // Keep the container in our list
1223 if (*Head == NULL((void*)0)) {
1224 *Head = p;
1225 }
1226 else
1227 {
1228 if (Subkey != NULL((void*)0) && last != NULL((void*)0)) {
1229
1230 last->NextSubkey = p;
1231
1232 // If Subkey is not null, then last is the last property with the same key,
1233 // but not necessarily is the last property in the list, so we need to move
1234 // to the actual list end
1235 while (last->Next != NULL((void*)0))
1236 last = last->Next;
1237 }
1238
1239 if (last != NULL((void*)0)) last->Next = p;
1240 }
1241
1242 p->Next = NULL((void*)0);
1243 p->NextSubkey = NULL((void*)0);
1244 }
1245
1246 p->WriteAs = WriteAs;
1247
1248 if (xValue != NULL((void*)0)) {
1249
1250 p->Value = AllocString(it8, xValue);
1251 }
1252 else {
1253 p->Value = NULL((void*)0);
1254 }
1255
1256 return p;
1257}
1258
1259static
1260KEYVALUE* AddAvailableProperty(cmsIT8* it8, const char* Key, WRITEMODE as)
1261{
1262 return AddToList(it8, &it8->ValidKeywords, Key, NULL((void*)0), NULL((void*)0), as);
1263}
1264
1265
1266static
1267KEYVALUE* AddAvailableSampleID(cmsIT8* it8, const char* Key)
1268{
1269 return AddToList(it8, &it8->ValidSampleID, Key, NULL((void*)0), NULL((void*)0), WRITE_UNCOOKED);
1270}
1271
1272
1273static
1274void AllocTable(cmsIT8* it8)
1275{
1276 TABLE* t;
1277
1278 t = it8 ->Tab + it8 ->TablesCount;
1279
1280 t->HeaderList = NULL((void*)0);
1281 t->DataFormat = NULL((void*)0);
1282 t->Data = NULL((void*)0);
1283
1284 it8 ->TablesCount++;
1285}
1286
1287
1288cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE IT8, cmsUInt32Number nTable)
1289{
1290 cmsIT8* it8 = (cmsIT8*) IT8;
1291
1292 if (nTable >= it8 ->TablesCount) {
1293
1294 if (nTable == it8 ->TablesCount) {
1295
1296 AllocTable(it8);
1297 }
1298 else {
1299 SynError(it8, "Table %d is out of sequence", nTable);
1300 return -1;
1301 }
1302 }
1303
1304 it8 ->nTable = nTable;
1305
1306 return (cmsInt32Number) nTable;
1307}
1308
1309
1310
1311// Init an empty container
1312cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID)
1313{
1314 cmsIT8* it8;
1315 cmsUInt32Number i;
1316
1317 it8 = (cmsIT8*) _cmsMallocZero(ContextID, sizeof(cmsIT8));
1318 if (it8 == NULL((void*)0)) return NULL((void*)0);
1319
1320 AllocTable(it8);
1321
1322 it8->MemoryBlock = NULL((void*)0);
1323 it8->MemorySink = NULL((void*)0);
1324
1325 it8 ->nTable = 0;
1326
1327 it8->ContextID = ContextID;
1328 it8->Allocator.Used = 0;
1329 it8->Allocator.Block = NULL((void*)0);
1330 it8->Allocator.BlockSize = 0;
1331
1332 it8->ValidKeywords = NULL((void*)0);
1333 it8->ValidSampleID = NULL((void*)0);
1334
1335 it8 -> sy = SUNDEFINED;
1336 it8 -> ch = ' ';
1337 it8 -> Source = NULL((void*)0);
1338 it8 -> inum = 0;
1339 it8 -> dnum = 0.0;
1340
1341 it8->FileStack[0] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX));
1342 it8->IncludeSP = 0;
1343 it8 -> lineno = 1;
1344
1345 strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT"%.10g");
1346 cmsIT8SetSheetType((cmsHANDLE) it8, "CGATS.17");
1347
1348 // Initialize predefined properties & data
1349
1350 for (i=0; i < NUMPREDEFINEDPROPS(sizeof(PredefinedProperties)/sizeof(PROPERTY)); i++)
1351 AddAvailableProperty(it8, PredefinedProperties[i].id, PredefinedProperties[i].as);
1352
1353 for (i=0; i < NUMPREDEFINEDSAMPLEID(sizeof(PredefinedSampleID)/sizeof(char *)); i++)
1354 AddAvailableSampleID(it8, PredefinedSampleID[i]);
1355
1356
1357 return (cmsHANDLE) it8;
1358}
1359
1360
1361const char* CMSEXPORT cmsIT8GetSheetType(cmsHANDLE hIT8)
1362{
1363 return GetTable((cmsIT8*) hIT8)->SheetType;
1364}
1365
1366cmsBool CMSEXPORT cmsIT8SetSheetType(cmsHANDLE hIT8, const char* Type)
1367{
1368 TABLE* t = GetTable((cmsIT8*) hIT8);
1369
1370 strncpy(t ->SheetType, Type, MAXSTR1024-1);
1371 t ->SheetType[MAXSTR1024-1] = 0;
1372 return TRUE1;
1373}
1374
1375cmsBool CMSEXPORT cmsIT8SetComment(cmsHANDLE hIT8, const char* Val)
1376{
1377 cmsIT8* it8 = (cmsIT8*) hIT8;
1378
1379 if (!Val) return FALSE0;
1380 if (!*Val) return FALSE0;
1381
1382 return AddToList(it8, &GetTable(it8)->HeaderList, "# ", NULL((void*)0), Val, WRITE_UNCOOKED) != NULL((void*)0);
1383}
1384
1385// Sets a property
1386cmsBool CMSEXPORT cmsIT8SetPropertyStr(cmsHANDLE hIT8, const char* Key, const char *Val)
1387{
1388 cmsIT8* it8 = (cmsIT8*) hIT8;
1389
1390 if (!Val) return FALSE0;
1391 if (!*Val) return FALSE0;
1392
1393 return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL((void*)0), Val, WRITE_STRINGIFY) != NULL((void*)0);
1394}
1395
1396cmsBool CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFloat64Number Val)
1397{
1398 cmsIT8* it8 = (cmsIT8*) hIT8;
1399 char Buffer[1024];
1400
1401 snprintf(Buffer, 1023, it8->DoubleFormatter, Val)__builtin___snprintf_chk (Buffer, 1023, 2 - 1, __builtin_object_size
(Buffer, 2 > 1), it8->DoubleFormatter, Val)
;
1402
1403 return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL((void*)0), Buffer, WRITE_UNCOOKED) != NULL((void*)0);
1404}
1405
1406cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUInt32Number Val)
1407{
1408 cmsIT8* it8 = (cmsIT8*) hIT8;
1409 char Buffer[1024];
1410
1411 snprintf(Buffer, 1023, "%u", Val)__builtin___snprintf_chk (Buffer, 1023, 2 - 1, __builtin_object_size
(Buffer, 2 > 1), "%u", Val)
;
1412
1413 return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL((void*)0), Buffer, WRITE_HEXADECIMAL) != NULL((void*)0);
1414}
1415
1416cmsBool CMSEXPORT cmsIT8SetPropertyUncooked(cmsHANDLE hIT8, const char* Key, const char* Buffer)
1417{
1418 cmsIT8* it8 = (cmsIT8*) hIT8;
1419
1420 return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL((void*)0), Buffer, WRITE_UNCOOKED) != NULL((void*)0);
1421}
1422
1423cmsBool CMSEXPORT cmsIT8SetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer)
1424{
1425 cmsIT8* it8 = (cmsIT8*) hIT8;
1426
1427 return AddToList(it8, &GetTable(it8)->HeaderList, Key, SubKey, Buffer, WRITE_PAIR) != NULL((void*)0);
1428}
1429
1430// Gets a property
1431const char* CMSEXPORT cmsIT8GetProperty(cmsHANDLE hIT8, const char* Key)
1432{
1433 cmsIT8* it8 = (cmsIT8*) hIT8;
1434 KEYVALUE* p;
1435
1436 if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, NULL((void*)0), &p))
1437 {
1438 return p -> Value;
1439 }
1440 return NULL((void*)0);
1441}
1442
1443
1444cmsFloat64Number CMSEXPORT cmsIT8GetPropertyDbl(cmsHANDLE hIT8, const char* cProp)
1445{
1446 const char *v = cmsIT8GetProperty(hIT8, cProp);
1447
1448 if (v == NULL((void*)0)) return 0.0;
1449
1450 return ParseFloatNumber(v);
1451}
1452
1453const char* CMSEXPORT cmsIT8GetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char *SubKey)
1454{
1455 cmsIT8* it8 = (cmsIT8*) hIT8;
1456 KEYVALUE* p;
1457
1458 if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, SubKey, &p)) {
1459 return p -> Value;
1460 }
1461 return NULL((void*)0);
1462}
1463
1464// ----------------------------------------------------------------- Datasets
1465
1466
1467static
1468void AllocateDataFormat(cmsIT8* it8)
1469{
1470 TABLE* t = GetTable(it8);
1471
1472 if (t -> DataFormat) return; // Already allocated
1473
1474 t -> nSamples = (int) cmsIT8GetPropertyDbl(it8, "NUMBER_OF_FIELDS");
1475
1476 if (t -> nSamples <= 0) {
1477
1478 SynError(it8, "AllocateDataFormat: Unknown NUMBER_OF_FIELDS");
1479 t -> nSamples = 10;
1480 }
1481
1482 t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *));
1483 if (t->DataFormat == NULL((void*)0)) {
1484
1485 SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array");
1486 }
1487
1488}
1489
1490static
1491const char *GetDataFormat(cmsIT8* it8, int n)
1492{
1493 TABLE* t = GetTable(it8);
1494
1495 if (t->DataFormat)
1496 return t->DataFormat[n];
1497
1498 return NULL((void*)0);
1499}
1500
1501static
1502cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label)
1503{
1504 TABLE* t = GetTable(it8);
1505
1506 if (!t->DataFormat)
1507 AllocateDataFormat(it8);
1508
1509 if (n > t -> nSamples) {
1510 SynError(it8, "More than NUMBER_OF_FIELDS fields.");
1511 return FALSE0;
1512 }
1513
1514 if (t->DataFormat) {
1515 t->DataFormat[n] = AllocString(it8, label);
1516 }
1517
1518 return TRUE1;
1519}
1520
1521
1522cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE h, int n, const char *Sample)
1523{
1524 cmsIT8* it8 = (cmsIT8*)h;
1525 return SetDataFormat(it8, n, Sample);
1526}
1527
1528// A safe atoi that returns 0 when NULL input is given
1529static
1530cmsInt32Number satoi(const char* b)
1531{
1532 if (b == NULL((void*)0)) return 0;
1533 return atoi(b);
1534}
1535
1536static
1537void AllocateDataSet(cmsIT8* it8)
1538{
1539 TABLE* t = GetTable(it8);
1540
1541 if (t -> Data) return; // Already allocated
1542
1543 t-> nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
1544 t-> nPatches = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
1545
1546 if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe)
1547 {
1548 SynError(it8, "AllocateDataSet: too much data");
1549 }
1550 else {
1551 // Some dumb analizers warns of possible overflow here, just take a look couple of lines above.
1552 t->Data = (char**)AllocChunk(it8, ((cmsUInt32Number)t->nSamples + 1) * ((cmsUInt32Number)t->nPatches + 1) * sizeof(char*));
1553 if (t->Data == NULL((void*)0)) {
1554
1555 SynError(it8, "AllocateDataSet: Unable to allocate data array");
1556 }
1557 }
1558
1559}
1560
1561static
1562char* GetData(cmsIT8* it8, int nSet, int nField)
1563{
1564 TABLE* t = GetTable(it8);
1565 int nSamples = t -> nSamples;
1566 int nPatches = t -> nPatches;
1567
1568 if (nSet >= nPatches || nField >= nSamples)
1569 return NULL((void*)0);
1570
1571 if (!t->Data) return NULL((void*)0);
1572 return t->Data [nSet * nSamples + nField];
1573}
1574
1575static
1576cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val)
1577{
1578 TABLE* t = GetTable(it8);
1579
1580 if (!t->Data)
1581 AllocateDataSet(it8);
1582
1583 if (!t->Data) return FALSE0;
1584
1585 if (nSet > t -> nPatches || nSet < 0) {
1586
1587 return SynError(it8, "Patch %d out of range, there are %d patches", nSet, t -> nPatches);
1588 }
1589
1590 if (nField > t ->nSamples || nField < 0) {
1591 return SynError(it8, "Sample %d out of range, there are %d samples", nField, t ->nSamples);
1592
1593 }
1594
1595 t->Data [nSet * t -> nSamples + nField] = AllocString(it8, Val);
1596 return TRUE1;
1597}
1598
1599
1600// --------------------------------------------------------------- File I/O
1601
1602
1603// Writes a string to file
1604static
1605void WriteStr(SAVESTREAM* f, const char *str)
1606{
1607 cmsUInt32Number len;
1608
1609 if (str == NULL((void*)0))
1610 str = " ";
1611
1612 // Length to write
1613 len = (cmsUInt32Number) strlen(str);
1614 f ->Used += len;
1615
1616
1617 if (f ->stream) { // Should I write it to a file?
1618
1619 if (fwrite(str, 1, len, f->stream) != len) {
1620 cmsSignalError(0, cmsERROR_WRITE7, "Write to file error in CGATS parser");
1621 return;
1622 }
1623
1624 }
1625 else { // Or to a memory block?
1626
1627 if (f ->Base) { // Am I just counting the bytes?
1628
1629 if (f ->Used > f ->Max) {
1630
1631 cmsSignalError(0, cmsERROR_WRITE7, "Write to memory overflows in CGATS parser");
1632 return;
1633 }
1634
1635 memmove(f ->Ptr, str, len);
1636 f->Ptr += len;
1637 }
1638
1639 }
1640}
1641
1642
1643// Write formatted
1644
1645static
1646void Writef(SAVESTREAM* f, const char* frm, ...)
1647{
1648 char Buffer[4096];
1649 va_list args;
1650
1651 va_start(args, frm)__builtin_va_start(args, frm);
1652 vsnprintf(Buffer, 4095, frm, args);
1653 Buffer[4095] = 0;
1654 WriteStr(f, Buffer);
1655 va_end(args)__builtin_va_end(args);
1656
1657}
1658
1659// Writes full header
1660static
1661void WriteHeader(cmsIT8* it8, SAVESTREAM* fp)
1662{
1663 KEYVALUE* p;
1664 TABLE* t = GetTable(it8);
1665
1666 // Writes the type
1667 WriteStr(fp, t->SheetType);
1668 WriteStr(fp, "\n");
1669
1670 for (p = t->HeaderList; (p != NULL((void*)0)); p = p->Next)
1671 {
1672 if (*p ->Keyword == '#') {
1673
1674 char* Pt;
1675
1676 WriteStr(fp, "#\n# ");
1677 for (Pt = p ->Value; *Pt; Pt++) {
1678
1679
1680 Writef(fp, "%c", *Pt);
1681
1682 if (*Pt == '\n') {
1683 WriteStr(fp, "# ");
1684 }
1685 }
1686
1687 WriteStr(fp, "\n#\n");
1688 continue;
1689 }
1690
1691
1692 if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL((void*)0), NULL((void*)0))) {
1693
1694#ifdef CMS_STRICT_CGATS
1695 WriteStr(fp, "KEYWORD\t\"");
1696 WriteStr(fp, p->Keyword);
1697 WriteStr(fp, "\"\n");
1698#endif
1699
1700 AddAvailableProperty(it8, p->Keyword, WRITE_UNCOOKED);
1701 }
1702
1703 WriteStr(fp, p->Keyword);
1704 if (p->Value) {
1705
1706 switch (p ->WriteAs) {
1707
1708 case WRITE_UNCOOKED:
1709 Writef(fp, "\t%s", p ->Value);
1710 break;
1711
1712 case WRITE_STRINGIFY:
1713 Writef(fp, "\t\"%s\"", p->Value );
1714 break;
1715
1716 case WRITE_HEXADECIMAL:
1717 Writef(fp, "\t0x%X", satoi(p ->Value));
1718 break;
1719
1720 case WRITE_BINARY:
1721 Writef(fp, "\t0x%B", satoi(p ->Value));
1722 break;
1723
1724 case WRITE_PAIR:
1725 Writef(fp, "\t\"%s,%s\"", p->Subkey, p->Value);
1726 break;
1727
1728 default: SynError(it8, "Unknown write mode %d", p ->WriteAs);
1729 return;
1730 }
1731 }
1732
1733 WriteStr (fp, "\n");
1734 }
1735
1736}
1737
1738
1739// Writes the data format
1740static
1741void WriteDataFormat(SAVESTREAM* fp, cmsIT8* it8)
1742{
1743 int i, nSamples;
1744 TABLE* t = GetTable(it8);
1745
1746 if (!t -> DataFormat) return;
1747
1748 WriteStr(fp, "BEGIN_DATA_FORMAT\n");
1749 WriteStr(fp, " ");
1750 nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
1751
1752 for (i = 0; i < nSamples; i++) {
1753
1754 WriteStr(fp, t->DataFormat[i]);
1755 WriteStr(fp, ((i == (nSamples-1)) ? "\n" : "\t"));
1756 }
1757
1758 WriteStr (fp, "END_DATA_FORMAT\n");
1759}
1760
1761
1762// Writes data array
1763static
1764void WriteData(SAVESTREAM* fp, cmsIT8* it8)
1765{
1766 int i, j;
1767 TABLE* t = GetTable(it8);
1768
1769 if (!t->Data) return;
1770
1771 WriteStr (fp, "BEGIN_DATA\n");
1772
1773 t->nPatches = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
1774
1775 for (i = 0; i < t-> nPatches; i++) {
1776
1777 WriteStr(fp, " ");
1778
1779 for (j = 0; j < t->nSamples; j++) {
1780
1781 char *ptr = t->Data[i*t->nSamples+j];
1782
1783 if (ptr == NULL((void*)0)) WriteStr(fp, "\"\"");
1784 else {
1785 // If value contains whitespace, enclose within quote
1786
1787 if (strchr(ptr, ' ') != NULL((void*)0)) {
1788
1789 WriteStr(fp, "\"");
1790 WriteStr(fp, ptr);
1791 WriteStr(fp, "\"");
1792 }
1793 else
1794 WriteStr(fp, ptr);
1795 }
1796
1797 WriteStr(fp, ((j == (t->nSamples-1)) ? "\n" : "\t"));
1798 }
1799 }
1800 WriteStr (fp, "END_DATA\n");
1801}
1802
1803
1804
1805// Saves whole file
1806cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName)
1807{
1808 SAVESTREAM sd;
1809 cmsUInt32Number i;
1810 cmsIT8* it8 = (cmsIT8*) hIT8;
1811
1812 memset(&sd, 0, sizeof(sd));
1813
1814 sd.stream = fopen(cFileName, "wt");
1815 if (!sd.stream) return FALSE0;
1816
1817 for (i=0; i < it8 ->TablesCount; i++) {
1818
1819 cmsIT8SetTable(hIT8, i);
1820 WriteHeader(it8, &sd);
1821 WriteDataFormat(&sd, it8);
1822 WriteData(&sd, it8);
1823 }
1824
1825 if (fclose(sd.stream) != 0) return FALSE0;
1826
1827 return TRUE1;
1828}
1829
1830
1831// Saves to memory
1832cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* BytesNeeded)
1833{
1834 SAVESTREAM sd;
1835 cmsUInt32Number i;
1836 cmsIT8* it8 = (cmsIT8*) hIT8;
1837
1838 memset(&sd, 0, sizeof(sd));
1839
1840 sd.stream = NULL((void*)0);
1841 sd.Base = (cmsUInt8Number*) MemPtr;
1842 sd.Ptr = sd.Base;
1843
1844 sd.Used = 0;
1845
1846 if (sd.Base)
1847 sd.Max = *BytesNeeded; // Write to memory?
1848 else
1849 sd.Max = 0; // Just counting the needed bytes
1850
1851 for (i=0; i < it8 ->TablesCount; i++) {
1852
1853 cmsIT8SetTable(hIT8, i);
1854 WriteHeader(it8, &sd);
1855 WriteDataFormat(&sd, it8);
1856 WriteData(&sd, it8);
1857 }
1858
1859 sd.Used++; // The \0 at the very end
1860
1861 if (sd.Base)
1862 *sd.Ptr = 0;
1863
1864 *BytesNeeded = sd.Used;
1865
1866 return TRUE1;
1867}
1868
1869
1870// -------------------------------------------------------------- Higher level parsing
1871
1872static
1873cmsBool DataFormatSection(cmsIT8* it8)
1874{
1875 int iField = 0;
1876 TABLE* t = GetTable(it8);
1877
1878 InSymbol(it8); // Eats "BEGIN_DATA_FORMAT"
1879 CheckEOLN(it8);
1880
1881 while (it8->sy != SEND_DATA_FORMAT &&
1882 it8->sy != SEOLN &&
1883 it8->sy != SEOF &&
1884 it8->sy != SSYNERROR) {
1885
1886 if (it8->sy != SIDENT) {
1887
1888 return SynError(it8, "Sample type expected");
1889 }
1890
1891 if (!SetDataFormat(it8, iField, it8->id)) return FALSE0;
1892 iField++;
1893
1894 InSymbol(it8);
1895 SkipEOLN(it8);
1896 }
1897
1898 SkipEOLN(it8);
1899 Skip(it8, SEND_DATA_FORMAT);
1900 SkipEOLN(it8);
1901
1902 if (iField != t ->nSamples) {
1903 SynError(it8, "Count mismatch. NUMBER_OF_FIELDS was %d, found %d\n", t ->nSamples, iField);
1904
1905
1906 }
1907
1908 return TRUE1;
1909}
1910
1911
1912
1913static
1914cmsBool DataSection (cmsIT8* it8)
1915{
1916 int iField = 0;
1917 int iSet = 0;
1918 char Buffer[256];
1919 TABLE* t = GetTable(it8);
1920
1921 InSymbol(it8); // Eats "BEGIN_DATA"
1922 CheckEOLN(it8);
1923
1924 if (!t->Data)
1925 AllocateDataSet(it8);
1926
1927 while (it8->sy != SEND_DATA && it8->sy != SEOF)
1928 {
1929 if (iField >= t -> nSamples) {
1930 iField = 0;
1931 iSet++;
1932
1933 }
1934
1935 if (it8->sy != SEND_DATA && it8->sy != SEOF) {
1936
1937 if (!GetVal(it8, Buffer, 255, "Sample data expected"))
1938 return FALSE0;
1939
1940 if (!SetData(it8, iSet, iField, Buffer))
1941 return FALSE0;
1942
1943 iField++;
1944
1945 InSymbol(it8);
1946 SkipEOLN(it8);
1947 }
1948 }
1949
1950 SkipEOLN(it8);
1951 Skip(it8, SEND_DATA);
1952 SkipEOLN(it8);
1953
1954 // Check for data completion.
1955
1956 if ((iSet+1) != t -> nPatches)
1957 return SynError(it8, "Count mismatch. NUMBER_OF_SETS was %d, found %d\n", t ->nPatches, iSet+1);
1958
1959 return TRUE1;
1960}
1961
1962
1963
1964
1965static
1966cmsBool HeaderSection(cmsIT8* it8)
1967{
1968 char VarName[MAXID128];
1969 char Buffer[MAXSTR1024];
1970 KEYVALUE* Key;
1971
1972 while (it8->sy != SEOF &&
1973 it8->sy != SSYNERROR &&
1974 it8->sy != SBEGIN_DATA_FORMAT &&
1975 it8->sy != SBEGIN_DATA) {
1976
1977
1978 switch (it8 -> sy) {
1979
1980 case SKEYWORD:
1981 InSymbol(it8);
1982 if (!GetVal(it8, Buffer, MAXSTR1024-1, "Keyword expected")) return FALSE0;
1983 if (!AddAvailableProperty(it8, Buffer, WRITE_UNCOOKED)) return FALSE0;
1984 InSymbol(it8);
1985 break;
1986
1987
1988 case SDATA_FORMAT_ID:
1989 InSymbol(it8);
1990 if (!GetVal(it8, Buffer, MAXSTR1024-1, "Keyword expected")) return FALSE0;
1991 if (!AddAvailableSampleID(it8, Buffer)) return FALSE0;
1992 InSymbol(it8);
1993 break;
1994
1995
1996 case SIDENT:
1997 strncpy(VarName, it8->id, MAXID128 - 1);
1998 VarName[MAXID128 - 1] = 0;
1999
2000 if (!IsAvailableOnList(it8->ValidKeywords, VarName, NULL((void*)0), &Key)) {
2001
2002#ifdef CMS_STRICT_CGATS
2003 return SynError(it8, "Undefined keyword '%s'", VarName);
2004#else
2005 Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED);
2006 if (Key == NULL((void*)0)) return FALSE0;
2007#endif
2008 }
2009
2010 InSymbol(it8);
2011 if (!GetVal(it8, Buffer, MAXSTR1024 - 1, "Property data expected")) return FALSE0;
2012
2013 if (Key->WriteAs != WRITE_PAIR) {
2014 AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL((void*)0), Buffer,
2015 (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
2016 }
2017 else {
2018 const char *Subkey;
2019 char *Nextkey;
2020 if (it8->sy != SSTRING)
2021 return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName);
2022
2023 // chop the string as a list of "subkey, value" pairs, using ';' as a separator
2024 for (Subkey = Buffer; Subkey != NULL((void*)0); Subkey = Nextkey)
2025 {
2026 char *Value, *temp;
2027
2028 // identify token pair boundary
2029 Nextkey = (char*)strchr(Subkey, ';');
2030 if (Nextkey)
2031 *Nextkey++ = '\0';
2032
2033 // for each pair, split the subkey and the value
2034 Value = (char*)strrchr(Subkey, ',');
2035 if (Value == NULL((void*)0))
2036 return SynError(it8, "Invalid value for property '%s'.", VarName);
2037
2038 // gobble the spaces before the coma, and the coma itself
2039 temp = Value++;
2040 do *temp-- = '\0'; while (temp >= Subkey && *temp == ' ');
2041
2042 // gobble any space at the right
2043 temp = Value + strlen(Value) - 1;
2044 while (*temp == ' ') *temp-- = '\0';
2045
2046 // trim the strings from the left
2047 Subkey += strspn(Subkey, " ");
2048 Value += strspn(Value, " ");
2049
2050 if (Subkey[0] == 0 || Value[0] == 0)
2051 return SynError(it8, "Invalid value for property '%s'.", VarName);
2052 AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR);
2053 }
2054 }
2055
2056 InSymbol(it8);
2057 break;
2058
2059
2060 case SEOLN: break;
2061
2062 default:
2063 return SynError(it8, "expected keyword or identifier");
2064 }
2065
2066 SkipEOLN(it8);
2067 }
2068
2069 return TRUE1;
2070
2071}
2072
2073
2074static
2075void ReadType(cmsIT8* it8, char* SheetTypePtr)
2076{
2077 cmsInt32Number cnt = 0;
2078
2079 // First line is a very special case.
2080
2081 while (isseparator(it8->ch))
2082 NextCh(it8);
2083
2084 while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != 0) {
2085
2086 if (cnt++ < MAXSTR1024)
2087 *SheetTypePtr++= (char) it8 ->ch;
2088 NextCh(it8);
2089 }
2090
2091 *SheetTypePtr = 0;
2092}
2093
2094
2095static
2096cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
2097{
2098 char* SheetTypePtr = it8 ->Tab[0].SheetType;
2099
2100 if (nosheet == 0) {
2101 ReadType(it8, SheetTypePtr);
2102 }
2103
2104 InSymbol(it8);
2105
2106 SkipEOLN(it8);
2107
2108 while (it8-> sy != SEOF &&
2109 it8-> sy != SSYNERROR) {
2110
2111 switch (it8 -> sy) {
2112
2113 case SBEGIN_DATA_FORMAT:
2114 if (!DataFormatSection(it8)) return FALSE0;
2115 break;
2116
2117 case SBEGIN_DATA:
2118
2119 if (!DataSection(it8)) return FALSE0;
2120
2121 if (it8 -> sy != SEOF) {
2122
2123 AllocTable(it8);
2124 it8 ->nTable = it8 ->TablesCount - 1;
2125
2126 // Read sheet type if present. We only support identifier and string.
2127 // <ident> <eoln> is a type string
2128 // anything else, is not a type string
2129 if (nosheet == 0) {
2130
2131 if (it8 ->sy == SIDENT) {
2132
2133 // May be a type sheet or may be a prop value statement. We cannot use insymbol in
2134 // this special case...
2135 while (isseparator(it8->ch))
2136 NextCh(it8);
2137
2138 // If a newline is found, then this is a type string
2139 if (it8 ->ch == '\n' || it8->ch == '\r') {
2140
2141 cmsIT8SetSheetType(it8, it8 ->id);
2142 InSymbol(it8);
2143 }
2144 else
2145 {
2146 // It is not. Just continue
2147 cmsIT8SetSheetType(it8, "");
2148 }
2149 }
2150 else
2151 // Validate quoted strings
2152 if (it8 ->sy == SSTRING) {
2153 cmsIT8SetSheetType(it8, it8 ->str);
2154 InSymbol(it8);
2155 }
2156 }
2157
2158 }
2159 break;
2160
2161 case SEOLN:
2162 SkipEOLN(it8);
2163 break;
2164
2165 default:
2166 if (!HeaderSection(it8)) return FALSE0;
2167 }
2168
2169 }
2170
2171 return (it8 -> sy != SSYNERROR);
2172}
2173
2174
2175
2176// Init useful pointers
2177
2178static
2179void CookPointers(cmsIT8* it8)
2180{
2181 int idField, i;
2182 char* Fld;
2183 cmsUInt32Number j;
2184 cmsUInt32Number nOldTable = it8 ->nTable;
2185
2186 for (j=0; j < it8 ->TablesCount; j++) {
2187
2188 TABLE* t = it8 ->Tab + j;
2189
2190 t -> SampleID = 0;
2191 it8 ->nTable = j;
2192
2193 for (idField = 0; idField < t -> nSamples; idField++)
2194 {
2195 if (t ->DataFormat == NULL((void*)0)){
2196 SynError(it8, "Undefined DATA_FORMAT");
2197 return;
2198 }
2199
2200 Fld = t->DataFormat[idField];
2201 if (!Fld) continue;
2202
2203
2204 if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) {
2205
2206 t -> SampleID = idField;
2207 }
2208
2209 // "LABEL" is an extension. It keeps references to forward tables
2210
2211 if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$') {
2212
2213 // Search for table references...
2214 for (i = 0; i < t->nPatches; i++) {
2215
2216 char* Label = GetData(it8, i, idField);
2217
2218 if (Label) {
2219
2220 cmsUInt32Number k;
2221
2222 // This is the label, search for a table containing
2223 // this property
2224
2225 for (k = 0; k < it8->TablesCount; k++) {
2226
2227 TABLE* Table = it8->Tab + k;
2228 KEYVALUE* p;
2229
2230 if (IsAvailableOnList(Table->HeaderList, Label, NULL((void*)0), &p)) {
2231
2232 // Available, keep type and table
2233 char Buffer[256];
2234
2235 char* Type = p->Value;
2236 int nTable = (int)k;
2237
2238 snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type)__builtin___snprintf_chk (Buffer, 255, 2 - 1, __builtin_object_size
(Buffer, 2 > 1), "%s %d %s", Label, nTable, Type)
;
2239
2240 SetData(it8, i, idField, Buffer);
2241 }
2242 }
2243
2244
2245 }
2246
2247 }
2248
2249
2250 }
2251
2252 }
2253 }
2254
2255 it8 ->nTable = nOldTable;
2256}
2257
2258// Try to infere if the file is a CGATS/IT8 file at all. Read first line
2259// that should be something like some printable characters plus a \n
2260// returns 0 if this is not like a CGATS, or an integer otherwise. This integer is the number of words in first line?
2261static
2262int IsMyBlock(const cmsUInt8Number* Buffer, cmsUInt32Number n)
2263{
2264 int words = 1, space = 0, quot = 0;
2265 cmsUInt32Number i;
2266
2267 if (n < 10) return 0; // Too small
2268
2269 if (n > 132)
2270 n = 132;
2271
2272 for (i = 1; i < n; i++) {
2273
2274 switch(Buffer[i])
2275 {
2276 case '\n':
2277 case '\r':
2278 return ((quot == 1) || (words > 2)) ? 0 : words;
2279 case '\t':
2280 case ' ':
2281 if(!quot && !space)
2282 space = 1;
2283 break;
2284 case '\"':
2285 quot = !quot;
2286 break;
2287 default:
2288 if (Buffer[i] < 32) return 0;
2289 if (Buffer[i] > 127) return 0;
2290 words += space;
2291 space = 0;
2292 break;
2293 }
2294 }
2295
2296 return 0;
2297}
2298
2299
2300static
2301cmsBool IsMyFile(const char* FileName)
2302{
2303 FILE *fp;
2304 cmsUInt32Number Size;
2305 cmsUInt8Number Ptr[133];
2306
2307 fp = fopen(FileName, "rt");
2308 if (!fp) {
2309 cmsSignalError(0, cmsERROR_FILE1, "File '%s' not found", FileName);
2310 return FALSE0;
2311 }
2312
2313 Size = (cmsUInt32Number) fread(Ptr, 1, 132, fp);
2314
2315 if (fclose(fp) != 0)
2316 return FALSE0;
2317
2318 Ptr[Size] = '\0';
2319
2320 return IsMyBlock(Ptr, Size);
2321}
2322
2323// ---------------------------------------------------------- Exported routines
2324
2325
2326cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, const void *Ptr, cmsUInt32Number len)
2327{
2328 cmsHANDLE hIT8;
2329 cmsIT8* it8;
2330 int type;
2331
2332 _cmsAssert(Ptr != NULL)(((Ptr != ((void*)0))) ? (void) (0) : __assert_fail ("(Ptr != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2332, __extension__ __PRETTY_FUNCTION__))
;
2333 _cmsAssert(len != 0)(((len != 0)) ? (void) (0) : __assert_fail ("(len != 0)", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2333, __extension__ __PRETTY_FUNCTION__))
;
2334
2335 type = IsMyBlock((const cmsUInt8Number*)Ptr, len);
2336 if (type == 0) return NULL((void*)0);
2337
2338 hIT8 = cmsIT8Alloc(ContextID);
2339 if (!hIT8) return NULL((void*)0);
2340
2341 it8 = (cmsIT8*) hIT8;
2342 it8 ->MemoryBlock = (char*) _cmsMalloc(ContextID, len + 1);
2343 if (it8->MemoryBlock == NULL((void*)0))
2344 {
2345 cmsIT8Free(hIT8);
2346 return FALSE0;
2347 }
2348
2349 strncpy(it8 ->MemoryBlock, (const char*) Ptr, len);
2350 it8 ->MemoryBlock[len] = 0;
2351
2352 strncpy(it8->FileStack[0]->FileName, "", cmsMAX_PATH256-1);
2353 it8-> Source = it8 -> MemoryBlock;
2354
2355 if (!ParseIT8(it8, type-1)) {
2356
2357 cmsIT8Free(hIT8);
2358 return FALSE0;
2359 }
2360
2361 CookPointers(it8);
2362 it8 ->nTable = 0;
2363
2364 _cmsFree(ContextID, it8->MemoryBlock);
2365 it8 -> MemoryBlock = NULL((void*)0);
2366
2367 return hIT8;
2368
2369
2370}
2371
2372
2373cmsHANDLE CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileName)
2374{
2375
2376 cmsHANDLE hIT8;
2377 cmsIT8* it8;
2378 int type;
2379
2380 _cmsAssert(cFileName != NULL)(((cFileName != ((void*)0))) ? (void) (0) : __assert_fail ("(cFileName != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2380, __extension__ __PRETTY_FUNCTION__))
;
2381
2382 type = IsMyFile(cFileName);
2383 if (type == 0) return NULL((void*)0);
2384
2385 hIT8 = cmsIT8Alloc(ContextID);
2386 it8 = (cmsIT8*) hIT8;
2387 if (!hIT8) return NULL((void*)0);
2388
2389
2390 it8 ->FileStack[0]->Stream = fopen(cFileName, "rt");
2391
2392 if (!it8 ->FileStack[0]->Stream) {
2393 cmsIT8Free(hIT8);
2394 return NULL((void*)0);
2395 }
2396
2397
2398 strncpy(it8->FileStack[0]->FileName, cFileName, cmsMAX_PATH256-1);
2399 it8->FileStack[0]->FileName[cmsMAX_PATH256-1] = 0;
2400
2401 if (!ParseIT8(it8, type-1)) {
2402
2403 fclose(it8 ->FileStack[0]->Stream);
2404 cmsIT8Free(hIT8);
2405 return NULL((void*)0);
2406 }
2407
2408 CookPointers(it8);
2409 it8 ->nTable = 0;
2410
2411 if (fclose(it8 ->FileStack[0]->Stream)!= 0) {
2412 cmsIT8Free(hIT8);
2413 return NULL((void*)0);
2414 }
2415
2416 return hIT8;
2417
2418}
2419
2420int CMSEXPORT cmsIT8EnumDataFormat(cmsHANDLE hIT8, char ***SampleNames)
2421{
2422 cmsIT8* it8 = (cmsIT8*) hIT8;
2423 TABLE* t;
2424
2425 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2425, __extension__ __PRETTY_FUNCTION__))
;
2426
2427 t = GetTable(it8);
2428
2429 if (SampleNames)
2430 *SampleNames = t -> DataFormat;
2431 return t -> nSamples;
2432}
2433
2434
2435cmsUInt32Number CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyNames)
2436{
2437 cmsIT8* it8 = (cmsIT8*) hIT8;
2438 KEYVALUE* p;
2439 cmsUInt32Number n;
2440 char **Props;
2441 TABLE* t;
2442
2443 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2443, __extension__ __PRETTY_FUNCTION__))
;
2444
2445 t = GetTable(it8);
2446
2447 // Pass#1 - count properties
2448
2449 n = 0;
2450 for (p = t -> HeaderList; p != NULL((void*)0); p = p->Next) {
2451 n++;
2452 }
2453
2454
2455 Props = (char **) AllocChunk(it8, sizeof(char *) * n);
2456
2457 // Pass#2 - Fill pointers
2458 n = 0;
2459 for (p = t -> HeaderList; p != NULL((void*)0); p = p->Next) {
2460 Props[n++] = p -> Keyword;
2461 }
2462
2463 *PropertyNames = Props;
2464 return n;
2465}
2466
2467cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cProp, const char ***SubpropertyNames)
2468{
2469 cmsIT8* it8 = (cmsIT8*) hIT8;
2470 KEYVALUE *p, *tmp;
2471 cmsUInt32Number n;
2472 const char **Props;
2473 TABLE* t;
2474
2475 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2475, __extension__ __PRETTY_FUNCTION__))
;
2476
2477
2478 t = GetTable(it8);
2479
2480 if(!IsAvailableOnList(t->HeaderList, cProp, NULL((void*)0), &p)) {
2481 *SubpropertyNames = 0;
2482 return 0;
2483 }
2484
2485 // Pass#1 - count properties
2486
2487 n = 0;
2488 for (tmp = p; tmp != NULL((void*)0); tmp = tmp->NextSubkey) {
2489 if(tmp->Subkey != NULL((void*)0))
2490 n++;
2491 }
2492
2493
2494 Props = (const char **) AllocChunk(it8, sizeof(char *) * n);
2495
2496 // Pass#2 - Fill pointers
2497 n = 0;
2498 for (tmp = p; tmp != NULL((void*)0); tmp = tmp->NextSubkey) {
2499 if(tmp->Subkey != NULL((void*)0))
2500 Props[n++] = p ->Subkey;
2501 }
2502
2503 *SubpropertyNames = Props;
2504 return n;
2505}
2506
2507static
2508int LocatePatch(cmsIT8* it8, const char* cPatch)
2509{
2510 int i;
2511 const char *data;
2512 TABLE* t = GetTable(it8);
2513
2514 for (i=0; i < t-> nPatches; i++) {
2515
2516 data = GetData(it8, i, t->SampleID);
2517
2518 if (data != NULL((void*)0)) {
2519
2520 if (cmsstrcasecmp(data, cPatch) == 0)
2521 return i;
2522 }
2523 }
2524
2525 // SynError(it8, "Couldn't find patch '%s'\n", cPatch);
2526 return -1;
2527}
2528
2529
2530static
2531int LocateEmptyPatch(cmsIT8* it8)
2532{
2533 int i;
2534 const char *data;
2535 TABLE* t = GetTable(it8);
2536
2537 for (i=0; i < t-> nPatches; i++) {
2538
2539 data = GetData(it8, i, t->SampleID);
2540
2541 if (data == NULL((void*)0))
2542 return i;
2543
2544 }
2545
2546 return -1;
2547}
2548
2549static
2550int LocateSample(cmsIT8* it8, const char* cSample)
2551{
2552 int i;
2553 const char *fld;
2554 TABLE* t = GetTable(it8);
2555
2556 for (i=0; i < t->nSamples; i++) {
2557
2558 fld = GetDataFormat(it8, i);
2559 if (fld != NULL((void*)0)) {
2560 if (cmsstrcasecmp(fld, cSample) == 0)
2561 return i;
2562 }
2563 }
2564
2565 return -1;
2566
2567}
2568
2569
2570int CMSEXPORT cmsIT8FindDataFormat(cmsHANDLE hIT8, const char* cSample)
2571{
2572 cmsIT8* it8 = (cmsIT8*) hIT8;
2573
2574 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2574, __extension__ __PRETTY_FUNCTION__))
;
2575
2576 return LocateSample(it8, cSample);
2577}
2578
2579
2580
2581const char* CMSEXPORT cmsIT8GetDataRowCol(cmsHANDLE hIT8, int row, int col)
2582{
2583 cmsIT8* it8 = (cmsIT8*) hIT8;
2584
2585 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2585, __extension__ __PRETTY_FUNCTION__))
;
2586
2587 return GetData(it8, row, col);
2588}
2589
2590
2591cmsFloat64Number CMSEXPORT cmsIT8GetDataRowColDbl(cmsHANDLE hIT8, int row, int col)
2592{
2593 const char* Buffer;
2594
2595 Buffer = cmsIT8GetDataRowCol(hIT8, row, col);
2596
2597 if (Buffer == NULL((void*)0)) return 0.0;
2598
2599 return ParseFloatNumber(Buffer);
2600}
2601
2602
2603cmsBool CMSEXPORT cmsIT8SetDataRowCol(cmsHANDLE hIT8, int row, int col, const char* Val)
2604{
2605 cmsIT8* it8 = (cmsIT8*) hIT8;
2606
2607 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2607, __extension__ __PRETTY_FUNCTION__))
;
2608
2609 return SetData(it8, row, col, Val);
2610}
2611
2612
2613cmsBool CMSEXPORT cmsIT8SetDataRowColDbl(cmsHANDLE hIT8, int row, int col, cmsFloat64Number Val)
2614{
2615 cmsIT8* it8 = (cmsIT8*) hIT8;
2616 char Buff[256];
2617
2618 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2618, __extension__ __PRETTY_FUNCTION__))
;
2619
2620 snprintf(Buff, 255, it8->DoubleFormatter, Val)__builtin___snprintf_chk (Buff, 255, 2 - 1, __builtin_object_size
(Buff, 2 > 1), it8->DoubleFormatter, Val)
;
2621
2622 return SetData(it8, row, col, Buff);
2623}
2624
2625
2626
2627const char* CMSEXPORT cmsIT8GetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample)
2628{
2629 cmsIT8* it8 = (cmsIT8*) hIT8;
2630 int iField, iSet;
2631
2632 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2632, __extension__ __PRETTY_FUNCTION__))
;
2633
2634 iField = LocateSample(it8, cSample);
2635 if (iField < 0) {
2636 return NULL((void*)0);
2637 }
2638
2639 iSet = LocatePatch(it8, cPatch);
2640 if (iSet < 0) {
2641 return NULL((void*)0);
2642 }
2643
2644 return GetData(it8, iSet, iField);
2645}
2646
2647
2648cmsFloat64Number CMSEXPORT cmsIT8GetDataDbl(cmsHANDLE it8, const char* cPatch, const char* cSample)
2649{
2650 const char* Buffer;
2651
2652 Buffer = cmsIT8GetData(it8, cPatch, cSample);
2653
2654 return ParseFloatNumber(Buffer);
2655}
2656
2657
2658
2659cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample, const char *Val)
2660{
2661 cmsIT8* it8 = (cmsIT8*) hIT8;
2662 int iField, iSet;
2663 TABLE* t;
2664
2665 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2665, __extension__ __PRETTY_FUNCTION__))
;
2666
2667 t = GetTable(it8);
2668
2669 iField = LocateSample(it8, cSample);
2670
2671 if (iField < 0)
2672 return FALSE0;
2673
2674 if (t-> nPatches == 0) {
2675
2676 AllocateDataFormat(it8);
2677 AllocateDataSet(it8);
2678 CookPointers(it8);
2679 }
2680
2681 if (cmsstrcasecmp(cSample, "SAMPLE_ID") == 0) {
2682
2683 iSet = LocateEmptyPatch(it8);
2684 if (iSet < 0) {
2685 return SynError(it8, "Couldn't add more patches '%s'\n", cPatch);
2686 }
2687
2688 iField = t -> SampleID;
2689 }
2690 else {
2691 iSet = LocatePatch(it8, cPatch);
2692 if (iSet < 0) {
2693 return FALSE0;
2694 }
2695 }
2696
2697 return SetData(it8, iSet, iField, Val);
2698}
2699
2700
2701cmsBool CMSEXPORT cmsIT8SetDataDbl(cmsHANDLE hIT8, const char* cPatch,
2702 const char* cSample,
2703 cmsFloat64Number Val)
2704{
2705 cmsIT8* it8 = (cmsIT8*) hIT8;
2706 char Buff[256];
2707
2708 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2708, __extension__ __PRETTY_FUNCTION__))
;
2709
2710 snprintf(Buff, 255, it8->DoubleFormatter, Val)__builtin___snprintf_chk (Buff, 255, 2 - 1, __builtin_object_size
(Buff, 2 > 1), it8->DoubleFormatter, Val)
;
2711 return cmsIT8SetData(hIT8, cPatch, cSample, Buff);
2712}
2713
2714// Buffer should get MAXSTR at least
2715
2716const char* CMSEXPORT cmsIT8GetPatchName(cmsHANDLE hIT8, int nPatch, char* buffer)
2717{
2718 cmsIT8* it8 = (cmsIT8*) hIT8;
2719 TABLE* t;
2720 char* Data;
2721
2722 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2722, __extension__ __PRETTY_FUNCTION__))
;
2723
2724 t = GetTable(it8);
2725 Data = GetData(it8, nPatch, t->SampleID);
2726
2727 if (!Data) return NULL((void*)0);
2728 if (!buffer) return Data;
2729
2730 strncpy(buffer, Data, MAXSTR1024-1);
2731 buffer[MAXSTR1024-1] = 0;
2732 return buffer;
2733}
2734
2735int CMSEXPORT cmsIT8GetPatchByName(cmsHANDLE hIT8, const char *cPatch)
2736{
2737 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2737, __extension__ __PRETTY_FUNCTION__))
;
2738
2739 return LocatePatch((cmsIT8*)hIT8, cPatch);
2740}
2741
2742cmsUInt32Number CMSEXPORT cmsIT8TableCount(cmsHANDLE hIT8)
2743{
2744 cmsIT8* it8 = (cmsIT8*) hIT8;
2745
2746 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2746, __extension__ __PRETTY_FUNCTION__))
;
2747
2748 return it8 ->TablesCount;
2749}
2750
2751// This handles the "LABEL" extension.
2752// Label, nTable, Type
2753
2754int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType)
2755{
2756 const char* cLabelFld;
2757 char Type[256], Label[256];
2758 cmsUInt32Number nTable;
2759
2760 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2760, __extension__ __PRETTY_FUNCTION__))
;
2761
2762 if (cField != NULL((void*)0) && *cField == 0)
2763 cField = "LABEL";
2764
2765 if (cField == NULL((void*)0))
2766 cField = "LABEL";
2767
2768 cLabelFld = cmsIT8GetData(hIT8, cSet, cField);
2769 if (!cLabelFld) return -1;
2770
2771 if (sscanf(cLabelFld, "%255s %u %255s", Label, &nTable, Type) != 3)
2772 return -1;
2773
2774 if (ExpectedType != NULL((void*)0) && *ExpectedType == 0)
2775 ExpectedType = NULL((void*)0);
2776
2777 if (ExpectedType) {
2778
2779 if (cmsstrcasecmp(Type, ExpectedType) != 0) return -1;
2780 }
2781
2782 return cmsIT8SetTable(hIT8, nTable);
2783}
2784
2785
2786cmsBool CMSEXPORT cmsIT8SetIndexColumn(cmsHANDLE hIT8, const char* cSample)
2787{
2788 cmsIT8* it8 = (cmsIT8*) hIT8;
2789 int pos;
2790
2791 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2791, __extension__ __PRETTY_FUNCTION__))
;
2792
2793 pos = LocateSample(it8, cSample);
2794 if(pos == -1)
2795 return FALSE0;
2796
2797 it8->Tab[it8->nTable].SampleID = pos;
2798 return TRUE1;
2799}
2800
2801
2802void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter)
2803{
2804 cmsIT8* it8 = (cmsIT8*) hIT8;
2805
2806 _cmsAssert(hIT8 != NULL)(((hIT8 != ((void*)0))) ? (void) (0) : __assert_fail ("(hIT8 != ((void*)0))"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmscgats.c"
, 2806, __extension__ __PRETTY_FUNCTION__))
;
2807
2808 if (Formatter == NULL((void*)0))
2809 strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT"%.10g");
2810 else
2811 strncpy(it8->DoubleFormatter, Formatter, sizeof(it8->DoubleFormatter));
2812
2813 it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0;
2814}
2815