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 char s_file_head_str
[] =
29 "# This file is generated with wrc version " WRC_FULLVERSION
". Do not edit!\n"
37 char s_file_tail_str
[] =
41 char s_file_autoreg_str
[] =
45 #ifdef NEED_UNDERSCORE_PREFIX
46 "\tcall\t_LIBRES_RegisterResources\n"
48 "\tcall\tLIBRES_RegisterResources\n"
53 ".stabs \"___CTOR_LIST__\",22,0,0,.LAuto_Register\n\n"
55 "\t.section .ctors,\"aw\"\n"
56 "\t.long\t.LAuto_Register\n\n"
60 char h_file_head_str
[] =
62 " * This file is generated with wrc version " WRC_FULLVERSION
". Do not edit!\n"
67 "#ifndef __%08x_H\n" /* This becomes the data of compile */
68 "#define __%08x_H\n\n"
69 "#ifndef __WRC_RSC_H\n"
70 "#include <wrc_rsc.h>\n"
74 char h_file_tail_str
[] =
79 char _NEResTab
[] = "_NEResTab";
80 char _PEResTab
[] = "_PEResTab";
81 char _ResTable
[] = "_ResTable";
83 res_count_t
*rcarray
= NULL
;
86 int n_name_entries
= 0;
91 *****************************************************************************
92 * Function : write_resfile
93 * Syntax : void write_resfile(char *outname, resource_t *top)
95 * outname - Filename to write to
96 * top - The resource-tree to convert
100 *****************************************************************************
102 void write_resfile(char *outname
, resource_t
*top
)
106 char zeros
[3] = {0, 0, 0};
108 fo
= fopen(outname
, "wb");
111 error("Could not open %s\n", outname
);
116 /* Put an empty resource first to signal win32 format */
117 res_t
*res
= new_res();
118 put_dword(res
, 0); /* ResSize */
119 put_dword(res
, 0x00000020); /* HeaderSize */
120 put_word(res
, 0xffff); /* ResType */
122 put_word(res
, 0xffff); /* ResName */
124 put_dword(res
, 0); /* DataVersion */
125 put_word(res
, 0); /* Memory options */
126 put_word(res
, 0); /* Language */
127 put_dword(res
, 0); /* Version */
128 put_dword(res
, 0); /* Charateristics */
129 ret
= fwrite(res
->data
, 1, res
->size
, fo
);
133 error("Error writing %s", outname
);
138 for(; top
; top
= top
->next
)
143 ret
= fwrite(top
->binres
->data
, 1, top
->binres
->size
, fo
);
144 if(ret
!= top
->binres
->size
)
147 error("Error writing %s", outname
);
149 if(win32
&& (top
->binres
->size
& 0x03))
152 ret
= fwrite(zeros
, 1, 4 - (top
->binres
->size
& 0x03), fo
);
153 if(ret
!= 4 - (top
->binres
->size
& 0x03))
156 error("Error writing %s", outname
);
164 *****************************************************************************
165 * Function : write_s_res
166 * Syntax : void write_s_res(FILE *fp, res_t *res)
171 *****************************************************************************
173 #define BYTESPERLINE 8
174 void write_s_res(FILE *fp
, res_t
*res
)
176 int idx
= res
->dataidx
;
178 int rest
= (end
- idx
) % BYTESPERLINE
;
179 int lines
= (end
- idx
) / BYTESPERLINE
;
182 for(i
= 0 ; i
< lines
; i
++)
184 fprintf(fp
, "\t.byte\t");
185 for(j
= 0; j
< BYTESPERLINE
; j
++, idx
++)
187 fprintf(fp
, "0x%02x%s", res
->data
[idx
] & 0xff,
188 j
== BYTESPERLINE
-1 ? "" : ", ");
194 fprintf(fp
, "\t.byte\t");
195 for(j
= 0; j
< rest
; j
++, idx
++)
197 fprintf(fp
, "0x%02x%s", res
->data
[idx
] & 0xff,
198 j
== rest
-1 ? "" : ", ");
205 *****************************************************************************
206 * Function : write_name_str
207 * Syntax : void write_name_str(FILE *fp, name_id_t *nid)
211 * Remarks : One level self recursive for string type conversion
212 *****************************************************************************
214 void write_name_str(FILE *fp
, name_id_t
*nid
)
217 assert(nid
->type
== name_str
);
219 if(!win32
&& nid
->name
.s_name
->type
== str_char
)
221 res
.size
= strlen(nid
->name
.s_name
->str
.cstr
);
223 error("Can't write strings larger than 254 bytes");
225 internal_error(__FILE__
, __LINE__
, "Attempt to write empty string");
227 res
.data
= (char *)xmalloc(res
.size
+ 1);
228 res
.data
[0] = (char)res
.size
;
229 res
.size
++; /* We need to write the lenth byte as well */
230 strcpy(res
.data
+1, nid
->name
.s_name
->str
.cstr
);
231 write_s_res(fp
, &res
);
234 else if(!win32
&& nid
->name
.s_name
->type
== str_unicode
)
239 lnid
.type
= name_str
;
240 lnid
.name
.s_name
= &str
;
242 str
.str
.cstr
= dupwstr2cstr(nid
->name
.s_name
->str
.wstr
);
243 write_name_str(fp
, &lnid
);
246 else if(win32
&& nid
->name
.s_name
->type
== str_char
)
251 lnid
.type
= name_str
;
252 lnid
.name
.s_name
= &str
;
253 str
.type
= str_unicode
;
254 str
.str
.wstr
= dupcstr2wstr(nid
->name
.s_name
->str
.cstr
);
255 write_name_str(fp
, &lnid
);
258 else if(win32
&& nid
->name
.s_name
->type
== str_unicode
)
260 res
.size
= wstrlen(nid
->name
.s_name
->str
.wstr
);
262 error("Can't write strings larger than 65534 bytes");
264 internal_error(__FILE__
, __LINE__
, "Attempt to write empty string");
266 res
.data
= (char *)xmalloc((res
.size
+ 1) * 2);
267 ((short *)res
.data
)[0] = (short)res
.size
;
268 wstrcpy((short *)(res
.data
+2), nid
->name
.s_name
->str
.wstr
);
269 res
.size
*= 2; /* Function writes bytes, not shorts... */
270 res
.size
+= 2; /* We need to write the length word as well */
271 write_s_res(fp
, &res
);
276 internal_error(__FILE__
, __LINE__
, "Hmm, requested to write a string of unknown type %d",
277 nid
->name
.s_name
->type
);
282 *****************************************************************************
283 * Function : compare_name_id
284 * Syntax : int compare_name_id(name_id_t *n1, name_id_t *n2)
289 *****************************************************************************
291 int compare_name_id(name_id_t
*n1
, name_id_t
*n2
)
293 if(n1
->type
== name_ord
&& n2
->type
== name_ord
)
295 return n1
->name
.i_name
- n2
->name
.i_name
;
297 else if(n1
->type
== name_str
&& n2
->type
== name_str
)
299 if(n1
->name
.s_name
->type
== str_char
300 && n2
->name
.s_name
->type
== str_char
)
302 return stricmp(n1
->name
.s_name
->str
.cstr
, n2
->name
.s_name
->str
.cstr
);
304 else if(n1
->name
.s_name
->type
== str_unicode
305 && n2
->name
.s_name
->type
== str_unicode
)
307 return wstricmp(n1
->name
.s_name
->str
.wstr
, n2
->name
.s_name
->str
.wstr
);
311 internal_error(__FILE__
, __LINE__
, "Can't yet compare strings of mixed type");
314 else if(n1
->type
== name_ord
&& n2
->type
== name_str
)
316 else if(n1
->type
== name_str
&& n2
->type
== name_ord
)
319 internal_error(__FILE__
, __LINE__
, "Comparing name-ids with unknown types (%d, %d)",
322 return 0; /* Keep the compiler happy */
326 *****************************************************************************
327 * Function : find_counter
328 * Syntax : res_count_t *find_counter(name_id_t *type)
333 *****************************************************************************
335 res_count_t
*find_counter(name_id_t
*type
)
338 for(i
= 0; i
< rccount
; i
++)
340 if(!compare_name_id(type
, &(rcarray
[i
].type
)))
347 *****************************************************************************
348 * Function : count_resources
349 * Syntax : res_count_t *count_resources(resource_t *top)
353 * Remarks : The whole lot is converted into arrays because they are
354 * easy sortable. Makes the lot almost unreadable, but it
355 * works (I hope). Basically you have to keep in mind that
356 * the lot is a three-dimensional structure for win32 and a
357 * two-dimensional structure for win16.
358 *****************************************************************************
360 #define RCT(v) (*((resource_t **)(v)))
361 /* qsort sorting function */
362 int sort_name_id(const void *e1
, const void *e2
)
364 return compare_name_id(RCT(e1
)->name
, RCT(e2
)->name
);
367 int sort_language(const void *e1
, const void *e2
)
369 assert((RCT(e1
)->lan
) != NULL
);
370 assert((RCT(e2
)->lan
) != NULL
);
372 return MAKELANGID(RCT(e1
)->lan
->id
, RCT(e1
)->lan
->sub
)
373 - MAKELANGID(RCT(e2
)->lan
->id
, RCT(e2
)->lan
->sub
);
376 #define RCT(v) ((res_count_t *)(v))
377 int sort_type(const void *e1
, const void *e2
)
379 return compare_name_id(&(RCT(e1
)->type
), &(RCT(e2
)->type
));
383 void count_resources(resource_t
*top
)
390 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
397 nid
.name
.i_name
= WRC_RT_DIALOG
;
401 nid
.name
.i_name
= WRC_RT_MENU
;
405 nid
= *(rsc
->res
.usr
->type
);
408 nid
.name
.i_name
= rsc
->type
;
412 if((rcp
= find_counter(&nid
)) == NULL
)
414 /* Count the number of uniq ids and names */
416 if(nid
.type
== name_ord
)
423 rcarray
= (res_count_t
*)xmalloc(sizeof(res_count_t
));
425 rcarray
[0].count
= 1;
426 rcarray
[0].type
= nid
;
427 rcarray
[0].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
428 rcarray
[0].rscarray
[0] = rsc
;
433 rcarray
= (res_count_t
*)xrealloc(rcarray
, rccount
* sizeof(res_count_t
));
434 rcarray
[rccount
-1].count
= 1;
435 rcarray
[rccount
-1].type
= nid
;
436 rcarray
[rccount
-1].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
437 rcarray
[rccount
-1].rscarray
[0] = rsc
;
443 rcp
->rscarray
= (resource_t
**)xrealloc(rcp
->rscarray
, rcp
->count
* sizeof(resource_t
*));
444 rcp
->rscarray
[rcp
->count
-1] = rsc
;
450 /* We're done, win16 requires no special sorting */
454 /* We now have a unsorted list of types with an array of res_count_t
455 * in rcarray[0..rccount-1]. And we have names of one type in the
456 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
457 * The list needs to be sorted for win32's top level tree structure.
462 qsort(rcarray
, rccount
, sizeof(rcarray
[0]), sort_type
);
464 /* Now sort the name-id arrays */
465 for(i
= 0; i
< rccount
; i
++)
467 if(rcarray
[i
].count
> 1)
468 qsort(rcarray
[i
].rscarray
, rcarray
[i
].count
, sizeof(rcarray
[0].rscarray
[0]), sort_name_id
);
471 /* Now split the name-id arrays into name/language
472 * subs. Don't look at the awfull expressions...
473 * We do this by taking the array elements out of rscarray and putting
474 * together a new array in rsc32array.
476 for(i
= 0; i
< rccount
; i
++)
480 assert(rcarray
[i
].count
>= 1);
482 /* rcap points to the current type we are dealing with */
483 rcap
= &(rcarray
[i
]);
485 /* Insert the first name-id */
486 rcap
->rsc32array
= (res32_count_t
*)xmalloc(sizeof(res32_count_t
));
488 rcap
->rsc32array
[0].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
489 rcap
->rsc32array
[0].count
= 1;
490 rcap
->rsc32array
[0].rsc
[0] = rcap
->rscarray
[0];
491 if(rcap
->rscarray
[0]->name
->type
== name_ord
)
493 rcap
->n_id_entries
= 1;
494 rcap
->n_name_entries
= 0;
498 rcap
->n_id_entries
= 0;
499 rcap
->n_name_entries
= 1;
502 /* Now loop over the resting resources of the current type
503 * to find duplicate names (which should have different
506 for(j
= 1; j
< rcap
->count
; j
++)
508 res32_count_t
*r32cp
;
510 /* r32cp points to the current res32_count structure
511 * that holds the resource name we are processing.
513 r32cp
= &(rcap
->rsc32array
[rcap
->count32
-1]);
515 if(!compare_name_id(r32cp
->rsc
[0]->name
, rcarray
[i
].rscarray
[j
]->name
))
517 /* Names are the same, add to list */
519 r32cp
->rsc
= (resource_t
**)xrealloc(r32cp
->rsc
, r32cp
->count
* sizeof(resource_t
*));
520 r32cp
->rsc
[r32cp
->count
-1] = rcap
->rscarray
[j
];
522 if(rcap
->rscarray
[j
]->name
->type
== name_ord
)
524 rcap
->n_id_entries
= 1;
525 rcap
->n_name_entries
= 0;
529 rcap
->n_id_entries
= 0;
530 rcap
->n_name_entries
= 1;
535 /* New name-id, sort the old one by
536 * language and create new list
539 qsort(r32cp
->rsc
, r32cp
->count
, sizeof(r32cp
->rsc
[0]), sort_language
);
541 rcap
->rsc32array
= (res32_count_t
*)xrealloc(rcap
->rsc32array
, rcap
->count32
* sizeof(res32_count_t
));
542 rcap
->rsc32array
[rcap
->count32
-1].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
543 rcap
->rsc32array
[rcap
->count32
-1].count
= 1;
544 rcap
->rsc32array
[rcap
->count32
-1].rsc
[0] = rcap
->rscarray
[j
];
546 if(rcap
->rscarray
[j
]->name
->type
== name_ord
)
547 rcap
->n_id_entries
++;
549 rcap
->n_name_entries
++;
552 /* Also sort the languages of the last name group */
553 if(rcap
->rsc32array
[rcap
->count32
-1].count
> 1)
554 qsort(rcap
->rsc32array
[rcap
->count32
-1].rsc
,
555 rcap
->rsc32array
[rcap
->count32
-1].count
,
556 sizeof(rcap
->rsc32array
[rcap
->count32
-1].rsc
[0]),
562 *****************************************************************************
563 * Function : write_pe_segment
564 * Syntax : void write_pe_segment(FILE *fp, resource_t *top)
569 *****************************************************************************
571 void write_pe_segment(FILE *fp
, resource_t
*top
)
575 fprintf(fp
, "\t.align\t4\n");
576 fprintf(fp
, "%s%s:\n", prefix
, _PEResTab
);
577 fprintf(fp
, "\t.globl\t%s%s\n", prefix
, _PEResTab
);
579 fprintf(fp
, "\t.long\t0\n");
580 /* Time/Date stamp */
581 fprintf(fp
, "\t.long\t0x%08lx\n", now
);
583 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
584 /* # of id entries, # of name entries */
585 fprintf(fp
, "\t.short\t%d, %d\n", n_name_entries
, n_id_entries
);
587 /* Write the type level of the tree */
588 for(i
= 0; i
< rccount
; i
++)
596 if(rcp
->type
.type
== name_ord
)
597 fprintf(fp
, "\t.long\t%d\n", rcp
->type
.name
.i_name
);
600 char *name
= prep_nid_for_label(&(rcp
->type
));
601 fprintf(fp
, "\t.long\t(%s_%s_typename - %s%s) | 0x80000000\n",
608 label
= prep_nid_for_label(&(rcp
->type
));
609 fprintf(fp
, "\t.long\t(.L%s - %s%s) | 0x80000000\n",
615 /* Write the name level of the tree */
617 for(i
= 0; i
< rccount
; i
++)
626 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
627 fprintf(fp
, ".L%s:\n", typelabel
);
629 fprintf(fp
, "\t.long\t0\n"); /* Flags */
630 fprintf(fp
, "\t.long\t0x%08lx\n", now
); /* TimeDate */
631 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
632 fprintf(fp
, "\t.short\t%d, %d\n", rcp
->n_name_entries
, rcp
->n_id_entries
);
633 for(j
= 0; j
< rcp
->count32
; j
++)
635 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
637 if(rsc
->name
->type
== name_ord
)
638 fprintf(fp
, "\t.long\t%d\n", rsc
->name
->name
.i_name
);
641 fprintf(fp
, "\t.long\t(%s%s_name - %s%s) | 0x80000000\n",
647 /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
648 * put the offset to the resource data entry.
649 * ?? Is unescaping worth while ??
652 namelabel
= prep_nid_for_label(rsc
->name
);
653 fprintf(fp
, "\t.long\t(.L%s_%s - %s%s) | 0x80000000\n",
662 /* Write the language level of the tree */
664 for(i
= 0; i
< rccount
; i
++)
672 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
674 for(j
= 0; j
< rcp
->count32
; j
++)
676 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
679 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
680 fprintf(fp
, ".L%s_%s:\n", typelabel
, namelabel
);
682 fprintf(fp
, "\t.long\t0\n"); /* Flags */
683 fprintf(fp
, "\t.long\t0x%08lx\n", now
); /* TimeDate */
684 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
685 fprintf(fp
, "\t.short\t0, %d\n", r32cp
->count
);
687 for(k
= 0; k
< r32cp
->count
; k
++)
689 resource_t
*rsc
= r32cp
->rsc
[k
];
690 assert(rsc
->lan
!= NULL
);
692 fprintf(fp
, "\t.long\t0x%08x\n", rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
694 fprintf(fp
, "\t.long\t.L%s_%s_%d - %s%s\n",
697 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0,
706 /* Write the resource table itself */
708 for(i
= 0; i
< rccount
; i
++)
716 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
718 for(j
= 0; j
< rcp
->count32
; j
++)
720 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
723 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
725 for(k
= 0; k
< r32cp
->count
; k
++)
727 resource_t
*rsc
= r32cp
->rsc
[k
];
729 assert(rsc
->lan
!= NULL
);
731 fprintf(fp
, ".L%s_%s_%d:\n",
734 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
737 fprintf(fp
, "\t.long\t%s%s_data - %s%s\n",
743 fprintf(fp
, "\t.long\t%d\n",
744 rsc
->binres
->size
- rsc
->binres
->dataidx
);
746 fprintf(fp
, "\t.long\t%ld\n", codepage
);
748 fprintf(fp
, "\t.long\t0\n");
755 fprintf(fp
, "\t.align\t4\n");
756 fprintf(fp
, "%s_ResourceDirectorySize:\n", Underscore
);
757 fprintf(fp
, "\t.globl\t%s_ResourceDirectorySize\n", Underscore
);
758 fprintf(fp
, "\t.long\t. - %s%s\n", prefix
, _PEResTab
);
762 *****************************************************************************
763 * Function : write_ne_segment
764 * Syntax : void write_ne_segment(FILE *fp, resource_t *top)
769 *****************************************************************************
771 void write_ne_segment(FILE *fp
, resource_t
*top
)
775 fprintf(fp
, "\t.align\t4\n");
776 fprintf(fp
, "%s%s:\n", prefix
, _NEResTab
);
777 fprintf(fp
, "\t.globl\t%s%s\n", prefix
, _NEResTab
);
780 fprintf(fp
, "\t.short\t%d\n", alignment_pwr
);
783 for(i
= 0; i
< rccount
; i
++)
785 res_count_t
*rcp
= &rcarray
[i
];
788 if(rcp
->type
.type
== name_ord
)
789 fprintf(fp
, "\t.short\t0x%04x\n", rcp
->type
.name
.i_name
| 0x8000);
791 fprintf(fp
, "\t.short\t%s_%s_typename - %s%s\n",
793 rcp
->type
.name
.s_name
->str
.cstr
,
797 fprintf(fp
, "\t.short\t%d\n", rcp
->count
);
799 fprintf(fp
, "\t.long\t0\n");
801 for(j
= 0; j
< rcp
->count
; j
++)
803 /* FIXME: dividing by `alignment` doesn't seem to
804 * work with as (GAS). Shifting results in the
805 * correct behaviour. Maybe an as bug or just my
806 * lack of knowing as expression-syntax.
811 * The offset is relative to the beginning of the NE resource segment
812 * and _NOT_ to the file-beginning. This is because we do not have a
813 * file based resource, but a simulated NE segment. The offset _is_
814 * scaled by the AlignShift field.
815 * All other things are as the MS doc describes (alignment etc.)
817 fprintf(fp
, "\t.short\t(%s%s_data - %s%s) >> %d\n",
819 rcp
->rscarray
[j
]->c_name
,
824 fprintf(fp
, "\t.short\t%d\n",
825 rcp
->rscarray
[j
]->binres
->size
- rcp
->rscarray
[j
]->binres
->dataidx
);
827 fprintf(fp
, "\t.short\t0x%04x\n", (WORD
)rcp
->rscarray
[j
]->memopt
);
829 if(rcp
->rscarray
[j
]->name
->type
== name_ord
)
830 fprintf(fp
, "\t.short\t0x%04x\n", rcp
->rscarray
[j
]->name
->name
.i_name
| 0x8000);
832 fprintf(fp
, "\t.short\t%s%s_name - %s%s\n",
834 rcp
->rscarray
[j
]->c_name
,
837 /* Handle and Usage */
838 fprintf(fp
, "\t.short\t0, 0\n");
842 fprintf(fp
, "\t.short\t0\n");
846 *****************************************************************************
847 * Function : write_rsc_names
848 * Syntax : void write_rsc_names(FILE *fp, resource_t *top)
853 *****************************************************************************
855 void write_rsc_names(FILE *fp
, resource_t
*top
)
861 /* Write the names */
863 for(i
= 0; i
< rccount
; i
++)
869 if(rcp
->type
.type
== name_str
)
871 char *name
= prep_nid_for_label(&(rcp
->type
));
872 fprintf(fp
, "%s_%s_typename:\n",
875 write_name_str(fp
, &(rcp
->type
));
878 for(j
= 0; j
< rcp
->count32
; j
++)
880 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
882 if(rsc
->name
->type
== name_str
)
884 fprintf(fp
, "%s%s_name:\n",
887 write_name_str(fp
, rsc
->name
);
895 for(i
= 0; i
< rccount
; i
++)
897 res_count_t
*rcp
= &rcarray
[i
];
899 for(j
= 0; j
< rcp
->count
; j
++)
901 if(rcp
->type
.type
== name_str
)
903 fprintf(fp
, "%s_%s_typename:\n",
905 rcp
->type
.name
.s_name
->str
.cstr
);
906 write_name_str(fp
, &(rcp
->type
));
908 if(rcp
->rscarray
[j
]->name
->type
== name_str
)
910 fprintf(fp
, "%s%s_name:\n",
912 rcp
->rscarray
[j
]->c_name
);
913 write_name_str(fp
, rcp
->rscarray
[j
]->name
);
919 /* This is to end the NE resource table */
921 fprintf(fp
, "\t.byte\t0\n");
928 *****************************************************************************
929 * Function : write_s_file
930 * Syntax : void write_s_file(char *outname, resource_t *top)
932 * outname - Filename to write to
933 * top - The resource-tree to convert
937 *****************************************************************************
939 void write_s_file(char *outname
, resource_t
*top
)
944 fo
= fopen(outname
, "wt");
947 error("Could not open %s\n", outname
);
951 fprintf(fo
, s_file_head_str
, input_name
? input_name
: "stdin",
952 cmdline
, ctime(&now
));
954 /* Get an idea how many we have and restructure the tables */
955 count_resources(top
);
957 /* First write the segment tables */
961 write_pe_segment(fo
, top
);
963 write_ne_segment(fo
, top
);
967 write_rsc_names(fo
, top
);
971 /* Write the resource data */
972 fprintf(fo
, "#\n# Resource binary data\n#\n");
973 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
978 fprintf(fo
, "\t.align\t%d\n", win32
? 4 : alignment
);
979 fprintf(fo
, "%s%s_data:\n", prefix
, rsc
->c_name
);
981 fprintf(fo
, "\t.globl\t%s%s_data\n", prefix
, rsc
->c_name
);
983 write_s_res(fo
, rsc
->binres
);
990 /* Add the size of the entire resource section for elf-dlls */
991 fprintf(fo
, "%s_ResourceSectionSize:\n", Underscore
);
992 fprintf(fo
, "\t.long\t. - %s%s\n", prefix
, _PEResTab
);
998 /* Write the indirection structures */
999 fprintf(fo
, "\n#\n# Resource indirection structures\n#\n");
1000 fprintf(fo
, "\t.align\t4\n");
1001 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
1004 char *type_name
= NULL
;
1015 type
= WRC_RT_DIALOG
;
1018 assert(rsc
->res
.usr
->type
!= NULL
);
1019 type_name
= prep_nid_for_label(rsc
->res
.usr
->type
);
1027 * This follows a structure like:
1028 * struct wrc_resource {
1032 * RSCNAME *typename;
1036 * The 'RSCNAME' is a pascal-style string where the
1037 * first byte/word denotes the size and the rest the string
1040 fprintf(fo
, "%s%s:\n", prefix
, rsc
->c_name
);
1042 fprintf(fo
, "\t.globl\t%s%s\n", prefix
, rsc
->c_name
);
1043 fprintf(fo
, "\t.long\t%d, %s%s%s, %d, %s%s%s%s, %s%s_data, %d\n",
1044 rsc
->name
->type
== name_ord
? rsc
->name
->name
.i_name
: 0,
1045 rsc
->name
->type
== name_ord
? "0" : prefix
,
1046 rsc
->name
->type
== name_ord
? "" : rsc
->c_name
,
1047 rsc
->name
->type
== name_ord
? "" : "_name",
1049 type
? "0" : prefix
,
1051 type
? "" : type_name
,
1052 type
? "" : "_typename",
1055 rsc
->binres
->size
- rsc
->binres
->dataidx
);
1060 /* Write the indirection table */
1061 fprintf(fo
, "#\n# Resource indirection table\n#\n");
1062 fprintf(fo
, "\t.align\t4\n");
1063 fprintf(fo
, "%s%s:\n", prefix
, _ResTable
);
1064 fprintf(fo
, "\t.globl\t%s%s\n", prefix
, _ResTable
);
1065 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
1067 fprintf(fo
, "\t.long\t%s%s\n", prefix
, rsc
->c_name
);
1069 fprintf(fo
, "\t.long\t0\n");
1074 fprintf(fo
, s_file_autoreg_str
, prefix
, _ResTable
);
1076 fprintf(fo
, s_file_tail_str
);
1081 *****************************************************************************
1082 * Function : write_h_file
1083 * Syntax : void write_h_file(char *outname, resource_t *top)
1085 * outname - Filename to write to
1086 * top - The resource-tree to convert
1090 *****************************************************************************
1092 void write_h_file(char *outname
, resource_t
*top
)
1098 #ifdef NEED_UNDERSCORE_PREFIX
1099 h_prefix
= prefix
+ 1;
1104 fo
= fopen(outname
, "wt");
1107 error("Could not open %s\n", outname
);
1111 fprintf(fo
, h_file_head_str
, input_name
? input_name
: "stdin",
1112 cmdline
, ctime(&now
), now
, now
);
1114 /* First write the segment tables reference */
1117 fprintf(fo
, "extern %schar %s%s[];\n\n",
1118 constant
? "const " : "",
1120 win32
? _PEResTab
: _NEResTab
);
1123 /* Write the resource data */
1124 for(rsc
= top
; global
&& rsc
; rsc
= rsc
->next
)
1129 fprintf(fo
, "extern %schar %s%s_data[];\n",
1130 constant
? "const " : "",
1140 /* Write the indirection structures */
1141 for(rsc
= top
; global
&& rsc
; rsc
= rsc
->next
)
1143 fprintf(fo
, "extern %swrc_resource%d_t %s%s;\n",
1144 constant
? "const " : "",
1153 /* Write the indirection table */
1154 fprintf(fo
, "extern %swrc_resource%d_t %s%s[];\n\n",
1155 constant
? "const " : "",
1161 fprintf(fo
, h_file_tail_str
);