1 /********************************************************************************
2 * *
3 * R e s o u r c e W r a p p i n g U t i l i t y *
4 * *
5 *********************************************************************************
6 * Copyright (C) 1997,2006 by Jeroen van der Zijp. All Rights Reserved. *
7 *********************************************************************************
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
21 *********************************************************************************
22 * $Id: reswrap.cpp,v 1.17 2006/01/22 17:59:02 fox Exp $ *
23 ********************************************************************************/
24 #include "stdio.h"
25 #include "stdlib.h"
26 #include "string.h"
27 #include "ctype.h"
28
29
30
31 /*
32
33 Notes:
34 - Updated to version 4.0.
35 - Can now also generate output as a text string.
36 - When ASCII option is used with text string option, it prints human
37 readable C-style string, with non-ASCII characters escaped as appropriate.
38 - Removed PPM feature as that was never really used in FOX.
39 - License changed to GPL from LGPL because this is a standalone program
40 that does not need to be linked to anything.
41 - Added MSDOS mode, useful for wrapping ASCII text.
42 - Added option to keep extension (separated by '_').
43 - Need option to place #include "icons.h" or something into icons.cpp
44 - Always prepend prefix in front of resource name, even if name was overrided
45 because prefix may be namespace name.
46 */
47
48 /*******************************************************************************/
49
50 #define MODE_DECIMAL 0
51 #define MODE_HEX 1
52 #define MODE_TEXT 2
53
54
55 const char version[]="4.0.0";
56
57
58 /* Print some help */
printusage()59 void printusage(){
60 fprintf(stderr,"Usage: reswrap [options] [-o[a] outfile] files...\n");
61 fprintf(stderr,"Convert files containing images, text, or binary data into C/C++ data arrays.\n");
62 fprintf(stderr,"\n");
63 fprintf(stderr,"Options:\n");
64 fprintf(stderr," -o[a] outfile Output [append] to outfile instead of stdout\n");
65 fprintf(stderr," -h Print help\n");
66 fprintf(stderr," -v Print version number\n");
67 fprintf(stderr," -d Output as decimal\n");
68 fprintf(stderr," -m Read files with MS-DOS mode (default is binary)\n");
69 fprintf(stderr," -x Output as hex (default)\n");
70 fprintf(stderr," -t[a] Output as [ascii] text string\n");
71 fprintf(stderr," -e Generate external reference declaration\n");
72 fprintf(stderr," -i Build an include file\n");
73 fprintf(stderr," -k Keep extension, separated by underscore\n");
74 fprintf(stderr," -s Suppress header in output file\n");
75 fprintf(stderr," -p prefix Place prefix in front of names of declarations and definitions\n");
76 fprintf(stderr," -n namespace Place declarations and definitions inside given namespace\n");
77 fprintf(stderr," -c cols Change number of columns in output to cols\n");
78 fprintf(stderr," -u Force unsigned char even for text mode\n");
79 fprintf(stderr," -z Output size in declarations\n");
80 fprintf(stderr,"\n");
81 fprintf(stderr,"Each file may be preceded by the following extra option:\n");
82 fprintf(stderr," -r name Override resource name of following resource file\n");
83 fprintf(stderr,"\n");
84 }
85
86
87 /* Print version information */
printversion()88 void printversion(){
89 fprintf(stderr,"Reswrap %s %s.\n",version,__DATE__);
90 fprintf(stderr,"Copyright (C) 1997,2005 Jeroen van der Zijp. All Rights Reserved.\n");
91 fprintf(stderr,"Please visit: http://www.fox-toolkit.org for further information.\n");
92 fprintf(stderr,"\n");
93 fprintf(stderr,"This program is free software; you can redistribute it and/or modify\n");
94 fprintf(stderr,"it under the terms of the GNU General Public License as published by\n");
95 fprintf(stderr,"the Free Software Foundation; either version 2 of the License, or\n");
96 fprintf(stderr,"(at your option) any later version.\n");
97 fprintf(stderr,"\n");
98 fprintf(stderr,"This program is distributed in the hope that it will be useful,\n");
99 fprintf(stderr,"but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
100 fprintf(stderr,"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
101 fprintf(stderr,"GNU General Public License for more details.\n");
102 fprintf(stderr,"\n");
103 fprintf(stderr,"You should have received a copy of the GNU General Public License\n");
104 fprintf(stderr,"along with this program; if not, write to the Free Software\n");
105 fprintf(stderr,"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.\n");
106 }
107
108
109 /* Build resource name */
resourcename(char * name,const char * prefix,const char * filename,int keepdot)110 void resourcename(char *name,const char* prefix,const char* filename,int keepdot){
111 const char* begin=name;
112 const char* ptr;
113
114 /* Copy prefix */
115 while(*prefix){
116 *name++=*prefix++;
117 }
118
119 /* Get name only; take care of mixed path separator characters on mswindows */
120 if((ptr=strrchr(filename,'/'))!=0) filename=ptr;
121 if((ptr=strrchr(filename,'\\'))!=0) filename=ptr;
122
123 /* Copy filename */
124 while(*filename){
125
126 /* C++ identifier may contain _, alpha, digit (if not first), or namespace separator : */
127 if(*filename==':' || *filename=='_' || isalpha(*filename) || (isdigit(*filename) && (begin!=name))){
128 *name++=*filename;
129 }
130
131 /* We can squash dot extension to _ */
132 else if(*filename=='.'){
133 if(!keepdot) break;
134 *name++='_';
135 }
136
137 filename++;
138 }
139 *name=0;
140 }
141
142
143 /* Main */
main(int argc,char ** argv)144 int main(int argc,char **argv){
145 char *outfilename,*resfilename;
146 FILE *resfile,*outfile;
147 int i,b,first,col,append,maxcols,external,header,include,mode,colsset,ascii,msdos,keepext,hex,forceunsigned,declaresize,resfilesize;
148 const char *thenamespace,*theprefix;
149 char resname[1000];
150
151 /* Initialize */
152 outfilename=0;
153 outfile=stdout;
154 maxcols=16;
155 colsset=0;
156 external=0;
157 header=1;
158 include=0;
159 ascii=0;
160 mode=MODE_HEX;
161 msdos=0;
162 keepext=0;
163 thenamespace=0;
164 theprefix="";
165 append=0;
166 forceunsigned=0;
167 declaresize=0;
168
169 /* Check arguments */
170 if(argc<2){
171 printusage();
172 exit(1);
173 }
174
175 /* Process all options first, except for the -r option */
176 for(i=1; i<argc && argv[i][0]=='-' && argv[i][1]!='r'; i++){
177
178 /* Change output file */
179 if(argv[i][1]=='o'){
180 if(argv[i][2]=='a') append=1;
181 i++;
182 if(i>=argc){
183 fprintf(stderr,"reswrap: missing argument for -o option\n");
184 exit(1);
185 }
186 outfilename=argv[i];
187 }
188
189 /* Print help */
190 else if(argv[i][1]=='h'){
191 printusage();
192 exit(0);
193 }
194
195 /* Print version */
196 else if(argv[i][1]=='v'){
197 printversion();
198 exit(0);
199 }
200
201 /* Switch to decimal */
202 else if(argv[i][1]=='d'){
203 mode=MODE_DECIMAL;
204 if(!colsset) maxcols=10;
205 }
206
207 /* Switch to hex */
208 else if(argv[i][1]=='x'){
209 mode=MODE_HEX;
210 if(!colsset) maxcols=16;
211 }
212
213 /* Switch to text */
214 else if(argv[i][1]=='t'){
215 if(argv[i][2]=='a') ascii=1;
216 mode=MODE_TEXT;
217 if(!colsset) maxcols=80;
218 }
219
220 /* Suppress header */
221 else if(argv[i][1]=='s'){
222 header=0;
223 }
224
225 /* Force unsigned */
226 else if(argv[i][1]=='u'){
227 forceunsigned=1;
228 }
229
230 /* Declare size */
231 else if(argv[i][1]=='z'){
232 declaresize=1;
233 }
234
235 /* Generate as external reference */
236 else if(argv[i][1]=='e'){
237 external=1;
238 }
239
240 /* Building include file implies also extern */
241 else if(argv[i][1]=='i'){
242 include=1;
243 external=1;
244 }
245
246 /* Read resource with MS-DOS mode */
247 else if(argv[i][1]=='m'){
248 msdos=1;
249 }
250
251 /* Keep extension */
252 else if(argv[i][1]=='k'){
253 keepext=1;
254 }
255
256 /* Change number of columns */
257 else if(argv[i][1]=='c'){
258 i++;
259 if(i>=argc){
260 fprintf(stderr,"reswrap: missing argument for -c option\n");
261 exit(1);
262 }
263 if(sscanf(argv[i],"%d",&maxcols)==1 && maxcols<1){
264 fprintf(stderr,"reswrap: illegal argument for number of columns\n");
265 exit(1);
266 }
267 colsset=1;
268 }
269
270 /* Embed in namespace */
271 else if(argv[i][1]=='n'){
272 i++;
273 if(i>=argc){
274 fprintf(stderr,"reswrap: missing argument for -n option\n");
275 exit(1);
276 }
277 thenamespace=argv[i];
278 }
279
280 /* Prefix in front of declarations */
281 else if(argv[i][1]=='p'){
282 i++;
283 if(i>=argc){
284 fprintf(stderr,"reswrap: missing argument for -p option\n");
285 exit(1);
286 }
287 theprefix=argv[i];
288 }
289 }
290
291 /* To file instead out stdout */
292 if(outfilename){
293 outfile=fopen(outfilename,append?"a":"w");
294 if(!outfile){
295 fprintf(stderr,"reswrap: unable to open output file %s\n",outfilename);
296 exit(1);
297 }
298 }
299
300 /* Output header */
301 if(header){
302 fprintf(outfile,"/* Generated by reswrap version %s */\n\n",version);
303 }
304
305 /* Output namespace begin */
306 if(thenamespace){
307 fprintf(outfile,"namespace %s {\n\n",thenamespace);
308 }
309
310 /* Process resource files next */
311 for(; i<argc; i++){
312
313 /* Resource name override */
314 if(argv[i][0]=='-' && argv[i][1]=='r'){
315
316 /* Must have extra argument */
317 if(++i>=argc){
318 fprintf(stderr,"reswrap: missing name argument for -r option\n");
319 exit(1);
320 }
321
322 /* Get resource name */
323 resourcename(resname,theprefix,argv[i],keepext);
324
325 /* Must have following file name */
326 if(++i>=argc){
327 fprintf(stderr,"reswrap: missing resource file name\n");
328 exit(1);
329 }
330
331 /* Get resource file name */
332 resfilename=argv[i];
333 }
334
335 else{
336
337 /* Get resource file name */
338 resfilename=argv[i];
339
340 /* Get resource name */
341 resourcename(resname,theprefix,resfilename,keepext);
342 }
343
344
345 /* Check resource name not empty */
346 if(*resname==0){
347 fprintf(stderr,"reswrap: empty resource name for %s\n",resfilename);
348 exit(1);
349 }
350
351 /* Open resource file; always open as binary */
352 resfile=fopen(resfilename,"rb");
353 if(!resfile){
354 fprintf(stderr,"reswrap: unable to open input file %s\n",resfilename);
355 exit(1);
356 }
357
358 /* Get the size */
359 fseek(resfile,0,SEEK_END);
360 resfilesize=ftell(resfile);
361 fseek(resfile,0,SEEK_SET);
362
363 /* Add one if text mode, for end of string */
364 if(mode==MODE_TEXT){
365 resfilesize++;
366 }
367
368 /* Output header */
369 if(header){
370 fprintf(outfile,"/* created by reswrap from file %s */\n",resfilename);
371 }
372
373 /* Generate external reference for #include's */
374 if(external){ fprintf(outfile,"extern "); }
375
376 /* In text mode, output a 'char' declaration */
377 if((mode==MODE_TEXT) && !forceunsigned){
378 if(declaresize){
379 fprintf(outfile,"const char %s[%d]",resname,resfilesize);
380 }
381 else{
382 fprintf(outfile,"const char %s[]",resname);
383 }
384 }
385
386 /* In binary mode, output a 'unsigned char' declaration */
387 else{
388 if(declaresize){
389 fprintf(outfile,"const unsigned char %s[%d]",resname,resfilesize);
390 }
391 else{
392 fprintf(outfile,"const unsigned char %s[]",resname);
393 }
394 }
395
396 /* Generate resource array */
397 if(!include){
398 if(mode==MODE_TEXT){
399 col=0;
400 hex=0;
401 fprintf(outfile,"=\n \"");
402 while((b=fgetc(resfile))!=EOF){
403 if(msdos && (b=='\r')) continue;
404 if(col>=maxcols){
405 fprintf(outfile,"\"\n \"");
406 col=0;
407 }
408 if(ascii){
409 if(b=='\\'){ fprintf(outfile,"\\\\"); col+=2; hex=0; }
410 else if(b=='\a'){ fprintf(outfile,"\\a"); col+=2; hex=0; }
411 else if(b=='\t'){ fprintf(outfile,"\\t"); col+=2; hex=0; }
412 else if(b=='\r'){ fprintf(outfile,"\\r"); col+=2; hex=0; }
413 else if(b=='\f'){ fprintf(outfile,"\\f"); col+=2; hex=0; }
414 else if(b=='\v'){ fprintf(outfile,"\\v"); col+=2; hex=0; }
415 else if(b=='\"'){ fprintf(outfile,"\\\""); col+=2; hex=0; }
416 else if(b=='\n'){ fprintf(outfile,"\\n\"\n \""); col=0; hex=0; }
417 else if(b<32 || b>=127){ fprintf(outfile,"\\x%02x",b); col+=4; hex=1; }
418 else if(hex && isxdigit(b)){ fprintf(outfile,"\\x%02x",b); col+=4; hex=1; }
419 else{ fprintf(outfile,"%c",b); col+=1; hex=0; }
420 }
421 else{
422 fprintf(outfile,"\\x%02x",b); col+=4;
423 }
424 }
425 fprintf(outfile,"\"\n ");
426 }
427 else{
428 col=0;
429 first=1;
430 fprintf(outfile,"={\n ");
431 while((b=fgetc(resfile))!=EOF){
432 if(msdos && (b=='\r')) continue;
433 if(!first){
434 fprintf(outfile,",");
435 }
436 if(col>=maxcols){
437 fprintf(outfile,"\n ");
438 col=0;
439 }
440 if(mode==MODE_HEX)
441 fprintf(outfile,"0x%02x",b);
442 else
443 fprintf(outfile,"%3d",b);
444 first=0;
445 col++;
446 }
447 fprintf(outfile,"\n }");
448 }
449 }
450
451 fprintf(outfile,";\n\n");
452
453 /* Close resource file */
454 fclose(resfile);
455 }
456
457 /* Output namespace end */
458 if(thenamespace){
459 fprintf(outfile,"}\n");
460 }
461
462 /* To file instead out stdout */
463 if(outfilename){
464 fclose(outfile);
465 }
466
467 return 0;
468 }
469
470
471
472