include: Generate rmxftmpl.h from rmxftmpl.x using new build tool. (try 2)

Dylan Smith dylan.ah.smith at gmail.com
Thu Apr 21 14:24:30 CDT 2011


---
 .gitignore           |    2 +
 Make.rules.in        |    4 +-
 Make.vars.in         |    1 +
 include/Makefile.in  |    8 +-
 include/rmxftmpl.x   |  268 ++++++++++++++++++++++++++
 tools/Makefile.in    |    5 +
 tools/binencxftmpl.c |  512 ++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 798 insertions(+), 2 deletions(-)
 create mode 100644 include/rmxftmpl.x
 create mode 100644 tools/binencxftmpl.c

diff --git a/.gitignore b/.gitignore
index 84bddc8..0a6d00d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -216,6 +216,7 @@ include/propsys.h
 include/pstore.h
 include/qedit.h
 include/richole.h
+include/rmxftmpl.h
 include/sensevts.h
 include/servprov.h
 include/shdeprecated.h
@@ -279,6 +280,7 @@ tools/make_ctests
 tools/makedep
 tools/relpath
 tools/sfnt2fnt
+tools/binencxftmpl
 tools/widl/parser.tab.c
 tools/widl/parser.tab.h
 tools/widl/parser.yy.c
diff --git a/Make.rules.in b/Make.rules.in
index cd9c22e..53c7298 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -27,7 +27,7 @@ IDL_GEN_HEADERS = $(IDL_H_SRCS:.idl=.h) $(IDL_C_SRCS:.idl=.h) $(IDL_I_SRCS:.idl=
 CLEAN_FILES   = *.o *.a *.so *.ln *.res *.fake *.$(LIBEXT) \\\#*\\\# *~ *% .\\\#* *.bak *.orig *.rej *.flc core
 CLEAN_TARGETS = $(IDL_GEN_C_SRCS) $(IDL_GEN_HEADERS) $(IDL_TLB_SRCS:.idl=.tlb) $(IDL_P_SRCS:%=dlldata.c) \
                 $(BISON_SRCS:.y=.tab.c) $(BISON_SRCS:.y=.tab.h) $(LEX_SRCS:.l=.yy.c) \
-                $(PO_SRCS:%=rsrc.pot) $(MC_SRCS:%=msg.pot)
+                $(PO_SRCS:%=rsrc.pot) $(MC_SRCS:%=msg.pot) $(XTEMPLATE_SRCS:.x=.h)
 
 OBJS = $(C_SRCS:.c=.o) $(BISON_SRCS:.y=.tab.o) $(LEX_SRCS:.l=.yy.o) $(IDL_GEN_C_SRCS:.c=.o) \
        $(IDL_R_SRCS:.idl=_r.res) $(RC_SRCS:.rc=.res) $(MC_SRCS:.mc=.res) $(EXTRA_OBJS)
@@ -193,6 +193,8 @@ $(PO_SRCS:.rc=.res): $(ALL_PO_FILES)
 
 $(IDL_GEN_HEADERS) $(IDL_GEN_C_SRCS) $(IDL_TLB_SRCS:.idl=.tlb) $(IDL_R_SRCS:.idl=_r.res): $(WIDL)
 
+$(XTEMPLATE_SRCS:.x=.h): $(BINENCXFTMPL)
+
 dummy:
 
 .PHONY: dummy
diff --git a/Make.vars.in b/Make.vars.in
index 93eec22..b3be687 100644
--- a/Make.vars.in
+++ b/Make.vars.in
@@ -62,6 +62,7 @@ WINAPI_CHECK    = $(top_srcdir)/tools/winapi/winapi_check
 BUILDIMAGE      = $(top_srcdir)/tools/buildimage
 C2MAN           = $(top_srcdir)/tools/c2man.pl
 RUNTEST         = $(top_srcdir)/tools/runtest
+BINENCXFTMPL    = $(TOOLSDIR)/tools/binencxftmpl$(TOOLSEXT)
 MAKECTESTS      = $(TOOLSDIR)/tools/make_ctests$(TOOLSEXT)
 MAKEDEP         = $(TOOLSDIR)/tools/makedep$(TOOLSEXT)
 RELPATH         = $(TOOLSDIR)/tools/relpath$(TOOLSEXT)
diff --git a/include/Makefile.in b/include/Makefile.in
index 1155d30..dcc40a1 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -435,6 +435,7 @@ SRCDIR_INCLUDES = \
 	restartmanager.h \
 	richedit.h \
 	rmxfguid.h \
+	rmxftmpl.h \
 	row.idl \
 	rowchg.idl \
 	rpc.h \
@@ -573,11 +574,16 @@ INSTALLDIRS = \
 
 IDL_H_SRCS = $(PUBLIC_IDL_H_SRCS) $(PRIVATE_IDL_H_SRCS)
 
+XTEMPLATE_SRCS = rmxftmpl.x
+
 @MAKE_RULES@
 
 OBJDIR_INCLUDES = $(PUBLIC_IDL_H_SRCS:.idl=.h)
 
-all: $(IDL_H_SRCS:.idl=.h) $(IDL_TLB_SRCS:.idl=.tlb)
+all: $(IDL_H_SRCS:.idl=.h) $(IDL_TLB_SRCS:.idl=.tlb) $(XTEMPLATE_SRCS:.x=.h)
+
+rmxftmpl.h: rmxftmpl.x
+	$(BINENCXFTMPL) -i D3DRM_XTEMPLATES -s D3DRM_XTEMPLATE_BYTES -o $@ $<
 
 install install-dev:: $(OBJDIR_INCLUDES) $(INSTALLDIRS)
 	for f in $(SRCDIR_INCLUDES); do case $$f in \
diff --git a/include/rmxftmpl.x b/include/rmxftmpl.x
new file mode 100644
index 0000000..e7144b0
--- /dev/null
+++ b/include/rmxftmpl.x
@@ -0,0 +1,268 @@
+xof 0302txt 0064
+// Copyright (C) 2011 Dylan Smith
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
+template Header
+{
+    <3D82AB43-62DA-11CF-AB39-0020AF71E433>
+    WORD major;
+    WORD minor;
+    DWORD flags;
+}
+
+template Vector
+{
+    <3D82AB5E-62DA-11CF-AB39-0020AF71E433>
+    FLOAT x;
+    FLOAT y;
+    FLOAT z;
+}
+
+template Coords2d
+{
+    <F6F23F44-7686-11CF-8F52-0040333594A3>
+    FLOAT u;
+    FLOAT v;
+}
+
+template Matrix4x4
+{
+    <F6F23F45-7686-11CF-8F52-0040333594A3>
+    array FLOAT matrix[16];
+}
+
+template ColorRGBA
+{
+    <35FF44E0-6C7C-11CF-8F52-0040333594A3>
+    FLOAT red;
+    FLOAT green;
+    FLOAT blue;
+    FLOAT alpha;
+}
+
+template ColorRGB
+{
+    <D3E16E81-7835-11CF-8F52-0040333594A3>
+    FLOAT red;
+    FLOAT green;
+    FLOAT blue;
+}
+
+template IndexedColor
+{
+    <1630B820-7842-11CF-8F52-0040333594A3>
+    DWORD index;
+    ColorRGBA indexColor;
+}
+
+template Boolean
+{
+    <537DA6A0-CA37-11D0-941C-0080C80CFA7B>
+    DWORD truefalse;
+}
+
+template Boolean2d
+{
+    <4885AE63-78E8-11CF-8F52-0040333594A3>
+    Boolean u;
+    Boolean v;
+}
+
+template MaterialWrap
+{
+    <4885AE60-78E8-11CF-8F52-0040333594A3>
+    Boolean u;
+    Boolean v;
+}
+
+template TextureFilename
+{
+    <A42790E1-7810-11CF-8F52-0040333594A3>
+    STRING filename;
+}
+
+template Material
+{
+    <3D82AB4D-62DA-11CF-AB39-0020AF71E433>
+    ColorRGBA faceColor;
+    FLOAT power;
+    ColorRGB specularColor;
+    ColorRGB emissiveColor;
+    [ ... ]
+}
+
+template MeshFace
+{
+    <3D82AB5F-62DA-11CF-AB39-0020AF71E433>
+    DWORD nFaceVertexIndices;
+    array DWORD faceVertexIndices[nFaceVertexIndices];
+}
+
+template MeshFaceWraps
+{
+    <ED1EC5C0-C0A8-11D0-941C-0080C80CFA7B>
+    DWORD nFaceWrapValues;
+    array Boolean2d faceWrapValues[nFaceWrapValues];
+}
+
+template MeshTextureCoords
+{
+    <F6F23F40-7686-11CF-8F52-0040333594A3>
+    DWORD nTextureCoords;
+    array Coords2d textureCoords[nTextureCoords];
+}
+
+template MeshMaterialList
+{
+    <F6F23F42-7686-11CF-8F52-0040333594A3>
+    DWORD nMaterials;
+    DWORD nFaceIndexes;
+    array DWORD faceIndexes[nFaceIndexes];
+    [ Material ]
+}
+
+template MeshNormals
+{
+    <F6F23F43-7686-11CF-8F52-0040333594A3>
+    DWORD nNormals;
+    array Vector normals[nNormals];
+    DWORD nFaceNormals;
+    array MeshFace faceNormals[nFaceNormals];
+}
+
+template MeshVertexColors
+{
+    <1630B821-7842-11CF-8F52-0040333594A3>
+    DWORD nVertexColors;
+    array IndexedColor vertexColors[nVertexColors];
+}
+
+template Mesh
+{
+    <3D82AB44-62DA-11CF-AB39-0020AF71E433>
+    DWORD nVertices;
+    array Vector vertices[nVertices];
+    DWORD nFaces;
+    array MeshFace faces[nFaces];
+    [ ... ]
+}
+
+template FrameTransformMatrix
+{
+    <F6F23F41-7686-11CF-8F52-0040333594A3>
+    Matrix4x4 frameMatrix;
+}
+
+template Frame
+{
+    <3D82AB46-62DA-11CF-AB39-0020AF71E433>
+    [ ... ]
+}
+
+template FloatKeys
+{
+    <10DD46A9-775B-11CF-8F52-0040333594A3>
+    DWORD nValues;
+    array FLOAT values[nValues];
+}
+
+template TimedFloatKeys
+{
+    <F406B180-7B3B-11CF-8F52-0040333594A3>
+    DWORD time;
+    FloatKeys tfkeys;
+}
+
+template AnimationKey
+{
+    <10DD46A8-775B-11CF-8F52-0040333594A3>
+    DWORD keyType;
+    DWORD nKeys;
+    array TimedFloatKeys keys[nKeys];
+}
+
+template AnimationOptions
+{
+    <E2BF56C0-840F-11CF-8F52-0040333594A3>
+    DWORD openclosed;
+    DWORD positionquality;
+}
+
+template Animation
+{
+    <3D82AB4F-62DA-11CF-AB39-0020AF71E433>
+    [ ... ]
+}
+
+template AnimationSet
+{
+    <3D82AB50-62DA-11CF-AB39-0020AF71E433>
+    [ Animation ]
+}
+
+template InlineData
+{
+    <3A23EEA0-94B1-11D0-AB39-0020AF71E433>
+    [ BINARY ]
+}
+
+template Url
+{
+    <3A23EEA1-94B1-11D0-AB39-0020AF71E433>
+    DWORD nUrls;
+    array STRING urls[nUrls];
+}
+
+template ProgressiveMesh
+{
+    <8A63C360-997D-11D0-941C-0080C80CFA7B>
+    [ Url, InlineData ]
+}
+
+template Guid
+{
+    <A42790E0-7810-11CF-8F52-0040333594A3>
+    DWORD data1;
+    WORD data2;
+    WORD data3;
+    array UCHAR data4[8];
+}
+
+template StringProperty
+{
+    <7F0F21E0-BFE1-11D1-82C0-00A0C9697271>
+    STRING key;
+    STRING value;
+}
+
+template PropertyBag
+{
+    <7F0F21E1-BFE1-11D1-82C0-00A0C9697271>
+    [ StringProperty ]
+}
+
+template ExternalVisual
+{
+    <98116AA0-BDBA-11D1-82C0-00A0C9697271>
+    Guid guidExternalVisual;
+    [ ... ]
+}
+
+template RightHanded
+{
+    <7F5D5EA0-D53A-11D1-82C0-00A0C9697271>
+    DWORD bRightHanded;
+}
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 4c8b238..e6d3f5f 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -3,6 +3,7 @@ EXTRAINCL = @FREETYPEINCL@
 FREETYPELIBS = @FREETYPELIBS@
 
 PROGRAMS = \
+	binencxftmpl$(EXEEXT) \
 	fnt2bdf$(EXEEXT) \
 	fnt2fon$(EXEEXT) \
 	make_ctests$(EXEEXT) \
@@ -18,6 +19,7 @@ EXTRA_MANPAGES = \
 	winemaker.fr.man
 
 C_SRCS = \
+	binencxftmpl.c \
 	fnt2bdf.c \
 	fnt2fon.c \
 	make_ctests.c \
@@ -41,6 +43,9 @@ all: makedep$(EXEEXT) $(PROGRAMS)
 
 @MAKE_RULES@
 
+binencxftmpl$(EXEEXT): binencxftmpl.o
+	$(CC) $(CFLAGS) -o $@ binencxftmpl.o $(LDFLAGS)
+
 makedep$(EXEEXT) $(EXEEXT:%=makedep): makedep.o
 	$(CC) $(CFLAGS) -o $@ makedep.o $(LDFLAGS)
 
diff --git a/tools/binencxftmpl.c b/tools/binencxftmpl.c
new file mode 100644
index 0000000..8c00f8f
--- /dev/null
+++ b/tools/binencxftmpl.c
@@ -0,0 +1,512 @@
+/*
+ * Binary encode X templates from text format.
+ *
+ * Copyright 2011 Dylan Smith
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_GETOPT_H
+# include <getopt.h>
+#endif
+
+#include "windef.h"
+#include "guiddef.h"
+
+#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
+
+#define TOKEN_NAME         1
+#define TOKEN_STRING       2
+#define TOKEN_INTEGER      3
+#define TOKEN_GUID         5
+#define TOKEN_INTEGER_LIST 6
+#define TOKEN_FLOAT_LIST   7
+#define TOKEN_OBRACE      10
+#define TOKEN_CBRACE      11
+#define TOKEN_OPAREN      12
+#define TOKEN_CPAREN      13
+#define TOKEN_OBRACKET    14
+#define TOKEN_CBRACKET    15
+#define TOKEN_OANGLE      16
+#define TOKEN_CANGLE      17
+#define TOKEN_DOT         18
+#define TOKEN_COMMA       19
+#define TOKEN_SEMICOLON   20
+#define TOKEN_TEMPLATE    31
+#define TOKEN_WORD        40
+#define TOKEN_DWORD       41
+#define TOKEN_FLOAT       42
+#define TOKEN_DOUBLE      43
+#define TOKEN_CHAR        44
+#define TOKEN_UCHAR       45
+#define TOKEN_SWORD       46
+#define TOKEN_SDWORD      47
+#define TOKEN_VOID        48
+#define TOKEN_LPSTR       49
+#define TOKEN_UNICODE     50
+#define TOKEN_CSTRING     51
+#define TOKEN_ARRAY       52
+
+struct parser
+{
+    FILE *infile;
+    FILE *outfile;
+    int line_no;
+    UINT bytes_output;
+    BOOL(*write_bytes)(struct parser *parser, const BYTE *data, DWORD size);
+};
+
+struct keyword
+{
+    const char *word;
+    WORD token;
+};
+
+static const struct keyword reserved_words[] = {
+    {"ARRAY", TOKEN_ARRAY},
+    {"CHAR", TOKEN_CHAR},
+    {"CSTRING", TOKEN_CSTRING},
+    {"DOUBLE", TOKEN_DOUBLE},
+    {"DWORD", TOKEN_DWORD},
+    {"FLOAT", TOKEN_FLOAT},
+    {"SDWORD", TOKEN_SDWORD},
+    {"STRING", TOKEN_LPSTR},
+    {"SWORD", TOKEN_SWORD},
+    {"TEMPLATE", TOKEN_TEMPLATE},
+    {"UCHAR", TOKEN_UCHAR},
+    {"UNICODE", TOKEN_UNICODE},
+    {"VOID", TOKEN_VOID},
+    {"WORD", TOKEN_WORD}
+};
+
+static char *program_name;
+
+static inline BOOL read_byte(struct parser *parser, char *byte)
+{
+    int c = fgetc(parser->infile);
+    *byte = c;
+    return c != EOF;
+}
+
+static inline BOOL unread_byte(struct parser *parser, char last_byte)
+{
+    return ungetc(last_byte, parser->infile) != EOF;
+}
+
+static inline BOOL read_bytes(struct parser *parser, void *data, DWORD size)
+{
+    return fread(data, size, 1, parser->infile) > 0;
+}
+
+static BOOL write_c_hex_bytes(struct parser *parser, const BYTE *data, DWORD size)
+{
+    while (size--)
+    {
+        if (parser->bytes_output % 12 == 0)
+            fprintf(parser->outfile, "\n ");
+        fprintf(parser->outfile, " 0x%02x,", *data++);
+        parser->bytes_output++;
+    }
+    return TRUE;
+}
+
+static BOOL write_raw_bytes(struct parser *parser, const BYTE *data, DWORD size)
+{
+    return fwrite(data, size, 1, parser->outfile) > 0;
+}
+
+static inline BOOL write_bytes(struct parser *parser, const void *data, DWORD size)
+{
+    return parser->write_bytes(parser, data, size);
+}
+
+static inline BOOL write_byte(struct parser *parser, BYTE value)
+{
+    return write_bytes(parser, &value, sizeof(value));
+}
+
+static inline BOOL write_word(struct parser *parser, WORD value)
+{
+    return write_bytes(parser, &value, sizeof(value));
+}
+
+static inline BOOL write_dword(struct parser *parser, DWORD value)
+{
+    return write_bytes(parser, &value, sizeof(value));
+}
+
+static int compare_names(const void *a, const void *b)
+{
+    return strcasecmp(*(const char **)a, *(const char **)b);
+}
+
+static BOOL parse_keyword(struct parser *parser, const char *name)
+{
+    const struct keyword *keyword;
+
+    keyword = bsearch(&name, reserved_words, ARRAY_SIZE(reserved_words),
+                      sizeof(reserved_words[0]), compare_names);
+    if (!keyword)
+        return FALSE;
+
+    return write_word(parser, keyword->token);
+}
+
+static BOOL parse_guid(struct parser *parser)
+{
+    char buf[39];
+    GUID guid;
+    DWORD tab[10];
+    BOOL ret;
+    static const char *guidfmt = "<%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X>";
+
+    buf[0] = '<';
+    if (!read_bytes(parser, buf + 1, 37))
+        return FALSE;
+    buf[38] = 0;
+
+    ret = sscanf(buf, guidfmt, &guid.Data1, tab, tab+1, tab+2, tab+3, tab+4, tab+5, tab+6, tab+7, tab+8, tab+9);
+    if (ret != 11) {
+        fprintf(stderr, "%s: Invalid GUID '%s' (line %d)\n",
+                program_name, buf, parser->line_no);
+        return FALSE;
+    }
+
+    guid.Data2 = tab[0];
+    guid.Data3 = tab[1];
+    guid.Data4[0] = tab[2];
+    guid.Data4[1] = tab[3];
+    guid.Data4[2] = tab[4];
+    guid.Data4[3] = tab[5];
+    guid.Data4[4] = tab[6];
+    guid.Data4[5] = tab[7];
+    guid.Data4[6] = tab[8];
+    guid.Data4[7] = tab[9];
+
+    return write_word(parser, TOKEN_GUID) &&
+           write_bytes(parser, &guid, sizeof(guid));
+}
+
+static BOOL parse_name(struct parser *parser)
+{
+    char c;
+    int len = 0;
+    char name[512];
+
+    while (read_byte(parser, &c) && len < sizeof(name) &&
+           (isalnum(c) || c == '_' || c == '-'))
+    {
+        if (len + 1 < sizeof(name))
+            name[len++] = c;
+    }
+    unread_byte(parser, c);
+    name[len] = 0;
+
+    if (parse_keyword(parser, name)) {
+        return TRUE;
+    } else {
+        return write_word(parser, TOKEN_NAME) &&
+               write_dword(parser, len) &&
+               write_bytes(parser, name, len);
+    }
+}
+
+static BOOL parse_number(struct parser *parser)
+{
+    int len = 0;
+    char c;
+    char buffer[512];
+    BOOL dot = FALSE;
+    BOOL ret;
+
+    while (read_byte(parser, &c) &&
+           ((!len && c == '-') || (!dot && c == '.') || isdigit(c)))
+    {
+        if (len + 1 < sizeof(buffer))
+            buffer[len++] = c;
+        if (c == '.')
+            dot = TRUE;
+    }
+    unread_byte(parser, c);
+    buffer[len] = 0;
+
+    if (dot) {
+        float value;
+        ret = sscanf(buffer, "%f", &value);
+        if (!ret)
+            fprintf(stderr, "%s: Invalid float token (line %d).\n",
+                    program_name, parser->line_no);
+        else
+            ret = write_word(parser, TOKEN_FLOAT) &&
+                  write_bytes(parser, &value, sizeof(value));
+    } else {
+        int value;
+        ret = sscanf(buffer, "%d", &value);
+        if (!ret)
+            fprintf(stderr, "%s: Invalid integer token (line %d).\n",
+                    program_name, parser->line_no);
+        else
+            ret = write_word(parser, TOKEN_INTEGER) &&
+                  write_dword(parser, value);
+    }
+
+    return ret;
+}
+
+BOOL parse_token(struct parser *parser)
+{
+    char c;
+
+    if (!read_byte(parser, &c))
+        return FALSE;
+
+    switch (c)
+    {
+        case '\n':
+            parser->line_no++;
+            /* fall through */
+        case '\r':
+        case ' ':
+        case '\t':
+            return TRUE;
+
+        case '{': return write_word(parser, TOKEN_OBRACE);
+        case '}': return write_word(parser, TOKEN_CBRACE);
+        case '[': return write_word(parser, TOKEN_OBRACKET);
+        case ']': return write_word(parser, TOKEN_CBRACKET);
+        case '(': return write_word(parser, TOKEN_OPAREN);
+        case ')': return write_word(parser, TOKEN_CPAREN);
+        case ',': return write_word(parser, TOKEN_COMMA);
+        case ';': return write_word(parser, TOKEN_SEMICOLON);
+        case '.': return write_word(parser, TOKEN_DOT);
+
+        case '/':
+            if (!read_byte(parser, &c) || c != '/') {
+                fprintf(stderr, "%s: Invalid single '/' comment token (line %d).\n",
+                        program_name, parser->line_no);
+                return FALSE;
+            }
+            /* fall through */
+        case '#':
+            while (read_byte(parser, &c) && c != '\n');
+            return c == '\n';
+
+        case '<':
+            return parse_guid(parser);
+
+        case '"':
+        {
+            int len = 0;
+            char buffer[512];
+
+            /* FIXME: Handle '\' (e.g. "valid\"string") */
+            while (read_byte(parser, &c) && c != '"') {
+                if (len + 1 < sizeof(buffer))
+                    buffer[len++] = c;
+            }
+            if (c == EOF) {
+                fprintf(stderr, "%s: Unterminated string (line %d).\n",
+                        program_name, parser->line_no);
+                return FALSE;
+            }
+            return write_word(parser, TOKEN_STRING) &&
+                   write_dword(parser, len) &&
+                   write_bytes(parser, buffer, len);
+        }
+
+        default:
+            unread_byte(parser, c);
+            if (isdigit(c) || c == '-')
+                return parse_number(parser);
+            if (isalpha(c) || c == '_')
+                return parse_name(parser);
+            fprintf(stderr, "%s: Invalid character (%d) to start token (line %d).\n",
+                    program_name, c, parser->line_no);
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void usage(void)
+{
+    fprintf(stderr, "Usage: %s [OPTIONS] INFILE\n"
+                    "Options:\n"
+                    "  -i NAME   Output to a c header file, data in variable NAME\n"
+                    "  -s NAME   In a c header file, define NAME to be the data size\n"
+                    "  -o FILE   Write output to FILE\n",
+                    program_name);
+}
+
+static char *option_inc_var_name = NULL;
+static char *option_inc_size_name = NULL;
+static const char *option_outfile_name = "-";
+
+static char **parse_options(int argc, char **argv)
+{
+    int optc;
+
+    while ((optc = getopt(argc, argv, "hi:o:s:")) != -1)
+    {
+        switch (optc)
+        {
+            case 'h':
+                usage();
+                exit(0);
+            case 'i':
+                option_inc_var_name = strdup(optarg);
+                break;
+            case 'o':
+                option_outfile_name = strdup(optarg);
+                break;
+            case 's':
+                option_inc_size_name = strdup(optarg);
+                break;
+        }
+    }
+    return &argv[optind];
+}
+
+int main(int argc, char **argv)
+{
+    const char *infile_name;
+    int ret = 1;
+    char header[16];
+    struct parser parser;
+    char **args;
+    char *header_name = NULL;
+
+    program_name = argv[0];
+
+    args = parse_options(argc, argv);
+    infile_name = *args++;
+    if (!infile_name || *args)
+    {
+        usage();
+        return 1;
+    }
+
+    parser.infile = stdin;
+    parser.outfile = stdout;
+
+    if (!strcmp(infile_name, "-")) {
+        infile_name = "stdin";
+    } else if (!(parser.infile = fopen(infile_name, "rb"))) {
+        perror(infile_name);
+        goto done;
+    }
+
+    if (!strcmp(option_outfile_name, "-")) {
+        option_outfile_name = "stdout";
+    } else if (!(parser.outfile = fopen(option_outfile_name, "wb"))) {
+        perror(option_outfile_name);
+        goto done;
+    }
+
+    if (!read_bytes(&parser, header, sizeof(header)))
+        goto done;
+    if (strncmp(header, "xof ", 4))
+    {
+        fprintf(stderr, "%s: Invalid magic value '%.4s'\n", program_name, header);
+        goto done;
+    }
+    if (strncmp(header + 4, "0302", 4) && strncmp(header + 4, "0303", 4))
+    {
+        fprintf(stderr, "%s: Unsupported version '%.4s'\n", program_name, header + 4);
+        goto done;
+    }
+    if (strncmp(header + 8, "txt ", 4))
+    {
+        fprintf(stderr, "%s: Only support conversion from text encoded X files.",
+                program_name);
+        goto done;
+    }
+    if (strncmp(header + 12, "0032", 4) && strncmp(header + 12, "0064", 4))
+    {
+        fprintf(stderr, "%s: Only 32-bit or 64-bit float format supported, not '%.4s'.\n",
+                program_name, header + 12);
+        goto done;
+    }
+
+    if (option_inc_var_name)
+    {
+        char *str_ptr;
+
+        header_name = strrchr(option_outfile_name, '/');
+        if (header_name)
+            header_name = strdup(header_name + 1);
+        else
+            header_name = strdup(option_outfile_name);
+        if (!header_name) {
+            fprintf(stderr, "Out of memory\n");
+            goto done;
+        }
+
+        str_ptr = header_name;
+        while (*str_ptr) {
+            if (*str_ptr == '.')
+                *str_ptr++ = '_';
+            else
+                *str_ptr++ = toupper(*str_ptr);
+        }
+
+        fprintf(parser.outfile,
+            "/* File generated automatically from %s; do not edit */\n"
+            "\n"
+            "#ifndef __WINE_%s\n"
+            "#define __WINE_%s\n"
+            "\n"
+            "unsigned char %s[] = {",
+            infile_name, header_name, header_name, option_inc_var_name);
+
+        parser.write_bytes = &write_c_hex_bytes;
+    } else {
+        parser.write_bytes = &write_raw_bytes;
+    }
+
+    parser.bytes_output = 0;
+    if (!write_bytes(&parser, "xof 0302bin 0064", 16))
+        goto done;
+
+    parser.line_no = 1;
+    while (parse_token(&parser));
+
+    if (option_inc_var_name)
+    {
+        fprintf(parser.outfile, "\n};\n\n");
+        if (option_inc_size_name)
+            fprintf(parser.outfile, "#define %s %u\n\n", option_inc_size_name, parser.bytes_output);
+        fprintf(parser.outfile, "#endif /* __WINE_%s */\n", header_name);
+    }
+
+    ret = ferror(parser.outfile) ? 1 : 0;
+done:
+    if (parser.infile) {
+        if (ferror(parser.infile))
+            perror(infile_name);
+        fclose(parser.infile);
+    }
+    if (parser.outfile) {
+        if (ferror(parser.outfile))
+            perror(option_outfile_name);
+        fclose(parser.outfile);
+    }
+    return ret;
+}
-- 
1.7.2.5



More information about the wine-patches mailing list