diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmBootstrapCommands.cxx | 3 | ||||
-rw-r--r-- | Source/cmFileCommand.cxx | 10 | ||||
-rw-r--r-- | Source/cmFileCommand.h | 7 | ||||
-rw-r--r-- | Source/cmHexFileConverter.cxx | 266 | ||||
-rw-r--r-- | Source/cmHexFileConverter.h | 33 |
5 files changed, 315 insertions, 4 deletions
diff --git a/Source/cmBootstrapCommands.cxx b/Source/cmBootstrapCommands.cxx index 19be6df..f129eb0 100644 --- a/Source/cmBootstrapCommands.cxx +++ b/Source/cmBootstrapCommands.cxx @@ -30,6 +30,7 @@ #include "cmBuildCommand.cxx" #include "cmCMakeMinimumRequired.cxx" #include "cmConfigureFileCommand.cxx" +#include "cmCoreTryCompile.cxx" #include "cmCreateTestSourceList.cxx" #include "cmElseCommand.cxx" #include "cmEnableTestingCommand.cxx" @@ -47,6 +48,7 @@ #include "cmGetCMakePropertyCommand.cxx" #include "cmGetFilenameComponentCommand.cxx" #include "cmGetSourceFilePropertyCommand.cxx" +#include "cmHexFileConverter.cxx" #include "cmIfCommand.cxx" #include "cmIncludeCommand.cxx" #include "cmIncludeDirectoryCommand.cxx" @@ -66,7 +68,6 @@ #include "cmStringCommand.cxx" #include "cmSubdirCommand.cxx" #include "cmTargetLinkLibrariesCommand.cxx" -#include "cmCoreTryCompile.cxx" #include "cmTryCompileCommand.cxx" #include "cmTryRunCommand.cxx" diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index ed3ac2c..5b3390d 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -15,6 +15,8 @@ =========================================================================*/ #include "cmFileCommand.h" +#include "cmake.h" +#include "cmHexFileConverter.h" #include <sys/types.h> #include <sys/stat.h> @@ -414,6 +416,14 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) return false; } } + + std::string binaryFileName = this->Makefile->GetCurrentOutputDirectory(); + binaryFileName += cmake::GetCMakeFilesDirectory(); + binaryFileName += "/FileCommandStringsBinaryFile"; + if (cmHexFileConverter::TryConvert(fileName.c_str(), binaryFileName.c_str())) + { + fileName = binaryFileName; + } // Open the specified file. #if defined(_WIN32) || defined(__CYGWIN__) diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index f758151..5868725 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -93,9 +93,10 @@ public: "want to generate input files to CMake.\n" "READ will read the content of a file and store it into the " "variable.\n" - "STRINGS will parse a list of ASCII strings from a file and store it " - "in a variable. Binary data in the file are ignored. Carriage return " - "(CR) characters are ignored. " + "STRINGS will parse a list of ASCII strings from a binary file and " + "store it in a variable. Binary data in the file are ignored. Carriage " + "return (CR) characters are ignored. It works also for Intel Hex and " + "Motorola S-record files.\n " "LIMIT_COUNT sets the maximum number of strings to return. " "LIMIT_INPUT sets the maximum number of bytes to read from " "the input file. " diff --git a/Source/cmHexFileConverter.cxx b/Source/cmHexFileConverter.cxx new file mode 100644 index 0000000..f8d369f --- /dev/null +++ b/Source/cmHexFileConverter.cxx @@ -0,0 +1,266 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "cmHexFileConverter.h" + +#include <stdio.h> +#include <string.h> + +#define INTEL_HEX_MIN_LINE_LENGTH (1+8 +2) +#define INTEL_HEX_MAX_LINE_LENGTH (1+8+(256*2)+2) +#define MOTOROLA_SREC_MIN_LINE_LENGTH (2+2+4 +2) +#define MOTOROLA_SREC_MAX_LINE_LENGTH (2+2+8+(256*2)+2) + +// might go to SystemTools ? +static bool cm_IsHexChar(char c) +{ + return (((c >= '0') && (c <= '9')) + || ((c >= 'a') && (c <= 'f')) + || ((c >= 'A') && (c <= 'F'))); +} + +static unsigned int ChompStrlen(const char* line) +{ + if (line == 0) + { + return 0; + } + unsigned int length = strlen(line); + if ((line[length-1] == '\n') || (line[length-1] == '\r')) + { + length--; + } + if ((line[length-1] == '\n') || (line[length-1] == '\r')) + { + length--; + } + return length; +} + +static bool OutputBin(FILE* file, const char * buf, + unsigned int startIndex, unsigned int stopIndex) +{ + bool success = true; + char hexNumber[3]; + hexNumber[2] = '\0'; + char outBuf[256]; + int outBufCount = 0; + for (unsigned int i = startIndex; i < stopIndex; i += 2) + { + hexNumber[0] = buf[i]; + hexNumber[1] = buf[i+1]; + unsigned int convertedByte = 0; + if (sscanf(hexNumber, "%x", &convertedByte) != 1) + { + success = false; + break; + } + outBuf[outBufCount] = convertedByte & 0xff; + outBufCount++; + } + if (success) + { + success = (fwrite(outBuf, 1, outBufCount, file)==outBufCount); + } + return success; +} + +// see http://www.die.net/doc/linux/man/man5/srec.5.html +static bool ConvertMotorolaSrecLine(const char* buf, FILE* outFile) +{ + unsigned int slen = ChompStrlen(buf); + if ((slen < MOTOROLA_SREC_MIN_LINE_LENGTH) + || (slen > MOTOROLA_SREC_MAX_LINE_LENGTH)) + { + return false; + } + + // line length must be even + if (slen % 2 == 1) + { + return false; + } + + if (buf[0] != 'S') + { + return false; + } + + unsigned int dataStart = 0; + // ignore extra address records + if ((buf[1] == '5') || (buf[1] == '7') || (buf[1] == '8') || (buf[1] == '9')) + { + return true; + } + else if (buf[1] == '1') + { + dataStart = 8; + } + else if (buf[1] == '2') + { + dataStart = 10; + } + else if (buf[1] == '3') + { + dataStart = 12; + } + else // unknown record type + { + return false; + } + + // ignore the last two bytes (checksum) + return OutputBin(outFile, buf, dataStart, slen - 2); +} + +// see http://en.wikipedia.org/wiki/Intel_hex +static bool ConvertIntelHexLine(const char* buf, FILE* outFile) +{ + unsigned int slen = ChompStrlen(buf); + if ((slen < INTEL_HEX_MIN_LINE_LENGTH) + || (slen > INTEL_HEX_MAX_LINE_LENGTH)) + { + return false; + } + + // line length must be odd + if (slen % 2 == 0) + { + return false; + } + + if ((buf[0] != ':') || (buf[7] != '0')) + { + return false; + } + + unsigned int dataStart = 0; + if ((buf[8] == '0') || (buf[8] == '1')) + { + dataStart = 9; + } + // ignore extra address records + else if ((buf[8] == '2') || (buf[8] == '3') || (buf[8] == '4') || (buf[8] == '5')) + { + return true; + } + else // unknown record type + { + return false; + } + +// ignore the last two bytes (checksum) + return OutputBin(outFile, buf, dataStart, slen - 2); +} + +cmHexFileConverter::FileType cmHexFileConverter::DetermineFileType( + const char* inFileName) +{ + char buf[1024]; + FILE* inFile = fopen(inFileName, "rb"); + if (inFile == 0) + { + return Binary; + } + + fgets(buf, 1024, inFile); + fclose(inFile); + FileType type = Binary; + unsigned int minLineLength = 0; + unsigned int maxLineLength = 0; + if (buf[0] == ':') // might be an intel hex file + { + type = IntelHex; + minLineLength = INTEL_HEX_MIN_LINE_LENGTH; + maxLineLength = INTEL_HEX_MAX_LINE_LENGTH; + } + else if (buf[0] == 'S') // might be a motorola srec file + { + type = MotorolaSrec; + minLineLength = MOTOROLA_SREC_MIN_LINE_LENGTH; + maxLineLength = MOTOROLA_SREC_MAX_LINE_LENGTH; + } + else + { + return Binary; + } + + int slen = ChompStrlen(buf); + if ((slen < minLineLength) || (slen > maxLineLength)) + { + return Binary; + } + + for (unsigned int i = 1; i < slen; i++) + { + if (!cm_IsHexChar(buf[i])) + { + return Binary; + } + } + return type; +} + +bool cmHexFileConverter::TryConvert(const char* inFileName, + const char* outFileName) +{ + FileType type = DetermineFileType(inFileName); + if (type == Binary) + { + return false; + } + + // try to open the file + FILE* inFile = fopen(inFileName, "rb"); + FILE* outFile = fopen(outFileName, "wb"); + if ((inFile == 0) || (outFile == 0)) + { + if (inFile != 0) + { + fclose(inFile); + } + if (outFile != 0) + { + fclose(outFile); + } + return false; + } + + // convert them line by line + bool success = false; + char buf[1024]; + while (fgets(buf, 1024, inFile) != 0) + { + if (type == MotorolaSrec) + { + success = ConvertMotorolaSrecLine(buf, outFile); + } + else if (type == IntelHex) + { + success = ConvertIntelHexLine(buf, outFile); + } + if (success == false) + { + break; + } + } + + // close them again + fclose(inFile); + fclose(outFile); + return success; +} + diff --git a/Source/cmHexFileConverter.h b/Source/cmHexFileConverter.h new file mode 100644 index 0000000..8b6dc72 --- /dev/null +++ b/Source/cmHexFileConverter.h @@ -0,0 +1,33 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef cmHexFileConverter_h +#define cmHexFileConverter_h + +/** \class cmHexFileConverter + * \brief Can detects Intel Hex and Motorola S-record files and convert them + * to binary files. + * + */ +class cmHexFileConverter +{ +public: + enum FileType {Binary, IntelHex, MotorolaSrec}; + static FileType DetermineFileType(const char* inFileName); + static bool TryConvert(const char* inFileName, const char* outFileName); +}; + +#endif |