1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmHexFileConverter.cxx,v $
6 Date: $Date: 2007/07/20 12:36:16 $
7 Version: $Revision: 1.5 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmHexFileConverter.h"
22 #define INTEL_HEX_MIN_LINE_LENGTH (1+8 +2)
23 #define INTEL_HEX_MAX_LINE_LENGTH (1+8+(256*2)+2)
24 #define MOTOROLA_SREC_MIN_LINE_LENGTH (2+2+4 +2)
25 #define MOTOROLA_SREC_MAX_LINE_LENGTH (2+2+8+(256*2)+2)
27 // might go to SystemTools ?
28 static bool cm_IsHexChar(char c
)
30 return (((c
>= '0') && (c
<= '9'))
31 || ((c
>= 'a') && (c
<= 'f'))
32 || ((c
>= 'A') && (c
<= 'F')));
35 static unsigned int ChompStrlen(const char* line
)
41 unsigned int length
= static_cast<unsigned int>(strlen(line
));
42 if ((line
[length
-1] == '\n') || (line
[length
-1] == '\r'))
46 if ((line
[length
-1] == '\n') || (line
[length
-1] == '\r'))
53 static bool OutputBin(FILE* file
, const char * buf
,
54 unsigned int startIndex
, unsigned int stopIndex
)
60 unsigned int outBufCount
= 0;
61 for (unsigned int i
= startIndex
; i
< stopIndex
; i
+= 2)
63 hexNumber
[0] = buf
[i
];
64 hexNumber
[1] = buf
[i
+1];
65 unsigned int convertedByte
= 0;
66 if (sscanf(hexNumber
, "%x", &convertedByte
) != 1)
71 outBuf
[outBufCount
] = convertedByte
& 0xff;
76 success
= (fwrite(outBuf
, 1, outBufCount
, file
)==outBufCount
);
81 // see http://www.die.net/doc/linux/man/man5/srec.5.html
82 static bool ConvertMotorolaSrecLine(const char* buf
, FILE* outFile
)
84 unsigned int slen
= ChompStrlen(buf
);
85 if ((slen
< MOTOROLA_SREC_MIN_LINE_LENGTH
)
86 || (slen
> MOTOROLA_SREC_MAX_LINE_LENGTH
))
91 // line length must be even
102 unsigned int dataStart
= 0;
103 // ignore extra address records
104 if ((buf
[1] == '5') || (buf
[1] == '7') || (buf
[1] == '8') || (buf
[1] == '9'))
108 else if (buf
[1] == '1')
112 else if (buf
[1] == '2')
116 else if (buf
[1] == '3')
120 else // unknown record type
125 // ignore the last two bytes (checksum)
126 return OutputBin(outFile
, buf
, dataStart
, slen
- 2);
129 // see http://en.wikipedia.org/wiki/Intel_hex
130 static bool ConvertIntelHexLine(const char* buf
, FILE* outFile
)
132 unsigned int slen
= ChompStrlen(buf
);
133 if ((slen
< INTEL_HEX_MIN_LINE_LENGTH
)
134 || (slen
> INTEL_HEX_MAX_LINE_LENGTH
))
139 // line length must be odd
145 if ((buf
[0] != ':') || (buf
[7] != '0'))
150 unsigned int dataStart
= 0;
151 if ((buf
[8] == '0') || (buf
[8] == '1'))
155 // ignore extra address records
156 else if ((buf
[8] == '2') || (buf
[8] == '3') || (buf
[8] == '4')
161 else // unknown record type
166 // ignore the last two bytes (checksum)
167 return OutputBin(outFile
, buf
, dataStart
, slen
- 2);
170 cmHexFileConverter::FileType
cmHexFileConverter::DetermineFileType(
171 const char* inFileName
)
174 FILE* inFile
= fopen(inFileName
, "rb");
180 fgets(buf
, 1024, inFile
);
182 FileType type
= Binary
;
183 unsigned int minLineLength
= 0;
184 unsigned int maxLineLength
= 0;
185 if (buf
[0] == ':') // might be an intel hex file
188 minLineLength
= INTEL_HEX_MIN_LINE_LENGTH
;
189 maxLineLength
= INTEL_HEX_MAX_LINE_LENGTH
;
191 else if (buf
[0] == 'S') // might be a motorola srec file
194 minLineLength
= MOTOROLA_SREC_MIN_LINE_LENGTH
;
195 maxLineLength
= MOTOROLA_SREC_MAX_LINE_LENGTH
;
202 unsigned int slen
= ChompStrlen(buf
);
203 if ((slen
< minLineLength
) || (slen
> maxLineLength
))
208 for (unsigned int i
= 1; i
< slen
; i
++)
210 if (!cm_IsHexChar(buf
[i
]))
218 bool cmHexFileConverter::TryConvert(const char* inFileName
,
219 const char* outFileName
)
221 FileType type
= DetermineFileType(inFileName
);
227 // try to open the file
228 FILE* inFile
= fopen(inFileName
, "rb");
229 FILE* outFile
= fopen(outFileName
, "wb");
230 if ((inFile
== 0) || (outFile
== 0))
243 // convert them line by line
244 bool success
= false;
246 while (fgets(buf
, 1024, inFile
) != 0)
248 if (type
== MotorolaSrec
)
250 success
= ConvertMotorolaSrecLine(buf
, outFile
);
252 else if (type
== IntelHex
)
254 success
= ConvertIntelHexLine(buf
, outFile
);
256 if (success
== false)