source: trunk/tools/wrc/writeres.c@ 6114

Last change on this file since 6114 was 6114, checked in by bird, 24 years ago

EMX -> WIN32OS2, makeing fopen use w not wt. writeres.c

File size: 35.6 KB
Line 
1/*
2 * Write .res, .s and .h file(s) from a resource-tree
3 *
4 * Copyright 1998 Bertho A. Stultiens
5 *
6 */
7
8#include "config.h"
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <assert.h>
14
15#include "wine/unicode.h"
16#include "wrc.h"
17#include "writeres.h"
18#include "genres.h"
19#include "newstruc.h"
20#include "utils.h"
21
22#ifdef NEED_UNDERSCORE_PREFIX
23char Underscore[] = "_";
24#else
25char Underscore[] = "";
26#endif
27
28#ifdef MASM
29 #define DIRECTIVE_BYTE "db"
30 #define DIRECTIVE_SHORT "dw"
31 #define DIRECTIVE_LONG "dd"
32 #define DIRECTIVE_ALIGN "align"
33 #define DIRECTIVE_GLOBAL "public"
34 #define LOCAL_PREFIX ""
35 #define LONGFRMT "0%08lxh"
36 #define SHORTFRMT "0%04xh"
37 #define BYTEFRMT "0%02xh"
38 #define HEXBIT31 "80000000h"
39 #define COMMENT_LINE ";"
40 #define OR "or"
41
42static char s_file_head_str[] =
43 "; This file is generated with wrc version " WRC_FULLVERSION ". Do not edit! */\n"
44 "; Source : %s */\n"
45 "; Cmdline: %s */\n"
46 "; Date : %s */\n"
47 "\n"
48 "\t.386p\n"
49 "\t.model flat\n"
50 "\t.data\n"
51 "\n"
52 ;
53
54static char s_file_tail_str[] =
55 "\tend\n"
56 "; <eof> */\n"
57 "\n"
58 ;
59
60#else
61 #define DIRECTIVE_BYTE ".byte"
62 #define DIRECTIVE_SHORT ".short"
63 #define DIRECTIVE_LONG ".long"
64 #define DIRECTIVE_ALIGN ".align"
65 #define DIRECTIVE_GLOBAL ".globl"
66 #define LOCAL_PREFIX "."
67 #define LONGFRMT "0x%08lx"
68 #define SHORTFRMT "0x%04x"
69 #define BYTEFRMT "0x%02x"
70 #define HEXBIT31 "0x80000000"
71 #define COMMENT_LINE
72 #define OR "|"
73
74static char s_file_head_str[] =
75 "/* This file is generated with wrc version " WRC_FULLVERSION ". Do not edit! */\n"
76 "/* Source : %s */\n"
77 "/* Cmdline: %s */\n"
78 "/* Date : %s */\n"
79 "\n"
80 "\t.data\n"
81 "\n"
82 ;
83
84static char s_file_tail_str[] =
85 "/* <eof> */\n"
86 "\n"
87 ;
88
89#endif
90
91
92static char s_file_autoreg_str[] =
93 "\t.text\n"
94 ".LAuto_Register:\n"
95 "\tpushl\t$%s%s\n"
96#ifdef NEED_UNDERSCORE_PREFIX
97 "\tcall\t_LIBRES_RegisterResources\n"
98#else
99 "\tcall\tLIBRES_RegisterResources\n"
100#endif
101 "\taddl\t$4,%%esp\n"
102 "\tret\n\n"
103#ifdef __NetBSD__
104 ".stabs \"___CTOR_LIST__\",22,0,0,.LAuto_Register\n\n"
105#else
106 "\t.section .ctors,\"aw\"\n"
107 "\t"DIRECTIVE_LONG"\t.LAuto_Register\n\n"
108#endif
109 ;
110
111static char h_file_head_str[] =
112 "/*\n"
113 " * This file is generated with wrc version " WRC_FULLVERSION ". Do not edit!\n"
114 " * Source : %s\n"
115 " * Cmdline: %s\n"
116 " * Date : %s"
117 " */\n"
118 "\n"
119 "#ifndef __%08lx_H\n" /* This becomes the date of compile */
120 "#define __%08lx_H\n"
121 "\n"
122 "#include <wrc_rsc.h>\n"
123 "\n"
124 ;
125
126static char h_file_tail_str[] =
127 "#endif\n"
128 "/* <eof> */\n\n"
129 ;
130
131char _NEResTab[] = "_NEResTab";
132char _PEResTab[] = "_PEResTab";
133char _ResTable[] = "_ResTable";
134
135/* Variables used for resource sorting */
136res_count_t *rcarray = NULL; /* Type-level count array */
137int rccount = 0; /* Nr of entries in the type-level array */
138int n_id_entries = 0; /* win32 only: Nr of unique ids in the type-level array */
139int n_name_entries = 0; /* win32 only: Nr of unique namess in the type-level array */
140
141static int direntries; /* win32 only: Total number of unique resources */
142
143/*
144 *****************************************************************************
145 * Function : write_resfile
146 * Syntax : void write_resfile(char *outname, resource_t *top)
147 * Input :
148 * outname - Filename to write to
149 * top - The resource-tree to convert
150 * Output :
151 * Description :
152 * Remarks :
153 *****************************************************************************
154*/
155void write_resfile(char *outname, resource_t *top)
156{
157 FILE *fo;
158 int ret;
159 char zeros[3] = {0, 0, 0};
160
161 fo = fopen(outname, "wb");
162 if(!fo)
163 {
164 error("Could not open %s\n", outname);
165 }
166
167 if(win32)
168 {
169 /* Put an empty resource first to signal win32 format */
170 res_t *res = new_res();
171 put_dword(res, 0); /* ResSize */
172 put_dword(res, 0x00000020); /* HeaderSize */
173 put_word(res, 0xffff); /* ResType */
174 put_word(res, 0);
175 put_word(res, 0xffff); /* ResName */
176 put_word(res, 0);
177 put_dword(res, 0); /* DataVersion */
178 put_word(res, 0); /* Memory options */
179 put_word(res, 0); /* Language */
180 put_dword(res, 0); /* Version */
181 put_dword(res, 0); /* Charateristics */
182 ret = fwrite(res->data, 1, res->size, fo);
183 if(ret != res->size)
184 {
185 fclose(fo);
186 error("Error writing %s", outname);
187 }
188 free(res);
189 }
190
191 for(; top; top = top->next)
192 {
193 if(!top->binres)
194 continue;
195
196 ret = fwrite(top->binres->data, 1, top->binres->size, fo);
197 if(ret != top->binres->size)
198 {
199 fclose(fo);
200 error("Error writing %s", outname);
201 }
202 if(win32 && (top->binres->size & 0x03))
203 {
204 /* Write padding */
205 ret = fwrite(zeros, 1, 4 - (top->binres->size & 0x03), fo);
206 if(ret != 4 - (top->binres->size & 0x03))
207 {
208 fclose(fo);
209 error("Error writing %s", outname);
210 }
211 }
212 }
213 fclose(fo);
214}
215
216/*
217 *****************************************************************************
218 * Function : write_s_res
219 * Syntax : void write_s_res(FILE *fp, res_t *res)
220 * Input :
221 * Output :
222 * Description :
223 * Remarks :
224 *****************************************************************************
225*/
226#define BYTESPERLINE 8
227static void write_s_res(FILE *fp, res_t *res)
228{
229 int idx = res->dataidx;
230 int end = res->size;
231 int rest = (end - idx) % BYTESPERLINE;
232 int lines = (end - idx) / BYTESPERLINE;
233 int i, j;
234
235 for(i = 0 ; i < lines; i++)
236 {
237 fprintf(fp, "\t"DIRECTIVE_BYTE"\t");
238 for(j = 0; j < BYTESPERLINE; j++, idx++)
239 {
240 fprintf(fp, ""BYTEFRMT"%s", res->data[idx] & 0xff,
241 j == BYTESPERLINE-1 ? "" : ", ");
242 }
243 fprintf(fp, "\n");
244 }
245 if(rest)
246 {
247 fprintf(fp, "\t"DIRECTIVE_BYTE"\t");
248 for(j = 0; j < rest; j++, idx++)
249 {
250 fprintf(fp, ""BYTEFRMT"%s", res->data[idx] & 0xff,
251 j == rest-1 ? "" : ", ");
252 }
253 fprintf(fp, "\n");
254 }
255}
256#undef BYTESPERLINE
257
258/*
259 *****************************************************************************
260 * Function : write_name_str
261 * Syntax : void write_name_str(FILE *fp, name_id_t *nid)
262 * Input :
263 * Output :
264 * Description :
265 * Remarks : One level self recursive for string type conversion
266 *****************************************************************************
267*/
268static void write_name_str(FILE *fp, name_id_t *nid)
269{
270 res_t res;
271 assert(nid->type == name_str);
272
273 if(!win32 && nid->name.s_name->type == str_char)
274 {
275 res.size = strlen(nid->name.s_name->str.cstr);
276 if(res.size > 254)
277 error("Can't write strings larger than 254 bytes");
278 if(res.size == 0)
279 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
280 res.dataidx = 0;
281 res.data = (char *)xmalloc(res.size + 1);
282 res.data[0] = (char)res.size;
283 res.size++; /* We need to write the length byte as well */
284 strcpy(res.data+1, nid->name.s_name->str.cstr);
285 write_s_res(fp, &res);
286 free(res.data);
287 }
288 else if(!win32 && nid->name.s_name->type == str_unicode)
289 {
290 name_id_t lnid;
291 string_t str;
292
293 lnid.type = name_str;
294 lnid.name.s_name = &str;
295 str.type = str_char;
296 str.str.cstr = dupwstr2cstr(nid->name.s_name->str.wstr);
297 write_name_str(fp, &lnid);
298 free(str.str.cstr);
299 }
300 else if(win32 && nid->name.s_name->type == str_char)
301 {
302 name_id_t lnid;
303 string_t str;
304
305 lnid.type = name_str;
306 lnid.name.s_name = &str;
307 str.type = str_unicode;
308 str.str.wstr = dupcstr2wstr(nid->name.s_name->str.cstr);
309 write_name_str(fp, &lnid);
310 free(str.str.wstr);
311 }
312 else if(win32 && nid->name.s_name->type == str_unicode)
313 {
314 res.size = strlenW(nid->name.s_name->str.wstr);
315 if(res.size > 65534)
316 error("Can't write strings larger than 65534 bytes");
317 if(res.size == 0)
318 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
319 res.dataidx = 0;
320 res.data = (char *)xmalloc((res.size + 1) * 2);
321 ((short *)res.data)[0] = (short)res.size;
322 strcpyW((WCHAR *)(res.data+2), nid->name.s_name->str.wstr);
323 res.size *= 2; /* Function writes bytes, not shorts... */
324 res.size += 2; /* We need to write the length word as well */
325 write_s_res(fp, &res);
326 free(res.data);
327 }
328 else
329 {
330 internal_error(__FILE__, __LINE__, "Hmm, requested to write a string of unknown type %d",
331 nid->name.s_name->type);
332 }
333}
334
335/*
336 *****************************************************************************
337 * Function : find_counter
338 * Syntax : res_count_t *find_counter(name_id_t *type)
339 * Input :
340 * Output :
341 * Description :
342 * Remarks :
343 *****************************************************************************
344*/
345static res_count_t *find_counter(name_id_t *type)
346{
347 int i;
348 for(i = 0; i < rccount; i++)
349 {
350 if(!compare_name_id(type, &(rcarray[i].type)))
351 return &rcarray[i];
352 }
353 return NULL;
354}
355
356/*
357 *****************************************************************************
358 * Function : count_resources
359 * Syntax : res_count_t *count_resources(resource_t *top)
360 * Input :
361 * Output :
362 * Description :
363 * Remarks : The whole lot is converted into arrays because they are
364 * easy sortable. Makes the lot almost unreadable, but it
365 * works (I hope). Basically you have to keep in mind that
366 * the lot is a three-dimensional structure for win32 and a
367 * two-dimensional structure for win16.
368 *****************************************************************************
369*/
370#define RCT(v) (*((resource_t **)(v)))
371/* qsort sorting function */
372static int sort_name_id(const void *e1, const void *e2)
373{
374 return compare_name_id(RCT(e1)->name, RCT(e2)->name);
375}
376
377static int sort_language(const void *e1, const void *e2)
378{
379 assert((RCT(e1)->lan) != NULL);
380 assert((RCT(e2)->lan) != NULL);
381
382 return MAKELANGID(RCT(e1)->lan->id, RCT(e1)->lan->sub)
383 - MAKELANGID(RCT(e2)->lan->id, RCT(e2)->lan->sub);
384}
385#undef RCT
386#define RCT(v) ((res_count_t *)(v))
387static int sort_type(const void *e1, const void *e2)
388{
389 return compare_name_id(&(RCT(e1)->type), &(RCT(e2)->type));
390}
391#undef RCT
392
393static void count_resources(resource_t *top)
394{
395 resource_t *rsc;
396 res_count_t *rcp;
397 name_id_t nid;
398 int i, j;
399
400 for(rsc = top; rsc; rsc = rsc->next)
401 {
402 if(!rsc->binres)
403 continue;
404 switch(rsc->type)
405 {
406 case res_dlgex:
407 nid.name.i_name = WRC_RT_DIALOG;
408 nid.type = name_ord;
409 break;
410 case res_menex:
411 nid.name.i_name = WRC_RT_MENU;
412 nid.type = name_ord;
413 break;
414 case res_usr:
415 nid = *(rsc->res.usr->type);
416 break;
417 default:
418 nid.name.i_name = rsc->type;
419 nid.type = name_ord;
420 }
421
422 if((rcp = find_counter(&nid)) == NULL)
423 {
424 /* Count the number of uniq ids and names */
425
426 if(nid.type == name_ord)
427 n_id_entries++;
428 else
429 n_name_entries++;
430
431 if(!rcarray)
432 {
433 rcarray = (res_count_t *)xmalloc(sizeof(res_count_t));
434 rccount = 1;
435 rcarray[0].count = 1;
436 rcarray[0].type = nid;
437 rcarray[0].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
438 rcarray[0].rscarray[0] = rsc;
439 }
440 else
441 {
442 rccount++;
443 rcarray = (res_count_t *)xrealloc(rcarray, rccount * sizeof(res_count_t));
444 rcarray[rccount-1].count = 1;
445 rcarray[rccount-1].type = nid;
446 rcarray[rccount-1].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
447 rcarray[rccount-1].rscarray[0] = rsc;
448 }
449 }
450 else
451 {
452 rcp->count++;
453 rcp->rscarray = (resource_t **)xrealloc(rcp->rscarray, rcp->count * sizeof(resource_t *));
454 rcp->rscarray[rcp->count-1] = rsc;
455 }
456 }
457
458 if(!win32)
459 {
460 /* We're done, win16 requires no special sorting */
461 return;
462 }
463
464 /* We now have a unsorted list of types with an array of res_count_t
465 * in rcarray[0..rccount-1]. And we have names of one type in the
466 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
467 * The list needs to be sorted for win32's top level tree structure.
468 */
469
470 /* Sort the types */
471 if(rccount > 1)
472 qsort(rcarray, rccount, sizeof(rcarray[0]), sort_type);
473
474 /* Now sort the name-id arrays */
475 for(i = 0; i < rccount; i++)
476 {
477 if(rcarray[i].count > 1)
478 qsort(rcarray[i].rscarray, rcarray[i].count, sizeof(rcarray[0].rscarray[0]), sort_name_id);
479 }
480
481 /* Now split the name-id arrays into name/language
482 * subs. Don't look at the awfull expressions...
483 * We do this by taking the array elements out of rscarray and putting
484 * together a new array in rsc32array.
485 */
486 for(i = 0; i < rccount; i++)
487 {
488 res_count_t *rcap;
489
490 assert(rcarray[i].count >= 1);
491
492 /* rcap points to the current type we are dealing with */
493 rcap = &(rcarray[i]);
494
495 /* Insert the first name-id */
496 rcap->rsc32array = (res32_count_t *)xmalloc(sizeof(res32_count_t));
497 rcap->count32 = 1;
498 rcap->rsc32array[0].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
499 rcap->rsc32array[0].count = 1;
500 rcap->rsc32array[0].rsc[0] = rcap->rscarray[0];
501 if(rcap->rscarray[0]->name->type == name_ord)
502 {
503 rcap->n_id_entries = 1;
504 rcap->n_name_entries = 0;
505 }
506 else
507 {
508 rcap->n_id_entries = 0;
509 rcap->n_name_entries = 1;
510 }
511
512 /* Now loop over the resting resources of the current type
513 * to find duplicate names (which should have different
514 * languages).
515 */
516 for(j = 1; j < rcap->count; j++)
517 {
518 res32_count_t *r32cp;
519
520 /* r32cp points to the current res32_count structure
521 * that holds the resource name we are processing.
522 */
523 r32cp = &(rcap->rsc32array[rcap->count32-1]);
524
525 if(!compare_name_id(r32cp->rsc[0]->name, rcarray[i].rscarray[j]->name))
526 {
527 /* Names are the same, add to list */
528 r32cp->count++;
529 r32cp->rsc = (resource_t **)xrealloc(r32cp->rsc, r32cp->count * sizeof(resource_t *));
530 r32cp->rsc[r32cp->count-1] = rcap->rscarray[j];
531 }
532 else
533 {
534 /* New name-id, sort the old one by
535 * language and create new list
536 */
537 if(r32cp->count > 1)
538 qsort(r32cp->rsc, r32cp->count, sizeof(r32cp->rsc[0]), sort_language);
539 rcap->count32++;
540 rcap->rsc32array = (res32_count_t*)xrealloc(rcap->rsc32array, rcap->count32 * sizeof(res32_count_t));
541 rcap->rsc32array[rcap->count32-1].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
542 rcap->rsc32array[rcap->count32-1].count = 1;
543 rcap->rsc32array[rcap->count32-1].rsc[0] = rcap->rscarray[j];
544
545 if(rcap->rscarray[j]->name->type == name_ord)
546 rcap->n_id_entries++;
547 else
548 rcap->n_name_entries++;
549 }
550 }
551 /* Also sort the languages of the last name group */
552 if(rcap->rsc32array[rcap->count32-1].count > 1)
553 qsort(rcap->rsc32array[rcap->count32-1].rsc,
554 rcap->rsc32array[rcap->count32-1].count,
555 sizeof(rcap->rsc32array[rcap->count32-1].rsc[0]),
556 sort_language);
557 }
558}
559
560/*
561 *****************************************************************************
562 * Function : write_pe_segment
563 * Syntax : void write_pe_segment(FILE *fp)
564 * Input :
565 * Output :
566 * Description :
567 * Remarks :
568 *****************************************************************************
569*/
570static void write_pe_segment(FILE *fp)
571{
572 int i;
573
574 fprintf(fp, "\t"DIRECTIVE_ALIGN"\t4\n");
575 fprintf(fp, "%s%s:\n", prefix, _PEResTab);
576 fprintf(fp, "\t"DIRECTIVE_GLOBAL"\t%s%s\n", prefix, _PEResTab);
577 /* Flags */
578 fprintf(fp, "\t"DIRECTIVE_LONG"\t0\n");
579 /* Time/Date stamp */
580 fprintf(fp, "\t"DIRECTIVE_LONG"\t"LONGFRMT"\n", (long)now);
581 /* Version */
582 fprintf(fp, "\t"DIRECTIVE_LONG"\t0\n"); /* FIXME: must version be filled out? */
583 /* # of id entries, # of name entries */
584 fprintf(fp, "\t"DIRECTIVE_SHORT"\t%d, %d\n", n_name_entries, n_id_entries);
585
586 /* Write the type level of the tree */
587 for(i = 0; i < rccount; i++)
588 {
589 res_count_t *rcp;
590 char *label;
591
592 rcp = &rcarray[i];
593
594 /* TypeId */
595 if(rcp->type.type == name_ord)
596 fprintf(fp, "\t"DIRECTIVE_LONG"\t%d\n", rcp->type.name.i_name);
597 else
598 {
599 char *name = prep_nid_for_label(&(rcp->type));
600 fprintf(fp, "\t"DIRECTIVE_LONG"\t(%s_%s_typename - %s%s) "OR" "HEXBIT31"\n",
601 prefix,
602 name,
603 prefix,
604 _PEResTab);
605 }
606 /* Offset */
607 label = prep_nid_for_label(&(rcp->type));
608 fprintf(fp, "\t"DIRECTIVE_LONG"\t("LOCAL_PREFIX"L%s - %s%s) "OR" "HEXBIT31"\n",
609 label,
610 prefix,
611 _PEResTab);
612 }
613
614 /* Write the name level of the tree */
615
616 for(i = 0; i < rccount; i++)
617 {
618 res_count_t *rcp;
619 char *typelabel;
620 char *namelabel;
621 int j;
622
623 rcp = &rcarray[i];
624
625 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
626 fprintf(fp, ""LOCAL_PREFIX"L%s:\n", typelabel);
627
628 fprintf(fp, "\t"DIRECTIVE_LONG"\t0\n"); /* Flags */
629 fprintf(fp, "\t"DIRECTIVE_LONG"\t"LONGFRMT"\n", (long)now); /* TimeDate */
630 fprintf(fp, "\t"DIRECTIVE_LONG"\t0\n"); /* FIXME: must version be filled out? */
631 fprintf(fp, "\t"DIRECTIVE_SHORT"\t%d, %d\n", rcp->n_name_entries, rcp->n_id_entries);
632 for(j = 0; j < rcp->count32; j++)
633 {
634 resource_t *rsc = rcp->rsc32array[j].rsc[0];
635 /* NameId */
636 if(rsc->name->type == name_ord)
637 fprintf(fp, "\t"DIRECTIVE_LONG"\t%d\n", rsc->name->name.i_name);
638 else
639 {
640 fprintf(fp, "\t"DIRECTIVE_LONG"\t(%s%s_name - %s%s) "OR" "HEXBIT31"\n",
641 prefix,
642 rsc->c_name,
643 prefix,
644 _PEResTab);
645 }
646 /* Maybe FIXME: Unescape the tree (ommit "HEXBIT31") and
647 * put the offset to the resource data entry.
648 * ?? Is unescaping worth while ??
649 */
650 /* Offset */
651 namelabel = prep_nid_for_label(rsc->name);
652 fprintf(fp, "\t"DIRECTIVE_LONG"\t("LOCAL_PREFIX"L%s_%s - %s%s) "OR" "HEXBIT31"\n",
653 typelabel,
654 namelabel,
655 prefix,
656 _PEResTab);
657 }
658 free(typelabel);
659 }
660
661 /* Write the language level of the tree */
662
663 for(i = 0; i < rccount; i++)
664 {
665 res_count_t *rcp;
666 char *namelabel;
667 char *typelabel;
668 int j;
669
670 rcp = &rcarray[i];
671 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
672
673 for(j = 0; j < rcp->count32; j++)
674 {
675 res32_count_t *r32cp = &(rcp->rsc32array[j]);
676 int k;
677
678 namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
679 fprintf(fp, ""LOCAL_PREFIX"L%s_%s:\n", typelabel, namelabel);
680
681 fprintf(fp, "\t"DIRECTIVE_LONG"\t0\n"); /* Flags */
682 fprintf(fp, "\t"DIRECTIVE_LONG"\t"LONGFRMT"\n", (long)now); /* TimeDate */
683 fprintf(fp, "\t"DIRECTIVE_LONG"\t0\n"); /* FIXME: must version be filled out? */
684 fprintf(fp, "\t"DIRECTIVE_SHORT"\t0, %d\n", r32cp->count);
685
686 for(k = 0; k < r32cp->count; k++)
687 {
688 resource_t *rsc = r32cp->rsc[k];
689 assert(rsc->lan != NULL);
690 /* LanguageId */
691 fprintf(fp, "\t"DIRECTIVE_LONG"\t"LONGFRMT"\n", rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
692 /* Offset */
693 fprintf(fp, "\t"DIRECTIVE_LONG"\t"LOCAL_PREFIX"L%s_%s_%d - %s%s\n",
694 typelabel,
695 namelabel,
696 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0,
697 prefix,
698 _PEResTab);
699 }
700 free(namelabel);
701 }
702 free(typelabel);
703 }
704
705 /* Write the resource table itself */
706 fprintf(fp, "%s_ResourceDirectory:\n", prefix);
707 fprintf(fp, "\t"DIRECTIVE_GLOBAL"\t%s_ResourceDirectory\n", prefix);
708 direntries = 0;
709
710 for(i = 0; i < rccount; i++)
711 {
712 res_count_t *rcp;
713 char *namelabel;
714 char *typelabel;
715 int j;
716
717 rcp = &rcarray[i];
718 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
719
720 for(j = 0; j < rcp->count32; j++)
721 {
722 res32_count_t *r32cp = &(rcp->rsc32array[j]);
723 int k;
724
725 namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
726
727 for(k = 0; k < r32cp->count; k++)
728 {
729 resource_t *rsc = r32cp->rsc[k];
730
731 assert(rsc->lan != NULL);
732
733 fprintf(fp, ""LOCAL_PREFIX"L%s_%s_%d:\n",
734 typelabel,
735 namelabel,
736 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
737
738 /* Data RVA */
739 fprintf(fp, "\t"DIRECTIVE_LONG"\t%s%s_data - %s%s\n",
740 prefix,
741 rsc->c_name,
742 prefix,
743 _PEResTab);
744 /* Size */
745 fprintf(fp, "\t"DIRECTIVE_LONG"\t%d\n",
746 rsc->binres->size - rsc->binres->dataidx);
747 /* CodePage */
748 fprintf(fp, "\t"DIRECTIVE_LONG"\t%ld\n", codepage);
749 /* Reserved */
750 fprintf(fp, "\t"DIRECTIVE_LONG"\t0\n");
751
752 direntries++;
753 }
754 free(namelabel);
755 }
756 free(typelabel);
757 }
758}
759
760/*
761 *****************************************************************************
762 * Function : write_ne_segment
763 * Syntax : void write_ne_segment(FILE *fp)
764 * Input :
765 * Output :
766 * Description :
767 * Remarks :
768 *****************************************************************************
769*/
770static void write_ne_segment(FILE *fp)
771{
772 int i, j;
773
774 fprintf(fp, "\t"DIRECTIVE_ALIGN"\t4\n");
775 fprintf(fp, "%s%s:\n", prefix, _NEResTab);
776 fprintf(fp, "\t"DIRECTIVE_GLOBAL"\t%s%s\n", prefix, _NEResTab);
777
778 /* AlignmentShift */
779 fprintf(fp, "\t"DIRECTIVE_SHORT"\t%d\n", alignment_pwr);
780
781 /* TypeInfo */
782 for(i = 0; i < rccount; i++)
783 {
784 res_count_t *rcp = &rcarray[i];
785
786 /* TypeId */
787 if(rcp->type.type == name_ord)
788 fprintf(fp, "\t"DIRECTIVE_SHORT"\t"SHORTFRMT"\n", rcp->type.name.i_name | 0x8000);
789 else
790 fprintf(fp, "\t"DIRECTIVE_SHORT"\t%s_%s_typename - %s%s\n",
791 prefix,
792 rcp->type.name.s_name->str.cstr,
793 prefix,
794 _NEResTab);
795 /* ResourceCount */
796 fprintf(fp, "\t"DIRECTIVE_SHORT"\t%d\n", rcp->count);
797 /* Reserved */
798 fprintf(fp, "\t"DIRECTIVE_LONG"\t0\n");
799 /* NameInfo */
800 for(j = 0; j < rcp->count; j++)
801 {
802/*
803 * VERY IMPORTANT:
804 * The offset is relative to the beginning of the NE resource segment
805 * and _NOT_ to the file-beginning. This is because we do not have a
806 * file based resource, but a simulated NE segment. The offset _is_
807 * scaled by the AlignShift field.
808 * All other things are as the MS doc describes (alignment etc.)
809 */
810 /* Offset */
811 fprintf(fp, "\t"DIRECTIVE_SHORT"\t(%s%s_data - %s%s) >> %d\n",
812 prefix,
813 rcp->rscarray[j]->c_name,
814 prefix,
815 _NEResTab,
816 alignment_pwr);
817 /* Length */
818 fprintf(fp, "\t"DIRECTIVE_SHORT"\t%d\n",
819 (rcp->rscarray[j]->binres->size - rcp->rscarray[j]->binres->dataidx + alignment - 1) >> alignment_pwr);
820 /* Flags */
821 fprintf(fp, "\t"DIRECTIVE_SHORT"\t"SHORTFRMT"\n", (WORD)rcp->rscarray[j]->memopt);
822 /* Id */
823 if(rcp->rscarray[j]->name->type == name_ord)
824 fprintf(fp, "\t"DIRECTIVE_SHORT"\t"SHORTFRMT"\n", rcp->rscarray[j]->name->name.i_name | 0x8000);
825 else
826 fprintf(fp, "\t"DIRECTIVE_SHORT"\t%s%s_name - %s%s\n",
827 prefix,
828 rcp->rscarray[j]->c_name,
829 prefix,
830 _NEResTab);
831 /* Handle and Usage */
832 fprintf(fp, "\t"DIRECTIVE_SHORT"\t0, 0\n");
833 }
834 }
835 /* EndTypes */
836 fprintf(fp, "\t"DIRECTIVE_SHORT"\t0\n");
837}
838
839/*
840 *****************************************************************************
841 * Function : write_rsc_names
842 * Syntax : void write_rsc_names(FILE *fp)
843 * Input :
844 * Output :
845 * Description :
846 * Remarks :
847 *****************************************************************************
848*/
849static void write_rsc_names(FILE *fp)
850{
851 int i, j;
852
853 if(win32)
854 {
855 /* Write the names */
856
857 for(i = 0; i < rccount; i++)
858 {
859 res_count_t *rcp;
860
861 rcp = &rcarray[i];
862
863 if(rcp->type.type == name_str)
864 {
865 char *name = prep_nid_for_label(&(rcp->type));
866 fprintf(fp, "%s_%s_typename:\n",
867 prefix,
868 name);
869 write_name_str(fp, &(rcp->type));
870 }
871
872 for(j = 0; j < rcp->count32; j++)
873 {
874 resource_t *rsc = rcp->rsc32array[j].rsc[0];
875
876 if(rsc->name->type == name_str)
877 {
878 fprintf(fp, "%s%s_name:\n",
879 prefix,
880 rsc->c_name);
881 write_name_str(fp, rsc->name);
882 }
883 }
884 }
885 }
886 else
887 {
888 /* ResourceNames */
889 for(i = 0; i < rccount; i++)
890 {
891 res_count_t *rcp = &rcarray[i];
892
893 if(rcp->type.type == name_str)
894 {
895 fprintf(fp, "%s_%s_typename:\n",
896 prefix,
897 rcp->type.name.s_name->str.cstr);
898 write_name_str(fp, &(rcp->type));
899 }
900 for(j = 0; j < rcp->count; j++)
901 {
902 if(rcp->rscarray[j]->name->type == name_str)
903 {
904 fprintf(fp, "%s%s_name:\n",
905 prefix,
906 rcp->rscarray[j]->c_name);
907 write_name_str(fp, rcp->rscarray[j]->name);
908 }
909 }
910 }
911 /* EndNames */
912
913 /* This is to end the NE resource table */
914 if(create_dir)
915 fprintf(fp, "\t"DIRECTIVE_BYTE"\t0\n");
916 }
917
918 fprintf(fp, "\n");
919}
920
921/*
922 *****************************************************************************
923 * Function : write_s_file
924 * Syntax : void write_s_file(char *outname, resource_t *top)
925 * Input :
926 * outname - Filename to write to
927 * top - The resource-tree to convert
928 * Output :
929 * Description :
930 * Remarks :
931 *****************************************************************************
932*/
933void write_s_file(char *outname, resource_t *top)
934{
935 FILE *fo;
936 resource_t *rsc;
937
938 #ifdef __WIN32OS2__
939 fo = fopen(outname, "w");
940 #else
941 fo = fopen(outname, "wt");
942 #endif
943 if(!fo)
944 {
945 error("Could not open %s\n", outname);
946 return;
947 }
948
949 {
950 char *s, *p;
951 s = ctime(&now);
952 p = strchr(s, '\n');
953 if(p) *p = '\0';
954 fprintf(fo, s_file_head_str, input_name ? input_name : "stdin",
955 cmdline, s);
956 }
957
958 /* Get an idea how many we have and restructure the tables */
959 count_resources(top);
960
961 /* First write the segment tables */
962 if(create_dir)
963 {
964 if(win32)
965 write_pe_segment(fo);
966 else
967 write_ne_segment(fo);
968 }
969
970 /* Dump the names */
971 write_rsc_names(fo);
972
973 if(create_dir)
974 fprintf(fo, LOCAL_PREFIX"LResTabEnd:\n");
975
976 if(!indirect_only)
977 {
978 /* Write the resource data */
979#ifdef MASM
980 fprintf(fo, "\n; Resource binary data */\n\n");
981#else
982 fprintf(fo, "\n/* Resource binary data */\n\n");
983#endif
984 for(rsc = top; rsc; rsc = rsc->next)
985 {
986 if(!rsc->binres)
987 continue;
988
989 fprintf(fo, "\t"DIRECTIVE_ALIGN"\t%d\n", win32 ? 4 : alignment);
990 fprintf(fo, "%s%s_data:\n", prefix, rsc->c_name);
991 if(global)
992 fprintf(fo, "\t"DIRECTIVE_GLOBAL"\t%s%s_data\n", prefix, rsc->c_name);
993
994 write_s_res(fo, rsc->binres);
995
996 fprintf(fo, "\n");
997 }
998
999 if(create_dir)
1000 {
1001 /* Add a resource descriptor for built-in and elf-dlls */
1002 fprintf(fo, "\t"DIRECTIVE_ALIGN"\t4\n");
1003 fprintf(fo, "%s_ResourceDescriptor:\n", prefix);
1004 fprintf(fo, "\t"DIRECTIVE_GLOBAL"\t%s_ResourceDescriptor\n", prefix);
1005 fprintf(fo, "%s_ResourceTable:\n", prefix);
1006 if(global)
1007 fprintf(fo, "\t"DIRECTIVE_GLOBAL"\t%s_ResourceTable\n", prefix);
1008 fprintf(fo, "\t"DIRECTIVE_LONG"\t%s%s\n", prefix, win32 ? _PEResTab : _NEResTab);
1009 fprintf(fo, "%s_NumberOfResources:\n", prefix);
1010 if(global)
1011 fprintf(fo, "\t"DIRECTIVE_GLOBAL"\t%s_NumberOfResources\n", prefix);
1012 fprintf(fo, "\t"DIRECTIVE_LONG"\t%d\n", direntries);
1013 fprintf(fo, "%s_ResourceSectionSize:\n", prefix);
1014 if(global)
1015 fprintf(fo, "\t"DIRECTIVE_GLOBAL"\t%s_ResourceSectionSize\n", prefix);
1016 fprintf(fo, "\t"DIRECTIVE_LONG"\t"LOCAL_PREFIX"LResTabEnd - %s%s\n", prefix, win32 ? _PEResTab : _NEResTab);
1017 if(win32)
1018 {
1019 fprintf(fo, "%s_ResourcesEntries:\n", prefix);
1020 if(global)
1021 fprintf(fo, "\t"DIRECTIVE_GLOBAL"\t%s_ResourcesEntries\n", prefix);
1022 fprintf(fo, "\t"DIRECTIVE_LONG"\t%s_ResourceDirectory\n", prefix);
1023 }
1024 }
1025 }
1026
1027 if(indirect)
1028 {
1029 /* Write the indirection structures */
1030 fprintf(fo, "\n/* Resource indirection structures */\n\n");
1031 fprintf(fo, "\t"DIRECTIVE_ALIGN"\t4\n");
1032 for(rsc = top; rsc; rsc = rsc->next)
1033 {
1034 int type;
1035 char *type_name = NULL;
1036
1037 if(!rsc->binres)
1038 continue;
1039
1040 switch(rsc->type)
1041 {
1042 case res_menex:
1043 type = WRC_RT_MENU;
1044 break;
1045 case res_dlgex:
1046 type = WRC_RT_DIALOG;
1047 break;
1048 case res_usr:
1049 assert(rsc->res.usr->type != NULL);
1050 type_name = prep_nid_for_label(rsc->res.usr->type);
1051 type = 0;
1052 break;
1053 default:
1054 type = rsc->type;
1055 }
1056
1057 /*
1058 * This follows a structure like:
1059 * struct wrc_resource {
1060 * INT32 id;
1061 * RSCNAME *resname;
1062 * INT32 restype;
1063 * RSCNAME *typename;
1064 * void *data;
1065 * UINT32 datasize;
1066 * };
1067 * The 'RSCNAME' is a pascal-style string where the
1068 * first byte/word denotes the size and the rest the string
1069 * itself.
1070 */
1071 fprintf(fo, "%s%s:\n", prefix, rsc->c_name);
1072 if(global)
1073 fprintf(fo, "\t"DIRECTIVE_GLOBAL"\t%s%s\n", prefix, rsc->c_name);
1074 fprintf(fo, "\t"DIRECTIVE_LONG"\t%d, %s%s%s, %d, %s%s%s%s, %s%s_data, %d\n",
1075 rsc->name->type == name_ord ? rsc->name->name.i_name : 0,
1076 rsc->name->type == name_ord ? "0" : prefix,
1077 rsc->name->type == name_ord ? "" : rsc->c_name,
1078 rsc->name->type == name_ord ? "" : "_name",
1079 type,
1080 type ? "0" : prefix,
1081 type ? "" : "_",
1082 type ? "" : type_name,
1083 type ? "" : "_typename",
1084 prefix,
1085 rsc->c_name,
1086 rsc->binres->size - rsc->binres->dataidx);
1087 fprintf(fo, "\n");
1088 }
1089 fprintf(fo, "\n");
1090
1091 /* Write the indirection table */
1092 fprintf(fo, "/* Resource indirection table */\n\n");
1093 fprintf(fo, "\t"DIRECTIVE_ALIGN"\t4\n");
1094 fprintf(fo, "%s%s:\n", prefix, _ResTable);
1095 fprintf(fo, "\t"DIRECTIVE_GLOBAL"\t%s%s\n", prefix, _ResTable);
1096 for(rsc = top; rsc; rsc = rsc->next)
1097 {
1098 fprintf(fo, "\t"DIRECTIVE_LONG"\t%s%s\n", prefix, rsc->c_name);
1099 }
1100 fprintf(fo, "\t"DIRECTIVE_LONG"\t0\n");
1101 fprintf(fo, "\n");
1102 }
1103
1104 if(auto_register)
1105 fprintf(fo, s_file_autoreg_str, prefix, _ResTable);
1106
1107 fprintf(fo, s_file_tail_str);
1108 fclose(fo);
1109}
1110
1111/*
1112 *****************************************************************************
1113 * Function : write_h_file
1114 * Syntax : void write_h_file(char *outname, resource_t *top)
1115 * Input :
1116 * outname - Filename to write to
1117 * top - The resource-tree to convert
1118 * Output :
1119 * Description :
1120 * Remarks :
1121 *****************************************************************************
1122*/
1123void write_h_file(char *outname, resource_t *top)
1124{
1125 FILE *fo;
1126 resource_t *rsc;
1127 char *h_prefix;
1128
1129#ifdef NEED_UNDERSCORE_PREFIX
1130 h_prefix = prefix + 1;
1131#else
1132 h_prefix = prefix;
1133#endif
1134
1135 #ifdef __WIN32OS2__
1136 fo = fopen(outname, "w");
1137 #else
1138 fo = fopen(outname, "wt");
1139 #endif
1140 if(!fo)
1141 {
1142 error("Could not open %s\n", outname);
1143 }
1144
1145 fprintf(fo, h_file_head_str, input_name ? input_name : "stdin",
1146 cmdline, ctime(&now), (long)now, (long)now);
1147
1148 /* First write the segment tables reference */
1149 if(create_dir)
1150 {
1151 fprintf(fo, "extern %schar %s%s[];\n\n",
1152 constant ? "const " : "",
1153 h_prefix,
1154 win32 ? _PEResTab : _NEResTab);
1155 }
1156
1157 /* Write the resource data */
1158 for(rsc = top; global && rsc; rsc = rsc->next)
1159 {
1160 if(!rsc->binres)
1161 continue;
1162
1163 fprintf(fo, "extern %schar %s%s_data[];\n",
1164 constant ? "const " : "",
1165 h_prefix,
1166 rsc->c_name);
1167 }
1168
1169 if(indirect)
1170 {
1171 if(global)
1172 fprintf(fo, "\n");
1173
1174 /* Write the indirection structures */
1175 for(rsc = top; global && rsc; rsc = rsc->next)
1176 {
1177 fprintf(fo, "extern %swrc_resource%d_t %s%s;\n",
1178 constant ? "const " : "",
1179 win32 ? 32 : 16,
1180 h_prefix,
1181 rsc->c_name);
1182 }
1183
1184 if(global)
1185 fprintf(fo, "\n");
1186
1187 /* Write the indirection table */
1188 fprintf(fo, "extern %swrc_resource%d_t %s%s[];\n\n",
1189 constant ? "const " : "",
1190 win32 ? 32 : 16,
1191 h_prefix,
1192 _ResTable);
1193 }
1194
1195 fprintf(fo, h_file_tail_str);
1196 fclose(fo);
1197}
1198
Note: See TracBrowser for help on using the repository browser.