Update ooo320-m1
[ooovba.git] / xml2cmp / source / xcd / parse.cxx
blobe5f623f4cd3b1a4a6cebda5668ba7bf00a3d53c7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: parse.cxx,v $
10 * $Revision: 1.12 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org 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 Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 #include <parse.hxx>
34 #include <string.h>
35 #include <iostream>
36 #include <xmlelem.hxx>
38 #if (_MSC_VER >=1400)
39 #pragma warning(disable:4365)
40 #endif
42 #ifdef UNX
43 #define strnicmp strncasecmp
44 #endif
48 // NOT FULLY DEFINED SERVICES
52 #define AssertionOf(x) \
53 {if (!(x)) {std::cerr << "Assertion failed: " << #x << __FILE__ << __LINE__ << std::endl; exit(3); }}
57 X2CParser::X2CParser( XmlElement & o_rDocumentData )
58 : // sFileName,
59 nFileLine(0),
60 pDocumentData(&o_rDocumentData),
61 // sWord,
62 text(0)
66 X2CParser::~X2CParser()
71 bool
72 X2CParser::LoadFile( const char * i_sFilename )
74 sFileName = i_sFilename;
75 nFileLine = 1;
77 // Load file:
78 if ( ! LoadXmlFile( aFile, i_sFilename ) )
79 return false;
81 // Test correct end:
82 const char * pLastTag = strrchr(aFile.operator const char *(),'<');
83 if (pLastTag == 0)
84 return false;
85 if ( strnicmp(pLastTag+2, pDocumentData->Name().str(), pDocumentData->Name().l()) != 0
86 || strnicmp(pLastTag, "</", 2) != 0 )
87 return false;
88 if (strchr(pLastTag,'>') == 0)
89 return false;
90 return true;
93 void
94 X2CParser::Parse()
96 // Parse:
97 text = aFile.operator const char *();
99 Parse_XmlDeclaration();
100 Parse_Doctype();
102 pDocumentData->Parse(*this);
105 bool
106 X2CParser::Parse( const char * i_sFilename )
108 bool ret = LoadFile(i_sFilename);
109 if (ret)
110 Parse();
111 return ret;
114 void
115 X2CParser::Parse_XmlDeclaration()
117 Goto('<');
118 if ( IsText("<?xml") )
120 Goto_And_Pass('>');
124 void
125 X2CParser::Parse_Doctype()
127 Goto('<');
128 if ( IsText("<!DOCTYPE") )
129 Goto_And_Pass('>');
132 void
133 X2CParser::Parse_Sequence( DynamicList<XmlElement> & o_rElements,
134 const Simstr & i_sElementName )
136 CheckAndPassBeginTag(i_sElementName.str());
138 unsigned int i_max = o_rElements.size();
139 for (unsigned i = 0; i < i_max; ++i)
141 o_rElements[i]->Parse(*this);
142 } // end for
144 CheckAndPassEndTag(i_sElementName.str());
147 void
148 X2CParser::Parse_FreeChoice( DynamicList<XmlElement> & o_rElements )
150 unsigned nSize = o_rElements.size();
152 for ( bool bBreak = false; !bBreak; )
154 bBreak = true;
155 for ( unsigned i = 0; i < nSize; ++i )
157 Goto('<');
158 if ( IsBeginTag(o_rElements[i]->Name().str()) )
160 o_rElements[i]->Parse(*this);
161 bBreak = false;
162 break;
164 } // end for i
165 } // end for !bBreak
168 void
169 X2CParser::Parse_List( ListElement & o_rListElem )
172 for ( Goto('<'); IsBeginTag(o_rListElem.Name().str()); Goto('<') )
174 XmlElement * pNew = o_rListElem.Create_and_Add_NewElement();
175 pNew->Parse(*this);
179 void
180 X2CParser::Parse_Text( Simstr & o_sText,
181 const Simstr & i_sElementName,
182 bool i_bReverseName )
185 if ( ! CheckAndPassBeginTag(i_sElementName.str()) )
186 return;
188 // Add new Element
189 GetTextTill( o_sText, '<', i_bReverseName );
190 o_sText.remove_trailing_blanks();
192 CheckAndPassEndTag(i_sElementName.str());
195 void
196 X2CParser::Parse_MultipleText( List<Simstr> & o_rTexts,
197 const Simstr & i_sElementName,
198 bool i_bReverseName )
200 for ( Goto('<'); IsBeginTag(i_sElementName.str()); Goto('<') )
202 Simstr sNew;
203 Parse_Text(sNew, i_sElementName, i_bReverseName);
204 if (sNew.l() > 0)
205 o_rTexts.push_back(sNew);
209 void
210 X2CParser::Parse_SglAttr( Simstr & o_sAttrValue,
211 const Simstr & i_sElementName,
212 const Simstr & i_sAttrName )
214 Goto('<');
215 if ( !IsBeginTag(i_sElementName.str()) )
216 SyntaxError("unexpected element");
217 Move( i_sElementName.l() + 1 );
219 Pass_White();
220 if (*text == '>')
221 SyntaxError("no attribute found, where one was expected");
222 Simstr sAttrName;
223 Get_Attribute(o_sAttrValue, sAttrName);
224 if (sAttrName != i_sAttrName)
225 SyntaxError("unknown attribute found");
226 Pass_White();
227 if (strncmp(text,"/>",2) != 0)
228 SyntaxError("missing \"/>\" at end of empty element");
229 Move(2);
232 void
233 X2CParser::Parse_MultipleAttr( List<Simstr> & o_rAttrValues,
234 const Simstr & i_sElementName,
235 const List<Simstr> & i_rAttrNames )
237 Goto('<');
238 if ( !IsBeginTag(i_sElementName.str()) )
239 SyntaxError("unexpected element");
240 Move( i_sElementName.l() + 1 );
241 Simstr sAttrName;
242 Simstr sAttrValue;
243 unsigned nSize = i_rAttrNames.size();
244 unsigned i;
246 for ( Pass_White(); *text != '/'; Pass_White() )
249 Get_Attribute(sAttrValue, sAttrName);
251 for ( i = 0; i < nSize; ++i )
253 if ( i_rAttrNames[i] == sAttrName )
255 o_rAttrValues[i] = sAttrValue;
256 break;
259 if (i == nSize)
260 SyntaxError("unknown attribute found");
262 Move(2);
266 void
267 X2CParser::Get_Attribute( Simstr & o_rAttrValue,
268 Simstr & o_rAttrName )
270 GetTextTill( o_rAttrName, '=');
272 while (*(++text) != '"')
274 if (*text == '\0')
275 SyntaxError("unexpected end of file");
278 ++text;
279 GetTextTill( o_rAttrValue, '"');
280 ++text;
283 bool
284 X2CParser::IsText( const char * i_sComparedText )
286 return strnicmp( text, i_sComparedText, strlen(i_sComparedText) ) == 0;
289 bool
290 X2CParser::IsBeginTag( const char * i_sTagName )
292 return strnicmp( text+1, i_sTagName, strlen(i_sTagName) ) == 0
293 && *text == '<';
296 bool
297 X2CParser::IsEndTag( const char * i_sTagName )
299 return strnicmp( text+2, i_sTagName, strlen(i_sTagName) ) == 0
300 && strnicmp( text, "</", 2 ) == 0;
303 void
304 X2CParser::Goto( char i_cNext )
306 while (*text != i_cNext)
308 TestCurChar();
309 ++text;
313 void
314 X2CParser::Goto_And_Pass( char i_cNext )
316 Goto(i_cNext);
317 ++text;
320 void
321 X2CParser::Move( int i_nForward )
323 text += i_nForward;
326 void
327 X2CParser::Pass_White()
329 while (*text <= 32)
331 TestCurChar();
332 ++text;
336 void
337 X2CParser::GetTextTill( Simstr & o_rText,
338 char i_cEnd,
339 bool i_bReverseName )
341 char * pResult = &sWord[0];
342 char * pSet;
344 for ( pSet = pResult;
345 *text != i_cEnd;
346 ++text )
348 TestCurChar();
349 *pSet++ = *text;
352 while ( *pResult < 33 && *pResult > 0 )
353 ++pResult;
354 while ( pSet > pResult ? *(pSet-1) < 33 : false )
355 pSet--;
356 *pSet = '\0';
359 if (i_bReverseName)
361 const unsigned int nMaxLen = 1000;
362 if (strlen(pResult) < nMaxLen)
364 char * sBreak = strrchr(pResult,'.');
365 if (sBreak != 0)
367 static char sScope[nMaxLen+10];
368 static char sName[nMaxLen+10];
370 unsigned nScopeLen = sBreak - pResult;
371 strncpy ( sScope, pResult, nScopeLen ); // STRNCPY SAFE HERE
372 sScope[nScopeLen] = '\0';
373 strcpy( sName, sBreak + 1 ); // STRCPY SAFE HERE
374 strcat( sName, " in " ); // STRCAT SAFE HERE
375 strcat( sName, sScope ); // STRCAT SAFE HERE
377 o_rText = sName;
378 return;
381 } // endif (i_bReverseName)
383 o_rText = &sWord[0];
386 bool
387 X2CParser::CheckAndPassBeginTag( const char * i_sElementName )
389 bool ret = true;
390 Goto('<');
391 if ( ! IsBeginTag(i_sElementName) )
392 SyntaxError( "unexpected element");
393 if (IsAbsoluteEmpty())
394 ret = false;
395 Goto_And_Pass('>');
396 if (ret)
397 Pass_White();
398 return ret;
401 void
402 X2CParser::CheckAndPassEndTag( const char * i_sElementName )
404 Pass_White();
405 if ( !IsEndTag(i_sElementName) )
406 SyntaxError("missing or not matching end tag");
407 Goto_And_Pass('>');
410 bool
411 X2CParser::IsAbsoluteEmpty() const
413 const char * pEnd = strchr(text+1, '>');
414 if (pEnd != 0)
416 if ( *(pEnd-1) == '/' )
418 const char * pAttr = strchr(text+1, '"');
419 if (pAttr == 0)
420 return true;
421 else if ( (pAttr-text) > (pEnd-text) )
422 return true;
425 return false;
428 void
429 X2CParser::SyntaxError( const char * i_sText )
431 std::cerr
432 << "Syntax error "
433 << i_sText
434 << " in file: "
435 << sFileName.str()
436 << " in line "
437 << nFileLine
438 << "."
439 << std::endl;
441 exit(3);
444 void
445 X2CParser::TestCurChar()
447 // if (*text == '\0')
448 // SyntaxError("unexpected end of file");
449 // else
451 if (*text == '\n')
452 nFileLine++;