2 * Write .res, .s and .h file(s) from a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
21 char s_file_head_str[] =
23 "# This file is generated with wrc version " WRC_FULLVERSION ". Do not edit!\n"
31 char s_file_tail_str[] =
35 char s_file_autoreg_str[] =
39 #ifdef NEED_UNDERSCORE_PREFIX
40 "\tcall\t_LIBRES_RegisterResources\n"
42 "\tcall\tLIBRES_RegisterResources\n"
46 "\t.section .ctors,\"aw\"\n"
47 "\t.long\t.LAuto_Register\n\n"
50 char h_file_head_str[] =
52 " * This file is generated with wrc version " WRC_FULLVERSION ". Do not edit!\n"
57 "#ifndef __%08x_H\n" /* This becomes the data of compile */
58 "#define __%08x_H\n\n"
59 "#ifndef __WRC_RSC_H\n"
60 "#include <wrc_rsc.h>\n"
64 char h_file_tail_str[] =
69 char _NEResTab[] = "_NEResTab";
70 char _PEResTab[] = "_PEResTab";
71 char _ResTable[] = "_ResTable";
73 res_count_t *rcarray = NULL;
76 int n_name_entries = 0;
81 *****************************************************************************
82 * Function : write_resfile
83 * Syntax : void write_resfile(char *outname, resource_t *top)
85 * outname - Filename to write to
86 * top - The resource-tree to convert
90 *****************************************************************************
92 void write_resfile(char *outname, resource_t *top)
96 char zeros[3] = {0, 0, 0};
98 fo = fopen(outname, "wb");
101 error("Could not open %s\n", outname);
106 /* Put an empty resource first to signal win32 format */
107 res_t *res = new_res();
108 put_dword(res, 0); /* ResSize */
109 put_dword(res, 0x00000020); /* HeaderSize */
110 put_word(res, 0xffff); /* ResType */
112 put_word(res, 0xffff); /* ResName */
114 put_dword(res, 0); /* DataVersion */
115 put_word(res, 0); /* Memory options */
116 put_word(res, 0); /* Language */
117 put_dword(res, 0); /* Version */
118 put_dword(res, 0); /* Charateristics */
119 ret = fwrite(res->data, 1, res->size, fo);
123 error("Error writing %s", outname);
128 for(; top; top = top->next)
133 ret = fwrite(top->binres->data, 1, top->binres->size, fo);
134 if(ret != top->binres->size)
137 error("Error writing %s", outname);
139 if(win32 && (top->binres->size & 0x03))
142 ret = fwrite(zeros, 1, 4 - (top->binres->size & 0x03), fo);
143 if(ret != 4 - (top->binres->size & 0x03))
146 error("Error writing %s", outname);
154 *****************************************************************************
155 * Function : write_s_res
156 * Syntax : void write_s_res(FILE *fp, res_t *res)
161 *****************************************************************************
163 #define BYTESPERLINE 8
164 void write_s_res(FILE *fp, res_t *res)
166 int idx = res->dataidx;
168 int rest = (end - idx) % BYTESPERLINE;
169 int lines = (end - idx) / BYTESPERLINE;
172 for(i = 0 ; i < lines; i++)
174 fprintf(fp, "\t.byte\t");
175 for(j = 0; j < BYTESPERLINE; j++, idx++)
177 fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
178 j == BYTESPERLINE-1 ? "" : ", ");
184 fprintf(fp, "\t.byte\t");
185 for(j = 0; j < rest; j++, idx++)
187 fprintf(fp, "0x%02x%s", res->data[idx] & 0xff,
188 j == rest-1 ? "" : ", ");
195 *****************************************************************************
196 * Function : write_name_str
197 * Syntax : void write_name_str(FILE *fp, name_id_t *nid)
201 * Remarks : One level self recursive for string type conversion
202 *****************************************************************************
204 void write_name_str(FILE *fp, name_id_t *nid)
207 assert(nid->type == name_str);
209 if(!win32 && nid->name.s_name->type == str_char)
211 res.size = strlen(nid->name.s_name->str.cstr) + 1;
213 error("Can't write strings larger than 254 bytes");
215 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
217 res.data = (char *)xmalloc(res.size);
218 res.data[0] = (char)res.size;
219 strcpy(res.data+1, nid->name.s_name->str.cstr);
220 write_s_res(fp, &res);
223 else if(!win32 && nid->name.s_name->type == str_unicode)
228 lnid.type = name_str;
229 lnid.name.s_name = &str;
231 str.str.cstr = dupwstr2cstr(nid->name.s_name->str.wstr);
232 write_name_str(fp, &lnid);
235 else if(win32 && nid->name.s_name->type == str_char)
240 lnid.type = name_str;
241 lnid.name.s_name = &str;
242 str.type = str_unicode;
243 str.str.wstr = dupcstr2wstr(nid->name.s_name->str.cstr);
244 write_name_str(fp, &lnid);
247 else if(win32 && nid->name.s_name->type == str_unicode)
249 res.size = wstrlen(nid->name.s_name->str.wstr) + 1;
251 error("Can't write strings larger than 65534 bytes");
253 internal_error(__FILE__, __LINE__, "Attempt to write empty string");
255 res.data = (char *)xmalloc(res.size * 2);
256 ((short *)res.data)[0] = (char)res.size;
257 wstrcpy((short *)(res.data+2), nid->name.s_name->str.wstr);
258 res.size *= 2; /* Function writes bytes, not shorts... */
259 write_s_res(fp, &res);
264 internal_error(__FILE__, __LINE__, "Hmm, requested to write a string of unknown type %d",
265 nid->name.s_name->type);
270 *****************************************************************************
271 * Function : compare_name_id
272 * Syntax : int compare_name_id(name_id_t *n1, name_id_t *n2)
277 *****************************************************************************
279 int compare_name_id(name_id_t *n1, name_id_t *n2)
281 if(n1->type == name_ord && n2->type == name_ord)
283 return n1->name.i_name - n2->name.i_name;
285 else if(n1->type == name_str && n2->type == name_str)
287 if(n1->name.s_name->type == str_char
288 && n2->name.s_name->type == str_char)
290 return stricmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr);
292 else if(n1->name.s_name->type == str_unicode
293 && n2->name.s_name->type == str_unicode)
295 return wstricmp(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr);
299 internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type");
302 else if(n1->type == name_ord && n2->type == name_str)
304 else if(n1->type == name_str && n2->type == name_ord)
307 internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)",
310 return 0; /* Keep the compiler happy */
314 *****************************************************************************
315 * Function : find_counter
316 * Syntax : res_count_t *find_counter(name_id_t *type)
321 *****************************************************************************
323 res_count_t *find_counter(name_id_t *type)
326 for(i = 0; i < rccount; i++)
328 if(!compare_name_id(type, &(rcarray[i].type)))
335 *****************************************************************************
336 * Function : count_resources
337 * Syntax : res_count_t *count_resources(resource_t *top)
341 * Remarks : The whole lot is converted into arrays because they are
342 * easy sortable. Makes the lot almost unreadable, but it
343 * works (I hope). Basically you have to keep in mind that
344 * the lot is a three-dimensional structure for win32 and a
345 * two-dimensional structure for win16.
346 *****************************************************************************
348 #define RCT(v) (*((resource_t **)(v)))
349 /* qsort sorting function */
350 int sort_name_id(const void *e1, const void *e2)
352 return compare_name_id(RCT(e1)->name, RCT(e2)->name);
355 int sort_language(const void *e1, const void *e2)
357 assert((RCT(e1)->lan) != NULL);
358 assert((RCT(e2)->lan) != NULL);
360 return MAKELANGID(RCT(e1)->lan->id, RCT(e1)->lan->sub)
361 - MAKELANGID(RCT(e2)->lan->id, RCT(e2)->lan->sub);
364 #define RCT(v) ((res_count_t *)(v))
365 int sort_type(const void *e1, const void *e2)
367 return compare_name_id(&(RCT(e1)->type), &(RCT(e2)->type));
371 void count_resources(resource_t *top)
378 for(rsc = top; rsc; rsc = rsc->next)
385 nid.name.i_name = WRC_RT_DIALOG;
389 nid.name.i_name = WRC_RT_MENU;
393 nid = *(rsc->res.usr->type);
396 nid.name.i_name = rsc->type;
400 if((rcp = find_counter(&nid)) == NULL)
402 /* Count the number of uniq ids and names */
404 if(nid.type == name_ord)
411 rcarray = (res_count_t *)xmalloc(sizeof(res_count_t));
413 rcarray[0].count = 1;
414 rcarray[0].type = nid;
415 rcarray[0].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
416 rcarray[0].rscarray[0] = rsc;
421 rcarray = (res_count_t *)xrealloc(rcarray, rccount * sizeof(res_count_t));
422 rcarray[rccount-1].count = 1;
423 rcarray[rccount-1].type = nid;
424 rcarray[rccount-1].rscarray = (resource_t **)xmalloc(sizeof(resource_t *));
425 rcarray[rccount-1].rscarray[0] = rsc;
431 rcp->rscarray = (resource_t **)xrealloc(rcp->rscarray, rcp->count * sizeof(resource_t *));
432 rcp->rscarray[rcp->count-1] = rsc;
438 /* We're done, win16 requires no special sorting */
442 /* We now have a unsorted list of types with an array of res_count_t
443 * in rcarray[0..rccount-1]. And we have names of one type in the
444 * rcarray[x].rsc[0..rcarray[x].count-1] arrays.
445 * The list needs to be sorted for win32's top level tree structure.
450 qsort(rcarray, rccount, sizeof(rcarray[0]), sort_type);
452 /* Now sort the name-id arrays */
453 for(i = 0; i < rccount; i++)
455 if(rcarray[i].count > 1)
456 qsort(rcarray[i].rscarray, rcarray[i].count, sizeof(rcarray[0].rscarray[0]), sort_name_id);
459 /* Now split the name-id arrays into name/language
460 * subs. Don't look at the awfull expressions...
461 * We do this by taking the array elements out of rscarray and putting
462 * together a new array in rsc32array.
464 for(i = 0; i < rccount; i++)
468 assert(rcarray[i].count >= 1);
470 /* rcap points to the current type we are dealing with */
471 rcap = &(rcarray[i]);
473 /* Insert the first name-id */
474 rcap->rsc32array = (res32_count_t *)xmalloc(sizeof(res32_count_t));
476 rcap->rsc32array[0].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
477 rcap->rsc32array[0].count = 1;
478 rcap->rsc32array[0].rsc[0] = rcap->rscarray[0];
479 if(rcap->rscarray[0]->name->type == name_ord)
481 rcap->n_id_entries = 1;
482 rcap->n_name_entries = 0;
486 rcap->n_id_entries = 0;
487 rcap->n_name_entries = 1;
490 /* Now loop over the resting resources of the current type
491 * to find duplicate names (which should have different
494 for(j = 1; j < rcap->count; j++)
496 res32_count_t *r32cp;
498 /* r32cp points to the current res32_count structure
499 * that holds the resource name we are processing.
501 r32cp = &(rcap->rsc32array[rcap->count32-1]);
503 if(!compare_name_id(r32cp->rsc[0]->name, rcarray[i].rscarray[j]->name))
505 /* Names are the same, add to list */
507 r32cp->rsc = (resource_t **)xrealloc(r32cp->rsc, r32cp->count * sizeof(resource_t *));
508 r32cp->rsc[r32cp->count-1] = rcap->rscarray[j];
510 if(rcap->rscarray[j]->name->type == name_ord)
512 rcap->n_id_entries = 1;
513 rcap->n_name_entries = 0;
517 rcap->n_id_entries = 0;
518 rcap->n_name_entries = 1;
523 /* New name-id, sort the old one by
524 * language and create new list
527 qsort(r32cp->rsc, r32cp->count, sizeof(r32cp->rsc[0]), sort_language);
529 rcap->rsc32array = (res32_count_t*)xrealloc(rcap->rsc32array, rcap->count32 * sizeof(res32_count_t));
530 rcap->rsc32array[rcap->count32-1].rsc = (resource_t **)xmalloc(sizeof(resource_t *));
531 rcap->rsc32array[rcap->count32-1].count = 1;
532 rcap->rsc32array[rcap->count32-1].rsc[0] = rcap->rscarray[j];
534 if(rcap->rscarray[j]->name->type == name_ord)
535 rcap->n_id_entries++;
537 rcap->n_name_entries++;
540 /* Also sort the languages of the last name group */
541 if(rcap->rsc32array[rcap->count32-1].count > 1)
542 qsort(rcap->rsc32array[rcap->count32-1].rsc,
543 rcap->rsc32array[rcap->count32-1].count,
544 sizeof(rcap->rsc32array[rcap->count32-1].rsc[0]),
550 *****************************************************************************
551 * Function : write_pe_segment
552 * Syntax : void write_pe_segment(FILE *fp, resource_t *top)
557 *****************************************************************************
559 void write_pe_segment(FILE *fp, resource_t *top)
563 fprintf(fp, "\t.align\t4\n");
564 fprintf(fp, "%s%s:\n", prefix, _PEResTab);
565 fprintf(fp, "\t.globl\t%s%s\n", prefix, _PEResTab);
567 fprintf(fp, "\t.long\t0\n");
568 /* Time/Date stamp */
569 fprintf(fp, "\t.long\t0x%08lx\n", now);
571 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
572 /* # of id entries, # of name entries */
573 fprintf(fp, "\t.short\t%d, %d\n", n_name_entries, n_id_entries);
575 /* Write the type level of the tree */
576 for(i = 0; i < rccount; i++)
584 if(rcp->type.type == name_ord)
585 fprintf(fp, "\t.long\t%d\n", rcp->type.name.i_name);
588 char *name = prep_nid_for_label(&(rcp->type));
589 fprintf(fp, "\t.long\t(%s_%s_typename - %s%s) | 0x80000000\n",
596 label = prep_nid_for_label(&(rcp->type));
597 fprintf(fp, "\t.long\t(.L%s - %s%s) | 0x80000000\n",
603 /* Write the name level of the tree */
605 for(i = 0; i < rccount; i++)
614 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
615 fprintf(fp, ".L%s:\n", typelabel);
617 fprintf(fp, "\t.long\t0\n"); /* Flags */
618 fprintf(fp, "\t.long\t0x%08lx\n", now); /* TimeDate */
619 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
620 fprintf(fp, "\t.short\t%d, %d\n", rcp->n_name_entries, rcp->n_id_entries);
621 for(j = 0; j < rcp->count32; j++)
623 resource_t *rsc = rcp->rsc32array[j].rsc[0];
625 if(rsc->name->type == name_ord)
626 fprintf(fp, "\t.long\t%d\n", rsc->name->name.i_name);
629 fprintf(fp, "\t.long\t(%s%s_name - %s%s) | 0x80000000\n",
635 /* Maybe FIXME: Unescape the tree (ommit 0x80000000) and
636 * put the offset to the resource data entry.
637 * ?? Is unescaping worth while ??
640 namelabel = prep_nid_for_label(rsc->name);
641 fprintf(fp, "\t.long\t(.L%s_%s - %s%s) | 0x80000000\n",
650 /* Write the language level of the tree */
652 for(i = 0; i < rccount; i++)
660 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
662 for(j = 0; j < rcp->count32; j++)
664 res32_count_t *r32cp = &(rcp->rsc32array[j]);
667 namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
668 fprintf(fp, ".L%s_%s:\n", typelabel, namelabel);
670 fprintf(fp, "\t.long\t0\n"); /* Flags */
671 fprintf(fp, "\t.long\t0x%08lx\n", now); /* TimeDate */
672 fprintf(fp, "\t.long\t0\n"); /* FIXME: must version be filled out? */
673 fprintf(fp, "\t.short\t0, %d\n", r32cp->count);
675 for(k = 0; k < r32cp->count; k++)
677 resource_t *rsc = r32cp->rsc[k];
678 assert(rsc->lan != NULL);
680 fprintf(fp, "\t.long\t0x%08x\n", rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
682 fprintf(fp, "\t.long\t.L%s_%s_%d - %s%s\n",
685 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0,
694 /* Write the resource table itself */
696 for(i = 0; i < rccount; i++)
704 typelabel = xstrdup(prep_nid_for_label(&(rcp->type)));
706 for(j = 0; j < rcp->count32; j++)
708 res32_count_t *r32cp = &(rcp->rsc32array[j]);
711 namelabel = xstrdup(prep_nid_for_label(r32cp->rsc[0]->name));
713 for(k = 0; k < r32cp->count; k++)
715 resource_t *rsc = r32cp->rsc[k];
717 assert(rsc->lan != NULL);
719 fprintf(fp, ".L%s_%s_%d:\n",
722 rsc->lan ? MAKELANGID(rsc->lan->id, rsc->lan->sub) : 0);
725 fprintf(fp, "\t.long\t%s%s_data - %s%s\n",
731 fprintf(fp, "\t.long\t%d\n",
732 rsc->binres->size - rsc->binres->dataidx);
734 fprintf(fp, "\t.long\t%ld\n", codepage);
736 fprintf(fp, "\t.long\t0\n");
746 *****************************************************************************
747 * Function : write_ne_segment
748 * Syntax : void write_ne_segment(FILE *fp, resource_t *top)
753 *****************************************************************************
755 void write_ne_segment(FILE *fp, resource_t *top)
759 fprintf(fp, "\t.align\t4\n");
760 fprintf(fp, "%s%s:\n", prefix, _NEResTab);
761 fprintf(fp, "\t.globl\t%s%s\n", prefix, _NEResTab);
764 fprintf(fp, "\t.short\t%d\n", alignment_pwr);
767 for(i = 0; i < rccount; i++)
769 res_count_t *rcp = &rcarray[i];
772 if(rcp->type.type == name_ord)
773 fprintf(fp, "\t.short\t0x%04x\n", rcp->type.name.i_name | 0x8000);
775 fprintf(fp, "\t.short\t%s_%s_typename - %s%s\n",
777 rcp->type.name.s_name->str.cstr,
781 fprintf(fp, "\t.short\t%d\n", rcp->count);
783 fprintf(fp, "\t.long\t0\n");
785 for(j = 0; j < rcp->count; j++)
787 /* FIXME: dividing by `alignment` doesn't seem to
788 * work with as (GAS). Shifting results in the
789 * correct behaviour. Maybe an as bug or just my
790 * lack of knowing as expression-syntax.
795 * The offset is relative to the beginning of the NE resource segment
796 * and _NOT_ to the file-beginning. This is because we do not have a
797 * file based resource, but a simulated NE segment. The offset _is_
798 * scaled by the AlignShift field.
799 * All other things are as the MS doc describes (alignment etc.)
801 fprintf(fp, "\t.short\t(%s%s_data - %s%s) >> %d\n",
803 rcp->rscarray[j]->c_name,
808 fprintf(fp, "\t.short\t%d\n",
809 rcp->rscarray[j]->binres->size - rcp->rscarray[j]->binres->dataidx);
811 fprintf(fp, "\t.short\t0x%04x\n", (WORD)rcp->rscarray[j]->memopt);
813 if(rcp->rscarray[j]->name->type == name_ord)
814 fprintf(fp, "\t.short\t0x%04x\n", rcp->rscarray[j]->name->name.i_name | 0x8000);
816 fprintf(fp, "\t.short\t%s%s_name - %s%s\n",
818 rcp->rscarray[j]->c_name,
821 /* Handle and Usage */
822 fprintf(fp, "\t.short\t0, 0\n");
826 fprintf(fp, "\t.short\t0\n");
830 *****************************************************************************
831 * Function : write_rsc_names
832 * Syntax : void write_rsc_names(FILE *fp, resource_t *top)
837 *****************************************************************************
839 void write_rsc_names(FILE *fp, resource_t *top)
845 /* Write the names */
847 for(i = 0; i < rccount; i++)
853 if(rcp->type.type == name_str)
855 char *name = prep_nid_for_label(&(rcp->type));
856 fprintf(fp, "%s_%s_typename:\n",
859 write_name_str(fp, &(rcp->type));
862 for(j = 0; j < rcp->count32; j++)
864 resource_t *rsc = rcp->rsc32array[j].rsc[0];
866 if(rsc->name->type == name_str)
868 fprintf(fp, "%s%s_name:\n",
871 write_name_str(fp, rsc->name);
879 for(i = 0; i < rccount; i++)
881 res_count_t *rcp = &rcarray[i];
883 for(j = 0; j < rcp->count; j++)
885 if(rcp->type.type == name_str)
887 fprintf(fp, "%s_%s_typename:\n",
889 rcp->type.name.s_name->str.cstr);
890 write_name_str(fp, &(rcp->type));
892 if(rcp->rscarray[j]->name->type == name_str)
894 fprintf(fp, "%s%s_name:\n",
896 rcp->rscarray[j]->c_name);
897 write_name_str(fp, rcp->rscarray[j]->name);
903 /* This is to end the NE resource table */
905 fprintf(fp, "\t.byte\t0\n");
912 *****************************************************************************
913 * Function : write_s_file
914 * Syntax : void write_s_file(char *outname, resource_t *top)
916 * outname - Filename to write to
917 * top - The resource-tree to convert
921 *****************************************************************************
923 void write_s_file(char *outname, resource_t *top)
928 fo = fopen(outname, "wt");
931 error("Could not open %s\n", outname);
935 fprintf(fo, s_file_head_str, input_name, cmdline, ctime(&now));
937 /* Get an idea how many we have and restructure the tables */
938 count_resources(top);
940 /* First write the segment tables */
944 write_pe_segment(fo, top);
946 write_ne_segment(fo, top);
950 write_rsc_names(fo, top);
954 /* Write the resource data */
955 fprintf(fo, "#\n# Resource binary data\n#\n");
956 for(rsc = top; rsc; rsc = rsc->next)
961 fprintf(fo, "\t.align\t%d\n", win32 ? 4 : alignment);
962 fprintf(fo, "%s%s_data:\n", prefix, rsc->c_name);
964 fprintf(fo, "\t.globl\t%s%s_data\n", prefix, rsc->c_name);
966 write_s_res(fo, rsc->binres);
974 /* Write the indirection structures */
975 fprintf(fo, "\n#\n# Resource indirection structures\n#\n");
976 fprintf(fo, "\t.align\t4\n");
977 for(rsc = top; rsc; rsc = rsc->next)
980 char *type_name = NULL;
991 type = WRC_RT_DIALOG;
994 assert(rsc->res.usr->type != NULL);
995 type_name = prep_nid_for_label(rsc->res.usr->type);
1003 * This follows a structure like:
1004 * struct wrc_resource {
1008 * RSCNAME *typename;
1012 * The 'RSCNAME' is a pascal-style string where the
1013 * first byte/word denotes the size and the rest the string
1016 fprintf(fo, "%s%s:\n", prefix, rsc->c_name);
1018 fprintf(fo, "\t.globl\t%s%s\n", prefix, rsc->c_name);
1019 fprintf(fo, "\t.long\t%d, %s%s%s, %d, %s%s%s%s, %s%s_data, %d\n",
1020 rsc->name->type == name_ord ? rsc->name->name.i_name : 0,
1021 rsc->name->type == name_ord ? "0" : prefix,
1022 rsc->name->type == name_ord ? "" : rsc->c_name,
1023 rsc->name->type == name_ord ? "" : "_name",
1025 type ? "0" : prefix,
1027 type ? "" : type_name,
1028 type ? "" : "_typename",
1031 rsc->binres->size - rsc->binres->dataidx);
1036 /* Write the indirection table */
1037 fprintf(fo, "#\n# Resource indirection table\n#\n");
1038 fprintf(fo, "\t.align\t4\n");
1039 fprintf(fo, "%s%s:\n", prefix, _ResTable);
1040 fprintf(fo, "\t.globl\t%s%s\n", prefix, _ResTable);
1041 for(rsc = top; rsc; rsc = rsc->next)
1043 fprintf(fo, "\t.long\t%s%s\n", prefix, rsc->c_name);
1045 fprintf(fo, "\t.long\t0\n");
1050 fprintf(fo, s_file_autoreg_str, prefix, _ResTable);
1052 fprintf(fo, s_file_tail_str);
1057 *****************************************************************************
1058 * Function : write_h_file
1059 * Syntax : void write_h_file(char *outname, resource_t *top)
1061 * outname - Filename to write to
1062 * top - The resource-tree to convert
1066 *****************************************************************************
1068 void write_h_file(char *outname, resource_t *top)
1074 #ifdef NEED_UNDERSCORE_PREFIX
1075 h_prefix = prefix + 1;
1080 fo = fopen(outname, "wt");
1083 error("Could not open %s\n", outname);
1087 fprintf(fo, h_file_head_str, input_name, cmdline, ctime(&now), now, now);
1089 /* First write the segment tables reference */
1092 fprintf(fo, "extern %schar %s%s[];\n\n",
1093 constant ? "const " : "",
1095 win32 ? _PEResTab : _NEResTab);
1098 /* Write the resource data */
1099 for(rsc = top; global && rsc; rsc = rsc->next)
1104 fprintf(fo, "extern %schar %s%s_data[];\n",
1105 constant ? "const " : "",
1115 /* Write the indirection structures */
1116 for(rsc = top; global && rsc; rsc = rsc->next)
1118 fprintf(fo, "extern %swrc_resource%d_t %s%s;\n",
1119 constant ? "const " : "",
1128 /* Write the indirection table */
1129 fprintf(fo, "extern %swrc_resource%d_t %s%s[];\n\n",
1130 constant ? "const " : "",
1136 fprintf(fo, h_file_tail_str);