2 * Write .res, .s and .h file(s) from a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
21 #ifdef NEED_UNDERSCORE_PREFIX
22 char Underscore[] = "_";
24 char Underscore[] = "";
27 char s_file_head_str[] =
29 "# This file is generated with wrc version " WRC_FULLVERSION ". Do not edit!\n"
37 char s_file_tail_str[] =
41 char s_file_autoreg_str[] =
45 #ifdef NEED_UNDERSCORE_PREFIX
46 "\tcall\t_LIBRES_RegisterResources\n"
48 "\tcall\tLIBRES_RegisterResources\n"
53 ".stabs \"___CTOR_LIST__\",22,0,0,.LAuto_Register\n\n"
55 "\t.section .ctors,\"aw\"\n"
56 "\t.long\t.LAuto_Register\n\n"
60 char h_file_head_str[] =
62 " * This file is generated with wrc version " WRC_FULLVERSION ". Do not edit!\n"
67 "#ifndef __%08lx_H\n" /* This becomes the date of compile */
68 "#define __%08lx_H\n\n"
69 "#ifndef __WRC_RSC_H\n"
70 "#include <wrc_rsc.h>\n"
74 char h_file_tail_str[] =
79 char _NEResTab[] = "_NEResTab";
80 char _PEResTab[] = "_PEResTab";
81 char _ResTable[] = "_ResTable";
83 /* Variables used for resource sorting */
84 res_count_t *rcarray = NULL; /* Type-level count array */
85 int rccount = 0; /* Nr of entries in the type-level array */
86 int n_id_entries = 0; /* win32 only: Nr of unique ids in the type-level array */
87 int n_name_entries = 0; /* win32 only: Nr of unique namess in the type-level array */
89 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)
98 * outname - Filename to write to
99 * top - The resource-tree to convert
103 *****************************************************************************
105 void write_resfile(char *outname, resource_t *top)
109 char zeros[3] = {0, 0, 0};
111 fo = fopen(outname, "wb");
114 error("Could not open %s\n", outname);
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 */
125 put_word(res, 0xffff); /* ResName */
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);
136 error("Error writing %s", outname);
141 for(; top; top = top->next)
146 ret = fwrite(top->binres->data, 1, top->binres->size, fo);
147 if(ret != top->binres->size)
150 error("Error writing %s", outname);
152 if(win32 && (top->binres->size & 0x03))
155 ret = fwrite(zeros, 1, 4 - (top->binres->size & 0x03), fo);
156 if(ret != 4 - (top->binres->size & 0x03))
159 error("Error writing %s", outname);
167 *****************************************************************************
168 * Function : write_s_res
169 * Syntax : void write_s_res(FILE *fp, res_t *res)
174 *****************************************************************************
176 #define BYTESPERLINE 8
177 void write_s_res(FILE *fp, res_t *res)
179 int idx = res->dataidx;
181 int rest = (end - idx) % BYTESPERLINE;
182 int lines = (end - idx) / BYTESPERLINE;
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 ? "" : ", ");
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 ? "" : ", ");
208 *****************************************************************************
209 * Function : write_name_str
210 * Syntax : void write_name_str(FILE *fp, name_id_t *nid)
214 * Remarks : One level self recursive for string type conversion
215 *****************************************************************************
217 void write_name_str(FILE *fp, name_id_t *nid)
220 assert(nid->type == name_str);
222 if(!win32 && nid->name.s_name->type == str_char)
224 res.size = strlen(nid->name.s_name->str.cstr);
226 error("Can't write strings larger than 254 bytes");
228 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
230 res.data = (char *)xmalloc(res.size + 1);
231 res.data[0] = (char)res.size;
232 res.size++; /* We need to write the lenth byte as well */
233 strcpy(res.data+1, nid->name.s_name->str.cstr);
234 write_s_res(fp, &res);
237 else if(!win32 && nid->name.s_name->type == str_unicode)
242 lnid.type = name_str;
243 lnid.name.s_name = &str;
245 str.str.cstr = dupwstr2cstr(nid->name.s_name->str.wstr);
246 write_name_str(fp, &lnid);
249 else if(win32 && nid->name.s_name->type == str_char)
254 lnid.type = name_str;
255 lnid.name.s_name = &str;
256 str.type = str_unicode;
257 str.str.wstr = dupcstr2wstr(nid->name.s_name->str.cstr);
258 write_name_str(fp, &lnid);
261 else if(win32 && nid->name.s_name->type == str_unicode)
263 res.size = wstrlen(nid->name.s_name->str.wstr);
265 error("Can't write strings larger than 65534 bytes");
267 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
269 res.data = (char *)xmalloc((res.size + 1) * 2);
270 ((short *)res.data)[0] = (short)res.size;
271 wstrcpy((short *)(res.data+2), nid->name.s_name->str.wstr);
272 res.size *= 2; /* Function writes bytes, not shorts... */
273 res.size += 2; /* We need to write the length word as well */
274 write_s_res(fp, &res);
279 internal_error(__FILE__, __LINE__, "Hmm, requested to write a string of unknown type %d",
280 nid->name.s_name->type);
285 *****************************************************************************
286 * Function : compare_name_id
287 * Syntax : int compare_name_id(name_id_t *n1, name_id_t *n2)
292 *****************************************************************************
294 int compare_name_id(name_id_t *n1, name_id_t *n2)
296 if(n1->type == name_ord && n2->type == name_ord)
298 return n1->name.i_name - n2->name.i_name;
300 else if(n1->type == name_str && n2->type == name_str)
302 if(n1->name.s_name->type == str_char
303 && n2->name.s_name->type == str_char)
305 return strcasecmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr);
307 else if(n1->name.s_name->type == str_unicode
308 && n2->name.s_name->type == str_unicode)
310 return wstricmp(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr);
314 internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type");
317 else if(n1->type == name_ord && n2->type == name_str)
319 else if(n1->type == name_str && n2->type == name_ord)
322 internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)",
325 return 0; /* Keep the compiler happy */
329 *****************************************************************************
330 * Function : find_counter
331 * Syntax : res_count_t *find_counter(name_id_t *type)
336 *****************************************************************************
338 res_count_t *find_counter(name_id_t *type)
341 for(i = 0; i < rccount; i++)
343 if(!compare_name_id(type, &(rcarray[i].type)))
350 *****************************************************************************
351 * Function : count_resources
352 * Syntax : res_count_t *count_resources(resource_t *top)
356 * Remarks : The whole lot is converted into arrays because they are
357 * easy sortable. Makes the lot almost unreadable, but it
358 * works (I hope). Basically you have to keep in mind that
359 * the lot is a three-dimensional structure for win32 and a
360 * two-dimensional structure for win16.
361 *****************************************************************************
363 #define RCT(v) (*((resource_t **)(v)))
364 /* qsort sorting function */
365 int sort_name_id(const void *e1, const void *e2)
367 return compare_name_id(RCT(e1)->name, RCT(e2)->name);
370 int sort_language(const void *e1, const void *e2)
372 assert((RCT(e1)->lan) != NULL);
373 assert((RCT(e2)->lan) != NULL);
375 return MAKELANGID(RCT(e1)->lan->id, RCT(e1)->lan->sub)
376 - MAKELANGID(RCT(e2)->lan->id, RCT(e2)->lan->sub);
379 #define RCT(v) ((res_count_t *)(v))
380 int sort_type(const void *e1, const void *e2)
382 return compare_name_id(&(RCT(e1)->type), &(RCT(e2)->type));
386 void count_resources(resource_t *top)
393 for(rsc = top; rsc; rsc = rsc->next)
400 nid.name.i_name = WRC_RT_DIALOG;
404 nid.name.i_name = WRC_RT_MENU;
408 nid = *(rsc->res.usr->type);
411 nid.name.i_name = rsc->type;
415 if((rcp = find_counter(&nid)) == NULL)
417 /* Count the number of uniq ids and names */
419 if(nid.type == name_ord)
426 rcarray = (res_count_t *)xmalloc(sizeof(res_count_t));
428 rcarray[0].count = 1;
429 rcarray[0].type = nid;
430 rcarray[0].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
431 rcarray[0].rscarray[0] = rsc;
436 rcarray = (res_count_t *)xrealloc(rcarray, rccount * sizeof(res_count_t));
437 rcarray[rccount-1].count = 1;
438 rcarray[rccount-1].type = nid;
439 rcarray[rccount-1].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
440 rcarray[rccount-1].rscarray[0] = rsc;
446 rcp->rscarray = (resource_t **)xrealloc(rcp->rscarray, rcp->count * sizeof(resource_t *));
447 rcp->rscarray[rcp->count-1] = rsc;
453 /* We're done, win16 requires no special sorting */
457 /* We now have a unsorted list of types with an array of res_count_t
458 * in rcarray[0..rccount-1]. And we have names of one type in the
459 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
460 * The list needs to be sorted for win32's top level tree structure.
465 qsort(rcarray, rccount, sizeof(rcarray[0]), sort_type);
467 /* Now sort the name-id arrays */
468 for(i = 0; i < rccount; i++)
470 if(rcarray[i].count > 1)
471 qsort(rcarray[i].rscarray, rcarray[i].count, sizeof(rcarray[0].rscarray[0]), sort_name_id);
474 /* Now split the name-id arrays into name/language
475 * subs. Don't look at the awfull expressions...
476 * We do this by taking the array elements out of rscarray and putting
477 * together a new array in rsc32array.
479 for(i = 0; i < rccount; i++)
483 assert(rcarray[i].count >= 1);
485 /* rcap points to the current type we are dealing with */
486 rcap = &(rcarray[i]);
488 /* Insert the first name-id */
489 rcap->rsc32array = (res32_count_t *)xmalloc(sizeof(res32_count_t));
491 rcap->rsc32array[0].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
492 rcap->rsc32array[0].count = 1;
493 rcap->rsc32array[0].rsc[0] = rcap->rscarray[0];
494 if(rcap->rscarray[0]->name->type == name_ord)
496 rcap->n_id_entries = 1;
497 rcap->n_name_entries = 0;
501 rcap->n_id_entries = 0;
502 rcap->n_name_entries = 1;
505 /* Now loop over the resting resources of the current type
506 * to find duplicate names (which should have different
509 for(j = 1; j < rcap->count; j++)
511 res32_count_t *r32cp;
513 /* r32cp points to the current res32_count structure
514 * that holds the resource name we are processing.
516 r32cp = &(rcap->rsc32array[rcap->count32-1]);
518 if(!compare_name_id(r32cp->rsc[0]->name, rcarray[i].rscarray[j]->name))
520 /* Names are the same, add to list */
522 r32cp->rsc = (resource_t **)xrealloc(r32cp->rsc, r32cp->count * sizeof(resource_t *));
523 r32cp->rsc[r32cp->count-1] = rcap->rscarray[j];
527 /* New name-id, sort the old one by
528 * language and create new list
531 qsort(r32cp->rsc, r32cp->count, sizeof(r32cp->rsc[0]), sort_language);
533 rcap->rsc32array = (res32_count_t*)xrealloc(rcap->rsc32array, rcap->count32 * sizeof(res32_count_t));
534 rcap->rsc32array[rcap->count32-1].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
535 rcap->rsc32array[rcap->count32-1].count = 1;
536 rcap->rsc32array[rcap->count32-1].rsc[0] = rcap->rscarray[j];
538 if(rcap->rscarray[j]->name->type == name_ord)
539 rcap->n_id_entries++;
541 rcap->n_name_entries++;
544 /* Also sort the languages of the last name group */
545 if(rcap->rsc32array[rcap->count32-1].count > 1)
546 qsort(rcap->rsc32array[rcap->count32-1].rsc,
547 rcap->rsc32array[rcap->count32-1].count,
548 sizeof(rcap->rsc32array[rcap->count32-1].rsc[0]),
554 *****************************************************************************
555 * Function : write_pe_segment
556 * Syntax : void write_pe_segment(FILE *fp, resource_t *top)
561 *****************************************************************************
563 void write_pe_segment(FILE *fp, resource_t *top)
567 fprintf(fp, "\t.align\t4\n");
568 fprintf(fp, "%s%s:\n", prefix, _PEResTab);
569 fprintf(fp, "\t.globl\t%s%s\n", prefix, _PEResTab);
571 fprintf(fp, "\t.long\t0\n");
572 /* Time/Date stamp */
573 fprintf(fp, "\t.long\t0x%08lx\n", (long)now);
575 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
576 /* # of id entries, # of name entries */
577 fprintf(fp, "\t.short\t%d, %d\n", n_name_entries, n_id_entries);
579 /* Write the type level of the tree */
580 for(i = 0; i < rccount; i++)
588 if(rcp->type.type == name_ord)
589 fprintf(fp, "\t.long\t%d\n", rcp->type.name.i_name);
592 char *name = prep_nid_for_label(&(rcp->type));
593 fprintf(fp, "\t.long\t(%s_%s_typename - %s%s) | 0x80000000\n",
600 label = prep_nid_for_label(&(rcp->type));
601 fprintf(fp, "\t.long\t(.L%s - %s%s) | 0x80000000\n",
607 /* Write the name level of the tree */
609 for(i = 0; i < rccount; i++)
618 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
619 fprintf(fp, ".L%s:\n", typelabel);
621 fprintf(fp, "\t.long\t0\n"); /* Flags */
622 fprintf(fp, "\t.long\t0x%08lx\n", (long)now); /* TimeDate */
623 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
624 fprintf(fp, "\t.short\t%d, %d\n", rcp->n_name_entries, rcp->n_id_entries);
625 for(j = 0; j < rcp->count32; j++)
627 resource_t *rsc = rcp->rsc32array[j].rsc[0];
629 if(rsc->name->type == name_ord)
630 fprintf(fp, "\t.long\t%d\n", rsc->name->name.i_name);
633 char *label = prep_nid_for_label(rsc->name);
634 fprintf(fp, "\t.long\t(%s_%s_name - %s%s) | 0x80000000\n",
640 /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
641 * put the offset to the resource data entry.
642 * ?? Is unescaping worth while ??
645 namelabel = prep_nid_for_label(rsc->name);
646 fprintf(fp, "\t.long\t(.L%s_%s - %s%s) | 0x80000000\n",
655 /* Write the language level of the tree */
657 for(i = 0; i < rccount; i++)
665 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
667 for(j = 0; j < rcp->count32; j++)
669 res32_count_t *r32cp = &(rcp->rsc32array[j]);
672 namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
673 fprintf(fp, ".L%s_%s:\n", typelabel, namelabel);
675 fprintf(fp, "\t.long\t0\n"); /* Flags */
676 fprintf(fp, "\t.long\t0x%08lx\n", (long)now); /* TimeDate */
677 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
678 fprintf(fp, "\t.short\t0, %d\n", r32cp->count);
680 for(k = 0; k < r32cp->count; k++)
682 resource_t *rsc = r32cp->rsc[k];
683 assert(rsc->lan != NULL);
685 fprintf(fp, "\t.long\t0x%08x\n", rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
687 fprintf(fp, "\t.long\t.L%s_%s_%d - %s%s\n",
690 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0,
699 /* Write the resource table itself */
700 fprintf(fp, "%s_ResourceDirectory:\n", prefix);
701 fprintf(fp, "\t.globl\t%s_ResourceDirectory\n", prefix);
704 for(i = 0; i < rccount; 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]);
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",
730 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
733 fprintf(fp, "\t.long\t%s%s_data - %s%s\n",
739 fprintf(fp, "\t.long\t%d\n",
740 rsc->binres->size - rsc->binres->dataidx);
742 fprintf(fp, "\t.long\t%ld\n", codepage);
744 fprintf(fp, "\t.long\t0\n");
755 *****************************************************************************
756 * Function : write_ne_segment
757 * Syntax : void write_ne_segment(FILE *fp, resource_t *top)
762 *****************************************************************************
764 void write_ne_segment(FILE *fp, resource_t *top)
768 fprintf(fp, "\t.align\t4\n");
769 fprintf(fp, "%s%s:\n", prefix, _NEResTab);
770 fprintf(fp, "\t.globl\t%s%s\n", prefix, _NEResTab);
773 fprintf(fp, "\t.short\t%d\n", alignment_pwr);
776 for(i = 0; i < rccount; i++)
778 res_count_t *rcp = &rcarray[i];
781 if(rcp->type.type == name_ord)
782 fprintf(fp, "\t.short\t0x%04x\n", rcp->type.name.i_name | 0x8000);
784 fprintf(fp, "\t.short\t%s_%s_typename - %s%s\n",
786 rcp->type.name.s_name->str.cstr,
790 fprintf(fp, "\t.short\t%d\n", rcp->count);
792 fprintf(fp, "\t.long\t0\n");
794 for(j = 0; j < rcp->count; j++)
798 * The offset is relative to the beginning of the NE resource segment
799 * and _NOT_ to the file-beginning. This is because we do not have a
800 * file based resource, but a simulated NE segment. The offset _is_
801 * scaled by the AlignShift field.
802 * All other things are as the MS doc describes (alignment etc.)
805 fprintf(fp, "\t.short\t(%s%s_data - %s%s) >> %d\n",
807 rcp->rscarray[j]->c_name,
812 fprintf(fp, "\t.short\t%d\n",
813 rcp->rscarray[j]->binres->size - rcp->rscarray[j]->binres->dataidx);
815 fprintf(fp, "\t.short\t0x%04x\n", (WORD)rcp->rscarray[j]->memopt);
817 if(rcp->rscarray[j]->name->type == name_ord)
818 fprintf(fp, "\t.short\t0x%04x\n", rcp->rscarray[j]->name->name.i_name | 0x8000);
820 fprintf(fp, "\t.short\t%s%s_name - %s%s\n",
822 rcp->rscarray[j]->c_name,
825 /* Handle and Usage */
826 fprintf(fp, "\t.short\t0, 0\n");
830 fprintf(fp, "\t.short\t0\n");
834 *****************************************************************************
835 * Function : write_rsc_names
836 * Syntax : void write_rsc_names(FILE *fp, resource_t *top)
841 *****************************************************************************
843 void write_rsc_names(FILE *fp, resource_t *top)
849 /* Write the names */
851 for(i = 0; i < rccount; i++)
857 if(rcp->type.type == name_str)
859 char *name = prep_nid_for_label(&(rcp->type));
860 fprintf(fp, "%s_%s_typename:\n",
863 write_name_str(fp, &(rcp->type));
866 for(j = 0; j < rcp->count32; j++)
868 resource_t *rsc = rcp->rsc32array[j].rsc[0];
870 if(rsc->name->type == name_str)
872 char *name = prep_nid_for_label(rsc->name);
873 fprintf(fp, "%s_%s_name:\n",
876 write_name_str(fp, rsc->name);
884 for(i = 0; i < rccount; i++)
886 res_count_t *rcp = &rcarray[i];
888 for(j = 0; j < rcp->count; j++)
890 if(rcp->type.type == name_str)
892 fprintf(fp, "%s_%s_typename:\n",
894 rcp->type.name.s_name->str.cstr);
895 write_name_str(fp, &(rcp->type));
897 if(rcp->rscarray[j]->name->type == name_str)
899 fprintf(fp, "%s%s_name:\n",
901 rcp->rscarray[j]->c_name);
902 write_name_str(fp, rcp->rscarray[j]->name);
908 /* This is to end the NE resource table */
910 fprintf(fp, "\t.byte\t0\n");
917 *****************************************************************************
918 * Function : write_s_file
919 * Syntax : void write_s_file(char *outname, resource_t *top)
921 * outname - Filename to write to
922 * top - The resource-tree to convert
926 *****************************************************************************
928 void write_s_file(char *outname, resource_t *top)
933 fo = fopen(outname, "wt");
936 error("Could not open %s\n", outname);
940 fprintf(fo, s_file_head_str, input_name ? input_name : "stdin",
941 cmdline, ctime(&now));
943 /* Get an idea how many we have and restructure the tables */
944 count_resources(top);
946 /* First write the segment tables */
950 write_pe_segment(fo, top);
952 write_ne_segment(fo, top);
956 write_rsc_names(fo, top);
959 fprintf(fo, ".LResTabEnd:\n");
963 /* Write the resource data */
964 fprintf(fo, "#\n# Resource binary data\n#\n");
965 for(rsc = top; rsc; rsc = rsc->next)
970 fprintf(fo, "\t.align\t%d\n", win32 ? 4 : alignment);
971 fprintf(fo, "%s%s_data:\n", prefix, rsc->c_name);
973 fprintf(fo, "\t.globl\t%s%s_data\n", prefix, rsc->c_name);
975 write_s_res(fo, rsc->binres);
982 /* Add a resource descriptor for built-in and elf-dlls */
983 fprintf(fo, "\t.align\t4\n");
984 fprintf(fo, "%s_ResourceDescriptor:\n", prefix);
985 fprintf(fo, "\t.globl\t%s_ResourceDescriptor\n", prefix);
986 fprintf(fo, "%s_ResourceTable:\n", prefix);
988 fprintf(fo, "\t.globl\t%s_ResourceTable\n", prefix);
989 fprintf(fo, "\t.long\t%s%s\n", prefix, win32 ? _PEResTab : _NEResTab);
990 fprintf(fo, "%s_NumberOfResources:\n", prefix);
992 fprintf(fo, "\t.globl\t%s_NumberOfResources\n", prefix);
993 fprintf(fo, "\t.long\t%d\n", direntries);
994 fprintf(fo, "%s_ResourceSectionSize:\n", prefix);
996 fprintf(fo, "\t.globl\t%s_ResourceSectionSize\n", prefix);
997 fprintf(fo, "\t.long\t.LResTabEnd - %s%s\n", prefix, win32 ? _PEResTab : _NEResTab);
1000 fprintf(fo, "%s_ResourcesEntries:\n", prefix);
1002 fprintf(fo, "\t.globl\t%s_ResourcesEntries\n", prefix);
1003 fprintf(fo, "\t.long\t%s_ResourceDirectory\n", prefix);
1010 /* Write the indirection structures */
1011 fprintf(fo, "\n#\n# Resource indirection structures\n#\n");
1012 fprintf(fo, "\t.align\t4\n");
1013 for(rsc = top; rsc; rsc = rsc->next)
1016 char *type_name = NULL;
1028 type = WRC_RT_DIALOG;
1031 assert(rsc->res.usr->type != NULL);
1032 type_name = prep_nid_for_label(rsc->res.usr->type);
1040 * This follows a structure like:
1041 * struct wrc_resource {
1045 * RSCNAME *typename;
1049 * The 'RSCNAME' is a pascal-style string where the
1050 * first byte/word denotes the size and the rest the string
1053 fprintf(fo, "%s%s:\n", prefix, rsc->c_name);
1055 fprintf(fo, "\t.globl\t%s%s\n", prefix, rsc->c_name);
1056 label = prep_nid_for_label(rsc->name);
1057 fprintf(fo, "\t.long\t%d, %s%s%s%s, %d, %s%s%s%s, %s%s_data, %d\n",
1058 rsc->name->type == name_ord ? rsc->name->name.i_name : 0,
1059 rsc->name->type == name_ord ? "0" : prefix,
1060 rsc->name->type == name_ord ? "" : "_",
1061 rsc->name->type == name_ord ? "" : label,
1062 rsc->name->type == name_ord ? "" : "_name",
1064 type ? "0" : prefix,
1066 type ? "" : type_name,
1067 type ? "" : "_typename",
1070 rsc->binres->size - rsc->binres->dataidx);
1075 /* Write the indirection table */
1076 fprintf(fo, "#\n# Resource indirection table\n#\n");
1077 fprintf(fo, "\t.align\t4\n");
1078 fprintf(fo, "%s%s:\n", prefix, _ResTable);
1079 fprintf(fo, "\t.globl\t%s%s\n", prefix, _ResTable);
1080 for(rsc = top; rsc; rsc = rsc->next)
1082 fprintf(fo, "\t.long\t%s%s\n", prefix, rsc->c_name);
1084 fprintf(fo, "\t.long\t0\n");
1089 fprintf(fo, s_file_autoreg_str, prefix, _ResTable);
1091 fprintf(fo, s_file_tail_str);
1096 *****************************************************************************
1097 * Function : write_h_file
1098 * Syntax : void write_h_file(char *outname, resource_t *top)
1100 * outname - Filename to write to
1101 * top - The resource-tree to convert
1105 *****************************************************************************
1107 void write_h_file(char *outname, resource_t *top)
1113 #ifdef NEED_UNDERSCORE_PREFIX
1114 h_prefix = prefix + 1;
1119 fo = fopen(outname, "wt");
1122 error("Could not open %s\n", outname);
1126 fprintf(fo, h_file_head_str, input_name ? input_name : "stdin",
1127 cmdline, ctime(&now), (long)now, (long)now);
1129 /* First write the segment tables reference */
1132 fprintf(fo, "extern %schar %s%s[];\n\n",
1133 constant ? "const " : "",
1135 win32 ? _PEResTab : _NEResTab);
1138 /* Write the resource data */
1139 for(rsc = top; global && rsc; rsc = rsc->next)
1144 fprintf(fo, "extern %schar %s%s_data[];\n",
1145 constant ? "const " : "",
1155 /* Write the indirection structures */
1156 for(rsc = top; global && rsc; rsc = rsc->next)
1158 fprintf(fo, "extern %swrc_resource%d_t %s%s;\n",
1159 constant ? "const " : "",
1168 /* Write the indirection table */
1169 fprintf(fo, "extern %swrc_resource%d_t %s%s[];\n\n",
1170 constant ? "const " : "",
1176 fprintf(fo, h_file_tail_str);