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
28 #include "wine/unicode.h"
35 #ifdef NEED_UNDERSCORE_PREFIX
36 char Underscore
[] = "_";
38 char Underscore
[] = "";
41 static char s_file_head_str
[] =
42 "/* This file is generated with wrc version " WRC_FULLVERSION
". Do not edit! */\n"
51 static char s_file_tail_str
[] =
56 static char s_file_autoreg_str
[] =
60 #ifdef NEED_UNDERSCORE_PREFIX
61 "\tcall\t_LIBRES_RegisterResources\n"
63 "\tcall\tLIBRES_RegisterResources\n"
68 ".stabs \"___CTOR_LIST__\",22,0,0,.LAuto_Register\n\n"
70 "\t.section .ctors,\"aw\"\n"
71 "\t.long\t.LAuto_Register\n\n"
75 static char h_file_head_str
[] =
77 " * This file is generated with wrc version " WRC_FULLVERSION
". Do not edit!\n"
83 "#ifndef __%08lx_H\n" /* This becomes the date of compile */
86 "#include <wrc_rsc.h>\n"
90 static char h_file_tail_str
[] =
95 char _NEResTab
[] = "_NEResTab";
96 char _PEResTab
[] = "_PEResTab";
97 char _ResTable
[] = "_ResTable";
99 /* Variables used for resource sorting */
100 res_count_t
*rcarray
= NULL
; /* Type-level count array */
101 int rccount
= 0; /* Nr of entries in the type-level array */
102 int n_id_entries
= 0; /* win32 only: Nr of unique ids in the type-level array */
103 int n_name_entries
= 0; /* win32 only: Nr of unique namess in the type-level array */
105 static int direntries
; /* win32 only: Total number of unique resources */
108 *****************************************************************************
109 * Function : write_resfile
110 * Syntax : void write_resfile(char *outname, resource_t *top)
112 * outname - Filename to write to
113 * top - The resource-tree to convert
117 *****************************************************************************
119 void write_resfile(char *outname
, resource_t
*top
)
123 char zeros
[3] = {0, 0, 0};
125 fo
= fopen(outname
, "wb");
128 error("Could not open %s\n", outname
);
133 /* Put an empty resource first to signal win32 format */
134 res_t
*res
= new_res();
135 put_dword(res
, 0); /* ResSize */
136 put_dword(res
, 0x00000020); /* HeaderSize */
137 put_word(res
, 0xffff); /* ResType */
139 put_word(res
, 0xffff); /* ResName */
141 put_dword(res
, 0); /* DataVersion */
142 put_word(res
, 0); /* Memory options */
143 put_word(res
, 0); /* Language */
144 put_dword(res
, 0); /* Version */
145 put_dword(res
, 0); /* Charateristics */
146 ret
= fwrite(res
->data
, 1, res
->size
, fo
);
150 error("Error writing %s", outname
);
155 for(; top
; top
= top
->next
)
160 ret
= fwrite(top
->binres
->data
, 1, top
->binres
->size
, fo
);
161 if(ret
!= top
->binres
->size
)
164 error("Error writing %s", outname
);
166 if(win32
&& (top
->binres
->size
& 0x03))
169 ret
= fwrite(zeros
, 1, 4 - (top
->binres
->size
& 0x03), fo
);
170 if(ret
!= 4 - (top
->binres
->size
& 0x03))
173 error("Error writing %s", outname
);
181 *****************************************************************************
182 * Function : write_s_res
183 * Syntax : void write_s_res(FILE *fp, res_t *res)
188 *****************************************************************************
190 #define BYTESPERLINE 8
191 static void write_s_res(FILE *fp
, res_t
*res
)
193 int idx
= res
->dataidx
;
195 int rest
= (end
- idx
) % BYTESPERLINE
;
196 int lines
= (end
- idx
) / BYTESPERLINE
;
199 for(i
= 0 ; i
< lines
; i
++)
201 fprintf(fp
, "\t.byte\t");
202 for(j
= 0; j
< BYTESPERLINE
; j
++, idx
++)
204 fprintf(fp
, "0x%02x%s", res
->data
[idx
] & 0xff,
205 j
== BYTESPERLINE
-1 ? "" : ", ");
211 fprintf(fp
, "\t.byte\t");
212 for(j
= 0; j
< rest
; j
++, idx
++)
214 fprintf(fp
, "0x%02x%s", res
->data
[idx
] & 0xff,
215 j
== rest
-1 ? "" : ", ");
223 *****************************************************************************
224 * Function : write_name_str
225 * Syntax : void write_name_str(FILE *fp, name_id_t *nid)
229 * Remarks : One level self recursive for string type conversion
230 *****************************************************************************
232 static void write_name_str(FILE *fp
, name_id_t
*nid
)
235 assert(nid
->type
== name_str
);
237 if(!win32
&& nid
->name
.s_name
->type
== str_char
)
239 res
.size
= strlen(nid
->name
.s_name
->str
.cstr
);
241 error("Can't write strings larger than 254 bytes");
243 internal_error(__FILE__
, __LINE__
, "Attempt to write empty string");
245 res
.data
= (char *)xmalloc(1 + res
.size
+ 1);
246 res
.data
[0] = (char)res
.size
;
247 res
.size
++; /* We need to write the length byte as well */
248 strcpy(res
.data
+1, nid
->name
.s_name
->str
.cstr
);
249 write_s_res(fp
, &res
);
252 else if(!win32
&& nid
->name
.s_name
->type
== str_unicode
)
257 lnid
.type
= name_str
;
258 lnid
.name
.s_name
= &str
;
260 str
.str
.cstr
= dupwstr2cstr(nid
->name
.s_name
->str
.wstr
);
261 write_name_str(fp
, &lnid
);
264 else if(win32
&& nid
->name
.s_name
->type
== str_char
)
269 lnid
.type
= name_str
;
270 lnid
.name
.s_name
= &str
;
271 str
.type
= str_unicode
;
272 str
.str
.wstr
= dupcstr2wstr(nid
->name
.s_name
->str
.cstr
);
273 write_name_str(fp
, &lnid
);
276 else if(win32
&& nid
->name
.s_name
->type
== str_unicode
)
278 res
.size
= strlenW(nid
->name
.s_name
->str
.wstr
);
280 error("Can't write strings larger than 65534 characters");
282 internal_error(__FILE__
, __LINE__
, "Attempt to write empty string");
284 res
.data
= (char *)xmalloc(2 + (res
.size
+ 1) * 2);
285 ((short *)res
.data
)[0] = (short)res
.size
;
286 strcpyW((WCHAR
*)(res
.data
+2), nid
->name
.s_name
->str
.wstr
);
287 res
.size
*= 2; /* Function writes bytes, not shorts... */
288 res
.size
+= 2; /* We need to write the length word as well */
289 write_s_res(fp
, &res
);
294 internal_error(__FILE__
, __LINE__
, "Hmm, requested to write a string of unknown type %d",
295 nid
->name
.s_name
->type
);
300 *****************************************************************************
301 * Function : find_counter
302 * Syntax : res_count_t *find_counter(name_id_t *type)
307 *****************************************************************************
309 static res_count_t
*find_counter(name_id_t
*type
)
312 for(i
= 0; i
< rccount
; i
++)
314 if(!compare_name_id(type
, &(rcarray
[i
].type
)))
321 *****************************************************************************
322 * Function : count_resources
323 * Syntax : res_count_t *count_resources(resource_t *top)
327 * Remarks : The whole lot is converted into arrays because they are
328 * easy sortable. Makes the lot almost unreadable, but it
329 * works (I hope). Basically you have to keep in mind that
330 * the lot is a three-dimensional structure for win32 and a
331 * two-dimensional structure for win16.
332 *****************************************************************************
334 #define RCT(v) (*((resource_t **)(v)))
335 /* qsort sorting function */
336 static int sort_name_id(const void *e1
, const void *e2
)
338 return compare_name_id(RCT(e1
)->name
, RCT(e2
)->name
);
341 static int sort_language(const void *e1
, const void *e2
)
343 assert((RCT(e1
)->lan
) != NULL
);
344 assert((RCT(e2
)->lan
) != NULL
);
346 return MAKELANGID(RCT(e1
)->lan
->id
, RCT(e1
)->lan
->sub
)
347 - MAKELANGID(RCT(e2
)->lan
->id
, RCT(e2
)->lan
->sub
);
350 #define RCT(v) ((res_count_t *)(v))
351 static int sort_type(const void *e1
, const void *e2
)
353 return compare_name_id(&(RCT(e1
)->type
), &(RCT(e2
)->type
));
357 static void count_resources(resource_t
*top
)
364 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
371 nid
.name
.i_name
= WRC_RT_DIALOG
;
375 nid
.name
.i_name
= WRC_RT_MENU
;
379 nid
= *(rsc
->res
.usr
->type
);
382 nid
.name
.i_name
= rsc
->type
;
386 if((rcp
= find_counter(&nid
)) == NULL
)
388 /* Count the number of uniq ids and names */
390 if(nid
.type
== name_ord
)
397 rcarray
= (res_count_t
*)xmalloc(sizeof(res_count_t
));
399 rcarray
[0].count
= 1;
400 rcarray
[0].type
= nid
;
401 rcarray
[0].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
402 rcarray
[0].rscarray
[0] = rsc
;
407 rcarray
= (res_count_t
*)xrealloc(rcarray
, rccount
* sizeof(res_count_t
));
408 rcarray
[rccount
-1].count
= 1;
409 rcarray
[rccount
-1].type
= nid
;
410 rcarray
[rccount
-1].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
411 rcarray
[rccount
-1].rscarray
[0] = rsc
;
417 rcp
->rscarray
= (resource_t
**)xrealloc(rcp
->rscarray
, rcp
->count
* sizeof(resource_t
*));
418 rcp
->rscarray
[rcp
->count
-1] = rsc
;
424 /* We're done, win16 requires no special sorting */
428 /* We now have a unsorted list of types with an array of res_count_t
429 * in rcarray[0..rccount-1]. And we have names of one type in the
430 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
431 * The list needs to be sorted for win32's top level tree structure.
436 qsort(rcarray
, rccount
, sizeof(rcarray
[0]), sort_type
);
438 /* Now sort the name-id arrays */
439 for(i
= 0; i
< rccount
; i
++)
441 if(rcarray
[i
].count
> 1)
442 qsort(rcarray
[i
].rscarray
, rcarray
[i
].count
, sizeof(rcarray
[0].rscarray
[0]), sort_name_id
);
445 /* Now split the name-id arrays into name/language
446 * subs. Don't look at the awfull expressions...
447 * We do this by taking the array elements out of rscarray and putting
448 * together a new array in rsc32array.
450 for(i
= 0; i
< rccount
; i
++)
454 assert(rcarray
[i
].count
>= 1);
456 /* rcap points to the current type we are dealing with */
457 rcap
= &(rcarray
[i
]);
459 /* Insert the first name-id */
460 rcap
->rsc32array
= (res32_count_t
*)xmalloc(sizeof(res32_count_t
));
462 rcap
->rsc32array
[0].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
463 rcap
->rsc32array
[0].count
= 1;
464 rcap
->rsc32array
[0].rsc
[0] = rcap
->rscarray
[0];
465 if(rcap
->rscarray
[0]->name
->type
== name_ord
)
467 rcap
->n_id_entries
= 1;
468 rcap
->n_name_entries
= 0;
472 rcap
->n_id_entries
= 0;
473 rcap
->n_name_entries
= 1;
476 /* Now loop over the resting resources of the current type
477 * to find duplicate names (which should have different
480 for(j
= 1; j
< rcap
->count
; j
++)
482 res32_count_t
*r32cp
;
484 /* r32cp points to the current res32_count structure
485 * that holds the resource name we are processing.
487 r32cp
= &(rcap
->rsc32array
[rcap
->count32
-1]);
489 if(!compare_name_id(r32cp
->rsc
[0]->name
, rcarray
[i
].rscarray
[j
]->name
))
491 /* Names are the same, add to list */
493 r32cp
->rsc
= (resource_t
**)xrealloc(r32cp
->rsc
, r32cp
->count
* sizeof(resource_t
*));
494 r32cp
->rsc
[r32cp
->count
-1] = rcap
->rscarray
[j
];
498 /* New name-id, sort the old one by
499 * language and create new list
502 qsort(r32cp
->rsc
, r32cp
->count
, sizeof(r32cp
->rsc
[0]), sort_language
);
504 rcap
->rsc32array
= (res32_count_t
*)xrealloc(rcap
->rsc32array
, rcap
->count32
* sizeof(res32_count_t
));
505 rcap
->rsc32array
[rcap
->count32
-1].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
506 rcap
->rsc32array
[rcap
->count32
-1].count
= 1;
507 rcap
->rsc32array
[rcap
->count32
-1].rsc
[0] = rcap
->rscarray
[j
];
509 if(rcap
->rscarray
[j
]->name
->type
== name_ord
)
510 rcap
->n_id_entries
++;
512 rcap
->n_name_entries
++;
515 /* Also sort the languages of the last name group */
516 if(rcap
->rsc32array
[rcap
->count32
-1].count
> 1)
517 qsort(rcap
->rsc32array
[rcap
->count32
-1].rsc
,
518 rcap
->rsc32array
[rcap
->count32
-1].count
,
519 sizeof(rcap
->rsc32array
[rcap
->count32
-1].rsc
[0]),
525 *****************************************************************************
526 * Function : write_pe_segment
527 * Syntax : void write_pe_segment(FILE *fp)
532 *****************************************************************************
534 static void write_pe_segment(FILE *fp
)
538 fprintf(fp
, "\t.align\t4\n");
539 fprintf(fp
, "%s%s:\n", prefix
, _PEResTab
);
540 fprintf(fp
, "\t.globl\t%s%s\n", prefix
, _PEResTab
);
542 fprintf(fp
, "\t.long\t0\n");
543 /* Time/Date stamp */
544 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
);
546 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
547 /* # of id entries, # of name entries */
548 fprintf(fp
, "\t.short\t%d, %d\n", n_name_entries
, n_id_entries
);
550 /* Write the type level of the tree */
551 for(i
= 0; i
< rccount
; i
++)
559 if(rcp
->type
.type
== name_ord
)
560 fprintf(fp
, "\t.long\t%d\n", rcp
->type
.name
.i_name
);
563 char *name
= prep_nid_for_label(&(rcp
->type
));
564 fprintf(fp
, "\t.long\t(%s_%s_typename - %s%s) | 0x80000000\n",
571 label
= prep_nid_for_label(&(rcp
->type
));
572 fprintf(fp
, "\t.long\t(.L%s - %s%s) | 0x80000000\n",
578 /* Write the name level of the tree */
580 for(i
= 0; i
< rccount
; i
++)
589 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
590 fprintf(fp
, ".L%s:\n", typelabel
);
592 fprintf(fp
, "\t.long\t0\n"); /* Flags */
593 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
); /* TimeDate */
594 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
595 fprintf(fp
, "\t.short\t%d, %d\n", rcp
->n_name_entries
, rcp
->n_id_entries
);
596 for(j
= 0; j
< rcp
->count32
; j
++)
598 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
600 if(rsc
->name
->type
== name_ord
)
601 fprintf(fp
, "\t.long\t%d\n", rsc
->name
->name
.i_name
);
604 fprintf(fp
, "\t.long\t(%s%s_name - %s%s) | 0x80000000\n",
610 /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
611 * put the offset to the resource data entry.
612 * ?? Is unescaping worth while ??
615 namelabel
= prep_nid_for_label(rsc
->name
);
616 fprintf(fp
, "\t.long\t(.L%s_%s - %s%s) | 0x80000000\n",
625 /* Write the language level of the tree */
627 for(i
= 0; i
< rccount
; i
++)
635 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
637 for(j
= 0; j
< rcp
->count32
; j
++)
639 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
642 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
643 fprintf(fp
, ".L%s_%s:\n", typelabel
, namelabel
);
645 fprintf(fp
, "\t.long\t0\n"); /* Flags */
646 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
); /* TimeDate */
647 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
648 fprintf(fp
, "\t.short\t0, %d\n", r32cp
->count
);
650 for(k
= 0; k
< r32cp
->count
; k
++)
652 resource_t
*rsc
= r32cp
->rsc
[k
];
653 assert(rsc
->lan
!= NULL
);
655 fprintf(fp
, "\t.long\t0x%08x\n", rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
657 fprintf(fp
, "\t.long\t.L%s_%s_%d - %s%s\n",
660 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0,
669 /* Write the resource table itself */
670 fprintf(fp
, "%s_ResourceDirectory:\n", prefix
);
671 fprintf(fp
, "\t.globl\t%s_ResourceDirectory\n", prefix
);
674 for(i
= 0; i
< rccount
; i
++)
682 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
684 for(j
= 0; j
< rcp
->count32
; j
++)
686 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
689 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
691 for(k
= 0; k
< r32cp
->count
; k
++)
693 resource_t
*rsc
= r32cp
->rsc
[k
];
695 assert(rsc
->lan
!= NULL
);
697 fprintf(fp
, ".L%s_%s_%d:\n",
700 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
703 fprintf(fp
, "\t.long\t%s%s_data - %s%s\n",
709 fprintf(fp
, "\t.long\t%d\n",
710 rsc
->binres
->size
- rsc
->binres
->dataidx
);
712 fprintf(fp
, "\t.long\t%ld\n", codepage
);
714 fprintf(fp
, "\t.long\t0\n");
725 *****************************************************************************
726 * Function : write_ne_segment
727 * Syntax : void write_ne_segment(FILE *fp)
732 *****************************************************************************
734 static void write_ne_segment(FILE *fp
)
738 fprintf(fp
, "\t.align\t4\n");
739 fprintf(fp
, "%s%s:\n", prefix
, _NEResTab
);
740 fprintf(fp
, "\t.globl\t%s%s\n", prefix
, _NEResTab
);
743 fprintf(fp
, "\t.short\t%d\n", alignment_pwr
);
746 for(i
= 0; i
< rccount
; i
++)
748 res_count_t
*rcp
= &rcarray
[i
];
751 if(rcp
->type
.type
== name_ord
)
752 fprintf(fp
, "\t.short\t0x%04x\n", rcp
->type
.name
.i_name
| 0x8000);
754 fprintf(fp
, "\t.short\t%s_%s_typename - %s%s\n",
756 rcp
->type
.name
.s_name
->str
.cstr
,
760 fprintf(fp
, "\t.short\t%d\n", rcp
->count
);
762 fprintf(fp
, "\t.long\t0\n");
764 for(j
= 0; j
< rcp
->count
; j
++)
768 * The offset is relative to the beginning of the NE resource segment
769 * and _NOT_ to the file-beginning. This is because we do not have a
770 * file based resource, but a simulated NE segment. The offset _is_
771 * scaled by the AlignShift field.
772 * All other things are as the MS doc describes (alignment etc.)
775 fprintf(fp
, "\t.short\t(%s%s_data - %s%s) >> %d\n",
777 rcp
->rscarray
[j
]->c_name
,
782 fprintf(fp
, "\t.short\t%d\n",
783 (rcp
->rscarray
[j
]->binres
->size
- rcp
->rscarray
[j
]->binres
->dataidx
+ alignment
- 1) >> alignment_pwr
);
785 fprintf(fp
, "\t.short\t0x%04x\n", (WORD
)rcp
->rscarray
[j
]->memopt
);
787 if(rcp
->rscarray
[j
]->name
->type
== name_ord
)
788 fprintf(fp
, "\t.short\t0x%04x\n", rcp
->rscarray
[j
]->name
->name
.i_name
| 0x8000);
790 fprintf(fp
, "\t.short\t%s%s_name - %s%s\n",
792 rcp
->rscarray
[j
]->c_name
,
795 /* Handle and Usage */
796 fprintf(fp
, "\t.short\t0, 0\n");
800 fprintf(fp
, "\t.short\t0\n");
804 *****************************************************************************
805 * Function : write_rsc_names
806 * Syntax : void write_rsc_names(FILE *fp)
811 *****************************************************************************
813 static void write_rsc_names(FILE *fp
)
819 /* Write the names */
821 for(i
= 0; i
< rccount
; i
++)
827 if(rcp
->type
.type
== name_str
)
829 char *name
= prep_nid_for_label(&(rcp
->type
));
830 fprintf(fp
, "%s_%s_typename:\n",
833 write_name_str(fp
, &(rcp
->type
));
836 for(j
= 0; j
< rcp
->count32
; j
++)
838 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
840 if(rsc
->name
->type
== name_str
)
842 fprintf(fp
, "%s%s_name:\n",
845 write_name_str(fp
, rsc
->name
);
853 for(i
= 0; i
< rccount
; i
++)
855 res_count_t
*rcp
= &rcarray
[i
];
857 if(rcp
->type
.type
== name_str
)
859 fprintf(fp
, "%s_%s_typename:\n",
861 rcp
->type
.name
.s_name
->str
.cstr
);
862 write_name_str(fp
, &(rcp
->type
));
864 for(j
= 0; j
< rcp
->count
; j
++)
866 if(rcp
->rscarray
[j
]->name
->type
== name_str
)
868 fprintf(fp
, "%s%s_name:\n",
870 rcp
->rscarray
[j
]->c_name
);
871 write_name_str(fp
, rcp
->rscarray
[j
]->name
);
877 /* This is to end the NE resource table */
879 fprintf(fp
, "\t.byte\t0\n");
886 *****************************************************************************
887 * Function : write_s_file
888 * Syntax : void write_s_file(char *outname, resource_t *top)
890 * outname - Filename to write to
891 * top - The resource-tree to convert
895 *****************************************************************************
897 void write_s_file(char *outname
, resource_t
*top
)
902 fo
= fopen(outname
, "wt");
905 error("Could not open %s\n", outname
);
914 fprintf(fo
, s_file_head_str
, input_name
? input_name
: "stdin",
918 /* Get an idea how many we have and restructure the tables */
919 count_resources(top
);
921 /* First write the segment tables */
925 write_pe_segment(fo
);
927 write_ne_segment(fo
);
934 fprintf(fo
, ".LResTabEnd:\n");
938 /* Write the resource data */
939 fprintf(fo
, "\n/* Resource binary data */\n\n");
940 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
945 fprintf(fo
, "\t.align\t%d\n", win32
? 4 : alignment
);
946 fprintf(fo
, "%s%s_data:\n", prefix
, rsc
->c_name
);
948 fprintf(fo
, "\t.globl\t%s%s_data\n", prefix
, rsc
->c_name
);
950 write_s_res(fo
, rsc
->binres
);
957 /* Add a resource descriptor for built-in and elf-dlls */
958 fprintf(fo
, "\t.align\t4\n");
959 fprintf(fo
, "%s_ResourceDescriptor:\n", prefix
);
960 fprintf(fo
, "\t.globl\t%s_ResourceDescriptor\n", prefix
);
961 fprintf(fo
, "%s_ResourceTable:\n", prefix
);
963 fprintf(fo
, "\t.globl\t%s_ResourceTable\n", prefix
);
964 fprintf(fo
, "\t.long\t%s%s\n", prefix
, win32
? _PEResTab
: _NEResTab
);
965 fprintf(fo
, "%s_NumberOfResources:\n", prefix
);
967 fprintf(fo
, "\t.globl\t%s_NumberOfResources\n", prefix
);
968 fprintf(fo
, "\t.long\t%d\n", direntries
);
969 fprintf(fo
, "%s_ResourceSectionSize:\n", prefix
);
971 fprintf(fo
, "\t.globl\t%s_ResourceSectionSize\n", prefix
);
972 fprintf(fo
, "\t.long\t.LResTabEnd - %s%s\n", prefix
, win32
? _PEResTab
: _NEResTab
);
975 fprintf(fo
, "%s_ResourcesEntries:\n", prefix
);
977 fprintf(fo
, "\t.globl\t%s_ResourcesEntries\n", prefix
);
978 fprintf(fo
, "\t.long\t%s_ResourceDirectory\n", prefix
);
985 /* Write the indirection structures */
986 fprintf(fo
, "\n/* Resource indirection structures */\n\n");
987 fprintf(fo
, "\t.align\t4\n");
988 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
991 char *type_name
= NULL
;
1002 type
= WRC_RT_DIALOG
;
1005 assert(rsc
->res
.usr
->type
!= NULL
);
1006 type_name
= prep_nid_for_label(rsc
->res
.usr
->type
);
1014 * This follows a structure like:
1015 * struct wrc_resource {
1019 * RSCNAME *typename;
1023 * The 'RSCNAME' is a pascal-style string where the
1024 * first byte/word denotes the size and the rest the string
1027 fprintf(fo
, "%s%s:\n", prefix
, rsc
->c_name
);
1029 fprintf(fo
, "\t.globl\t%s%s\n", prefix
, rsc
->c_name
);
1030 fprintf(fo
, "\t.long\t%d, %s%s%s, %d, %s%s%s%s, %s%s_data, %d\n",
1031 rsc
->name
->type
== name_ord
? rsc
->name
->name
.i_name
: 0,
1032 rsc
->name
->type
== name_ord
? "0" : prefix
,
1033 rsc
->name
->type
== name_ord
? "" : rsc
->c_name
,
1034 rsc
->name
->type
== name_ord
? "" : "_name",
1036 type
? "0" : prefix
,
1038 type
? "" : type_name
,
1039 type
? "" : "_typename",
1042 rsc
->binres
->size
- rsc
->binres
->dataidx
);
1047 /* Write the indirection table */
1048 fprintf(fo
, "/* Resource indirection table */\n\n");
1049 fprintf(fo
, "\t.align\t4\n");
1050 fprintf(fo
, "%s%s:\n", prefix
, _ResTable
);
1051 fprintf(fo
, "\t.globl\t%s%s\n", prefix
, _ResTable
);
1052 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
1054 fprintf(fo
, "\t.long\t%s%s\n", prefix
, rsc
->c_name
);
1056 fprintf(fo
, "\t.long\t0\n");
1061 fprintf(fo
, s_file_autoreg_str
, prefix
, _ResTable
);
1063 fprintf(fo
, s_file_tail_str
);
1068 *****************************************************************************
1069 * Function : write_h_file
1070 * Syntax : void write_h_file(char *outname, resource_t *top)
1072 * outname - Filename to write to
1073 * top - The resource-tree to convert
1077 *****************************************************************************
1079 void write_h_file(char *outname
, resource_t
*top
)
1085 #ifdef NEED_UNDERSCORE_PREFIX
1086 h_prefix
= prefix
+ 1;
1091 fo
= fopen(outname
, "wt");
1094 error("Could not open %s\n", outname
);
1097 fprintf(fo
, h_file_head_str
, input_name
? input_name
: "stdin",
1098 cmdline
, ctime(&now
), (long)now
, (long)now
);
1100 /* First write the segment tables reference */
1103 fprintf(fo
, "extern %schar %s%s[];\n\n",
1104 constant
? "const " : "",
1106 win32
? _PEResTab
: _NEResTab
);
1109 /* Write the resource data */
1110 for(rsc
= top
; global
&& rsc
; rsc
= rsc
->next
)
1115 fprintf(fo
, "extern %schar %s%s_data[];\n",
1116 constant
? "const " : "",
1126 /* Write the indirection structures */
1127 for(rsc
= top
; global
&& rsc
; rsc
= rsc
->next
)
1129 fprintf(fo
, "extern %swrc_resource%d_t %s%s;\n",
1130 constant
? "const " : "",
1139 /* Write the indirection table */
1140 fprintf(fo
, "extern %swrc_resource%d_t %s%s[];\n\n",
1141 constant
? "const " : "",
1147 fprintf(fo
, h_file_tail_str
);