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