2 * Write .res, .s and .h file(s) from a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
21 #ifdef NEED_UNDERSCORE_PREFIX
22 char Underscore
[] = "_";
24 char Underscore
[] = "";
27 static char s_file_head_str
[] =
28 "/* This file is generated with wrc version " WRC_FULLVERSION
". Do not edit! */\n"
37 static char s_file_tail_str
[] =
42 static char s_file_autoreg_str
[] =
46 #ifdef NEED_UNDERSCORE_PREFIX
47 "\tcall\t_LIBRES_RegisterResources\n"
49 "\tcall\tLIBRES_RegisterResources\n"
54 ".stabs \"___CTOR_LIST__\",22,0,0,.LAuto_Register\n\n"
56 "\t.section .ctors,\"aw\"\n"
57 "\t.long\t.LAuto_Register\n\n"
61 static char h_file_head_str
[] =
63 " * This file is generated with wrc version " WRC_FULLVERSION
". Do not edit!\n"
69 "#ifndef __%08lx_H\n" /* This becomes the date of compile */
72 "#include <wrc_rsc.h>\n"
76 static char h_file_tail_str
[] =
81 char _NEResTab
[] = "_NEResTab";
82 char _PEResTab
[] = "_PEResTab";
83 char _ResTable
[] = "_ResTable";
85 /* Variables used for resource sorting */
86 res_count_t
*rcarray
= NULL
; /* Type-level count array */
87 int rccount
= 0; /* Nr of entries in the type-level array */
88 int n_id_entries
= 0; /* win32 only: Nr of unique ids in the type-level array */
89 int n_name_entries
= 0; /* win32 only: Nr of unique namess in the type-level array */
91 static int direntries
; /* win32 only: Total number of unique resources */
94 *****************************************************************************
95 * Function : write_resfile
96 * Syntax : void write_resfile(char *outname, resource_t *top)
98 * outname - Filename to write to
99 * top - The resource-tree to convert
103 *****************************************************************************
105 void write_resfile(char *outname
, resource_t
*top
)
109 char zeros
[3] = {0, 0, 0};
111 fo
= fopen(outname
, "wb");
114 error("Could not open %s\n", outname
);
119 /* Put an empty resource first to signal win32 format */
120 res_t
*res
= new_res();
121 put_dword(res
, 0); /* ResSize */
122 put_dword(res
, 0x00000020); /* HeaderSize */
123 put_word(res
, 0xffff); /* ResType */
125 put_word(res
, 0xffff); /* ResName */
127 put_dword(res
, 0); /* DataVersion */
128 put_word(res
, 0); /* Memory options */
129 put_word(res
, 0); /* Language */
130 put_dword(res
, 0); /* Version */
131 put_dword(res
, 0); /* Charateristics */
132 ret
= fwrite(res
->data
, 1, res
->size
, fo
);
136 error("Error writing %s", outname
);
141 for(; top
; top
= top
->next
)
146 ret
= fwrite(top
->binres
->data
, 1, top
->binres
->size
, fo
);
147 if(ret
!= top
->binres
->size
)
150 error("Error writing %s", outname
);
152 if(win32
&& (top
->binres
->size
& 0x03))
155 ret
= fwrite(zeros
, 1, 4 - (top
->binres
->size
& 0x03), fo
);
156 if(ret
!= 4 - (top
->binres
->size
& 0x03))
159 error("Error writing %s", outname
);
167 *****************************************************************************
168 * Function : write_s_res
169 * Syntax : void write_s_res(FILE *fp, res_t *res)
174 *****************************************************************************
176 #define BYTESPERLINE 8
177 static void write_s_res(FILE *fp
, res_t
*res
)
179 int idx
= res
->dataidx
;
181 int rest
= (end
- idx
) % BYTESPERLINE
;
182 int lines
= (end
- idx
) / BYTESPERLINE
;
185 for(i
= 0 ; i
< lines
; i
++)
187 fprintf(fp
, "\t.byte\t");
188 for(j
= 0; j
< BYTESPERLINE
; j
++, idx
++)
190 fprintf(fp
, "0x%02x%s", res
->data
[idx
] & 0xff,
191 j
== BYTESPERLINE
-1 ? "" : ", ");
197 fprintf(fp
, "\t.byte\t");
198 for(j
= 0; j
< rest
; j
++, idx
++)
200 fprintf(fp
, "0x%02x%s", res
->data
[idx
] & 0xff,
201 j
== rest
-1 ? "" : ", ");
209 *****************************************************************************
210 * Function : write_name_str
211 * Syntax : void write_name_str(FILE *fp, name_id_t *nid)
215 * Remarks : One level self recursive for string type conversion
216 *****************************************************************************
218 static void write_name_str(FILE *fp
, name_id_t
*nid
)
221 assert(nid
->type
== name_str
);
223 if(!win32
&& nid
->name
.s_name
->type
== str_char
)
225 res
.size
= strlen(nid
->name
.s_name
->str
.cstr
);
227 error("Can't write strings larger than 254 bytes");
229 internal_error(__FILE__
, __LINE__
, "Attempt to write empty string");
231 res
.data
= (char *)xmalloc(res
.size
+ 1);
232 res
.data
[0] = (char)res
.size
;
233 res
.size
++; /* We need to write the length byte as well */
234 strcpy(res
.data
+1, nid
->name
.s_name
->str
.cstr
);
235 write_s_res(fp
, &res
);
238 else if(!win32
&& nid
->name
.s_name
->type
== str_unicode
)
243 lnid
.type
= name_str
;
244 lnid
.name
.s_name
= &str
;
246 str
.str
.cstr
= dupwstr2cstr(nid
->name
.s_name
->str
.wstr
);
247 write_name_str(fp
, &lnid
);
250 else if(win32
&& nid
->name
.s_name
->type
== str_char
)
255 lnid
.type
= name_str
;
256 lnid
.name
.s_name
= &str
;
257 str
.type
= str_unicode
;
258 str
.str
.wstr
= dupcstr2wstr(nid
->name
.s_name
->str
.cstr
);
259 write_name_str(fp
, &lnid
);
262 else if(win32
&& nid
->name
.s_name
->type
== str_unicode
)
264 res
.size
= wstrlen(nid
->name
.s_name
->str
.wstr
);
266 error("Can't write strings larger than 65534 bytes");
268 internal_error(__FILE__
, __LINE__
, "Attempt to write empty string");
270 res
.data
= (char *)xmalloc((res
.size
+ 1) * 2);
271 ((short *)res
.data
)[0] = (short)res
.size
;
272 wstrcpy((short *)(res
.data
+2), nid
->name
.s_name
->str
.wstr
);
273 res
.size
*= 2; /* Function writes bytes, not shorts... */
274 res
.size
+= 2; /* We need to write the length word as well */
275 write_s_res(fp
, &res
);
280 internal_error(__FILE__
, __LINE__
, "Hmm, requested to write a string of unknown type %d",
281 nid
->name
.s_name
->type
);
286 *****************************************************************************
287 * Function : find_counter
288 * Syntax : res_count_t *find_counter(name_id_t *type)
293 *****************************************************************************
295 static res_count_t
*find_counter(name_id_t
*type
)
298 for(i
= 0; i
< rccount
; i
++)
300 if(!compare_name_id(type
, &(rcarray
[i
].type
)))
307 *****************************************************************************
308 * Function : count_resources
309 * Syntax : res_count_t *count_resources(resource_t *top)
313 * Remarks : The whole lot is converted into arrays because they are
314 * easy sortable. Makes the lot almost unreadable, but it
315 * works (I hope). Basically you have to keep in mind that
316 * the lot is a three-dimensional structure for win32 and a
317 * two-dimensional structure for win16.
318 *****************************************************************************
320 #define RCT(v) (*((resource_t **)(v)))
321 /* qsort sorting function */
322 static int sort_name_id(const void *e1
, const void *e2
)
324 return compare_name_id(RCT(e1
)->name
, RCT(e2
)->name
);
327 static int sort_language(const void *e1
, const void *e2
)
329 assert((RCT(e1
)->lan
) != NULL
);
330 assert((RCT(e2
)->lan
) != NULL
);
332 return MAKELANGID(RCT(e1
)->lan
->id
, RCT(e1
)->lan
->sub
)
333 - MAKELANGID(RCT(e2
)->lan
->id
, RCT(e2
)->lan
->sub
);
336 #define RCT(v) ((res_count_t *)(v))
337 static int sort_type(const void *e1
, const void *e2
)
339 return compare_name_id(&(RCT(e1
)->type
), &(RCT(e2
)->type
));
343 static void count_resources(resource_t
*top
)
350 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
357 nid
.name
.i_name
= WRC_RT_DIALOG
;
361 nid
.name
.i_name
= WRC_RT_MENU
;
365 nid
= *(rsc
->res
.usr
->type
);
368 nid
.name
.i_name
= rsc
->type
;
372 if((rcp
= find_counter(&nid
)) == NULL
)
374 /* Count the number of uniq ids and names */
376 if(nid
.type
== name_ord
)
383 rcarray
= (res_count_t
*)xmalloc(sizeof(res_count_t
));
385 rcarray
[0].count
= 1;
386 rcarray
[0].type
= nid
;
387 rcarray
[0].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
388 rcarray
[0].rscarray
[0] = rsc
;
393 rcarray
= (res_count_t
*)xrealloc(rcarray
, rccount
* sizeof(res_count_t
));
394 rcarray
[rccount
-1].count
= 1;
395 rcarray
[rccount
-1].type
= nid
;
396 rcarray
[rccount
-1].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
397 rcarray
[rccount
-1].rscarray
[0] = rsc
;
403 rcp
->rscarray
= (resource_t
**)xrealloc(rcp
->rscarray
, rcp
->count
* sizeof(resource_t
*));
404 rcp
->rscarray
[rcp
->count
-1] = rsc
;
410 /* We're done, win16 requires no special sorting */
414 /* We now have a unsorted list of types with an array of res_count_t
415 * in rcarray[0..rccount-1]. And we have names of one type in the
416 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
417 * The list needs to be sorted for win32's top level tree structure.
422 qsort(rcarray
, rccount
, sizeof(rcarray
[0]), sort_type
);
424 /* Now sort the name-id arrays */
425 for(i
= 0; i
< rccount
; i
++)
427 if(rcarray
[i
].count
> 1)
428 qsort(rcarray
[i
].rscarray
, rcarray
[i
].count
, sizeof(rcarray
[0].rscarray
[0]), sort_name_id
);
431 /* Now split the name-id arrays into name/language
432 * subs. Don't look at the awfull expressions...
433 * We do this by taking the array elements out of rscarray and putting
434 * together a new array in rsc32array.
436 for(i
= 0; i
< rccount
; i
++)
440 assert(rcarray
[i
].count
>= 1);
442 /* rcap points to the current type we are dealing with */
443 rcap
= &(rcarray
[i
]);
445 /* Insert the first name-id */
446 rcap
->rsc32array
= (res32_count_t
*)xmalloc(sizeof(res32_count_t
));
448 rcap
->rsc32array
[0].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
449 rcap
->rsc32array
[0].count
= 1;
450 rcap
->rsc32array
[0].rsc
[0] = rcap
->rscarray
[0];
451 if(rcap
->rscarray
[0]->name
->type
== name_ord
)
453 rcap
->n_id_entries
= 1;
454 rcap
->n_name_entries
= 0;
458 rcap
->n_id_entries
= 0;
459 rcap
->n_name_entries
= 1;
462 /* Now loop over the resting resources of the current type
463 * to find duplicate names (which should have different
466 for(j
= 1; j
< rcap
->count
; j
++)
468 res32_count_t
*r32cp
;
470 /* r32cp points to the current res32_count structure
471 * that holds the resource name we are processing.
473 r32cp
= &(rcap
->rsc32array
[rcap
->count32
-1]);
475 if(!compare_name_id(r32cp
->rsc
[0]->name
, rcarray
[i
].rscarray
[j
]->name
))
477 /* Names are the same, add to list */
479 r32cp
->rsc
= (resource_t
**)xrealloc(r32cp
->rsc
, r32cp
->count
* sizeof(resource_t
*));
480 r32cp
->rsc
[r32cp
->count
-1] = rcap
->rscarray
[j
];
484 /* New name-id, sort the old one by
485 * language and create new list
488 qsort(r32cp
->rsc
, r32cp
->count
, sizeof(r32cp
->rsc
[0]), sort_language
);
490 rcap
->rsc32array
= (res32_count_t
*)xrealloc(rcap
->rsc32array
, rcap
->count32
* sizeof(res32_count_t
));
491 rcap
->rsc32array
[rcap
->count32
-1].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
492 rcap
->rsc32array
[rcap
->count32
-1].count
= 1;
493 rcap
->rsc32array
[rcap
->count32
-1].rsc
[0] = rcap
->rscarray
[j
];
495 if(rcap
->rscarray
[j
]->name
->type
== name_ord
)
496 rcap
->n_id_entries
++;
498 rcap
->n_name_entries
++;
501 /* Also sort the languages of the last name group */
502 if(rcap
->rsc32array
[rcap
->count32
-1].count
> 1)
503 qsort(rcap
->rsc32array
[rcap
->count32
-1].rsc
,
504 rcap
->rsc32array
[rcap
->count32
-1].count
,
505 sizeof(rcap
->rsc32array
[rcap
->count32
-1].rsc
[0]),
511 *****************************************************************************
512 * Function : write_pe_segment
513 * Syntax : void write_pe_segment(FILE *fp, resource_t *top)
518 *****************************************************************************
520 static void write_pe_segment(FILE *fp
, resource_t
*top
)
524 fprintf(fp
, "\t.align\t4\n");
525 fprintf(fp
, "%s%s:\n", prefix
, _PEResTab
);
526 fprintf(fp
, "\t.globl\t%s%s\n", prefix
, _PEResTab
);
528 fprintf(fp
, "\t.long\t0\n");
529 /* Time/Date stamp */
530 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
);
532 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
533 /* # of id entries, # of name entries */
534 fprintf(fp
, "\t.short\t%d, %d\n", n_name_entries
, n_id_entries
);
536 /* Write the type level of the tree */
537 for(i
= 0; i
< rccount
; i
++)
545 if(rcp
->type
.type
== name_ord
)
546 fprintf(fp
, "\t.long\t%d\n", rcp
->type
.name
.i_name
);
549 char *name
= prep_nid_for_label(&(rcp
->type
));
550 fprintf(fp
, "\t.long\t(%s_%s_typename - %s%s) | 0x80000000\n",
557 label
= prep_nid_for_label(&(rcp
->type
));
558 fprintf(fp
, "\t.long\t(.L%s - %s%s) | 0x80000000\n",
564 /* Write the name level of the tree */
566 for(i
= 0; i
< rccount
; i
++)
575 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
576 fprintf(fp
, ".L%s:\n", typelabel
);
578 fprintf(fp
, "\t.long\t0\n"); /* Flags */
579 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
); /* TimeDate */
580 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
581 fprintf(fp
, "\t.short\t%d, %d\n", rcp
->n_name_entries
, rcp
->n_id_entries
);
582 for(j
= 0; j
< rcp
->count32
; j
++)
584 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
586 if(rsc
->name
->type
== name_ord
)
587 fprintf(fp
, "\t.long\t%d\n", rsc
->name
->name
.i_name
);
590 fprintf(fp
, "\t.long\t(%s%s_name - %s%s) | 0x80000000\n",
596 /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
597 * put the offset to the resource data entry.
598 * ?? Is unescaping worth while ??
601 namelabel
= prep_nid_for_label(rsc
->name
);
602 fprintf(fp
, "\t.long\t(.L%s_%s - %s%s) | 0x80000000\n",
611 /* Write the language level of the tree */
613 for(i
= 0; i
< rccount
; i
++)
621 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
623 for(j
= 0; j
< rcp
->count32
; j
++)
625 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
628 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
629 fprintf(fp
, ".L%s_%s:\n", typelabel
, namelabel
);
631 fprintf(fp
, "\t.long\t0\n"); /* Flags */
632 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
); /* TimeDate */
633 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
634 fprintf(fp
, "\t.short\t0, %d\n", r32cp
->count
);
636 for(k
= 0; k
< r32cp
->count
; k
++)
638 resource_t
*rsc
= r32cp
->rsc
[k
];
639 assert(rsc
->lan
!= NULL
);
641 fprintf(fp
, "\t.long\t0x%08x\n", rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
643 fprintf(fp
, "\t.long\t.L%s_%s_%d - %s%s\n",
646 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0,
655 /* Write the resource table itself */
656 fprintf(fp
, "%s_ResourceDirectory:\n", prefix
);
657 fprintf(fp
, "\t.globl\t%s_ResourceDirectory\n", prefix
);
660 for(i
= 0; i
< rccount
; i
++)
668 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
670 for(j
= 0; j
< rcp
->count32
; j
++)
672 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
675 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
677 for(k
= 0; k
< r32cp
->count
; k
++)
679 resource_t
*rsc
= r32cp
->rsc
[k
];
681 assert(rsc
->lan
!= NULL
);
683 fprintf(fp
, ".L%s_%s_%d:\n",
686 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
689 fprintf(fp
, "\t.long\t%s%s_data - %s%s\n",
695 fprintf(fp
, "\t.long\t%d\n",
696 rsc
->binres
->size
- rsc
->binres
->dataidx
);
698 fprintf(fp
, "\t.long\t%ld\n", codepage
);
700 fprintf(fp
, "\t.long\t0\n");
711 *****************************************************************************
712 * Function : write_ne_segment
713 * Syntax : void write_ne_segment(FILE *fp, resource_t *top)
718 *****************************************************************************
720 static void write_ne_segment(FILE *fp
, resource_t
*top
)
724 fprintf(fp
, "\t.align\t4\n");
725 fprintf(fp
, "%s%s:\n", prefix
, _NEResTab
);
726 fprintf(fp
, "\t.globl\t%s%s\n", prefix
, _NEResTab
);
729 fprintf(fp
, "\t.short\t%d\n", alignment_pwr
);
732 for(i
= 0; i
< rccount
; i
++)
734 res_count_t
*rcp
= &rcarray
[i
];
737 if(rcp
->type
.type
== name_ord
)
738 fprintf(fp
, "\t.short\t0x%04x\n", rcp
->type
.name
.i_name
| 0x8000);
740 fprintf(fp
, "\t.short\t%s_%s_typename - %s%s\n",
742 rcp
->type
.name
.s_name
->str
.cstr
,
746 fprintf(fp
, "\t.short\t%d\n", rcp
->count
);
748 fprintf(fp
, "\t.long\t0\n");
750 for(j
= 0; j
< rcp
->count
; j
++)
754 * The offset is relative to the beginning of the NE resource segment
755 * and _NOT_ to the file-beginning. This is because we do not have a
756 * file based resource, but a simulated NE segment. The offset _is_
757 * scaled by the AlignShift field.
758 * All other things are as the MS doc describes (alignment etc.)
761 fprintf(fp
, "\t.short\t(%s%s_data - %s%s) >> %d\n",
763 rcp
->rscarray
[j
]->c_name
,
768 fprintf(fp
, "\t.short\t%d\n",
769 rcp
->rscarray
[j
]->binres
->size
- rcp
->rscarray
[j
]->binres
->dataidx
);
771 fprintf(fp
, "\t.short\t0x%04x\n", (WORD
)rcp
->rscarray
[j
]->memopt
);
773 if(rcp
->rscarray
[j
]->name
->type
== name_ord
)
774 fprintf(fp
, "\t.short\t0x%04x\n", rcp
->rscarray
[j
]->name
->name
.i_name
| 0x8000);
776 fprintf(fp
, "\t.short\t%s%s_name - %s%s\n",
778 rcp
->rscarray
[j
]->c_name
,
781 /* Handle and Usage */
782 fprintf(fp
, "\t.short\t0, 0\n");
786 fprintf(fp
, "\t.short\t0\n");
790 *****************************************************************************
791 * Function : write_rsc_names
792 * Syntax : void write_rsc_names(FILE *fp, resource_t *top)
797 *****************************************************************************
799 static void write_rsc_names(FILE *fp
, resource_t
*top
)
805 /* Write the names */
807 for(i
= 0; i
< rccount
; i
++)
813 if(rcp
->type
.type
== name_str
)
815 char *name
= prep_nid_for_label(&(rcp
->type
));
816 fprintf(fp
, "%s_%s_typename:\n",
819 write_name_str(fp
, &(rcp
->type
));
822 for(j
= 0; j
< rcp
->count32
; j
++)
824 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
826 if(rsc
->name
->type
== name_str
)
828 fprintf(fp
, "%s%s_name:\n",
831 write_name_str(fp
, rsc
->name
);
839 for(i
= 0; i
< rccount
; i
++)
841 res_count_t
*rcp
= &rcarray
[i
];
843 for(j
= 0; j
< rcp
->count
; j
++)
845 if(rcp
->type
.type
== name_str
)
847 fprintf(fp
, "%s_%s_typename:\n",
849 rcp
->type
.name
.s_name
->str
.cstr
);
850 write_name_str(fp
, &(rcp
->type
));
852 if(rcp
->rscarray
[j
]->name
->type
== name_str
)
854 fprintf(fp
, "%s%s_name:\n",
856 rcp
->rscarray
[j
]->c_name
);
857 write_name_str(fp
, rcp
->rscarray
[j
]->name
);
863 /* This is to end the NE resource table */
865 fprintf(fp
, "\t.byte\t0\n");
872 *****************************************************************************
873 * Function : write_s_file
874 * Syntax : void write_s_file(char *outname, resource_t *top)
876 * outname - Filename to write to
877 * top - The resource-tree to convert
881 *****************************************************************************
883 void write_s_file(char *outname
, resource_t
*top
)
888 fo
= fopen(outname
, "wt");
891 error("Could not open %s\n", outname
);
900 fprintf(fo
, s_file_head_str
, input_name
? input_name
: "stdin",
904 /* Get an idea how many we have and restructure the tables */
905 count_resources(top
);
907 /* First write the segment tables */
911 write_pe_segment(fo
, top
);
913 write_ne_segment(fo
, top
);
917 write_rsc_names(fo
, top
);
920 fprintf(fo
, ".LResTabEnd:\n");
924 /* Write the resource data */
925 fprintf(fo
, "\n/* Resource binary data */\n\n");
926 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
931 fprintf(fo
, "\t.align\t%d\n", win32
? 4 : alignment
);
932 fprintf(fo
, "%s%s_data:\n", prefix
, rsc
->c_name
);
934 fprintf(fo
, "\t.globl\t%s%s_data\n", prefix
, rsc
->c_name
);
936 write_s_res(fo
, rsc
->binres
);
943 /* Add a resource descriptor for built-in and elf-dlls */
944 fprintf(fo
, "\t.align\t4\n");
945 fprintf(fo
, "%s_ResourceDescriptor:\n", prefix
);
946 fprintf(fo
, "\t.globl\t%s_ResourceDescriptor\n", prefix
);
947 fprintf(fo
, "%s_ResourceTable:\n", prefix
);
949 fprintf(fo
, "\t.globl\t%s_ResourceTable\n", prefix
);
950 fprintf(fo
, "\t.long\t%s%s\n", prefix
, win32
? _PEResTab
: _NEResTab
);
951 fprintf(fo
, "%s_NumberOfResources:\n", prefix
);
953 fprintf(fo
, "\t.globl\t%s_NumberOfResources\n", prefix
);
954 fprintf(fo
, "\t.long\t%d\n", direntries
);
955 fprintf(fo
, "%s_ResourceSectionSize:\n", prefix
);
957 fprintf(fo
, "\t.globl\t%s_ResourceSectionSize\n", prefix
);
958 fprintf(fo
, "\t.long\t.LResTabEnd - %s%s\n", prefix
, win32
? _PEResTab
: _NEResTab
);
961 fprintf(fo
, "%s_ResourcesEntries:\n", prefix
);
963 fprintf(fo
, "\t.globl\t%s_ResourcesEntries\n", prefix
);
964 fprintf(fo
, "\t.long\t%s_ResourceDirectory\n", prefix
);
971 /* Write the indirection structures */
972 fprintf(fo
, "\n/* Resource indirection structures */\n\n");
973 fprintf(fo
, "\t.align\t4\n");
974 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
977 char *type_name
= NULL
;
988 type
= WRC_RT_DIALOG
;
991 assert(rsc
->res
.usr
->type
!= NULL
);
992 type_name
= prep_nid_for_label(rsc
->res
.usr
->type
);
1000 * This follows a structure like:
1001 * struct wrc_resource {
1005 * RSCNAME *typename;
1009 * The 'RSCNAME' is a pascal-style string where the
1010 * first byte/word denotes the size and the rest the string
1013 fprintf(fo
, "%s%s:\n", prefix
, rsc
->c_name
);
1015 fprintf(fo
, "\t.globl\t%s%s\n", prefix
, rsc
->c_name
);
1016 fprintf(fo
, "\t.long\t%d, %s%s%s, %d, %s%s%s%s, %s%s_data, %d\n",
1017 rsc
->name
->type
== name_ord
? rsc
->name
->name
.i_name
: 0,
1018 rsc
->name
->type
== name_ord
? "0" : prefix
,
1019 rsc
->name
->type
== name_ord
? "" : rsc
->c_name
,
1020 rsc
->name
->type
== name_ord
? "" : "_name",
1022 type
? "0" : prefix
,
1024 type
? "" : type_name
,
1025 type
? "" : "_typename",
1028 rsc
->binres
->size
- rsc
->binres
->dataidx
);
1033 /* Write the indirection table */
1034 fprintf(fo
, "/* Resource indirection table */\n\n");
1035 fprintf(fo
, "\t.align\t4\n");
1036 fprintf(fo
, "%s%s:\n", prefix
, _ResTable
);
1037 fprintf(fo
, "\t.globl\t%s%s\n", prefix
, _ResTable
);
1038 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
1040 fprintf(fo
, "\t.long\t%s%s\n", prefix
, rsc
->c_name
);
1042 fprintf(fo
, "\t.long\t0\n");
1047 fprintf(fo
, s_file_autoreg_str
, prefix
, _ResTable
);
1049 fprintf(fo
, s_file_tail_str
);
1054 *****************************************************************************
1055 * Function : write_h_file
1056 * Syntax : void write_h_file(char *outname, resource_t *top)
1058 * outname - Filename to write to
1059 * top - The resource-tree to convert
1063 *****************************************************************************
1065 void write_h_file(char *outname
, resource_t
*top
)
1071 #ifdef NEED_UNDERSCORE_PREFIX
1072 h_prefix
= prefix
+ 1;
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
);