1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
12 #include "cmHexFileConverter.h"
17 #define INTEL_HEX_MIN_LINE_LENGTH (1+8 +2)
18 #define INTEL_HEX_MAX_LINE_LENGTH (1+8+(256*2)+2)
19 #define MOTOROLA_SREC_MIN_LINE_LENGTH (2+2+4 +2)
20 #define MOTOROLA_SREC_MAX_LINE_LENGTH (2+2+8+(256*2)+2)
22 // might go to SystemTools ?
23 static bool cm_IsHexChar(char c)
25 return (((c >= '0') && (c <= '9'))
26 || ((c >= 'a') && (c <= 'f'))
27 || ((c >= 'A') && (c <= 'F')));
30 static unsigned int ChompStrlen(const char* line)
36 unsigned int length = static_cast<unsigned int>(strlen(line));
37 if ((line[length-1] == '\n') || (line[length-1] == '\r'))
41 if ((line[length-1] == '\n') || (line[length-1] == '\r'))
48 static bool OutputBin(FILE* file, const char * buf,
49 unsigned int startIndex, unsigned int stopIndex)
55 unsigned int outBufCount = 0;
56 for (unsigned int i = startIndex; i < stopIndex; i += 2)
58 hexNumber[0] = buf[i];
59 hexNumber[1] = buf[i+1];
60 unsigned int convertedByte = 0;
61 if (sscanf(hexNumber, "%x", &convertedByte) != 1)
66 outBuf[outBufCount] = static_cast<char>(convertedByte & 0xff);
71 success = (fwrite(outBuf, 1, outBufCount, file)==outBufCount);
76 // see http://www.die.net/doc/linux/man/man5/srec.5.html
77 static bool ConvertMotorolaSrecLine(const char* buf, FILE* outFile)
79 unsigned int slen = ChompStrlen(buf);
80 if ((slen < MOTOROLA_SREC_MIN_LINE_LENGTH)
81 || (slen > MOTOROLA_SREC_MAX_LINE_LENGTH))
86 // line length must be even
97 unsigned int dataStart = 0;
98 // ignore extra address records
99 if ((buf[1] == '5') || (buf[1] == '7') || (buf[1] == '8') || (buf[1] == '9'))
103 else if (buf[1] == '1')
107 else if (buf[1] == '2')
111 else if (buf[1] == '3')
115 else // unknown record type
120 // ignore the last two bytes (checksum)
121 return OutputBin(outFile, buf, dataStart, slen - 2);
124 // see http://en.wikipedia.org/wiki/Intel_hex
125 static bool ConvertIntelHexLine(const char* buf, FILE* outFile)
127 unsigned int slen = ChompStrlen(buf);
128 if ((slen < INTEL_HEX_MIN_LINE_LENGTH)
129 || (slen > INTEL_HEX_MAX_LINE_LENGTH))
134 // line length must be odd
140 if ((buf[0] != ':') || (buf[7] != '0'))
145 unsigned int dataStart = 0;
146 if ((buf[8] == '0') || (buf[8] == '1'))
150 // ignore extra address records
151 else if ((buf[8] == '2') || (buf[8] == '3') || (buf[8] == '4')
156 else // unknown record type
161 // ignore the last two bytes (checksum)
162 return OutputBin(outFile, buf, dataStart, slen - 2);
165 cmHexFileConverter::FileType cmHexFileConverter::DetermineFileType(
166 const char* inFileName)
169 FILE* inFile = fopen(inFileName, "rb");
175 if(!fgets(buf, 1024, inFile))
180 FileType type = Binary;
181 unsigned int minLineLength = 0;
182 unsigned int maxLineLength = 0;
183 if (buf[0] == ':') // might be an intel hex file
186 minLineLength = INTEL_HEX_MIN_LINE_LENGTH;
187 maxLineLength = INTEL_HEX_MAX_LINE_LENGTH;
189 else if (buf[0] == 'S') // might be a motorola srec file
192 minLineLength = MOTOROLA_SREC_MIN_LINE_LENGTH;
193 maxLineLength = MOTOROLA_SREC_MAX_LINE_LENGTH;
200 unsigned int slen = ChompStrlen(buf);
201 if ((slen < minLineLength) || (slen > maxLineLength))
206 for (unsigned int i = 1; i < slen; i++)
208 if (!cm_IsHexChar(buf[i]))
216 bool cmHexFileConverter::TryConvert(const char* inFileName,
217 const char* outFileName)
219 FileType type = DetermineFileType(inFileName);
225 // try to open the file
226 FILE* inFile = fopen(inFileName, "rb");
227 FILE* outFile = fopen(outFileName, "wb");
228 if ((inFile == 0) || (outFile == 0))
241 // convert them line by line
242 bool success = false;
244 while (fgets(buf, 1024, inFile) != 0)
246 if (type == MotorolaSrec)
248 success = ConvertMotorolaSrecLine(buf, outFile);
250 else if (type == IntelHex)
252 success = ConvertIntelHexLine(buf, outFile);
254 if (success == false)