version 2.8
file2c.c
1 /*
2  * This file is subject to the terms of the GFX License. If a copy of
3  * the license was not distributed with this file, you can obtain one at:
4  *
5  * http://ugfx.org/license.html
6  */
7 
8 #include <stdio.h>
9 #include <fcntl.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <time.h>
13 #ifdef WIN32
14  #include <io.h>
15 #endif
16 
17 static unsigned char buf[1024];
18 static char tname[FILENAME_MAX];
19 
20 static char *filenameof(char *fname) {
21  char *p;
22 
23 #ifdef WIN32
24  if (fname[1] == ':')
25  fname = fname+2;
26  p = strrchr(fname, '\\');
27  if (p) fname = p+1;
28 #endif
29  p = strrchr(fname, '/');
30  if (p) fname = p+1;
31  return fname;
32 }
33 
34 static char *basenameof(char *fname) {
35  char *p;
36 
37  fname = filenameof(fname);
38  p = strchr(fname, '.');
39  if (p) *p = 0;
40  return fname;
41 }
42 
43 static char *clean4c(char *fname) {
44  char *p;
45 
46  while((p = strpbrk(fname, "-+ `~!@#$%^&*(){}[]|:;'\",<>?/|=.\\"))) *p = '_';
47  return fname;
48 }
49 
50 int main(int argc, char * argv[])
51 {
52 char * opt_progname;
53 char * opt_inputfile;
54 char * opt_outputfile;
55 char * opt_arrayname;
56 char * opt_dirname;
57 int opt_breakblocks;
58 int opt_romdir;
59 char * opt_static;
60 char * opt_const;
61 FILE * f_input;
62 FILE * f_output;
63 unsigned blocknum;
64 size_t len, totallen;
65 size_t i;
66 
67  /* Default values for our parameters */
68  opt_progname = basenameof(argv[0]);
69  opt_inputfile = opt_outputfile = opt_arrayname = opt_dirname = 0;
70  opt_breakblocks = opt_romdir = 0;
71  opt_static = opt_const = "";
72 
73  /* Read the arguments */
74  while(*++argv) {
75  if (argv[0][0] == '-') {
76  while (*++(argv[0])) {
77  switch(argv[0][0]) {
78  case '?': case 'h': goto usage;
79  case 'd': opt_romdir = 1; break;
80  case 'b': opt_breakblocks = 1; break;
81  case 'c': opt_const = "const "; break;
82  case 's': opt_static = "static "; break;
83  case 'n': opt_arrayname = *++argv; goto nextarg;
84  case 'f': opt_romdir = 1; opt_dirname = *++argv; goto nextarg;
85  default:
86  fprintf(stderr, "Unknown flag -%c\n", argv[0][0]);
87  goto usage;
88  }
89  }
90  } else if (!opt_inputfile)
91  opt_inputfile = argv[0];
92  else if (!opt_outputfile)
93  opt_outputfile = argv[0];
94  else {
95  usage:
96  fprintf(stderr, "Usage:\n\n%s -?\n"
97  "%s [-dbcs] [-n name] [-f file] [inputfile] [outputfile]\n"
98  "\t-?\tThis help\n"
99  "\t-h\tThis help\n"
100  "\t-d\tAdd a directory entry for the ROM file system\n"
101  "\t-b\tBreak the arrays for compilers that won't handle large arrays\n"
102  "\t-c\tDeclare as const (useful to ensure they end up in Flash)\n"
103  "\t-s\tDeclare as static\n"
104  "\t-n name\tUse \"name\" as the name of the array\n"
105  "\t-f file\tUse \"file\" as the filename in the ROM directory entry\n"
106  , opt_progname, opt_progname);
107  return 1;
108  }
109  nextarg: ;
110  }
111 
112  /* Make sure we can generate a default directory name if required */
113  if (opt_romdir && !opt_dirname && !opt_inputfile) {
114  fprintf(stderr, "If using -d you must either specify an input filename or use -f to specify a directory entry filename\n");
115  goto usage;
116  }
117 
118  /* Open the input file */
119  if (opt_inputfile) {
120  f_input = fopen(opt_inputfile,
121 #ifdef WIN32
122  "rb");
123 #else
124  "r");
125 #endif
126  if (!f_input) {
127  fprintf(stderr, "Could not open input file '%s'\n", opt_inputfile);
128  goto usage;
129  }
130  } else {
131  f_input = stdin;
132 #ifdef WIN32
133  _setmode(_fileno(stdin), _O_BINARY);
134 #endif
135  }
136 
137  /* Open the output file */
138  if (opt_outputfile) {
139  f_output = fopen(opt_outputfile, "w");
140  if (!f_output) {
141  fprintf(stderr, "Could not open output file '%s'\n", opt_outputfile);
142  goto usage;
143  }
144  } else
145  f_output = stdout;
146 
147  /* Print the comment header */
148  fprintf(f_output, "/**\n * This file was generated ");
149  if (opt_inputfile) fprintf(f_output, "from \"%s\" ", opt_inputfile);
150  fprintf(f_output, "using...\n *\n *\t%s", opt_progname);
151  if (opt_arrayname || opt_static[0] || opt_const[0] || opt_breakblocks || opt_romdir) {
152  fprintf(f_output, " -");
153  if (opt_romdir) fprintf(f_output, "d");
154  if (opt_breakblocks) fprintf(f_output, "b");
155  if (opt_const[0]) fprintf(f_output, "c");
156  if (opt_static[0]) fprintf(f_output, "s");
157  if (opt_arrayname) fprintf(f_output, "n %s", opt_arrayname);
158  if (opt_dirname) fprintf(f_output, (opt_arrayname ? " -f %s" : "f %s"), opt_dirname);
159  }
160  if (opt_inputfile) fprintf(f_output, " %s", opt_inputfile);
161  if (opt_outputfile) fprintf(f_output, " %s", opt_outputfile);
162  fprintf(f_output, "\n *\n */\n");
163 
164  /*
165  * Set the array name and dir name
166  */
167  if (!opt_arrayname) {
168  if (opt_inputfile)
169  opt_arrayname = basenameof(strcpy(tname, opt_inputfile));
170  if (!opt_arrayname || !opt_arrayname[0]) {
171  srand(time(0));
172  sprintf(tname, "filearray%u", rand());
173  opt_arrayname = tname;
174  }
175  }
176  opt_arrayname = clean4c(opt_arrayname);
177  if (opt_romdir && !opt_dirname)
178  opt_dirname = filenameof(opt_inputfile);
179 
180  /* Read the file processing 1K at a time */
181  blocknum = 0;
182  totallen = 0;
183  while((len = fread(buf, 1, sizeof(buf), f_input))) {
184  if (!blocknum++)
185  fprintf(f_output, "%s%schar %s[] = {", opt_static, opt_const, opt_arrayname);
186  else if (opt_breakblocks)
187  fprintf(f_output, "\n};\n%s%schar %s_p%u[] = {", opt_static, opt_const, opt_arrayname, blocknum);
188  for(i = 0; i < len; i++) {
189  fprintf(f_output, (i & 0x0F) ? " 0x%02X," : "\n\t0x%02X,", buf[i]);
190  }
191  totallen += len;
192  }
193  fprintf(f_output, "\n};\n");
194 
195  /* Add the directory entry if required */
196  if (opt_romdir) {
197  fprintf(f_output, "\n#ifdef ROMFS_DIRENTRY_HEAD\n");
198  fprintf(f_output, "\t%s%sROMFS_DIRENTRY %s_dir = { 0, 0, ROMFS_DIRENTRY_HEAD, \"%s\", %u, %s };\n", opt_static, opt_const, opt_arrayname, opt_dirname, totallen, opt_arrayname);
199  fprintf(f_output, "\t#undef ROMFS_DIRENTRY_HEAD\n\t#define ROMFS_DIRENTRY_HEAD &%s_dir\n#endif\n", opt_arrayname);
200  }
201 
202  /* Clean up */
203  if (ferror(f_input))
204  fprintf(stderr, "Input file read error\n");
205  if (ferror(f_output))
206  fprintf(stderr, "Output file write error - disk full?\n");
207  if (f_input != stdin)
208  fclose(f_input);
209  if (f_output != stdout)
210  fclose(f_output);
211 
212  return 0;
213 }
214