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