source: rtems/tools/build/rtems-bin2c.c @ 1281c34

4.115
Last change on this file since 1281c34 was 1281c34, checked in by Gedare Bloom <gedare@…>, on 02/23/15 at 15:38:37

Use counted strnlen in bin2c. Closes #2238.

  • Property mode set to 100644
File size: 7.0 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)
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 = strdup(ifname);
123  if ( ifbasename_to_free == NULL ) {
124    fprintf(stderr, "cannot allocate memory\n" );
125    fclose(ifile);
126    if ( createC ) { fclose(ocfile); }
127    if ( createH ) { fclose(ohfile); }
128    exit(1);
129  }
130
131  char *ifbasename;
132  ifbasename = basename(ifbasename_to_free);
133
134  strcpy(buf, ifbasename);
135  for (p = buf; *p != '\0'; ++p) {
136    if (!isalnum((unsigned char)*p)) /* cast to avoid negative indexing */
137      *p = '_';
138  }
139
140  if ( createC ) {
141    /* print C file header */
142    fprintf(
143      ocfile,
144      "/*\n"
145      " *  Declarations for C structure representing binary file %s\n"
146      " *\n"
147      " *  WARNING: Automatically generated -- do not edit!\n"
148      " */\n"
149      "\n"
150      "#include <sys/types.h>\n"
151      "\n",
152      ifbasename
153    );
154
155    /* print structure */
156    fprintf(
157      ocfile,
158      "%s%sunsigned char %s[] = {\n  ",
159      ((usestatic) ? "static " : ""),
160      ((useconst) ? "const " : ""),
161      buf
162    );
163    int c, col = 1;
164    while ((c = myfgetc(ifile)) != EOF) {
165      if (col >= 78 - 6) {
166        fprintf(ocfile, "\n  ");
167        col = 1;
168      }
169      fprintf(ocfile, "0x%.2x, ", c);
170      col += 6;
171
172    }
173    fprintf(ocfile, "\n};\n");
174
175    /* print sizeof */
176    fprintf(
177      ocfile,
178      "\n"
179      "%s%ssize_t %s_size = sizeof(%s);\n",
180      ((usestatic) ? "static " : ""),
181      ((useconst) ? "const " : ""),
182      buf,
183      buf
184    );
185  } /* createC */
186
187  /*****************************************************************/
188  /******                    END OF C FILE                     *****/
189  /*****************************************************************/
190
191  if ( createH ) {
192    /* print H file header */
193    char hbasename[PATH_MAX];
194    char* p;
195    /* Clean up the file name if it is an abs path */
196    strcpy(
197      hbasename,
198      obasename
199    );
200    p = hbasename;
201    while (*p != '\0') {
202      if (*p < '0' || *p > 'z')
203        *p = '_';
204      ++p;
205    }
206    fprintf(
207      ohfile,
208      "/*\n"
209      " *  Extern declarations for C structure representing binary file %s\n"
210      " *\n"
211      " *  WARNING: Automatically generated -- do not edit!\n"
212      " */\n"
213      "\n"
214      "#ifndef __%s_h\n"
215      "#define __%s_h\n"
216      "\n"
217      "#include <sys/types.h>\n"
218      "\n",
219      ifbasename,  /* header */
220      hbasename,  /* ifndef */
221      hbasename   /* define */
222    );
223
224    /* print structure */
225    fprintf(
226      ohfile,
227      "extern %s%sunsigned char %s[];",
228      ((usestatic) ? "static " : ""),
229      ((useconst) ? "const " : ""),
230      buf
231    );
232    /* print sizeof */
233    fprintf(
234      ohfile,
235      "\n"
236      "extern %s%ssize_t %s_size;\n",
237      ((usestatic) ? "static " : ""),
238      ((useconst) ? "const " : ""),
239      buf
240    );
241
242    fprintf(
243      ohfile,
244      "\n"
245      "#endif\n"
246    );
247  } /* createH */
248
249  /*****************************************************************/
250  /******                    END OF H FILE                     *****/
251  /*****************************************************************/
252
253  fclose(ifile);
254  if ( createC ) { fclose(ocfile); }
255  if ( createH ) { fclose(ohfile); }
256  free(ifbasename_to_free);
257}
258
259void usage(void)
260{
261  fprintf(
262     stderr,
263     "usage: bin2c [-csvzCH] <input_file> <output_file>\n"
264     "  <input_file> is the binary file to convert\n"
265     "  <output_file> should not have a .c or .h extension\n"
266     "\n"
267     "  -c - do NOT use const in declaration\n"
268     "  -s - do use static in declaration\n"
269     "  -v - verbose\n"
270     "  -z - add zero terminator\n"
271     "  -H - create c-header only\n"
272     "  -C - create c-source file only\n"
273    );
274  exit(1);
275}
276
277int main(int argc, char **argv)
278{
279  while (argc > 3) {
280    if (!strcmp(argv[1], "-c")) {
281      useconst = 0;
282      --argc;
283      ++argv;
284    } else if (!strcmp(argv[1], "-s")) {
285      usestatic = 1;
286      --argc;
287      ++argv;
288    } else if (!strcmp(argv[1], "-v")) {
289      verbose = 1;
290      --argc;
291      ++argv;
292    } else if (!strcmp(argv[1], "-z")) {
293      zeroterminated = 1;
294      --argc;
295      ++argv;
296    } else if (!strcmp(argv[1], "-C")) {
297      createH = 0;
298      createC = 1;
299      --argc;
300      ++argv;
301    } else if (!strcmp(argv[1], "-H")) {
302      createC = 0;
303      createH = 1;
304      --argc;
305      ++argv;
306    } else {
307      usage();
308    }
309  }
310  if (argc != 3) {
311    usage();
312  }
313
314  /* process( input_file, output_basename ) */
315  process(argv[1], argv[2]);
316  return 0;
317}
318
Note: See TracBrowser for help on using the repository browser.