[GENINC]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Fri, 13 May 2011 19:19:05 +0000 (19:19 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Fri, 13 May 2011 19:19:05 +0000 (19:19 +0000)
Merge geninc tool from cmake branch

svn path=/trunk/; revision=51706

reactos/tools/geninc/geninc.c

index f1cafd0..410ebcf 100644 (file)
@@ -4,8 +4,210 @@
 #include <stdlib.h>
 #include <string.h>
 
+#ifdef _WIN32
+#define PRIx64 "I64x"
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#else
+#include <stdint.h>
+#define PRIx64 "llx"
+#define _stricmp strcasecmp
+#endif
 
+typedef struct
+{
+    char Type;
+    char Name[55];
+    uint64_t Value;
+} ASMGENDATA;
+
+#define TYPE_END 0
+#define TYPE_RAW 1
+#define TYPE_CONSTANT 2
+#define TYPE_HEADER 3
 
 int main(int argc, char* argv[])
 {
+    FILE *input, *output;
+    ASMGENDATA data;
+    int i, result = -1;
+    int ms_format = 0;
+    char header[20];
+    uint32_t e_lfanew, signature;
+    uint16_t Machine, NumberOfSections, SizeOfOptionalHeader;
+    typedef struct
+    {
+        char Name[8];
+        uint32_t VirtualSize;
+        uint32_t VirtualAddress;
+        uint32_t RawSize;
+        uint32_t RawAddress;
+        uint32_t RelocAddress;
+        uint32_t LineNumbers;
+        uint16_t RelocationsNumber;
+        uint16_t LineNumbersNumber;
+        uint32_t Characteristics;
+    } SECTION;
+    SECTION section;
+
+    if (argc >= 4 && _stricmp(argv[3], "-ms") == 0) ms_format = 1;
+
+    /* Open the input file */
+    input = fopen(argv[1], "rb");
+    if (!input)
+    {
+        fprintf(stderr, "Could not open input file '%s'\n", argv[1]);
+        return -1;
+    }
+
+    /* Open the output file */
+    output = fopen(argv[2], "w");
+    if (!output)
+    {
+        fprintf(stderr, "Could not open output file '%s'\n", argv[2]);
+        return -1;
+    }
+
+    /* Read the DOS header */
+    if (fread(&header, 1, 2, input) != 2)
+    {
+        fprintf(stderr, "Error reading header.\n");
+        goto quit;
+    }
+
+    if (header[0] != 0x4d || header[1] != 0x5a)
+    {
+        fprintf(stderr, "Not a PE file.\n");
+        goto quit;
+    }
+
+    fseek(input, 0x3C, SEEK_SET);
+    if (fread(&e_lfanew, 1, 4, input) != 4)
+    {
+        fprintf(stderr, "Could not read e_lfanew.\n");
+        goto quit;
+    }
+
+    fseek(input, e_lfanew, SEEK_SET);
+    if (fread(&signature, 1, 4, input) != 4)
+    {
+        fprintf(stderr, "Could not read signature.\n");
+        goto quit;
+    }
+
+    /* Verify the PE signature */
+    if (signature != 0x4550)
+    {
+        fprintf(stderr, "Invalid signature: 0x%lx.\n", signature);
+        goto quit;
+    }
+
+    /* Read Machine */
+    fseek(input, e_lfanew + 4, SEEK_SET);
+    if (fread(&Machine, 1, 2, input) != 2)
+    {
+        fprintf(stderr, "Could not read ExportDirectoryRVA.\n");
+        goto quit;
+    }
+
+    if (Machine != 0x14c && Machine != 0x8664)
+    {
+        fprintf(stderr, "Invalid Machine: 0x%x.\n", Machine);
+        goto quit;
+    }
+
+    /* Read NumberOfSections */
+    if (fread(&NumberOfSections, 1, 2, input) != 2)
+    {
+        fprintf(stderr, "Could not read NumberOfSections.\n");
+        goto quit;
+    }
+
+    fseek(input, e_lfanew + 0x14, SEEK_SET);
+    if (fread(&SizeOfOptionalHeader, 1, 2, input) != 2)
+    {
+        fprintf(stderr, "Could not read SizeOfOptionalHeader.\n");
+        goto quit;
+    }
+
+    /* Read the section table */
+    fseek(input, e_lfanew + 0x18 + SizeOfOptionalHeader, SEEK_SET);
+
+    /* Search for the .asmdef section */
+    for (i = 0; i < NumberOfSections; i++)
+    {
+        if (fread(&section, 1, sizeof(SECTION), input) !=  sizeof(SECTION))
+        {
+            fprintf(stderr, "Could not read section.\n");
+            goto quit;
+        }
+
+        if (strcmp(section.Name, ".asmdef") == 0)
+        {
+            break;
+        }
+    }
+
+    if (i == NumberOfSections)
+    {
+        fprintf(stderr, "Could not find section.\n");
+        goto quit;
+    }
+
+    /* Read the section table */
+    fseek(input, section.RawAddress, SEEK_SET);
+
+    while (1)
+    {
+        /* Read one entry */
+        if (fread(&data, 1, sizeof(data), input) != sizeof(data))
+        {
+            fprintf(stderr, "Error reading input file.\n");
+            goto quit;
+        }
+
+        switch(data.Type)
+        {
+            case TYPE_END:
+                break;
+
+            case TYPE_RAW:
+                fprintf(output, "%s\n", data.Name);
+                continue;
+
+            case TYPE_CONSTANT:
+                if (ms_format)
+                {
+                    fprintf(output, "%s equ 0%"PRIx64"h\n", data.Name, data.Value);
+                }
+                else
+                {
+                    fprintf(output, "%s = 0x%"PRIx64"\n", data.Name, data.Value);
+                }
+                continue;
+
+            case TYPE_HEADER:
+                if (ms_format)
+                {
+                    fprintf(output, "\n; %s\n", data.Name);
+                }
+                else
+                {
+                    fprintf(output, "\n/* %s */\n", data.Name);
+                }
+                continue;
+        }
+
+        break;
+    }
+
+    result = 0;
+
+quit:
+    /* Close files */
+    fclose(input);
+    fclose(output);
+
+    return result;
 }