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

This commit is contained in:
kevin 2014-01-31 10:31:34 -08:00
commit 6bb138b1ad
10 changed files with 249 additions and 46 deletions

174
cmFile.c
View File

@ -2,9 +2,13 @@
#include "cmGlobal.h" #include "cmGlobal.h"
#include "cmRpt.h" #include "cmRpt.h"
#include "cmErr.h" #include "cmErr.h"
#include "cmCtx.h"
#include "cmFile.h" #include "cmFile.h"
#include "cmFileSys.h"
#include "cmMem.h" #include "cmMem.h"
#include "cmMallocDebug.h" #include "cmMallocDebug.h"
#include "cmLinkedHeap.h"
#include "cmText.h"
#include <sys/stat.h> #include <sys/stat.h>
cmFileH_t cmFileNullHandle = { NULL }; cmFileH_t cmFileNullHandle = { NULL };
@ -34,9 +38,9 @@ cmFileRC_t _cmFileError( cmFile_t* p, cmFileRC_t rc, int errNumb, const cmChar_t
cmFileRC_t cmFileOpen( cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlags_t flags, cmRpt_t* rpt ) cmFileRC_t cmFileOpen( cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlags_t flags, cmRpt_t* rpt )
{ {
char mode[] = "/0/0/0"; char mode[] = "/0/0/0";
cmFile_t* p = NULL; cmFile_t* p = NULL;
cmErr_t err; cmErr_t err;
cmFileRC_t rc; cmFileRC_t rc;
if((rc = cmFileClose(hp)) != kOkFileRC ) if((rc = cmFileClose(hp)) != kOkFileRC )
@ -47,21 +51,21 @@ cmFileRC_t cmFileOpen( cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlag
hp->h = NULL; hp->h = NULL;
if( cmIsFlag(flags,kReadFileFl) ) if( cmIsFlag(flags,kReadFileFl) )
mode[0]='r'; mode[0] = 'r';
else else
if( cmIsFlag(flags,kWriteFileFl) ) if( cmIsFlag(flags,kWriteFileFl) )
mode[0]='w'; mode[0] = 'w';
else else
if( cmIsFlag(flags,kAppendFileFl) ) if( cmIsFlag(flags,kAppendFileFl) )
mode[0]='a'; mode[0] = 'a';
else else
cmErrMsg(&err,kInvalidFlagFileRC,"File open flags must contain 'kReadFileFl','kWriteFileFl', or 'kAppendFileFl'."); cmErrMsg(&err,kInvalidFlagFileRC,"File open flags must contain 'kReadFileFl','kWriteFileFl', or 'kAppendFileFl'.");
if( cmIsFlag(flags,kUpdateFileFl) ) if( cmIsFlag(flags,kUpdateFileFl) )
mode[1]='+'; mode[1] = '+';
// handle requests to use stdin,stdout,stderr // handle requests to use stdin,stdout,stderr
FILE* sfp = NULL; FILE* sfp = NULL;
if( cmIsFlag(flags,kStdoutFileFl) ) if( cmIsFlag(flags,kStdoutFileFl) )
{ {
sfp = stdout; sfp = stdout;
@ -107,7 +111,7 @@ cmFileRC_t cmFileOpen( cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlag
} }
} }
hp->h = p; hp->h = p;
return kOkFileRC; return kOkFileRC;
} }
@ -158,7 +162,7 @@ cmFileRC_t cmFileWrite( cmFileH_t h, const void* buf, unsigned bufByteCnt )
cmFileRC_t cmFileSeek( cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByteCnt ) cmFileRC_t cmFileSeek( cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByteCnt )
{ {
cmFile_t* p = _cmFileHandleToPtr(h); cmFile_t* p = _cmFileHandleToPtr(h);
unsigned fileflags = 0; unsigned fileflags = 0;
if( cmIsFlag(flags,kBeginFileFl) ) if( cmIsFlag(flags,kBeginFileFl) )
fileflags = SEEK_SET; fileflags = SEEK_SET;
@ -171,7 +175,7 @@ cmFileRC_t cmFileSeek( cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByt
else else
return cmErrMsg(&p->err,kInvalidFlagFileRC,"Invalid file seek flag on '%s'.",p->fnStr); return cmErrMsg(&p->err,kInvalidFlagFileRC,"Invalid file seek flag on '%s'.",p->fnStr);
errno = 0; errno = 0;
if( fseek(p->fp,offsByteCnt,fileflags) != 0 ) if( fseek(p->fp,offsByteCnt,fileflags) != 0 )
return _cmFileError(p,kSeekFailFileRC,errno,"File seek failed"); return _cmFileError(p,kSeekFailFileRC,errno,"File seek failed");
@ -181,9 +185,10 @@ cmFileRC_t cmFileSeek( cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByt
cmFileRC_t cmFileTell( cmFileH_t h, long* offsPtr ) cmFileRC_t cmFileTell( cmFileH_t h, long* offsPtr )
{ {
assert( offsPtr != NULL ); assert( offsPtr != NULL );
*offsPtr = -1; *offsPtr = -1;
cmFile_t* p = _cmFileHandleToPtr(h); cmFile_t* p = _cmFileHandleToPtr(h);
errno = 0; errno = 0;
if((*offsPtr = ftell(p->fp)) == -1) if((*offsPtr = ftell(p->fp)) == -1)
return _cmFileError(p,kTellFailFileRC,errno,"File tell failed"); return _cmFileError(p,kTellFailFileRC,errno,"File tell failed");
return kOkFileRC; return kOkFileRC;
@ -222,7 +227,8 @@ cmFileRC_t cmFileByteCountFn( const cmChar_t* fn, cmRpt_t* rpt, unsigned* file
{ {
assert( fileByteCntPtr != NULL ); assert( fileByteCntPtr != NULL );
cmFileRC_t rc; cmFileRC_t rc;
cmFileH_t h = cmFileNullHandle; cmFileH_t h = cmFileNullHandle;
if((rc = cmFileOpen(&h,fn,kReadFileFl,rpt)) != kOkFileRC ) if((rc = cmFileOpen(&h,fn,kReadFileFl,rpt)) != kOkFileRC )
return rc; return rc;
@ -241,8 +247,8 @@ cmFileRC_t cmFileCompare( const cmChar_t* fn0, const cmChar_t* fn1, cmRpt_t* rpt
cmFileH_t h0 = cmFileNullHandle; cmFileH_t h0 = cmFileNullHandle;
cmFileH_t h1 = cmFileNullHandle; cmFileH_t h1 = cmFileNullHandle;
char b0[ bufByteCnt ]; char b0[ bufByteCnt ];
char b1[ bufByteCnt ]; char b1[ bufByteCnt ];
assert(isEqualPtr != NULL ); assert(isEqualPtr != NULL );
*isEqualPtr = true; *isEqualPtr = true;
@ -253,14 +259,14 @@ cmFileRC_t cmFileCompare( const cmChar_t* fn0, const cmChar_t* fn1, cmRpt_t* rpt
if((rc = cmFileOpen(&h1,fn1,kReadFileFl,rpt)) != kOkFileRC ) if((rc = cmFileOpen(&h1,fn1,kReadFileFl,rpt)) != kOkFileRC )
goto errLabel; goto errLabel;
cmFile_t* p0 = _cmFileHandleToPtr(h0); cmFile_t* p0 = _cmFileHandleToPtr(h0);
cmFile_t* p1 = _cmFileHandleToPtr(h1); cmFile_t* p1 = _cmFileHandleToPtr(h1);
while(1) while(1)
{ {
size_t n0 = fread(b0,1,bufByteCnt,p0->fp); size_t n0 = fread(b0,1,bufByteCnt,p0->fp);
size_t n1 = fread(b1,1,bufByteCnt,p1->fp); size_t n1 = fread(b1,1,bufByteCnt,p1->fp);
if( n0 != n1 || memcmp(b0,b1,n0)!=0 ) if( n0 != n1 || memcmp(b0,b1,n0) != 0 )
{ {
*isEqualPtr = false; *isEqualPtr = false;
break; break;
@ -285,7 +291,7 @@ const cmChar_t* cmFileName( cmFileH_t h )
cmFileRC_t cmFileFnWrite( const cmChar_t* fn, cmRpt_t* rpt, const void* buf, unsigned bufByteCnt ) cmFileRC_t cmFileFnWrite( const cmChar_t* fn, cmRpt_t* rpt, const void* buf, unsigned bufByteCnt )
{ {
cmFileH_t h = cmFileNullHandle; cmFileH_t h = cmFileNullHandle;
cmFileRC_t rc; cmFileRC_t rc;
if((rc = cmFileOpen(&h,fn,kWriteFileFl,rpt)) != kOkFileRC ) if((rc = cmFileOpen(&h,fn,kWriteFileFl,rpt)) != kOkFileRC )
@ -305,7 +311,7 @@ cmChar_t* _cmFileToBuf( cmFileH_t h, unsigned nn, unsigned* bufByteCntPtr )
unsigned n = cmFileByteCount(h); unsigned n = cmFileByteCount(h);
cmChar_t* buf = NULL; cmChar_t* buf = NULL;
cmFile_t* p = _cmFileHandleToPtr(h); cmFile_t* p = _cmFileHandleToPtr(h);
// if the file size calculation is ok // if the file size calculation is ok
@ -346,7 +352,7 @@ cmChar_t* _cmFileToBuf( cmFileH_t h, unsigned nn, unsigned* bufByteCntPtr )
cmChar_t* _cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned nn, unsigned* bufByteCntPtr ) cmChar_t* _cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned nn, unsigned* bufByteCntPtr )
{ {
cmFileH_t h = cmFileNullHandle; cmFileH_t h = cmFileNullHandle;
cmChar_t* buf = NULL; cmChar_t* buf = NULL;
if( cmFileOpen(&h,fn,kReadFileFl | kBinaryFileFl,rpt) != kOkFileRC ) 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
return buf; return buf;
} }
cmFileRC_t cmFileCopy(
const cmChar_t* srcDir,
const cmChar_t* srcFn,
const cmChar_t* srcExt,
const cmChar_t* dstDir,
const cmChar_t* dstFn,
const cmChar_t* dstExt,
cmErr_t* err)
{
cmFileRC_t rc = kOkFileRC;
unsigned byteCnt = 0;
cmChar_t* buf = NULL;
const cmChar_t* srcPathFn = NULL;
const cmChar_t* dstPathFn = NULL;
// form the source path fn
if((srcPathFn = cmFsMakeFn(srcDir,srcFn,srcExt,NULL)) == NULL )
{
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));
goto errLabel;
}
// form the dest path fn
if((dstPathFn = cmFsMakeFn(dstDir,dstFn,dstExt,NULL)) == NULL )
{
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));
goto errLabel;
}
// verify that the source exists
if( cmFsIsFile(srcPathFn) == false )
{
rc = cmErrMsg(err,kOpenFailFileRC,"The source file '%s' does not exist.",cmStringNullGuard(srcPathFn));
goto errLabel;
}
// read the source file into a buffer
if((buf = cmFileFnToBuf(srcPathFn,err->rpt,&byteCnt)) == NULL )
rc = cmErrMsg(err,kReadFailFileRC,"Attempt to fill a buffer from '%s' failed.",cmStringNullGuard(srcPathFn));
else
{
// write the file to the output file
if( cmFileFnWrite(dstPathFn,err->rpt,buf,byteCnt) != kOkFileRC )
rc = cmErrMsg(err,kWriteFailFileRC,"An attempt to write a buffer to '%s' failed.",cmStringNullGuard(dstPathFn));
}
errLabel:
// free the buffer
cmMemFree(buf);
cmFsFreeFn(srcPathFn);
cmFsFreeFn(dstPathFn);
return rc;
}
cmFileRC_t cmFileBackup( const cmChar_t* dir, const cmChar_t* name, const cmChar_t* ext, cmErr_t* err )
{
cmFileRC_t rc = kOkFileRC;
cmChar_t* newName = NULL;
const cmChar_t* newFn = NULL;
unsigned n = 0;
const cmChar_t* srcFn = NULL;
// form the name of the backup file
if((srcFn = cmFsMakeFn(dir,name,ext,NULL)) == NULL )
{
rc = cmErrMsg(err,kFileSysFailFileRC,"Backup source file name formation failed.");
goto errLabel;
}
// if the src file does not exist then there is nothing to do
if( cmFsIsFile(srcFn) == false )
return rc;
// break the source file name up into dir/fn/ext.
cmFileSysPathPart_t* pp = NULL;
if((pp = cmFsPathParts(srcFn)) == NULL || pp->fnStr==NULL)
{
rc = cmErrMsg(err,kFileSysFailFileRC,"The file name '%s' could not be parsed into its parts.",cmStringNullGuard(srcFn));
goto errLabel;
}
// iterate until a unique file name is found
for(n=0; 1; ++n)
{
cmFsFreeFn(newFn);
// generate a new file name
newName = cmTsPrintfP(newName,"%s_%i",pp->fnStr,n);
// form the new file name into a complete path
if((newFn = cmFsMakeFn(pp->dirStr,newName,pp->extStr,NULL)) == NULL )
{
rc = cmErrMsg(err,kFileSysFailFileRC,"A backup file name could not be formed for the file '%s'.",cmStringNullGuard(newName));
goto errLabel;
}
// if the new file name is not already in use ...
if( cmFsIsFile(newFn) == false )
{
// .. then duplicate the file
if((rc = cmFileCopy(srcFn,NULL,NULL,newFn,NULL,NULL,err)) != kOkFileRC )
rc = cmErrMsg(err,rc,"The file '%s' could not be duplicated as '%s'.",cmStringNullGuard(srcFn),cmStringNullGuard(newFn));
break;
}
}
errLabel:
cmFsFreeFn(srcFn);
cmFsFreeFn(newFn);
cmMemFree(newName);
cmFsFreePathParts(pp);
return rc;
}
cmChar_t* cmFileToBuf( cmFileH_t h, unsigned* bufByteCntPtr ) cmChar_t* cmFileToBuf( cmFileH_t h, unsigned* bufByteCntPtr )
{ return _cmFileToBuf(h,0,bufByteCntPtr); } { return _cmFileToBuf(h,0,bufByteCntPtr); }

View File

@ -27,7 +27,9 @@ extern "C" {
kHandleInvalidFileRC, kHandleInvalidFileRC,
kStatFailFileRC, kStatFailFileRC,
kBufAllocFailFileRC, kBufAllocFailFileRC,
kBufTooSmallFileRC kBufTooSmallFileRC,
kFileSysFailFileRC,
}; };
typedef unsigned cmFileRC_t; typedef unsigned cmFileRC_t;
@ -117,6 +119,28 @@ extern "C" {
// 'rpt' is the report object to use for error reporting. // 'rpt' is the report object to use for error reporting.
cmChar_t* cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned* bufByteCntPtr ); cmChar_t* cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned* bufByteCntPtr );
// Copy the file named in srcDir/srcFn/srcExt to a file named dstDir/dstFn/dstExt.
// Note that srcExt/dstExt may be set to NULL if the file extension is included
// in srcFn/dstFn. Likewise srcFn/dstFn may be set to NULL if the file name
// is included in srcDir/dstDir.
cmFileRC_t cmFileCopy(
const cmChar_t* srcDir,
const cmChar_t* srcFn,
const cmChar_t* srcExt,
const cmChar_t* dstDir,
const cmChar_t* dstFn,
const cmChar_t* dstExt,
cmErr_t* err);
// This function creates a backup copy of the file 'fn' by duplicating it into
// a file named fn_#.ext where # is an integer which makes the file name unique.
// The integers chosen with zero and are incremented until an
// unused file name is found in the same directory as 'fn'.
// If the file identified by 'fn' is not found then the function returns quietly.
cmFileRC_t cmFileBackup( const cmChar_t* dir, const cmChar_t* name, const cmChar_t* ext, cmErr_t* err );
// Allocate and fill a zero terminated string from a file. // Allocate and fill a zero terminated string from a file.
// Set *bufByteCntPtr to count of bytes read into the buffer.= // Set *bufByteCntPtr to count of bytes read into the buffer.=
// (the buffer memory size is one byte larger to account for the terminating zero) // (the buffer memory size is one byte larger to account for the terminating zero)

View File

@ -378,14 +378,13 @@ const cmChar_t* cmFileSysVMakeFn( cmFileSysH_t h, const cmChar_t* dir, const cmC
va_list vl_t; va_list vl_t;
va_copy(vl_t,vl); va_copy(vl_t,vl);
assert( fn != NULL );
// get prefix directory length // get prefix directory length
if( dir != NULL ) if( dir != NULL )
n += strlen(dir) + 1; // add 1 for ending sep n += strlen(dir) + 1; // add 1 for ending sep
// get file name length // get file name length
n += strlen(fn); if( fn != NULL )
n += strlen(fn);
// get extension length // get extension length
if( ext != NULL ) if( ext != NULL )
@ -423,12 +422,13 @@ const cmChar_t* cmFileSysVMakeFn( cmFileSysH_t h, const cmChar_t* dir, const cmC
// copy out the file name // copy out the file name
if(!_cmFileSysConcat(rp,n,pathSep,fn)) if( fn != NULL )
{ if(!_cmFileSysConcat(rp,n,pathSep,fn))
assert(0); {
rc = _cmFileSysError(p,kAssertFailFsRC,0,"Assert failed."); assert(0);
goto errLabel; rc = _cmFileSysError(p,kAssertFailFsRC,0,"Assert failed.");
} goto errLabel;
}
// copy out the extension // copy out the extension
if( ext != NULL ) if( ext != NULL )

View File

@ -35,7 +35,7 @@ extern "C" {
kOsxFailFsRC, kOsxFailFsRC,
kLinuxFailFsRC, kLinuxFailFsRC,
kInvalidDirFsRC, kInvalidDirFsRC,
kGenFileFailFsRC kGenFileFailFsRC,
}; };

29
cmLex.c
View File

@ -323,19 +323,30 @@ unsigned _cmLexIdentMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
unsigned _cmLexQStrMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr ) unsigned _cmLexQStrMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
{ {
cmChar_t qStr[]="\""; bool escFl = false;
unsigned n = strlen(qStr); unsigned i = 0;
if( strncmp(qStr,cp,n) == 0 ) if( cp[i] != '"' )
return 0;
for(i=1; i<cn; ++i)
{ {
unsigned i; if( escFl )
if((i = _cmLexScanTo(cp+n, cn-n, qStr)) == cmInvalidIdx )
{ {
_cmLexError( p, kMissingEndQuoteLexRC, "Missing string end quote."); escFl = false;
return 0; continue;
} }
return n+i;
if( cp[i] == '\\' )
{
escFl = true;
continue;
}
if( cp[i] == '"' )
return i+1;
} }
return 0;
return _cmLexError(p, kMissingEndQuoteLexRC, "Missing string literal end quote.");
} }
unsigned _cmLexQCharMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr ) unsigned _cmLexQCharMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )

17
cmMem.c
View File

@ -518,8 +518,11 @@ void* cmMmAllocate(
// p->nextId is incremented here // p->nextId is incremented here
cmThUIntIncr(&p->nextId,1); cmThUIntIncr(&p->nextId,1);
/* /*
if( p->nextId == 2393 ) // breakpoint for noticing allocation of memory blocks - see below for
// the location to notice reallocations of memory blocks
if( p->nextId == 7218 )
{ {
cmErrMsg(&p->err,kOkMmRC,"Breakpoint for memory allocation id:%i.",p->nextId); cmErrMsg(&p->err,kOkMmRC,"Breakpoint for memory allocation id:%i.",p->nextId);
} }
@ -553,11 +556,23 @@ void* cmMmAllocate(
} }
else // a reallocation occurred. else // a reallocation occurred.
{
if( orgDataPtr == ndp ) if( orgDataPtr == ndp )
{ {
if((rp = _cmMmFindRecd(p,orgDataPtr)) == NULL ) if((rp = _cmMmFindRecd(p,orgDataPtr)) == NULL )
cmErrMsg(&p->err,kMissingRecdMmRC,"Unable to locate a tracking record associated with reallocation data area pointer:%p.",orgDataPtr); cmErrMsg(&p->err,kMissingRecdMmRC,"Unable to locate a tracking record associated with reallocation data area pointer:%p.",orgDataPtr);
else
{
/*
// break point for noticing reallocations on a memory block
if( rp->uniqueId == 7218 )
{
cmErrMsg(&p->err,kOkMmRC,"Breakpoint for memory reallocation id:%i.",p->nextId);
}
*/
}
} }
}
} }
return ndp; return ndp;

View File

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

View File

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

View File

@ -498,6 +498,26 @@ const cmChar_t* cmTextLastNonWhiteCharC( const cmChar_t* s )
{ return cmTextLastNonWhiteChar(s); } { return cmTextLastNonWhiteChar(s); }
cmChar_t* cmTextLastWhiteChar( const cmChar_t* s )
{
unsigned n;
if(s==NULL || (n = strlen(s)) == 0 )
return NULL;
cmChar_t* s0 = (cmChar_t*)s + n-1;
for(; s0>=s; --s0)
if( isspace(*s0) )
return s0;
return NULL;
}
const cmChar_t* cmTextLastWhiteCharC( const cmChar_t* s )
{ return cmTextLastWhiteChar(s); }
void cmTextShrinkS( cmChar_t* s, const cmChar_t* t, unsigned tn ) void cmTextShrinkS( cmChar_t* s, const cmChar_t* t, unsigned tn )
{ cmVOC_Shrink(s,strlen(s)+1,t,tn); } { cmVOC_Shrink(s,strlen(s)+1,t,tn); }

View File

@ -146,9 +146,14 @@ extern "C" {
const cmChar_t* cmTextEndOfLineC( const cmChar_t* s ); const cmChar_t* cmTextEndOfLineC( const cmChar_t* s );
// Return a pointer to the last non-white character in the string // Return a pointer to the last non-white character in the string
// or NULL if s is NULL or empty.
cmChar_t* cmTextLastNonWhiteChar( const cmChar_t* s ); cmChar_t* cmTextLastNonWhiteChar( const cmChar_t* s );
const cmChar_t* cmTextLastNonWhiteCharC( const cmChar_t* s ); const cmChar_t* cmTextLastNonWhiteCharC( const cmChar_t* s );
// Return a pointer to the last white character in the string
// or NULL if s is NULL or empty.
cmChar_t* cmTextLastWhiteChar( const cmChar_t* s );
const cmChar_t* cmTextLastWhiteCharC( const cmChar_t* s );