2 * Write .res, .s and .h file(s) from a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
21 char s_file_head_str
[] =
23 "# This file is generated with wrc version " WRC_FULLVERSION
". Do not edit!\n"
31 char s_file_tail_str
[] =
35 char s_file_autoreg_str
[] =
39 #ifdef NEED_UNDERSCORE_PREFIX
40 "\tcall\t_LIBRES_RegisterResources\n"
42 "\tcall\tLIBRES_RegisterResources\n"
46 "\t.section .ctors,\"aw\"\n"
47 "\t.long\t.LAuto_Register\n\n"
50 char h_file_head_str
[] =
52 " * This file is generated with wrc version " WRC_FULLVERSION
". Do not edit!\n"
57 "#ifndef __%08x_H\n" /* This becomes the data of compile */
58 "#define __%08x_H\n\n"
59 "#ifndef __WRC_RSC_H\n"
60 "#include <wrc_rsc.h>\n"
64 char h_file_tail_str
[] =
69 char _NEResTab
[] = "_NEResTab";
70 char _PEResTab
[] = "_PEResTab";
71 char _ResTable
[] = "_ResTable";
73 res_count_t
*rcarray
= NULL
;
76 int n_name_entries
= 0;
81 *****************************************************************************
82 * Function : write_resfile
83 * Syntax : void write_resfile(char *outname, resource_t *top)
85 * outname - Filename to write to
86 * top - The resource-tree to convert
90 *****************************************************************************
92 void write_resfile(char *outname
, resource_t
*top
)
96 char zeros
[3] = {0, 0, 0};
98 fo
= fopen(outname
, "wb");
101 error("Could not open %s\n", outname
);
106 /* Put an empty resource first to signal win32 format */
107 res_t
*res
= new_res();
108 put_dword(res
, 0); /* ResSize */
109 put_dword(res
, 0x00000020); /* HeaderSize */
110 put_word(res
, 0xffff); /* ResType */
112 put_word(res
, 0xffff); /* ResName */
114 put_dword(res
, 0); /* DataVersion */
115 put_word(res
, 0); /* Memory options */
116 put_word(res
, 0); /* Language */
117 put_dword(res
, 0); /* Version */
118 put_dword(res
, 0); /* Charateristics */
119 ret
= fwrite(res
->data
, 1, res
->size
, fo
);
123 error("Error writing %s", outname
);
128 for(; top
; top
= top
->next
)
133 ret
= fwrite(top
->binres
->data
, 1, top
->binres
->size
, fo
);
134 if(ret
!= top
->binres
->size
)
137 error("Error writing %s", outname
);
139 if(win32
&& (top
->binres
->size
& 0x03))
142 ret
= fwrite(zeros
, 1, 4 - (top
->binres
->size
& 0x03), fo
);
143 if(ret
!= 4 - (top
->binres
->size
& 0x03))
146 error("Error writing %s", outname
);
154 *****************************************************************************
155 * Function : write_s_res
156 * Syntax : void write_s_res(FILE *fp, res_t *res)
161 *****************************************************************************
163 #define BYTESPERLINE 8
164 void write_s_res(FILE *fp
, res_t
*res
)
166 int idx
= res
->dataidx
;
168 int rest
= (end
- idx
) % BYTESPERLINE
;
169 int lines
= (end
- idx
) / BYTESPERLINE
;
172 for(i
= 0 ; i
< lines
; i
++)
174 fprintf(fp
, "\t.byte\t");
175 for(j
= 0; j
< BYTESPERLINE
; j
++, idx
++)
177 fprintf(fp
, "0x%02x%s", res
->data
[idx
] & 0xff,
178 j
== BYTESPERLINE
-1 ? "" : ", ");
184 fprintf(fp
, "\t.byte\t");
185 for(j
= 0; j
< rest
; j
++, idx
++)
187 fprintf(fp
, "0x%02x%s", res
->data
[idx
] & 0xff,
188 j
== rest
-1 ? "" : ", ");
195 *****************************************************************************
196 * Function : write_name_str
197 * Syntax : void write_name_str(FILE *fp, name_id_t *nid)
201 * Remarks : One level self recursive for string type conversion
202 *****************************************************************************
204 void write_name_str(FILE *fp
, name_id_t
*nid
)
207 assert(nid
->type
== name_str
);
209 if(!win32
&& nid
->name
.s_name
->type
== str_char
)
211 res
.size
= strlen(nid
->name
.s_name
->str
.cstr
) + 1;
213 error("Can't write strings larger than 254 bytes");
215 internal_error(__FILE__
, __LINE__
, "Attempt to write empty string");
217 res
.data
= (char *)xmalloc(res
.size
);
218 res
.data
[0] = (char)res
.size
;
219 strcpy(res
.data
+1, nid
->name
.s_name
->str
.cstr
);
220 write_s_res(fp
, &res
);
223 else if(!win32
&& nid
->name
.s_name
->type
== str_unicode
)
228 lnid
.type
= name_str
;
229 lnid
.name
.s_name
= &str
;
231 str
.str
.cstr
= dupwstr2cstr(nid
->name
.s_name
->str
.wstr
);
232 write_name_str(fp
, &lnid
);
235 else if(win32
&& nid
->name
.s_name
->type
== str_char
)
240 lnid
.type
= name_str
;
241 lnid
.name
.s_name
= &str
;
242 str
.type
= str_unicode
;
243 str
.str
.wstr
= dupcstr2wstr(nid
->name
.s_name
->str
.cstr
);
244 write_name_str(fp
, &lnid
);
247 else if(win32
&& nid
->name
.s_name
->type
== str_unicode
)
249 res
.size
= wstrlen(nid
->name
.s_name
->str
.wstr
) + 1;
251 error("Can't write strings larger than 65534 bytes");
253 internal_error(__FILE__
, __LINE__
, "Attempt to write empty string");
255 res
.data
= (char *)xmalloc(res
.size
* 2);
256 ((short *)res
.data
)[0] = (char)res
.size
;
257 wstrcpy((short *)(res
.data
+2), nid
->name
.s_name
->str
.wstr
);
258 res
.size
*= 2; /* Function writes bytes, not shorts... */
259 write_s_res(fp
, &res
);
264 internal_error(__FILE__
, __LINE__
, "Hmm, requested to write a string of unknown type %d",
265 nid
->name
.s_name
->type
);
270 *****************************************************************************
271 * Function : compare_name_id
272 * Syntax : int compare_name_id(name_id_t *n1, name_id_t *n2)
277 *****************************************************************************
279 int compare_name_id(name_id_t
*n1
, name_id_t
*n2
)
281 if(n1
->type
== name_ord
&& n2
->type
== name_ord
)
283 return n1
->name
.i_name
- n2
->name
.i_name
;
285 else if(n1
->type
== name_str
&& n2
->type
== name_str
)
287 if(n1
->name
.s_name
->type
== str_char
288 && n2
->name
.s_name
->type
== str_char
)
290 return stricmp(n1
->name
.s_name
->str
.cstr
, n2
->name
.s_name
->str
.cstr
);
292 else if(n1
->name
.s_name
->type
== str_unicode
293 && n2
->name
.s_name
->type
== str_unicode
)
295 return wstricmp(n1
->name
.s_name
->str
.wstr
, n2
->name
.s_name
->str
.wstr
);
299 internal_error(__FILE__
, __LINE__
, "Can't yet compare strings of mixed type");
302 else if(n1
->type
== name_ord
&& n2
->type
== name_str
)
304 else if(n1
->type
== name_str
&& n2
->type
== name_ord
)
307 internal_error(__FILE__
, __LINE__
, "Comparing name-ids with unknown types (%d, %d)",
310 return 0; /* Keep the compiler happy */
314 *****************************************************************************
315 * Function : find_counter
316 * Syntax : res_count_t *find_counter(name_id_t *type)
321 *****************************************************************************
323 res_count_t
*find_counter(name_id_t
*type
)
326 for(i
= 0; i
< rccount
; i
++)
328 if(!compare_name_id(type
, &(rcarray
[i
].type
)))
335 *****************************************************************************
336 * Function : count_resources
337 * Syntax : res_count_t *count_resources(resource_t *top)
341 * Remarks : The whole lot is converted into arrays because they are
342 * easy sortable. Makes the lot almost unreadable, but it
343 * works (I hope). Basically you have to keep in mind that
344 * the lot is a three-dimensional structure for win32 and a
345 * two-dimensional structure for win16.
346 *****************************************************************************
348 #define RCT(v) (*((resource_t **)(v)))
349 /* qsort sorting function */
350 int sort_name_id(const void *e1
, const void *e2
)
352 return compare_name_id(RCT(e1
)->name
, RCT(e2
)->name
);
355 int sort_language(const void *e1
, const void *e2
)
357 assert((RCT(e1
)->lan
) != NULL
);
358 assert((RCT(e2
)->lan
) != NULL
);
360 return MAKELANGID(RCT(e1
)->lan
->id
, RCT(e1
)->lan
->sub
)
361 - MAKELANGID(RCT(e2
)->lan
->id
, RCT(e2
)->lan
->sub
);
364 #define RCT(v) ((res_count_t *)(v))
365 int sort_type(const void *e1
, const void *e2
)
367 return compare_name_id(&(RCT(e1
)->type
), &(RCT(e2
)->type
));
371 void count_resources(resource_t
*top
)
378 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
385 nid
.name
.i_name
= WRC_RT_DIALOG
;
389 nid
.name
.i_name
= WRC_RT_MENU
;
393 nid
= *(rsc
->res
.usr
->type
);
396 nid
.name
.i_name
= rsc
->type
;
400 if((rcp
= find_counter(&nid
)) == NULL
)
402 /* Count the number of uniq ids and names */
404 if(nid
.type
== name_ord
)
411 rcarray
= (res_count_t
*)xmalloc(sizeof(res_count_t
));
413 rcarray
[0].count
= 1;
414 rcarray
[0].type
= nid
;
415 rcarray
[0].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
416 rcarray
[0].rscarray
[0] = rsc
;
421 rcarray
= (res_count_t
*)xrealloc(rcarray
, rccount
* sizeof(res_count_t
));
422 rcarray
[rccount
-1].count
= 1;
423 rcarray
[rccount
-1].type
= nid
;
424 rcarray
[rccount
-1].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
425 rcarray
[rccount
-1].rscarray
[0] = rsc
;
431 rcp
->rscarray
= (resource_t
**)xrealloc(rcp
->rscarray
, rcp
->count
* sizeof(resource_t
*));
432 rcp
->rscarray
[rcp
->count
-1] = rsc
;
438 /* We're done, win16 requires no special sorting */
442 /* We now have a unsorted list of types with an array of res_count_t
443 * in rcarray[0..rccount-1]. And we have names of one type in the
444 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
445 * The list needs to be sorted for win32's top level tree structure.
450 qsort(rcarray
, rccount
, sizeof(rcarray
[0]), sort_type
);
452 /* Now sort the name-id arrays */
453 for(i
= 0; i
< rccount
; i
++)
455 if(rcarray
[i
].count
> 1)
456 qsort(rcarray
[i
].rscarray
, rcarray
[i
].count
, sizeof(rcarray
[0].rscarray
[0]), sort_name_id
);
459 /* Now split the name-id arrays into name/language
460 * subs. Don't look at the awfull expressions...
461 * We do this by taking the array elements out of rscarray and putting
462 * together a new array in rsc32array.
464 for(i
= 0; i
< rccount
; i
++)
468 assert(rcarray
[i
].count
>= 1);
470 /* rcap points to the current type we are dealing with */
471 rcap
= &(rcarray
[i
]);
473 /* Insert the first name-id */
474 rcap
->rsc32array
= (res32_count_t
*)xmalloc(sizeof(res32_count_t
));
476 rcap
->rsc32array
[0].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
477 rcap
->rsc32array
[0].count
= 1;
478 rcap
->rsc32array
[0].rsc
[0] = rcap
->rscarray
[0];
479 if(rcap
->rscarray
[0]->name
->type
== name_ord
)
481 rcap
->n_id_entries
= 1;
482 rcap
->n_name_entries
= 0;
486 rcap
->n_id_entries
= 0;
487 rcap
->n_name_entries
= 1;
490 /* Now loop over the resting resources of the current type
491 * to find duplicate names (which should have different
494 for(j
= 1; j
< rcap
->count
; j
++)
496 res32_count_t
*r32cp
;
498 /* r32cp points to the current res32_count structure
499 * that holds the resource name we are processing.
501 r32cp
= &(rcap
->rsc32array
[rcap
->count32
-1]);
503 if(!compare_name_id(r32cp
->rsc
[0]->name
, rcarray
[i
].rscarray
[j
]->name
))
505 /* Names are the same, add to list */
507 r32cp
->rsc
= (resource_t
**)xrealloc(r32cp
->rsc
, r32cp
->count
* sizeof(resource_t
*));
508 r32cp
->rsc
[r32cp
->count
-1] = rcap
->rscarray
[j
];
510 if(rcap
->rscarray
[j
]->name
->type
== name_ord
)
512 rcap
->n_id_entries
= 1;
513 rcap
->n_name_entries
= 0;
517 rcap
->n_id_entries
= 0;
518 rcap
->n_name_entries
= 1;
523 /* New name-id, sort the old one by
524 * language and create new list
527 qsort(r32cp
->rsc
, r32cp
->count
, sizeof(r32cp
->rsc
[0]), sort_language
);
529 rcap
->rsc32array
= (res32_count_t
*)xrealloc(rcap
->rsc32array
, rcap
->count32
* sizeof(res32_count_t
));
530 rcap
->rsc32array
[rcap
->count32
-1].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
531 rcap
->rsc32array
[rcap
->count32
-1].count
= 1;
532 rcap
->rsc32array
[rcap
->count32
-1].rsc
[0] = rcap
->rscarray
[j
];
534 if(rcap
->rscarray
[j
]->name
->type
== name_ord
)
535 rcap
->n_id_entries
++;
537 rcap
->n_name_entries
++;
540 /* Also sort the languages of the last name group */
541 if(rcap
->rsc32array
[rcap
->count32
-1].count
> 1)
542 qsort(rcap
->rsc32array
[rcap
->count32
-1].rsc
,
543 rcap
->rsc32array
[rcap
->count32
-1].count
,
544 sizeof(rcap
->rsc32array
[rcap
->count32
-1].rsc
[0]),
550 *****************************************************************************
551 * Function : write_pe_segment
552 * Syntax : void write_pe_segment(FILE *fp, resource_t *top)
557 *****************************************************************************
559 void write_pe_segment(FILE *fp
, resource_t
*top
)
563 fprintf(fp
, "\t.align\t4\n");
564 fprintf(fp
, "%s%s:\n", prefix
, _PEResTab
);
565 fprintf(fp
, "\t.globl\t%s%s\n", prefix
, _PEResTab
);
567 fprintf(fp
, "\t.long\t0\n");
568 /* Time/Date stamp */
569 fprintf(fp
, "\t.long\t0x%08lx\n", now
);
571 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
572 /* # of id entries, # of name entries */
573 fprintf(fp
, "\t.short\t%d, %d\n", n_name_entries
, n_id_entries
);
575 /* Write the type level of the tree */
576 for(i
= 0; i
< rccount
; i
++)
584 if(rcp
->type
.type
== name_ord
)
585 fprintf(fp
, "\t.long\t%d\n", rcp
->type
.name
.i_name
);
588 char *name
= prep_nid_for_label(&(rcp
->type
));
589 fprintf(fp
, "\t.long\t(%s_%s_typename - %s%s) | 0x80000000\n",
596 label
= prep_nid_for_label(&(rcp
->type
));
597 fprintf(fp
, "\t.long\t(.L%s - %s%s) | 0x80000000\n",
603 /* Write the name level of the tree */
605 for(i
= 0; i
< rccount
; i
++)
614 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
615 fprintf(fp
, ".L%s:\n", typelabel
);
617 fprintf(fp
, "\t.long\t0\n"); /* Flags */
618 fprintf(fp
, "\t.long\t0x%08lx\n", now
); /* TimeDate */
619 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
620 fprintf(fp
, "\t.short\t%d, %d\n", rcp
->n_name_entries
, rcp
->n_id_entries
);
621 for(j
= 0; j
< rcp
->count32
; j
++)
623 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
625 if(rsc
->name
->type
== name_ord
)
626 fprintf(fp
, "\t.long\t%d\n", rsc
->name
->name
.i_name
);
629 fprintf(fp
, "\t.long\t(%s%s_name - %s%s) | 0x80000000\n",
635 /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
636 * put the offset to the resource data entry.
637 * ?? Is unescaping worth while ??
640 namelabel
= prep_nid_for_label(rsc
->name
);
641 fprintf(fp
, "\t.long\t(.L%s_%s - %s%s) | 0x80000000\n",
650 /* Write the language level of the tree */
652 for(i
= 0; i
< rccount
; i
++)
660 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
662 for(j
= 0; j
< rcp
->count32
; j
++)
664 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
667 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
668 fprintf(fp
, ".L%s_%s:\n", typelabel
, namelabel
);
670 fprintf(fp
, "\t.long\t0\n"); /* Flags */
671 fprintf(fp
, "\t.long\t0x%08lx\n", now
); /* TimeDate */
672 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
673 fprintf(fp
, "\t.short\t0, %d\n", r32cp
->count
);
675 for(k
= 0; k
< r32cp
->count
; k
++)
677 resource_t
*rsc
= r32cp
->rsc
[k
];
678 assert(rsc
->lan
!= NULL
);
680 fprintf(fp
, "\t.long\t0x%08x\n", rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
682 fprintf(fp
, "\t.long\t.L%s_%s_%d - %s%s\n",
685 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0,
694 /* Write the resource table itself */
696 for(i
= 0; i
< rccount
; i
++)
704 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
706 for(j
= 0; j
< rcp
->count32
; j
++)
708 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
711 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
713 for(k
= 0; k
< r32cp
->count
; k
++)
715 resource_t
*rsc
= r32cp
->rsc
[k
];
717 assert(rsc
->lan
!= NULL
);
719 fprintf(fp
, ".L%s_%s_%d:\n",
722 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
725 fprintf(fp
, "\t.long\t%s%s_data - %s%s\n",
731 fprintf(fp
, "\t.long\t%d\n",
732 rsc
->binres
->size
- rsc
->binres
->dataidx
);
734 fprintf(fp
, "\t.long\t%ld\n", codepage
);
736 fprintf(fp
, "\t.long\t0\n");
746 *****************************************************************************
747 * Function : write_ne_segment
748 * Syntax : void write_ne_segment(FILE *fp, resource_t *top)
753 *****************************************************************************
755 void write_ne_segment(FILE *fp
, resource_t
*top
)
759 fprintf(fp
, "\t.align\t4\n");
760 fprintf(fp
, "%s%s:\n", prefix
, _NEResTab
);
761 fprintf(fp
, "\t.globl\t%s%s\n", prefix
, _NEResTab
);
764 fprintf(fp
, "\t.short\t%d\n", alignment_pwr
);
767 for(i
= 0; i
< rccount
; i
++)
769 res_count_t
*rcp
= &rcarray
[i
];
772 if(rcp
->type
.type
== name_ord
)
773 fprintf(fp
, "\t.short\t0x%04x\n", rcp
->type
.name
.i_name
| 0x8000);
775 fprintf(fp
, "\t.short\t%s_%s_typename - %s%s\n",
777 rcp
->type
.name
.s_name
->str
.cstr
,
781 fprintf(fp
, "\t.short\t%d\n", rcp
->count
);
783 fprintf(fp
, "\t.long\t0\n");
785 for(j
= 0; j
< rcp
->count
; j
++)
787 /* FIXME: dividing by `alignment` doesn't seem to
788 * work with as (GAS). Shifting results in the
789 * correct behaviour. Maybe an as bug or just my
790 * lack of knowing as expression-syntax.
795 * The offset is relative to the beginning of the NE resource segment
796 * and _NOT_ to the file-beginning. This is because we do not have a
797 * file based resource, but a simulated NE segment. The offset _is_
798 * scaled by the AlignShift field.
799 * All other things are as the MS doc describes (alignment etc.)
801 fprintf(fp
, "\t.short\t(%s%s_data - %s%s) >> %d\n",
803 rcp
->rscarray
[j
]->c_name
,
808 fprintf(fp
, "\t.short\t%d\n",
809 rcp
->rscarray
[j
]->binres
->size
- rcp
->rscarray
[j
]->binres
->dataidx
);
811 fprintf(fp
, "\t.short\t0x%04x\n", (WORD
)rcp
->rscarray
[j
]->memopt
);
813 if(rcp
->rscarray
[j
]->name
->type
== name_ord
)
814 fprintf(fp
, "\t.short\t0x%04x\n", rcp
->rscarray
[j
]->name
->name
.i_name
| 0x8000);
816 fprintf(fp
, "\t.short\t%s%s_name - %s%s\n",
818 rcp
->rscarray
[j
]->c_name
,
821 /* Handle and Usage */
822 fprintf(fp
, "\t.short\t0, 0\n");
826 fprintf(fp
, "\t.short\t0\n");
830 *****************************************************************************
831 * Function : write_rsc_names
832 * Syntax : void write_rsc_names(FILE *fp, resource_t *top)
837 *****************************************************************************
839 void write_rsc_names(FILE *fp
, resource_t
*top
)
845 /* Write the names */
847 for(i
= 0; i
< rccount
; i
++)
853 if(rcp
->type
.type
== name_str
)
855 char *name
= prep_nid_for_label(&(rcp
->type
));
856 fprintf(fp
, "%s_%s_typename:\n",
859 write_name_str(fp
, &(rcp
->type
));
862 for(j
= 0; j
< rcp
->count32
; j
++)
864 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
866 if(rsc
->name
->type
== name_str
)
868 fprintf(fp
, "%s%s_name:\n",
871 write_name_str(fp
, rsc
->name
);
879 for(i
= 0; i
< rccount
; i
++)
881 res_count_t
*rcp
= &rcarray
[i
];
883 for(j
= 0; j
< rcp
->count
; j
++)
885 if(rcp
->type
.type
== name_str
)
887 fprintf(fp
, "%s_%s_typename:\n",
889 rcp
->type
.name
.s_name
->str
.cstr
);
890 write_name_str(fp
, &(rcp
->type
));
892 if(rcp
->rscarray
[j
]->name
->type
== name_str
)
894 fprintf(fp
, "%s%s_name:\n",
896 rcp
->rscarray
[j
]->c_name
);
897 write_name_str(fp
, rcp
->rscarray
[j
]->name
);
903 /* This is to end the NE resource table */
905 fprintf(fp
, "\t.byte\t0\n");
912 *****************************************************************************
913 * Function : write_s_file
914 * Syntax : void write_s_file(char *outname, resource_t *top)
916 * outname - Filename to write to
917 * top - The resource-tree to convert
921 *****************************************************************************
923 void write_s_file(char *outname
, resource_t
*top
)
928 fo
= fopen(outname
, "wt");
931 error("Could not open %s\n", outname
);
935 fprintf(fo
, s_file_head_str
, input_name
? input_name
: "stdin",
936 cmdline
, ctime(&now
));
938 /* Get an idea how many we have and restructure the tables */
939 count_resources(top
);
941 /* First write the segment tables */
945 write_pe_segment(fo
, top
);
947 write_ne_segment(fo
, top
);
951 write_rsc_names(fo
, top
);
955 /* Write the resource data */
956 fprintf(fo
, "#\n# Resource binary data\n#\n");
957 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
962 fprintf(fo
, "\t.align\t%d\n", win32
? 4 : alignment
);
963 fprintf(fo
, "%s%s_data:\n", prefix
, rsc
->c_name
);
965 fprintf(fo
, "\t.globl\t%s%s_data\n", prefix
, rsc
->c_name
);
967 write_s_res(fo
, rsc
->binres
);
975 /* Write the indirection structures */
976 fprintf(fo
, "\n#\n# Resource indirection structures\n#\n");
977 fprintf(fo
, "\t.align\t4\n");
978 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
981 char *type_name
= NULL
;
992 type
= WRC_RT_DIALOG
;
995 assert(rsc
->res
.usr
->type
!= NULL
);
996 type_name
= prep_nid_for_label(rsc
->res
.usr
->type
);
1004 * This follows a structure like:
1005 * struct wrc_resource {
1009 * RSCNAME *typename;
1013 * The 'RSCNAME' is a pascal-style string where the
1014 * first byte/word denotes the size and the rest the string
1017 fprintf(fo
, "%s%s:\n", prefix
, rsc
->c_name
);
1019 fprintf(fo
, "\t.globl\t%s%s\n", prefix
, rsc
->c_name
);
1020 fprintf(fo
, "\t.long\t%d, %s%s%s, %d, %s%s%s%s, %s%s_data, %d\n",
1021 rsc
->name
->type
== name_ord
? rsc
->name
->name
.i_name
: 0,
1022 rsc
->name
->type
== name_ord
? "0" : prefix
,
1023 rsc
->name
->type
== name_ord
? "" : rsc
->c_name
,
1024 rsc
->name
->type
== name_ord
? "" : "_name",
1026 type
? "0" : prefix
,
1028 type
? "" : type_name
,
1029 type
? "" : "_typename",
1032 rsc
->binres
->size
- rsc
->binres
->dataidx
);
1037 /* Write the indirection table */
1038 fprintf(fo
, "#\n# Resource indirection table\n#\n");
1039 fprintf(fo
, "\t.align\t4\n");
1040 fprintf(fo
, "%s%s:\n", prefix
, _ResTable
);
1041 fprintf(fo
, "\t.globl\t%s%s\n", prefix
, _ResTable
);
1042 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
1044 fprintf(fo
, "\t.long\t%s%s\n", prefix
, rsc
->c_name
);
1046 fprintf(fo
, "\t.long\t0\n");
1051 fprintf(fo
, s_file_autoreg_str
, prefix
, _ResTable
);
1053 fprintf(fo
, s_file_tail_str
);
1058 *****************************************************************************
1059 * Function : write_h_file
1060 * Syntax : void write_h_file(char *outname, resource_t *top)
1062 * outname - Filename to write to
1063 * top - The resource-tree to convert
1067 *****************************************************************************
1069 void write_h_file(char *outname
, resource_t
*top
)
1075 #ifdef NEED_UNDERSCORE_PREFIX
1076 h_prefix
= prefix
+ 1;
1081 fo
= fopen(outname
, "wt");
1084 error("Could not open %s\n", outname
);
1088 fprintf(fo
, h_file_head_str
, input_name
? input_name
: "stdin",
1089 cmdline
, ctime(&now
), now
, now
);
1091 /* First write the segment tables reference */
1094 fprintf(fo
, "extern %schar %s%s[];\n\n",
1095 constant
? "const " : "",
1097 win32
? _PEResTab
: _NEResTab
);
1100 /* Write the resource data */
1101 for(rsc
= top
; global
&& rsc
; rsc
= rsc
->next
)
1106 fprintf(fo
, "extern %schar %s%s_data[];\n",
1107 constant
? "const " : "",
1117 /* Write the indirection structures */
1118 for(rsc
= top
; global
&& rsc
; rsc
= rsc
->next
)
1120 fprintf(fo
, "extern %swrc_resource%d_t %s%s;\n",
1121 constant
? "const " : "",
1130 /* Write the indirection table */
1131 fprintf(fo
, "extern %swrc_resource%d_t %s%s[];\n\n",
1132 constant
? "const " : "",
1138 fprintf(fo
, h_file_tail_str
);