2 * Write .res, .s and .h file(s) from a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
29 #include "wine/unicode.h"
36 static char s_file_head_str[] =
37 "/* This file is generated with wrc version " WRC_FULLVERSION ". Do not edit! */\n"
46 static char s_file_tail_str[] =
51 static char s_file_autoreg_str[] =
54 "\tpushl\t$" __ASM_NAME("%s%s") "\n"
55 "\tcall\t" __ASM_NAME("LIBRES_RegisterResources") "\n"
59 ".stabs \"___CTOR_LIST__\",22,0,0,.LAuto_Register\n\n"
61 "\t.section .ctors,\"aw\"\n"
62 "\t.long\t.LAuto_Register\n\n"
66 static char h_file_head_str[] =
68 " * This file is generated with wrc version " WRC_FULLVERSION ". Do not edit!\n"
74 "#ifndef __%08lx_H\n" /* This becomes the date of compile */
77 "#include <wrc_rsc.h>\n"
81 static char h_file_tail_str[] =
86 char _NEResTab[] = "_NEResTab";
87 char _PEResTab[] = "_PEResTab";
88 char _ResTable[] = "_ResTable";
90 /* Variables used for resource sorting */
91 res_count_t *rcarray = NULL; /* Type-level count array */
92 int rccount = 0; /* Nr of entries in the type-level array */
93 int n_id_entries = 0; /* win32 only: Nr of unique ids in the type-level array */
94 int n_name_entries = 0; /* win32 only: Nr of unique namess in the type-level array */
96 static int direntries; /* win32 only: Total number of unique resources */
99 *****************************************************************************
100 * Function : write_resfile
101 * Syntax : void write_resfile(char *outname, resource_t *top)
103 * outname - Filename to write to
104 * top - The resource-tree to convert
108 *****************************************************************************
110 void write_resfile(char *outname, resource_t *top)
114 char zeros[3] = {0, 0, 0};
116 fo = fopen(outname, "wb");
119 error("Could not open %s\n", outname);
124 /* Put an empty resource first to signal win32 format */
125 res_t *res = new_res();
126 put_dword(res, 0); /* ResSize */
127 put_dword(res, 0x00000020); /* HeaderSize */
128 put_word(res, 0xffff); /* ResType */
130 put_word(res, 0xffff); /* ResName */
132 put_dword(res, 0); /* DataVersion */
133 put_word(res, 0); /* Memory options */
134 put_word(res, 0); /* Language */
135 put_dword(res, 0); /* Version */
136 put_dword(res, 0); /* Charateristics */
137 ret = fwrite(res->data, 1, res->size, fo);
141 error("Error writing %s", outname);
146 for(; top; top = top->next)
151 ret = fwrite(top->binres->data, 1, top->binres->size, fo);
152 if(ret != top->binres->size)
155 error("Error writing %s", outname);
157 if(win32 && (top->binres->size & 0x03))
160 ret = fwrite(zeros, 1, 4 - (top->binres->size & 0x03), fo);
161 if(ret != 4 - (top->binres->size & 0x03))
164 error("Error writing %s", outname);
172 *****************************************************************************
173 * Function : write_s_res
174 * Syntax : void write_s_res(FILE *fp, res_t *res)
179 *****************************************************************************
181 #define BYTESPERLINE 8
182 static void write_s_res(FILE *fp, res_t *res)
184 int idx = res->dataidx;
186 int rest = (end - idx) % BYTESPERLINE;
187 int lines = (end - idx) / BYTESPERLINE;
190 for(i = 0 ; i < lines; i++)
192 fprintf(fp, "\t.byte\t");
193 for(j = 0; j < BYTESPERLINE; j++, idx++)
195 fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
196 j == BYTESPERLINE-1 ? "" : ", ");
202 fprintf(fp, "\t.byte\t");
203 for(j = 0; j < rest; j++, idx++)
205 fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
206 j == rest-1 ? "" : ", ");
214 *****************************************************************************
215 * Function : write_name_str
216 * Syntax : void write_name_str(FILE *fp, name_id_t *nid)
220 * Remarks : One level self recursive for string type conversion
221 *****************************************************************************
223 static void write_name_str(FILE *fp, name_id_t *nid)
226 assert(nid->type == name_str);
228 if(!win32 && nid->name.s_name->type == str_char)
230 res.size = strlen(nid->name.s_name->str.cstr);
232 error("Can't write strings larger than 254 bytes");
234 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
236 res.data = (char *)xmalloc(1 + res.size + 1);
237 res.data[0] = (char)res.size;
238 res.size++; /* We need to write the length byte as well */
239 strcpy(res.data+1, nid->name.s_name->str.cstr);
240 write_s_res(fp, &res);
243 else if(!win32 && nid->name.s_name->type == str_unicode)
248 lnid.type = name_str;
249 lnid.name.s_name = &str;
251 str.str.cstr = dupwstr2cstr(nid->name.s_name->str.wstr);
252 write_name_str(fp, &lnid);
255 else if(win32 && nid->name.s_name->type == str_char)
260 lnid.type = name_str;
261 lnid.name.s_name = &str;
262 str.type = str_unicode;
263 str.str.wstr = dupcstr2wstr(nid->name.s_name->str.cstr);
264 write_name_str(fp, &lnid);
267 else if(win32 && nid->name.s_name->type == str_unicode)
269 res.size = strlenW(nid->name.s_name->str.wstr);
271 error("Can't write strings larger than 65534 characters");
273 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
275 res.data = (char *)xmalloc(2 + (res.size + 1) * 2);
276 ((short *)res.data)[0] = (short)res.size;
277 strcpyW((WCHAR *)(res.data+2), nid->name.s_name->str.wstr);
278 res.size *= 2; /* Function writes bytes, not shorts... */
279 res.size += 2; /* We need to write the length word as well */
280 write_s_res(fp, &res);
285 internal_error(__FILE__, __LINE__, "Hmm, requested to write a string of unknown type %d",
286 nid->name.s_name->type);
291 *****************************************************************************
292 * Function : find_counter
293 * Syntax : res_count_t *find_counter(name_id_t *type)
298 *****************************************************************************
300 static res_count_t *find_counter(name_id_t *type)
303 for(i = 0; i < rccount; i++)
305 if(!compare_name_id(type, &(rcarray[i].type)))
312 *****************************************************************************
313 * Function : count_resources
314 * Syntax : res_count_t *count_resources(resource_t *top)
318 * Remarks : The whole lot is converted into arrays because they are
319 * easy sortable. Makes the lot almost unreadable, but it
320 * works (I hope). Basically you have to keep in mind that
321 * the lot is a three-dimensional structure for win32 and a
322 * two-dimensional structure for win16.
323 *****************************************************************************
325 #define RCT(v) (*((resource_t **)(v)))
326 /* qsort sorting function */
327 static int sort_name_id(const void *e1, const void *e2)
329 return compare_name_id(RCT(e1)->name, RCT(e2)->name);
332 static int sort_language(const void *e1, const void *e2)
334 assert((RCT(e1)->lan) != NULL);
335 assert((RCT(e2)->lan) != NULL);
337 return MAKELANGID(RCT(e1)->lan->id, RCT(e1)->lan->sub)
338 - MAKELANGID(RCT(e2)->lan->id, RCT(e2)->lan->sub);
341 #define RCT(v) ((res_count_t *)(v))
342 static int sort_type(const void *e1, const void *e2)
344 return compare_name_id(&(RCT(e1)->type), &(RCT(e2)->type));
348 static void count_resources(resource_t *top)
355 for(rsc = top; rsc; rsc = rsc->next)
362 nid.name.i_name = WRC_RT_DIALOG;
366 nid.name.i_name = WRC_RT_MENU;
370 nid = *(rsc->res.usr->type);
373 nid.name.i_name = rsc->type;
377 if((rcp = find_counter(&nid)) == NULL)
379 /* Count the number of uniq ids and names */
381 if(nid.type == name_ord)
388 rcarray = (res_count_t *)xmalloc(sizeof(res_count_t));
390 rcarray[0].count = 1;
391 rcarray[0].type = nid;
392 rcarray[0].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
393 rcarray[0].rscarray[0] = rsc;
398 rcarray = (res_count_t *)xrealloc(rcarray, rccount * sizeof(res_count_t));
399 rcarray[rccount-1].count = 1;
400 rcarray[rccount-1].type = nid;
401 rcarray[rccount-1].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
402 rcarray[rccount-1].rscarray[0] = rsc;
408 rcp->rscarray = (resource_t **)xrealloc(rcp->rscarray, rcp->count * sizeof(resource_t *));
409 rcp->rscarray[rcp->count-1] = rsc;
415 /* We're done, win16 requires no special sorting */
419 /* We now have a unsorted list of types with an array of res_count_t
420 * in rcarray[0..rccount-1]. And we have names of one type in the
421 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
422 * The list needs to be sorted for win32's top level tree structure.
427 qsort(rcarray, rccount, sizeof(rcarray[0]), sort_type);
429 /* Now sort the name-id arrays */
430 for(i = 0; i < rccount; i++)
432 if(rcarray[i].count > 1)
433 qsort(rcarray[i].rscarray, rcarray[i].count, sizeof(rcarray[0].rscarray[0]), sort_name_id);
436 /* Now split the name-id arrays into name/language
437 * subs. Don't look at the awfull expressions...
438 * We do this by taking the array elements out of rscarray and putting
439 * together a new array in rsc32array.
441 for(i = 0; i < rccount; i++)
445 assert(rcarray[i].count >= 1);
447 /* rcap points to the current type we are dealing with */
448 rcap = &(rcarray[i]);
450 /* Insert the first name-id */
451 rcap->rsc32array = (res32_count_t *)xmalloc(sizeof(res32_count_t));
453 rcap->rsc32array[0].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
454 rcap->rsc32array[0].count = 1;
455 rcap->rsc32array[0].rsc[0] = rcap->rscarray[0];
456 if(rcap->rscarray[0]->name->type == name_ord)
458 rcap->n_id_entries = 1;
459 rcap->n_name_entries = 0;
463 rcap->n_id_entries = 0;
464 rcap->n_name_entries = 1;
467 /* Now loop over the resting resources of the current type
468 * to find duplicate names (which should have different
471 for(j = 1; j < rcap->count; j++)
473 res32_count_t *r32cp;
475 /* r32cp points to the current res32_count structure
476 * that holds the resource name we are processing.
478 r32cp = &(rcap->rsc32array[rcap->count32-1]);
480 if(!compare_name_id(r32cp->rsc[0]->name, rcarray[i].rscarray[j]->name))
482 /* Names are the same, add to list */
484 r32cp->rsc = (resource_t **)xrealloc(r32cp->rsc, r32cp->count * sizeof(resource_t *));
485 r32cp->rsc[r32cp->count-1] = rcap->rscarray[j];
489 /* New name-id, sort the old one by
490 * language and create new list
493 qsort(r32cp->rsc, r32cp->count, sizeof(r32cp->rsc[0]), sort_language);
495 rcap->rsc32array = (res32_count_t*)xrealloc(rcap->rsc32array, rcap->count32 * sizeof(res32_count_t));
496 rcap->rsc32array[rcap->count32-1].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
497 rcap->rsc32array[rcap->count32-1].count = 1;
498 rcap->rsc32array[rcap->count32-1].rsc[0] = rcap->rscarray[j];
500 if(rcap->rscarray[j]->name->type == name_ord)
501 rcap->n_id_entries++;
503 rcap->n_name_entries++;
506 /* Also sort the languages of the last name group */
507 if(rcap->rsc32array[rcap->count32-1].count > 1)
508 qsort(rcap->rsc32array[rcap->count32-1].rsc,
509 rcap->rsc32array[rcap->count32-1].count,
510 sizeof(rcap->rsc32array[rcap->count32-1].rsc[0]),
516 *****************************************************************************
517 * Function : write_pe_segment
518 * Syntax : void write_pe_segment(FILE *fp)
523 *****************************************************************************
525 static void write_pe_segment(FILE *fp)
529 fprintf(fp, "\t.align\t4\n");
530 fprintf(fp, __ASM_NAME("%s%s") ":\n", prefix, _PEResTab);
531 fprintf(fp, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix, _PEResTab);
533 fprintf(fp, "\t.long\t0\n");
534 /* Time/Date stamp */
535 fprintf(fp, "\t.long\t0x%08lx\n", (long)now);
537 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
538 /* # of id entries, # of name entries */
539 fprintf(fp, "\t.short\t%d, %d\n", n_name_entries, n_id_entries);
541 /* Write the type level of the tree */
542 for(i = 0; i < rccount; i++)
550 if(rcp->type.type == name_ord)
551 fprintf(fp, "\t.long\t%d\n", rcp->type.name.i_name);
554 char *name = prep_nid_for_label(&(rcp->type));
555 fprintf(fp, "\t.long\t(" __ASM_NAME("%s_%s_typename") " - " __ASM_NAME("%s%s") ") | 0x80000000\n",
562 label = prep_nid_for_label(&(rcp->type));
563 fprintf(fp, "\t.long\t(.L%s - " __ASM_NAME("%s%s") ") | 0x80000000\n",
569 /* Write the name level of the tree */
571 for(i = 0; i < rccount; i++)
580 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
581 fprintf(fp, ".L%s:\n", typelabel);
583 fprintf(fp, "\t.long\t0\n"); /* Flags */
584 fprintf(fp, "\t.long\t0x%08lx\n", (long)now); /* TimeDate */
585 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
586 fprintf(fp, "\t.short\t%d, %d\n", rcp->n_name_entries, rcp->n_id_entries);
587 for(j = 0; j < rcp->count32; j++)
589 resource_t *rsc = rcp->rsc32array[j].rsc[0];
591 if(rsc->name->type == name_ord)
592 fprintf(fp, "\t.long\t%d\n", rsc->name->name.i_name);
595 fprintf(fp, "\t.long\t(" __ASM_NAME("%s%s_name") " - " __ASM_NAME("%s%s") ") | 0x80000000\n",
601 /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
602 * put the offset to the resource data entry.
603 * ?? Is unescaping worth while ??
606 namelabel = prep_nid_for_label(rsc->name);
607 fprintf(fp, "\t.long\t(.L%s_%s - " __ASM_NAME("%s%s") ") | 0x80000000\n",
616 /* Write the language level of the tree */
618 for(i = 0; i < rccount; i++)
626 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
628 for(j = 0; j < rcp->count32; j++)
630 res32_count_t *r32cp = &(rcp->rsc32array[j]);
633 namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
634 fprintf(fp, ".L%s_%s:\n", typelabel, namelabel);
636 fprintf(fp, "\t.long\t0\n"); /* Flags */
637 fprintf(fp, "\t.long\t0x%08lx\n", (long)now); /* TimeDate */
638 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
639 fprintf(fp, "\t.short\t0, %d\n", r32cp->count);
641 for(k = 0; k < r32cp->count; k++)
643 resource_t *rsc = r32cp->rsc[k];
644 assert(rsc->lan != NULL);
646 fprintf(fp, "\t.long\t0x%08x\n", rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
648 fprintf(fp, "\t.long\t.L%s_%s_%d - " __ASM_NAME("%s%s") "\n",
651 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0,
660 /* Write the resource table itself */
661 fprintf(fp, __ASM_NAME("%s_ResourceDirectory") ":\n", prefix);
662 fprintf(fp, "\t.globl\t" __ASM_NAME("%s_ResourceDirectory") "\n", prefix);
665 for(i = 0; i < rccount; i++)
673 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
675 for(j = 0; j < rcp->count32; j++)
677 res32_count_t *r32cp = &(rcp->rsc32array[j]);
680 namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
682 for(k = 0; k < r32cp->count; k++)
684 resource_t *rsc = r32cp->rsc[k];
686 assert(rsc->lan != NULL);
688 fprintf(fp, ".L%s_%s_%d:\n",
691 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
694 fprintf(fp, "\t.long\t" __ASM_NAME("%s%s_data") " - " __ASM_NAME("%s%s") "\n",
700 fprintf(fp, "\t.long\t%d\n",
701 rsc->binres->size - rsc->binres->dataidx);
703 fprintf(fp, "\t.long\t%ld\n", codepage);
705 fprintf(fp, "\t.long\t0\n");
716 *****************************************************************************
717 * Function : write_ne_segment
718 * Syntax : void write_ne_segment(FILE *fp)
723 *****************************************************************************
725 static void write_ne_segment(FILE *fp)
729 fprintf(fp, "\t.align\t4\n");
730 fprintf(fp, __ASM_NAME("%s%s") ":\n", prefix, _NEResTab);
731 fprintf(fp, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix, _NEResTab);
734 fprintf(fp, "\t.short\t%d\n", alignment_pwr);
737 for(i = 0; i < rccount; i++)
739 res_count_t *rcp = &rcarray[i];
742 if(rcp->type.type == name_ord)
743 fprintf(fp, "\t.short\t0x%04x\n", rcp->type.name.i_name | 0x8000);
745 fprintf(fp, "\t.short\t" __ASM_NAME("%s_%s_typename") " - " __ASM_NAME("%s%s") "\n",
747 rcp->type.name.s_name->str.cstr,
751 fprintf(fp, "\t.short\t%d\n", rcp->count);
753 fprintf(fp, "\t.long\t0\n");
755 for(j = 0; j < rcp->count; j++)
759 * The offset is relative to the beginning of the NE resource segment
760 * and _NOT_ to the file-beginning. This is because we do not have a
761 * file based resource, but a simulated NE segment. The offset _is_
762 * scaled by the AlignShift field.
763 * All other things are as the MS doc describes (alignment etc.)
766 fprintf(fp, "\t.short\t(" __ASM_NAME("%s%s_data") " - " __ASM_NAME("%s%s") ") >> %d\n",
768 rcp->rscarray[j]->c_name,
773 fprintf(fp, "\t.short\t%d\n",
774 (rcp->rscarray[j]->binres->size - rcp->rscarray[j]->binres->dataidx + alignment - 1) >> alignment_pwr);
776 fprintf(fp, "\t.short\t0x%04x\n", (WORD)rcp->rscarray[j]->memopt);
778 if(rcp->rscarray[j]->name->type == name_ord)
779 fprintf(fp, "\t.short\t0x%04x\n", rcp->rscarray[j]->name->name.i_name | 0x8000);
781 fprintf(fp, "\t.short\t" __ASM_NAME("%s%s_name") " - " __ASM_NAME("%s%s") "\n",
783 rcp->rscarray[j]->c_name,
786 /* Handle and Usage */
787 fprintf(fp, "\t.short\t0, 0\n");
791 fprintf(fp, "\t.short\t0\n");
795 *****************************************************************************
796 * Function : write_rsc_names
797 * Syntax : void write_rsc_names(FILE *fp)
802 *****************************************************************************
804 static void write_rsc_names(FILE *fp)
810 /* Write the names */
812 for(i = 0; i < rccount; i++)
818 if(rcp->type.type == name_str)
820 char *name = prep_nid_for_label(&(rcp->type));
821 fprintf(fp, __ASM_NAME("%s_%s_typename") ":\n",
824 write_name_str(fp, &(rcp->type));
827 for(j = 0; j < rcp->count32; j++)
829 resource_t *rsc = rcp->rsc32array[j].rsc[0];
831 if(rsc->name->type == name_str)
833 fprintf(fp, __ASM_NAME("%s%s_name") ":\n",
836 write_name_str(fp, rsc->name);
844 for(i = 0; i < rccount; i++)
846 res_count_t *rcp = &rcarray[i];
848 if(rcp->type.type == name_str)
850 fprintf(fp, __ASM_NAME("%s_%s_typename") ":\n",
852 rcp->type.name.s_name->str.cstr);
853 write_name_str(fp, &(rcp->type));
855 for(j = 0; j < rcp->count; j++)
857 if(rcp->rscarray[j]->name->type == name_str)
859 fprintf(fp, __ASM_NAME("%s%s_name") ":\n",
861 rcp->rscarray[j]->c_name);
862 write_name_str(fp, rcp->rscarray[j]->name);
868 /* This is to end the NE resource table */
870 fprintf(fp, "\t.byte\t0\n");
877 *****************************************************************************
878 * Function : write_s_file
879 * Syntax : void write_s_file(char *outname, resource_t *top)
881 * outname - Filename to write to
882 * top - The resource-tree to convert
886 *****************************************************************************
888 void write_s_file(char *outname, resource_t *top)
893 fo = fopen(outname, "wt");
896 error("Could not open %s\n", outname);
905 fprintf(fo, s_file_head_str, input_name ? input_name : "stdin",
909 /* Get an idea how many we have and restructure the tables */
910 count_resources(top);
912 /* First write the segment tables */
916 write_pe_segment(fo);
918 write_ne_segment(fo);
925 fprintf(fo, ".LResTabEnd:\n");
929 /* Write the resource data */
930 fprintf(fo, "\n/* Resource binary data */\n\n");
931 for(rsc = top; rsc; rsc = rsc->next)
936 fprintf(fo, "\t.align\t%d\n", win32 ? 4 : alignment);
937 fprintf(fo, __ASM_NAME("%s%s_data") ":\n", prefix, rsc->c_name);
939 fprintf(fo, "\t.globl\t" __ASM_NAME("%s%s_data") "\n", prefix, rsc->c_name);
941 write_s_res(fo, rsc->binres);
948 /* Add a resource descriptor for built-in and elf-dlls */
949 fprintf(fo, "\t.align\t4\n");
950 fprintf(fo, __ASM_NAME("%s_ResourceDescriptor") ":\n", prefix);
951 fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourceDescriptor") "\n", prefix);
952 fprintf(fo, __ASM_NAME("%s_ResourceTable") ":\n", prefix);
954 fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourceTable") "\n", prefix);
955 fprintf(fo, "\t.long\t" __ASM_NAME("%s%s") "\n", prefix, win32 ? _PEResTab : _NEResTab);
956 fprintf(fo, __ASM_NAME("%s_NumberOfResources") ":\n", prefix);
958 fprintf(fo, "\t.globl\t" __ASM_NAME("%s_NumberOfResources") "\n", prefix);
959 fprintf(fo, "\t.long\t%d\n", direntries);
960 fprintf(fo, __ASM_NAME("%s_ResourceSectionSize") ":\n", prefix);
962 fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourceSectionSize") "\n", prefix);
963 fprintf(fo, "\t.long\t.LResTabEnd - " __ASM_NAME("%s%s") "\n", prefix, win32 ? _PEResTab : _NEResTab);
966 fprintf(fo, __ASM_NAME("%s_ResourcesEntries") ":\n", prefix);
968 fprintf(fo, "\t.globl\t" __ASM_NAME("%s_ResourcesEntries") "\n", prefix);
969 fprintf(fo, "\t.long\t" __ASM_NAME("%s_ResourceDirectory") "\n", prefix);
976 /* Write the indirection structures */
977 fprintf(fo, "\n/* Resource indirection structures */\n\n");
978 fprintf(fo, "\t.align\t4\n");
979 for(rsc = top; rsc; rsc = rsc->next)
982 char *type_name = NULL;
993 type = WRC_RT_DIALOG;
996 assert(rsc->res.usr->type != NULL);
997 type_name = prep_nid_for_label(rsc->res.usr->type);
1005 * This follows a structure like:
1006 * struct wrc_resource {
1010 * RSCNAME *typename;
1014 * The 'RSCNAME' is a pascal-style string where the
1015 * first byte/word denotes the size and the rest the string
1018 fprintf(fo, __ASM_NAME("%s%s") ":\n", prefix, rsc->c_name);
1020 fprintf(fo, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix, rsc->c_name);
1021 if (rsc->name->type == name_ord)
1022 fprintf(fo, "\t.long\t%d, 0, ", rsc->name->name.i_name );
1024 fprintf(fo, "\t.long\t0, " __ASM_NAME("%s%s_name") ", ",
1025 prefix, rsc->c_name );
1027 fprintf(fo, "%d, 0, ", type);
1029 fprintf(fo, "0, " __ASM_NAME("%s_%s_typename") ", ",
1030 prefix, type_name );
1032 fprintf(fo, __ASM_NAME("%s%s_data") ", %d\n",
1035 rsc->binres->size - rsc->binres->dataidx);
1040 /* Write the indirection table */
1041 fprintf(fo, "/* Resource indirection table */\n\n");
1042 fprintf(fo, "\t.align\t4\n");
1043 fprintf(fo, __ASM_NAME("%s%s") ":\n", prefix, _ResTable);
1044 fprintf(fo, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix, _ResTable);
1045 for(rsc = top; rsc; rsc = rsc->next)
1047 fprintf(fo, "\t.long\t" __ASM_NAME("%s%s") "\n", prefix, rsc->c_name);
1049 fprintf(fo, "\t.long\t0\n");
1054 fprintf(fo, s_file_autoreg_str, prefix, _ResTable);
1056 fprintf(fo, s_file_tail_str);
1061 *****************************************************************************
1062 * Function : write_h_file
1063 * Syntax : void write_h_file(char *outname, resource_t *top)
1065 * outname - Filename to write to
1066 * top - The resource-tree to convert
1070 *****************************************************************************
1072 void write_h_file(char *outname, resource_t *top)
1077 fo = fopen(outname, "wt");
1080 error("Could not open %s\n", outname);
1083 fprintf(fo, h_file_head_str, input_name ? input_name : "stdin",
1084 cmdline, ctime(&now), (long)now, (long)now);
1086 /* First write the segment tables reference */
1089 fprintf(fo, "extern %schar %s%s[];\n\n",
1090 constant ? "const " : "",
1092 win32 ? _PEResTab : _NEResTab);
1095 /* Write the resource data */
1096 for(rsc = top; global && rsc; rsc = rsc->next)
1101 fprintf(fo, "extern %schar %s%s_data[];\n",
1102 constant ? "const " : "",
1112 /* Write the indirection structures */
1113 for(rsc = top; global && rsc; rsc = rsc->next)
1115 fprintf(fo, "extern %swrc_resource%d_t %s%s;\n",
1116 constant ? "const " : "",
1125 /* Write the indirection table */
1126 fprintf(fo, "extern %swrc_resource%d_t %s%s[];\n\n",
1127 constant ? "const " : "",
1133 fprintf(fo, h_file_tail_str);