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