wine/tools/bin2res.c
2002-06-02 21:22:50 +00:00

361 lines
7.4 KiB
C

/************************************************
*
* Converting binary resources from/to *.rc files
*
* Copyright 1999 Juergen Schmied
*
* 11/99 first release
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
extern char* g_lpstrFileName;
/* global options */
char* g_lpstrFileName = NULL;
char* g_lpstrInputFile = NULL;
int b_to_binary = 0;
int b_force_overwrite = 0;
static char* errorOpenFile = "Unable to open file.\n";
static char* errorRCFormat = "Unexpexted syntax in rc file line %i\n";
void usage(void)
{
printf("Usage: bin2res [-d bin] [input file]\n");
printf(" -d bin convert a *.res back to a binary\n");
printf(" -f force overwriting newer files\n");
exit(-1);
}
void parse_options(int argc, char **argv)
{
int i;
switch( argc )
{
case 2:
g_lpstrInputFile = argv[1];
break;
case 3:
case 4:
case 5:
for( i = 1; i < argc - 1; i++ )
{
if( argv[i][0] != '-' ||
strlen(argv[i]) != 2 ) break;
if( argv[i][1] == 'd')
{
if (strcmp ("bin", argv[i+1])==0)
{
b_to_binary =1;
i++;
}
else
{
usage();
}
}
else if ( argv[i][1] == 'f')
{
b_force_overwrite = 1;
}
else
{
usage();
}
}
if( i == argc - 1 )
{
g_lpstrInputFile = argv[i];
break;
}
default: usage();
}
}
int insert_hex (char * infile, FILE * outfile)
{
#ifdef HAVE_MMAP
unsigned int i;
int fd;
struct stat st;
LPBYTE p_in_file = NULL;
if( (fd = open( infile, O_RDONLY))==-1 )
{
fprintf(stderr, errorOpenFile );
exit(1);
}
if ((fstat(fd, &st) == -1) || (p_in_file = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
{
fprintf(stderr, errorOpenFile );
close(fd);
exit(1);
}
fprintf (outfile, "{\n '");
i = 0;
while (1)
{
fprintf(outfile, "%02X", p_in_file[i]);
if (++i >= st.st_size) break;
fprintf(outfile, "%s", (i == (i & 0xfffffff0)) ? "'\n '" :" ");
}
fprintf (outfile, "'\n}");
munmap(p_in_file, st.st_size);
close(fd);
return 1;
#else /* HAVE_MMAP */
FILE* fp;
struct stat st;
unsigned int i;
int c;
fp = fopen( infile, "r" );
if ( fp == NULL )
{
fprintf(stderr, errorOpenFile );
exit(1);
}
if (fstat(fileno(fp), &st) == -1)
{
fprintf(stderr, errorOpenFile );
fclose(fp);
exit(1);
}
fprintf (outfile, "{\n '");
i = 0;
while (1)
{
c = fgetc(fp);
if ( c == EOF )
{
fprintf(stderr, errorOpenFile );
fclose(fp);
exit(1);
}
fprintf(outfile, "%02X", c);
if (++i >= st.st_size) break;
fprintf(outfile, "%s", (i == (i & 0xfffffff0)) ? "'\n '" :" ");
}
fprintf (outfile, "'\n}");
fclose(fp);
return 1;
#endif /* HAVE_MMAP */
}
int convert_to_res ()
{
FILE *fin, *ftemp;
char buffer[255];
char infile[255];
char tmpfile[255];
char *pos;
int c, len;
struct stat st;
int line = 0;
time_t tinput;
long startpos, endpos;
strcpy( tmpfile, g_lpstrInputFile );
strcat( tmpfile, "-tmp" );
/* FIXME: should use better tmp name and create with O_EXCL */
if( (ftemp = fopen( tmpfile, "w")) == NULL ) goto error_open_file;
if( (fin = fopen( g_lpstrInputFile, "r")) == NULL || stat(g_lpstrInputFile, &st)) goto error_open_file;
tinput = st.st_ctime;
while ( NULL != fgets(buffer, 255, fin))
{
fputs(buffer, ftemp);
line++;
if ( (pos = strstr(buffer, "BINRES")) != NULL)
{
/* get the out-file name */
len = 0; pos += 6; startpos=0; endpos=0;
while ( *pos == ' ') pos++;
while ( pos[len] != ' ') len++;
strncpy(infile, pos, len);
infile[len]=0;
if ( (!stat(infile, &st) && st.st_ctime > tinput) || b_force_overwrite)
{
/* write a output file */
printf("[%s:c]", infile);
while((c = fgetc(fin))!='{' && c != EOF) fputc(c, ftemp);
if (c == EOF ) goto error_rc_format;
while((c = fgetc(fin))!='}' && c != EOF);
if (c == EOF ) goto error_rc_format;
insert_hex(infile, ftemp);
}
else
{
printf("[%s:s]", infile);
}
}
}
fclose(fin);
fclose(ftemp);
if (unlink(g_lpstrInputFile) == -1)
{
perror("unlink");
unlink(tmpfile);
return 0;
}
if (rename(tmpfile, g_lpstrInputFile) == -1)
{
perror("rename");
unlink(tmpfile);
return 0;
}
return 1;
error_open_file:
fprintf(stderr, errorOpenFile );
return 0;
error_rc_format:
fprintf(stderr, errorRCFormat, line);
return 0;
}
int convert_to_bin()
{
FILE *fin, *fout;
char buffer[255];
char outfile[255];
char *pos;
int len, index, in_resource;
unsigned int byte;
struct stat st;
int line = 0;
time_t tinput;
if( (fin = fopen( g_lpstrInputFile, "r")) == NULL || stat(g_lpstrInputFile, &st)) goto error_open_file;
tinput = st.st_ctime;
while ( NULL != fgets(buffer, 255, fin))
{
line++;
if ( (pos = strstr(buffer, "BINRES")) != NULL)
{
/* get the out-file name */
len = 0; pos += 6;
while ( *pos == ' ') pos++;
while ( pos[len] != ' ') len++;
strncpy(outfile, pos, len);
outfile[len]=0;
if ( stat(outfile, &st) || st.st_ctime < tinput || b_force_overwrite)
{
/* write a output file */
printf("[%s:c]", outfile);
if ( (fout = fopen( outfile, "w")) == NULL) goto error_open_file;
in_resource = 0;
while (1)
{
if ( NULL == fgets(buffer, 255, fin)) goto error_rc_format;
line++;
/* parse a line */
for ( index = 0; buffer[index] != 0; index++ )
{
if ( ! in_resource )
{
if ( buffer[index] == '{' ) in_resource = 1;
continue;
}
if ( buffer[index] == ' ' || buffer[index] == '\''|| buffer[index] == '\n' ) continue;
if ( buffer[index] == '}' ) goto end_of_resource;
if ( ! isxdigit(buffer[index])) goto error_rc_format;
index += sscanf(&buffer[index], "%02x", &byte);
fputc(byte, fout);
}
}
fclose(fout);
}
else
{
printf("[%s:s]", outfile);
}
end_of_resource: ;
}
}
fclose(fin);
return 1;
error_open_file:
fprintf(stderr, errorOpenFile );
return 0;
error_rc_format:
fprintf(stderr, errorRCFormat, line);
return 0;
}
int main(int argc, char **argv)
{
parse_options( argc, argv);
if (b_to_binary == 0)
{
convert_to_res();
}
else
{
convert_to_bin();
}
printf("\n");
return 0;
}