Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : :
21 : : #include <parse.hxx>
22 : :
23 : : #include <string.h>
24 : : #include <iostream>
25 : : #include <xmlelem.hxx>
26 : :
27 : : #if (_MSC_VER >=1400)
28 : : #pragma warning(disable:4365)
29 : : #endif
30 : :
31 : : #ifdef UNX
32 : : #define strnicmp strncasecmp
33 : : #endif
34 : :
35 : :
36 : :
37 : : // NOT FULLY DEFINED SERVICES
38 : :
39 : :
40 : 2 : X2CParser::X2CParser( XmlElement & o_rDocumentData )
41 : : : // sFileName,
42 : : nFileLine(0),
43 : : pDocumentData(&o_rDocumentData),
44 : : // sWord,
45 : 2 : text(0)
46 : : {
47 : 2 : }
48 : :
49 : 2 : X2CParser::~X2CParser()
50 : : {
51 : 2 : }
52 : :
53 : :
54 : : bool
55 : 2 : X2CParser::LoadFile( const char * i_sFilename )
56 : : {
57 [ + - ]: 2 : sFileName = i_sFilename;
58 : 2 : nFileLine = 1;
59 : :
60 : : // Load file:
61 [ - + ]: 2 : if ( ! LoadXmlFile( aFile, i_sFilename ) )
62 : 0 : return false;
63 : :
64 : : // Test correct end:
65 : 2 : const char * pLastTag = strrchr(aFile.operator const char *(),'<');
66 [ - + ]: 2 : if (pLastTag == 0)
67 : 0 : return false;
68 [ + - ][ - + ]: 2 : if ( strnicmp(pLastTag+2, pDocumentData->Name().str(), pDocumentData->Name().l()) != 0
[ - + ]
69 : 2 : || strnicmp(pLastTag, "</", 2) != 0 )
70 : 0 : return false;
71 [ - + ]: 2 : if (strchr(pLastTag,'>') == 0)
72 : 0 : return false;
73 : 2 : return true;
74 : : }
75 : :
76 : : void
77 : 2 : X2CParser::Parse()
78 : : {
79 : : // Parse:
80 : 2 : text = aFile.operator const char *();
81 : :
82 : 2 : Parse_XmlDeclaration();
83 : 2 : Parse_Doctype();
84 : :
85 : : // skip XML comment
86 : 2 : Goto('<');
87 [ + - ]: 2 : if ( IsText("<!--") )
88 : 2 : Goto_And_Pass('>');
89 : :
90 : 2 : pDocumentData->Parse(*this);
91 : 2 : }
92 : :
93 : : bool
94 : 0 : X2CParser::Parse( const char * i_sFilename )
95 : : {
96 : 0 : bool ret = LoadFile(i_sFilename);
97 [ # # ]: 0 : if (ret)
98 : 0 : Parse();
99 : 0 : return ret;
100 : : }
101 : :
102 : : void
103 : 2 : X2CParser::Parse_XmlDeclaration()
104 : : {
105 : 2 : Goto('<');
106 [ + - ]: 2 : if ( IsText("<?xml") )
107 : : {
108 : 2 : Goto_And_Pass('>');
109 : : }
110 : 2 : }
111 : :
112 : : void
113 : 2 : X2CParser::Parse_Doctype()
114 : : {
115 : 2 : Goto('<');
116 [ + - ]: 2 : if ( IsText("<!DOCTYPE") )
117 : 2 : Goto_And_Pass('>');
118 : 2 : }
119 : :
120 : : void
121 : 20 : X2CParser::Parse_Sequence( DynamicList<XmlElement> & o_rElements,
122 : : const Simstr & i_sElementName )
123 : : {
124 : 20 : CheckAndPassBeginTag(i_sElementName.str());
125 : :
126 : 20 : unsigned int i_max = o_rElements.size();
127 [ + + ]: 170 : for (unsigned i = 0; i < i_max; ++i)
128 : : {
129 : 150 : o_rElements[i]->Parse(*this);
130 : : } // end for
131 : :
132 : 20 : CheckAndPassEndTag(i_sElementName.str());
133 : 20 : }
134 : :
135 : : void
136 : 20 : X2CParser::Parse_FreeChoice( DynamicList<XmlElement> & o_rElements )
137 : : {
138 : 20 : unsigned nSize = o_rElements.size();
139 : :
140 [ + + ]: 74 : for ( bool bBreak = false; !bBreak; )
141 : : {
142 : 54 : bBreak = true;
143 [ + + ]: 178 : for ( unsigned i = 0; i < nSize; ++i )
144 : : {
145 : 158 : Goto('<');
146 [ + + ]: 158 : if ( IsBeginTag(o_rElements[i]->Name().str()) )
147 : : {
148 : 34 : o_rElements[i]->Parse(*this);
149 : 34 : bBreak = false;
150 : 34 : break;
151 : : }
152 : : } // end for i
153 : : } // end for !bBreak
154 : 20 : }
155 : :
156 : : void
157 : 2 : X2CParser::Parse_List( ListElement & o_rListElem )
158 : : {
159 : :
160 [ + + ]: 20 : for ( Goto('<'); IsBeginTag(o_rListElem.Name().str()); Goto('<') )
161 : : {
162 : 18 : XmlElement * pNew = o_rListElem.Create_and_Add_NewElement();
163 : 18 : pNew->Parse(*this);
164 : : }
165 : 2 : }
166 : :
167 : : void
168 : 562 : X2CParser::Parse_Text( Simstr & o_sText,
169 : : const Simstr & i_sElementName,
170 : : bool i_bReverseName )
171 : : {
172 : :
173 [ - + ]: 562 : if ( ! CheckAndPassBeginTag(i_sElementName.str()) )
174 : 562 : return;
175 : :
176 : : // Add new Element
177 : 562 : GetTextTill( o_sText, '<', i_bReverseName );
178 : 562 : o_sText.remove_trailing_blanks();
179 : :
180 : 562 : CheckAndPassEndTag(i_sElementName.str());
181 : : }
182 : :
183 : : void
184 : 50 : X2CParser::Parse_MultipleText( List<Simstr> & o_rTexts,
185 : : const Simstr & i_sElementName,
186 : : bool i_bReverseName )
187 : : {
188 [ + + ]: 520 : for ( Goto('<'); IsBeginTag(i_sElementName.str()); Goto('<') )
189 : : {
190 [ + - ]: 470 : Simstr sNew;
191 [ + - ]: 470 : Parse_Text(sNew, i_sElementName, i_bReverseName);
192 [ + - ]: 470 : if (sNew.l() > 0)
193 [ + - ]: 470 : o_rTexts.push_back(sNew);
194 [ + - ]: 470 : }
195 : 50 : }
196 : :
197 : : void
198 : 18 : X2CParser::Parse_SglAttr( Simstr & o_sAttrValue,
199 : : const Simstr & i_sElementName,
200 : : const Simstr & i_sAttrName )
201 : : {
202 [ + - ]: 18 : Goto('<');
203 [ - + ]: 18 : if ( !IsBeginTag(i_sElementName.str()) )
204 [ # # ]: 0 : SyntaxError("unexpected element");
205 : 18 : Move( i_sElementName.l() + 1 );
206 : :
207 [ + - ]: 18 : Pass_White();
208 [ - + ]: 18 : if (*text == '>')
209 [ # # ]: 0 : SyntaxError("no attribute found where one was expected");
210 [ + - ]: 18 : Simstr sAttrName;
211 [ + - ]: 18 : Get_Attribute(o_sAttrValue, sAttrName);
212 [ + - ][ - + ]: 18 : if (sAttrName != i_sAttrName)
213 [ # # ]: 0 : SyntaxError("unknown attribute found");
214 [ + - ]: 18 : Pass_White();
215 [ - + ]: 18 : if (strncmp(text,"/>",2) != 0)
216 [ # # ]: 0 : SyntaxError("missing \"/>\" at end of empty element");
217 [ + - ]: 18 : Move(2);
218 : 18 : }
219 : :
220 : : void
221 : 2 : X2CParser::Parse_MultipleAttr( List<Simstr> & o_rAttrValues,
222 : : const Simstr & i_sElementName,
223 : : const List<Simstr> & i_rAttrNames )
224 : : {
225 [ + - ]: 2 : Goto('<');
226 [ - + ]: 2 : if ( !IsBeginTag(i_sElementName.str()) )
227 [ # # ]: 0 : SyntaxError("unexpected element");
228 : 2 : Move( i_sElementName.l() + 1 );
229 [ + - ]: 2 : Simstr sAttrName;
230 [ + - ]: 2 : Simstr sAttrValue;
231 : 2 : unsigned nSize = i_rAttrNames.size();
232 : : unsigned i;
233 : :
234 [ + - ][ + + ]: 6 : for ( Pass_White(); *text != '/'; Pass_White() )
[ + - ]
235 : : {
236 : :
237 [ + - ]: 4 : Get_Attribute(sAttrValue, sAttrName);
238 : :
239 [ + - ]: 12 : for ( i = 0; i < nSize; ++i )
240 : : {
241 [ + - ][ + - ]: 12 : if ( i_rAttrNames[i] == sAttrName )
[ + + ]
242 : : {
243 [ + - ][ + - ]: 4 : o_rAttrValues[i] = sAttrValue;
244 : 4 : break;
245 : : }
246 : : }
247 [ - + ]: 4 : if (i == nSize)
248 [ # # ]: 0 : SyntaxError("unknown attribute found");
249 : : }
250 [ + - ][ + - ]: 2 : Move(2);
251 : 2 : }
252 : :
253 : :
254 : : void
255 : 22 : X2CParser::Get_Attribute( Simstr & o_rAttrValue,
256 : : Simstr & o_rAttrName )
257 : : {
258 : 22 : GetTextTill( o_rAttrName, '=');
259 : :
260 [ - + ]: 22 : while (*(++text) != '"')
261 : : {
262 [ # # ]: 0 : if (*text == '\0')
263 : 0 : SyntaxError("unexpected end of file");
264 : : }
265 : :
266 : 22 : ++text;
267 : 22 : GetTextTill( o_rAttrValue, '"');
268 : 22 : ++text;
269 : 22 : }
270 : :
271 : : bool
272 : 6 : X2CParser::IsText( const char * i_sComparedText )
273 : : {
274 : 6 : return strnicmp( text, i_sComparedText, strlen(i_sComparedText) ) == 0;
275 : : }
276 : :
277 : : bool
278 : 1300 : X2CParser::IsBeginTag( const char * i_sTagName )
279 : : {
280 : 1300 : return strnicmp( text+1, i_sTagName, strlen(i_sTagName) ) == 0
281 [ + + ][ + - ]: 1300 : && *text == '<';
282 : : }
283 : :
284 : : bool
285 : 582 : X2CParser::IsEndTag( const char * i_sTagName )
286 : : {
287 : 582 : return strnicmp( text+2, i_sTagName, strlen(i_sTagName) ) == 0
288 [ + - ][ + - ]: 582 : && strnicmp( text, "</", 2 ) == 0;
289 : : }
290 : :
291 : : void
292 : 2476 : X2CParser::Goto( char i_cNext )
293 : : {
294 [ + + ]: 19550 : while (*text != i_cNext)
295 : : {
296 : 17074 : TestCurChar();
297 : 17074 : ++text;
298 : : }
299 : 2476 : }
300 : :
301 : : void
302 : 1170 : X2CParser::Goto_And_Pass( char i_cNext )
303 : : {
304 : 1170 : Goto(i_cNext);
305 : 1170 : ++text;
306 : 1170 : }
307 : :
308 : : void
309 : 40 : X2CParser::Move( int i_nForward )
310 : : {
311 : 40 : text += i_nForward;
312 : 40 : }
313 : :
314 : : void
315 : 1206 : X2CParser::Pass_White()
316 : : {
317 [ + + ]: 2318 : while (*text <= 32)
318 : : {
319 : 1112 : TestCurChar();
320 : 1112 : ++text;
321 : : }
322 : 1206 : }
323 : :
324 : : void
325 : 606 : X2CParser::GetTextTill( Simstr & o_rText,
326 : : char i_cEnd,
327 : : bool i_bReverseName )
328 : : {
329 : 606 : char * pResult = &sWord[0];
330 : : char * pSet;
331 : :
332 [ + + ]: 29466 : for ( pSet = pResult;
333 : : *text != i_cEnd;
334 : : ++text )
335 : : {
336 : 28860 : TestCurChar();
337 : 28860 : *pSet++ = *text;
338 : : }
339 : :
340 [ - + ][ # # ]: 606 : while ( *pResult < 33 && *pResult > 0 )
[ - + ]
341 : 0 : ++pResult;
342 [ + - ][ + + ]: 6604 : while ( pSet > pResult ? *(pSet-1) < 33 : false )
[ + + ]
343 : 5998 : pSet--;
344 : 606 : *pSet = '\0';
345 : :
346 : :
347 [ + + ]: 606 : if (i_bReverseName)
348 : : {
349 : 476 : const unsigned int nMaxLen = 1000;
350 [ + - ]: 476 : if (strlen(pResult) < nMaxLen)
351 : : {
352 : 476 : char * sBreak = strrchr(pResult,'.');
353 [ + + ]: 476 : if (sBreak != 0)
354 : : {
355 : : static char sScope[nMaxLen+10];
356 : : static char sName[nMaxLen+10];
357 : :
358 : 474 : unsigned nScopeLen = sBreak - pResult;
359 : 474 : strncpy ( sScope, pResult, nScopeLen ); // STRNCPY SAFE HERE
360 : 474 : sScope[nScopeLen] = '\0';
361 : 474 : strcpy( sName, sBreak + 1 ); // STRCPY SAFE HERE
362 : 474 : strcat( sName, " in " ); // STRCAT SAFE HERE
363 : 474 : strcat( sName, sScope ); // STRCAT SAFE HERE
364 : :
365 [ + - ]: 474 : o_rText = sName;
366 : 606 : return;
367 : : }
368 : : }
369 : : } // endif (i_bReverseName)
370 : :
371 [ + - ]: 132 : o_rText = &sWord[0];
372 : : }
373 : :
374 : : bool
375 : 582 : X2CParser::CheckAndPassBeginTag( const char * i_sElementName )
376 : : {
377 : 582 : bool ret = true;
378 : 582 : Goto('<');
379 [ - + ]: 582 : if ( ! IsBeginTag(i_sElementName) )
380 : 0 : SyntaxError( "unexpected element");
381 [ - + ]: 582 : if (IsAbsoluteEmpty())
382 : 0 : ret = false;
383 : 582 : Goto_And_Pass('>');
384 [ + - ]: 582 : if (ret)
385 : 582 : Pass_White();
386 : 582 : return ret;
387 : : }
388 : :
389 : : void
390 : 582 : X2CParser::CheckAndPassEndTag( const char * i_sElementName )
391 : : {
392 : 582 : Pass_White();
393 [ - + ]: 582 : if ( !IsEndTag(i_sElementName) )
394 : 0 : SyntaxError("missing or not matching end tag");
395 : 582 : Goto_And_Pass('>');
396 : 582 : }
397 : :
398 : : bool
399 : 582 : X2CParser::IsAbsoluteEmpty() const
400 : : {
401 : 582 : const char * pEnd = strchr(text+1, '>');
402 [ + - ]: 582 : if (pEnd != 0)
403 : : {
404 [ - + ]: 582 : if ( *(pEnd-1) == '/' )
405 : : {
406 : 0 : const char * pAttr = strchr(text+1, '"');
407 [ # # ]: 0 : if (pAttr == 0)
408 : 0 : return true;
409 [ # # ]: 0 : else if ( (pAttr-text) > (pEnd-text) )
410 : 0 : return true;
411 : : }
412 : : }
413 : 582 : return false;
414 : : }
415 : :
416 : : void
417 : 0 : X2CParser::SyntaxError( const char * i_sText )
418 : : {
419 : : std::cerr
420 : 0 : << "Syntax error "
421 : 0 : << i_sText
422 : 0 : << " in file: "
423 : 0 : << sFileName.str()
424 : 0 : << " in line "
425 : 0 : << nFileLine
426 : 0 : << "."
427 : 0 : << std::endl;
428 : :
429 : 0 : exit(3);
430 : : }
431 : :
432 : : void
433 : 47046 : X2CParser::TestCurChar()
434 : : {
435 [ + + ]: 47046 : if (*text == '\n')
436 : 748 : nFileLine++;
437 [ + - ][ + - ]: 47052 : }
438 : :
439 : :
440 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|