4 * Copyright 2008 Christian Costa
6 * This file contains the (internal) driver registration functions,
7 * driver enumeration APIs and DirectDraw creation functions.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/debug.h"
32 #include "d3dxof_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(d3dxof_parsing
);
39 #define MAKEFOUR(a,b,c,d) ((DWORD)a + ((DWORD)b << 8) + ((DWORD)c << 16) + ((DWORD)d << 24))
40 #define XOFFILE_FORMAT_MAGIC MAKEFOUR('x','o','f',' ')
41 #define XOFFILE_FORMAT_VERSION_302 MAKEFOUR('0','3','0','2')
42 #define XOFFILE_FORMAT_VERSION_303 MAKEFOUR('0','3','0','3')
43 #define XOFFILE_FORMAT_BINARY MAKEFOUR('b','i','n',' ')
44 #define XOFFILE_FORMAT_TEXT MAKEFOUR('t','x','t',' ')
45 #define XOFFILE_FORMAT_BINARY_MSZIP MAKEFOUR('b','z','i','p')
46 #define XOFFILE_FORMAT_TEXT_MSZIP MAKEFOUR('t','z','i','p')
47 #define XOFFILE_FORMAT_COMPRESSED MAKEFOUR('c','m','p',' ')
48 #define XOFFILE_FORMAT_FLOAT_BITS_32 MAKEFOUR('0','0','3','2')
49 #define XOFFILE_FORMAT_FLOAT_BITS_64 MAKEFOUR('0','0','6','4')
52 #define TOKEN_STRING 2
53 #define TOKEN_INTEGER 3
55 #define TOKEN_INTEGER_LIST 6
56 #define TOKEN_FLOAT_LIST 7
57 #define TOKEN_OBRACE 10
58 #define TOKEN_CBRACE 11
59 #define TOKEN_OPAREN 12
60 #define TOKEN_CPAREN 13
61 #define TOKEN_OBRACKET 14
62 #define TOKEN_CBRACKET 15
63 #define TOKEN_OANGLE 16
64 #define TOKEN_CANGLE 17
66 #define TOKEN_COMMA 19
67 #define TOKEN_SEMICOLON 20
68 #define TOKEN_TEMPLATE 31
70 #define TOKEN_DWORD 41
71 #define TOKEN_FLOAT 42
72 #define TOKEN_DOUBLE 43
74 #define TOKEN_UCHAR 45
75 #define TOKEN_SWORD 46
76 #define TOKEN_SDWORD 47
78 #define TOKEN_LPSTR 49
79 #define TOKEN_UNICODE 50
80 #define TOKEN_CSTRING 51
81 #define TOKEN_ARRAY 52
83 #define CLSIDFMT "<%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X>"
85 /* FOURCC to string conversion for debug messages */
86 static const char *debugstr_fourcc(DWORD fourcc
)
88 if (!fourcc
) return "'null'";
89 return wine_dbg_sprintf ("\'%c%c%c%c\'",
90 (char)(fourcc
), (char)(fourcc
>> 8),
91 (char)(fourcc
>> 16), (char)(fourcc
>> 24));
94 static const char* get_primitive_string(WORD token
)
128 static void dump_template(xtemplate
* templates_array
, xtemplate
* ptemplate
)
133 clsid
= &ptemplate
->class_id
;
135 DPRINTF("template %s\n", ptemplate
->name
);
137 DPRINTF(CLSIDFMT
"\n", clsid
->Data1
, clsid
->Data2
, clsid
->Data3
, clsid
->Data4
[0],
138 clsid
->Data4
[1], clsid
->Data4
[2], clsid
->Data4
[3], clsid
->Data4
[4], clsid
->Data4
[5], clsid
->Data4
[6], clsid
->Data4
[7]);
139 for (j
= 0; j
< ptemplate
->nb_members
; j
++)
141 if (ptemplate
->members
[j
].nb_dims
)
143 if (ptemplate
->members
[j
].type
== TOKEN_NAME
)
144 DPRINTF("%s ", templates_array
[ptemplate
->members
[j
].idx_template
].name
);
146 DPRINTF("%s ", get_primitive_string(ptemplate
->members
[j
].type
));
147 DPRINTF("%s", ptemplate
->members
[j
].name
);
148 for (k
= 0; k
< ptemplate
->members
[j
].nb_dims
; k
++)
150 if (ptemplate
->members
[j
].dim_fixed
[k
])
151 DPRINTF("[%d]", ptemplate
->members
[j
].dim_value
[k
]);
153 DPRINTF("[%s]", ptemplate
->members
[ptemplate
->members
[j
].dim_value
[k
]].name
);
159 else if (ptemplate
->nb_children
)
161 DPRINTF("[%s", ptemplate
->children
[0]);
162 for (j
= 1; j
< ptemplate
->nb_children
; j
++)
163 DPRINTF(",%s", ptemplate
->children
[j
]);
169 static BOOL
read_bytes(parse_buffer
* buf
, LPVOID data
, DWORD size
)
171 if (buf
->rem_bytes
< size
)
173 memcpy(data
, buf
->buffer
, size
);
175 buf
->rem_bytes
-= size
;
179 static void rewind_bytes(parse_buffer
* buf
, DWORD size
)
182 buf
->rem_bytes
+= size
;
185 HRESULT
parse_header(parse_buffer
* buf
, BYTE
** decomp_buffer_ptr
)
187 /* X File common header:
188 * 0-3 -> Magic Number (format identifier)
189 * 4-7 -> Format Version
190 * 8-11 -> Format Type (text or binary, decompressed or compressed)
191 * 12-15 -> Float Size (32 or 64 bits) */
194 if (!read_bytes(buf
, header
, sizeof(header
)))
195 return DXFILEERR_BADFILETYPE
;
197 if (TRACE_ON(d3dxof_parsing
))
200 memcpy(string
, header
, 16);
202 TRACE("header = '%s'\n", string
);
205 if (header
[0] != XOFFILE_FORMAT_MAGIC
)
206 return DXFILEERR_BADFILETYPE
;
208 if (header
[1] != XOFFILE_FORMAT_VERSION_302
&& header
[1] != XOFFILE_FORMAT_VERSION_303
)
209 return DXFILEERR_BADFILEVERSION
;
211 if (header
[2] != XOFFILE_FORMAT_BINARY
&& header
[2] != XOFFILE_FORMAT_TEXT
&&
212 header
[2] != XOFFILE_FORMAT_BINARY_MSZIP
&& header
[2] != XOFFILE_FORMAT_TEXT_MSZIP
)
214 WARN("File type %s unknown\n", debugstr_fourcc(header
[2]));
215 return DXFILEERR_BADFILETYPE
;
218 if (header
[3] != XOFFILE_FORMAT_FLOAT_BITS_32
&& header
[3] != XOFFILE_FORMAT_FLOAT_BITS_64
)
219 return DXFILEERR_BADFILEFLOATSIZE
;
221 buf
->txt
= header
[2] == XOFFILE_FORMAT_TEXT
|| header
[2] == XOFFILE_FORMAT_TEXT_MSZIP
;
223 if (header
[2] == XOFFILE_FORMAT_BINARY_MSZIP
|| header
[2] == XOFFILE_FORMAT_TEXT_MSZIP
)
225 /* Extended header for compressed data:
226 * 16-17 -> decompressed size w/ header, 18-19 -> null,
227 * 20-21 -> decompressed size w/o header, 22-23 -> size of MSZIP compressed data,
228 * 24-xx -> compressed MSZIP data */
232 LPBYTE decomp_buffer
;
234 buf
->rem_bytes
-= sizeof(WORD
) * 2;
235 buf
->buffer
+= sizeof(WORD
) * 2;
236 if (!read_bytes(buf
, &decomp_size
, sizeof(decomp_size
)))
237 return DXFILEERR_BADFILETYPE
;
238 if (!read_bytes(buf
, &comp_size
, sizeof(comp_size
)))
239 return DXFILEERR_BADFILETYPE
;
241 TRACE("Compressed format %s detected: compressed_size = %x, decompressed_size = %x\n",
242 debugstr_fourcc(header
[2]), comp_size
, decomp_size
);
244 decomp_buffer
= HeapAlloc(GetProcessHeap(), 0, decomp_size
);
247 ERR("Out of memory\n");
248 return DXFILEERR_BADALLOC
;
250 err
= mszip_decompress(comp_size
, decomp_size
, (char*)buf
->buffer
, (char*)decomp_buffer
);
253 WARN("Error while decompressing mszip archive %d\n", err
);
254 HeapFree(GetProcessHeap(), 0, decomp_buffer
);
255 return DXFILEERR_BADALLOC
;
257 /* Use decompressed data */
258 buf
->buffer
= *decomp_buffer_ptr
= decomp_buffer
;
259 buf
->rem_bytes
= decomp_size
;
262 TRACE("Header is correct\n");
267 static void dump_TOKEN(WORD token
)
269 #define DUMP_TOKEN(t) case t: TRACE(#t "\n"); break
272 DUMP_TOKEN(TOKEN_NAME
);
273 DUMP_TOKEN(TOKEN_STRING
);
274 DUMP_TOKEN(TOKEN_INTEGER
);
275 DUMP_TOKEN(TOKEN_GUID
);
276 DUMP_TOKEN(TOKEN_INTEGER_LIST
);
277 DUMP_TOKEN(TOKEN_FLOAT_LIST
);
278 DUMP_TOKEN(TOKEN_OBRACE
);
279 DUMP_TOKEN(TOKEN_CBRACE
);
280 DUMP_TOKEN(TOKEN_OPAREN
);
281 DUMP_TOKEN(TOKEN_CPAREN
);
282 DUMP_TOKEN(TOKEN_OBRACKET
);
283 DUMP_TOKEN(TOKEN_CBRACKET
);
284 DUMP_TOKEN(TOKEN_OANGLE
);
285 DUMP_TOKEN(TOKEN_CANGLE
);
286 DUMP_TOKEN(TOKEN_DOT
);
287 DUMP_TOKEN(TOKEN_COMMA
);
288 DUMP_TOKEN(TOKEN_SEMICOLON
);
289 DUMP_TOKEN(TOKEN_TEMPLATE
);
290 DUMP_TOKEN(TOKEN_WORD
);
291 DUMP_TOKEN(TOKEN_DWORD
);
292 DUMP_TOKEN(TOKEN_FLOAT
);
293 DUMP_TOKEN(TOKEN_DOUBLE
);
294 DUMP_TOKEN(TOKEN_CHAR
);
295 DUMP_TOKEN(TOKEN_UCHAR
);
296 DUMP_TOKEN(TOKEN_SWORD
);
297 DUMP_TOKEN(TOKEN_SDWORD
);
298 DUMP_TOKEN(TOKEN_VOID
);
299 DUMP_TOKEN(TOKEN_LPSTR
);
300 DUMP_TOKEN(TOKEN_UNICODE
);
301 DUMP_TOKEN(TOKEN_CSTRING
);
302 DUMP_TOKEN(TOKEN_ARRAY
);
305 TRACE("Unknown token %d\n", token
);
311 static BOOL
is_space(char c
)
325 static BOOL
is_operator(char c
)
344 static inline BOOL
is_separator(char c
)
346 return is_space(c
) || is_operator(c
);
349 static WORD
get_operator_token(char c
)
358 return TOKEN_OBRACKET
;
360 return TOKEN_CBRACKET
;
372 return TOKEN_SEMICOLON
;
377 static BOOL
is_keyword(parse_buffer
* buf
, const char* keyword
)
379 char tmp
[8]; /* longest keyword size (template) */
380 DWORD len
= strlen(keyword
);
382 if (!read_bytes(buf
, tmp
, len
))
384 if (strncasecmp(tmp
, keyword
, len
))
386 rewind_bytes(buf
, len
);
390 if (!read_bytes(buf
, tmp
, 1))
392 if (is_separator(tmp
[0]))
394 rewind_bytes(buf
, 1);
397 rewind_bytes(buf
, len
+1);
401 static WORD
get_keyword_token(parse_buffer
* buf
)
403 if (is_keyword(buf
, "template"))
404 return TOKEN_TEMPLATE
;
405 if (is_keyword(buf
, "WORD"))
407 if (is_keyword(buf
, "DWORD"))
409 if (is_keyword(buf
, "FLOAT"))
411 if (is_keyword(buf
, "DOUBLE"))
413 if (is_keyword(buf
, "CHAR"))
415 if (is_keyword(buf
, "UCHAR"))
417 if (is_keyword(buf
, "SWORD"))
419 if (is_keyword(buf
, "SDWORD"))
421 if (is_keyword(buf
, "VOID"))
423 if (is_keyword(buf
, "STRING"))
425 if (is_keyword(buf
, "UNICODE"))
426 return TOKEN_UNICODE
;
427 if (is_keyword(buf
, "CSTRING"))
428 return TOKEN_CSTRING
;
429 if (is_keyword(buf
, "array"))
435 static BOOL
is_guid(parse_buffer
* buf
)
443 if (buf
->rem_bytes
< 38 || *buf
->buffer
!= '<')
446 while (pos
< sizeof(tmp
) - 2 && *(buf
->buffer
+pos
) != '>')
448 tmp
[pos
] = *(buf
->buffer
+pos
);
453 if (pos
!= 38 /* <+36+> */)
455 TRACE("Wrong guid %s (%d)\n", tmp
, pos
);
459 buf
->rem_bytes
-= pos
;
461 ret
= sscanf(tmp
, CLSIDFMT
, &class_id
.Data1
, tab
, tab
+1, tab
+2, tab
+3, tab
+4, tab
+5, tab
+6, tab
+7, tab
+8, tab
+9);
464 TRACE("Wrong guid %s (%d)\n", tmp
, pos
);
467 TRACE("Found guid %s (%d)\n", tmp
, pos
);
469 class_id
.Data2
= tab
[0];
470 class_id
.Data3
= tab
[1];
471 class_id
.Data4
[0] = tab
[2];
472 class_id
.Data4
[1] = tab
[3];
473 class_id
.Data4
[2] = tab
[4];
474 class_id
.Data4
[3] = tab
[5];
475 class_id
.Data4
[4] = tab
[6];
476 class_id
.Data4
[5] = tab
[7];
477 class_id
.Data4
[6] = tab
[8];
478 class_id
.Data4
[7] = tab
[9];
480 *(GUID
*)buf
->value
= class_id
;
485 static BOOL
is_name(parse_buffer
* buf
)
491 while (pos
< buf
->rem_bytes
&& !is_separator(c
= *(buf
->buffer
+pos
)))
493 if (!(((c
>= 'a') && (c
<= 'z')) || ((c
>= 'A') && (c
<= 'Z')) || ((c
>= '0') && (c
<= '9')) || (c
== '_') || (c
== '-')))
495 if (pos
< sizeof(tmp
))
499 tmp
[min(pos
, sizeof(tmp
) - 1)] = 0;
503 TRACE("Wrong name %s\n", tmp
);
508 buf
->rem_bytes
-= pos
;
510 TRACE("Found name %s\n", tmp
);
511 strcpy((char*)buf
->value
, tmp
);
516 static BOOL
is_float(parse_buffer
* buf
)
524 while (pos
< buf
->rem_bytes
&& !is_separator(c
= *(buf
->buffer
+pos
)))
526 if (!((!pos
&& (c
== '-')) || ((c
>= '0') && (c
<= '9')) || (!dot
&& (c
== '.'))))
530 if (pos
< sizeof(tmp
))
534 tmp
[min(pos
, sizeof(tmp
) - 1)] = 0;
537 buf
->rem_bytes
-= pos
;
539 sscanf(tmp
, "%f", &decimal
);
541 TRACE("Found float %s - %f\n", tmp
, decimal
);
543 *(float*)buf
->value
= decimal
;
548 static BOOL
is_integer(parse_buffer
* buf
)
555 while (pos
< buf
->rem_bytes
&& !is_separator(c
= *(buf
->buffer
+pos
)))
557 if (!((c
>= '0') && (c
<= '9')))
559 if (pos
< sizeof(tmp
))
563 tmp
[min(pos
, sizeof(tmp
) - 1)] = 0;
566 buf
->rem_bytes
-= pos
;
568 sscanf(tmp
, "%d", &integer
);
570 TRACE("Found integer %s - %d\n", tmp
, integer
);
572 *(DWORD
*)buf
->value
= integer
;
577 static BOOL
is_string(parse_buffer
* buf
)
584 if (*buf
->buffer
!= '"')
587 while (pos
< buf
->rem_bytes
&& !is_operator(c
= *(buf
->buffer
+pos
+1)))
594 if (pos
< sizeof(tmp
))
598 tmp
[min(pos
, sizeof(tmp
) - 1)] = 0;
602 TRACE("Wrong string %s\n", tmp
);
606 buf
->buffer
+= pos
+ 2;
607 buf
->rem_bytes
-= pos
+ 2;
609 TRACE("Found string %s\n", tmp
);
610 strcpy((char*)buf
->value
, tmp
);
615 static WORD
parse_TOKEN(parse_buffer
* buf
)
624 if (!read_bytes(buf
, &c
, 1))
626 /*TRACE("char = '%c'\n", is_space(c) ? ' ' : c);*/
627 if ((c
== '#') || (c
== '/'))
629 /* Handle comment (# or //) */
632 if (!read_bytes(buf
, &c
, 1))
640 if (!read_bytes(buf
, &c
, 1))
647 if (is_operator(c
) && (c
!= '<'))
649 token
= get_operator_token(c
);
659 rewind_bytes(buf
, 1);
661 if ((token
= get_keyword_token(buf
)))
671 token
= TOKEN_INTEGER
;
690 FIXME("Unrecognize element\n");
702 if (!read_bytes(buf
, &token
, 2))
705 /* Convert integer and float list into separate elements */
706 if (token
== TOKEN_INTEGER_LIST
)
708 if (!read_bytes(buf
, &nb_elem
, 4))
710 token
= TOKEN_INTEGER
;
712 TRACE("Integer list (TOKEN_INTEGER_LIST) of size %d\n", nb_elem
);
714 else if (token
== TOKEN_FLOAT_LIST
)
716 if (!read_bytes(buf
, &nb_elem
, 4))
720 TRACE("Float list (TOKEN_FLOAT_LIST) of size %d\n", nb_elem
);
726 token
= is_float
? TOKEN_FLOAT
: TOKEN_INTEGER
;
731 if (!read_bytes(buf
, &integer
, 4))
734 *(DWORD
*)buf
->value
= integer
;
747 if (!read_bytes(buf
, &count
, 4))
749 if (!read_bytes(buf
, strname
, count
))
752 /*TRACE("name = %s\n", strname);*/
754 strcpy((char*)buf
->value
, strname
);
761 if (!read_bytes(buf
, &integer
, 4))
763 /*TRACE("integer = %ld\n", integer);*/
765 *(DWORD
*)buf
->value
= integer
;
773 if (!read_bytes(buf
, &class_id
, 16))
775 sprintf(strguid
, CLSIDFMT
, class_id
.Data1
, class_id
.Data2
, class_id
.Data3
, class_id
.Data4
[0],
776 class_id
.Data4
[1], class_id
.Data4
[2], class_id
.Data4
[3], class_id
.Data4
[4], class_id
.Data4
[5],
777 class_id
.Data4
[6], class_id
.Data4
[7]);
778 /*TRACE("guid = {%s}\n", strguid);*/
780 *(GUID
*)buf
->value
= class_id
;
788 if (!read_bytes(buf
, &count
, 4))
790 if (!read_bytes(buf
, strname
, count
))
793 if (!read_bytes(buf
, &tmp_token
, 2))
795 if ((tmp_token
!= TOKEN_COMMA
) && (tmp_token
!= TOKEN_SEMICOLON
))
796 ERR("No comma or semicolon (got %d)\n", tmp_token
);
797 /*TRACE("name = %s\n", strname);*/
799 strcpy((char*)buf
->value
, strname
);
813 case TOKEN_SEMICOLON
:
839 static WORD
get_TOKEN(parse_buffer
* buf
)
841 if (buf
->token_present
)
843 buf
->token_present
= FALSE
;
844 return buf
->current_token
;
847 buf
->current_token
= parse_TOKEN(buf
);
849 return buf
->current_token
;
852 static WORD
check_TOKEN(parse_buffer
* buf
)
854 if (buf
->token_present
)
855 return buf
->current_token
;
857 buf
->current_token
= parse_TOKEN(buf
);
858 buf
->token_present
= TRUE
;
860 return buf
->current_token
;
863 static BOOL
is_template_available(parse_buffer
* buf
)
865 return check_TOKEN(buf
) == TOKEN_TEMPLATE
;
868 static inline BOOL
is_primitive_type(WORD token
)
893 static BOOL
parse_template_option_info(parse_buffer
* buf
)
895 xtemplate
* cur_template
= &buf
->pdxf
->xtemplates
[buf
->pdxf
->nb_xtemplates
];
897 if (check_TOKEN(buf
) == TOKEN_DOT
)
900 if (get_TOKEN(buf
) != TOKEN_DOT
)
902 if (get_TOKEN(buf
) != TOKEN_DOT
)
904 cur_template
->open
= TRUE
;
910 if (get_TOKEN(buf
) != TOKEN_NAME
)
912 strcpy(cur_template
->children
[cur_template
->nb_children
], (char*)buf
->value
);
913 if (check_TOKEN(buf
) == TOKEN_GUID
)
915 cur_template
->nb_children
++;
916 if (check_TOKEN(buf
) != TOKEN_COMMA
)
920 cur_template
->open
= FALSE
;
926 static BOOL
parse_template_members_list(parse_buffer
* buf
)
935 cur_member
= &buf
->pdxf
->xtemplates
[buf
->pdxf
->nb_xtemplates
].members
[idx_member
];
937 if (check_TOKEN(buf
) == TOKEN_ARRAY
)
943 if (check_TOKEN(buf
) == TOKEN_NAME
)
945 cur_member
->type
= get_TOKEN(buf
);
946 cur_member
->idx_template
= 0;
947 while (cur_member
->idx_template
< buf
->pdxf
->nb_xtemplates
)
949 if (!strcasecmp((char*)buf
->value
, buf
->pdxf
->xtemplates
[cur_member
->idx_template
].name
))
951 cur_member
->idx_template
++;
953 if (cur_member
->idx_template
== buf
->pdxf
->nb_xtemplates
)
955 ERR("Reference to a nonexistent template '%s'\n", (char*)buf
->value
);
959 else if (is_primitive_type(check_TOKEN(buf
)))
960 cur_member
->type
= get_TOKEN(buf
);
964 if (get_TOKEN(buf
) != TOKEN_NAME
)
966 strcpy(cur_member
->name
, (char*)buf
->value
);
970 while (check_TOKEN(buf
) == TOKEN_OBRACKET
)
972 if (nb_dims
>= MAX_ARRAY_DIM
)
974 FIXME("Too many dimensions (%d) for multi-dimensional array\n", nb_dims
+ 1);
978 if (check_TOKEN(buf
) == TOKEN_INTEGER
)
981 cur_member
->dim_fixed
[nb_dims
] = TRUE
;
982 cur_member
->dim_value
[nb_dims
] = *(DWORD
*)buf
->value
;
987 if (get_TOKEN(buf
) != TOKEN_NAME
)
989 for (i
= 0; i
< idx_member
; i
++)
991 if (!strcmp((char*)buf
->value
, buf
->pdxf
->xtemplates
[buf
->pdxf
->nb_xtemplates
].members
[i
].name
))
993 if (buf
->pdxf
->xtemplates
[buf
->pdxf
->nb_xtemplates
].members
[i
].nb_dims
)
995 ERR("Array cannot be used to specify variable array size\n");
998 if (buf
->pdxf
->xtemplates
[buf
->pdxf
->nb_xtemplates
].members
[i
].type
!= TOKEN_DWORD
)
1000 FIXME("Only DWORD supported to specify variable array size\n");
1006 if (i
== idx_member
)
1008 ERR("Reference to unknown member %s\n", (char*)buf
->value
);
1011 cur_member
->dim_fixed
[nb_dims
] = FALSE
;
1012 cur_member
->dim_value
[nb_dims
] = i
;
1014 if (get_TOKEN(buf
) != TOKEN_CBRACKET
)
1020 cur_member
->nb_dims
= nb_dims
;
1022 if (get_TOKEN(buf
) != TOKEN_SEMICOLON
)
1028 buf
->pdxf
->xtemplates
[buf
->pdxf
->nb_xtemplates
].nb_members
= idx_member
;
1033 static BOOL
parse_template_parts(parse_buffer
* buf
)
1035 if (!parse_template_members_list(buf
))
1037 if (check_TOKEN(buf
) == TOKEN_OBRACKET
)
1040 if (!parse_template_option_info(buf
))
1042 if (get_TOKEN(buf
) != TOKEN_CBRACKET
)
1049 static void go_to_next_definition(parse_buffer
* buf
)
1052 while (buf
->rem_bytes
)
1054 if (!read_bytes(buf
, &c
, 1))
1056 if ((c
== '#') || (c
== '/'))
1058 /* Handle comment (# or //) */
1061 if (!read_bytes(buf
, &c
, 1))
1069 if (!read_bytes(buf
, &c
, 1))
1074 else if (!is_space(c
))
1076 rewind_bytes(buf
, 1);
1082 static BOOL
parse_template(parse_buffer
* buf
)
1084 if (get_TOKEN(buf
) != TOKEN_TEMPLATE
)
1086 if (get_TOKEN(buf
) != TOKEN_NAME
)
1088 strcpy(buf
->pdxf
->xtemplates
[buf
->pdxf
->nb_xtemplates
].name
, (char*)buf
->value
);
1089 if (get_TOKEN(buf
) != TOKEN_OBRACE
)
1091 if (get_TOKEN(buf
) != TOKEN_GUID
)
1093 buf
->pdxf
->xtemplates
[buf
->pdxf
->nb_xtemplates
].class_id
= *(GUID
*)buf
->value
;
1094 if (!parse_template_parts(buf
))
1096 if (get_TOKEN(buf
) != TOKEN_CBRACE
)
1100 /* Go to the next template */
1101 go_to_next_definition(buf
);
1104 TRACE("%d - %s - %s\n", buf
->pdxf
->nb_xtemplates
, buf
->pdxf
->xtemplates
[buf
->pdxf
->nb_xtemplates
].name
, debugstr_guid(&buf
->pdxf
->xtemplates
[buf
->pdxf
->nb_xtemplates
].class_id
));
1105 buf
->pdxf
->nb_xtemplates
++;
1110 BOOL
parse_templates(parse_buffer
* buf
)
1112 while (buf
->rem_bytes
&& is_template_available(buf
))
1114 if (!parse_template(buf
))
1116 WARN("Template is not correct\n");
1121 TRACE("Template successfully parsed:\n");
1122 if (TRACE_ON(d3dxof_parsing
))
1123 dump_template(buf
->pdxf
->xtemplates
, &buf
->pdxf
->xtemplates
[buf
->pdxf
->nb_xtemplates
- 1]);
1129 static BOOL
check_buffer(parse_buffer
* buf
, ULONG size
)
1131 if ((buf
->cur_pos_data
+ size
) > buf
->capacity
)
1134 ULONG new_capacity
= buf
->capacity
? 2 * buf
->capacity
: 100000;
1136 pdata
= HeapAlloc(GetProcessHeap(), 0, new_capacity
);
1139 memcpy(pdata
, buf
->pdata
, buf
->cur_pos_data
);
1140 HeapFree(GetProcessHeap(), 0, buf
->pdata
);
1141 buf
->capacity
= new_capacity
;
1143 buf
->pxo
->root
->pdata
= pdata
;
1148 static BOOL
parse_object_parts(parse_buffer
* buf
, BOOL allow_optional
);
1149 static BOOL
parse_object_members_list(parse_buffer
* buf
)
1153 xtemplate
* pt
= buf
->pxt
[buf
->level
];
1155 for (i
= 0; i
< pt
->nb_members
; i
++)
1160 buf
->pxo
->members
[i
].name
= pt
->members
[i
].name
;
1161 buf
->pxo
->members
[i
].start
= buf
->cur_pos_data
;
1163 for (k
= 0; k
< pt
->members
[i
].nb_dims
; k
++)
1165 if (pt
->members
[i
].dim_fixed
[k
])
1166 nb_elems
*= pt
->members
[i
].dim_value
[k
];
1168 nb_elems
*= *(DWORD
*)(buf
->pxo
->root
->pdata
+ buf
->pxo
->members
[pt
->members
[i
].dim_value
[k
]].start
);
1171 TRACE("Elements to consider: %d\n", nb_elems
);
1173 for (k
= 0; k
< nb_elems
; k
++)
1177 token
= check_TOKEN(buf
);
1178 if (token
== TOKEN_COMMA
)
1184 /* Allow comma omission */
1185 if (!((token
== TOKEN_FLOAT
) || (token
== TOKEN_INTEGER
)))
1190 if (pt
->members
[i
].type
== TOKEN_NAME
)
1194 TRACE("Found sub-object %s\n", buf
->pdxf
->xtemplates
[pt
->members
[i
].idx_template
].name
);
1196 /* To do template lookup */
1197 for (j
= 0; j
< buf
->pdxf
->nb_xtemplates
; j
++)
1199 if (!strcasecmp(buf
->pdxf
->xtemplates
[pt
->members
[i
].idx_template
].name
, buf
->pdxf
->xtemplates
[j
].name
))
1201 buf
->pxt
[buf
->level
] = &buf
->pdxf
->xtemplates
[j
];
1205 if (j
== buf
->pdxf
->nb_xtemplates
)
1207 ERR("Unknown template %s\n", (char*)buf
->value
);
1211 TRACE("Enter %s\n", buf
->pdxf
->xtemplates
[pt
->members
[i
].idx_template
].name
);
1212 if (!parse_object_parts(buf
, FALSE
))
1221 token
= check_TOKEN(buf
);
1222 if (token
== TOKEN_INTEGER
)
1225 TRACE("%s = %d\n", pt
->members
[i
].name
, *(DWORD
*)buf
->value
);
1226 /* Assume larger size */
1227 if (!check_buffer(buf
, 4))
1229 if (pt
->members
[i
].type
== TOKEN_WORD
)
1231 *(((WORD
*)(buf
->cur_pos_data
+ buf
->pdata
))) = (WORD
)(*(DWORD
*)buf
->value
);
1232 buf
->cur_pos_data
+= 2;
1234 else if (pt
->members
[i
].type
== TOKEN_DWORD
)
1236 *(((DWORD
*)(buf
->cur_pos_data
+ buf
->pdata
))) = (DWORD
)(*(DWORD
*)buf
->value
);
1237 buf
->cur_pos_data
+= 4;
1241 FIXME("Token %d not supported\n", pt
->members
[i
].type
);
1245 else if (token
== TOKEN_FLOAT
)
1248 TRACE("%s = %f\n", pt
->members
[i
].name
, *(float*)buf
->value
);
1249 if (!check_buffer(buf
, 4))
1251 if (pt
->members
[i
].type
== TOKEN_FLOAT
)
1253 *(((float*)(buf
->cur_pos_data
+ buf
->pdata
))) = (float)(*(float*)buf
->value
);
1254 buf
->cur_pos_data
+= 4;
1258 FIXME("Token %d not supported\n", pt
->members
[i
].type
);
1262 else if (token
== TOKEN_LPSTR
)
1265 TRACE("%s = %s\n", pt
->members
[i
].name
, (char*)buf
->value
);
1266 if (!check_buffer(buf
, sizeof(LPSTR
)))
1268 if (pt
->members
[i
].type
== TOKEN_LPSTR
)
1270 int len
= strlen((char*)buf
->value
) + 1;
1271 if ((buf
->cur_pstrings
- buf
->pstrings
+ len
) > MAX_STRINGS_BUFFER
)
1273 FIXME("Buffer too small %p %p %d\n", buf
->cur_pstrings
, buf
->pstrings
, len
);
1276 strcpy((char*)buf
->cur_pstrings
, (char*)buf
->value
);
1277 *(((LPCSTR
*)(buf
->cur_pos_data
+ buf
->pdata
))) = (char*)buf
->cur_pstrings
;
1278 buf
->cur_pstrings
+= len
;
1279 buf
->cur_pos_data
+= sizeof(LPSTR
);
1283 FIXME("Token %d not supported\n", pt
->members
[i
].type
);
1289 FIXME("Unexpected token %d\n", token
);
1295 if (nb_elems
&& buf
->txt
&& (check_TOKEN(buf
) != TOKEN_CBRACE
) && (check_TOKEN(buf
) != TOKEN_NAME
))
1297 token
= get_TOKEN(buf
);
1298 if ((token
!= TOKEN_SEMICOLON
) && (token
!= TOKEN_COMMA
))
1306 static BOOL
parse_object_parts(parse_buffer
* buf
, BOOL allow_optional
)
1308 buf
->pxo
->nb_children
= 0;
1310 if (!parse_object_members_list(buf
))
1315 buf
->pxo
->size
= buf
->cur_pos_data
- buf
->pxo
->pos_data
;
1317 /* Skip trailing semicolon */
1318 while (check_TOKEN(buf
) == TOKEN_SEMICOLON
)
1323 if (check_TOKEN(buf
) == TOKEN_OBRACE
)
1327 if (get_TOKEN(buf
) != TOKEN_NAME
)
1329 if (get_TOKEN(buf
) != TOKEN_CBRACE
)
1331 TRACE("Found optional reference %s\n", (char*)buf
->value
);
1332 for (i
= 0; i
< (buf
->nb_pxo_globals
+1); i
++)
1334 for (j
= 0; j
< (buf
->pxo_globals
[i
])[0].nb_subobjects
; j
++)
1336 if (!strcmp((buf
->pxo_globals
[i
])[j
].name
, (char*)buf
->value
))
1341 if (i
== (buf
->nb_pxo_globals
+1))
1343 ERR("Reference to unknown object %s\n", (char*)buf
->value
);
1347 if (buf
->pxo
->root
->nb_subobjects
>= MAX_SUBOBJECTS
)
1349 FIXME("Too many sub-objects\n");
1353 buf
->pxo
->children
[buf
->pxo
->nb_children
] = &buf
->pxo_tab
[buf
->pxo
->root
->nb_subobjects
++];
1354 buf
->pxo
->children
[buf
->pxo
->nb_children
]->ptarget
= &(buf
->pxo_globals
[i
])[j
];
1355 buf
->pxo
->children
[buf
->pxo
->nb_children
]->binary
= FALSE
;
1356 buf
->pxo
->nb_children
++;
1358 else if (check_TOKEN(buf
) == TOKEN_NAME
)
1360 xobject
* pxo
= buf
->pxo
;
1362 if (buf
->pxo
->root
->nb_subobjects
>= MAX_SUBOBJECTS
)
1364 FIXME("Too many sub-objects\n");
1368 buf
->pxo
= buf
->pxo
->children
[buf
->pxo
->nb_children
] = &buf
->pxo_tab
[buf
->pxo
->root
->nb_subobjects
++];
1370 TRACE("Enter optional %s\n", (char*)buf
->value
);
1372 if (!parse_object(buf
))
1379 buf
->pxo
->nb_children
++;
1386 if (buf
->pxo
->nb_children
> MAX_CHILDREN
)
1388 FIXME("Too many children %d\n", buf
->pxo
->nb_children
);
1395 BOOL
parse_object(parse_buffer
* buf
)
1399 buf
->pxo
->pos_data
= buf
->cur_pos_data
;
1400 buf
->pxo
->ptarget
= NULL
;
1401 buf
->pxo
->binary
= FALSE
;
1402 buf
->pxo
->root
= buf
->pxo_tab
;
1404 if (get_TOKEN(buf
) != TOKEN_NAME
)
1407 /* To do template lookup */
1408 for (i
= 0; i
< buf
->pdxf
->nb_xtemplates
; i
++)
1410 if (!strcasecmp((char*)buf
->value
, buf
->pdxf
->xtemplates
[i
].name
))
1412 buf
->pxt
[buf
->level
] = &buf
->pdxf
->xtemplates
[i
];
1413 memcpy(&buf
->pxo
->type
, &buf
->pdxf
->xtemplates
[i
].class_id
, 16);
1417 if (i
== buf
->pdxf
->nb_xtemplates
)
1419 ERR("Unknown template %s\n", (char*)buf
->value
);
1423 if (check_TOKEN(buf
) == TOKEN_NAME
)
1426 strcpy(buf
->pxo
->name
, (char*)buf
->value
);
1429 buf
->pxo
->name
[0] = 0;
1431 if (get_TOKEN(buf
) != TOKEN_OBRACE
)
1433 if (check_TOKEN(buf
) == TOKEN_GUID
)
1436 memcpy(&buf
->pxo
->class_id
, buf
->value
, 16);
1439 memset(&buf
->pxo
->class_id
, 0, 16);
1441 if (!parse_object_parts(buf
, TRUE
))
1443 if (get_TOKEN(buf
) != TOKEN_CBRACE
)
1448 /* Go to the next object */
1449 go_to_next_definition(buf
);