#include "wrc.h"
#include "utils.h"
-#include "writeres.h"
#include "readres.h"
#include "dumpres.h"
#include "genres.h"
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"
" -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"
" * 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"
" 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).
*/
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
*/
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)
*/
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' },
case 'a':
alignment = atoi(optarg);
break;
- case 'b':
- binary = 1;
- break;
case 'B':
switch(optarg[0])
{
case 'F':
/* ignored for compatibility with windres */
break;
- case 'g':
- global = 1;
- break;
case 'h':
printf(usage);
exit(0);
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;
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)
{
}
}
- 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++)
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
input_name = temp_name;
}
- if(!binary)
- {
- /* Go from .rc to .res or .s */
- chat("Starting parse");
-
- if(!(yyin = fopen(input_name, "rb")))
- error("Could not open %s for input\n", input_name);
+ /* Go from .rc to .res */
+ chat("Starting parse");
- ret = yyparse();
+ if(!(yyin = fopen(input_name, "rb")))
+ error("Could not open %s for input\n", input_name);
- if(input_name)
- fclose(yyin);
+ ret = yyparse();
- if(ret)
- {
- /* Error during parse */
- exit(1);
- }
+ if(input_name) fclose(yyin);
- if(debuglevel & DEBUGLEVEL_DUMP)
- dump_resources(resource_top);
+ if(ret) exit(1); /* Error during parse */
- /* Convert the internal lists to binary data */
- resources2res(resource_top);
+ if(debuglevel & DEBUGLEVEL_DUMP)
+ dump_resources(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);
- }
+ /* Convert the internal lists to binary data */
+ resources2res(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);
- }
- }
+ chat("Writing .res-file");
+ write_resfile(output_name, resource_top);
return 0;
}
/*
- * Write .res, .s and .h file(s) from a resource-tree
+ * Write .res file from a resource-tree
*
* Copyright 1998 Bertho A. Stultiens
*
#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
}
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);
-}