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