Ignore:
Timestamp:
Sep 11, 1999, 4:22:44 AM (26 years ago)
Author:
bird
Message:

A quick and dirty fix to make wrc produce alp compatible assembly code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/wrc/writeres.c

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