dlls: Assorted spelling fixes.
[wine] / dlls / d3dxof / parsing.c
1 /*
2  * X Files parsing
3  *
4  * Copyright 2008 Christian Costa
5  *
6  * This file contains the (internal) driver registration functions,
7  * driver enumeration APIs and DirectDraw creation functions.
8  *
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.
13  *
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.
18  *
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
22  */
23
24 #include "config.h"
25 #include "wine/debug.h"
26
27 #define COBJMACROS
28
29 #include "winbase.h"
30 #include "wingdi.h"
31
32 #include "d3dxof_private.h"
33 #include "dxfile.h"
34
35 #include <stdio.h>
36
37 WINE_DEFAULT_DEBUG_CHANNEL(d3dxof_parsing);
38
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')
50
51 #define TOKEN_NAME         1
52 #define TOKEN_STRING       2
53 #define TOKEN_INTEGER      3
54 #define TOKEN_GUID         5
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
65 #define TOKEN_DOT         18
66 #define TOKEN_COMMA       19
67 #define TOKEN_SEMICOLON   20
68 #define TOKEN_TEMPLATE    31
69 #define TOKEN_WORD        40
70 #define TOKEN_DWORD       41
71 #define TOKEN_FLOAT       42
72 #define TOKEN_DOUBLE      43
73 #define TOKEN_CHAR        44
74 #define TOKEN_UCHAR       45
75 #define TOKEN_SWORD       46
76 #define TOKEN_SDWORD      47
77 #define TOKEN_VOID        48
78 #define TOKEN_LPSTR       49
79 #define TOKEN_UNICODE     50
80 #define TOKEN_CSTRING     51
81 #define TOKEN_ARRAY       52
82
83 #define CLSIDFMT "<%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X>"
84
85 /* FOURCC to string conversion for debug messages */
86 static const char *debugstr_fourcc(DWORD fourcc)
87 {
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));
92 }
93
94 static const char* get_primitive_string(WORD token)
95 {
96   switch(token)
97   {
98     case TOKEN_WORD:
99       return "WORD";
100     case TOKEN_DWORD:
101       return "DWORD";
102     case TOKEN_FLOAT:
103       return "FLOAT";
104     case TOKEN_DOUBLE:
105       return "DOUBLE";
106     case TOKEN_CHAR:
107       return "CHAR";
108     case TOKEN_UCHAR:
109       return "UCHAR";
110     case TOKEN_SWORD:
111       return "SWORD";
112     case TOKEN_SDWORD:
113       return "SDWORD";
114     case TOKEN_VOID:
115       return "VOID";
116     case TOKEN_LPSTR:
117       return "STRING";
118     case TOKEN_UNICODE:
119       return "UNICODE";
120     case TOKEN_CSTRING:
121       return "CSTRING ";
122     default:
123       break;
124   }
125   return NULL;
126 }
127
128 static void dump_template(xtemplate* templates_array, xtemplate* ptemplate)
129 {
130   int j, k;
131   GUID* clsid;
132
133   clsid = &ptemplate->class_id;
134
135   DPRINTF("template %s\n", ptemplate->name);
136   DPRINTF("{\n");
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++)
140   {
141     if (ptemplate->members[j].nb_dims)
142       DPRINTF("array ");
143     if (ptemplate->members[j].type == TOKEN_NAME)
144       DPRINTF("%s ", templates_array[ptemplate->members[j].idx_template].name);
145     else
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++)
149     {
150       if (ptemplate->members[j].dim_fixed[k])
151         DPRINTF("[%d]", ptemplate->members[j].dim_value[k]);
152       else
153         DPRINTF("[%s]", ptemplate->members[ptemplate->members[j].dim_value[k]].name);
154     }
155     DPRINTF(";\n");
156   }
157   if (ptemplate->open)
158     DPRINTF("[...]\n");
159   else if (ptemplate->nb_childs)
160   {
161     DPRINTF("[%s", ptemplate->childs[0]);
162     for (j = 1; j < ptemplate->nb_childs; j++)
163       DPRINTF(",%s", ptemplate->childs[j]);
164     DPRINTF("]\n");
165   }
166   DPRINTF("}\n");
167 }
168
169 static BOOL read_bytes(parse_buffer * buf, LPVOID data, DWORD size)
170 {
171   if (buf->rem_bytes < size)
172     return FALSE;
173   memcpy(data, buf->buffer, size);
174   buf->buffer += size;
175   buf->rem_bytes -= size;
176   return TRUE;
177 }
178
179 static void rewind_bytes(parse_buffer * buf, DWORD size)
180 {
181   buf->buffer -= size;
182   buf->rem_bytes += size;
183 }
184
185 HRESULT parse_header(parse_buffer * buf, BYTE ** decomp_buffer_ptr)
186 {
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) */
192   DWORD header[4];
193
194   if (!read_bytes(buf, header, sizeof(header)))
195     return DXFILEERR_BADFILETYPE;
196
197   if (TRACE_ON(d3dxof_parsing))
198   {
199     char string[17];
200     memcpy(string, header, 16);
201     string[16] = 0;
202     TRACE("header = '%s'\n", string);
203   }
204
205   if (header[0] != XOFFILE_FORMAT_MAGIC)
206     return DXFILEERR_BADFILETYPE;
207
208   if (header[1] != XOFFILE_FORMAT_VERSION_302 && header[1] != XOFFILE_FORMAT_VERSION_303)
209     return DXFILEERR_BADFILEVERSION;
210
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)
213   {
214     WARN("File type %s unknown\n", debugstr_fourcc(header[2]));
215     return DXFILEERR_BADFILETYPE;
216   }
217
218   if (header[3] != XOFFILE_FORMAT_FLOAT_BITS_32 && header[3] != XOFFILE_FORMAT_FLOAT_BITS_64)
219     return DXFILEERR_BADFILEFLOATSIZE;
220
221   buf->txt = header[2] == XOFFILE_FORMAT_TEXT || header[2] == XOFFILE_FORMAT_TEXT_MSZIP;
222
223   if (header[2] == XOFFILE_FORMAT_BINARY_MSZIP || header[2] == XOFFILE_FORMAT_TEXT_MSZIP)
224   {
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 */
229     int err;
230     WORD decomp_size;
231     WORD comp_size;
232     LPBYTE decomp_buffer;
233
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;
240
241     TRACE("Compressed format %s detected: compressed_size = %x, decompressed_size = %x\n",
242         debugstr_fourcc(header[2]), comp_size, decomp_size);
243
244     decomp_buffer = HeapAlloc(GetProcessHeap(), 0, decomp_size);
245     if (!decomp_buffer)
246     {
247         ERR("Out of memory\n");
248         return DXFILEERR_BADALLOC;
249     }
250     err = mszip_decompress(comp_size, decomp_size, (char*)buf->buffer, (char*)decomp_buffer);
251     if (err)
252     {
253         WARN("Error while decompressing mszip archive %d\n", err);
254         HeapFree(GetProcessHeap(), 0, decomp_buffer);
255         return DXFILEERR_BADALLOC;
256     }
257     /* Use decompressed data */
258     buf->buffer = *decomp_buffer_ptr = decomp_buffer;
259     buf->rem_bytes = decomp_size;
260   }
261
262   TRACE("Header is correct\n");
263
264   return S_OK;
265 }
266
267 static void dump_TOKEN(WORD token)
268 {
269 #define DUMP_TOKEN(t) case t: TRACE(#t "\n"); break
270   switch(token)
271   {
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);
303     default:
304       if (0)
305         TRACE("Unknown token %d\n", token);
306       break;
307   }
308 #undef DUMP_TOKEN
309 }
310
311 static BOOL is_space(char c)
312 {
313   switch (c)
314   {
315     case 0x00:
316     case 0x0D:
317     case 0x0A:
318     case ' ':
319     case '\t':
320       return TRUE;
321   }
322   return FALSE;
323 }
324
325 static BOOL is_operator(char c)
326 {
327   switch(c)
328   {
329     case '{':
330     case '}':
331     case '[':
332     case ']':
333     case '(':
334     case ')':
335     case '<':
336     case '>':
337     case ',':
338     case ';':
339       return TRUE;
340   }
341   return FALSE;
342 }
343
344 static inline BOOL is_separator(char c)
345 {
346   return is_space(c) || is_operator(c);
347 }
348
349 static WORD get_operator_token(char c)
350 {
351   switch(c)
352   {
353     case '{':
354       return TOKEN_OBRACE;
355     case '}':
356       return TOKEN_CBRACE;
357     case '[':
358       return TOKEN_OBRACKET;
359     case ']':
360       return TOKEN_CBRACKET;
361     case '(':
362       return TOKEN_OPAREN;
363     case ')':
364       return TOKEN_CPAREN;
365     case '<':
366       return TOKEN_OANGLE;
367     case '>':
368       return TOKEN_CANGLE;
369     case ',':
370       return TOKEN_COMMA;
371     case ';':
372       return TOKEN_SEMICOLON;
373   }
374   return 0;
375 }
376
377 static BOOL is_keyword(parse_buffer* buf, const char* keyword)
378 {
379   char tmp[8]; /* longest keyword size (template) */
380   DWORD len = strlen(keyword);
381
382   if (!read_bytes(buf, tmp, len))
383     return FALSE;
384   if (strncasecmp(tmp, keyword, len))
385   {
386     rewind_bytes(buf, len);
387     return FALSE;
388   }
389
390   if (!read_bytes(buf, tmp, 1))
391     return TRUE;
392   if (is_separator(tmp[0]))
393   {
394     rewind_bytes(buf, 1);
395     return TRUE;
396   }
397   rewind_bytes(buf, len+1);
398   return FALSE;
399 }
400
401 static WORD get_keyword_token(parse_buffer* buf)
402 {
403   if (is_keyword(buf, "template"))
404     return TOKEN_TEMPLATE;
405   if (is_keyword(buf, "WORD"))
406     return TOKEN_WORD;
407   if (is_keyword(buf, "DWORD"))
408     return TOKEN_DWORD;
409   if (is_keyword(buf, "FLOAT"))
410     return TOKEN_FLOAT;
411   if (is_keyword(buf, "DOUBLE"))
412     return TOKEN_DOUBLE;
413   if (is_keyword(buf, "CHAR"))
414     return TOKEN_CHAR;
415   if (is_keyword(buf, "UCHAR"))
416     return TOKEN_UCHAR;
417   if (is_keyword(buf, "SWORD"))
418     return TOKEN_SWORD;
419   if (is_keyword(buf, "SDWORD"))
420     return TOKEN_SDWORD;
421   if (is_keyword(buf, "VOID"))
422     return TOKEN_VOID;
423   if (is_keyword(buf, "STRING"))
424     return TOKEN_LPSTR;
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"))
430     return TOKEN_ARRAY;
431
432   return 0;
433 }
434
435 static BOOL is_guid(parse_buffer* buf)
436 {
437   char tmp[50];
438   DWORD pos = 1;
439   GUID class_id;
440   DWORD tab[10];
441   int ret;
442
443   if (buf->rem_bytes < 38 || *buf->buffer != '<')
444     return FALSE;
445   tmp[0] = '<';
446   while (pos < sizeof(tmp) - 2 && *(buf->buffer+pos) != '>')
447   {
448     tmp[pos] = *(buf->buffer+pos);
449     pos++;
450   }
451   tmp[pos++] = '>';
452   tmp[pos] = 0;
453   if (pos != 38 /* <+36+> */)
454   {
455     TRACE("Wrong guid %s (%d)\n", tmp, pos);
456     return FALSE;
457   }
458   buf->buffer += pos;
459   buf->rem_bytes -= pos;
460
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);
462   if (ret != 11)
463   {
464     TRACE("Wrong guid %s (%d)\n", tmp, pos);
465     return FALSE;
466   }
467   TRACE("Found guid %s (%d)\n", tmp, pos);
468
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];
479
480   *(GUID*)buf->value = class_id;
481
482   return TRUE;
483 }
484
485 static BOOL is_name(parse_buffer* buf)
486 {
487   char tmp[512];
488   DWORD pos = 0;
489   char c;
490   BOOL error = 0;
491   while (pos < buf->rem_bytes && !is_separator(c = *(buf->buffer+pos)))
492   {
493     if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')) || (c == '_') || (c == '-')))
494       error = 1;
495     if (pos < sizeof(tmp))
496         tmp[pos] = c;
497     pos++;
498   }
499   tmp[min(pos, sizeof(tmp) - 1)] = 0;
500
501   if (error)
502   {
503     TRACE("Wrong name %s\n", tmp);
504     return FALSE;
505   }
506
507   buf->buffer += pos;
508   buf->rem_bytes -= pos;
509
510   TRACE("Found name %s\n", tmp);
511   strcpy((char*)buf->value, tmp);
512
513   return TRUE;
514 }
515
516 static BOOL is_float(parse_buffer* buf)
517 {
518   char tmp[512];
519   DWORD pos = 0;
520   char c;
521   float decimal;
522   BOOL dot = 0;
523
524   while (pos < buf->rem_bytes && !is_separator(c = *(buf->buffer+pos)))
525   {
526     if (!((!pos && (c == '-')) || ((c >= '0') && (c <= '9')) || (!dot && (c == '.'))))
527       return FALSE;
528     if (c == '.')
529       dot = TRUE;
530     if (pos < sizeof(tmp))
531         tmp[pos] = c;
532     pos++;
533   }
534   tmp[min(pos, sizeof(tmp) - 1)] = 0;
535
536   buf->buffer += pos;
537   buf->rem_bytes -= pos;
538
539   sscanf(tmp, "%f", &decimal);
540
541   TRACE("Found float %s - %f\n", tmp, decimal);
542
543   *(float*)buf->value = decimal;
544
545   return TRUE;
546 }
547
548 static BOOL is_integer(parse_buffer* buf)
549 {
550   char tmp[512];
551   DWORD pos = 0;
552   char c;
553   DWORD integer;
554
555   while (pos < buf->rem_bytes && !is_separator(c = *(buf->buffer+pos)))
556   {
557     if (!((c >= '0') && (c <= '9')))
558       return FALSE;
559     if (pos < sizeof(tmp))
560         tmp[pos] = c;
561     pos++;
562   }
563   tmp[min(pos, sizeof(tmp) - 1)] = 0;
564
565   buf->buffer += pos;
566   buf->rem_bytes -= pos;
567
568   sscanf(tmp, "%d", &integer);
569
570   TRACE("Found integer %s - %d\n", tmp, integer);
571
572   *(DWORD*)buf->value = integer;
573
574   return TRUE;
575 }
576
577 static BOOL is_string(parse_buffer* buf)
578 {
579   char tmp[512];
580   DWORD pos = 0;
581   char c;
582   BOOL ok = 0;
583
584   if (*buf->buffer != '"')
585     return FALSE;
586
587   while (pos < buf->rem_bytes && !is_operator(c = *(buf->buffer+pos+1)))
588   {
589     if (c == '"')
590     {
591       ok = 1;
592       break;
593     }
594     if (pos < sizeof(tmp))
595         tmp[pos] = c;
596     pos++;
597   }
598   tmp[min(pos, sizeof(tmp) - 1)] = 0;
599
600   if (!ok)
601   {
602     TRACE("Wrong string %s\n", tmp);
603     return FALSE;
604   }
605
606   buf->buffer += pos + 2;
607   buf->rem_bytes -= pos + 2;
608
609   TRACE("Found string %s\n", tmp);
610   strcpy((char*)buf->value, tmp);
611
612   return TRUE;
613 }
614
615 static WORD parse_TOKEN(parse_buffer * buf)
616 {
617   WORD token;
618
619   if (buf->txt)
620   {
621     while(1)
622     {
623       char c;
624       if (!read_bytes(buf, &c, 1))
625         return 0;
626       /*TRACE("char = '%c'\n", is_space(c) ? ' ' : c);*/
627       if ((c == '#') || (c == '/'))
628       {
629         /* Handle comment (# or //) */
630         if (c == '/')
631         {
632           if (!read_bytes(buf, &c, 1))
633             return 0;
634           if (c != '/')
635             return 0;
636         }
637         c = 0;
638         while (c != 0x0A)
639         {
640           if (!read_bytes(buf, &c, 1))
641             return 0;
642         }
643         continue;
644       }
645       if (is_space(c))
646         continue;
647       if (is_operator(c) && (c != '<'))
648       {
649         token = get_operator_token(c);
650         break;
651       }
652       else if (c == '.')
653       {
654         token = TOKEN_DOT;
655         break;
656       }
657       else
658       {
659         rewind_bytes(buf, 1);
660
661         if ((token = get_keyword_token(buf)))
662           break;
663
664         if (is_guid(buf))
665         {
666           token = TOKEN_GUID;
667           break;
668         }
669         if (is_integer(buf))
670         {
671           token = TOKEN_INTEGER;
672           break;
673         }
674         if (is_float(buf))
675         {
676           token = TOKEN_FLOAT;
677           break;
678         }
679         if (is_string(buf))
680         {
681           token = TOKEN_LPSTR;
682           break;
683         }
684         if (is_name(buf))
685         {
686           token = TOKEN_NAME;
687           break;
688         }
689
690         FIXME("Unrecognize element\n");
691         return 0;
692       }
693     }
694   }
695   else
696   {
697     static int nb_elem;
698     static int is_float;
699
700     if (!nb_elem)
701     {
702       if (!read_bytes(buf, &token, 2))
703         return 0;
704
705       /* Convert integer and float list into separate elements */
706       if (token == TOKEN_INTEGER_LIST)
707       {
708         if (!read_bytes(buf, &nb_elem, 4))
709           return 0;
710         token = TOKEN_INTEGER;
711         is_float = FALSE;
712         TRACE("Integer list (TOKEN_INTEGER_LIST) of size %d\n", nb_elem);
713       }
714       else if (token == TOKEN_FLOAT_LIST)
715       {
716         if (!read_bytes(buf, &nb_elem, 4))
717           return 0;
718         token = TOKEN_FLOAT;
719         is_float = TRUE;
720         TRACE("Float list (TOKEN_FLOAT_LIST) of size %d\n", nb_elem);
721       }
722     }
723
724     if (nb_elem)
725     {
726       token = is_float ? TOKEN_FLOAT : TOKEN_INTEGER;
727       nb_elem--;
728         {
729           DWORD integer;
730
731           if (!read_bytes(buf, &integer, 4))
732             return 0;
733
734           *(DWORD*)buf->value = integer;
735         }
736       dump_TOKEN(token);
737       return token;
738     }
739
740     switch (token)
741     {
742       case TOKEN_NAME:
743         {
744           DWORD count;
745           char strname[100];
746
747           if (!read_bytes(buf, &count, 4))
748             return 0;
749           if (!read_bytes(buf, strname, count))
750             return 0;
751           strname[count] = 0;
752           /*TRACE("name = %s\n", strname);*/
753
754           strcpy((char*)buf->value, strname);
755         }
756         break;
757       case TOKEN_INTEGER:
758         {
759           DWORD integer;
760
761           if (!read_bytes(buf, &integer, 4))
762             return 0;
763           /*TRACE("integer = %ld\n", integer);*/
764
765           *(DWORD*)buf->value = integer;
766         }
767         break;
768       case TOKEN_GUID:
769         {
770           char strguid[39];
771           GUID class_id;
772
773           if (!read_bytes(buf, &class_id, 16))
774             return 0;
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);*/
779
780           *(GUID*)buf->value = class_id;
781         }
782         break;
783       case TOKEN_STRING:
784         {
785           DWORD count;
786           WORD tmp_token;
787           char strname[100];
788           if (!read_bytes(buf, &count, 4))
789             return 0;
790           if (!read_bytes(buf, strname, count))
791             return 0;
792           strname[count] = 0;
793           if (!read_bytes(buf, &tmp_token, 2))
794             return 0;
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);*/
798
799           strcpy((char*)buf->value, strname);
800           token = TOKEN_LPSTR;
801         }
802         break;
803       case TOKEN_OBRACE:
804       case TOKEN_CBRACE:
805       case TOKEN_OPAREN:
806       case TOKEN_CPAREN:
807       case TOKEN_OBRACKET:
808       case TOKEN_CBRACKET:
809       case TOKEN_OANGLE:
810       case TOKEN_CANGLE:
811       case TOKEN_DOT:
812       case TOKEN_COMMA:
813       case TOKEN_SEMICOLON:
814       case TOKEN_TEMPLATE:
815       case TOKEN_WORD:
816       case TOKEN_DWORD:
817       case TOKEN_FLOAT:
818       case TOKEN_DOUBLE:
819       case TOKEN_CHAR:
820       case TOKEN_UCHAR:
821       case TOKEN_SWORD:
822       case TOKEN_SDWORD:
823       case TOKEN_VOID:
824       case TOKEN_LPSTR:
825       case TOKEN_UNICODE:
826       case TOKEN_CSTRING:
827       case TOKEN_ARRAY:
828         break;
829       default:
830         return 0;
831     }
832   }
833
834   dump_TOKEN(token);
835
836   return token;
837 }
838
839 static WORD get_TOKEN(parse_buffer * buf)
840 {
841   if (buf->token_present)
842   {
843     buf->token_present = FALSE;
844     return buf->current_token;
845   }
846
847   buf->current_token = parse_TOKEN(buf);
848
849   return buf->current_token;
850 }
851
852 static WORD check_TOKEN(parse_buffer * buf)
853 {
854   if (buf->token_present)
855     return buf->current_token;
856
857   buf->current_token = parse_TOKEN(buf);
858   buf->token_present = TRUE;
859
860   return buf->current_token;
861 }
862
863 static BOOL is_template_available(parse_buffer * buf)
864 {
865   return check_TOKEN(buf) == TOKEN_TEMPLATE;
866 }
867
868 static inline BOOL is_primitive_type(WORD token)
869 {
870   BOOL ret;
871   switch(token)
872   {
873     case TOKEN_WORD:
874     case TOKEN_DWORD:
875     case TOKEN_FLOAT:
876     case TOKEN_DOUBLE:
877     case TOKEN_CHAR:
878     case TOKEN_UCHAR:
879     case TOKEN_SWORD:
880     case TOKEN_SDWORD:
881     case TOKEN_LPSTR:
882     case TOKEN_UNICODE:
883     case TOKEN_CSTRING:
884       ret = 1;
885       break;
886     default:
887       ret = 0;
888       break;
889   }
890   return ret;
891 }
892
893 static BOOL parse_template_option_info(parse_buffer * buf)
894 {
895   xtemplate* cur_template = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates];
896
897   if (check_TOKEN(buf) == TOKEN_DOT)
898   {
899     get_TOKEN(buf);
900     if (get_TOKEN(buf) != TOKEN_DOT)
901       return FALSE;
902     if (get_TOKEN(buf) != TOKEN_DOT)
903       return FALSE;
904     cur_template->open = TRUE;
905   }
906   else
907   {
908     while (1)
909     {
910       if (get_TOKEN(buf) != TOKEN_NAME)
911         return FALSE;
912       strcpy(cur_template->childs[cur_template->nb_childs], (char*)buf->value);
913       if (check_TOKEN(buf) == TOKEN_GUID)
914         get_TOKEN(buf);
915       cur_template->nb_childs++;
916       if (check_TOKEN(buf) != TOKEN_COMMA)
917         break;
918       get_TOKEN(buf);
919     }
920     cur_template->open = FALSE;
921   }
922
923   return TRUE;
924 }
925
926 static BOOL parse_template_members_list(parse_buffer * buf)
927 {
928   int idx_member = 0;
929   member* cur_member;
930
931   while (1)
932   {
933     BOOL array = 0;
934     int nb_dims = 0;
935     cur_member = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[idx_member];
936
937     if (check_TOKEN(buf) == TOKEN_ARRAY)
938     {
939       get_TOKEN(buf);
940       array = 1;
941     }
942
943     if (check_TOKEN(buf) == TOKEN_NAME)
944     {
945       cur_member->type = get_TOKEN(buf);
946       cur_member->idx_template = 0;
947       while (cur_member->idx_template < buf->pdxf->nb_xtemplates)
948       {
949         if (!strcasecmp((char*)buf->value, buf->pdxf->xtemplates[cur_member->idx_template].name))
950           break;
951         cur_member->idx_template++;
952       }
953       if (cur_member->idx_template == buf->pdxf->nb_xtemplates)
954       {
955         ERR("Reference to a nonexistent template '%s'\n", (char*)buf->value);
956         return FALSE;
957       }
958     }
959     else if (is_primitive_type(check_TOKEN(buf)))
960       cur_member->type = get_TOKEN(buf);
961     else
962       break;
963
964     if (get_TOKEN(buf) != TOKEN_NAME)
965       return FALSE;
966     strcpy(cur_member->name, (char*)buf->value);
967
968     if (array)
969     {
970       while (check_TOKEN(buf) == TOKEN_OBRACKET)
971       {
972         if (nb_dims >= MAX_ARRAY_DIM)
973         {
974           FIXME("Too many dimensions (%d) for multi-dimensional array\n", nb_dims + 1);
975           return FALSE;
976         }
977         get_TOKEN(buf);
978         if (check_TOKEN(buf) == TOKEN_INTEGER)
979         {
980           get_TOKEN(buf);
981           cur_member->dim_fixed[nb_dims] = TRUE;
982           cur_member->dim_value[nb_dims] = *(DWORD*)buf->value;
983         }
984         else
985         {
986           int i;
987           if (get_TOKEN(buf) != TOKEN_NAME)
988             return FALSE;
989           for (i = 0; i < idx_member; i++)
990           {
991             if (!strcmp((char*)buf->value, buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[i].name))
992             {
993               if (buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[i].nb_dims)
994               {
995                 ERR("Array cannot be used to specify variable array size\n");
996                 return FALSE;
997               }
998               if (buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[i].type != TOKEN_DWORD)
999               {
1000                 FIXME("Only DWORD supported to specify variable array size\n");
1001                 return FALSE;
1002               }
1003               break;
1004             }
1005           }
1006           if (i == idx_member)
1007           {
1008             ERR("Reference to unknown member %s\n", (char*)buf->value);
1009             return FALSE;
1010           }
1011           cur_member->dim_fixed[nb_dims] = FALSE;
1012           cur_member->dim_value[nb_dims] = i;
1013         }
1014         if (get_TOKEN(buf) != TOKEN_CBRACKET)
1015           return FALSE;
1016         nb_dims++;
1017       }
1018       if (!nb_dims)
1019         return FALSE;
1020       cur_member->nb_dims = nb_dims;
1021     }
1022     if (get_TOKEN(buf) != TOKEN_SEMICOLON)
1023       return FALSE;
1024
1025     idx_member++;
1026   }
1027
1028   buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].nb_members = idx_member;
1029
1030   return TRUE;
1031 }
1032
1033 static BOOL parse_template_parts(parse_buffer * buf)
1034 {
1035   if (!parse_template_members_list(buf))
1036     return FALSE;
1037   if (check_TOKEN(buf) == TOKEN_OBRACKET)
1038   {
1039     get_TOKEN(buf);
1040     if (!parse_template_option_info(buf))
1041       return FALSE;
1042     if (get_TOKEN(buf) != TOKEN_CBRACKET)
1043      return FALSE;
1044   }
1045
1046   return TRUE;
1047 }
1048
1049 static void go_to_next_definition(parse_buffer * buf)
1050 {
1051   char c;
1052   while (buf->rem_bytes)
1053   {
1054     if (!read_bytes(buf, &c, 1))
1055       return;
1056     if ((c == '#') || (c == '/'))
1057     {
1058       /* Handle comment (# or //) */
1059       if (c == '/')
1060       {
1061         if (!read_bytes(buf, &c, 1))
1062           return;
1063         if (c != '/')
1064           return;
1065       }
1066       c = 0;
1067       while (c != 0x0A)
1068       {
1069         if (!read_bytes(buf, &c, 1))
1070           return;
1071       }
1072       continue;
1073     }
1074     else if (!is_space(c))
1075     {
1076       rewind_bytes(buf, 1);
1077       break;
1078     }
1079   }
1080 }
1081
1082 static BOOL parse_template(parse_buffer * buf)
1083 {
1084   if (get_TOKEN(buf) != TOKEN_TEMPLATE)
1085     return FALSE;
1086   if (get_TOKEN(buf) != TOKEN_NAME)
1087     return FALSE;
1088   strcpy(buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].name, (char*)buf->value);
1089   if (get_TOKEN(buf) != TOKEN_OBRACE)
1090     return FALSE;
1091   if (get_TOKEN(buf) != TOKEN_GUID)
1092     return FALSE;
1093   buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].class_id = *(GUID*)buf->value;
1094   if (!parse_template_parts(buf))
1095     return FALSE;
1096   if (get_TOKEN(buf) != TOKEN_CBRACE)
1097     return FALSE;
1098   if (buf->txt)
1099   {
1100     /* Go to the next template */
1101     go_to_next_definition(buf);
1102   }
1103
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++;
1106
1107   return TRUE;
1108 }
1109
1110 BOOL parse_templates(parse_buffer * buf)
1111 {
1112   while (buf->rem_bytes && is_template_available(buf))
1113   {
1114     if (!parse_template(buf))
1115     {
1116       WARN("Template is not correct\n");
1117       return FALSE;
1118     }
1119     else
1120     {
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]);
1124     }
1125   }
1126   return TRUE;
1127 }
1128
1129 static BOOL check_buffer(parse_buffer * buf, ULONG size)
1130 {
1131   if ((buf->cur_pos_data + size) > buf->capacity)
1132   {
1133     LPBYTE pdata;
1134     ULONG new_capacity = buf->capacity ? 2 * buf->capacity : 100000;
1135
1136     pdata = HeapAlloc(GetProcessHeap(), 0, new_capacity);
1137     if (!pdata)
1138       return FALSE;
1139     memcpy(pdata, buf->pdata, buf->cur_pos_data);
1140     HeapFree(GetProcessHeap(), 0, buf->pdata);
1141     buf->capacity = new_capacity;
1142     buf->pdata = pdata;
1143     buf->pxo->root->pdata = pdata;
1144   }
1145   return TRUE;
1146 }
1147
1148 static BOOL parse_object_parts(parse_buffer * buf, BOOL allow_optional);
1149 static BOOL parse_object_members_list(parse_buffer * buf)
1150 {
1151   DWORD token;
1152   int i;
1153   xtemplate* pt = buf->pxt[buf->level];
1154
1155   for (i = 0; i < pt->nb_members; i++)
1156   {
1157     int k;
1158     int nb_elems = 1;
1159
1160     buf->pxo->members[i].name = pt->members[i].name;
1161     buf->pxo->members[i].start = buf->cur_pos_data;
1162
1163     for (k = 0; k < pt->members[i].nb_dims; k++)
1164     {
1165       if (pt->members[i].dim_fixed[k])
1166         nb_elems *= pt->members[i].dim_value[k];
1167       else
1168         nb_elems *= *(DWORD*)(buf->pxo->root->pdata + buf->pxo->members[pt->members[i].dim_value[k]].start);
1169     }
1170
1171     TRACE("Elements to consider: %d\n", nb_elems);
1172
1173     for (k = 0; k < nb_elems; k++)
1174     {
1175       if (buf->txt && k)
1176       {
1177         token = check_TOKEN(buf);
1178         if (token == TOKEN_COMMA)
1179         {
1180           get_TOKEN(buf);
1181         }
1182         else
1183         {
1184           /* Allow comma omission */
1185           if (!((token == TOKEN_FLOAT) || (token == TOKEN_INTEGER)))
1186             return FALSE;
1187         }
1188       }
1189
1190       if (pt->members[i].type == TOKEN_NAME)
1191       {
1192         int j;
1193
1194         TRACE("Found sub-object %s\n", buf->pdxf->xtemplates[pt->members[i].idx_template].name);
1195         buf->level++;
1196         /* To do template lookup */
1197         for (j = 0; j < buf->pdxf->nb_xtemplates; j++)
1198         {
1199           if (!strcasecmp(buf->pdxf->xtemplates[pt->members[i].idx_template].name, buf->pdxf->xtemplates[j].name))
1200           {
1201             buf->pxt[buf->level] = &buf->pdxf->xtemplates[j];
1202             break;
1203           }
1204         }
1205         if (j == buf->pdxf->nb_xtemplates)
1206         {
1207           ERR("Unknown template %s\n", (char*)buf->value);
1208           buf->level--;
1209           return FALSE;
1210         }
1211         TRACE("Enter %s\n", buf->pdxf->xtemplates[pt->members[i].idx_template].name);
1212         if (!parse_object_parts(buf, FALSE))
1213         {
1214           buf->level--;
1215           return FALSE;
1216         }
1217         buf->level--;
1218       }
1219       else
1220       {
1221         token = check_TOKEN(buf);
1222         if (token == TOKEN_INTEGER)
1223         {
1224           get_TOKEN(buf);
1225           TRACE("%s = %d\n", pt->members[i].name, *(DWORD*)buf->value);
1226           /* Assume larger size */
1227           if (!check_buffer(buf, 4))
1228             return FALSE;
1229           if (pt->members[i].type == TOKEN_WORD)
1230           {
1231             *(((WORD*)(buf->cur_pos_data + buf->pdata))) = (WORD)(*(DWORD*)buf->value);
1232             buf->cur_pos_data += 2;
1233           }
1234           else if (pt->members[i].type == TOKEN_DWORD)
1235           {
1236             *(((DWORD*)(buf->cur_pos_data + buf->pdata))) = (DWORD)(*(DWORD*)buf->value);
1237             buf->cur_pos_data += 4;
1238           }
1239           else
1240           {
1241             FIXME("Token %d not supported\n", pt->members[i].type);
1242             return FALSE;
1243           }
1244         }
1245         else if (token == TOKEN_FLOAT)
1246         {
1247           get_TOKEN(buf);
1248           TRACE("%s = %f\n", pt->members[i].name, *(float*)buf->value);
1249           if (!check_buffer(buf, 4))
1250             return FALSE;
1251           if (pt->members[i].type == TOKEN_FLOAT)
1252           {
1253             *(((float*)(buf->cur_pos_data + buf->pdata))) = (float)(*(float*)buf->value);
1254             buf->cur_pos_data += 4;
1255           }
1256           else
1257           {
1258             FIXME("Token %d not supported\n", pt->members[i].type);
1259             return FALSE;
1260           }
1261         }
1262         else if (token == TOKEN_LPSTR)
1263         {
1264           get_TOKEN(buf);
1265           TRACE("%s = %s\n", pt->members[i].name, (char*)buf->value);
1266           if (!check_buffer(buf, sizeof(LPSTR)))
1267             return FALSE;
1268           if (pt->members[i].type == TOKEN_LPSTR)
1269           {
1270             int len = strlen((char*)buf->value) + 1;
1271             if ((buf->cur_pstrings - buf->pstrings + len) > MAX_STRINGS_BUFFER)
1272             {
1273               FIXME("Buffer too small %p %p %d\n", buf->cur_pstrings, buf->pstrings, len);
1274               return FALSE;
1275             }
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);
1280           }
1281           else
1282           {
1283             FIXME("Token %d not supported\n", pt->members[i].type);
1284             return FALSE;
1285           }
1286         }
1287         else
1288         {
1289           FIXME("Unexpected token %d\n", token);
1290           return FALSE;
1291         }
1292       }
1293     }
1294
1295     if (nb_elems && buf->txt && (check_TOKEN(buf) != TOKEN_CBRACE) && (check_TOKEN(buf) != TOKEN_NAME))
1296     {
1297       token = get_TOKEN(buf);
1298       if ((token != TOKEN_SEMICOLON) && (token != TOKEN_COMMA))
1299         return FALSE;
1300     }
1301   }
1302
1303   return TRUE;
1304 }
1305
1306 static BOOL parse_object_parts(parse_buffer * buf, BOOL allow_optional)
1307 {
1308   buf->pxo->nb_childs = 0;
1309
1310   if (!parse_object_members_list(buf))
1311     return FALSE;
1312
1313   if (allow_optional)
1314   {
1315     buf->pxo->size = buf->cur_pos_data - buf->pxo->pos_data;
1316
1317     /* Skip trailing semicolon */
1318     while (check_TOKEN(buf) == TOKEN_SEMICOLON)
1319       get_TOKEN(buf);
1320
1321     while (1)
1322     {
1323       if (check_TOKEN(buf) == TOKEN_OBRACE)
1324       {
1325         int i, j;
1326         get_TOKEN(buf);
1327         if (get_TOKEN(buf) != TOKEN_NAME)
1328           return FALSE;
1329         if (get_TOKEN(buf) != TOKEN_CBRACE)
1330           return FALSE;
1331         TRACE("Found optional reference %s\n", (char*)buf->value);
1332         for (i = 0; i < (buf->nb_pxo_globals+1); i++)
1333         {
1334           for (j = 0; j < (buf->pxo_globals[i])[0].nb_subobjects; j++)
1335           {
1336             if (!strcmp((buf->pxo_globals[i])[j].name, (char*)buf->value))
1337               goto _exit;
1338           }
1339         }
1340 _exit:
1341         if (i == (buf->nb_pxo_globals+1))
1342         {
1343           ERR("Reference to unknown object %s\n", (char*)buf->value);
1344           return FALSE;
1345         }
1346
1347         if (buf->pxo->root->nb_subobjects >= MAX_SUBOBJECTS)
1348         {
1349             FIXME("Too many sub-objects\n");
1350             return FALSE;
1351         }
1352
1353         buf->pxo->childs[buf->pxo->nb_childs] = &buf->pxo_tab[buf->pxo->root->nb_subobjects++];
1354         buf->pxo->childs[buf->pxo->nb_childs]->ptarget = &(buf->pxo_globals[i])[j];
1355         buf->pxo->childs[buf->pxo->nb_childs]->binary = FALSE;
1356         buf->pxo->nb_childs++;
1357       }
1358       else if (check_TOKEN(buf) == TOKEN_NAME)
1359       {
1360         xobject* pxo = buf->pxo;
1361
1362         if (buf->pxo->root->nb_subobjects >= MAX_SUBOBJECTS)
1363         {
1364             FIXME("Too many sub-objects\n");
1365             return FALSE;
1366         }
1367
1368         buf->pxo = buf->pxo->childs[buf->pxo->nb_childs] = &buf->pxo_tab[buf->pxo->root->nb_subobjects++];
1369
1370         TRACE("Enter optional %s\n", (char*)buf->value);
1371         buf->level++;
1372         if (!parse_object(buf))
1373         {
1374           buf->level--;
1375           return FALSE;
1376         }
1377         buf->level--;
1378         buf->pxo = pxo;
1379         buf->pxo->nb_childs++;
1380       }
1381       else
1382         break;
1383     }
1384   }
1385
1386   if (buf->pxo->nb_childs > MAX_CHILDS)
1387   {
1388     FIXME("Too many children %d\n", buf->pxo->nb_childs);
1389     return FALSE;
1390   }
1391
1392   return TRUE;
1393 }
1394
1395 BOOL parse_object(parse_buffer * buf)
1396 {
1397   int i;
1398
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;
1403
1404   if (get_TOKEN(buf) != TOKEN_NAME)
1405     return FALSE;
1406
1407   /* To do template lookup */
1408   for (i = 0; i < buf->pdxf->nb_xtemplates; i++)
1409   {
1410     if (!strcasecmp((char*)buf->value, buf->pdxf->xtemplates[i].name))
1411     {
1412       buf->pxt[buf->level] = &buf->pdxf->xtemplates[i];
1413       memcpy(&buf->pxo->type, &buf->pdxf->xtemplates[i].class_id, 16);
1414       break;
1415     }
1416   }
1417   if (i == buf->pdxf->nb_xtemplates)
1418   {
1419     ERR("Unknown template %s\n", (char*)buf->value);
1420     return FALSE;
1421   }
1422
1423   if (check_TOKEN(buf) == TOKEN_NAME)
1424   {
1425     get_TOKEN(buf);
1426     strcpy(buf->pxo->name, (char*)buf->value);
1427   }
1428   else
1429     buf->pxo->name[0] = 0;
1430
1431   if (get_TOKEN(buf) != TOKEN_OBRACE)
1432     return FALSE;
1433   if (check_TOKEN(buf) == TOKEN_GUID)
1434   {
1435     get_TOKEN(buf);
1436     memcpy(&buf->pxo->class_id, buf->value, 16);
1437   }
1438   else
1439     memset(&buf->pxo->class_id, 0, 16);
1440
1441   if (!parse_object_parts(buf, TRUE))
1442     return FALSE;
1443   if (get_TOKEN(buf) != TOKEN_CBRACE)
1444     return FALSE;
1445
1446   if (buf->txt)
1447   {
1448     /* Go to the next object */
1449     go_to_next_definition(buf);
1450   }
1451
1452   return TRUE;
1453 }