Must include 'stdlib.h'.
[wine/dcerpc.git] / tools / wrc / writeres.c
blob544f061e8166c104a692ac7fcf9c552cd2e7fba5
1 /*
2 * Write .res, .s and .h file(s) from a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
6 */
8 #include "config.h"
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <assert.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 static char s_file_head_str[] =
28 "/* This file is generated with wrc version " WRC_FULLVERSION ". Do not edit! */\n"
29 "/* Source : %s */\n"
30 "/* Cmdline: %s */\n"
31 "/* Date : %s */\n"
32 "\n"
33 "\t.data\n"
34 "\n"
37 static char s_file_tail_str[] =
38 "/* <eof> */\n"
39 "\n"
42 static char s_file_autoreg_str[] =
43 "\t.text\n"
44 ".LAuto_Register:\n"
45 "\tpushl\t$%s%s\n"
46 #ifdef NEED_UNDERSCORE_PREFIX
47 "\tcall\t_LIBRES_RegisterResources\n"
48 #else
49 "\tcall\tLIBRES_RegisterResources\n"
50 #endif
51 "\taddl\t$4,%%esp\n"
52 "\tret\n\n"
53 #ifdef __NetBSD__
54 ".stabs \"___CTOR_LIST__\",22,0,0,.LAuto_Register\n\n"
55 #else
56 "\t.section .ctors,\"aw\"\n"
57 "\t.long\t.LAuto_Register\n\n"
58 #endif
61 static char h_file_head_str[] =
62 "/*\n"
63 " * This file is generated with wrc version " WRC_FULLVERSION ". Do not edit!\n"
64 " * Source : %s\n"
65 " * Cmdline: %s\n"
66 " * Date : %s"
67 " */\n"
68 "\n"
69 "#ifndef __%08lx_H\n" /* This becomes the date of compile */
70 "#define __%08lx_H\n"
71 "\n"
72 "#include <wrc_rsc.h>\n"
73 "\n"
76 static char h_file_tail_str[] =
77 "#endif\n"
78 "/* <eof> */\n\n"
81 char _NEResTab[] = "_NEResTab";
82 char _PEResTab[] = "_PEResTab";
83 char _ResTable[] = "_ResTable";
85 /* Variables used for resource sorting */
86 res_count_t *rcarray = NULL; /* Type-level count array */
87 int rccount = 0; /* Nr of entries in the type-level array */
88 int n_id_entries = 0; /* win32 only: Nr of unique ids in the type-level array */
89 int n_name_entries = 0; /* win32 only: Nr of unique namess in the type-level array */
91 static int direntries; /* win32 only: Total number of unique resources */
94 *****************************************************************************
95 * Function : write_resfile
96 * Syntax : void write_resfile(char *outname, resource_t *top)
97 * Input :
98 * outname - Filename to write to
99 * top - The resource-tree to convert
100 * Output :
101 * Description :
102 * Remarks :
103 *****************************************************************************
105 void write_resfile(char *outname, resource_t *top)
107 FILE *fo;
108 int ret;
109 char zeros[3] = {0, 0, 0};
111 fo = fopen(outname, "wb");
112 if(!fo)
114 error("Could not open %s\n", outname);
117 if(win32)
119 /* Put an empty resource first to signal win32 format */
120 res_t *res = new_res();
121 put_dword(res, 0); /* ResSize */
122 put_dword(res, 0x00000020); /* HeaderSize */
123 put_word(res, 0xffff); /* ResType */
124 put_word(res, 0);
125 put_word(res, 0xffff); /* ResName */
126 put_word(res, 0);
127 put_dword(res, 0); /* DataVersion */
128 put_word(res, 0); /* Memory options */
129 put_word(res, 0); /* Language */
130 put_dword(res, 0); /* Version */
131 put_dword(res, 0); /* Charateristics */
132 ret = fwrite(res->data, 1, res->size, fo);
133 if(ret != res->size)
135 fclose(fo);
136 error("Error writing %s", outname);
138 free(res);
141 for(; top; top = top->next)
143 if(!top->binres)
144 continue;
146 ret = fwrite(top->binres->data, 1, top->binres->size, fo);
147 if(ret != top->binres->size)
149 fclose(fo);
150 error("Error writing %s", outname);
152 if(win32 && (top->binres->size & 0x03))
154 /* Write padding */
155 ret = fwrite(zeros, 1, 4 - (top->binres->size & 0x03), fo);
156 if(ret != 4 - (top->binres->size & 0x03))
158 fclose(fo);
159 error("Error writing %s", outname);
163 fclose(fo);
167 *****************************************************************************
168 * Function : write_s_res
169 * Syntax : void write_s_res(FILE *fp, res_t *res)
170 * Input :
171 * Output :
172 * Description :
173 * Remarks :
174 *****************************************************************************
176 #define BYTESPERLINE 8
177 static void write_s_res(FILE *fp, res_t *res)
179 int idx = res->dataidx;
180 int end = res->size;
181 int rest = (end - idx) % BYTESPERLINE;
182 int lines = (end - idx) / BYTESPERLINE;
183 int i, j;
185 for(i = 0 ; i < lines; i++)
187 fprintf(fp, "\t.byte\t");
188 for(j = 0; j < BYTESPERLINE; j++, idx++)
190 fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
191 j == BYTESPERLINE-1 ? "" : ", ");
193 fprintf(fp, "\n");
195 if(rest)
197 fprintf(fp, "\t.byte\t");
198 for(j = 0; j < rest; j++, idx++)
200 fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
201 j == rest-1 ? "" : ", ");
203 fprintf(fp, "\n");
206 #undef BYTESPERLINE
209 *****************************************************************************
210 * Function : write_name_str
211 * Syntax : void write_name_str(FILE *fp, name_id_t *nid)
212 * Input :
213 * Output :
214 * Description :
215 * Remarks : One level self recursive for string type conversion
216 *****************************************************************************
218 static void write_name_str(FILE *fp, name_id_t *nid)
220 res_t res;
221 assert(nid->type == name_str);
223 if(!win32 && nid->name.s_name->type == str_char)
225 res.size = strlen(nid->name.s_name->str.cstr);
226 if(res.size > 254)
227 error("Can't write strings larger than 254 bytes");
228 if(res.size == 0)
229 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
230 res.dataidx = 0;
231 res.data = (char *)xmalloc(res.size + 1);
232 res.data[0] = (char)res.size;
233 res.size++; /* We need to write the length byte as well */
234 strcpy(res.data+1, nid->name.s_name->str.cstr);
235 write_s_res(fp, &res);
236 free(res.data);
238 else if(!win32 && nid->name.s_name->type == str_unicode)
240 name_id_t lnid;
241 string_t str;
243 lnid.type = name_str;
244 lnid.name.s_name = &str;
245 str.type = str_char;
246 str.str.cstr = dupwstr2cstr(nid->name.s_name->str.wstr);
247 write_name_str(fp, &lnid);
248 free(str.str.cstr);
250 else if(win32 && nid->name.s_name->type == str_char)
252 name_id_t lnid;
253 string_t str;
255 lnid.type = name_str;
256 lnid.name.s_name = &str;
257 str.type = str_unicode;
258 str.str.wstr = dupcstr2wstr(nid->name.s_name->str.cstr);
259 write_name_str(fp, &lnid);
260 free(str.str.wstr);
262 else if(win32 && nid->name.s_name->type == str_unicode)
264 res.size = wstrlen(nid->name.s_name->str.wstr);
265 if(res.size > 65534)
266 error("Can't write strings larger than 65534 bytes");
267 if(res.size == 0)
268 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
269 res.dataidx = 0;
270 res.data = (char *)xmalloc((res.size + 1) * 2);
271 ((short *)res.data)[0] = (short)res.size;
272 wstrcpy((short *)(res.data+2), nid->name.s_name->str.wstr);
273 res.size *= 2; /* Function writes bytes, not shorts... */
274 res.size += 2; /* We need to write the length word as well */
275 write_s_res(fp, &res);
276 free(res.data);
278 else
280 internal_error(__FILE__, __LINE__, "Hmm, requested to write a string of unknown type %d",
281 nid->name.s_name->type);
286 *****************************************************************************
287 * Function : find_counter
288 * Syntax : res_count_t *find_counter(name_id_t *type)
289 * Input :
290 * Output :
291 * Description :
292 * Remarks :
293 *****************************************************************************
295 static res_count_t *find_counter(name_id_t *type)
297 int i;
298 for(i = 0; i < rccount; i++)
300 if(!compare_name_id(type, &(rcarray[i].type)))
301 return &rcarray[i];
303 return NULL;
307 *****************************************************************************
308 * Function : count_resources
309 * Syntax : res_count_t *count_resources(resource_t *top)
310 * Input :
311 * Output :
312 * Description :
313 * Remarks : The whole lot is converted into arrays because they are
314 * easy sortable. Makes the lot almost unreadable, but it
315 * works (I hope). Basically you have to keep in mind that
316 * the lot is a three-dimensional structure for win32 and a
317 * two-dimensional structure for win16.
318 *****************************************************************************
320 #define RCT(v) (*((resource_t **)(v)))
321 /* qsort sorting function */
322 static int sort_name_id(const void *e1, const void *e2)
324 return compare_name_id(RCT(e1)->name, RCT(e2)->name);
327 static int sort_language(const void *e1, const void *e2)
329 assert((RCT(e1)->lan) != NULL);
330 assert((RCT(e2)->lan) != NULL);
332 return MAKELANGID(RCT(e1)->lan->id, RCT(e1)->lan->sub)
333 - MAKELANGID(RCT(e2)->lan->id, RCT(e2)->lan->sub);
335 #undef RCT
336 #define RCT(v) ((res_count_t *)(v))
337 static int sort_type(const void *e1, const void *e2)
339 return compare_name_id(&(RCT(e1)->type), &(RCT(e2)->type));
341 #undef RCT
343 static void count_resources(resource_t *top)
345 resource_t *rsc;
346 res_count_t *rcp;
347 name_id_t nid;
348 int i, j;
350 for(rsc = top; rsc; rsc = rsc->next)
352 if(!rsc->binres)
353 continue;
354 switch(rsc->type)
356 case res_dlgex:
357 nid.name.i_name = WRC_RT_DIALOG;
358 nid.type = name_ord;
359 break;
360 case res_menex:
361 nid.name.i_name = WRC_RT_MENU;
362 nid.type = name_ord;
363 break;
364 case res_usr:
365 nid = *(rsc->res.usr->type);
366 break;
367 default:
368 nid.name.i_name = rsc->type;
369 nid.type = name_ord;
372 if((rcp = find_counter(&nid)) == NULL)
374 /* Count the number of uniq ids and names */
376 if(nid.type == name_ord)
377 n_id_entries++;
378 else
379 n_name_entries++;
381 if(!rcarray)
383 rcarray = (res_count_t *)xmalloc(sizeof(res_count_t));
384 rccount = 1;
385 rcarray[0].count = 1;
386 rcarray[0].type = nid;
387 rcarray[0].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
388 rcarray[0].rscarray[0] = rsc;
390 else
392 rccount++;
393 rcarray = (res_count_t *)xrealloc(rcarray, rccount * sizeof(res_count_t));
394 rcarray[rccount-1].count = 1;
395 rcarray[rccount-1].type = nid;
396 rcarray[rccount-1].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
397 rcarray[rccount-1].rscarray[0] = rsc;
400 else
402 rcp->count++;
403 rcp->rscarray = (resource_t **)xrealloc(rcp->rscarray, rcp->count * sizeof(resource_t *));
404 rcp->rscarray[rcp->count-1] = rsc;
408 if(!win32)
410 /* We're done, win16 requires no special sorting */
411 return;
414 /* We now have a unsorted list of types with an array of res_count_t
415 * in rcarray[0..rccount-1]. And we have names of one type in the
416 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
417 * The list needs to be sorted for win32's top level tree structure.
420 /* Sort the types */
421 if(rccount > 1)
422 qsort(rcarray, rccount, sizeof(rcarray[0]), sort_type);
424 /* Now sort the name-id arrays */
425 for(i = 0; i < rccount; i++)
427 if(rcarray[i].count > 1)
428 qsort(rcarray[i].rscarray, rcarray[i].count, sizeof(rcarray[0].rscarray[0]), sort_name_id);
431 /* Now split the name-id arrays into name/language
432 * subs. Don't look at the awfull expressions...
433 * We do this by taking the array elements out of rscarray and putting
434 * together a new array in rsc32array.
436 for(i = 0; i < rccount; i++)
438 res_count_t *rcap;
440 assert(rcarray[i].count >= 1);
442 /* rcap points to the current type we are dealing with */
443 rcap = &(rcarray[i]);
445 /* Insert the first name-id */
446 rcap->rsc32array = (res32_count_t *)xmalloc(sizeof(res32_count_t));
447 rcap->count32 = 1;
448 rcap->rsc32array[0].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
449 rcap->rsc32array[0].count = 1;
450 rcap->rsc32array[0].rsc[0] = rcap->rscarray[0];
451 if(rcap->rscarray[0]->name->type == name_ord)
453 rcap->n_id_entries = 1;
454 rcap->n_name_entries = 0;
456 else
458 rcap->n_id_entries = 0;
459 rcap->n_name_entries = 1;
462 /* Now loop over the resting resources of the current type
463 * to find duplicate names (which should have different
464 * languages).
466 for(j = 1; j < rcap->count; j++)
468 res32_count_t *r32cp;
470 /* r32cp points to the current res32_count structure
471 * that holds the resource name we are processing.
473 r32cp = &(rcap->rsc32array[rcap->count32-1]);
475 if(!compare_name_id(r32cp->rsc[0]->name, rcarray[i].rscarray[j]->name))
477 /* Names are the same, add to list */
478 r32cp->count++;
479 r32cp->rsc = (resource_t **)xrealloc(r32cp->rsc, r32cp->count * sizeof(resource_t *));
480 r32cp->rsc[r32cp->count-1] = rcap->rscarray[j];
482 else
484 /* New name-id, sort the old one by
485 * language and create new list
487 if(r32cp->count > 1)
488 qsort(r32cp->rsc, r32cp->count, sizeof(r32cp->rsc[0]), sort_language);
489 rcap->count32++;
490 rcap->rsc32array = (res32_count_t*)xrealloc(rcap->rsc32array, rcap->count32 * sizeof(res32_count_t));
491 rcap->rsc32array[rcap->count32-1].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
492 rcap->rsc32array[rcap->count32-1].count = 1;
493 rcap->rsc32array[rcap->count32-1].rsc[0] = rcap->rscarray[j];
495 if(rcap->rscarray[j]->name->type == name_ord)
496 rcap->n_id_entries++;
497 else
498 rcap->n_name_entries++;
501 /* Also sort the languages of the last name group */
502 if(rcap->rsc32array[rcap->count32-1].count > 1)
503 qsort(rcap->rsc32array[rcap->count32-1].rsc,
504 rcap->rsc32array[rcap->count32-1].count,
505 sizeof(rcap->rsc32array[rcap->count32-1].rsc[0]),
506 sort_language);
511 *****************************************************************************
512 * Function : write_pe_segment
513 * Syntax : void write_pe_segment(FILE *fp, resource_t *top)
514 * Input :
515 * Output :
516 * Description :
517 * Remarks :
518 *****************************************************************************
520 static void write_pe_segment(FILE *fp, resource_t *top)
522 int i;
524 fprintf(fp, "\t.align\t4\n");
525 fprintf(fp, "%s%s:\n", prefix, _PEResTab);
526 fprintf(fp, "\t.globl\t%s%s\n", prefix, _PEResTab);
527 /* Flags */
528 fprintf(fp, "\t.long\t0\n");
529 /* Time/Date stamp */
530 fprintf(fp, "\t.long\t0x%08lx\n", (long)now);
531 /* Version */
532 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
533 /* # of id entries, # of name entries */
534 fprintf(fp, "\t.short\t%d, %d\n", n_name_entries, n_id_entries);
536 /* Write the type level of the tree */
537 for(i = 0; i < rccount; i++)
539 res_count_t *rcp;
540 char *label;
542 rcp = &rcarray[i];
544 /* TypeId */
545 if(rcp->type.type == name_ord)
546 fprintf(fp, "\t.long\t%d\n", rcp->type.name.i_name);
547 else
549 char *name = prep_nid_for_label(&(rcp->type));
550 fprintf(fp, "\t.long\t(%s_%s_typename - %s%s) | 0x80000000\n",
551 prefix,
552 name,
553 prefix,
554 _PEResTab);
556 /* Offset */
557 label = prep_nid_for_label(&(rcp->type));
558 fprintf(fp, "\t.long\t(.L%s - %s%s) | 0x80000000\n",
559 label,
560 prefix,
561 _PEResTab);
564 /* Write the name level of the tree */
566 for(i = 0; i < rccount; i++)
568 res_count_t *rcp;
569 char *typelabel;
570 char *namelabel;
571 int j;
573 rcp = &rcarray[i];
575 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
576 fprintf(fp, ".L%s:\n", typelabel);
578 fprintf(fp, "\t.long\t0\n"); /* Flags */
579 fprintf(fp, "\t.long\t0x%08lx\n", (long)now); /* TimeDate */
580 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
581 fprintf(fp, "\t.short\t%d, %d\n", rcp->n_name_entries, rcp->n_id_entries);
582 for(j = 0; j < rcp->count32; j++)
584 resource_t *rsc = rcp->rsc32array[j].rsc[0];
585 /* NameId */
586 if(rsc->name->type == name_ord)
587 fprintf(fp, "\t.long\t%d\n", rsc->name->name.i_name);
588 else
590 fprintf(fp, "\t.long\t(%s%s_name - %s%s) | 0x80000000\n",
591 prefix,
592 rsc->c_name,
593 prefix,
594 _PEResTab);
596 /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
597 * put the offset to the resource data entry.
598 * ?? Is unescaping worth while ??
600 /* Offset */
601 namelabel = prep_nid_for_label(rsc->name);
602 fprintf(fp, "\t.long\t(.L%s_%s - %s%s) | 0x80000000\n",
603 typelabel,
604 namelabel,
605 prefix,
606 _PEResTab);
608 free(typelabel);
611 /* Write the language level of the tree */
613 for(i = 0; i < rccount; i++)
615 res_count_t *rcp;
616 char *namelabel;
617 char *typelabel;
618 int j;
620 rcp = &rcarray[i];
621 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
623 for(j = 0; j < rcp->count32; j++)
625 res32_count_t *r32cp = &(rcp->rsc32array[j]);
626 int k;
628 namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
629 fprintf(fp, ".L%s_%s:\n", typelabel, namelabel);
631 fprintf(fp, "\t.long\t0\n"); /* Flags */
632 fprintf(fp, "\t.long\t0x%08lx\n", (long)now); /* TimeDate */
633 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
634 fprintf(fp, "\t.short\t0, %d\n", r32cp->count);
636 for(k = 0; k < r32cp->count; k++)
638 resource_t *rsc = r32cp->rsc[k];
639 assert(rsc->lan != NULL);
640 /* LanguageId */
641 fprintf(fp, "\t.long\t0x%08x\n", rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
642 /* Offset */
643 fprintf(fp, "\t.long\t.L%s_%s_%d - %s%s\n",
644 typelabel,
645 namelabel,
646 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0,
647 prefix,
648 _PEResTab);
650 free(namelabel);
652 free(typelabel);
655 /* Write the resource table itself */
656 fprintf(fp, "%s_ResourceDirectory:\n", prefix);
657 fprintf(fp, "\t.globl\t%s_ResourceDirectory\n", prefix);
658 direntries = 0;
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));
677 for(k = 0; k < r32cp->count; k++)
679 resource_t *rsc = r32cp->rsc[k];
681 assert(rsc->lan != NULL);
683 fprintf(fp, ".L%s_%s_%d:\n",
684 typelabel,
685 namelabel,
686 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
688 /* Data RVA */
689 fprintf(fp, "\t.long\t%s%s_data - %s%s\n",
690 prefix,
691 rsc->c_name,
692 prefix,
693 _PEResTab);
694 /* Size */
695 fprintf(fp, "\t.long\t%d\n",
696 rsc->binres->size - rsc->binres->dataidx);
697 /* CodePage */
698 fprintf(fp, "\t.long\t%ld\n", codepage);
699 /* Reserved */
700 fprintf(fp, "\t.long\t0\n");
702 direntries++;
704 free(namelabel);
706 free(typelabel);
711 *****************************************************************************
712 * Function : write_ne_segment
713 * Syntax : void write_ne_segment(FILE *fp, resource_t *top)
714 * Input :
715 * Output :
716 * Description :
717 * Remarks :
718 *****************************************************************************
720 static void write_ne_segment(FILE *fp, resource_t *top)
722 int i, j;
724 fprintf(fp, "\t.align\t4\n");
725 fprintf(fp, "%s%s:\n", prefix, _NEResTab);
726 fprintf(fp, "\t.globl\t%s%s\n", prefix, _NEResTab);
728 /* AlignmentShift */
729 fprintf(fp, "\t.short\t%d\n", alignment_pwr);
731 /* TypeInfo */
732 for(i = 0; i < rccount; i++)
734 res_count_t *rcp = &rcarray[i];
736 /* TypeId */
737 if(rcp->type.type == name_ord)
738 fprintf(fp, "\t.short\t0x%04x\n", rcp->type.name.i_name | 0x8000);
739 else
740 fprintf(fp, "\t.short\t%s_%s_typename - %s%s\n",
741 prefix,
742 rcp->type.name.s_name->str.cstr,
743 prefix,
744 _NEResTab);
745 /* ResourceCount */
746 fprintf(fp, "\t.short\t%d\n", rcp->count);
747 /* Reserved */
748 fprintf(fp, "\t.long\t0\n");
749 /* NameInfo */
750 for(j = 0; j < rcp->count; j++)
753 * VERY IMPORTANT:
754 * The offset is relative to the beginning of the NE resource segment
755 * and _NOT_ to the file-beginning. This is because we do not have a
756 * file based resource, but a simulated NE segment. The offset _is_
757 * scaled by the AlignShift field.
758 * All other things are as the MS doc describes (alignment etc.)
760 /* Offset */
761 fprintf(fp, "\t.short\t(%s%s_data - %s%s) >> %d\n",
762 prefix,
763 rcp->rscarray[j]->c_name,
764 prefix,
765 _NEResTab,
766 alignment_pwr);
767 /* Length */
768 fprintf(fp, "\t.short\t%d\n",
769 rcp->rscarray[j]->binres->size - rcp->rscarray[j]->binres->dataidx);
770 /* Flags */
771 fprintf(fp, "\t.short\t0x%04x\n", (WORD)rcp->rscarray[j]->memopt);
772 /* Id */
773 if(rcp->rscarray[j]->name->type == name_ord)
774 fprintf(fp, "\t.short\t0x%04x\n", rcp->rscarray[j]->name->name.i_name | 0x8000);
775 else
776 fprintf(fp, "\t.short\t%s%s_name - %s%s\n",
777 prefix,
778 rcp->rscarray[j]->c_name,
779 prefix,
780 _NEResTab);
781 /* Handle and Usage */
782 fprintf(fp, "\t.short\t0, 0\n");
785 /* EndTypes */
786 fprintf(fp, "\t.short\t0\n");
790 *****************************************************************************
791 * Function : write_rsc_names
792 * Syntax : void write_rsc_names(FILE *fp, resource_t *top)
793 * Input :
794 * Output :
795 * Description :
796 * Remarks :
797 *****************************************************************************
799 static void write_rsc_names(FILE *fp, resource_t *top)
801 int i, j;
803 if(win32)
805 /* Write the names */
807 for(i = 0; i < rccount; i++)
809 res_count_t *rcp;
811 rcp = &rcarray[i];
813 if(rcp->type.type == name_str)
815 char *name = prep_nid_for_label(&(rcp->type));
816 fprintf(fp, "%s_%s_typename:\n",
817 prefix,
818 name);
819 write_name_str(fp, &(rcp->type));
822 for(j = 0; j < rcp->count32; j++)
824 resource_t *rsc = rcp->rsc32array[j].rsc[0];
826 if(rsc->name->type == name_str)
828 fprintf(fp, "%s%s_name:\n",
829 prefix,
830 rsc->c_name);
831 write_name_str(fp, rsc->name);
836 else
838 /* ResourceNames */
839 for(i = 0; i < rccount; i++)
841 res_count_t *rcp = &rcarray[i];
843 for(j = 0; j < rcp->count; j++)
845 if(rcp->type.type == name_str)
847 fprintf(fp, "%s_%s_typename:\n",
848 prefix,
849 rcp->type.name.s_name->str.cstr);
850 write_name_str(fp, &(rcp->type));
852 if(rcp->rscarray[j]->name->type == name_str)
854 fprintf(fp, "%s%s_name:\n",
855 prefix,
856 rcp->rscarray[j]->c_name);
857 write_name_str(fp, rcp->rscarray[j]->name);
861 /* EndNames */
863 /* This is to end the NE resource table */
864 if(create_dir)
865 fprintf(fp, "\t.byte\t0\n");
868 fprintf(fp, "\n");
872 *****************************************************************************
873 * Function : write_s_file
874 * Syntax : void write_s_file(char *outname, resource_t *top)
875 * Input :
876 * outname - Filename to write to
877 * top - The resource-tree to convert
878 * Output :
879 * Description :
880 * Remarks :
881 *****************************************************************************
883 void write_s_file(char *outname, resource_t *top)
885 FILE *fo;
886 resource_t *rsc;
888 fo = fopen(outname, "wt");
889 if(!fo)
891 error("Could not open %s\n", outname);
892 return;
896 char *s, *p;
897 s = ctime(&now);
898 p = strchr(s, '\n');
899 if(p) *p = '\0';
900 fprintf(fo, s_file_head_str, input_name ? input_name : "stdin",
901 cmdline, s);
904 /* Get an idea how many we have and restructure the tables */
905 count_resources(top);
907 /* First write the segment tables */
908 if(create_dir)
910 if(win32)
911 write_pe_segment(fo, top);
912 else
913 write_ne_segment(fo, top);
916 /* Dump the names */
917 write_rsc_names(fo, top);
919 if(create_dir)
920 fprintf(fo, ".LResTabEnd:\n");
922 if(!indirect_only)
924 /* Write the resource data */
925 fprintf(fo, "\n/* Resource binary data */\n\n");
926 for(rsc = top; rsc; rsc = rsc->next)
928 if(!rsc->binres)
929 continue;
931 fprintf(fo, "\t.align\t%d\n", win32 ? 4 : alignment);
932 fprintf(fo, "%s%s_data:\n", prefix, rsc->c_name);
933 if(global)
934 fprintf(fo, "\t.globl\t%s%s_data\n", prefix, rsc->c_name);
936 write_s_res(fo, rsc->binres);
938 fprintf(fo, "\n");
941 if(create_dir)
943 /* Add a resource descriptor for built-in and elf-dlls */
944 fprintf(fo, "\t.align\t4\n");
945 fprintf(fo, "%s_ResourceDescriptor:\n", prefix);
946 fprintf(fo, "\t.globl\t%s_ResourceDescriptor\n", prefix);
947 fprintf(fo, "%s_ResourceTable:\n", prefix);
948 if(global)
949 fprintf(fo, "\t.globl\t%s_ResourceTable\n", prefix);
950 fprintf(fo, "\t.long\t%s%s\n", prefix, win32 ? _PEResTab : _NEResTab);
951 fprintf(fo, "%s_NumberOfResources:\n", prefix);
952 if(global)
953 fprintf(fo, "\t.globl\t%s_NumberOfResources\n", prefix);
954 fprintf(fo, "\t.long\t%d\n", direntries);
955 fprintf(fo, "%s_ResourceSectionSize:\n", prefix);
956 if(global)
957 fprintf(fo, "\t.globl\t%s_ResourceSectionSize\n", prefix);
958 fprintf(fo, "\t.long\t.LResTabEnd - %s%s\n", prefix, win32 ? _PEResTab : _NEResTab);
959 if(win32)
961 fprintf(fo, "%s_ResourcesEntries:\n", prefix);
962 if(global)
963 fprintf(fo, "\t.globl\t%s_ResourcesEntries\n", prefix);
964 fprintf(fo, "\t.long\t%s_ResourceDirectory\n", prefix);
969 if(indirect)
971 /* Write the indirection structures */
972 fprintf(fo, "\n/* Resource indirection structures */\n\n");
973 fprintf(fo, "\t.align\t4\n");
974 for(rsc = top; rsc; rsc = rsc->next)
976 int type;
977 char *type_name = NULL;
979 if(!rsc->binres)
980 continue;
982 switch(rsc->type)
984 case res_menex:
985 type = WRC_RT_MENU;
986 break;
987 case res_dlgex:
988 type = WRC_RT_DIALOG;
989 break;
990 case res_usr:
991 assert(rsc->res.usr->type != NULL);
992 type_name = prep_nid_for_label(rsc->res.usr->type);
993 type = 0;
994 break;
995 default:
996 type = rsc->type;
1000 * This follows a structure like:
1001 * struct wrc_resource {
1002 * INT32 id;
1003 * RSCNAME *resname;
1004 * INT32 restype;
1005 * RSCNAME *typename;
1006 * void *data;
1007 * UINT32 datasize;
1008 * };
1009 * The 'RSCNAME' is a pascal-style string where the
1010 * first byte/word denotes the size and the rest the string
1011 * itself.
1013 fprintf(fo, "%s%s:\n", prefix, rsc->c_name);
1014 if(global)
1015 fprintf(fo, "\t.globl\t%s%s\n", prefix, rsc->c_name);
1016 fprintf(fo, "\t.long\t%d, %s%s%s, %d, %s%s%s%s, %s%s_data, %d\n",
1017 rsc->name->type == name_ord ? rsc->name->name.i_name : 0,
1018 rsc->name->type == name_ord ? "0" : prefix,
1019 rsc->name->type == name_ord ? "" : rsc->c_name,
1020 rsc->name->type == name_ord ? "" : "_name",
1021 type,
1022 type ? "0" : prefix,
1023 type ? "" : "_",
1024 type ? "" : type_name,
1025 type ? "" : "_typename",
1026 prefix,
1027 rsc->c_name,
1028 rsc->binres->size - rsc->binres->dataidx);
1029 fprintf(fo, "\n");
1031 fprintf(fo, "\n");
1033 /* Write the indirection table */
1034 fprintf(fo, "/* Resource indirection table */\n\n");
1035 fprintf(fo, "\t.align\t4\n");
1036 fprintf(fo, "%s%s:\n", prefix, _ResTable);
1037 fprintf(fo, "\t.globl\t%s%s\n", prefix, _ResTable);
1038 for(rsc = top; rsc; rsc = rsc->next)
1040 fprintf(fo, "\t.long\t%s%s\n", prefix, rsc->c_name);
1042 fprintf(fo, "\t.long\t0\n");
1043 fprintf(fo, "\n");
1046 if(auto_register)
1047 fprintf(fo, s_file_autoreg_str, prefix, _ResTable);
1049 fprintf(fo, s_file_tail_str);
1050 fclose(fo);
1054 *****************************************************************************
1055 * Function : write_h_file
1056 * Syntax : void write_h_file(char *outname, resource_t *top)
1057 * Input :
1058 * outname - Filename to write to
1059 * top - The resource-tree to convert
1060 * Output :
1061 * Description :
1062 * Remarks :
1063 *****************************************************************************
1065 void write_h_file(char *outname, resource_t *top)
1067 FILE *fo;
1068 resource_t *rsc;
1069 char *h_prefix;
1071 #ifdef NEED_UNDERSCORE_PREFIX
1072 h_prefix = prefix + 1;
1073 #else
1074 h_prefix = prefix;
1075 #endif
1077 fo = fopen(outname, "wt");
1078 if(!fo)
1080 error("Could not open %s\n", outname);
1083 fprintf(fo, h_file_head_str, input_name ? input_name : "stdin",
1084 cmdline, ctime(&now), (long)now, (long)now);
1086 /* First write the segment tables reference */
1087 if(create_dir)
1089 fprintf(fo, "extern %schar %s%s[];\n\n",
1090 constant ? "const " : "",
1091 h_prefix,
1092 win32 ? _PEResTab : _NEResTab);
1095 /* Write the resource data */
1096 for(rsc = top; global && rsc; rsc = rsc->next)
1098 if(!rsc->binres)
1099 continue;
1101 fprintf(fo, "extern %schar %s%s_data[];\n",
1102 constant ? "const " : "",
1103 h_prefix,
1104 rsc->c_name);
1107 if(indirect)
1109 if(global)
1110 fprintf(fo, "\n");
1112 /* Write the indirection structures */
1113 for(rsc = top; global && rsc; rsc = rsc->next)
1115 fprintf(fo, "extern %swrc_resource%d_t %s%s;\n",
1116 constant ? "const " : "",
1117 win32 ? 32 : 16,
1118 h_prefix,
1119 rsc->c_name);
1122 if(global)
1123 fprintf(fo, "\n");
1125 /* Write the indirection table */
1126 fprintf(fo, "extern %swrc_resource%d_t %s%s[];\n\n",
1127 constant ? "const " : "",
1128 win32 ? 32 : 16,
1129 h_prefix,
1130 _ResTable);
1133 fprintf(fo, h_file_tail_str);
1134 fclose(fo);