summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorAlexander Neundorf <neundorf@kde.org>2007-05-25 15:22:22 -0400
committerAlexander Neundorf <neundorf@kde.org>2007-05-25 15:22:22 -0400
commitf4eb541880bfc89456e26d8b3eb62ec590571da5 (patch)
tree4e549a05db829d9e7fd3324e3f687e0aa2499c65 /Source
parent1ed238c7f5f1e2573beb864ea7b2b0c5be4508f2 (diff)
downloadcmake-f4eb541880bfc89456e26d8b3eb62ec590571da5.tar.gz
ENH: make the compiler id detection work, even if the output file name of
the compiler is completely unknown and even if it produces intel hex or motorola s-record files, with test Alex
Diffstat (limited to 'Source')
-rw-r--r--Source/cmBootstrapCommands.cxx3
-rw-r--r--Source/cmFileCommand.cxx10
-rw-r--r--Source/cmFileCommand.h7
-rw-r--r--Source/cmHexFileConverter.cxx266
-rw-r--r--Source/cmHexFileConverter.h33
5 files changed, 315 insertions, 4 deletions
diff --git a/Source/cmBootstrapCommands.cxx b/Source/cmBootstrapCommands.cxx
index 19be6dfd56..f129eb08aa 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 ed3ac2c5e1..5b3390d72d 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 f758151d6f..5868725f7c 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 0000000000..f8d369f1d0
--- /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 0000000000..8b6dc7226b
--- /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