[TOOLS_BIN2C]
[reactos.git] / reactos / tools / bin2c.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS bin2c
4 * FILE: tools/bin2c/bin2c.c
5 * PURPOSE: Converts a binary file into a byte array
6 * PROGRAMMER: Hermès Bélusca - Maïto
7 */
8
9 #include <stdio.h>
10
11 static size_t dumpHex(FILE* inFile, FILE* outCFile, char nullTerminate)
12 {
13 size_t bufLen = 0;
14 unsigned char ch;
15
16 fprintf(outCFile, "\n{");
17 do
18 {
19 /* Read the next byte */
20 ch = fgetc(inFile);
21
22 if (feof(inFile) && nullTerminate)
23 ch = 0x00;
24
25 if (!feof(inFile) || nullTerminate)
26 {
27 /* Start a new line if needed */
28 if ((bufLen % 16) == 0)
29 fprintf(outCFile, "\n ");
30
31 /* Write the byte or the optional NULL terminator */
32 fprintf(outCFile, " 0x%02x,", (unsigned int)ch);
33
34 ++bufLen;
35 }
36 } while (!feof(inFile));
37 fprintf(outCFile, "\n}");
38
39 return bufLen;
40 }
41
42 static size_t dumpStr(FILE* inFile, FILE* outCFile)
43 {
44 size_t bufLen = 0;
45 unsigned char ch;
46
47 /* Always start the first line */
48 fprintf(outCFile, "\n \"");
49 do
50 {
51 /* Read the next byte */
52 ch = fgetc(inFile);
53
54 /* If a byte is available... */
55 if (!feof(inFile))
56 {
57 /* ... do we need to start a new line? */
58 if ((bufLen != 0) && (bufLen % 16) == 0)
59 {
60 /* Yes, end the current line and start a new one */
61 fprintf(outCFile, "\"");
62 fprintf(outCFile, "\n \"");
63 }
64
65 /* Now write the byte */
66 fprintf(outCFile, "\\x%02x", (unsigned int)ch);
67 }
68 /* ... otherwise, end the current line... */
69 else
70 {
71 fprintf(outCFile, "\"");
72 /* We break just after */
73 }
74
75 ++bufLen; // This takes also the final NULL terminator into account.
76
77 } while (!feof(inFile));
78
79 return bufLen;
80 }
81
82 static void usage(char* name)
83 {
84 fprintf(stdout, "Usage: %s infile.bin outfile.c outfile.h [BIN|BINSTR|STR] array_name [array_attribute [header_for_attribute]]\n", name);
85 }
86
87 int main(int argc, char* argv[])
88 {
89 FILE* inFile;
90 FILE* outCFile;
91 FILE* outHFile;
92 size_t bufLen;
93
94 /* Validate the arguments */
95 if (argc < 6)
96 {
97 usage(argv[0]);
98 return -1;
99 }
100
101 /* Verify the output format */
102 if (_stricmp(argv[4], "BIN" ) != 0 &&
103 _stricmp(argv[4], "BINSTR") != 0 &&
104 _stricmp(argv[4], "STR" ) != 0)
105 {
106 usage(argv[0]);
107 return -1;
108 }
109
110 /* Open the input and output files */
111 inFile = fopen(argv[1], "rb");
112 if (!inFile)
113 {
114 fprintf(stderr, "ERROR: Couldn't open data file '%s'.\n", argv[1]);
115 return -1;
116 }
117 outCFile = fopen(argv[2], "w");
118 if (!outCFile)
119 {
120 fclose(inFile);
121 fprintf(stderr, "ERROR: Couldn't create output source file '%s'.\n", argv[2]);
122 return -1;
123 }
124 outHFile = fopen(argv[3], "w");
125 if (!outHFile)
126 {
127 fclose(outCFile);
128 fclose(inFile);
129 fprintf(stderr, "ERROR: Couldn't create output header file '%s'.\n", argv[3]);
130 return -1;
131 }
132
133 /* Generate the source file and close it */
134 fprintf(outCFile, "/* This file is autogenerated, do not edit. */\n\n");
135 if (argc >= 8)
136 {
137 /* Include needed header for defining the array attribute */
138 fprintf(outCFile, "#include \"%s\"\n", argv[7]);
139 }
140 fprintf(outCFile, "#include \"%s\"\n\n", argv[3]);
141
142 /* Generate the data array */
143 if (argc >= 7)
144 {
145 /* Add the array attribute */
146 fprintf(outCFile, "%s ", argv[6]);
147 }
148 fprintf(outCFile, "unsigned char %s[] =", argv[5]);
149
150 /* Output the bytes in the chosen format */
151 if (_stricmp(argv[4], "BIN") == 0)
152 bufLen = dumpHex(inFile, outCFile, 0);
153 else if (_stricmp(argv[4], "BINSTR") == 0)
154 bufLen = dumpHex(inFile, outCFile, 1);
155 else // (_stricmp(argv[4], "STR") == 0)
156 bufLen = dumpStr(inFile, outCFile);
157
158 fprintf(outCFile, ";\n");
159 fclose(outCFile);
160
161 /* Generate the header file and close it */
162 fprintf(outHFile, "/* This file is autogenerated, do not edit. */\n\n");
163 fprintf(outHFile, "#define %s_SIZE %lu\n" , argv[5], bufLen);
164 fprintf(outHFile, "extern unsigned char %s[%lu];\n", argv[5], bufLen);
165 fclose(outHFile);
166
167 /* Close the input file */
168 fclose(inFile);
169
170 return 0;
171 }
172
173 /* EOF */