diff --git a/cmFile.c b/cmFile.c index 01c7276..f292e5b 100644 --- a/cmFile.c +++ b/cmFile.c @@ -2,9 +2,13 @@ #include "cmGlobal.h" #include "cmRpt.h" #include "cmErr.h" +#include "cmCtx.h" #include "cmFile.h" +#include "cmFileSys.h" #include "cmMem.h" #include "cmMallocDebug.h" +#include "cmLinkedHeap.h" +#include "cmText.h" #include 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 ) { - char mode[] = "/0/0/0"; - cmFile_t* p = NULL; - cmErr_t err; + char mode[] = "/0/0/0"; + cmFile_t* p = NULL; + cmErr_t err; cmFileRC_t rc; if((rc = cmFileClose(hp)) != kOkFileRC ) @@ -47,21 +51,21 @@ cmFileRC_t cmFileOpen( cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlag hp->h = NULL; if( cmIsFlag(flags,kReadFileFl) ) - mode[0]='r'; + mode[0] = 'r'; else if( cmIsFlag(flags,kWriteFileFl) ) - mode[0]='w'; + mode[0] = 'w'; else if( cmIsFlag(flags,kAppendFileFl) ) - mode[0]='a'; + mode[0] = 'a'; else cmErrMsg(&err,kInvalidFlagFileRC,"File open flags must contain 'kReadFileFl','kWriteFileFl', or 'kAppendFileFl'."); if( cmIsFlag(flags,kUpdateFileFl) ) - mode[1]='+'; + mode[1] = '+'; // handle requests to use stdin,stdout,stderr - FILE* sfp = NULL; + FILE* sfp = NULL; if( cmIsFlag(flags,kStdoutFileFl) ) { 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; } @@ -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 ) { cmFile_t* p = _cmFileHandleToPtr(h); - unsigned fileflags = 0; + unsigned fileflags = 0; if( cmIsFlag(flags,kBeginFileFl) ) fileflags = SEEK_SET; @@ -171,7 +175,7 @@ cmFileRC_t cmFileSeek( cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByt else return cmErrMsg(&p->err,kInvalidFlagFileRC,"Invalid file seek flag on '%s'.",p->fnStr); - errno = 0; + errno = 0; if( fseek(p->fp,offsByteCnt,fileflags) != 0 ) 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 ) { assert( offsPtr != NULL ); - *offsPtr = -1; - cmFile_t* p = _cmFileHandleToPtr(h); - errno = 0; + *offsPtr = -1; + cmFile_t* p = _cmFileHandleToPtr(h); + errno = 0; + if((*offsPtr = ftell(p->fp)) == -1) return _cmFileError(p,kTellFailFileRC,errno,"File tell failed"); return kOkFileRC; @@ -222,7 +227,8 @@ cmFileRC_t cmFileByteCountFn( const cmChar_t* fn, cmRpt_t* rpt, unsigned* file { assert( fileByteCntPtr != NULL ); cmFileRC_t rc; - cmFileH_t h = cmFileNullHandle; + cmFileH_t h = cmFileNullHandle; + if((rc = cmFileOpen(&h,fn,kReadFileFl,rpt)) != kOkFileRC ) 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 h1 = cmFileNullHandle; - char b0[ bufByteCnt ]; - char b1[ bufByteCnt ]; + char b0[ bufByteCnt ]; + char b1[ bufByteCnt ]; assert(isEqualPtr != NULL ); *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 ) goto errLabel; - cmFile_t* p0 = _cmFileHandleToPtr(h0); - cmFile_t* p1 = _cmFileHandleToPtr(h1); + cmFile_t* p0 = _cmFileHandleToPtr(h0); + cmFile_t* p1 = _cmFileHandleToPtr(h1); while(1) { size_t n0 = fread(b0,1,bufByteCnt,p0->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; 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 ) { - cmFileH_t h = cmFileNullHandle; + cmFileH_t h = cmFileNullHandle; cmFileRC_t rc; 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); cmChar_t* buf = NULL; - cmFile_t* p = _cmFileHandleToPtr(h); + cmFile_t* p = _cmFileHandleToPtr(h); // 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 ) { - cmFileH_t h = cmFileNullHandle; + cmFileH_t h = cmFileNullHandle; cmChar_t* buf = NULL; 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; } +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 ) { return _cmFileToBuf(h,0,bufByteCntPtr); } diff --git a/cmFile.h b/cmFile.h index af2341b..0143d28 100644 --- a/cmFile.h +++ b/cmFile.h @@ -27,7 +27,9 @@ extern "C" { kHandleInvalidFileRC, kStatFailFileRC, kBufAllocFailFileRC, - kBufTooSmallFileRC + kBufTooSmallFileRC, + kFileSysFailFileRC, + }; typedef unsigned cmFileRC_t; @@ -116,6 +118,28 @@ extern "C" { // Same as cmFileToBuf() but accepts a file name argument. // 'rpt' is the report object to use for error reporting. 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. // Set *bufByteCntPtr to count of bytes read into the buffer.= diff --git a/cmFileSys.c b/cmFileSys.c index 9a96583..470c463 100644 --- a/cmFileSys.c +++ b/cmFileSys.c @@ -378,14 +378,13 @@ const cmChar_t* cmFileSysVMakeFn( cmFileSysH_t h, const cmChar_t* dir, const cmC va_list vl_t; va_copy(vl_t,vl); - assert( fn != NULL ); - // get prefix directory length if( dir != NULL ) n += strlen(dir) + 1; // add 1 for ending sep // get file name length - n += strlen(fn); + if( fn != NULL ) + n += strlen(fn); // get extension length 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 - if(!_cmFileSysConcat(rp,n,pathSep,fn)) - { - assert(0); - rc = _cmFileSysError(p,kAssertFailFsRC,0,"Assert failed."); - goto errLabel; - } + if( fn != NULL ) + if(!_cmFileSysConcat(rp,n,pathSep,fn)) + { + assert(0); + rc = _cmFileSysError(p,kAssertFailFsRC,0,"Assert failed."); + goto errLabel; + } // copy out the extension if( ext != NULL ) diff --git a/cmFileSys.h b/cmFileSys.h index e67dca9..073b1f2 100644 --- a/cmFileSys.h +++ b/cmFileSys.h @@ -35,7 +35,7 @@ extern "C" { kOsxFailFsRC, kLinuxFailFsRC, kInvalidDirFsRC, - kGenFileFailFsRC + kGenFileFailFsRC, }; diff --git a/cmLex.c b/cmLex.c index 7267493..5f89e7c 100644 --- a/cmLex.c +++ b/cmLex.c @@ -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 ) { - cmChar_t qStr[]="\""; - unsigned n = strlen(qStr); - if( strncmp(qStr,cp,n) == 0 ) + bool escFl = false; + unsigned i = 0; + if( cp[i] != '"' ) + return 0; + + for(i=1; inextId is incremented here 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); } @@ -553,11 +556,23 @@ void* cmMmAllocate( } else // a reallocation occurred. + { if( orgDataPtr == ndp ) { if((rp = _cmMmFindRecd(p,orgDataPtr)) == NULL ) 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; diff --git a/cmPgmOpts.c b/cmPgmOpts.c index 735c388..9f13d0b 100644 --- a/cmPgmOpts.c +++ b/cmPgmOpts.c @@ -710,7 +710,7 @@ cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt, char* argArray[] ) unsigned state = kDash; _cmPoOpt_t* r = NULL; _cmPoArg_t* a = NULL; - int i = 0; // arg index + int i = 1; // arg index int j = 0; // arg label character index diff --git a/cmPgmOpts.h b/cmPgmOpts.h index 3dcb569..bcee202 100644 --- a/cmPgmOpts.h +++ b/cmPgmOpts.h @@ -198,7 +198,7 @@ extern "C" { // Get and set the current result code. 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 ); void cmPgmOptPrintHelp( cmPgmOptH_t h, cmRpt_t* rpt ); diff --git a/cmText.c b/cmText.c index 300676d..7af0957 100644 --- a/cmText.c +++ b/cmText.c @@ -498,6 +498,26 @@ const cmChar_t* cmTextLastNonWhiteCharC( const cmChar_t* 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 ) { cmVOC_Shrink(s,strlen(s)+1,t,tn); } diff --git a/cmText.h b/cmText.h index fde6e70..8742abe 100644 --- a/cmText.h +++ b/cmText.h @@ -146,9 +146,14 @@ extern "C" { const cmChar_t* cmTextEndOfLineC( const cmChar_t* s ); // 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 ); 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 );