2 * Write .res, .s and .h file(s) from a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
22 #ifdef NEED_UNDERSCORE_PREFIX
23 char Underscore
[] = "_";
25 char Underscore
[] = "";
28 char s_file_head_str
[] =
29 "/* This file is generated with wrc version " WRC_FULLVERSION
". Do not edit! */\n"
38 char s_file_tail_str
[] =
43 char s_file_autoreg_str
[] =
47 #ifdef NEED_UNDERSCORE_PREFIX
48 "\tcall\t_LIBRES_RegisterResources\n"
50 "\tcall\tLIBRES_RegisterResources\n"
55 ".stabs \"___CTOR_LIST__\",22,0,0,.LAuto_Register\n\n"
57 "\t.section .ctors,\"aw\"\n"
58 "\t.long\t.LAuto_Register\n\n"
62 char h_file_head_str
[] =
64 " * This file is generated with wrc version " WRC_FULLVERSION
". Do not edit!\n"
70 "#ifndef __%08lx_H\n" /* This becomes the date of compile */
73 "#include <wrc_rsc.h>\n"
77 char h_file_tail_str
[] =
82 char _NEResTab
[] = "_NEResTab";
83 char _PEResTab
[] = "_PEResTab";
84 char _ResTable
[] = "_ResTable";
86 /* Variables used for resource sorting */
87 res_count_t
*rcarray
= NULL
; /* Type-level count array */
88 int rccount
= 0; /* Nr of entries in the type-level array */
89 int n_id_entries
= 0; /* win32 only: Nr of unique ids in the type-level array */
90 int n_name_entries
= 0; /* win32 only: Nr of unique namess in the type-level array */
92 static int direntries
; /* win32 only: Total number of unique resources */
97 *****************************************************************************
98 * Function : write_resfile
99 * Syntax : void write_resfile(char *outname, resource_t *top)
101 * outname - Filename to write to
102 * top - The resource-tree to convert
106 *****************************************************************************
108 void write_resfile(char *outname
, resource_t
*top
)
112 char zeros
[3] = {0, 0, 0};
114 fo
= fopen(outname
, "wb");
117 error("Could not open %s\n", outname
);
122 /* Put an empty resource first to signal win32 format */
123 res_t
*res
= new_res();
124 put_dword(res
, 0); /* ResSize */
125 put_dword(res
, 0x00000020); /* HeaderSize */
126 put_word(res
, 0xffff); /* ResType */
128 put_word(res
, 0xffff); /* ResName */
130 put_dword(res
, 0); /* DataVersion */
131 put_word(res
, 0); /* Memory options */
132 put_word(res
, 0); /* Language */
133 put_dword(res
, 0); /* Version */
134 put_dword(res
, 0); /* Charateristics */
135 ret
= fwrite(res
->data
, 1, res
->size
, fo
);
139 error("Error writing %s", outname
);
144 for(; top
; top
= top
->next
)
149 ret
= fwrite(top
->binres
->data
, 1, top
->binres
->size
, fo
);
150 if(ret
!= top
->binres
->size
)
153 error("Error writing %s", outname
);
155 if(win32
&& (top
->binres
->size
& 0x03))
158 ret
= fwrite(zeros
, 1, 4 - (top
->binres
->size
& 0x03), fo
);
159 if(ret
!= 4 - (top
->binres
->size
& 0x03))
162 error("Error writing %s", outname
);
170 *****************************************************************************
171 * Function : write_s_res
172 * Syntax : void write_s_res(FILE *fp, res_t *res)
177 *****************************************************************************
179 #define BYTESPERLINE 8
180 void write_s_res(FILE *fp
, res_t
*res
)
182 int idx
= res
->dataidx
;
184 int rest
= (end
- idx
) % BYTESPERLINE
;
185 int lines
= (end
- idx
) / BYTESPERLINE
;
188 for(i
= 0 ; i
< lines
; i
++)
190 fprintf(fp
, "\t.byte\t");
191 for(j
= 0; j
< BYTESPERLINE
; j
++, idx
++)
193 fprintf(fp
, "0x%02x%s", res
->data
[idx
] & 0xff,
194 j
== BYTESPERLINE
-1 ? "" : ", ");
200 fprintf(fp
, "\t.byte\t");
201 for(j
= 0; j
< rest
; j
++, idx
++)
203 fprintf(fp
, "0x%02x%s", res
->data
[idx
] & 0xff,
204 j
== rest
-1 ? "" : ", ");
211 *****************************************************************************
212 * Function : write_name_str
213 * Syntax : void write_name_str(FILE *fp, name_id_t *nid)
217 * Remarks : One level self recursive for string type conversion
218 *****************************************************************************
220 void write_name_str(FILE *fp
, name_id_t
*nid
)
223 assert(nid
->type
== name_str
);
225 if(!win32
&& nid
->name
.s_name
->type
== str_char
)
227 res
.size
= strlen(nid
->name
.s_name
->str
.cstr
);
229 error("Can't write strings larger than 254 bytes");
231 internal_error(__FILE__
, __LINE__
, "Attempt to write empty string");
233 res
.data
= (char *)xmalloc(res
.size
+ 1);
234 res
.data
[0] = (char)res
.size
;
235 res
.size
++; /* We need to write the lenth byte as well */
236 strcpy(res
.data
+1, nid
->name
.s_name
->str
.cstr
);
237 write_s_res(fp
, &res
);
240 else if(!win32
&& nid
->name
.s_name
->type
== str_unicode
)
245 lnid
.type
= name_str
;
246 lnid
.name
.s_name
= &str
;
248 str
.str
.cstr
= dupwstr2cstr(nid
->name
.s_name
->str
.wstr
);
249 write_name_str(fp
, &lnid
);
252 else if(win32
&& nid
->name
.s_name
->type
== str_char
)
257 lnid
.type
= name_str
;
258 lnid
.name
.s_name
= &str
;
259 str
.type
= str_unicode
;
260 str
.str
.wstr
= dupcstr2wstr(nid
->name
.s_name
->str
.cstr
);
261 write_name_str(fp
, &lnid
);
264 else if(win32
&& nid
->name
.s_name
->type
== str_unicode
)
266 res
.size
= wstrlen(nid
->name
.s_name
->str
.wstr
);
268 error("Can't write strings larger than 65534 bytes");
270 internal_error(__FILE__
, __LINE__
, "Attempt to write empty string");
272 res
.data
= (char *)xmalloc((res
.size
+ 1) * 2);
273 ((short *)res
.data
)[0] = (short)res
.size
;
274 wstrcpy((short *)(res
.data
+2), nid
->name
.s_name
->str
.wstr
);
275 res
.size
*= 2; /* Function writes bytes, not shorts... */
276 res
.size
+= 2; /* We need to write the length word as well */
277 write_s_res(fp
, &res
);
282 internal_error(__FILE__
, __LINE__
, "Hmm, requested to write a string of unknown type %d",
283 nid
->name
.s_name
->type
);
288 *****************************************************************************
289 * Function : compare_name_id
290 * Syntax : int compare_name_id(name_id_t *n1, name_id_t *n2)
295 *****************************************************************************
297 int compare_name_id(name_id_t
*n1
, name_id_t
*n2
)
299 if(n1
->type
== name_ord
&& n2
->type
== name_ord
)
301 return n1
->name
.i_name
- n2
->name
.i_name
;
303 else if(n1
->type
== name_str
&& n2
->type
== name_str
)
305 if(n1
->name
.s_name
->type
== str_char
306 && n2
->name
.s_name
->type
== str_char
)
308 return strcasecmp(n1
->name
.s_name
->str
.cstr
, n2
->name
.s_name
->str
.cstr
);
310 else if(n1
->name
.s_name
->type
== str_unicode
311 && n2
->name
.s_name
->type
== str_unicode
)
313 return wstricmp(n1
->name
.s_name
->str
.wstr
, n2
->name
.s_name
->str
.wstr
);
317 internal_error(__FILE__
, __LINE__
, "Can't yet compare strings of mixed type");
320 else if(n1
->type
== name_ord
&& n2
->type
== name_str
)
322 else if(n1
->type
== name_str
&& n2
->type
== name_ord
)
325 internal_error(__FILE__
, __LINE__
, "Comparing name-ids with unknown types (%d, %d)",
328 return 0; /* Keep the compiler happy */
332 *****************************************************************************
333 * Function : find_counter
334 * Syntax : res_count_t *find_counter(name_id_t *type)
339 *****************************************************************************
341 res_count_t
*find_counter(name_id_t
*type
)
344 for(i
= 0; i
< rccount
; i
++)
346 if(!compare_name_id(type
, &(rcarray
[i
].type
)))
353 *****************************************************************************
354 * Function : count_resources
355 * Syntax : res_count_t *count_resources(resource_t *top)
359 * Remarks : The whole lot is converted into arrays because they are
360 * easy sortable. Makes the lot almost unreadable, but it
361 * works (I hope). Basically you have to keep in mind that
362 * the lot is a three-dimensional structure for win32 and a
363 * two-dimensional structure for win16.
364 *****************************************************************************
366 #define RCT(v) (*((resource_t **)(v)))
367 /* qsort sorting function */
368 int sort_name_id(const void *e1
, const void *e2
)
370 return compare_name_id(RCT(e1
)->name
, RCT(e2
)->name
);
373 int sort_language(const void *e1
, const void *e2
)
375 assert((RCT(e1
)->lan
) != NULL
);
376 assert((RCT(e2
)->lan
) != NULL
);
378 return MAKELANGID(RCT(e1
)->lan
->id
, RCT(e1
)->lan
->sub
)
379 - MAKELANGID(RCT(e2
)->lan
->id
, RCT(e2
)->lan
->sub
);
382 #define RCT(v) ((res_count_t *)(v))
383 int sort_type(const void *e1
, const void *e2
)
385 return compare_name_id(&(RCT(e1
)->type
), &(RCT(e2
)->type
));
389 void count_resources(resource_t
*top
)
396 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
403 nid
.name
.i_name
= WRC_RT_DIALOG
;
407 nid
.name
.i_name
= WRC_RT_MENU
;
411 nid
= *(rsc
->res
.usr
->type
);
414 nid
.name
.i_name
= rsc
->type
;
418 if((rcp
= find_counter(&nid
)) == NULL
)
420 /* Count the number of uniq ids and names */
422 if(nid
.type
== name_ord
)
429 rcarray
= (res_count_t
*)xmalloc(sizeof(res_count_t
));
431 rcarray
[0].count
= 1;
432 rcarray
[0].type
= nid
;
433 rcarray
[0].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
434 rcarray
[0].rscarray
[0] = rsc
;
439 rcarray
= (res_count_t
*)xrealloc(rcarray
, rccount
* sizeof(res_count_t
));
440 rcarray
[rccount
-1].count
= 1;
441 rcarray
[rccount
-1].type
= nid
;
442 rcarray
[rccount
-1].rscarray
= (resource_t
**)xmalloc(sizeof(resource_t
*));
443 rcarray
[rccount
-1].rscarray
[0] = rsc
;
449 rcp
->rscarray
= (resource_t
**)xrealloc(rcp
->rscarray
, rcp
->count
* sizeof(resource_t
*));
450 rcp
->rscarray
[rcp
->count
-1] = rsc
;
456 /* We're done, win16 requires no special sorting */
460 /* We now have a unsorted list of types with an array of res_count_t
461 * in rcarray[0..rccount-1]. And we have names of one type in the
462 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
463 * The list needs to be sorted for win32's top level tree structure.
468 qsort(rcarray
, rccount
, sizeof(rcarray
[0]), sort_type
);
470 /* Now sort the name-id arrays */
471 for(i
= 0; i
< rccount
; i
++)
473 if(rcarray
[i
].count
> 1)
474 qsort(rcarray
[i
].rscarray
, rcarray
[i
].count
, sizeof(rcarray
[0].rscarray
[0]), sort_name_id
);
477 /* Now split the name-id arrays into name/language
478 * subs. Don't look at the awfull expressions...
479 * We do this by taking the array elements out of rscarray and putting
480 * together a new array in rsc32array.
482 for(i
= 0; i
< rccount
; i
++)
486 assert(rcarray
[i
].count
>= 1);
488 /* rcap points to the current type we are dealing with */
489 rcap
= &(rcarray
[i
]);
491 /* Insert the first name-id */
492 rcap
->rsc32array
= (res32_count_t
*)xmalloc(sizeof(res32_count_t
));
494 rcap
->rsc32array
[0].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
495 rcap
->rsc32array
[0].count
= 1;
496 rcap
->rsc32array
[0].rsc
[0] = rcap
->rscarray
[0];
497 if(rcap
->rscarray
[0]->name
->type
== name_ord
)
499 rcap
->n_id_entries
= 1;
500 rcap
->n_name_entries
= 0;
504 rcap
->n_id_entries
= 0;
505 rcap
->n_name_entries
= 1;
508 /* Now loop over the resting resources of the current type
509 * to find duplicate names (which should have different
512 for(j
= 1; j
< rcap
->count
; j
++)
514 res32_count_t
*r32cp
;
516 /* r32cp points to the current res32_count structure
517 * that holds the resource name we are processing.
519 r32cp
= &(rcap
->rsc32array
[rcap
->count32
-1]);
521 if(!compare_name_id(r32cp
->rsc
[0]->name
, rcarray
[i
].rscarray
[j
]->name
))
523 /* Names are the same, add to list */
525 r32cp
->rsc
= (resource_t
**)xrealloc(r32cp
->rsc
, r32cp
->count
* sizeof(resource_t
*));
526 r32cp
->rsc
[r32cp
->count
-1] = rcap
->rscarray
[j
];
530 /* New name-id, sort the old one by
531 * language and create new list
534 qsort(r32cp
->rsc
, r32cp
->count
, sizeof(r32cp
->rsc
[0]), sort_language
);
536 rcap
->rsc32array
= (res32_count_t
*)xrealloc(rcap
->rsc32array
, rcap
->count32
* sizeof(res32_count_t
));
537 rcap
->rsc32array
[rcap
->count32
-1].rsc
= (resource_t
**)xmalloc(sizeof(resource_t
*));
538 rcap
->rsc32array
[rcap
->count32
-1].count
= 1;
539 rcap
->rsc32array
[rcap
->count32
-1].rsc
[0] = rcap
->rscarray
[j
];
541 if(rcap
->rscarray
[j
]->name
->type
== name_ord
)
542 rcap
->n_id_entries
++;
544 rcap
->n_name_entries
++;
547 /* Also sort the languages of the last name group */
548 if(rcap
->rsc32array
[rcap
->count32
-1].count
> 1)
549 qsort(rcap
->rsc32array
[rcap
->count32
-1].rsc
,
550 rcap
->rsc32array
[rcap
->count32
-1].count
,
551 sizeof(rcap
->rsc32array
[rcap
->count32
-1].rsc
[0]),
557 *****************************************************************************
558 * Function : write_pe_segment
559 * Syntax : void write_pe_segment(FILE *fp, resource_t *top)
564 *****************************************************************************
566 void write_pe_segment(FILE *fp
, resource_t
*top
)
570 fprintf(fp
, "\t.align\t4\n");
571 fprintf(fp
, "%s%s:\n", prefix
, _PEResTab
);
572 fprintf(fp
, "\t.globl\t%s%s\n", prefix
, _PEResTab
);
574 fprintf(fp
, "\t.long\t0\n");
575 /* Time/Date stamp */
576 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
);
578 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
579 /* # of id entries, # of name entries */
580 fprintf(fp
, "\t.word\t%d, %d\n", n_name_entries
, n_id_entries
);
582 /* Write the type level of the tree */
583 for(i
= 0; i
< rccount
; i
++)
591 if(rcp
->type
.type
== name_ord
)
592 fprintf(fp
, "\t.long\t%d\n", rcp
->type
.name
.i_name
);
595 char *name
= prep_nid_for_label(&(rcp
->type
));
596 fprintf(fp
, "\t.long\t(%s_%s_typename - %s%s) | 0x80000000\n",
603 label
= prep_nid_for_label(&(rcp
->type
));
604 fprintf(fp
, "\t.long\t(.L%s - %s%s) | 0x80000000\n",
610 /* Write the name level of the tree */
612 for(i
= 0; i
< rccount
; i
++)
621 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
622 fprintf(fp
, ".L%s:\n", typelabel
);
624 fprintf(fp
, "\t.long\t0\n"); /* Flags */
625 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
); /* TimeDate */
626 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
627 fprintf(fp
, "\t.word\t%d, %d\n", rcp
->n_name_entries
, rcp
->n_id_entries
);
628 for(j
= 0; j
< rcp
->count32
; j
++)
630 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
632 if(rsc
->name
->type
== name_ord
)
633 fprintf(fp
, "\t.long\t%d\n", rsc
->name
->name
.i_name
);
636 fprintf(fp
, "\t.long\t(%s%s_name - %s%s) | 0x80000000\n",
642 /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
643 * put the offset to the resource data entry.
644 * ?? Is unescaping worth while ??
647 namelabel
= prep_nid_for_label(rsc
->name
);
648 fprintf(fp
, "\t.long\t(.L%s_%s - %s%s) | 0x80000000\n",
657 /* Write the language level of the tree */
659 for(i
= 0; i
< rccount
; i
++)
667 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
669 for(j
= 0; j
< rcp
->count32
; j
++)
671 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
674 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
675 fprintf(fp
, ".L%s_%s:\n", typelabel
, namelabel
);
677 fprintf(fp
, "\t.long\t0\n"); /* Flags */
678 fprintf(fp
, "\t.long\t0x%08lx\n", (long)now
); /* TimeDate */
679 fprintf(fp
, "\t.long\t0\n"); /* FIXME: must version be filled out? */
680 fprintf(fp
, "\t.word\t0, %d\n", r32cp
->count
);
682 for(k
= 0; k
< r32cp
->count
; k
++)
684 resource_t
*rsc
= r32cp
->rsc
[k
];
685 assert(rsc
->lan
!= NULL
);
687 fprintf(fp
, "\t.long\t0x%08x\n", rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
689 fprintf(fp
, "\t.long\t.L%s_%s_%d - %s%s\n",
692 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0,
701 /* Write the resource table itself */
702 fprintf(fp
, "%s_ResourceDirectory:\n", prefix
);
703 fprintf(fp
, "\t.globl\t%s_ResourceDirectory\n", prefix
);
706 for(i
= 0; i
< rccount
; i
++)
714 typelabel
= xstrdup(prep_nid_for_label(&(rcp
->type
)));
716 for(j
= 0; j
< rcp
->count32
; j
++)
718 res32_count_t
*r32cp
= &(rcp
->rsc32array
[j
]);
721 namelabel
= xstrdup(prep_nid_for_label(r32cp
->rsc
[0]->name
));
723 for(k
= 0; k
< r32cp
->count
; k
++)
725 resource_t
*rsc
= r32cp
->rsc
[k
];
727 assert(rsc
->lan
!= NULL
);
729 fprintf(fp
, ".L%s_%s_%d:\n",
732 rsc
->lan
? MAKELANGID(rsc
->lan
->id
, rsc
->lan
->sub
) : 0);
735 fprintf(fp
, "\t.long\t%s%s_data - %s%s\n",
741 fprintf(fp
, "\t.long\t%d\n",
742 rsc
->binres
->size
- rsc
->binres
->dataidx
);
744 fprintf(fp
, "\t.long\t%ld\n", codepage
);
746 fprintf(fp
, "\t.long\t0\n");
757 *****************************************************************************
758 * Function : write_ne_segment
759 * Syntax : void write_ne_segment(FILE *fp, resource_t *top)
764 *****************************************************************************
766 void write_ne_segment(FILE *fp
, resource_t
*top
)
770 fprintf(fp
, "\t.align\t4\n");
771 fprintf(fp
, "%s%s:\n", prefix
, _NEResTab
);
772 fprintf(fp
, "\t.globl\t%s%s\n", prefix
, _NEResTab
);
775 fprintf(fp
, "\t.word\t%d\n", alignment_pwr
);
778 for(i
= 0; i
< rccount
; i
++)
780 res_count_t
*rcp
= &rcarray
[i
];
783 if(rcp
->type
.type
== name_ord
)
784 fprintf(fp
, "\t.word\t0x%04x\n", rcp
->type
.name
.i_name
| 0x8000);
786 fprintf(fp
, "\t.word\t%s_%s_typename - %s%s\n",
788 rcp
->type
.name
.s_name
->str
.cstr
,
792 fprintf(fp
, "\t.word\t%d\n", rcp
->count
);
794 fprintf(fp
, "\t.long\t0\n");
796 for(j
= 0; j
< rcp
->count
; j
++)
800 * The offset is relative to the beginning of the NE resource segment
801 * and _NOT_ to the file-beginning. This is because we do not have a
802 * file based resource, but a simulated NE segment. The offset _is_
803 * scaled by the AlignShift field.
804 * All other things are as the MS doc describes (alignment etc.)
807 fprintf(fp
, "\t.word\t(%s%s_data - %s%s) >> %d\n",
809 rcp
->rscarray
[j
]->c_name
,
814 fprintf(fp
, "\t.word\t%d\n",
815 rcp
->rscarray
[j
]->binres
->size
- rcp
->rscarray
[j
]->binres
->dataidx
);
817 fprintf(fp
, "\t.word\t0x%04x\n", (WORD
)rcp
->rscarray
[j
]->memopt
);
819 if(rcp
->rscarray
[j
]->name
->type
== name_ord
)
820 fprintf(fp
, "\t.word\t0x%04x\n", rcp
->rscarray
[j
]->name
->name
.i_name
| 0x8000);
822 fprintf(fp
, "\t.word\t%s%s_name - %s%s\n",
824 rcp
->rscarray
[j
]->c_name
,
827 /* Handle and Usage */
828 fprintf(fp
, "\t.word\t0, 0\n");
832 fprintf(fp
, "\t.word\t0\n");
836 *****************************************************************************
837 * Function : write_rsc_names
838 * Syntax : void write_rsc_names(FILE *fp, resource_t *top)
843 *****************************************************************************
845 void write_rsc_names(FILE *fp
, resource_t
*top
)
851 /* Write the names */
853 for(i
= 0; i
< rccount
; i
++)
859 if(rcp
->type
.type
== name_str
)
861 char *name
= prep_nid_for_label(&(rcp
->type
));
862 fprintf(fp
, "%s_%s_typename:\n",
865 write_name_str(fp
, &(rcp
->type
));
868 for(j
= 0; j
< rcp
->count32
; j
++)
870 resource_t
*rsc
= rcp
->rsc32array
[j
].rsc
[0];
872 if(rsc
->name
->type
== name_str
)
874 fprintf(fp
, "%s%s_name:\n",
877 write_name_str(fp
, rsc
->name
);
885 for(i
= 0; i
< rccount
; i
++)
887 res_count_t
*rcp
= &rcarray
[i
];
889 for(j
= 0; j
< rcp
->count
; j
++)
891 if(rcp
->type
.type
== name_str
)
893 fprintf(fp
, "%s_%s_typename:\n",
895 rcp
->type
.name
.s_name
->str
.cstr
);
896 write_name_str(fp
, &(rcp
->type
));
898 if(rcp
->rscarray
[j
]->name
->type
== name_str
)
900 fprintf(fp
, "%s%s_name:\n",
902 rcp
->rscarray
[j
]->c_name
);
903 write_name_str(fp
, rcp
->rscarray
[j
]->name
);
909 /* This is to end the NE resource table */
911 fprintf(fp
, "\t.byte\t0\n");
918 *****************************************************************************
919 * Function : write_s_file
920 * Syntax : void write_s_file(char *outname, resource_t *top)
922 * outname - Filename to write to
923 * top - The resource-tree to convert
927 *****************************************************************************
929 void write_s_file(char *outname
, resource_t
*top
)
934 fo
= fopen(outname
, "wt");
937 error("Could not open %s\n", outname
);
947 fprintf(fo
, s_file_head_str
, input_name
? input_name
: "stdin",
951 /* Get an idea how many we have and restructure the tables */
952 count_resources(top
);
954 /* First write the segment tables */
958 write_pe_segment(fo
, top
);
960 write_ne_segment(fo
, top
);
964 write_rsc_names(fo
, top
);
967 fprintf(fo
, ".LResTabEnd:\n");
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 a resource descriptor for built-in and elf-dlls */
991 fprintf(fo
, "\t.align\t4\n");
992 fprintf(fo
, "%s_ResourceDescriptor:\n", prefix
);
993 fprintf(fo
, "\t.globl\t%s_ResourceDescriptor\n", prefix
);
994 fprintf(fo
, "%s_ResourceTable:\n", prefix
);
996 fprintf(fo
, "\t.globl\t%s_ResourceTable\n", prefix
);
997 fprintf(fo
, "\t.long\t%s%s\n", prefix
, win32
? _PEResTab
: _NEResTab
);
998 fprintf(fo
, "%s_NumberOfResources:\n", prefix
);
1000 fprintf(fo
, "\t.globl\t%s_NumberOfResources\n", prefix
);
1001 fprintf(fo
, "\t.long\t%d\n", direntries
);
1002 fprintf(fo
, "%s_ResourceSectionSize:\n", prefix
);
1004 fprintf(fo
, "\t.globl\t%s_ResourceSectionSize\n", prefix
);
1005 fprintf(fo
, "\t.long\t.LResTabEnd - %s%s\n", prefix
, win32
? _PEResTab
: _NEResTab
);
1008 fprintf(fo
, "%s_ResourcesEntries:\n", prefix
);
1010 fprintf(fo
, "\t.globl\t%s_ResourcesEntries\n", prefix
);
1011 fprintf(fo
, "\t.long\t%s_ResourceDirectory\n", prefix
);
1018 /* Write the indirection structures */
1019 fprintf(fo
, "\n/* Resource indirection structures */\n\n");
1020 fprintf(fo
, "\t.align\t4\n");
1021 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
1024 char *type_name
= NULL
;
1035 type
= WRC_RT_DIALOG
;
1038 assert(rsc
->res
.usr
->type
!= NULL
);
1039 type_name
= prep_nid_for_label(rsc
->res
.usr
->type
);
1047 * This follows a structure like:
1048 * struct wrc_resource {
1052 * RSCNAME *typename;
1056 * The 'RSCNAME' is a pascal-style string where the
1057 * first byte/word denotes the size and the rest the string
1060 fprintf(fo
, "%s%s:\n", prefix
, rsc
->c_name
);
1062 fprintf(fo
, "\t.globl\t%s%s\n", prefix
, rsc
->c_name
);
1063 fprintf(fo
, "\t.long\t%d, %s%s%s, %d, %s%s%s%s, %s%s_data, %d\n",
1064 rsc
->name
->type
== name_ord
? rsc
->name
->name
.i_name
: 0,
1065 rsc
->name
->type
== name_ord
? "0" : prefix
,
1066 rsc
->name
->type
== name_ord
? "" : rsc
->c_name
,
1067 rsc
->name
->type
== name_ord
? "" : "_name",
1069 type
? "0" : prefix
,
1071 type
? "" : type_name
,
1072 type
? "" : "_typename",
1075 rsc
->binres
->size
- rsc
->binres
->dataidx
);
1080 /* Write the indirection table */
1081 fprintf(fo
, "/* Resource indirection table */\n\n");
1082 fprintf(fo
, "\t.align\t4\n");
1083 fprintf(fo
, "%s%s:\n", prefix
, _ResTable
);
1084 fprintf(fo
, "\t.globl\t%s%s\n", prefix
, _ResTable
);
1085 for(rsc
= top
; rsc
; rsc
= rsc
->next
)
1087 fprintf(fo
, "\t.long\t%s%s\n", prefix
, rsc
->c_name
);
1089 fprintf(fo
, "\t.long\t0\n");
1094 fprintf(fo
, s_file_autoreg_str
, prefix
, _ResTable
);
1096 fprintf(fo
, s_file_tail_str
);
1101 *****************************************************************************
1102 * Function : write_h_file
1103 * Syntax : void write_h_file(char *outname, resource_t *top)
1105 * outname - Filename to write to
1106 * top - The resource-tree to convert
1110 *****************************************************************************
1112 void write_h_file(char *outname
, resource_t
*top
)
1118 #ifdef NEED_UNDERSCORE_PREFIX
1119 h_prefix
= prefix
+ 1;
1124 fo
= fopen(outname
, "wt");
1127 error("Could not open %s\n", outname
);
1131 fprintf(fo
, h_file_head_str
, input_name
? input_name
: "stdin",
1132 cmdline
, ctime(&now
), (long)now
, (long)now
);
1134 /* First write the segment tables reference */
1137 fprintf(fo
, "extern %schar %s%s[];\n\n",
1138 constant
? "const " : "",
1140 win32
? _PEResTab
: _NEResTab
);
1143 /* Write the resource data */
1144 for(rsc
= top
; global
&& rsc
; rsc
= rsc
->next
)
1149 fprintf(fo
, "extern %schar %s%s_data[];\n",
1150 constant
? "const " : "",
1160 /* Write the indirection structures */
1161 for(rsc
= top
; global
&& rsc
; rsc
= rsc
->next
)
1163 fprintf(fo
, "extern %swrc_resource%d_t %s%s;\n",
1164 constant
? "const " : "",
1173 /* Write the indirection table */
1174 fprintf(fo
, "extern %swrc_resource%d_t %s%s[];\n\n",
1175 constant
? "const " : "",
1181 fprintf(fo
, h_file_tail_str
);