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
)
247 lnid
.type
= name_str
;
248 lnid
.name
.s_name
= convert_string( nid
->name
.s_name
, str_char
,
249 get_language_codepage(0,0) );
250 write_name_str(fp
, &lnid
);
251 free_string( lnid
.name
.s_name
);
253 else if(win32
&& nid
->name
.s_name
->type
== str_char
)
257 lnid
.type
= name_str
;
258 lnid
.name
.s_name
= convert_string( nid
->name
.s_name
, str_unicode
,
259 get_language_codepage(0,0) );
260 write_name_str(fp
, &lnid
);
261 free_string( lnid
.name
.s_name
);
263 else if(win32
&& nid
->name
.s_name
->type
== str_unicode
)
265 res
.size
= strlenW(nid
->name
.s_name
->str
.wstr
);
267 error("Can't write strings larger than 65534 characters");
269 internal_error(__FILE__
, __LINE__
, "Attempt to write empty string");
271 res
.data
= (char *)xmalloc(2 + (res
.size
+ 1) * 2);
272 ((short *)res
.data
)[0] = (short)res
.size
;
273 strcpyW((WCHAR
*)(res
.data
+2), nid
->name
.s_name
->str
.wstr
);
274 res
.size
*= 2; /* Function writes bytes, not shorts... */
275 res
.size
+= 2; /* We need to write the length word as well */
276 write_s_res(fp
, &res
);
281 internal_error(__FILE__
, __LINE__
, "Hmm, requested to write a string of unknown type %d",
282 nid
->name
.s_name
->type
);
287 *****************************************************************************
288 * Function : find_counter
289 * Syntax : res_count_t *find_counter(name_id_t *type)
294 *****************************************************************************
296 static res_count_t
*find_counter(name_id_t
*type
)
299 for(i
= 0; i
< rccount
; i
++)
301 if(!compare_name_id(type
, &(rcarray
[i
].type
)))
308 *****************************************************************************
309 * Function : count_resources
310 * Syntax : res_count_t *count_resources(resource_t *top)
314 * Remarks : The whole lot is converted into arrays because they are
315 * easy sortable. Makes the lot almost unreadable, but it
316 * works (I hope). Basically you have to keep in mind that
317 * the lot is a three-dimensional structure for win32 and a
318 * two-dimensional structure for win16.
319 *****************************************************************************
321 #define RCT(v) (*((resource_t **)(v)))
322 /* qsort sorting function */
323 static int sort_name_id(const void *e1
, const void *e2
)
325 return compare_name_id(RCT(e1
)->name
, RCT(e2
)->name
);
328 static int sort_language(const void *e1
, const void *e2
)
330 assert((RCT(e1
)->lan
) != NULL
);
331 assert((RCT(e2
)->lan
) != NULL
);
333 return MAKELANGID(RCT(e1
)->lan
->id
, RCT(e1
)->lan
->sub
)
334 - MAKELANGID(RCT(e2
)->lan
->id
, RCT(e2
)->lan
->sub
);
337 #define RCT(v) ((res_count_t *)(v))
338 static int sort_type(const void *e1
, const void *e2
)
340 return compare_name_id(&(RCT(e1
)->type
), &(RCT(e2
)->type
));
344 static void count_resources(resource_t
*top
)
351 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
358 nid
.name
.i_name
= WRC_RT_DIALOG
;
362 nid
.name
.i_name
= WRC_RT_MENU
;
366 nid
= *(rsc
->res
.usr
->type
);
369 nid
.name
.i_name
= rsc
->type
;
373 if((rcp
= find_counter(&nid
)) == NULL
)
375 /* Count the number of uniq ids and names */
377 if(nid
.type
== name_ord
)
384 rcarray
= (res_count_t
*)xmalloc(sizeof(res_count_t
));
386 rcarray
[0].count
= 1;
387 rcarray
[0].type
= nid
;
388 rcarray
[0].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
389 rcarray
[0].rscarray
[0] = rsc
;
394 rcarray
= (res_count_t
*)xrealloc(rcarray
, rccount
* sizeof(res_count_t
));
395 rcarray
[rccount
-1].count
= 1;
396 rcarray
[rccount
-1].type
= nid
;
397 rcarray
[rccount
-1].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
398 rcarray
[rccount
-1].rscarray
[0] = rsc
;
404 rcp
->rscarray
= (resource_t
**)xrealloc(rcp
->rscarray
, rcp
->count
* sizeof(resource_t
*));
405 rcp
->rscarray
[rcp
->count
-1] = rsc
;
411 /* We're done, win16 requires no special sorting */
415 /* We now have a unsorted list of types with an array of res_count_t
416 * in rcarray[0..rccount-1]. And we have names of one type in the
417 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
418 * The list needs to be sorted for win32's top level tree structure.
423 qsort(rcarray
, rccount
, sizeof(rcarray
[0]), sort_type
);
425 /* Now sort the name-id arrays */
426 for(i
= 0; i
< rccount
; i
++)
428 if(rcarray
[i
].count
> 1)
429 qsort(rcarray
[i
].rscarray
, rcarray
[i
].count
, sizeof(rcarray
[0].rscarray
[0]), sort_name_id
);
432 /* Now split the name-id arrays into name/language
433 * subs. Don't look at the awfull expressions...
434 * We do this by taking the array elements out of rscarray and putting
435 * together a new array in rsc32array.
437 for(i
= 0; i
< rccount
; i
++)
441 assert(rcarray
[i
].count
>= 1);
443 /* rcap points to the current type we are dealing with */
444 rcap
= &(rcarray
[i
]);
446 /* Insert the first name-id */
447 rcap
->rsc32array
= (res32_count_t
*)xmalloc(sizeof(res32_count_t
));
449 rcap
->rsc32array
[0].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
450 rcap
->rsc32array
[0].count
= 1;
451 rcap
->rsc32array
[0].rsc
[0] = rcap
->rscarray
[0];
452 if(rcap
->rscarray
[0]->name
->type
== name_ord
)
454 rcap
->n_id_entries
= 1;
455 rcap
->n_name_entries
= 0;
459 rcap
->n_id_entries
= 0;
460 rcap
->n_name_entries
= 1;
463 /* Now loop over the resting resources of the current type
464 * to find duplicate names (which should have different
467 for(j
= 1; j
< rcap
->count
; j
++)
469 res32_count_t
*r32cp
;
471 /* r32cp points to the current res32_count structure
472 * that holds the resource name we are processing.
474 r32cp
= &(rcap
->rsc32array
[rcap
->count32
-1]);
476 if(!compare_name_id(r32cp
->rsc
[0]->name
, rcarray
[i
].rscarray
[j
]->name
))
478 /* Names are the same, add to list */
480 r32cp
->rsc
= (resource_t
**)xrealloc(r32cp
->rsc
, r32cp
->count
* sizeof(resource_t
*));
481 r32cp
->rsc
[r32cp
->count
-1] = rcap
->rscarray
[j
];
485 /* New name-id, sort the old one by
486 * language and create new list
489 qsort(r32cp
->rsc
, r32cp
->count
, sizeof(r32cp
->rsc
[0]), sort_language
);
491 rcap
->rsc32array
= (res32_count_t
*)xrealloc(rcap
->rsc32array
, rcap
->count32
* sizeof(res32_count_t
));
492 rcap
->rsc32array
[rcap
->count32
-1].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
493 rcap
->rsc32array
[rcap
->count32
-1].count
= 1;
494 rcap
->rsc32array
[rcap
->count32
-1].rsc
[0] = rcap
->rscarray
[j
];
496 if(rcap
->rscarray
[j
]->name
->type
== name_ord
)
497 rcap
->n_id_entries
++;
499 rcap
->n_name_entries
++;
502 /* Also sort the languages of the last name group */
503 if(rcap
->rsc32array
[rcap
->count32
-1].count
> 1)
504 qsort(rcap
->rsc32array
[rcap
->count32
-1].rsc
,
505 rcap
->rsc32array
[rcap
->count32
-1].count
,
506 sizeof(rcap
->rsc32array
[rcap
->count32
-1].rsc
[0]),
512 *****************************************************************************
513 * Function : write_pe_segment
514 * Syntax : void write_pe_segment(FILE *fp)
519 *****************************************************************************
521 static void write_pe_segment(FILE *fp
)
525 fprintf(fp
, "\t.align\t4\n");
526 fprintf(fp
, __ASM_NAME("%s%s") ":\n", prefix
, _PEResTab
);
527 fprintf(fp
, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix
, _PEResTab
);
529 fprintf(fp
, "\t.long\t0\n");
530 /* Time/Date stamp */
531 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
);
533 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
534 /* # of id entries, # of name entries */
535 fprintf(fp
, "\t.short\t%d, %d\n", n_name_entries
, n_id_entries
);
537 /* Write the type level of the tree */
538 for(i
= 0; i
< rccount
; i
++)
546 if(rcp
->type
.type
== name_ord
)
547 fprintf(fp
, "\t.long\t%d\n", rcp
->type
.name
.i_name
);
550 char *name
= prep_nid_for_label(&(rcp
->type
));
551 fprintf(fp
, "\t.long\t(" __ASM_NAME("%s_%s_typename") " - " __ASM_NAME("%s%s") ") | 0x80000000\n",
558 label
= prep_nid_for_label(&(rcp
->type
));
559 fprintf(fp
, "\t.long\t(.L%s - " __ASM_NAME("%s%s") ") | 0x80000000\n",
565 /* Write the name level of the tree */
567 for(i
= 0; i
< rccount
; i
++)
576 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
577 fprintf(fp
, ".L%s:\n", typelabel
);
579 fprintf(fp
, "\t.long\t0\n"); /* Flags */
580 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
); /* TimeDate */
581 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
582 fprintf(fp
, "\t.short\t%d, %d\n", rcp
->n_name_entries
, rcp
->n_id_entries
);
583 for(j
= 0; j
< rcp
->count32
; j
++)
585 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
587 if(rsc
->name
->type
== name_ord
)
588 fprintf(fp
, "\t.long\t%d\n", rsc
->name
->name
.i_name
);
591 fprintf(fp
, "\t.long\t(" __ASM_NAME("%s%s_name") " - " __ASM_NAME("%s%s") ") | 0x80000000\n",
597 /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
598 * put the offset to the resource data entry.
599 * ?? Is unescaping worth while ??
602 namelabel
= prep_nid_for_label(rsc
->name
);
603 fprintf(fp
, "\t.long\t(.L%s_%s - " __ASM_NAME("%s%s") ") | 0x80000000\n",
612 /* Write the language level of the tree */
614 for(i
= 0; i
< rccount
; i
++)
622 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
624 for(j
= 0; j
< rcp
->count32
; j
++)
626 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
629 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
630 fprintf(fp
, ".L%s_%s:\n", typelabel
, namelabel
);
632 fprintf(fp
, "\t.long\t0\n"); /* Flags */
633 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
); /* TimeDate */
634 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
635 fprintf(fp
, "\t.short\t0, %d\n", r32cp
->count
);
637 for(k
= 0; k
< r32cp
->count
; k
++)
639 resource_t
*rsc
= r32cp
->rsc
[k
];
640 assert(rsc
->lan
!= NULL
);
642 fprintf(fp
, "\t.long\t0x%08x\n", rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
644 fprintf(fp
, "\t.long\t.L%s_%s_%d - " __ASM_NAME("%s%s") "\n",
647 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0,
656 /* Write the resource table itself */
657 fprintf(fp
, __ASM_NAME("%s_ResourceDirectory") ":\n", prefix
);
658 fprintf(fp
, "\t.globl\t" __ASM_NAME("%s_ResourceDirectory") "\n", prefix
);
661 for(i
= 0; i
< rccount
; i
++)
669 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
671 for(j
= 0; j
< rcp
->count32
; j
++)
673 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
676 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
678 for(k
= 0; k
< r32cp
->count
; k
++)
680 resource_t
*rsc
= r32cp
->rsc
[k
];
682 assert(rsc
->lan
!= NULL
);
684 fprintf(fp
, ".L%s_%s_%d:\n",
687 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
690 fprintf(fp
, "\t.long\t" __ASM_NAME("%s%s_data") " - " __ASM_NAME("%s%s") "\n",
696 fprintf(fp
, "\t.long\t%d\n",
697 rsc
->binres
->size
- rsc
->binres
->dataidx
);
699 fprintf(fp
, "\t.long\t%ld\n", codepage
);
701 fprintf(fp
, "\t.long\t0\n");
712 *****************************************************************************
713 * Function : write_ne_segment
714 * Syntax : void write_ne_segment(FILE *fp)
719 *****************************************************************************
721 static void write_ne_segment(FILE *fp
)
725 fprintf(fp
, "\t.align\t4\n");
726 fprintf(fp
, __ASM_NAME("%s%s") ":\n", prefix
, _NEResTab
);
727 fprintf(fp
, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix
, _NEResTab
);
730 fprintf(fp
, "\t.short\t%d\n", alignment_pwr
);
733 for(i
= 0; i
< rccount
; i
++)
735 res_count_t
*rcp
= &rcarray
[i
];
738 if(rcp
->type
.type
== name_ord
)
739 fprintf(fp
, "\t.short\t0x%04x\n", rcp
->type
.name
.i_name
| 0x8000);
741 fprintf(fp
, "\t.short\t" __ASM_NAME("%s_%s_typename") " - " __ASM_NAME("%s%s") "\n",
743 rcp
->type
.name
.s_name
->str
.cstr
,
747 fprintf(fp
, "\t.short\t%d\n", rcp
->count
);
749 fprintf(fp
, "\t.long\t0\n");
751 for(j
= 0; j
< rcp
->count
; j
++)
755 * The offset is relative to the beginning of the NE resource segment
756 * and _NOT_ to the file-beginning. This is because we do not have a
757 * file based resource, but a simulated NE segment. The offset _is_
758 * scaled by the AlignShift field.
759 * All other things are as the MS doc describes (alignment etc.)
762 fprintf(fp
, "\t.short\t(" __ASM_NAME("%s%s_data") " - " __ASM_NAME("%s%s") ") >> %d\n",
764 rcp
->rscarray
[j
]->c_name
,
769 fprintf(fp
, "\t.short\t%d\n",
770 (rcp
->rscarray
[j
]->binres
->size
- rcp
->rscarray
[j
]->binres
->dataidx
+ alignment
- 1) >> alignment_pwr
);
772 fprintf(fp
, "\t.short\t0x%04x\n", (WORD
)rcp
->rscarray
[j
]->memopt
);
774 if(rcp
->rscarray
[j
]->name
->type
== name_ord
)
775 fprintf(fp
, "\t.short\t0x%04x\n", rcp
->rscarray
[j
]->name
->name
.i_name
| 0x8000);
777 fprintf(fp
, "\t.short\t" __ASM_NAME("%s%s_name") " - " __ASM_NAME("%s%s") "\n",
779 rcp
->rscarray
[j
]->c_name
,
782 /* Handle and Usage */
783 fprintf(fp
, "\t.short\t0, 0\n");
787 fprintf(fp
, "\t.short\t0\n");
791 *****************************************************************************
792 * Function : write_rsc_names
793 * Syntax : void write_rsc_names(FILE *fp)
798 *****************************************************************************
800 static void write_rsc_names(FILE *fp
)
806 /* Write the names */
808 for(i
= 0; i
< rccount
; i
++)
814 if(rcp
->type
.type
== name_str
)
816 char *name
= prep_nid_for_label(&(rcp
->type
));
817 fprintf(fp
, __ASM_NAME("%s_%s_typename") ":\n",
820 write_name_str(fp
, &(rcp
->type
));
823 for(j
= 0; j
< rcp
->count32
; j
++)
825 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
827 if(rsc
->name
->type
== name_str
)
829 fprintf(fp
, __ASM_NAME("%s%s_name") ":\n",
832 write_name_str(fp
, rsc
->name
);
840 for(i
= 0; i
< rccount
; i
++)
842 res_count_t
*rcp
= &rcarray
[i
];
844 if(rcp
->type
.type
== name_str
)
846 fprintf(fp
, __ASM_NAME("%s_%s_typename") ":\n",
848 rcp
->type
.name
.s_name
->str
.cstr
);
849 write_name_str(fp
, &(rcp
->type
));
851 for(j
= 0; j
< rcp
->count
; j
++)
853 if(rcp
->rscarray
[j
]->name
->type
== name_str
)
855 fprintf(fp
, __ASM_NAME("%s%s_name") ":\n",
857 rcp
->rscarray
[j
]->c_name
);
858 write_name_str(fp
, rcp
->rscarray
[j
]->name
);
864 /* This is to end the NE resource table */
866 fprintf(fp
, "\t.byte\t0\n");
873 *****************************************************************************
874 * Function : write_s_file
875 * Syntax : void write_s_file(char *outname, resource_t *top)
877 * outname - Filename to write to
878 * top - The resource-tree to convert
882 *****************************************************************************
884 void write_s_file(char *outname
, resource_t
*top
)
889 fo
= fopen(outname
, "wt");
892 error("Could not open %s\n", outname
);
901 fprintf(fo
, s_file_head_str
, input_name
? input_name
: "stdin",
905 /* Get an idea how many we have and restructure the tables */
906 count_resources(top
);
908 /* First write the segment tables */
912 write_pe_segment(fo
);
914 write_ne_segment(fo
);
921 fprintf(fo
, ".LResTabEnd:\n");
925 /* Write the resource data */
926 fprintf(fo
, "\n/* Resource binary data */\n\n");
927 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
932 fprintf(fo
, "\t.align\t%d\n", win32
? 4 : alignment
);
933 fprintf(fo
, __ASM_NAME("%s%s_data") ":\n", prefix
, rsc
->c_name
);
935 fprintf(fo
, "\t.globl\t" __ASM_NAME("%s%s_data") "\n", prefix
, rsc
->c_name
);
937 write_s_res(fo
, rsc
->binres
);
944 /* Add a resource descriptor for built-in and elf-dlls */
945 fprintf(fo
, "\t.align\t4\n");
946 fprintf(fo
, __ASM_NAME("%s_ResourceDescriptor") ":\n", prefix
);
947 fprintf(fo
, "\t.globl\t" __ASM_NAME("%s_ResourceDescriptor") "\n", prefix
);
948 fprintf(fo
, __ASM_NAME("%s_ResourceTable") ":\n", prefix
);
950 fprintf(fo
, "\t.globl\t" __ASM_NAME("%s_ResourceTable") "\n", prefix
);
951 fprintf(fo
, "\t.long\t" __ASM_NAME("%s%s") "\n", prefix
, win32
? _PEResTab
: _NEResTab
);
952 fprintf(fo
, __ASM_NAME("%s_NumberOfResources") ":\n", prefix
);
954 fprintf(fo
, "\t.globl\t" __ASM_NAME("%s_NumberOfResources") "\n", prefix
);
955 fprintf(fo
, "\t.long\t%d\n", direntries
);
956 fprintf(fo
, __ASM_NAME("%s_ResourceSectionSize") ":\n", prefix
);
958 fprintf(fo
, "\t.globl\t" __ASM_NAME("%s_ResourceSectionSize") "\n", prefix
);
959 fprintf(fo
, "\t.long\t.LResTabEnd - " __ASM_NAME("%s%s") "\n", prefix
, win32
? _PEResTab
: _NEResTab
);
962 fprintf(fo
, __ASM_NAME("%s_ResourcesEntries") ":\n", prefix
);
964 fprintf(fo
, "\t.globl\t" __ASM_NAME("%s_ResourcesEntries") "\n", prefix
);
965 fprintf(fo
, "\t.long\t" __ASM_NAME("%s_ResourceDirectory") "\n", prefix
);
972 /* Write the indirection structures */
973 fprintf(fo
, "\n/* Resource indirection structures */\n\n");
974 fprintf(fo
, "\t.align\t4\n");
975 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
978 char *type_name
= NULL
;
989 type
= WRC_RT_DIALOG
;
992 assert(rsc
->res
.usr
->type
!= NULL
);
993 type_name
= prep_nid_for_label(rsc
->res
.usr
->type
);
1001 * This follows a structure like:
1002 * struct wrc_resource {
1006 * RSCNAME *typename;
1010 * The 'RSCNAME' is a pascal-style string where the
1011 * first byte/word denotes the size and the rest the string
1014 fprintf(fo
, __ASM_NAME("%s%s") ":\n", prefix
, rsc
->c_name
);
1016 fprintf(fo
, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix
, rsc
->c_name
);
1017 if (rsc
->name
->type
== name_ord
)
1018 fprintf(fo
, "\t.long\t%d, 0, ", rsc
->name
->name
.i_name
);
1020 fprintf(fo
, "\t.long\t0, " __ASM_NAME("%s%s_name") ", ",
1021 prefix
, rsc
->c_name
);
1023 fprintf(fo
, "%d, 0, ", type
);
1025 fprintf(fo
, "0, " __ASM_NAME("%s_%s_typename") ", ",
1026 prefix
, type_name
);
1028 fprintf(fo
, __ASM_NAME("%s%s_data") ", %d\n",
1031 rsc
->binres
->size
- rsc
->binres
->dataidx
);
1036 /* Write the indirection table */
1037 fprintf(fo
, "/* Resource indirection table */\n\n");
1038 fprintf(fo
, "\t.align\t4\n");
1039 fprintf(fo
, __ASM_NAME("%s%s") ":\n", prefix
, _ResTable
);
1040 fprintf(fo
, "\t.globl\t" __ASM_NAME("%s%s") "\n", prefix
, _ResTable
);
1041 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
1043 fprintf(fo
, "\t.long\t" __ASM_NAME("%s%s") "\n", prefix
, rsc
->c_name
);
1045 fprintf(fo
, "\t.long\t0\n");
1050 fprintf(fo
, s_file_autoreg_str
, prefix
, _ResTable
);
1052 fprintf(fo
, s_file_tail_str
);
1057 *****************************************************************************
1058 * Function : write_h_file
1059 * Syntax : void write_h_file(char *outname, resource_t *top)
1061 * outname - Filename to write to
1062 * top - The resource-tree to convert
1066 *****************************************************************************
1068 void write_h_file(char *outname
, resource_t
*top
)
1073 fo
= fopen(outname
, "wt");
1076 error("Could not open %s\n", outname
);
1079 fprintf(fo
, h_file_head_str
, input_name
? input_name
: "stdin",
1080 cmdline
, ctime(&now
), (long)now
, (long)now
);
1082 /* First write the segment tables reference */
1085 fprintf(fo
, "extern %schar %s%s[];\n\n",
1086 constant
? "const " : "",
1088 win32
? _PEResTab
: _NEResTab
);
1091 /* Write the resource data */
1092 for(rsc
= top
; global
&& rsc
; rsc
= rsc
->next
)
1097 fprintf(fo
, "extern %schar %s%s_data[];\n",
1098 constant
? "const " : "",
1108 /* Write the indirection structures */
1109 for(rsc
= top
; global
&& rsc
; rsc
= rsc
->next
)
1111 fprintf(fo
, "extern %swrc_resource%d_t %s%s;\n",
1112 constant
? "const " : "",
1121 /* Write the indirection table */
1122 fprintf(fo
, "extern %swrc_resource%d_t %s%s[];\n\n",
1123 constant
? "const " : "",
1129 fprintf(fo
, h_file_tail_str
);