Several bug fixes and additions.
[wine] / tools / bin2res.c
1 /************************************************
2  *
3  * Converting binary resources from/to *.rc files
4  *
5  * Copyright 1999 Juergen Schmied
6  *
7  * 11/99 first release
8  */
9
10 #include "config.h"
11
12 #ifdef HAVE_SYS_PARAM_H
13 # include <sys/param.h>
14 #endif
15 #include <sys/types.h>
16 #include <sys/stat.h>
17
18 #include <ctype.h>
19 #include <string.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #include <fcntl.h>
25 #include <unistd.h>
26 #ifdef HAVE_SYS_MMAN_H
27 # include <sys/mman.h>
28 #endif
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34
35 extern char*   g_lpstrFileName;
36
37 /* global options */
38
39 char*   g_lpstrFileName = NULL;
40 char*   g_lpstrInputFile = NULL;
41 int     b_to_binary = 0;
42 int     b_force_overwrite = 0;
43
44 static char*    errorOpenFile = "Unable to open file.\n";
45 static char*    errorRCFormat = "Unexpexted syntax in rc file line %i\n";
46
47 void usage(void)
48 {
49     printf("Usage: bin2res [-d bin] [input file]\n");
50     printf("  -d bin convert a *.res back to a binary\n");
51     printf("  -f force overwriting newer files\n");
52     exit(-1);
53 }
54
55 void parse_options(int argc, char **argv)
56 {
57   int i;
58
59   switch( argc )
60   {
61     case 2:
62          g_lpstrInputFile = argv[1];
63          break;
64
65     case 3:
66     case 4:
67     case 5:
68          for( i = 1; i < argc - 1; i++ )
69          {
70            if( argv[i][0] != '-' ||
71                strlen(argv[i]) != 2 ) break;
72
73            if( argv[i][1] == 'd')
74            {
75              if (strcmp ("bin", argv[i+1])==0)
76              {
77                b_to_binary =1;
78                i++;
79              }
80              else
81              {
82                usage();
83              }
84              
85            }
86            else if ( argv[i][1] == 'f')
87            {
88              b_force_overwrite = 1;
89            }
90            else
91            {
92              usage();
93            }
94          } 
95          if( i == argc - 1 )
96          {
97            g_lpstrInputFile = argv[i];
98            break;
99          }
100     default: usage();
101   }
102 }
103
104 int insert_hex (char * infile, FILE * outfile)
105 {
106 #ifdef  HAVE_MMAP
107         unsigned int i;
108         int             fd;
109         struct stat     st;
110         LPBYTE p_in_file = NULL;
111
112         if( (fd = open( infile, O_RDONLY))==-1 ) 
113         {
114           fprintf(stderr, errorOpenFile );
115           exit(1);
116         }
117         if ((fstat(fd, &st) == -1) || (p_in_file = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
118         {
119           fprintf(stderr, errorOpenFile );
120           close(fd);
121           exit(1);
122         }
123
124         fprintf (outfile, "{\n '");
125         i = 0;
126         while (1)
127         {
128           fprintf(outfile, "%02X", p_in_file[i]);
129           if (++i >= st.st_size) break;
130           fprintf(outfile, "%s", (i == (i & 0xfffffff0)) ? "'\n '" :" ");
131         }
132         fprintf (outfile, "'\n}");
133         munmap(p_in_file, st.st_size);
134         close(fd);
135         return 1;
136 #else   /* HAVE_MMAP */
137         FILE*   fp;
138         struct stat     st;
139         unsigned int    i;
140         int             c;
141
142         fp = fopen( infile, "r" );
143         if ( fp == NULL )
144         {
145           fprintf(stderr, errorOpenFile );
146           exit(1);
147         }
148         if (fstat(fileno(fp), &st) == -1)
149         {
150           fprintf(stderr, errorOpenFile );
151           fclose(fp);
152           exit(1);
153         }
154
155         fprintf (outfile, "{\n '");
156         i = 0;
157         while (1)
158         {
159           c = fgetc(fp);
160           if ( c == EOF )
161           {
162             fprintf(stderr, errorOpenFile );
163             fclose(fp);
164             exit(1);
165           }
166           fprintf(outfile, "%02X", c);
167           if (++i >= st.st_size) break;
168           fprintf(outfile, "%s", (i == (i & 0xfffffff0)) ? "'\n '" :" ");
169         }
170         fprintf (outfile, "'\n}");
171
172         fclose(fp);
173         return 1;
174 #endif  /* HAVE_MMAP */
175 }
176
177 int convert_to_res ()
178 {
179         FILE    *fin, *ftemp;
180         char    buffer[255];
181         char    infile[255];
182         char    tmpfile[255];
183         char    *pos;
184         int     c, len;
185         struct stat     st;
186         int line = 0;
187         time_t  tinput;
188         long startpos, endpos;
189
190         strcpy( tmpfile, g_lpstrInputFile );
191         strcat( tmpfile, "-tmp" );
192         /* FIXME: should use better tmp name and create with O_EXCL */
193         if( (ftemp = fopen( tmpfile, "w")) == NULL ) goto error_open_file;
194         
195         if( (fin = fopen( g_lpstrInputFile, "r")) == NULL || stat(g_lpstrInputFile, &st)) goto error_open_file;
196         tinput = st.st_ctime;
197         
198         while ( NULL != fgets(buffer, 255, fin))
199         {
200           fputs(buffer, ftemp);
201           line++;
202           if ( (pos = strstr(buffer, "BINRES")) != NULL)
203           {
204             /* get the out-file name */
205             len = 0; pos += 6; startpos=0; endpos=0;
206             while ( *pos == ' ') pos++;
207             while ( pos[len] != ' ') len++;
208             strncpy(infile, pos, len);
209             infile[len]=0;
210             
211             if ( (!stat(infile, &st) && st.st_ctime > tinput) || b_force_overwrite)
212             {
213               /* write a output file */
214               printf("[%s:c]", infile);
215               while((c = fgetc(fin))!='{' && c != EOF) fputc(c, ftemp);
216               if (c == EOF ) goto error_rc_format;
217               while((c = fgetc(fin))!='}' && c != EOF);
218               if (c == EOF ) goto error_rc_format;
219
220               insert_hex(infile, ftemp);
221             }
222             else
223             {
224               printf("[%s:s]", infile);
225             }
226           }
227         }
228         
229         fclose(fin);
230         fclose(ftemp);
231         if (rename(tmpfile, g_lpstrInputFile) == -1)
232         {
233             perror("rename");
234             unlink(tmpfile);
235             return 0;
236         }
237         return 1;       
238
239 error_open_file:
240         fprintf(stderr, errorOpenFile );
241         return 0;
242
243 error_rc_format:        
244         fprintf(stderr, errorRCFormat, line);
245         return 0;
246 }
247
248 int convert_to_bin()
249 {
250         FILE    *fin, *fout;
251         char    buffer[255];
252         char    outfile[255];
253         char    *pos;
254         int     len, index, in_resource;
255         unsigned int    byte;
256         struct stat     st;
257         int line = 0;
258         time_t  tinput;
259                 
260         if( (fin = fopen( g_lpstrInputFile, "r")) == NULL || stat(g_lpstrInputFile, &st)) goto error_open_file;
261         tinput = st.st_ctime;
262         
263         while ( NULL != fgets(buffer, 255, fin))
264         {
265           line++;
266           if ( (pos = strstr(buffer, "BINRES")) != NULL)
267           {
268             /* get the out-file name */
269             len = 0; pos += 6;
270             while ( *pos == ' ') pos++;
271             while ( pos[len] != ' ') len++;
272             strncpy(outfile, pos, len);
273             outfile[len]=0;
274             
275             if ( stat(outfile, &st) || st.st_ctime < tinput || b_force_overwrite)
276             {
277               /* write a output file */
278               printf("[%s:c]", outfile);
279               if ( (fout = fopen( outfile, "w")) == NULL) goto error_open_file;
280
281               in_resource = 0;
282               while (1)
283               {
284                 if ( NULL == fgets(buffer, 255, fin)) goto error_rc_format;
285                 line++;
286
287                 /* parse a line */
288                 for ( index = 0; buffer[index] != 0; index++ )
289                 {
290                   if ( ! in_resource )
291                   {
292                     if ( buffer[index] == '{' ) in_resource = 1;
293                     continue;
294                   }
295
296                   if ( buffer[index] == ' ' || buffer[index] == '\''|| buffer[index] == '\n' ) continue;
297                   if ( buffer[index] == '}' ) goto end_of_resource;
298                   if ( ! isxdigit(buffer[index])) goto error_rc_format;
299                   index += sscanf(&buffer[index], "%02x", &byte);
300                   fputc(byte, fout);
301                 }  
302               }
303               fclose(fout);
304             }
305             else
306             {
307               printf("[%s:s]", outfile);
308             }
309 end_of_resource: ;
310           }
311         }
312         
313         fclose(fin);
314         return 1;       
315
316 error_open_file:
317         fprintf(stderr, errorOpenFile );
318         return 0;
319
320 error_rc_format:        
321         fprintf(stderr, errorRCFormat, line);
322         return 0;
323 }
324
325 int main(int argc, char **argv)
326 {
327         parse_options( argc, argv);
328
329         if (b_to_binary == 0)
330         {
331           convert_to_res();
332         }
333         else
334         {
335           convert_to_bin();
336         }
337         printf("\n");
338         return 0;
339 }