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