| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- /*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License 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 = static_cast<unsigned int>(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];
- unsigned 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;
- }
- unsigned 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;
- }
|