source: rtems/tools/build/rtems-bin2c.c @ 31cd205d

5
Last change on this file since 31cd205d was 31cd205d, checked in by Chris Johns <chrisj@…>, on 04/12/18 at 04:12:06

tools: Add a -N option to force a name on the array.

This can be used to have a different file name for the same data
name.

Update #2769

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*
2 * bin2c.c
3 *
4 * convert a binary file into a C source array.
5 *
6 * THE "BEER-WARE LICENSE" (Revision 3.1415):
7 * sandro AT sigala DOT it wrote this file. As long as you retain this
8 * notice you can do whatever you want with this stuff.  If we meet some
9 * day, and you think this stuff is worth it, you can buy me a beer in
10 * return.  Sandro Sigala
11 *
12 * Subsequently modified by Joel Sherrill <joel.sherrill@oarcorp.com>
13 * to add a number of capabilities not in the original.
14 *
15 * syntax:  bin2c [-c] [-z] <input_file> <output_file>
16 *
17 *    -c    do NOT add the "const" keyword to definition
18 *    -s    add the "static" keywork to definition
19 *    -v    verbose
20 *    -z    terminate the array with a zero (useful for embedded C strings)
21 *
22 * examples:
23 *     bin2c -c myimage.png myimage_png.cpp
24 *     bin2c -z sometext.txt sometext_txt.cpp
25 *
26 */
27
28#include <ctype.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <libgen.h>
33
34#ifndef PATH_MAX
35#define PATH_MAX 1024
36#endif
37
38int useconst = 1;
39int usestatic = 0;
40int verbose = 0;
41int zeroterminated = 0;
42int createC = 1;
43int createH = 1;
44
45int myfgetc(FILE *f)
46{
47  int c = fgetc(f);
48  if (c == EOF && zeroterminated) {
49    zeroterminated = 0;
50    return 0;
51  }
52  return c;
53}
54
55void process(const char *ifname, const char *ofname, const char *forced_name)
56{
57  FILE *ifile, *ocfile, *ohfile;
58  char buf[PATH_MAX+1], *p;
59  char obasename[PATH_MAX+1];
60  char ocname[PATH_MAX+1];
61  char ohname[PATH_MAX+1];
62  const char *cp;
63  size_t len;
64
65  ocfile = NULL;
66  ohfile = NULL;
67
68  /* Error check */
69  if ( !ifname || !ofname ) {
70    fprintf(stderr, "process has NULL filename\n");
71    exit(1);
72  }
73
74  strncpy( obasename, ofname, PATH_MAX );
75  len = strnlen( obasename, PATH_MAX );
76  if ( len >= 2 ) {
77    if ( obasename[len-2] == '.' ) {
78      if ( (obasename[len-1] == 'c') || (obasename[len-1] == 'h') )
79        obasename[len-2] = '\0';
80    }
81  }
82
83  sprintf( ocname, "%s.c", obasename );
84  sprintf( ohname, "%s.h", obasename );
85
86  if ( verbose ) {
87    fprintf(
88      stderr,
89      "in file: %s\n"
90      "c file: %s\n"
91      "h file: %s\n",
92      ifname,
93      ocname,
94      ohname
95    );
96  }
97
98  /* Open input and output files */
99  ifile = fopen(ifname, "rb");
100  if (ifile == NULL) {
101    fprintf(stderr, "cannot open %s for reading\n", ifname);
102    exit(1);
103  }
104
105  if ( createC ) {
106    ocfile = fopen(ocname, "wb");
107    if (ocfile == NULL) {
108      fprintf(stderr, "cannot open %s for writing\n", ocname);
109      exit(1);
110    }
111  }
112
113  if ( createH ) {
114    ohfile = fopen(ohname, "wb");
115    if (ohfile == NULL) {
116      fprintf(stderr, "cannot open %s for writing\n", ohname);
117      exit(1);
118    }
119  }
120
121  /* find basename */
122  char *ifbasename_to_free =
123    forced_name != NULL ? strdup(forced_name) : strdup(ifname);
124  if ( ifbasename_to_free == NULL ) {
125    fprintf(stderr, "cannot allocate memory\n" );
126    fclose(ifile);
127    if ( createC ) { fclose(ocfile); }
128    if ( createH ) { fclose(ohfile); }
129    exit(1);
130  }
131
132  char *ifbasename;
133  ifbasename = basename(ifbasename_to_free);
134
135  strcpy(buf, ifbasename);
136  for (p = buf; *p != '\0'; ++p) {
137    if (!isalnum((unsigned char)*p)) /* cast to avoid negative indexing */
138      *p = '_';
139  }
140
141  if ( createC ) {
142    /* print C file header */
143    fprintf(
144      ocfile,
145      "/*\n"
146      " *  Declarations for C structure representing binary file %s\n"
147      " *\n"
148      " *  WARNING: Automatically generated -- do not edit!\n"
149      " */\n"
150      "\n"
151      "#include <sys/types.h>\n"
152      "\n",
153      ifbasename
154    );
155
156    /* print structure */
157    fprintf(
158      ocfile,
159      "%s%sunsigned char %s[] = {\n  ",
160      ((usestatic) ? "static " : ""),
161      ((useconst) ? "const " : ""),
162      buf
163    );
164    int c, col = 1;
165    while ((c = myfgetc(ifile)) != EOF) {
166      if (col >= 78 - 6) {
167        fprintf(ocfile, "\n  ");
168        col = 1;
169      }
170      fprintf(ocfile, "0x%.2x, ", c);
171      col += 6;
172
173    }
174    fprintf(ocfile, "\n};\n");
175
176    /* print sizeof */
177    fprintf(
178      ocfile,
179      "\n"
180      "%s%ssize_t %s_size = sizeof(%s);\n",
181      ((usestatic) ? "static " : ""),
182      ((useconst) ? "const " : ""),
183      buf,
184      buf
185    );
186  } /* createC */
187
188  /*****************************************************************/
189  /******                    END OF C FILE                     *****/
190  /*****************************************************************/
191
192  if ( createH ) {
193    /* print H file header */
194    char hbasename[PATH_MAX];
195    char* p;
196    /* Clean up the file name if it is an abs path */
197    strcpy(
198      hbasename,
199      obasename
200    );
201    p = hbasename;
202    while (*p != '\0') {
203      if (*p < '0' || *p > 'z')
204        *p = '_';
205      ++p;
206    }
207    fprintf(
208      ohfile,
209      "/*\n"
210      " *  Extern declarations for C structure representing binary file %s\n"
211      " *\n"
212      " *  WARNING: Automatically generated -- do not edit!\n"
213      " */\n"
214      "\n"
215      "#ifndef __%s_h\n"
216      "#define __%s_h\n"
217      "\n"
218      "#include <sys/types.h>\n"
219      "\n",
220      ifbasename,  /* header */
221      hbasename,  /* ifndef */
222      hbasename   /* define */
223    );
224
225    /* print structure */
226    fprintf(
227      ohfile,
228      "extern %s%sunsigned char %s[];",
229      ((usestatic) ? "static " : ""),
230      ((useconst) ? "const " : ""),
231      buf
232    );
233    /* print sizeof */
234    fprintf(
235      ohfile,
236      "\n"
237      "extern %s%ssize_t %s_size;\n",
238      ((usestatic) ? "static " : ""),
239      ((useconst) ? "const " : ""),
240      buf
241    );
242
243    fprintf(
244      ohfile,
245      "\n"
246      "#endif\n"
247    );
248  } /* createH */
249
250  /*****************************************************************/
251  /******                    END OF H FILE                     *****/
252  /*****************************************************************/
253
254  fclose(ifile);
255  if ( createC ) { fclose(ocfile); }
256  if ( createH ) { fclose(ohfile); }
257  free(ifbasename_to_free);
258}
259
260void usage(void)
261{
262  fprintf(
263     stderr,
264     "usage: bin2c [-csvzCH] [-N name] <input_file> <output_file>\n"
265     "  <input_file> is the binary file to convert\n"
266     "  <output_file> should not have a .c or .h extension\n"
267     "\n"
268     "  -c - do NOT use const in declaration\n"
269     "  -s - do use static in declaration\n"
270     "  -v - verbose\n"
271     "  -z - add zero terminator\n"
272     "  -H - create c-header only\n"
273     "  -C - create c-source file only\n"
274     "  -N - force name of data array\n"
275    );
276  exit(1);
277}
278
279int main(int argc, char **argv)
280{
281  const char *name = NULL;
282  while (argc > 3) {
283    if (!strcmp(argv[1], "-c")) {
284      useconst = 0;
285      --argc;
286      ++argv;
287    } else if (!strcmp(argv[1], "-s")) {
288      usestatic = 1;
289      --argc;
290      ++argv;
291    } else if (!strcmp(argv[1], "-v")) {
292      verbose = 1;
293      --argc;
294      ++argv;
295    } else if (!strcmp(argv[1], "-z")) {
296      zeroterminated = 1;
297      --argc;
298      ++argv;
299    } else if (!strcmp(argv[1], "-C")) {
300      createH = 0;
301      createC = 1;
302      --argc;
303      ++argv;
304    } else if (!strcmp(argv[1], "-H")) {
305      createC = 0;
306      createH = 1;
307      --argc;
308      ++argv;
309    } else if (!strcmp(argv[1], "-N")) {
310      --argc;
311      ++argv;
312      if (argc <= 1) {
313        fprintf(stderr, "error: -N needs a name\n");
314        usage();
315      }
316      name = argv[1];
317      --argc;
318      ++argv;
319    } else {
320      usage();
321    }
322  }
323  if (argc != 3) {
324    usage();
325  }
326
327  /* process( input_file, output_basename ) */
328  process(argv[1], argv[2], name);
329  return 0;
330}
Note: See TracBrowser for help on using the repository browser.