Commit deaf02a5 authored by Dimitrie O. Paun's avatar Dimitrie O. Paun Committed by Alexandre Julliard

Remove assembly generation from wrc.

parent f498d4b8
......@@ -65,7 +65,6 @@
#include "wrc.h"
#include "utils.h"
#include "writeres.h"
#include "readres.h"
#include "dumpres.h"
#include "genres.h"
......@@ -86,7 +85,6 @@
static char usage[] =
"Usage: wrc [options...] [infile[.rc|.res]] [outfile]\n"
" -a n Alignment of resource (win16 only, default is 4)\n"
" -b Create an assembly array from a binary .res file\n"
" -B x Set output byte-order x={n[ative], l[ittle], b[ig]}\n"
" (win32 only; default is " ENDIAN "-endian)\n"
" -C cp Set the resource's codepage to cp (default is 0)\n"
......@@ -95,18 +93,15 @@ static char usage[] =
" -e Disable recognition of win32 keywords in 16bit compile\n"
" -E Preprocess only\n"
" -F target Ignored for compatibility with windres\n"
" -g Add symbols to the global c namespace\n"
" -h Prints this summary.\n"
" -i file The name of the input file.\n"
" -I path Set include search dir to path (multiple -I allowed)\n"
" -J Do not search the standard include path\n"
" -l lan Set default language to lan (default is neutral {0, 0})\n"
" -m Do not remap numerical resource IDs\n"
" -o file Output to file (default is infile.[res|s]\n"
" -O format The output format: one of `res', 'asm'.\n"
" -p prefix Give a prefix for the generated names\n"
" -o file Output to file (default is infile.res)\n"
" -O format The output format (must be `res').\n"
" -P program Specifies the preprocessor to use, including arguments.\n"
" -s Add structure with win32/16 (PE/NE) resource directory\n"
" -v Enable verbose mode.\n"
" -V Print version and exit\n"
" -w 16|32 Select win16 or win32 output (default is win32)\n"
......@@ -136,7 +131,7 @@ static char usage[] =
" * 0x10 Preprocessor lex messages\n"
" * 0x20 Preprocessor yacc trace\n"
"If no input filename is given and the output name is not overridden\n"
"with -o, then the output is written to \"wrc.tab.{s,res}\"\n"
"with -o, then the output is written to \"wrc.tab.res\"\n"
;
char version_string[] = "Wine Resource Compiler Version " WRC_FULLVERSION "\n"
......@@ -144,10 +139,9 @@ char version_string[] = "Wine Resource Compiler Version " WRC_FULLVERSION "\n"
" 1994 Martin von Loewis\n";
/*
* Default prefix for resource names used in the C array.
* Option '-p name' sets it to 'name'
* External functions
*/
char *prefix = __ASM_NAME("_Resource");
void write_resfile(char *outname, resource_t *top);
/*
* Set if compiling in 32bit mode (default).
......@@ -155,11 +149,6 @@ char *prefix = __ASM_NAME("_Resource");
int win32 = 1;
/*
* Output type (default res)
*/
enum output_t { output_def, output_res, output_asm } output_type = output_def;
/*
* debuglevel == DEBUGLEVEL_NONE Don't bother
* debuglevel & DEBUGLEVEL_CHAT Say whats done
* debuglevel & DEBUGLEVEL_DUMP Dump internal structures
......@@ -177,22 +166,6 @@ int debuglevel = DEBUGLEVEL_NONE;
int extensions = 1;
/*
* Set when creating C array from .res file (-b option).
*/
int binary = 0;
/*
* Set when the NE/PE resource directory should be dumped into
* the output file.
*/
int create_dir = 0;
/*
* Set when all symbols should be added to the global namespace (-g option)
*/
int global = 0;
/*
* NE segment resource aligment (-a option)
*/
int alignment = 4;
......@@ -250,7 +223,7 @@ static void rm_tempfile(void);
static void segvhandler(int sig);
static const char* short_options =
"a:AbB:cC:d:D:eEF:ghH:i:I:Jl:LmnNo:O:p:P:rstTvVw:W";
"a:AB:cC:d:D:eEF:hH:i:I:Jl:LmnNo:O:P:rtTvVw:W";
#ifdef HAVE_GETOPT_LONG
static struct option long_options[] = {
{ "input", 1, 0, 'i' },
......@@ -320,9 +293,6 @@ int main(int argc,char *argv[])
case 'a':
alignment = atoi(optarg);
break;
case 'b':
binary = 1;
break;
case 'B':
switch(optarg[0])
{
......@@ -361,9 +331,6 @@ int main(int argc,char *argv[])
case 'F':
/* ignored for compatibility with windres */
break;
case 'g':
global = 1;
break;
case 'h':
printf(usage);
exit(0);
......@@ -394,20 +361,13 @@ int main(int argc,char *argv[])
else error("Too many output files.\n");
break;
case 'O':
if (strcmp(optarg, "res") == 0) output_type = output_res;
else if (strcmp(optarg, "asm") == 0) output_type = output_asm;
else error("Output format %s not supported.", optarg);
break;
case 'p':
prefix = xstrdup(optarg);
if (strcmp(optarg, "res"))
error("Output format %s not supported.", optarg);
break;
case 'P':
if (strcmp(optarg, "cat") == 0) no_preprocess = 1;
else fprintf(stderr, "-P option not yet supported, ignored.\n");
break;
case 's':
create_dir = 1;
break;
case 'v':
debuglevel = DEBUGLEVEL_CHAT;
break;
......@@ -460,19 +420,6 @@ int main(int argc,char *argv[])
else error("Too many output files.\n");
}
/* Try to guess the output format based on output name */
if (output_type == output_def)
{
char *dotstr = output_name ? strrchr(output_name, '.') : 0;
output_type = output_res; /* by default generate .res files */
if (dotstr)
{
if (strcmp(dotstr+1, "s") == 0) output_type = output_asm;
}
}
/* Check the command line options for invalid combinations */
if(win32)
{
......@@ -483,51 +430,6 @@ int main(int argc,char *argv[])
}
}
if(output_type == output_res)
{
if(global)
{
warning("Option -g ignored with compile to .res\n");
global = 0;
}
if(create_dir)
{
error("Option -r and -s cannot be used together\n");
}
if(binary)
{
error("Option -r and -b cannot be used together\n");
}
}
if(byteorder != WRC_BO_NATIVE)
{
if(binary)
error("Forced byteordering not supported for binary resources\n");
}
if(preprocess_only)
{
if(global)
{
warning("Option -g ignored with preprocess only\n");
global = 0;
}
if(create_dir)
{
warning("Option -s ignored with preprocess only\n");
create_dir = 0;
}
if(binary)
{
error("Option -E and -b cannot be used together\n");
}
}
/* Set alignment power */
a = alignment;
for(alignment_pwr = 0; alignment_pwr < 10 && a > 1; alignment_pwr++)
......@@ -575,21 +477,15 @@ int main(int argc,char *argv[])
if(!currentlanguage)
currentlanguage = new_language(0, 0);
if(binary && !input_name)
{
error("Binary mode requires .res file as input\n");
}
/* Generate appropriate outfile names */
if(!output_name && !preprocess_only)
{
output_name = dup_basename(input_name, binary ? ".res" : ".rc");
if (output_type == output_res) strcat(output_name, ".res");
else if (output_type == output_asm) strcat(output_name, ".s");
output_name = dup_basename(input_name, ".rc");
strcat(output_name, ".res");
}
/* Run the preprocessor on the input */
if(!no_preprocess && !binary)
if(!no_preprocess)
{
/*
* Preprocess the input to a temp-file, or stdout if
......@@ -626,9 +522,7 @@ int main(int argc,char *argv[])
input_name = temp_name;
}
if(!binary)
{
/* Go from .rc to .res or .s */
/* Go from .rc to .res */
chat("Starting parse");
if(!(yyin = fopen(input_name, "rb")))
......@@ -636,14 +530,9 @@ int main(int argc,char *argv[])
ret = yyparse();
if(input_name)
fclose(yyin);
if(input_name) fclose(yyin);
if(ret)
{
/* Error during parse */
exit(1);
}
if(ret) exit(1); /* Error during parse */
if(debuglevel & DEBUGLEVEL_DUMP)
dump_resources(resource_top);
......@@ -651,29 +540,8 @@ int main(int argc,char *argv[])
/* Convert the internal lists to binary data */
resources2res(resource_top);
if(output_type == output_res)
{
chat("Writing .res-file");
write_resfile(output_name, resource_top);
}
else if(output_type == output_asm)
{
chat("Writing .s-file");
write_s_file(output_name, resource_top);
}
}
else
{
/* Go from .res to .s */
chat("Reading .res-file");
resource_top = read_resfile(input_name);
if(output_type == output_asm)
{
chat("Writing .s-file");
write_s_file(output_name, resource_top);
}
}
return 0;
}
......
......@@ -51,9 +51,6 @@ extern int debuglevel;
extern int win32;
extern int create_res;
extern int extensions;
extern int binary;
extern int create_dir;
extern int global;
extern int alignment;
extern int alignment_pwr;
extern int create_s;
......@@ -64,7 +61,6 @@ extern int preprocess_only;
extern int no_preprocess;
extern int remap;
extern char *prefix;
extern char *output_name;
extern char *input_name;
extern char *cmdline;
......
......@@ -5,39 +5,25 @@ wrc \- Wine Resource Compiler
.BI "wrc " "[options] " "[inputfile]"
.SH DESCRIPTION
.B wrc
compiles resources from
.I inputfile
into win16 and win32 compatible
binary format.
.B wrc
outputs the binary data either in a standard \fB.res\fR formatted binary
file, or an assembly file.
.B wrc
is also capable of reading \fB.res\fR formatted files and convert them
into an assembly file.
compiles resources from \fBinputfile\fR
into win16 and win32 compatible binary format.
.PP
The source\-file is preprocessed with a builtin ANSI\-C compatible
preprocessor before the resources are compiled. See \fBPREPROCESSOR\fR
below.
.PP
.B wrc
takes only one \fBinputfile\fR as argument. The \fBinputfile\fR has
extension \fB.rc\fR for resources in source form and \fB.res\fR for
binary resources. The resources are read from standard input if no
inputfile is given. If the outputfile is not specified with \fI-o\fR,
then \fBwrc\fR will write the output to \fBinputfile.{s,res}\fR
with \fB.rc\fR stripped, depending on the mode of compilation.
The outputfile is named \fBwrc.tab.{s,res}\fR if no inputfile was
given.
takes only one \fBinputfile\fR as argument. The resources are read from
standard input if no inputfile is given. If the output file is not
specified with \fI-o\fR, then \fBwrc\fR will write the output to
\fBinputfile.res\fR with \fB.rc\fR stripped, or to \fBwrc.tab.res\fR if
no inputfile was given.
.SH OPTIONS
.TP
.I \-a n
Win16 only; set the alignment between resources n. The alignment must
be a power of 2. The default is 4.
.TP
.I \-b
Create an assembly file from a binary \fB.res\fR file.
.TP
.I \-B x
Win32 only; set output byte\-ordering, where \fIx\fR is one of n[ative],
l[ittle] or b[ig]. Only resources in source-form can be reorderd. Native
......@@ -68,10 +54,6 @@ Preprocess only. The output is written to standard output if no
outputfile was selected. The output is compatible with what gcc would
generate.
.TP
.I \-g
Add symbols to the global C namespace. This makes all symbols available
for linking by other modules.
.TP
.I \-h
Prints a summary message and exits.
.TP
......@@ -106,29 +88,20 @@ source\-files that contain overlapping type\-IDs, or when the format of the
resource is not 100% compliant.
.TP
.I \-o file
Write output to \fIfile\fR. Default is \fBinputfile.{res,s,h}\fR
with \fB.rc\fR stripped or \fBwrc.tab.{s,h,res}\fR, depending on the
compilation mode.
Write output to \fIfile\fR. Default is \fBinputfile.res\fR
with \fB.rc\fR stripped or \fBwrc.tab.res\fR if input is read
from standard input.
.TP
.I \-O format
Sets the output format. \fformat\fR can one either 'res' or 'asm'
to generate a \fB.res\fR or \fB.s\fR file respectively.
If not specified, \fBwrc\fR assumes 'res'.
.TP
.I \-p prefix
Prefix all generated names with \fIprefix\fR. This is only relevant for
names in the assembly code and header file. Resource names are not
affected.
Sets the output format. The only supported \fformat\fR is 'res', which
is also the default format if this option is not specified. The option
exists mainly for compatibility with \fBwindres\fR.
.TP
.I \-P program
This option may be used to specify the preprocessor to use, including any
leading arguments. If not specified, \fBwrc\fR uses its builtin processor.
To disable preprocessing, use \fB-P cat\fR.
.TP
.I \-s
Add structure with win32/16 (PE/NE) resource directory to outputfile.
This directory is always in native byteorder.
.TP
.I \-v
Turns on verbose mode (equivalent to -d 1).
.TP
......
/*
* Write .res, .s and .h file(s) from a resource-tree
* Write .res file from a resource-tree
*
* Copyright 1998 Bertho A. Stultiens
*
......@@ -28,38 +28,10 @@
#include "wine/unicode.h"
#include "wrc.h"
#include "writeres.h"
#include "genres.h"
#include "newstruc.h"
#include "utils.h"
static char s_file_head_str[] =
"/* This file is generated with wrc version " WRC_FULLVERSION ". Do not edit! */\n"
"/* Source : %s */\n"
"/* Cmdline: %s */\n"
"/* Date : %s */\n"
"\n"
"\t.data\n"
"\n"
;
static char s_file_tail_str[] =
"/* <eof> */\n"
"\n"
;
char _NEResTab[] = "_NEResTab";
char _PEResTab[] = "_PEResTab";
char _ResTable[] = "_ResTable";
/* Variables used for resource sorting */
res_count_t *rcarray = NULL; /* Type-level count array */
int rccount = 0; /* Nr of entries in the type-level array */
int n_id_entries = 0; /* win32 only: Nr of unique ids in the type-level array */
int n_name_entries = 0; /* win32 only: Nr of unique namess in the type-level array */
static int direntries; /* win32 only: Total number of unique resources */
/*
*****************************************************************************
* Function : write_resfile
......@@ -132,803 +104,3 @@ void write_resfile(char *outname, resource_t *top)
}
fclose(fo);
}
/*
*****************************************************************************
* Function : write_s_res
* Syntax : void write_s_res(FILE *fp, res_t *res)
* Input :
* Output :
* Description :
* Remarks :
*****************************************************************************
*/
#define BYTESPERLINE 8
static void write_s_res(FILE *fp, res_t *res)
{
int idx = res->dataidx;
int end = res->size;
int rest = (end - idx) % BYTESPERLINE;
int lines = (end - idx) / BYTESPERLINE;
int i, j;
for(i = 0 ; i < lines; i++)
{
fprintf(fp, "\t.byte\t");
for(j = 0; j < BYTESPERLINE; j++, idx++)
{
fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
j == BYTESPERLINE-1 ? "" : ", ");
}
fprintf(fp, "\n");
}
if(rest)
{
fprintf(fp, "\t.byte\t");
for(j = 0; j < rest; j++, idx++)
{
fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
j == rest-1 ? "" : ", ");
}
fprintf(fp, "\n");
}
}
#undef BYTESPERLINE
/*
*****************************************************************************
* Function : write_name_str
* Syntax : void write_name_str(FILE *fp, name_id_t *nid)
* Input :
* Output :
* Description :
* Remarks : One level self recursive for string type conversion
*****************************************************************************
*/
static void write_name_str(FILE *fp, name_id_t *nid)
{
res_t res;
assert(nid->type == name_str);
if(!win32 && nid->name.s_name->type == str_char)
{
res.size = strlen(nid->name.s_name->str.cstr);
if(res.size > 254)
error("Can't write strings larger than 254 bytes");
if(res.size == 0)
internal_error(__FILE__, __LINE__, "Attempt to write empty string");
res.dataidx = 0;
res.data = (char *)xmalloc(1 + res.size + 1);
res.data[0] = (char)res.size;
res.size++; /* We need to write the length byte as well */
strcpy(res.data+1, nid->name.s_name->str.cstr);
write_s_res(fp, &res);
free(res.data);
}
else if(!win32 && nid->name.s_name->type == str_unicode)
{
name_id_t lnid;
lnid.type = name_str;
lnid.name.s_name = convert_string( nid->name.s_name, str_char,
get_language_codepage(0,0) );
write_name_str(fp, &lnid);
free_string( lnid.name.s_name );
}
else if(win32 && nid->name.s_name->type == str_char)
{
name_id_t lnid;
lnid.type = name_str;
lnid.name.s_name = convert_string( nid->name.s_name, str_unicode,
get_language_codepage(0,0) );
write_name_str(fp, &lnid);
free_string( lnid.name.s_name );
}
else if(win32 && nid->name.s_name->type == str_unicode)
{
res.size = strlenW(nid->name.s_name->str.wstr);
if(res.size > 65534)
error("Can't write strings larger than 65534 characters");
if(res.size == 0)
internal_error(__FILE__, __LINE__, "Attempt to write empty string");
res.dataidx = 0;
res.data = (char *)xmalloc(2 + (res.size + 1) * 2);
((short *)res.data)[0] = (short)res.size;
strcpyW((WCHAR *)(res.data+2), nid->name.s_name->str.wstr);
res.size *= 2; /* Function writes bytes, not shorts... */
res.size += 2; /* We need to write the length word as well */
write_s_res(fp, &res);
free(res.data);
}
else
{
internal_error(__FILE__, __LINE__, "Hmm, requested to write a string of unknown type %d",
nid->name.s_name->type);
}
}
/*
*****************************************************************************
* Function : find_counter
* Syntax : res_count_t *find_counter(name_id_t *type)
* Input :
* Output :
* Description :
* Remarks :
*****************************************************************************
*/
static res_count_t *find_counter(name_id_t *type)
{
int i;
for(i = 0; i < rccount; i++)
{
if(!compare_name_id(type, &(rcarray[i].type)))
return &rcarray[i];
}
return NULL;
}
/*
*****************************************************************************
* Function : count_resources
* Syntax : res_count_t *count_resources(resource_t *top)
* Input :
* Output :
* Description :
* Remarks : The whole lot is converted into arrays because they are
* easy sortable. Makes the lot almost unreadable, but it
* works (I hope). Basically you have to keep in mind that
* the lot is a three-dimensional structure for win32 and a
* two-dimensional structure for win16.
*****************************************************************************
*/
#define RCT(v) (*((resource_t **)(v)))
/* qsort sorting function */
static int sort_name_id(const void *e1, const void *e2)
{
return compare_name_id(RCT(e1)->name, RCT(e2)->name);
}
static int sort_language(const void *e1, const void *e2)
{
assert((RCT(e1)->lan) != NULL);
assert((RCT(e2)->lan) != NULL);
return MAKELANGID(RCT(e1)->lan->id, RCT(e1)->lan->sub)
- MAKELANGID(RCT(e2)->lan->id, RCT(e2)->lan->sub);
}
#undef RCT
#define RCT(v) ((res_count_t *)(v))
static int sort_type(const void *e1, const void *e2)
{
return compare_name_id(&(RCT(e1)->type), &(RCT(e2)->type));
}
#undef RCT
static void count_resources(resource_t *top)
{
resource_t *rsc;
res_count_t *rcp;
name_id_t nid;
int i, j;
for(rsc = top; rsc; rsc = rsc->next)
{
if(!rsc->binres)
continue;
switch(rsc->type)
{
case res_dlgex:
nid.name.i_name = WRC_RT_DIALOG;
nid.type = name_ord;
break;
case res_menex:
nid.name.i_name = WRC_RT_MENU;
nid.type = name_ord;
break;
case res_usr:
nid = *(rsc->res.usr->type);
break;
default:
nid.name.i_name = rsc->type;
nid.type = name_ord;
}
if((rcp = find_counter(&nid)) == NULL)
{
/* Count the number of uniq ids and names */
if(nid.type == name_ord)
n_id_entries++;
else
n_name_entries++;
if(!rcarray)
{
rcarray = (res_count_t *)xmalloc(sizeof(res_count_t));
rccount = 1;
rcarray[0].count = 1;
rcarray[0].type = nid;
rcarray[0].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
rcarray[0].rscarray[0] = rsc;
}
else
{
rccount++;
rcarray = (res_count_t *)xrealloc(rcarray, rccount * sizeof(res_count_t));
rcarray[rccount-1].count = 1;
rcarray[rccount-1].type = nid;
rcarray[rccount-1].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
rcarray[rccount-1].rscarray[0] = rsc;
}
}
else
{
rcp->count++;
rcp->rscarray = (resource_t **)xrealloc(rcp->rscarray, rcp->count * sizeof(resource_t *));
rcp->rscarray[rcp->count-1] = rsc;
}
}
if(!win32)
{
/* We're done, win16 requires no special sorting */
return;
}
/* We now have a unsorted list of types with an array of res_count_t
* in rcarray[0..rccount-1]. And we have names of one type in the
* rcarray[x].rsc[0..rcarray[x].count-1] arrays.
* The list needs to be sorted for win32's top level tree structure.
*/
/* Sort the types */
if(rccount > 1)
qsort(rcarray, rccount, sizeof(rcarray[0]), sort_type);
/* Now sort the name-id arrays */
for(i = 0; i < rccount; i++)
{
if(rcarray[i].count > 1)
qsort(rcarray[i].rscarray, rcarray[i].count, sizeof(rcarray[0].rscarray[0]), sort_name_id);
}
/* Now split the name-id arrays into name/language
* subs. Don't look at the awfull expressions...
* We do this by taking the array elements out of rscarray and putting
* together a new array in rsc32array.
*/
for(i = 0; i < rccount; i++)
{
res_count_t *rcap;
assert(rcarray[i].count >= 1);
/* rcap points to the current type we are dealing with */
rcap = &(rcarray[i]);
/* Insert the first name-id */
rcap->rsc32array = (res32_count_t *)xmalloc(sizeof(res32_count_t));
rcap->count32 = 1;
rcap->rsc32array[0].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
rcap->rsc32array[0].count = 1;
rcap->rsc32array[0].rsc[0] = rcap->rscarray[0];
if(rcap->rscarray[0]->name->type == name_ord)
{
rcap->n_id_entries = 1;
rcap->n_name_entries = 0;
}
else
{
rcap->n_id_entries = 0;
rcap->n_name_entries = 1;
}
/* Now loop over the resting resources of the current type
* to find duplicate names (which should have different
* languages).
*/
for(j = 1; j < rcap->count; j++)
{
res32_count_t *r32cp;
/* r32cp points to the current res32_count structure
* that holds the resource name we are processing.
*/
r32cp = &(rcap->rsc32array[rcap->count32-1]);
if(!compare_name_id(r32cp->rsc[0]->name, rcarray[i].rscarray[j]->name))
{
/* Names are the same, add to list */
r32cp->count++;
r32cp->rsc = (resource_t **)xrealloc(r32cp->rsc, r32cp->count * sizeof(resource_t *));
r32cp->rsc[r32cp->count-1] = rcap->rscarray[j];
}
else
{
/* New name-id, sort the old one by
* language and create new list
*/
if(r32cp->count > 1)
qsort(r32cp->rsc, r32cp->count, sizeof(r32cp->rsc[0]), sort_language);
rcap->count32++;
rcap->rsc32array = (res32_count_t*)xrealloc(rcap->rsc32array, rcap->count32 * sizeof(res32_count_t));
rcap->rsc32array[rcap->count32-1].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
rcap->rsc32array[rcap->count32-1].count = 1;
rcap->rsc32array[rcap->count32-1].rsc[0] = rcap->rscarray[j];
if(rcap->rscarray[j]->name->type == name_ord)
rcap->n_id_entries++;
else
rcap->n_name_entries++;
}
}
/* Also sort the languages of the last name group */
if(rcap->rsc32array[rcap->count32-1].count > 1)
qsort(rcap->rsc32array[rcap->count32-1].rsc,
rcap->rsc32array[rcap->count32-1].count,
sizeof(rcap->rsc32array[rcap->count32-1].rsc[0]),
sort_language);
}
}
/*
*****************************************************************************
* Function : write_pe_segment
* Syntax : void write_pe_segment(FILE *fp)
* Input :
* Output :
* Description :
* Remarks :
*****************************************************************************
*/
static void write_pe_segment(FILE *fp)
{
int i;
fprintf(fp, "\t.align\t4\n");
fprintf(fp, __ASM_NAME("%s%s") ":\n", prefix, _PEResTab);
fprintf(fp, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix, _PEResTab);
/* Flags */
fprintf(fp, "\t.long\t0\n");
/* Time/Date stamp */
fprintf(fp, "\t.long\t0x%08lx\n", (long)now);
/* Version */
fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
/* # of id entries, # of name entries */
fprintf(fp, "\t.short\t%d, %d\n", n_name_entries, n_id_entries);
/* Write the type level of the tree */
for(i = 0; i < rccount; i++)
{
res_count_t *rcp;
char *label;
rcp = &rcarray[i];
/* TypeId */
if(rcp->type.type == name_ord)
fprintf(fp, "\t.long\t%d\n", rcp->type.name.i_name);
else
{
char *name = prep_nid_for_label(&(rcp->type));
fprintf(fp, "\t.long\t(" __ASM_NAME("%s_%s_typename") " - " __ASM_NAME("%s%s") ") | 0x80000000\n",
prefix,
name,
prefix,
_PEResTab);
}
/* Offset */
label = prep_nid_for_label(&(rcp->type));
fprintf(fp, "\t.long\t(.L%s - " __ASM_NAME("%s%s") ") | 0x80000000\n",
label,
prefix,
_PEResTab);
}
/* Write the name level of the tree */
for(i = 0; i < rccount; i++)
{
res_count_t *rcp;
char *typelabel;
char *namelabel;
int j;
rcp = &rcarray[i];
typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
fprintf(fp, ".L%s:\n", typelabel);
fprintf(fp, "\t.long\t0\n"); /* Flags */
fprintf(fp, "\t.long\t0x%08lx\n", (long)now); /* TimeDate */
fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
fprintf(fp, "\t.short\t%d, %d\n", rcp->n_name_entries, rcp->n_id_entries);
for(j = 0; j < rcp->count32; j++)
{
resource_t *rsc = rcp->rsc32array[j].rsc[0];
/* NameId */
if(rsc->name->type == name_ord)
fprintf(fp, "\t.long\t%d\n", rsc->name->name.i_name);
else
{
fprintf(fp, "\t.long\t(" __ASM_NAME("%s%s_name") " - " __ASM_NAME("%s%s") ") | 0x80000000\n",
prefix,
rsc->c_name,
prefix,
_PEResTab);
}
/* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
* put the offset to the resource data entry.
* ?? Is unescaping worth while ??
*/
/* Offset */
namelabel = prep_nid_for_label(rsc->name);
fprintf(fp, "\t.long\t(.L%s_%s - " __ASM_NAME("%s%s") ") | 0x80000000\n",
typelabel,
namelabel,
prefix,
_PEResTab);
}
free(typelabel);
}
/* Write the language level of the tree */
for(i = 0; i < rccount; i++)
{
res_count_t *rcp;
char *namelabel;
char *typelabel;
int j;
rcp = &rcarray[i];
typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
for(j = 0; j < rcp->count32; j++)
{
res32_count_t *r32cp = &(rcp->rsc32array[j]);
int k;
namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
fprintf(fp, ".L%s_%s:\n", typelabel, namelabel);
fprintf(fp, "\t.long\t0\n"); /* Flags */
fprintf(fp, "\t.long\t0x%08lx\n", (long)now); /* TimeDate */
fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
fprintf(fp, "\t.short\t0, %d\n", r32cp->count);
for(k = 0; k < r32cp->count; k++)
{
resource_t *rsc = r32cp->rsc[k];
assert(rsc->lan != NULL);
/* LanguageId */
fprintf(fp, "\t.long\t0x%08x\n", rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
/* Offset */
fprintf(fp, "\t.long\t.L%s_%s_%d - " __ASM_NAME("%s%s") "\n",
typelabel,
namelabel,
rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0,
prefix,
_PEResTab);
}
free(namelabel);
}
free(typelabel);
}
/* Write the resource table itself */
fprintf(fp, __ASM_NAME("%s_ResourceDirectory") ":\n", prefix);
fprintf(fp, "\t.globl\t" __ASM_NAME("%s_ResourceDirectory") "\n", prefix);
direntries = 0;
for(i = 0; i < rccount; i++)
{
res_count_t *rcp;
char *namelabel;
char *typelabel;
int j;
rcp = &rcarray[i];
typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
for(j = 0; j < rcp->count32; j++)
{
res32_count_t *r32cp = &(rcp->rsc32array[j]);
int k;
namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
for(k = 0; k < r32cp->count; k++)
{
resource_t *rsc = r32cp->rsc[k];
assert(rsc->lan != NULL);
fprintf(fp, ".L%s_%s_%d:\n",
typelabel,
namelabel,
rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
/* Data RVA */
fprintf(fp, "\t.long\t" __ASM_NAME("%s%s_data") " - " __ASM_NAME("%s%s") "\n",
prefix,
rsc->c_name,
prefix,
_PEResTab);
/* Size */
fprintf(fp, "\t.long\t%d\n",
rsc->binres->size - rsc->binres->dataidx);
/* CodePage */
fprintf(fp, "\t.long\t%ld\n", codepage);
/* Reserved */
fprintf(fp, "\t.long\t0\n");
direntries++;
}
free(namelabel);
}
free(typelabel);
}
}
/*
*****************************************************************************
* Function : write_ne_segment
* Syntax : void write_ne_segment(FILE *fp)
* Input :
* Output :
* Description :
* Remarks :
*****************************************************************************
*/
static void write_ne_segment(FILE *fp)
{
int i, j;
fprintf(fp, "\t.align\t4\n");
fprintf(fp, __ASM_NAME("%s%s") ":\n", prefix, _NEResTab);
fprintf(fp, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix, _NEResTab);
/* AlignmentShift */
fprintf(fp, "\t.short\t%d\n", alignment_pwr);
/* TypeInfo */
for(i = 0; i < rccount; i++)
{
res_count_t *rcp = &rcarray[i];
/* TypeId */
if(rcp->type.type == name_ord)
fprintf(fp, "\t.short\t0x%04x\n", rcp->type.name.i_name | 0x8000);
else
fprintf(fp, "\t.short\t" __ASM_NAME("%s_%s_typename") " - " __ASM_NAME("%s%s") "\n",
prefix,
rcp->type.name.s_name->str.cstr,
prefix,
_NEResTab);
/* ResourceCount */
fprintf(fp, "\t.short\t%d\n", rcp->count);
/* Reserved */
fprintf(fp, "\t.long\t0\n");
/* NameInfo */
for(j = 0; j < rcp->count; j++)
{
/*
* VERY IMPORTANT:
* The offset is relative to the beginning of the NE resource segment
* and _NOT_ to the file-beginning. This is because we do not have a
* file based resource, but a simulated NE segment. The offset _is_
* scaled by the AlignShift field.
* All other things are as the MS doc describes (alignment etc.)
*/
/* Offset */
fprintf(fp, "\t.short\t(" __ASM_NAME("%s%s_data") " - " __ASM_NAME("%s%s") ") >> %d\n",
prefix,
rcp->rscarray[j]->c_name,
prefix,
_NEResTab,
alignment_pwr);
/* Length */
fprintf(fp, "\t.short\t%d\n",
(rcp->rscarray[j]->binres->size - rcp->rscarray[j]->binres->dataidx + alignment - 1) >> alignment_pwr);
/* Flags */
fprintf(fp, "\t.short\t0x%04x\n", (WORD)rcp->rscarray[j]->memopt);
/* Id */
if(rcp->rscarray[j]->name->type == name_ord)
fprintf(fp, "\t.short\t0x%04x\n", rcp->rscarray[j]->name->name.i_name | 0x8000);
else
fprintf(fp, "\t.short\t" __ASM_NAME("%s%s_name") " - " __ASM_NAME("%s%s") "\n",
prefix,
rcp->rscarray[j]->c_name,
prefix,
_NEResTab);
/* Handle and Usage */
fprintf(fp, "\t.short\t0, 0\n");
}
}
/* EndTypes */
fprintf(fp, "\t.short\t0\n");
}
/*
*****************************************************************************
* Function : write_rsc_names
* Syntax : void write_rsc_names(FILE *fp)
* Input :
* Output :
* Description :
* Remarks :
*****************************************************************************
*/
static void write_rsc_names(FILE *fp)
{
int i, j;
if(win32)
{
/* Write the names */
for(i = 0; i < rccount; i++)
{
res_count_t *rcp;
rcp = &rcarray[i];
if(rcp->type.type == name_str)
{
char *name = prep_nid_for_label(&(rcp->type));
fprintf(fp, __ASM_NAME("%s_%s_typename") ":\n",
prefix,
name);
write_name_str(fp, &(rcp->type));
}
for(j = 0; j < rcp->count32; j++)
{
resource_t *rsc = rcp->rsc32array[j].rsc[0];
if(rsc->name->type == name_str)
{
fprintf(fp, __ASM_NAME("%s%s_name") ":\n",
prefix,
rsc->c_name);
write_name_str(fp, rsc->name);
}
}
}
}
else
{
/* ResourceNames */
for(i = 0; i < rccount; i++)
{
res_count_t *rcp = &rcarray[i];
if(rcp->type.type == name_str)
{
fprintf(fp, __ASM_NAME("%s_%s_typename") ":\n",
prefix,
rcp->type.name.s_name->str.cstr);
write_name_str(fp, &(rcp->type));
}
for(j = 0; j < rcp->count; j++)
{
if(rcp->rscarray[j]->name->type == name_str)
{
fprintf(fp, __ASM_NAME("%s%s_name") ":\n",
prefix,
rcp->rscarray[j]->c_name);
write_name_str(fp, rcp->rscarray[j]->name);
}
}
}
/* EndNames */
/* This is to end the NE resource table */
if(create_dir)
fprintf(fp, "\t.byte\t0\n");
}
fprintf(fp, "\n");
}
/*
*****************************************************************************
* Function : write_s_file
* Syntax : void write_s_file(char *outname, resource_t *top)
* Input :
* outname - Filename to write to
* top - The resource-tree to convert
* Output :
* Description :
* Remarks :
*****************************************************************************
*/
void write_s_file(char *outname, resource_t *top)
{
FILE *fo;
resource_t *rsc;
fo = fopen(outname, "wt");
if(!fo)
{
error("Could not open %s\n", outname);
return;
}
{
char *s, *p;
s = ctime(&now);
p = strchr(s, '\n');
if(p) *p = '\0';
fprintf(fo, s_file_head_str, input_name ? input_name : "stdin",
cmdline, s);
}
/* Get an idea how many we have and restructure the tables */
count_resources(top);
/* First write the segment tables */
if(create_dir)
{
if(win32)
write_pe_segment(fo);
else
write_ne_segment(fo);
}
/* Dump the names */
write_rsc_names(fo);
if(create_dir)
fprintf(fo, ".LResTabEnd:\n");
/* Write the resource data */
fprintf(fo, "\n/* Resource binary data */\n\n");
for(rsc = top; rsc; rsc = rsc->next)
{
if(!rsc->binres)
continue;
fprintf(fo, "\t.align\t%d\n", win32 ? 4 : alignment);
fprintf(fo, __ASM_NAME("%s%s_data") ":\n", prefix, rsc->c_name);
if(global)
fprintf(fo, "\t.globl\t" __ASM_NAME("%s%s_data") "\n", prefix, rsc->c_name);
write_s_res(fo, rsc->binres);
fprintf(fo, "\n");
}
if(create_dir)
{
/* Add a resource descriptor for built-in and elf-dlls */
fprintf(fo, "\t.align\t4\n");
fprintf(fo, __ASM_NAME("%s_ResourceDescriptor") ":\n", prefix);
fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourceDescriptor") "\n", prefix);
fprintf(fo, __ASM_NAME("%s_ResourceTable") ":\n", prefix);
if(global)
fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourceTable") "\n", prefix);
fprintf(fo, "\t.long\t" __ASM_NAME("%s%s") "\n", prefix, win32 ? _PEResTab : _NEResTab);
fprintf(fo, __ASM_NAME("%s_NumberOfResources") ":\n", prefix);
if(global)
fprintf(fo, "\t.globl\t" __ASM_NAME("%s_NumberOfResources") "\n", prefix);
fprintf(fo, "\t.long\t%d\n", direntries);
fprintf(fo, __ASM_NAME("%s_ResourceSectionSize") ":\n", prefix);
if(global)
fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourceSectionSize") "\n", prefix);
fprintf(fo, "\t.long\t.LResTabEnd - " __ASM_NAME("%s%s") "\n", prefix, win32 ? _PEResTab : _NEResTab);
if(win32)
{
fprintf(fo, __ASM_NAME("%s_ResourcesEntries") ":\n", prefix);
if(global)
fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourcesEntries") "\n", prefix);
fprintf(fo, "\t.long\t" __ASM_NAME("%s_ResourceDirectory") "\n", prefix);
}
}
fprintf(fo, s_file_tail_str);
fclose(fo);
}
/*
* Write resource prototypes
*
* Copyright 1998 Bertho A. Stultiens (BS)
*
* 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
*/
#ifndef __WRC_WRITERES_H
#define __WRC_WRITERES_H
#ifndef __WRC_WRCTYPES_H
#include "wrctypes.h"
#endif
void write_resfile(char *outname, resource_t *top);
void write_s_file(char *outname, resource_t *top);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment