/* get rid of duplicate resources with different versions */ static void remove_duplicate_resources( DLLSPEC *spec ) { unsigned int i, n; for (i = n = 0; i < spec->nb_resources; i++, n++) { if (i && !cmp_string( &spec->resources[i].type, &spec->resources[i-1].type ) && !cmp_string( &spec->resources[i].name, &spec->resources[i-1].name ) && spec->resources[i].lang == spec->resources[i-1].lang) { if (spec->resources[i].version == spec->resources[i-1].version) { char *type_str = format_res_string( &spec->resources[i].type ); char *name_str = format_res_string( &spec->resources[i].name ); error( "winebuild: duplicate resource type %s name %s language %04x version %08x\n", type_str, name_str, spec->resources[i].lang, spec->resources[i].version ); } else n--; /* replace the previous one */ } if (n < i) spec->resources[n] = spec->resources[i]; } spec->nb_resources = n; }
/* build the 3-level (type,name,language) resource tree */ static struct res_tree *build_resource_tree( DLLSPEC *spec, unsigned int *dir_size ) { unsigned int i, k, n, offset, data_offset; struct res_tree *tree; struct res_type *type = NULL; struct res_name *name = NULL; struct resource *res; qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res ); tree = xmalloc( sizeof(*tree) ); tree->types = NULL; tree->nb_types = 0; for (i = 0; i < spec->nb_resources; i++) { if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type )) /* new type */ { type = add_type( tree, &spec->resources[i] ); name = add_name( type, &spec->resources[i] ); } else if (cmp_string( &spec->resources[i].name, &spec->resources[i-1].name )) /* new name */ { name = add_name( type, &spec->resources[i] ); } else if (spec->resources[i].lang == spec->resources[i-1].lang) { char *type_str = format_res_string( &spec->resources[i].type ); char *name_str = format_res_string( &spec->resources[i].name ); error( "winebuild: duplicate resource type %s name %s language %04x\n", type_str, name_str, spec->resources[i].lang ); } else name->nb_languages++; } /* compute the offsets */ offset = RESDIR_SIZE( tree->nb_types ); for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) { type->dir_offset = offset; offset += RESDIR_SIZE( type->nb_names ); for (n = 0, name = type->names; n < type->nb_names; n++, name++) { name->dir_offset = offset; offset += RESDIR_SIZE( name->nb_languages ); } } data_offset = offset; offset += spec->nb_resources * RESOURCE_DATA_ENTRY_SIZE; for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) { if (type->type->str) { type->name_offset = offset | 0x80000000; offset += (strlenW(type->type->str)+1) * sizeof(WCHAR); } else type->name_offset = type->type->id; for (n = 0, name = type->names; n < type->nb_names; n++, name++) { if (name->name->str) { name->name_offset = offset | 0x80000000; offset += (strlenW(name->name->str)+1) * sizeof(WCHAR); } else name->name_offset = name->name->id; for (k = 0, res = name->res; k < name->nb_languages; k++, res++) { unsigned int entry_offset = (res - spec->resources) * RESOURCE_DATA_ENTRY_SIZE; res->data_offset = data_offset + entry_offset; } } } if (dir_size) *dir_size = (offset + 3) & ~3; return tree; }