1 /*---------------------------------------------------------------------*
2 Project: tc library
3 File: TCScriptFile.cpp
4
5 Copyright 1998-2001 Nintendo. All rights reserved.
6
7 These coded instructions, statements and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 Change History:
14
15 $Log: TCScriptFile.cpp,v $
16 Revision 1.1 2006/02/17 09:01:53 mitu
17 1st version
18
19
20 6 4/11/01 3:08p John
21 Updated header copyrights and pathname.
22
23 5 3/09/01 3:21p John
24 Added better error checking for wrapS and wrapT modes.
25
26 4 3/09/01 2:50p John
27 Modified TCProcessImKey. Added ability to specify wrapS and wrapT mode
28 using TCS script file.
29
30 3 8/10/00 6:03p Mikepc
31
32 2 3/17/00 1:19p Mikepc
33 change tc to use indices numbered from 0.
34
35 1 12/03/99 3:45p Ryan
36
37 20 10/13/99 4:19p Mikepc
38
39 18 10/08/99 2:45p Mikepc
40 update for tplConv portability: altered data structures, replaced
41 references to 'read tga code' with ' *fileFn, removed redundant
42 functions. Changed some file conversion paths.
43
44 17 9/17/99 12:57p Mikepc
45 palette entry format defaults to rgb565
46
47 16 9/17/99 12:21p Mikepc
48 - arbitrary palette size has been removed- changed ReadTplTxtFile() to
49 reject CI4 and CI14_X2 as conversion formats.
50 - palette alpha layer has been removed- changed ProcessPlKey() to
51 default this to 0.
52
53 15 9/16/99 8:47p Mikepc
54 updated code for auto-palette generation
55
56 14 9/13/99 5:03p Mikepc
57 changed ProcessPlKey() to look for palette format RGB565 instead of
58 R5G6B5.
59
60 13 9/09/99 7:02p Mikepc
61 in ProcessImKey, changed 2 conversion format values to match latest
62 gxEnum.h: R5G6B5 to RGB565, and CMP to CMPR
63
64 12 9/02/99 11:12a Mikepc
65 some code re-organization between files.
66 added code (verify.cpp) to invoke s3tc.exe from within tc program.
67 changed some routines to accommodate the new texture creation path.
68
69 11 8/26/99 4:59p Mikepc
70 renamed file extensions from .c to .cpp.
71 .cpp extension allows addition of namespace protection to remove
72 potential name collisions with tool code. Exceptions are CreateTplFile
73 and QuickConvert. These are extern "C" linked.
74
75 10 8/26/99 11:38a Mikepc
76
77 9 8/26/99 11:03a Mikepc
78 tplCon rewrite for efficient memory usage, batch file processing
79 ability.
80
81 $NoKeywords: $
82
83 -----------------------------------------------------------------------*/
84
85 #include <string.h>
86 #include <stdio.h>
87 #include <stdlib.h>
88 #include <ctype.h>
89
90 #include <charPipeline/tc/TCCommon.h>
91
92 #include "TCSrcImageList.h"
93 #include "TCImageList.h"
94 #include "TCPaletteList.h"
95 #include "TCTextureList.h"
96 #include "TCGXDefs.h"
97
98 // path name and ptr for script file keys-
99 // was 'static', made global so it could be cleared
100 // each time for batch processing
101 char PathName[NAME_SIZE]; // stores current file path name
102 char* PathPtr = NULL;
103
104 /*>*******************************(*)*******************************<*/
105 static void TCProcessKeyName( char* lineBuff );
106 static void TCProcessSiKey ( u32 index, char* pathName, char* fileName );
107 static void TCProcessImKey ( u32 index, char* attList );
108 static void TCProcessPlKey ( u32 index, char* attList );
109 static void TCProcessTxKey ( u32 index, char* attList );
110
111 static void TCGetKeyTokens ( char* lineBuff, char* leftSide,
112 char* rightSide );
113
114 static void TCGetKeyNum ( char* srcStr, u32* num );
115 static void TCGetKeyString ( char* srcStr, char* dstStr );
116 static void TCStripBlanks ( char* srcStr, u32 leading, u32 trailing );
117
118 /*>*******************************(*)*******************************<*/
119 // parse an ini-style text file
120 /*>*******************************(*)*******************************<*/
TCReadTplTxtFile(char * fileName)121 void TCReadTplTxtFile ( char* fileName )
122 {
123 FILE* fp;
124 char lineBuff[NAME_SIZE];
125 char* buffPtr;
126
127
128 fp = fopen(fileName, "r");
129 TCAssertMsg( (fp != NULL), "TCReadTplTextFile: couldn't open %s for read\n", fileName );
130
131 // read one line at a time until EOF is reached.
132 // trim leading blanks while reading.
133 while( (buffPtr = fgets(lineBuff, NAME_SIZE, fp)) != NULL )
134 {
135 // ensure that the .txt file line was not greater than (NAME_SIZE-1) characters
136 // if the string is of size (NAME_SIZE-1), check if EOF or a newline was encountered at position 254
137 if( (strlen(lineBuff)) == (NAME_SIZE - 1) )
138 {
139 if( (feof(fp)) == 0 ) // this is not the end of the file
140 {
141 if( lineBuff[ (NAME_SIZE - 2) ] != '\n' ) // fgets should always include a newline at a line's end
142 // except at the end of the file
143 {
144 TCErrorMsg( "TCReadTplTextFile: line exceeded %d characters in '%s'", (NAME_SIZE-1), fileName );
145 }
146 }
147 }
148
149 TCStripBlanks( lineBuff, 1, 1 );
150
151 // identify the line type by its first character
152
153 if( lineBuff[0] == '\0' ) // '\n' after StripBlanks()
154 {
155 continue;
156 }
157
158 else if( lineBuff[0] == ';' ) // start of a comment
159 {
160 continue;
161 }
162
163 else // start of a possible key name
164 {
165 // take action depending on the type of this key
166 TCProcessKeyName(lineBuff);
167 }
168 }
169
170 fclose(fp);
171 }
172
173 /*>*******************************(*)*******************************<*/
174 // check the first few characters of a non-comment line for one of
175 // 'file', 'image', 'palette', 'texture'
176 // leading blanks will already have been stripped out when fgets was
177 // called for lineBuff so keyPtr should point to lineBuff on success
178 //
179 // note: if a key can't be identified, the entire line is ignored
180 //
181 /*>*******************************(*)*******************************<*/
TCProcessKeyName(char * lineBuff)182 static void TCProcessKeyName ( char* lineBuff )
183 {
184 char leftSide[NAME_SIZE], rightSide[NAME_SIZE];
185 char* keyPtr;
186 u32 index;
187
188
189 // split this key into left/right tokens, trim leading/trailing blanks
190 TCGetKeyTokens( lineBuff, leftSide, rightSide);
191
192 // trim blanks and comments from the right side string
193 TCGetKeyString( rightSide, rightSide );
194
195 // convert everything to upper case
196 TCStrToUpper( leftSide );
197 TCStrToUpper( rightSide );
198
199 // determine which key this is and get its number if needed
200
201 if( (keyPtr = strstr( leftSide, "PATH" )) == leftSide ) // path name key
202 {
203
204 // no number component in path key name
205
206 // check for null path name
207 if( ((strcmp(rightSide, "0")) == 0) || ((strcmp(rightSide, "NULL")) == 0) )
208 {
209 PathPtr = NULL;
210 }
211 else // set a new path name
212 {
213 PathPtr = PathName;
214 strcpy( PathPtr, rightSide );
215 }
216 }
217 else if( (keyPtr = strstr( leftSide, "FILE" )) == leftSide ) // source image (file name) key
218 {
219 TCGetKeyNum( (leftSide + strlen("FILE")), &index );
220 TCProcessSiKey( index, PathPtr, rightSide );
221 }
222
223 else if( (keyPtr = strstr( leftSide, "IMAGE" )) == leftSide ) // image key
224 {
225 TCGetKeyNum( (leftSide + strlen("IMAGE")), &index );
226 TCProcessImKey(index, rightSide);
227 }
228 else if( (keyPtr = strstr( leftSide, "PALETTE" )) == leftSide ) // palette key
229 {
230 TCGetKeyNum( (leftSide + strlen("PALETTE")), &index );
231 TCProcessPlKey(index, rightSide);
232 }
233 else if( (keyPtr = strstr( leftSide, "TEXTURE" )) == leftSide ) // texture key
234 {
235 TCGetKeyNum( (leftSide + strlen("TEXTURE")), &index );
236 TCProcessTxKey(index, rightSide);
237 }
238 else
239 {
240 ; // unknown key- treat as a comment and ignore the whole line
241 }
242 }
243
244 /*>*******************************(*)*******************************<*/
245 // fetch source image data using this key as file name.
246 // create a new source image, identify layers, create layer names
247 // based on index and file name
248 /*>*******************************(*)*******************************<*/
TCProcessSiKey(u32 index,char * pathName,char * fileName)249 static void TCProcessSiKey ( u32 index, char* pathName, char* fileName )
250 {
251 char fullName[NAME_SIZE];
252 u32 len;
253 TCSrcImage* newSi;
254
255
256 // 'X'ed out index? ignore this key
257 if( index == TC_UNUSED )
258 {
259 return;
260 }
261
262 TCAssertMsg( (fileName != NULL), "TCProcessSiKey: NULL fileName for file %d\n", index );
263 TCAssertMsg( (*fileName != '\0'), "TCProcessSiKey: NULL fileName for file %d\n", index );
264
265
266 len = 0;
267 if( pathName != NULL )
268 {
269 len = strlen(pathName);
270 }
271
272 len += strlen(fileName);
273 TCAssertMsg( (len <= (NAME_SIZE-1)), "TCProcessSiKey: length of (%s + path) > %d characters\n", (NAME_SIZE-1), fileName );
274
275 // build the source image name from the current path and file name
276 if(pathName)
277 {
278 strcpy(fullName, pathName);
279 strcat(fullName, fileName);
280 }
281 else
282 {
283 strcpy(fullName, fileName);
284 }
285
286 // create a new source image and set its attributes
287 newSi = TCNewSrcImage();
288 TCAssertMsg( (newSi != NULL),"ProcessSiKey: couldn't allocate memory for new source image %d\n", index );
289
290 // set source image attributes
291 // valid source file types depend on user-defined file reading functions
292 // set by InstallFileReadFn() - invalid types will be caught by ReadFile()
293 TCSetSrcImageFromFile( newSi, fullName, index );
294 }
295
296 /*>*******************************(*)*******************************<*/
TCProcessImKey(u32 index,char * attList)297 static void TCProcessImKey( u32 index, char* attList )
298 {
299 TCImage* newIm;
300 char* icPtr = NULL, *iaPtr = NULL, *fmtPtr = NULL;
301 char* minLODPtr = NULL, *maxLODPtr = NULL, *baseLODPtr = NULL;
302 char* wrapSPtr = NULL, *wrapTPtr = NULL;
303 u32 icNum = 0, iaNum = 0, fmt = 0;
304 u32 minLOD = 0, maxLOD = 0, baseLOD = 0;
305 u32 wrapS = 0, wrapT = 0;
306
307
308 // 'X'ed out index? ignore this key
309 if( index == TC_UNUSED )
310 {
311 return;
312 }
313
314 TCAssertMsg( (attList != NULL), "TCProcessImKey: missing attribute list for image %d in script file\n", index );
315 TCAssertMsg( (*attList != '\0'), "TCProcessImKey: missing attribute list for image %d in script file\n", index );
316
317
318 // split the attList string into tokens using commas as separators.
319 // remove whitespace from around tokens.
320 icPtr = strtok( attList, "," );
321 TCAssertMsg( (icPtr != NULL), "ProcessImKey: problem reading color index for image %d in script file\n", index );
322
323 iaPtr = strtok( NULL, "," );
324 TCAssertMsg( (iaPtr != NULL), "ProcessImKey: problem reading alpha index for image %d in script file\n", index );
325
326 fmtPtr = strtok( NULL, "," );
327 TCAssertMsg( (fmtPtr != NULL), "ProcessImKey: problem reading output format for image %d in script file\n", index );
328
329 // mipmap information is optional
330 // if present, there must be 3 more comma-separated values
331 if( (minLODPtr = strtok( NULL, "," )) != 0 )
332 {
333 TCStripBlanks( minLODPtr, 1,1 );
334 if( isdigit( *minLODPtr ) )
335 {
336 // Parse these three arguments as mipmap constants (minLOD, maxLOD, baseLOD)
337 maxLODPtr = strtok( NULL, "," );
338 TCAssertMsg( (maxLODPtr != NULL), "ProcessImKey: problem reading max LOD for image %d in script file\n", index );
339 TCStripBlanks( maxLODPtr, 1,1 );
340 TCAssertMsg( (isdigit( *maxLODPtr )), "ProcessImKey: missing max LOD for image %d (should be a number)\n", index );
341
342 baseLODPtr = strtok( NULL, "," );
343 TCAssertMsg( (baseLODPtr != NULL), "ProcessImKey: problem reading remap base LOD for image %d in script file\n", index );
344 TCStripBlanks( baseLODPtr, 1,1 );
345 TCAssertMsg( (isdigit( *baseLODPtr )), "ProcessImKey: missing base LOD for image %d (should be a number)\n", index );
346
347 // If two more args exist, parse as wrap modes (wrapS, wrapT)
348 if( (wrapSPtr = strtok( NULL, "," )) != 0 )
349 {
350 wrapTPtr = strtok( NULL, "" );
351 TCAssertMsg( (wrapTPtr != NULL), "ProcessImKey: problem reading wrapT mode for image %d in script file\n", index );
352 }
353 }
354 else
355 {
356 // Parse two arguments as wrap modes (wrapS, wrapT)
357 wrapSPtr = minLODPtr;
358 minLODPtr = NULL;
359
360 wrapTPtr = strtok( NULL, "" );
361 TCAssertMsg( (wrapTPtr != NULL), "ProcessImKey: problem reading wrapT mode for image %d in script file\n", index );
362 }
363 }
364
365 // strip whitespace from these tokens
366 TCStripBlanks( icPtr, 1,1 );
367 TCStripBlanks( iaPtr, 1,1 );
368 TCStripBlanks( fmtPtr, 1,1 );
369 TCStripBlanks( wrapSPtr, 1, 1 );
370 TCStripBlanks( wrapTPtr, 1, 1 );
371
372 // set the color and alpha layer indices:
373
374 // color layer index is mandatory
375 TCGetKeyNum ( icPtr, &icNum );
376 TCAssertMsg( (icNum != TC_UNUSED), "TCProcessImKey: invalid color index for image %d in script file\n", index );
377
378 // alpha layer index is optional.
379 // if no alpha layer, iaNum will be set to TC_UNUSED
380 TCGetKeyNum ( iaPtr, &iaNum );
381
382
383 // set the final hw pixel format
384 if( (strcmp(fmtPtr, "I4")) == 0 )
385 fmt = TPL_IMAGE_TEXEL_FMT_I4;
386 else if( (strcmp(fmtPtr, "I8")) == 0 )
387 fmt = TPL_IMAGE_TEXEL_FMT_I8;
388 else if( (strcmp(fmtPtr, "IA4")) == 0 )
389 fmt = TPL_IMAGE_TEXEL_FMT_IA4;
390 else if( (strcmp(fmtPtr, "IA8")) == 0 )
391 fmt = TPL_IMAGE_TEXEL_FMT_IA8;
392
393 else if( (strcmp(fmtPtr, "RGB565")) == 0 )
394 fmt = TPL_IMAGE_TEXEL_FMT_R5G6B5;
395
396 else if( (strcmp(fmtPtr, "RGB5A3")) == 0 )
397 fmt = TPL_IMAGE_TEXEL_FMT_RGB5A3;
398 else if( (strcmp(fmtPtr, "RGBA8")) == 0 )
399 fmt = TPL_IMAGE_TEXEL_FMT_RGBA8;
400
401 else if( (strcmp(fmtPtr, "CI8")) == 0 )
402 fmt = TPL_IMAGE_TEXEL_FMT_CI8;
403
404 //=========================================================================================
405 // note: input palette sizes other than 8-bit/ @256 entry are not supported in this version.
406 // if output palette is CI4, tc will use the low 4-bits of each index.
407 // if output palette is CI14_X2, tc will only create up to 256 'real' entries;
408 // the remaining palette entries will be padded with zeroes.
409
410 else if( (strcmp(fmtPtr, "CI4")) == 0 )
411 fmt = TPL_IMAGE_TEXEL_FMT_CI4;
412 else if( (strcmp(fmtPtr, "CI14_X2")) == 0 )
413 fmt = TPL_IMAGE_TEXEL_FMT_CI14_X2;
414
415 //==========================================================================================
416
417 else if( (strcmp(fmtPtr, "CMPR")) == 0 )
418 fmt = TPL_IMAGE_TEXEL_FMT_CMP;
419
420 else
421 TCErrorMsg( "ProcessImKey: unknown output format '%s' for image %d in script file \n", fmtPtr, index );
422
423
424 // if mipmap numbers are included, get their values
425 if( minLODPtr )
426 minLOD = atoi( minLODPtr );
427 if( maxLODPtr )
428 maxLOD = atoi( maxLODPtr );
429 if( baseLODPtr )
430 baseLOD = atoi( baseLODPtr );
431
432 if( wrapSPtr )
433 {
434 if( (strcmp(wrapSPtr, "GX_REPEAT")) == 0 )
435 wrapS = TPL_WRAP_MODE_REPEAT;
436 else if( (strcmp(wrapSPtr, "GX_CLAMP")) == 0 )
437 wrapS = TPL_WRAP_MODE_CLAMP;
438 else if( (strcmp(wrapSPtr, "GX_MIRROR")) == 0 )
439 wrapS = TPL_WRAP_MODE_MIRROR;
440 else
441 TCErrorMsg( "ProcessImKey: unknown wrapS mode '%s' for image %d in script file \n", wrapSPtr, index );
442 }
443 else
444 {
445 // Wrap mode will be set to defaults in TCWriteTplFile by TCSetFilterModeByDim in TCTPLToolbox.cpp
446 // We have to wait until then since TCSetFilterModeByDim needs information we don't have right now
447 wrapS = TPL_WRAP_MODE_NONE;
448 }
449
450 if( wrapTPtr )
451 {
452 if( (strcmp(wrapTPtr, "GX_REPEAT")) == 0 )
453 wrapT = TPL_WRAP_MODE_REPEAT;
454 else if( (strcmp(wrapTPtr, "GX_CLAMP")) == 0 )
455 wrapT = TPL_WRAP_MODE_CLAMP;
456 else if( (strcmp(wrapTPtr, "GX_MIRROR")) == 0 )
457 wrapT = TPL_WRAP_MODE_MIRROR;
458 else
459 TCErrorMsg( "ProcessImKey: unknown wrapT mode '%s' for image %d in script file \n", wrapTPtr, index );
460 }
461 else
462 {
463 // Wrap mode will be set to defaults in TCWriteTplFile by TCSetFilterModeByDim in TCTPLToolbox.cpp
464 // We have to wait until then since TCSetFilterModeByDim needs information we don't have right now
465 wrapT = TPL_WRAP_MODE_NONE;
466 }
467
468 // create a new Image structure and set its attributes.
469 // 'index' is also used as the final tpl bank location
470 newIm = TCNewImage();
471 TCAssertMsg( (newIm != NULL), "ProcessImKey: couldn't allocate new image %d\n", index );
472
473 // set new image attributes
474 TCSetImageIndex( newIm, index );
475 TCSetImageLayerAtt( newIm, icNum, iaNum );
476 TCSetImageTexelFormat( newIm, fmt );
477 TCSetImageMipMap( newIm, minLOD, maxLOD, baseLOD );
478 TCSetImageWrap( newIm, wrapS, wrapT );
479 }
480
481 /*>*******************************(*)*******************************<*/
TCProcessPlKey(u32 index,char * attList)482 static void TCProcessPlKey ( u32 index, char* attList )
483 {
484 char* psPtr, *fmtPtr;
485 u32 psNum, fmt;
486 TCPalette* newPl;
487
488
489 // 'X'ed out index? ignore this key
490 if( index == TC_UNUSED )
491 {
492 return;
493 }
494
495 TCAssertMsg( (attList != NULL), "TCProcessPlKey: missing attribute list for palette %d in script file\n", index );
496 TCAssertMsg( (*attList != '\0'), "TCProcessPlKey: missing attribute list for palette %d in script file\n", index );
497
498
499 // split the attList string into tokens using commas as separators.
500 // remove whitespace from around tokens.
501 psPtr = strtok( attList, "," );
502 TCAssertMsg( (psPtr != NULL), "ProcessPlKey: problem reading file index for palette %d in script file\n", index );
503
504 fmtPtr = strtok( NULL, "" );
505 TCAssertMsg( (fmtPtr != NULL), "ProcessPlKey: problem reading output format for palette %d in script file\n", index );
506
507
508 // strip whitespace from these tokens
509 TCStripBlanks( psPtr, 1,1 );
510 TCStripBlanks( fmtPtr, 1,1 );
511
512 // set the palette color layer
513 // (color and alpha must come from the same source image)
514 TCGetKeyNum ( psPtr, &psNum );
515 TCAssertMsg( (psNum != TC_UNUSED), "TCProcessPlKey: invalid color index for palette %d in script file\n", index );
516
517 // set the palette entry format
518 // note: IA8 format is not supported yet.
519 if( (strcmp(fmtPtr, "RGB565")) == 0 )
520 {
521 fmt = TPL_PALETTE_ENTRY_FMT_R5G6B5;
522 }
523 else if( (strcmp(fmtPtr, "RGB5A3")) == 0 )
524 {
525 fmt = TPL_PALETTE_ENTRY_FMT_RGB5A3;
526 }
527 else if( (strcmp(fmtPtr, "IA8")) == 0 )
528 {
529 TCErrorMsg( "ProcessPlKey: tc does not support output format '%s'. (palette %d in script file)\n", fmtPtr, index );
530 }
531 else
532 {
533 TCErrorMsg( "ProcessPlKey: unknown output format '%s' for palette %d in script file\n", fmtPtr, index );
534 }
535
536 // create a new Palette structure and set its attributes.
537 // 'index' is also used as the implied bank location
538 newPl = TCNewPalette();
539 TCAssertMsg( (newPl != NULL), "ProcessPlKey: couldn't allocate palette %d\n", index );
540
541 // set palette values
542 TCSetPaletteIndex( newPl, index );
543 TCSetPaletteSrcImage( newPl, psNum );
544 TCSetPaletteEntryFormat( newPl, fmt );
545 }
546
547 /*>*******************************(*)*******************************<*/
TCProcessTxKey(u32 index,char * attList)548 static void TCProcessTxKey ( u32 index, char* attList )
549 {
550 char* imPtr, *plPtr;
551 u32 imNum, plNum;
552 TCTexture* newTx;
553
554
555 // 'X'ed out index? ignore this key
556 if( index == TC_UNUSED )
557 {
558 return;
559 }
560
561 TCAssertMsg( (attList != NULL), "TCProcessTxKey: missing attribute list for texture %d in script file\n", index );
562 TCAssertMsg( (*attList != '\0'), "TCProcessTxKey: missing attribute list for texture %d in script file\n", index );
563
564
565 // split the attList string into tokens using commas as separators.
566 // remove whitespace from around tokens.
567 imPtr = strtok( attList, "," );
568 TCAssertMsg( (imPtr != NULL), "ProcessTxKey: problem reading image index for texture %d in script file\n", index );
569
570 plPtr = strtok( NULL, "," );
571 TCAssertMsg( (plPtr != NULL), "ProcessTxKey: problem reading palette index for texture %d in script file\n", index );
572
573 // strip whitespace from these tokens
574 TCStripBlanks( imPtr, 1,1 );
575 TCStripBlanks( plPtr, 1,1 );
576
577 // image index is mandatory
578 TCGetKeyNum ( imPtr, &imNum );
579 TCAssertMsg( (imNum != TC_UNUSED), "TCProcessTxKey: invalid image index for texture %d in script file\n", index );
580
581 // palette index is optional.
582 // if no palette, plNum will be set to TC_UNUSED
583 TCGetKeyNum ( plPtr, &plNum );
584
585 // create a new Texture structure and set its attributes.
586 // 'index' is also used as the implied bank location
587 newTx = TCNewTexture();
588 TCAssertMsg( (newTx != NULL), "ProcessTxKey(): couldn't allocate new Texture %d\n", index );
589
590 // set texture values
591 TCSetTextureAttributes( newTx, index, imNum, plNum );
592 }
593
594 /*>*******************************(*)*******************************<*/
595 // split lineBuff into two tokens separated by an '=' sign,
596 // strip away any leading/trailing whitespace
597 //
598 // note: while there is guaranteed to be at least a one character
599 // non-whitespace string for leftSide, rightSide may end up
600 // as NULL if no '=' was found. this could happen if the
601 // 'key' was actually just a line of text without a ';' comment
602 // delineator. The problem will be caught by TCProcessKeyName().
603 /*>*******************************(*)*******************************<*/
TCGetKeyTokens(char * lineBuff,char * leftSide,char * rightSide)604 static void TCGetKeyTokens ( char* lineBuff, char* leftSide, char* rightSide )
605 {
606 char* left, *right;
607
608
609 // safety check
610 if( (lineBuff == NULL) || (leftSide == NULL) || (rightSide == NULL) )
611 {
612 return;
613 }
614
615 *leftSide = '\0';
616 *rightSide = '\0';
617
618 if( *lineBuff == '\0')
619 {
620 return;
621 }
622
623 // use the '=' sign as leftSide/rightSide separator
624 if( (left = strtok( lineBuff, "=" )) == 0 )
625 {
626 return;
627 }
628
629 strcpy(leftSide, left);
630 TCStripBlanks( leftSide, 1, 1 );
631
632 if( (right = strtok( NULL, "" )) == 0 )
633 {
634 return;
635 }
636
637 strcpy(rightSide, right);
638 TCStripBlanks( rightSide, 1, 1 );
639 }
640
641 /*>*******************************(*)*******************************<*/
642 // get the string equivalent of the key name ( the 'N' portion of 'keyN')
643 // and place it in dstStr. num will hold the converted result.
644 // note: if *srcStr == TC_BLANK value (TCCommon.h),
645 // *num will be set to TC_UNUSED
646 /*>*******************************(*)*******************************<*/
TCGetKeyNum(char * srcStr,u32 * num)647 static void TCGetKeyNum ( char* srcStr, u32* num )
648 {
649 u32 found = 0;
650 char numStr[10];
651 char* numPtr = NULL;
652 char subStr[NAME_SIZE];
653 char* subPtr = NULL;
654
655
656 // initialize *num
657 *num = TC_UNUSED;
658
659 // safety check
660 if( (srcStr == NULL) || (*srcStr == '\0') ) // no string; return TC_UNUSED
661 {
662 return;
663 }
664
665 strcpy(subStr, srcStr); // if no string left after 'TCStripBlanks,
666 TCStripBlanks(subStr, 1, 1); // while loop will not execute;
667 // return TC_UNUSED
668
669
670 subPtr = subStr; // collect base-10 digits from
671 numPtr = numStr;
672 while( *subPtr != '\0' ) // *subStr to the first non-digit value
673 {
674 if( (isdigit(*subPtr)) != 0 )
675 {
676 found = 1;
677 *numPtr++ = *subPtr++;
678 continue;
679 }
680
681 break; // reached only if *subStr was not a base-10 digit
682 }
683 *numPtr = '\0';
684
685
686 if(found) // number found - convert to int value
687 {
688 *num = (u32)atoi(numStr);
689 }
690 }
691
692 /*>*******************************(*)*******************************<*/
693 // check the right side string for any ';' delineated comments.
694 // leading/trailing blanks have already been stripped
695 //
696 // note: src and dst may be the same address, so a temporary string is used
697 /*>*******************************(*)*******************************<*/
TCGetKeyString(char * srcStr,char * dstStr)698 static void TCGetKeyString( char* srcStr, char* dstStr )
699 {
700 char* name;
701 char tmp[NAME_SIZE];
702 u32 count = 0;
703
704
705 // safety check
706 if( (srcStr == NULL) || (dstStr == NULL) )
707 {
708 return;
709 }
710
711 // srcStr could be an empty string
712 if( *srcStr == '\0')
713 {
714 *dstStr = '\0';
715 return;
716 }
717
718 // strip away any trailing comment- if the whole string was a comment, return.
719 if( (name = strtok(srcStr, ";")) == 0 )
720 {
721 *dstStr = '\0';
722 return;
723 }
724
725 // trim any trailing blanks between the name and any removed comment
726 TCStripBlanks(name, 0, 1 );
727
728 // copy out the modified name
729 count = 0;
730 while( (tmp[count] = name[count]) != '\0' )
731 {
732 count++;
733 }
734 count = 0;
735 while( (dstStr[count] = tmp[count]) != '\0' )
736 {
737 count++;
738 }
739 }
740
741 /*>*******************************(*)*******************************<*/
742 // strip leading and trailing blanks from a string.
743 // if leading or trailing == 1, strip blanks from the indicated end
744 // else if leading or trailing == 0, do not strip blanks from the
745 // indicated end
746 /*>*******************************(*)*******************************<*/
TCStripBlanks(char * srcStr,u32 leading,u32 trailing)747 static void TCStripBlanks ( char* srcStr, u32 leading, u32 trailing )
748 {
749 u32 i, len;
750 char* startPtr, *endPtr;
751 char tmpStr[NAME_SIZE];
752
753
754 if( srcStr == NULL )
755 {
756 return;
757 }
758
759 len = strlen(srcStr);
760 if( (len == 0) || (len > (NAME_SIZE-1)) )
761 {
762 TCErrorMsg( "TCStripBlanks: invalid string length %d for string '%s'\n", srcStr );
763 }
764
765
766 startPtr = srcStr;
767
768 // strip leading blanks
769 if( leading == 1 )
770 {
771 while( (*startPtr != '\0') && ( (isspace(*startPtr)) != 0 ) )
772 {
773 startPtr++;
774 }
775 }
776
777 // strip trailing blanks
778 if( trailing == 1 )
779 {
780 if( *startPtr != '\0')
781 {
782 endPtr = startPtr + (strlen(startPtr)) - 1;
783
784 while( (endPtr >= startPtr) && ((isspace(*endPtr)) != 0) )
785 {
786 endPtr--;
787 }
788
789 endPtr++;
790 *endPtr = '\0';
791 }
792 }
793
794 // replace the original string with the stripped string
795 len = strlen(startPtr);
796 for(i=0; i <= len; i++) // include the '\0'
797 {
798 tmpStr[i] = startPtr[i];
799 }
800 for(i=0; i <= len; i++)
801 {
802 srcStr[i] = tmpStr[i];
803 }
804 }
805
806 /*>*******************************(*)*******************************<*/
807