SHMapPIDLToSystemImageListIndex try's to determine and load the exact
[wine/dcerpc.git] / tools / wrc / writeres.c
blobf02d39f4557e47c53720edfdb0d1dd90ecaefd60
1 /*
2 * Write .res, .s and .h file(s) from a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <assert.h>
12 #include <time.h>
14 #include <config.h>
15 #include "wrc.h"
16 #include "writeres.h"
17 #include "genres.h"
18 #include "newstruc.h"
19 #include "utils.h"
21 #ifdef NEED_UNDERSCORE_PREFIX
22 char Underscore[] = "_";
23 #else
24 char Underscore[] = "";
25 #endif
27 char s_file_head_str[] =
28 "#\n"
29 "# This file is generated with wrc version " WRC_FULLVERSION ". Do not edit!\n"
30 "# Source : %s\n"
31 "# Cmdline: %s\n"
32 "# Date : %s"
33 "#\n\n"
34 "\t.data\n\n"
37 char s_file_tail_str[] =
38 "# <eof>\n\n"
41 char s_file_autoreg_str[] =
42 "\t.text\n"
43 ".LAuto_Register:\n"
44 "\tpushl\t$%s%s\n"
45 #ifdef NEED_UNDERSCORE_PREFIX
46 "\tcall\t_LIBRES_RegisterResources\n"
47 #else
48 "\tcall\tLIBRES_RegisterResources\n"
49 #endif
50 "\taddl\t$4,%%esp\n"
51 "\tret\n\n"
52 "\t.section .ctors,\"aw\"\n"
53 "\t.long\t.LAuto_Register\n\n"
56 char h_file_head_str[] =
57 "/*\n"
58 " * This file is generated with wrc version " WRC_FULLVERSION ". Do not edit!\n"
59 " * Source : %s\n"
60 " * Cmdline: %s\n"
61 " * Date : %s"
62 " */\n\n"
63 "#ifndef __%08x_H\n" /* This becomes the data of compile */
64 "#define __%08x_H\n\n"
65 "#ifndef __WRC_RSC_H\n"
66 "#include <wrc_rsc.h>\n"
67 "#endif\n\n"
70 char h_file_tail_str[] =
71 "#endif\n"
72 "/* <eof> */\n\n"
75 char _NEResTab[] = "_NEResTab";
76 char _PEResTab[] = "_PEResTab";
77 char _ResTable[] = "_ResTable";
79 res_count_t *rcarray = NULL;
80 int rccount = 0;
81 int n_id_entries = 0;
82 int n_name_entries = 0;
84 time_t now;
87 *****************************************************************************
88 * Function : write_resfile
89 * Syntax : void write_resfile(char *outname, resource_t *top)
90 * Input :
91 * outname - Filename to write to
92 * top - The resource-tree to convert
93 * Output :
94 * Description :
95 * Remarks :
96 *****************************************************************************
98 void write_resfile(char *outname, resource_t *top)
100 FILE *fo;
101 int ret;
102 char zeros[3] = {0, 0, 0};
104 fo = fopen(outname, "wb");
105 if(!fo)
107 error("Could not open %s\n", outname);
110 if(win32)
112 /* Put an empty resource first to signal win32 format */
113 res_t *res = new_res();
114 put_dword(res, 0); /* ResSize */
115 put_dword(res, 0x00000020); /* HeaderSize */
116 put_word(res, 0xffff); /* ResType */
117 put_word(res, 0);
118 put_word(res, 0xffff); /* ResName */
119 put_word(res, 0);
120 put_dword(res, 0); /* DataVersion */
121 put_word(res, 0); /* Memory options */
122 put_word(res, 0); /* Language */
123 put_dword(res, 0); /* Version */
124 put_dword(res, 0); /* Charateristics */
125 ret = fwrite(res->data, 1, res->size, fo);
126 if(ret != res->size)
128 fclose(fo);
129 error("Error writing %s", outname);
131 free(res);
134 for(; top; top = top->next)
136 if(!top->binres)
137 continue;
139 ret = fwrite(top->binres->data, 1, top->binres->size, fo);
140 if(ret != top->binres->size)
142 fclose(fo);
143 error("Error writing %s", outname);
145 if(win32 && (top->binres->size & 0x03))
147 /* Write padding */
148 ret = fwrite(zeros, 1, 4 - (top->binres->size & 0x03), fo);
149 if(ret != 4 - (top->binres->size & 0x03))
151 fclose(fo);
152 error("Error writing %s", outname);
156 fclose(fo);
160 *****************************************************************************
161 * Function : write_s_res
162 * Syntax : void write_s_res(FILE *fp, res_t *res)
163 * Input :
164 * Output :
165 * Description :
166 * Remarks :
167 *****************************************************************************
169 #define BYTESPERLINE 8
170 void write_s_res(FILE *fp, res_t *res)
172 int idx = res->dataidx;
173 int end = res->size;
174 int rest = (end - idx) % BYTESPERLINE;
175 int lines = (end - idx) / BYTESPERLINE;
176 int i, j;
178 for(i = 0 ; i < lines; i++)
180 fprintf(fp, "\t.byte\t");
181 for(j = 0; j < BYTESPERLINE; j++, idx++)
183 fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
184 j == BYTESPERLINE-1 ? "" : ", ");
186 fprintf(fp, "\n");
188 if(rest)
190 fprintf(fp, "\t.byte\t");
191 for(j = 0; j < rest; j++, idx++)
193 fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
194 j == rest-1 ? "" : ", ");
196 fprintf(fp, "\n");
201 *****************************************************************************
202 * Function : write_name_str
203 * Syntax : void write_name_str(FILE *fp, name_id_t *nid)
204 * Input :
205 * Output :
206 * Description :
207 * Remarks : One level self recursive for string type conversion
208 *****************************************************************************
210 void write_name_str(FILE *fp, name_id_t *nid)
212 res_t res;
213 assert(nid->type == name_str);
215 if(!win32 && nid->name.s_name->type == str_char)
217 res.size = strlen(nid->name.s_name->str.cstr);
218 if(res.size > 254)
219 error("Can't write strings larger than 254 bytes");
220 if(res.size == 0)
221 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
222 res.dataidx = 0;
223 res.data = (char *)xmalloc(res.size + 1);
224 res.data[0] = (char)res.size;
225 res.size++; /* We need to write the lenth byte as well */
226 strcpy(res.data+1, nid->name.s_name->str.cstr);
227 write_s_res(fp, &res);
228 free(res.data);
230 else if(!win32 && nid->name.s_name->type == str_unicode)
232 name_id_t lnid;
233 string_t str;
235 lnid.type = name_str;
236 lnid.name.s_name = &str;
237 str.type = str_char;
238 str.str.cstr = dupwstr2cstr(nid->name.s_name->str.wstr);
239 write_name_str(fp, &lnid);
240 free(str.str.cstr);
242 else if(win32 && nid->name.s_name->type == str_char)
244 name_id_t lnid;
245 string_t str;
247 lnid.type = name_str;
248 lnid.name.s_name = &str;
249 str.type = str_unicode;
250 str.str.wstr = dupcstr2wstr(nid->name.s_name->str.cstr);
251 write_name_str(fp, &lnid);
252 free(str.str.wstr);
254 else if(win32 && nid->name.s_name->type == str_unicode)
256 res.size = wstrlen(nid->name.s_name->str.wstr);
257 if(res.size > 65534)
258 error("Can't write strings larger than 65534 bytes");
259 if(res.size == 0)
260 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
261 res.dataidx = 0;
262 res.data = (char *)xmalloc((res.size + 1) * 2);
263 ((short *)res.data)[0] = (short)res.size;
264 wstrcpy((short *)(res.data+2), nid->name.s_name->str.wstr);
265 res.size *= 2; /* Function writes bytes, not shorts... */
266 res.size += 2; /* We need to write the length word as well */
267 write_s_res(fp, &res);
268 free(res.data);
270 else
272 internal_error(__FILE__, __LINE__, "Hmm, requested to write a string of unknown type %d",
273 nid->name.s_name->type);
278 *****************************************************************************
279 * Function : compare_name_id
280 * Syntax : int compare_name_id(name_id_t *n1, name_id_t *n2)
281 * Input :
282 * Output :
283 * Description :
284 * Remarks :
285 *****************************************************************************
287 int compare_name_id(name_id_t *n1, name_id_t *n2)
289 if(n1->type == name_ord && n2->type == name_ord)
291 return n1->name.i_name - n2->name.i_name;
293 else if(n1->type == name_str && n2->type == name_str)
295 if(n1->name.s_name->type == str_char
296 && n2->name.s_name->type == str_char)
298 return stricmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr);
300 else if(n1->name.s_name->type == str_unicode
301 && n2->name.s_name->type == str_unicode)
303 return wstricmp(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr);
305 else
307 internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type");
310 else if(n1->type == name_ord && n2->type == name_str)
311 return -1;
312 else if(n1->type == name_str && n2->type == name_ord)
313 return 1;
314 else
315 internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)",
316 n1->type, n2->type);
318 return 0; /* Keep the compiler happy */
322 *****************************************************************************
323 * Function : find_counter
324 * Syntax : res_count_t *find_counter(name_id_t *type)
325 * Input :
326 * Output :
327 * Description :
328 * Remarks :
329 *****************************************************************************
331 res_count_t *find_counter(name_id_t *type)
333 int i;
334 for(i = 0; i < rccount; i++)
336 if(!compare_name_id(type, &(rcarray[i].type)))
337 return &rcarray[i];
339 return NULL;
343 *****************************************************************************
344 * Function : count_resources
345 * Syntax : res_count_t *count_resources(resource_t *top)
346 * Input :
347 * Output :
348 * Description :
349 * Remarks : The whole lot is converted into arrays because they are
350 * easy sortable. Makes the lot almost unreadable, but it
351 * works (I hope). Basically you have to keep in mind that
352 * the lot is a three-dimensional structure for win32 and a
353 * two-dimensional structure for win16.
354 *****************************************************************************
356 #define RCT(v) (*((resource_t **)(v)))
357 /* qsort sorting function */
358 int sort_name_id(const void *e1, const void *e2)
360 return compare_name_id(RCT(e1)->name, RCT(e2)->name);
363 int sort_language(const void *e1, const void *e2)
365 assert((RCT(e1)->lan) != NULL);
366 assert((RCT(e2)->lan) != NULL);
368 return MAKELANGID(RCT(e1)->lan->id, RCT(e1)->lan->sub)
369 - MAKELANGID(RCT(e2)->lan->id, RCT(e2)->lan->sub);
371 #undef RCT
372 #define RCT(v) ((res_count_t *)(v))
373 int sort_type(const void *e1, const void *e2)
375 return compare_name_id(&(RCT(e1)->type), &(RCT(e2)->type));
377 #undef RCT
379 void count_resources(resource_t *top)
381 resource_t *rsc;
382 res_count_t *rcp;
383 name_id_t nid;
384 int i, j;
386 for(rsc = top; rsc; rsc = rsc->next)
388 if(!rsc->binres)
389 continue;
390 switch(rsc->type)
392 case res_dlgex:
393 nid.name.i_name = WRC_RT_DIALOG;
394 nid.type = name_ord;
395 break;
396 case res_menex:
397 nid.name.i_name = WRC_RT_MENU;
398 nid.type = name_ord;
399 break;
400 case res_usr:
401 nid = *(rsc->res.usr->type);
402 break;
403 default:
404 nid.name.i_name = rsc->type;
405 nid.type = name_ord;
408 if((rcp = find_counter(&nid)) == NULL)
410 /* Count the number of uniq ids and names */
412 if(nid.type == name_ord)
413 n_id_entries++;
414 else
415 n_name_entries++;
417 if(!rcarray)
419 rcarray = (res_count_t *)xmalloc(sizeof(res_count_t));
420 rccount = 1;
421 rcarray[0].count = 1;
422 rcarray[0].type = nid;
423 rcarray[0].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
424 rcarray[0].rscarray[0] = rsc;
426 else
428 rccount++;
429 rcarray = (res_count_t *)xrealloc(rcarray, rccount * sizeof(res_count_t));
430 rcarray[rccount-1].count = 1;
431 rcarray[rccount-1].type = nid;
432 rcarray[rccount-1].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
433 rcarray[rccount-1].rscarray[0] = rsc;
436 else
438 rcp->count++;
439 rcp->rscarray = (resource_t **)xrealloc(rcp->rscarray, rcp->count * sizeof(resource_t *));
440 rcp->rscarray[rcp->count-1] = rsc;
444 if(!win32)
446 /* We're done, win16 requires no special sorting */
447 return;
450 /* We now have a unsorted list of types with an array of res_count_t
451 * in rcarray[0..rccount-1]. And we have names of one type in the
452 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
453 * The list needs to be sorted for win32's top level tree structure.
456 /* Sort the types */
457 if(rccount > 1)
458 qsort(rcarray, rccount, sizeof(rcarray[0]), sort_type);
460 /* Now sort the name-id arrays */
461 for(i = 0; i < rccount; i++)
463 if(rcarray[i].count > 1)
464 qsort(rcarray[i].rscarray, rcarray[i].count, sizeof(rcarray[0].rscarray[0]), sort_name_id);
467 /* Now split the name-id arrays into name/language
468 * subs. Don't look at the awfull expressions...
469 * We do this by taking the array elements out of rscarray and putting
470 * together a new array in rsc32array.
472 for(i = 0; i < rccount; i++)
474 res_count_t *rcap;
476 assert(rcarray[i].count >= 1);
478 /* rcap points to the current type we are dealing with */
479 rcap = &(rcarray[i]);
481 /* Insert the first name-id */
482 rcap->rsc32array = (res32_count_t *)xmalloc(sizeof(res32_count_t));
483 rcap->count32 = 1;
484 rcap->rsc32array[0].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
485 rcap->rsc32array[0].count = 1;
486 rcap->rsc32array[0].rsc[0] = rcap->rscarray[0];
487 if(rcap->rscarray[0]->name->type == name_ord)
489 rcap->n_id_entries = 1;
490 rcap->n_name_entries = 0;
492 else
494 rcap->n_id_entries = 0;
495 rcap->n_name_entries = 1;
498 /* Now loop over the resting resources of the current type
499 * to find duplicate names (which should have different
500 * languages).
502 for(j = 1; j < rcap->count; j++)
504 res32_count_t *r32cp;
506 /* r32cp points to the current res32_count structure
507 * that holds the resource name we are processing.
509 r32cp = &(rcap->rsc32array[rcap->count32-1]);
511 if(!compare_name_id(r32cp->rsc[0]->name, rcarray[i].rscarray[j]->name))
513 /* Names are the same, add to list */
514 r32cp->count++;
515 r32cp->rsc = (resource_t **)xrealloc(r32cp->rsc, r32cp->count * sizeof(resource_t *));
516 r32cp->rsc[r32cp->count-1] = rcap->rscarray[j];
518 if(rcap->rscarray[j]->name->type == name_ord)
520 rcap->n_id_entries = 1;
521 rcap->n_name_entries = 0;
523 else
525 rcap->n_id_entries = 0;
526 rcap->n_name_entries = 1;
529 else
531 /* New name-id, sort the old one by
532 * language and create new list
534 if(r32cp->count > 1)
535 qsort(r32cp->rsc, r32cp->count, sizeof(r32cp->rsc[0]), sort_language);
536 rcap->count32++;
537 rcap->rsc32array = (res32_count_t*)xrealloc(rcap->rsc32array, rcap->count32 * sizeof(res32_count_t));
538 rcap->rsc32array[rcap->count32-1].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
539 rcap->rsc32array[rcap->count32-1].count = 1;
540 rcap->rsc32array[rcap->count32-1].rsc[0] = rcap->rscarray[j];
542 if(rcap->rscarray[j]->name->type == name_ord)
543 rcap->n_id_entries++;
544 else
545 rcap->n_name_entries++;
548 /* Also sort the languages of the last name group */
549 if(rcap->rsc32array[rcap->count32-1].count > 1)
550 qsort(rcap->rsc32array[rcap->count32-1].rsc,
551 rcap->rsc32array[rcap->count32-1].count,
552 sizeof(rcap->rsc32array[rcap->count32-1].rsc[0]),
553 sort_language);
558 *****************************************************************************
559 * Function : write_pe_segment
560 * Syntax : void write_pe_segment(FILE *fp, resource_t *top)
561 * Input :
562 * Output :
563 * Description :
564 * Remarks :
565 *****************************************************************************
567 void write_pe_segment(FILE *fp, resource_t *top)
569 int i;
571 fprintf(fp, "\t.align\t4\n");
572 fprintf(fp, "%s%s:\n", prefix, _PEResTab);
573 fprintf(fp, "\t.globl\t%s%s\n", prefix, _PEResTab);
574 /* Flags */
575 fprintf(fp, "\t.long\t0\n");
576 /* Time/Date stamp */
577 fprintf(fp, "\t.long\t0x%08lx\n", now);
578 /* Version */
579 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
580 /* # of id entries, # of name entries */
581 fprintf(fp, "\t.short\t%d, %d\n", n_name_entries, n_id_entries);
583 /* Write the type level of the tree */
584 for(i = 0; i < rccount; i++)
586 res_count_t *rcp;
587 char *label;
589 rcp = &rcarray[i];
591 /* TypeId */
592 if(rcp->type.type == name_ord)
593 fprintf(fp, "\t.long\t%d\n", rcp->type.name.i_name);
594 else
596 char *name = prep_nid_for_label(&(rcp->type));
597 fprintf(fp, "\t.long\t(%s_%s_typename - %s%s) | 0x80000000\n",
598 prefix,
599 name,
600 prefix,
601 _PEResTab);
603 /* Offset */
604 label = prep_nid_for_label(&(rcp->type));
605 fprintf(fp, "\t.long\t(.L%s - %s%s) | 0x80000000\n",
606 label,
607 prefix,
608 _PEResTab);
611 /* Write the name level of the tree */
613 for(i = 0; i < rccount; i++)
615 res_count_t *rcp;
616 char *typelabel;
617 char *namelabel;
618 int j;
620 rcp = &rcarray[i];
622 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
623 fprintf(fp, ".L%s:\n", typelabel);
625 fprintf(fp, "\t.long\t0\n"); /* Flags */
626 fprintf(fp, "\t.long\t0x%08lx\n", now); /* TimeDate */
627 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
628 fprintf(fp, "\t.short\t%d, %d\n", rcp->n_name_entries, rcp->n_id_entries);
629 for(j = 0; j < rcp->count32; j++)
631 resource_t *rsc = rcp->rsc32array[j].rsc[0];
632 /* NameId */
633 if(rsc->name->type == name_ord)
634 fprintf(fp, "\t.long\t%d\n", rsc->name->name.i_name);
635 else
637 fprintf(fp, "\t.long\t(%s%s_name - %s%s) | 0x80000000\n",
638 prefix,
639 rsc->c_name,
640 prefix,
641 _PEResTab);
643 /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
644 * put the offset to the resource data entry.
645 * ?? Is unescaping worth while ??
647 /* Offset */
648 namelabel = prep_nid_for_label(rsc->name);
649 fprintf(fp, "\t.long\t(.L%s_%s - %s%s) | 0x80000000\n",
650 typelabel,
651 namelabel,
652 prefix,
653 _PEResTab);
655 free(typelabel);
658 /* Write the language level of the tree */
660 for(i = 0; i < rccount; i++)
662 res_count_t *rcp;
663 char *namelabel;
664 char *typelabel;
665 int j;
667 rcp = &rcarray[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]);
673 int k;
675 namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
676 fprintf(fp, ".L%s_%s:\n", typelabel, namelabel);
678 fprintf(fp, "\t.long\t0\n"); /* Flags */
679 fprintf(fp, "\t.long\t0x%08lx\n", now); /* TimeDate */
680 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
681 fprintf(fp, "\t.short\t0, %d\n", r32cp->count);
683 for(k = 0; k < r32cp->count; k++)
685 resource_t *rsc = r32cp->rsc[k];
686 assert(rsc->lan != NULL);
687 /* LanguageId */
688 fprintf(fp, "\t.long\t0x%08x\n", rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
689 /* Offset */
690 fprintf(fp, "\t.long\t.L%s_%s_%d - %s%s\n",
691 typelabel,
692 namelabel,
693 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0,
694 prefix,
695 _PEResTab);
697 free(namelabel);
699 free(typelabel);
702 /* Write the resource table itself */
704 for(i = 0; i < rccount; i++)
706 res_count_t *rcp;
707 char *namelabel;
708 char *typelabel;
709 int j;
711 rcp = &rcarray[i];
712 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
714 for(j = 0; j < rcp->count32; j++)
716 res32_count_t *r32cp = &(rcp->rsc32array[j]);
717 int k;
719 namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
721 for(k = 0; k < r32cp->count; k++)
723 resource_t *rsc = r32cp->rsc[k];
725 assert(rsc->lan != NULL);
727 fprintf(fp, ".L%s_%s_%d:\n",
728 typelabel,
729 namelabel,
730 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
732 /* Data RVA */
733 fprintf(fp, "\t.long\t%s%s_data - %s%s\n",
734 prefix,
735 rsc->c_name,
736 prefix,
737 _PEResTab);
738 /* Size */
739 fprintf(fp, "\t.long\t%d\n",
740 rsc->binres->size - rsc->binres->dataidx);
741 /* CodePage */
742 fprintf(fp, "\t.long\t%ld\n", codepage);
743 /* Reserved */
744 fprintf(fp, "\t.long\t0\n");
746 free(namelabel);
748 free(typelabel);
751 fprintf(fp, "\t.align\t4\n");
752 fprintf(fp, "%s_ResourceDirectorySize:\n", Underscore);
753 fprintf(fp, "\t.globl\t%s_ResourceDirectorySize\n", Underscore);
754 fprintf(fp, "\t.long\t. - %s%s\n", prefix, _PEResTab);
758 *****************************************************************************
759 * Function : write_ne_segment
760 * Syntax : void write_ne_segment(FILE *fp, resource_t *top)
761 * Input :
762 * Output :
763 * Description :
764 * Remarks :
765 *****************************************************************************
767 void write_ne_segment(FILE *fp, resource_t *top)
769 int i, j;
771 fprintf(fp, "\t.align\t4\n");
772 fprintf(fp, "%s%s:\n", prefix, _NEResTab);
773 fprintf(fp, "\t.globl\t%s%s\n", prefix, _NEResTab);
775 /* AlignmentShift */
776 fprintf(fp, "\t.short\t%d\n", alignment_pwr);
778 /* TypeInfo */
779 for(i = 0; i < rccount; i++)
781 res_count_t *rcp = &rcarray[i];
783 /* TypeId */
784 if(rcp->type.type == name_ord)
785 fprintf(fp, "\t.short\t0x%04x\n", rcp->type.name.i_name | 0x8000);
786 else
787 fprintf(fp, "\t.short\t%s_%s_typename - %s%s\n",
788 prefix,
789 rcp->type.name.s_name->str.cstr,
790 prefix,
791 _NEResTab);
792 /* ResourceCount */
793 fprintf(fp, "\t.short\t%d\n", rcp->count);
794 /* Reserved */
795 fprintf(fp, "\t.long\t0\n");
796 /* NameInfo */
797 for(j = 0; j < rcp->count; j++)
799 /* FIXME: dividing by `alignment` doesn't seem to
800 * work with as (GAS). Shifting results in the
801 * correct behaviour. Maybe an as bug or just my
802 * lack of knowing as expression-syntax.
804 /* Offset */
806 * VERY IMPORTANT:
807 * The offset is relative to the beginning of the NE resource segment
808 * and _NOT_ to the file-beginning. This is because we do not have a
809 * file based resource, but a simulated NE segment. The offset _is_
810 * scaled by the AlignShift field.
811 * All other things are as the MS doc describes (alignment etc.)
813 fprintf(fp, "\t.short\t(%s%s_data - %s%s) >> %d\n",
814 prefix,
815 rcp->rscarray[j]->c_name,
816 prefix,
817 _NEResTab,
818 alignment_pwr);
819 /* Length */
820 fprintf(fp, "\t.short\t%d\n",
821 rcp->rscarray[j]->binres->size - rcp->rscarray[j]->binres->dataidx);
822 /* Flags */
823 fprintf(fp, "\t.short\t0x%04x\n", (WORD)rcp->rscarray[j]->memopt);
824 /* Id */
825 if(rcp->rscarray[j]->name->type == name_ord)
826 fprintf(fp, "\t.short\t0x%04x\n", rcp->rscarray[j]->name->name.i_name | 0x8000);
827 else
828 fprintf(fp, "\t.short\t%s%s_name - %s%s\n",
829 prefix,
830 rcp->rscarray[j]->c_name,
831 prefix,
832 _NEResTab);
833 /* Handle and Usage */
834 fprintf(fp, "\t.short\t0, 0\n");
837 /* EndTypes */
838 fprintf(fp, "\t.short\t0\n");
842 *****************************************************************************
843 * Function : write_rsc_names
844 * Syntax : void write_rsc_names(FILE *fp, resource_t *top)
845 * Input :
846 * Output :
847 * Description :
848 * Remarks :
849 *****************************************************************************
851 void write_rsc_names(FILE *fp, resource_t *top)
853 int i, j;
855 if(win32)
857 /* Write the names */
859 for(i = 0; i < rccount; i++)
861 res_count_t *rcp;
863 rcp = &rcarray[i];
865 if(rcp->type.type == name_str)
867 char *name = prep_nid_for_label(&(rcp->type));
868 fprintf(fp, "%s_%s_typename:\n",
869 prefix,
870 name);
871 write_name_str(fp, &(rcp->type));
874 for(j = 0; j < rcp->count32; j++)
876 resource_t *rsc = rcp->rsc32array[j].rsc[0];
878 if(rsc->name->type == name_str)
880 fprintf(fp, "%s%s_name:\n",
881 prefix,
882 rsc->c_name);
883 write_name_str(fp, rsc->name);
888 else
890 /* ResourceNames */
891 for(i = 0; i < rccount; i++)
893 res_count_t *rcp = &rcarray[i];
895 for(j = 0; j < rcp->count; j++)
897 if(rcp->type.type == name_str)
899 fprintf(fp, "%s_%s_typename:\n",
900 prefix,
901 rcp->type.name.s_name->str.cstr);
902 write_name_str(fp, &(rcp->type));
904 if(rcp->rscarray[j]->name->type == name_str)
906 fprintf(fp, "%s%s_name:\n",
907 prefix,
908 rcp->rscarray[j]->c_name);
909 write_name_str(fp, rcp->rscarray[j]->name);
913 /* EndNames */
915 /* This is to end the NE resource table */
916 if(create_dir)
917 fprintf(fp, "\t.byte\t0\n");
920 fprintf(fp, "\n");
924 *****************************************************************************
925 * Function : write_s_file
926 * Syntax : void write_s_file(char *outname, resource_t *top)
927 * Input :
928 * outname - Filename to write to
929 * top - The resource-tree to convert
930 * Output :
931 * Description :
932 * Remarks :
933 *****************************************************************************
935 void write_s_file(char *outname, resource_t *top)
937 FILE *fo;
938 resource_t *rsc;
940 fo = fopen(outname, "wt");
941 if(!fo)
943 error("Could not open %s\n", outname);
946 now = time(NULL);
947 fprintf(fo, s_file_head_str, input_name ? input_name : "stdin",
948 cmdline, ctime(&now));
950 /* Get an idea how many we have and restructure the tables */
951 count_resources(top);
953 /* First write the segment tables */
954 if(create_dir)
956 if(win32)
957 write_pe_segment(fo, top);
958 else
959 write_ne_segment(fo, top);
962 /* Dump the names */
963 write_rsc_names(fo, top);
965 if(!indirect_only)
967 /* Write the resource data */
968 fprintf(fo, "#\n# Resource binary data\n#\n");
969 for(rsc = top; rsc; rsc = rsc->next)
971 if(!rsc->binres)
972 continue;
974 fprintf(fo, "\t.align\t%d\n", win32 ? 4 : alignment);
975 fprintf(fo, "%s%s_data:\n", prefix, rsc->c_name);
976 if(global)
977 fprintf(fo, "\t.globl\t%s%s_data\n", prefix, rsc->c_name);
979 write_s_res(fo, rsc->binres);
981 fprintf(fo, "\n");
984 if(create_dir)
986 /* Add the size of the entire resource section for elf-dlls */
987 fprintf(fo, "%s_ResourceSectionSize:\n", Underscore);
988 fprintf(fo, "\t.long\t. - %s%s\n", prefix, _PEResTab);
992 if(indirect)
994 /* Write the indirection structures */
995 fprintf(fo, "\n#\n# Resource indirection structures\n#\n");
996 fprintf(fo, "\t.align\t4\n");
997 for(rsc = top; rsc; rsc = rsc->next)
999 int type;
1000 char *type_name = NULL;
1002 if(!rsc->binres)
1003 continue;
1005 switch(rsc->type)
1007 case res_menex:
1008 type = WRC_RT_MENU;
1009 break;
1010 case res_dlgex:
1011 type = WRC_RT_DIALOG;
1012 break;
1013 case res_usr:
1014 assert(rsc->res.usr->type != NULL);
1015 type_name = prep_nid_for_label(rsc->res.usr->type);
1016 type = 0;
1017 break;
1018 default:
1019 type = rsc->type;
1023 * This follows a structure like:
1024 * struct wrc_resource {
1025 * INT32 id;
1026 * RSCNAME *resname;
1027 * INT32 restype;
1028 * RSCNAME *typename;
1029 * void *data;
1030 * UINT32 datasize;
1031 * };
1032 * The 'RSCNAME' is a pascal-style string where the
1033 * first byte/word denotes the size and the rest the string
1034 * itself.
1036 fprintf(fo, "%s%s:\n", prefix, rsc->c_name);
1037 if(global)
1038 fprintf(fo, "\t.globl\t%s%s\n", prefix, rsc->c_name);
1039 fprintf(fo, "\t.long\t%d, %s%s%s, %d, %s%s%s%s, %s%s_data, %d\n",
1040 rsc->name->type == name_ord ? rsc->name->name.i_name : 0,
1041 rsc->name->type == name_ord ? "0" : prefix,
1042 rsc->name->type == name_ord ? "" : rsc->c_name,
1043 rsc->name->type == name_ord ? "" : "_name",
1044 type,
1045 type ? "0" : prefix,
1046 type ? "" : "_",
1047 type ? "" : type_name,
1048 type ? "" : "_typename",
1049 prefix,
1050 rsc->c_name,
1051 rsc->binres->size - rsc->binres->dataidx);
1052 fprintf(fo, "\n");
1054 fprintf(fo, "\n");
1056 /* Write the indirection table */
1057 fprintf(fo, "#\n# Resource indirection table\n#\n");
1058 fprintf(fo, "\t.align\t4\n");
1059 fprintf(fo, "%s%s:\n", prefix, _ResTable);
1060 fprintf(fo, "\t.globl\t%s%s\n", prefix, _ResTable);
1061 for(rsc = top; rsc; rsc = rsc->next)
1063 fprintf(fo, "\t.long\t%s%s\n", prefix, rsc->c_name);
1065 fprintf(fo, "\t.long\t0\n");
1066 fprintf(fo, "\n");
1069 if(auto_register)
1070 fprintf(fo, s_file_autoreg_str, prefix, _ResTable);
1072 fprintf(fo, s_file_tail_str);
1073 fclose(fo);
1077 *****************************************************************************
1078 * Function : write_h_file
1079 * Syntax : void write_h_file(char *outname, resource_t *top)
1080 * Input :
1081 * outname - Filename to write to
1082 * top - The resource-tree to convert
1083 * Output :
1084 * Description :
1085 * Remarks :
1086 *****************************************************************************
1088 void write_h_file(char *outname, resource_t *top)
1090 FILE *fo;
1091 resource_t *rsc;
1092 char *h_prefix;
1094 #ifdef NEED_UNDERSCORE_PREFIX
1095 h_prefix = prefix + 1;
1096 #else
1097 h_prefix = prefix;
1098 #endif
1100 fo = fopen(outname, "wt");
1101 if(!fo)
1103 error("Could not open %s\n", outname);
1106 time(&now);
1107 fprintf(fo, h_file_head_str, input_name ? input_name : "stdin",
1108 cmdline, ctime(&now), now, now);
1110 /* First write the segment tables reference */
1111 if(create_dir)
1113 fprintf(fo, "extern %schar %s%s[];\n\n",
1114 constant ? "const " : "",
1115 h_prefix,
1116 win32 ? _PEResTab : _NEResTab);
1119 /* Write the resource data */
1120 for(rsc = top; global && rsc; rsc = rsc->next)
1122 if(!rsc->binres)
1123 continue;
1125 fprintf(fo, "extern %schar %s%s_data[];\n",
1126 constant ? "const " : "",
1127 h_prefix,
1128 rsc->c_name);
1131 if(indirect)
1133 if(global)
1134 fprintf(fo, "\n");
1136 /* Write the indirection structures */
1137 for(rsc = top; global && rsc; rsc = rsc->next)
1139 fprintf(fo, "extern %swrc_resource%d_t %s%s;\n",
1140 constant ? "const " : "",
1141 win32 ? 32 : 16,
1142 h_prefix,
1143 rsc->c_name);
1146 if(global)
1147 fprintf(fo, "\n");
1149 /* Write the indirection table */
1150 fprintf(fo, "extern %swrc_resource%d_t %s%s[];\n\n",
1151 constant ? "const " : "",
1152 win32 ? 32 : 16,
1153 h_prefix,
1154 _ResTable);
1157 fprintf(fo, h_file_tail_str);
1158 fclose(fo);