Browse Source

Merge branch 'master' of klarke.webfactional.com:webapps/git/repos/libcm

master
kevin 10 years ago
parent
commit
6bb138b1ad
10 changed files with 249 additions and 46 deletions
  1. 151
    23
      cmFile.c
  2. 25
    1
      cmFile.h
  3. 9
    9
      cmFileSys.c
  4. 1
    1
      cmFileSys.h
  5. 20
    9
      cmLex.c
  6. 16
    1
      cmMem.c
  7. 1
    1
      cmPgmOpts.c
  8. 1
    1
      cmPgmOpts.h
  9. 20
    0
      cmText.c
  10. 5
    0
      cmText.h

+ 151
- 23
cmFile.c View File

@@ -2,9 +2,13 @@
2 2
 #include "cmGlobal.h"
3 3
 #include "cmRpt.h"
4 4
 #include "cmErr.h"
5
+#include "cmCtx.h"
5 6
 #include "cmFile.h"
7
+#include "cmFileSys.h"
6 8
 #include "cmMem.h"
7 9
 #include "cmMallocDebug.h"
10
+#include "cmLinkedHeap.h"
11
+#include "cmText.h"
8 12
 #include <sys/stat.h>
9 13
 cmFileH_t cmFileNullHandle = { NULL };
10 14
 
@@ -34,9 +38,9 @@ cmFileRC_t _cmFileError( cmFile_t* p, cmFileRC_t rc, int errNumb, const cmChar_t
34 38
 
35 39
 cmFileRC_t cmFileOpen(    cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlags_t flags, cmRpt_t* rpt )
36 40
 {
37
-  char mode[] = "/0/0/0";
38
-  cmFile_t* p = NULL;
39
-  cmErr_t err;
41
+  char mode[]  = "/0/0/0";
42
+  cmFile_t*  p = NULL;
43
+  cmErr_t    err;
40 44
   cmFileRC_t rc;
41 45
 
42 46
   if((rc = cmFileClose(hp)) != kOkFileRC )
@@ -47,21 +51,21 @@ cmFileRC_t cmFileOpen(    cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlag
47 51
   hp->h = NULL;
48 52
 
49 53
   if( cmIsFlag(flags,kReadFileFl) )
50
-    mode[0]='r';
54
+    mode[0] = 'r';
51 55
   else
52 56
     if( cmIsFlag(flags,kWriteFileFl) )
53
-      mode[0]='w';
57
+      mode[0] = 'w';
54 58
     else
55 59
       if( cmIsFlag(flags,kAppendFileFl) )
56
-        mode[0]='a';
60
+        mode[0] = 'a';
57 61
       else
58 62
         cmErrMsg(&err,kInvalidFlagFileRC,"File open flags must contain 'kReadFileFl','kWriteFileFl', or 'kAppendFileFl'.");
59 63
   
60 64
   if( cmIsFlag(flags,kUpdateFileFl) )
61
-    mode[1]='+';
65
+    mode[1] = '+';
62 66
 
63 67
   // handle requests to use stdin,stdout,stderr
64
-  FILE*           sfp = NULL;
68
+  FILE* sfp = NULL;
65 69
   if( cmIsFlag(flags,kStdoutFileFl) )
66 70
   {
67 71
     sfp = stdout;
@@ -107,7 +111,7 @@ cmFileRC_t cmFileOpen(    cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlag
107 111
     }
108 112
   }
109 113
  
110
-  hp->h    = p;
114
+  hp->h = p;
111 115
 
112 116
   return kOkFileRC;
113 117
 }
@@ -158,7 +162,7 @@ cmFileRC_t cmFileWrite(   cmFileH_t h, const void* buf, unsigned bufByteCnt )
158 162
 cmFileRC_t cmFileSeek(    cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByteCnt )
159 163
 {
160 164
   cmFile_t* p = _cmFileHandleToPtr(h);
161
-  unsigned fileflags = 0;
165
+  unsigned  fileflags = 0;
162 166
 
163 167
   if( cmIsFlag(flags,kBeginFileFl) )
164 168
     fileflags = SEEK_SET;
@@ -171,7 +175,7 @@ cmFileRC_t cmFileSeek(    cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByt
171 175
       else
172 176
         return cmErrMsg(&p->err,kInvalidFlagFileRC,"Invalid file seek flag on '%s'.",p->fnStr);
173 177
   
174
-  errno = 0;
178
+  errno  = 0;
175 179
   if( fseek(p->fp,offsByteCnt,fileflags) != 0 )
176 180
     return _cmFileError(p,kSeekFailFileRC,errno,"File seek failed");
177 181
 
@@ -181,9 +185,10 @@ cmFileRC_t cmFileSeek(    cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByt
181 185
 cmFileRC_t cmFileTell( cmFileH_t h, long* offsPtr )
182 186
 {
183 187
   assert( offsPtr != NULL );
184
-  *offsPtr     = -1;
185
-  cmFile_t* p  = _cmFileHandleToPtr(h);
186
-  errno        = 0;
188
+  *offsPtr    = -1;
189
+  cmFile_t* p = _cmFileHandleToPtr(h);
190
+  errno       = 0;
191
+
187 192
   if((*offsPtr = ftell(p->fp)) == -1)
188 193
     return _cmFileError(p,kTellFailFileRC,errno,"File tell failed");
189 194
   return kOkFileRC;
@@ -222,7 +227,8 @@ cmFileRC_t   cmFileByteCountFn( const cmChar_t* fn, cmRpt_t* rpt, unsigned* file
222 227
 {
223 228
   assert( fileByteCntPtr != NULL );
224 229
   cmFileRC_t rc;
225
-  cmFileH_t h = cmFileNullHandle;
230
+  cmFileH_t  h = cmFileNullHandle;
231
+
226 232
   if((rc = cmFileOpen(&h,fn,kReadFileFl,rpt)) != kOkFileRC )
227 233
     return rc;
228 234
 
@@ -241,8 +247,8 @@ cmFileRC_t cmFileCompare( const cmChar_t* fn0, const cmChar_t* fn1, cmRpt_t* rpt
241 247
   cmFileH_t  h0         = cmFileNullHandle;
242 248
   cmFileH_t  h1         = cmFileNullHandle;
243 249
 
244
-  char       b0[ bufByteCnt ];
245
-  char       b1[ bufByteCnt ];
250
+  char b0[ bufByteCnt ];
251
+  char b1[ bufByteCnt ];
246 252
 
247 253
   assert(isEqualPtr != NULL );
248 254
   *isEqualPtr = true;
@@ -253,14 +259,14 @@ cmFileRC_t cmFileCompare( const cmChar_t* fn0, const cmChar_t* fn1, cmRpt_t* rpt
253 259
   if((rc = cmFileOpen(&h1,fn1,kReadFileFl,rpt)) != kOkFileRC )
254 260
     goto errLabel;
255 261
 
256
-  cmFile_t*   p0 = _cmFileHandleToPtr(h0);
257
-  cmFile_t*   p1 = _cmFileHandleToPtr(h1);
262
+  cmFile_t* p0 = _cmFileHandleToPtr(h0);
263
+  cmFile_t* p1 = _cmFileHandleToPtr(h1);
258 264
 
259 265
   while(1)
260 266
   {
261 267
     size_t n0 = fread(b0,1,bufByteCnt,p0->fp);
262 268
     size_t n1 = fread(b1,1,bufByteCnt,p1->fp);
263
-    if( n0 != n1 || memcmp(b0,b1,n0)!=0 )
269
+    if( n0 != n1 || memcmp(b0,b1,n0) != 0 )
264 270
     {
265 271
       *isEqualPtr = false;
266 272
       break;
@@ -285,7 +291,7 @@ const cmChar_t* cmFileName( cmFileH_t h )
285 291
 
286 292
 cmFileRC_t cmFileFnWrite( const cmChar_t* fn, cmRpt_t* rpt, const void* buf, unsigned bufByteCnt )
287 293
 {
288
-  cmFileH_t h = cmFileNullHandle;
294
+  cmFileH_t  h = cmFileNullHandle;
289 295
   cmFileRC_t rc;
290 296
 
291 297
   if((rc = cmFileOpen(&h,fn,kWriteFileFl,rpt)) != kOkFileRC )
@@ -305,7 +311,7 @@ cmChar_t*  _cmFileToBuf( cmFileH_t h, unsigned nn, unsigned* bufByteCntPtr )
305 311
 
306 312
   unsigned  n   = cmFileByteCount(h);
307 313
   cmChar_t* buf = NULL;
308
-  cmFile_t*   p = _cmFileHandleToPtr(h);
314
+  cmFile_t* p   = _cmFileHandleToPtr(h);
309 315
  
310 316
 
311 317
   // if the file size calculation is ok
@@ -346,7 +352,7 @@ cmChar_t*  _cmFileToBuf( cmFileH_t h, unsigned nn, unsigned* bufByteCntPtr )
346 352
 
347 353
 cmChar_t* _cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned nn, unsigned* bufByteCntPtr  )
348 354
 {
349
-  cmFileH_t h = cmFileNullHandle;
355
+  cmFileH_t h   = cmFileNullHandle;
350 356
   cmChar_t* buf = NULL;
351 357
 
352 358
   if( cmFileOpen(&h,fn,kReadFileFl | kBinaryFileFl,rpt) != kOkFileRC )
@@ -360,6 +366,128 @@ cmChar_t* _cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned nn, unsigne
360 366
   return buf;
361 367
 }
362 368
 
369
+cmFileRC_t    cmFileCopy( 
370
+    const cmChar_t* srcDir, 
371
+    const cmChar_t* srcFn, 
372
+    const cmChar_t* srcExt, 
373
+    const cmChar_t* dstDir, 
374
+    const cmChar_t* dstFn, 
375
+    const cmChar_t* dstExt,
376
+    cmErr_t*        err)
377
+{
378
+  cmFileRC_t      rc        = kOkFileRC;
379
+  unsigned        byteCnt   = 0;
380
+  cmChar_t*       buf       = NULL;
381
+  const cmChar_t* srcPathFn = NULL;
382
+  const cmChar_t* dstPathFn = NULL;
383
+
384
+  // form the source path fn
385
+  if((srcPathFn = cmFsMakeFn(srcDir,srcFn,srcExt,NULL)) == NULL )
386
+  {
387
+    rc = cmErrMsg(err,kFileSysFailFileRC,"The soure file name for dir:%s name:%s ext:%s could not be formed.",cmStringNullGuard(srcDir),cmStringNullGuard(srcFn),cmStringNullGuard(srcExt));
388
+    goto errLabel;
389
+  }
390
+
391
+  // form the dest path fn
392
+  if((dstPathFn = cmFsMakeFn(dstDir,dstFn,dstExt,NULL)) == NULL )
393
+  {
394
+    rc = cmErrMsg(err,kFileSysFailFileRC,"The destination file name for dir:%s name:%s ext:%s could not be formed.",cmStringNullGuard(dstDir),cmStringNullGuard(dstFn),cmStringNullGuard(dstExt));
395
+    goto errLabel;
396
+  }
397
+
398
+  // verify that the source exists
399
+  if( cmFsIsFile(srcPathFn) == false )
400
+  {
401
+    rc = cmErrMsg(err,kOpenFailFileRC,"The source file '%s' does not exist.",cmStringNullGuard(srcPathFn));
402
+    goto errLabel;
403
+  }
404
+
405
+  // read the source file into a buffer
406
+  if((buf = cmFileFnToBuf(srcPathFn,err->rpt,&byteCnt)) == NULL )
407
+    rc = cmErrMsg(err,kReadFailFileRC,"Attempt to fill a buffer from '%s' failed.",cmStringNullGuard(srcPathFn));
408
+  else
409
+  {
410
+    // write the file to the output file
411
+    if( cmFileFnWrite(dstPathFn,err->rpt,buf,byteCnt) != kOkFileRC )
412
+      rc = cmErrMsg(err,kWriteFailFileRC,"An attempt to write a buffer to '%s' failed.",cmStringNullGuard(dstPathFn));    
413
+  }
414
+
415
+ errLabel:
416
+  // free the buffer
417
+  cmMemFree(buf);
418
+  cmFsFreeFn(srcPathFn);
419
+  cmFsFreeFn(dstPathFn);
420
+  return rc;
421
+
422
+}
423
+
424
+cmFileRC_t cmFileBackup( const cmChar_t* dir, const cmChar_t* name, const cmChar_t* ext, cmErr_t* err )
425
+{
426
+  cmFileRC_t      rc      = kOkFileRC;
427
+  cmChar_t*       newName = NULL;
428
+  const cmChar_t* newFn   = NULL;
429
+  unsigned        n       = 0;
430
+  const cmChar_t* srcFn   = NULL;
431
+
432
+  // form the name of the backup file
433
+  if((srcFn = cmFsMakeFn(dir,name,ext,NULL)) == NULL )
434
+  {
435
+    rc = cmErrMsg(err,kFileSysFailFileRC,"Backup source file name formation failed.");
436
+    goto errLabel;
437
+  }
438
+
439
+  // if the src file does not exist then there is nothing to do
440
+  if( cmFsIsFile(srcFn) == false )
441
+    return rc;
442
+
443
+  // break the source file name up into dir/fn/ext.
444
+  cmFileSysPathPart_t* pp = NULL;
445
+  if((pp = cmFsPathParts(srcFn)) == NULL || pp->fnStr==NULL)
446
+  {
447
+    rc = cmErrMsg(err,kFileSysFailFileRC,"The file name '%s' could not be parsed into its parts.",cmStringNullGuard(srcFn));
448
+    goto errLabel;
449
+  }
450
+
451
+  // iterate until a unique file name is found
452
+  for(n=0; 1; ++n)
453
+  {
454
+    cmFsFreeFn(newFn);
455
+
456
+    // generate a new file name
457
+    newName = cmTsPrintfP(newName,"%s_%i",pp->fnStr,n);
458
+    
459
+    // form the new file name into a complete path
460
+    if((newFn = cmFsMakeFn(pp->dirStr,newName,pp->extStr,NULL)) == NULL )
461
+    {
462
+      rc = cmErrMsg(err,kFileSysFailFileRC,"A backup file name could not be formed for the file '%s'.",cmStringNullGuard(newName));
463
+      goto errLabel;
464
+    }
465
+
466
+    // if the new file name is not already in use ...
467
+    if( cmFsIsFile(newFn) == false )
468
+    {
469
+      // .. then duplicate the file
470
+      if((rc = cmFileCopy(srcFn,NULL,NULL,newFn,NULL,NULL,err)) != kOkFileRC )
471
+        rc = cmErrMsg(err,rc,"The file '%s' could not be duplicated as '%s'.",cmStringNullGuard(srcFn),cmStringNullGuard(newFn));
472
+
473
+      break;
474
+    }
475
+
476
+
477
+  }
478
+
479
+ errLabel:
480
+
481
+  cmFsFreeFn(srcFn);
482
+  cmFsFreeFn(newFn);
483
+  cmMemFree(newName);
484
+  cmFsFreePathParts(pp);
485
+
486
+  return rc;
487
+
488
+}
489
+
490
+
363 491
 cmChar_t*  cmFileToBuf( cmFileH_t h, unsigned* bufByteCntPtr )
364 492
 { return _cmFileToBuf(h,0,bufByteCntPtr); }
365 493
 

+ 25
- 1
cmFile.h View File

@@ -27,7 +27,9 @@ extern "C" {
27 27
     kHandleInvalidFileRC,
28 28
     kStatFailFileRC,
29 29
     kBufAllocFailFileRC,
30
-    kBufTooSmallFileRC
30
+    kBufTooSmallFileRC,
31
+    kFileSysFailFileRC,
32
+
31 33
   };
32 34
 
33 35
   typedef unsigned   cmFileRC_t;
@@ -116,6 +118,28 @@ extern "C" {
116 118
   // Same as cmFileToBuf() but accepts a file name argument.
117 119
   // 'rpt' is the report object to use for error reporting.
118 120
   cmChar_t*  cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned* bufByteCntPtr );
121
+
122
+
123
+  // Copy the file named in srcDir/srcFn/srcExt to a file named dstDir/dstFn/dstExt.
124
+  // Note that srcExt/dstExt may be set to NULL if the file extension is included
125
+  // in srcFn/dstFn.  Likewise srcFn/dstFn may be set to NULL if the file name
126
+  // is included in srcDir/dstDir.
127
+  cmFileRC_t    cmFileCopy( 
128
+    const cmChar_t* srcDir, 
129
+    const cmChar_t* srcFn, 
130
+    const cmChar_t* srcExt, 
131
+    const cmChar_t* dstDir, 
132
+    const cmChar_t* dstFn, 
133
+    const cmChar_t* dstExt,
134
+    cmErr_t*        err);
135
+
136
+
137
+  // This function creates a backup copy of the file 'fn' by duplicating it into
138
+  // a file named fn_#.ext where # is an integer which makes the file name unique.
139
+  // The integers chosen with zero and are incremented until an
140
+  // unused file name is found in the same directory as 'fn'.
141
+  // If the file identified by 'fn' is not found then the function returns quietly.
142
+  cmFileRC_t cmFileBackup( const cmChar_t* dir, const cmChar_t* name, const cmChar_t* ext, cmErr_t* err );
119 143
   
120 144
   // Allocate and fill a zero terminated string from a file.
121 145
   // Set *bufByteCntPtr to count of bytes read into the buffer.=

+ 9
- 9
cmFileSys.c View File

@@ -378,14 +378,13 @@ const cmChar_t* cmFileSysVMakeFn( cmFileSysH_t h, const cmChar_t* dir, const cmC
378 378
   va_list         vl_t;
379 379
   va_copy(vl_t,vl);
380 380
 
381
-  assert( fn != NULL );
382
-
383 381
   // get prefix directory length
384 382
   if( dir != NULL )
385 383
     n += strlen(dir) + 1;  // add 1 for ending sep
386 384
 
387 385
   // get file name length
388
-  n += strlen(fn);
386
+  if( fn != NULL )
387
+    n += strlen(fn);
389 388
 
390 389
   // get extension length
391 390
   if( ext != NULL )
@@ -423,12 +422,13 @@ const cmChar_t* cmFileSysVMakeFn( cmFileSysH_t h, const cmChar_t* dir, const cmC
423 422
 
424 423
 
425 424
   // copy out the file name
426
-  if(!_cmFileSysConcat(rp,n,pathSep,fn))
427
-  {
428
-    assert(0);
429
-    rc = _cmFileSysError(p,kAssertFailFsRC,0,"Assert failed.");
430
-    goto errLabel;
431
-  }
425
+  if( fn != NULL )
426
+    if(!_cmFileSysConcat(rp,n,pathSep,fn))
427
+    {
428
+      assert(0);
429
+      rc = _cmFileSysError(p,kAssertFailFsRC,0,"Assert failed.");
430
+      goto errLabel;
431
+    }
432 432
   
433 433
   // copy out the extension
434 434
   if( ext != NULL )

+ 1
- 1
cmFileSys.h View File

@@ -35,7 +35,7 @@ extern "C" {
35 35
     kOsxFailFsRC,
36 36
     kLinuxFailFsRC,
37 37
     kInvalidDirFsRC,
38
-    kGenFileFailFsRC
38
+    kGenFileFailFsRC,
39 39
   };
40 40
 
41 41
 

+ 20
- 9
cmLex.c View File

@@ -323,19 +323,30 @@ unsigned _cmLexIdentMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
323 323
 
324 324
 unsigned _cmLexQStrMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
325 325
 {
326
-  cmChar_t qStr[]="\"";
327
-  unsigned n = strlen(qStr);
328
-  if( strncmp(qStr,cp,n) == 0 )
326
+  bool escFl = false;
327
+  unsigned i = 0;
328
+  if( cp[i] != '"' )
329
+    return 0;
330
+
331
+  for(i=1; i<cn; ++i)
329 332
   {
330
-    unsigned i;
331
-    if((i = _cmLexScanTo(cp+n, cn-n, qStr)) == cmInvalidIdx )
333
+    if( escFl )
332 334
     {
333
-      _cmLexError( p, kMissingEndQuoteLexRC, "Missing string end quote.");
334
-      return 0;
335
+      escFl = false;
336
+      continue;
335 337
     }
336
-    return n+i;
338
+
339
+    if( cp[i] == '\\' )
340
+    {
341
+      escFl = true;
342
+      continue;
343
+    }
344
+
345
+    if( cp[i] == '"' )
346
+      return i+1;    
337 347
   }
338
-  return 0;
348
+
349
+  return _cmLexError(p, kMissingEndQuoteLexRC, "Missing string literal end quote.");
339 350
 }
340 351
 
341 352
 unsigned _cmLexQCharMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )

+ 16
- 1
cmMem.c View File

@@ -518,8 +518,11 @@ void* cmMmAllocate(
518 518
        // p->nextId is incremented here
519 519
        cmThUIntIncr(&p->nextId,1);
520 520
 
521
+       
521 522
        /*
522
-       if( p->nextId == 2393 )
523
+         // breakpoint for noticing allocation of memory blocks - see below for
524
+         // the location to notice reallocations of memory blocks
525
+       if( p->nextId == 7218 )
523 526
        {
524 527
          cmErrMsg(&p->err,kOkMmRC,"Breakpoint for memory allocation id:%i.",p->nextId);
525 528
        }
@@ -553,11 +556,23 @@ void* cmMmAllocate(
553 556
 
554 557
      }
555 558
      else // a reallocation occurred.
559
+     {
556 560
        if( orgDataPtr == ndp )
557 561
        {
558 562
          if((rp = _cmMmFindRecd(p,orgDataPtr)) == NULL )
559 563
            cmErrMsg(&p->err,kMissingRecdMmRC,"Unable to locate a tracking record associated with reallocation data area pointer:%p.",orgDataPtr);           
564
+         else
565
+         {
566
+           /*
567
+             // break point for noticing reallocations on a memory block
568
+           if( rp->uniqueId == 7218 )
569
+           {
570
+             cmErrMsg(&p->err,kOkMmRC,"Breakpoint for memory reallocation id:%i.",p->nextId);
571
+           }
572
+           */
573
+         }
560 574
        }
575
+     }
561 576
    }
562 577
 
563 578
    return ndp;

+ 1
- 1
cmPgmOpts.c View File

@@ -710,7 +710,7 @@ cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt,  char* argArray[] )
710 710
   unsigned    state = kDash;
711 711
   _cmPoOpt_t* r     = NULL;
712 712
   _cmPoArg_t* a     = NULL;
713
-  int         i     = 0; // arg index
713
+  int         i     = 1; // arg index
714 714
   int         j     = 0; // arg label character index
715 715
 
716 716
 

+ 1
- 1
cmPgmOpts.h View File

@@ -198,7 +198,7 @@ extern "C" {
198 198
   // Get and set the current result code.
199 199
   cmPoRC_t    cmPgmOptRC( cmPgmOptH_t h, cmPoRC_t rc );
200 200
 
201
-  // Returns 'true' only if non- built-in options were selected
201
+  // Returns 'false' if only built-in options were selected otherwise returns true.
202 202
   bool cmPgmOptHandleBuiltInActions( cmPgmOptH_t h, cmRpt_t* rpt );
203 203
 
204 204
   void cmPgmOptPrintHelp(    cmPgmOptH_t h, cmRpt_t* rpt );

+ 20
- 0
cmText.c View File

@@ -498,6 +498,26 @@ const cmChar_t* cmTextLastNonWhiteCharC( const cmChar_t* s )
498 498
 { return cmTextLastNonWhiteChar(s); }
499 499
 
500 500
 
501
+cmChar_t*       cmTextLastWhiteChar(  const cmChar_t* s )
502
+{
503
+  unsigned n;
504
+  if(s==NULL || (n = strlen(s)) == 0 )
505
+    return NULL;
506
+
507
+  cmChar_t* s0 = (cmChar_t*)s + n-1;
508
+
509
+  for(; s0>=s; --s0)
510
+    if( isspace(*s0) )
511
+      return s0;
512
+
513
+  return NULL;
514
+
515
+}
516
+
517
+const cmChar_t* cmTextLastWhiteCharC( const cmChar_t* s )
518
+{ return cmTextLastWhiteChar(s); }
519
+
520
+
501 521
 void cmTextShrinkS( cmChar_t* s, const cmChar_t* t, unsigned tn )
502 522
 { cmVOC_Shrink(s,strlen(s)+1,t,tn); }
503 523
 

+ 5
- 0
cmText.h View File

@@ -146,9 +146,14 @@ extern "C" {
146 146
   const cmChar_t* cmTextEndOfLineC( const cmChar_t* s );
147 147
 
148 148
   // Return a pointer to the last non-white character in the string
149
+  // or NULL if s is NULL or empty.
149 150
   cmChar_t*       cmTextLastNonWhiteChar(  const cmChar_t* s );
150 151
   const cmChar_t* cmTextLastNonWhiteCharC( const cmChar_t* s );
151 152
   
153
+  // Return a pointer to the last white character in the string
154
+  // or NULL if s is NULL or empty.
155
+  cmChar_t*       cmTextLastWhiteChar(  const cmChar_t* s );
156
+  const cmChar_t* cmTextLastWhiteCharC( const cmChar_t* s );
152 157
     
153 158
 
154 159
 

Loading…
Cancel
Save