FreeWRL/FreeX3D  3.0.0
ColladaParser.c
1 /*
2 
3 
4 ???
5 
6 */
7 
8 /****************************************************************************
9  This file is part of the FreeWRL/FreeX3D Distribution.
10 
11  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12 
13  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14  it under the terms of the GNU Lesser Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  GNU General Public License for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25 ****************************************************************************/
26 
27 #if defined (INCLUDE_NON_WEB3D_FORMATS)
28 #include <config.h>
29 
30 #include <system.h>
31 #include <display.h>
32 #include <internal.h>
33 
34 #include <libFreeWRL.h>
35 
36 #include "../vrml_parser/Structs.h"
37 #include "../main/headers.h"
38 #include "../vrml_parser/CParseGeneral.h"
39 #include "../scenegraph/Vector.h"
40 #include "../vrml_parser/CFieldDecls.h"
41 #include "../world_script/JScript.h"
42 #include "../world_script/CScripts.h"
43 #include "../world_script/fieldSet.h"
44 #include "../vrml_parser/CParseParser.h"
45 #include "../vrml_parser/CParseLexer.h"
46 #include "../vrml_parser/CParse.h"
47 #include "../input/EAIHeaders.h" /* resolving implicit declarations */
48 #include "../input/EAIHelpers.h" /* resolving implicit declarations */
49 
50 
51 #include "ColladaParser.h"
52 
53 
54 #define INCREMENT_PARENTINDEXC \
55  if (p->parentIndex < (PARENTSTACKSIZE-2)) { \
56  p->parentIndex++; \
57  p->colladaParentStack[p->parentIndex] = NULL; /* make sure we know the state of the new Top of Stack */ \
58  } else ConsoleMessage ("ColladaParser, line %d stack overflow",LINE);
59 
60 #include <libxml/parser.h>
61 typedef xmlSAXHandler* XML_Parser;
62 
63 /* for now - fill this in later */
64 #define XML_GetCurrentLineNumber(aaa) -1L
65 #define XML_ParserFree(aaa) FREE_IF_NZ(aaa)
66 #define XML_SetUserData(aaa,bbb)
67 #define XML_STATUS_ERROR -1
68 #define XML_GetErrorCode(aaa)
69 #define XML_ErrorString(aaa) "errors not currently being reported by libxml port"
70 
71 
72 static int XML_ParseFile(xmlSAXHandler *me, const char *myinput, int myinputlen, int recovery) {
73  int notUsed;
74 
75  if (xmlSAXUserParseMemory(me, &notUsed, myinput,myinputlen) == 0) return 0;
76  return XML_STATUS_ERROR;
77 }
78 
79 
80 /* basic parser stuff */
81 #define XML_CreateParserLevel(aaa) \
82  aaa = MALLOC(xmlSAXHandler *, sizeof (xmlSAXHandler)); \
83  bzero (aaa,sizeof(xmlSAXHandler));
84 
85 /* elements */
86 #define XML_SetElementHandler(aaa,bbb,ccc) \
87  aaa->startElement = bbb; \
88  aaa->endElement = ccc;
89 
90 /* CDATA handling */
91 #define XML_SetDefaultHandler(aaa,bbb) /* this is CDATA related too */
92 #define XML_SetCdataSectionHandler(aaa,bbb,ccc) \
93  aaa->cdataBlock = endCDATA;
94 
95 //#define PROTOINSTANCE_MAX_LEVELS 10
96 //static XML_Parser colladaParser[PROTOINSTANCE_MAX_LEVELS];
97 //static XML_Parser currentColladaParser = NULL;
99 //static int ColladaParserRecurseLevel = 0;
100 //static int inCDATA = FALSE;
101 //struct X3D_Node *colladaParentStack[PARENTSTACKSIZE];
102 //static int indentLevel = 0;
103 
104 typedef struct pColladaParser{
105  XML_Parser colladaParser[PROTOINSTANCE_MAX_LEVELS];
106  XML_Parser currentColladaParser;// = NULL;
107  int parentIndex;// = 0;
108  int ColladaParserRecurseLevel;// = 0;
109  int inCDATA;// = FALSE;
110  struct X3D_Node *colladaParentStack[PARENTSTACKSIZE];
111  int indentLevel;// = 0;
112 
113 }* ppColladaParser;
114 void *ColladaParser_constructor(){
115  void *v = MALLOCV(sizeof(struct pColladaParser));
116  memset(v,0,sizeof(struct pColladaParser));
117  return v;
118 }
119 void ColladaParser_init(struct tColladaParser *t){
120  //public
121  //private
122  t->prv = ColladaParser_constructor();
123  {
124  ppColladaParser p = (ppColladaParser)t->prv;
125  //p->colladaParser[PROTOINSTANCE_MAX_LEVELS];
126  p->currentColladaParser = NULL;
127  //static int parentIndex = 0;
128  p->ColladaParserRecurseLevel = 0;
129  p->inCDATA = FALSE;
130  //p->colladaParentStack[PARENTSTACKSIZE];
131  p->indentLevel = 0;
132  p->parentIndex = 0;
133  }
134 }
135 
136 static void XMLCALL startCDATA (void *userData) {
137  ttglobal tg = gglobal();
138  if (tg->X3DParser.CDATA_Text_curlen != 0) {
139 /*
140  ConsoleMessage ("X3DParser - hmmm, expected CDATA_Text_curlen to be 0, is not");
141  printf ("CDATA_TEXT_CURLEN is %d\n",CDATA_Text_curlen);
142 printf ("CADAT_Text:%s:\n",CDATA_Text);
143 */
144  tg->X3DParser.CDATA_Text_curlen = 0;
145  }
146 
147  #ifdef COLLADAPARSERVERBOSE
148  printf ("startCDATA -parentIndex %d parserMode %s\n",parentIndex,parserModeStrings[getMode(ud,TOP)]);
149  #endif
150  ((ppColladaParser)(gglobal()->ColladaParser.prv))->inCDATA = TRUE;
151 }
152 
153 static void XMLCALL endCDATA (void *userData, const xmlChar *value, int len) {
154  #ifdef COLLADAPARSERVERBOSE
155  printf ("endCDATA, cur index %d\n",CDATA_Text_curlen);
156  printf ("endCDATA -parentIndex %d parserMode %s\n",parentIndex,parserModeStrings[getMode(ud,TOP)]);
157  #endif
158  ((ppColladaParser)(gglobal()->ColladaParser.prv))->inCDATA = FALSE;
159 
160  /* x3d specific dumpCDATAtoProtoBody (CDATA_Text); */
161 
162  #ifdef COLLADAPARSERVERBOSE
163  printf ("returning from EndCData\n");
164  #endif
165 
166 
167 }
168 
169 static void XMLCALL handleCDATA (void *userData, const char *string, int len) {
170 /*
171  printf ("handleCDATA...(%d)...",len);
172 if (inCDATA) printf ("inCDATA..."); else printf ("not inCDATA...");
173 printf ("\n");
174 */
175 }
176 
177 static void XMLCALL ColladaStartElement(void *unused, const xmlChar *name, const xmlChar **atts) {
178 
179 #ifdef COLLADAVERBOSE
180 {int i,j; for (j=0; j< indentLevel; j++) printf (" ");
181  printf ("startElement: %s : level %d\n",name,indentLevel);
182  for (i = 0; atts[i]; i += 2) {
183  for (j=0; j< indentLevel; j++) printf (" ");
184  printf(" field:%s=%s\n", atts[i], atts[i + 1]);
185  }
186 }
187 #endif
188 
189  ((ppColladaParser)(gglobal()->ColladaParser.prv))->indentLevel++;
190 }
191 
192 static void XMLCALL ColladaEndElement(void *unused, const xmlChar *name) {
193  ((ppColladaParser)(gglobal()->ColladaParser.prv))->indentLevel--;
194 
195 #ifdef COLLADAVERBOSE
196 {int i; for (i=0; i< indentLevel; i++) printf (" ");
197  printf ("endElement: %s : level %d\n",name,indentLevel);
198 }
199 #endif
200 
201 }
202 
203 
204 static XML_Parser initializeColladaParser () {
205  ppColladaParser p = (ppColladaParser)gglobal()->ColladaParser.prv;
206  p->ColladaParserRecurseLevel++;
207 
208  if (p->ColladaParserRecurseLevel >= PROTOINSTANCE_MAX_LEVELS) {
209  ConsoleMessage ("XML_PARSER init: XML file PROTO nested too deep\n");
210  p->ColladaParserRecurseLevel--;
211  } else {
212  XML_CreateParserLevel(p->colladaParser[p->ColladaParserRecurseLevel]);
213  XML_SetElementHandler(p->colladaParser[p->ColladaParserRecurseLevel], ColladaStartElement, ColladaEndElement);
214  XML_SetCdataSectionHandler (p->colladaParser[p->ColladaParserRecurseLevel], startCDATA, endCDATA);
215  XML_SetDefaultHandler (p->colladaParser[p->ColladaParserRecurseLevel],handleCDATA);
216  XML_SetUserData(p->colladaParser[p->ColladaParserRecurseLevel], &p->parentIndex);
217  }
218  /* printf ("initializeColladaParser, level %d, parser %u\n",colladaParser[ColladaParserRecurseLevel]); */
219 
220  return p->colladaParser[p->ColladaParserRecurseLevel];
221 }
222 
223 static void shutdownColladaParser () {
224  ttglobal tg = gglobal();
225  ppColladaParser p = (ppColladaParser)tg->ColladaParser.prv;
226  /* printf ("shutdownColladaParser, recurseLevel %d\n",ColladaParserRecurseLevel); */
227  XML_ParserFree(p->colladaParser[p->ColladaParserRecurseLevel]);
228  p->ColladaParserRecurseLevel--;
229 
230  /* lets free up memory here for possible PROTO variables */
231  if (p->ColladaParserRecurseLevel == INT_ID_UNDEFINED) {
232  /* if we are at the bottom of the parser call nesting, lets reset parentIndex */
233  p->parentIndex = 0;
234  /* x3d specific freeProtoMemory (); */
235  }
236 
237  if (p->ColladaParserRecurseLevel < INT_ID_UNDEFINED) {
238  ConsoleMessage ("XML_PARSER close underflow");
239  p->ColladaParserRecurseLevel = INT_ID_UNDEFINED;
240  }
241 
242  /* CDATA text space, free it up */
243  FREE_IF_NZ(tg->X3DParser.CDATA_Text);
244  if (p->ColladaParserRecurseLevel > INT_ID_UNDEFINED)
245  p->currentColladaParser = p->colladaParser[p->ColladaParserRecurseLevel];
246 
247  /* printf ("shutdownColladaParser, current ColladaParser %u\n",currentColladaParser); */
248 }
249 
250 int ColladaParse (struct X3D_Group* myParent, const char *inputstring) {
251  ppColladaParser p = (ppColladaParser)gglobal()->ColladaParser.prv;
252  p->currentColladaParser = initializeColladaParser();
253 
254  /* printf ("X3DParse, current ColladaParser is %u\n",currentColladaParser); */
255 
256 
257  INCREMENT_PARENTINDEXC
258  p->colladaParentStack[p->parentIndex] = X3D_NODE(myParent);
259 
260  if (XML_ParseFile(p->currentColladaParser, inputstring, (int) strlen(inputstring), TRUE) == XML_STATUS_ERROR) {
261  fprintf(stderr,
262  "%s at line %" XML_FMT_INT_MOD "u\n",
263  XML_ErrorString(XML_GetErrorCode(currentColladaParser)),
264  XML_GetCurrentLineNumber(currentColladaParser));
265  shutdownColladaParser();
266  return FALSE;
267  }
268  shutdownColladaParser();
269  return TRUE;
270 }
271 #endif //INCLUDE_NON_WEB3D_FORMATS