diff options
author | Alexander Neundorf <neundorf@kde.org> | 2007-05-25 19:22:22 (GMT) |
---|---|---|
committer | Alexander Neundorf <neundorf@kde.org> | 2007-05-25 19:22:22 (GMT) |
commit | f4eb541880bfc89456e26d8b3eb62ec590571da5 (patch) | |
tree | 4e549a05db829d9e7fd3324e3f687e0aa2499c65 /Source/cmHexFileConverter.cxx | |
parent | 1ed238c7f5f1e2573beb864ea7b2b0c5be4508f2 (diff) | |
download | CMake-f4eb541880bfc89456e26d8b3eb62ec590571da5.zip CMake-f4eb541880bfc89456e26d8b3eb62ec590571da5.tar.gz CMake-f4eb541880bfc89456e26d8b3eb62ec590571da5.tar.bz2 |
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/cmHexFileConverter.cxx')
-rw-r--r-- | Source/cmHexFileConverter.cxx | 266 |
1 files changed, 266 insertions, 0 deletions
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; +} + |