2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* Copyright (c) 1995 FUJITSU LIMITED */
24 /* All Rights Reserved */
26 /* $TOG: DocParser.C /main/16 1998/04/17 11:48:07 mgreess $ */
31 #include "StyleSheetExceptions.h"
32 #include "DocParser.h"
35 #include "AttributeList.h"
37 #define DATA_BUF_SIZ 4096
39 #if defined(SC3) || defined(__osf__)
40 static ostrstream& terminate(ostrstream& ost)
42 char* pstring = ost.str();
43 *(pstring + ost.pcount()) = '\0';
49 DocParser::DocParser(Resolver &r)
50 : f_resolver(r), f_ignoring_element(0),
51 #if defined(SC3) || defined(__osf__)
52 f_buffer(new char[DATA_BUF_SIZ]),
53 f_output(f_buffer, DATA_BUF_SIZ)
55 f_streambuf(new stringbuf()),
61 DocParser::~DocParser()
63 #if defined(SC3) || defined(__osf__)
64 if (f_buffer) delete[] f_buffer;
66 // this causes a free memory read when f_output is deleted as part of this
67 // object...nothing we can do about it
73 DocParser::parse(istream &input)
76 unsigned int ok = rawParse(input);
82 DocParser::rawParse(istream &input)
86 input.unsetf(ios::skipws);
88 f_ignoring_element = 0 ;
90 switch(read_tag(input, f_output))
94 #if defined(SC3) || defined(__osf__)
95 Symbol name(gElemSymTab->intern(terminate(f_output).str()));
96 f_output.rdbuf()->freeze(0);
98 data = f_output.str().c_str();
101 MESSAGE(cerr, "StartTag case:");
102 debug(cerr, f_output.str().size());
103 debug(cerr, data.c_str());
106 Symbol name(gElemSymTab->intern(data.c_str()));
108 process(input, f_output, name, 1, 1);
112 case AttributeSection:
114 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
117 throw(CASTDPUDEXCEPT docParserUnexpectedData());
125 update_last_seen_child_name(Symbol*& last_seen_child_name, unsigned int& child_relative_sibling_number, const Symbol& new_child_name)
127 if ( last_seen_child_name == 0 ||
128 !(*last_seen_child_name == Symbol(new_child_name))
131 delete last_seen_child_name ;
132 last_seen_child_name = new Symbol(new_child_name);
133 child_relative_sibling_number= 1;
135 child_relative_sibling_number++;
141 DocParser::process(istream &input, ostringstream &output,
143 unsigned int sibling_number, unsigned int this_sibling_number)
145 ON_DEBUG(cerr << "process(" << name << ") -> " << sibling_number << endl);
147 Symbol* last_seen_child_name = 0;
149 unsigned int child_relative_sibling_number = 0;
151 unsigned int child = 1 ; // sibling numbers for child elements
153 #if !defined(SC3) && !defined(__osf__)
159 while ((input >> c) && (c == '\n'));
163 throw(CASTDPUEEXCEPT docParserUnexpectedEof());
169 // process whatever comes right after start tag
170 TagType tt = read_tag(input, output);
175 ON_DEBUG(cerr << "beginElement" << endl);
176 // have to begin this element before processing child elements
177 if (!f_ignoring_element)
179 ignore = f_resolver.beginElement(new Element(name,
182 this_sibling_number));
183 f_ignoring_element = ignore ;
187 /////////////////////////////
188 // first child of this node
189 /////////////////////////////
190 #if defined(SC3) || defined(__osf__)
191 Symbol name(gElemSymTab->intern(terminate(f_output).str()));
193 update_last_seen_child_name(last_seen_child_name,
194 child_relative_sibling_number, name);
196 f_output.rdbuf()->freeze(0);
198 process(input, output, name, child++, child_relative_sibling_number);
200 data = f_output.str().c_str();
201 //#if !defined(SC3) && !defined(__osf__)
202 // data[f_output.str().size()] = '\0';
204 Symbol name(gElemSymTab->intern(data.c_str()));
205 update_last_seen_child_name(last_seen_child_name,
206 child_relative_sibling_number, name);
208 process(input, output, name,
209 child++, child_relative_sibling_number);
214 // hit an end tag right after start tag
217 #if defined(SC3) || defined(__osf__)
218 data = terminate(f_output).str();
219 f_output.rdbuf()->freeze(0);
221 data = f_output.str().c_str();
223 //#if !defined(SC3) && !defined(__osf__)
224 // data[f_output.str().size()] = '\0';
227 cerr << "EndTag: " << data.c_str() << endl;
228 assert(gElemSymTab->intern(data.c_str()) == name);
233 if (!f_ignoring_element)
235 int ignore = f_resolver.beginElement(new Element(name,
237 0, 0, this_sibling_number));
239 f_resolver.endElement(name);
241 return ; // EXIT FUNCTION
243 case AttributeSection:
245 #if !defined(SC3) && \
246 !defined(__osf__) && \
247 !defined(_IBMR2) && \
249 !defined(CSRG_BASED) && \
253 AttributeList *attrs = 0;
254 #if !defined(SC3) && \
255 !defined(__osf__) && \
256 !defined(_IBMR2) && \
258 !defined(CSRG_BASED) && \
262 AttributeList *olias_attrs = 0;
266 process_attributes(input, output, attrs, olias_attrs);
268 if (!f_ignoring_element)
270 //////////////////////////////
271 // this node with attributes
272 //////////////////////////////
273 ignore = f_resolver.beginElement(new Element(name,
279 f_ignoring_element = ignore ;
295 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
300 if (!f_ignoring_element)
303 ignore = f_resolver.beginElement(new Element(name,
305 0, 0, this_sibling_number));
306 f_ignoring_element = ignore ;
309 read_data(input, output);
311 if (!f_ignoring_element)
313 // the str() call seems to add the null byte to the stream
314 // and increment the pcount, so we must make sure it gets
316 #if defined(SC3) || defined(__osf__)
317 char *pstring = terminate(f_output).str();
318 int size = f_output.pcount();
319 f_resolver.data(pstring, size);
320 f_output.rdbuf()->freeze(0);
322 pstring = f_output.str().c_str();
323 int size = pstring.size() + 1;
324 f_resolver.data(pstring.c_str(), size);
331 while ((tt = read_tag(input, output)) != EndTag)
336 /////////////////////////////
337 // second child and beyond.
338 /////////////////////////////
339 data = f_output.str().c_str();
340 #if defined(SC3) || defined(__osf__)
341 f_output.rdbuf()->freeze(0);
345 MESSAGE(cerr, "StartTag case2");
347 debug(cerr, f_output.str().size());
350 Symbol name(gElemSymTab->intern(data.c_str()));
351 update_last_seen_child_name(last_seen_child_name,
352 child_relative_sibling_number, name);
354 process(input, output, name, child++, child_relative_sibling_number);
357 case EndTag: // should never get this
359 // we have already processed these for this tag
360 case AttributeSection:
362 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
366 read_data(input, output);
368 if (!f_ignoring_element)
370 // the str() call seems to add the null byte to the stream
371 // and increment the pcount, so we must make sure it gets
373 #if defined(SC3) || defined(__osf__)
374 char *pstring = f_output.str();
375 int size = f_output.pcount();
376 *(pstring + size) = 0;
377 f_resolver.data(pstring, size);
378 f_output.rdbuf()->freeze(0);
380 pstring = f_output.str().c_str();
381 int size = pstring.size() + 1;
382 f_resolver.data(pstring.c_str(), size);
389 #if defined(SC3) || defined(__osf__)
390 data = terminate(f_output).str();
391 f_output.rdbuf()->freeze(0);
393 data = f_output.str().c_str();
395 cerr << "EndTag: " << data.c_str() << endl;
396 assert(gElemSymTab->intern(data.c_str()) == name);
399 // hit end tag, end processing
400 if (!f_ignoring_element)
401 f_resolver.endElement(name);
403 // if we set ignore flag, unset it
405 f_ignoring_element = 0;
412 ON_DEBUG(cerr << "exit process: " << name << endl);
413 delete last_seen_child_name;
418 DocParser::process_attributes(istream &input, ostringstream &output,
419 AttributeList *&attrs,
420 AttributeList *&olias_attrs)
422 #if !defined(SC3) && !defined(__osf__)
427 Attribute* newAttribute = 0;
429 AttributeList* orig_attrs = attrs;
430 AttributeList* orig_olias_attrs = olias_attrs;
433 while ((tt = read_tag(input,output)) != NoTag)
439 #if !defined(SC3) && !defined(__osf__)
440 theData = f_output.str().c_str();
443 attrs = new AttributeList ;
446 process_attribute(input, output,
447 #if defined(SC3) || defined(__osf__)
448 gSymTab->intern(terminate(f_output).str()),
449 gSymTab->intern(f_streambuf->str()),
451 gSymTab->intern(theData.c_str()),
455 attrs->add(newAttribute);
459 return ; // EXIT FUNCTION
461 case AttributeSection:
462 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
465 #if !defined(SC3) && !defined(__osf__)
466 theData = f_output.str().c_str();
470 olias_attrs = new AttributeList ;
473 process_attribute(input, output,
474 #if defined(SC3) || defined(__osf__)
475 gSymTab->intern(terminate(f_output).str()),
476 gSymTab->intern(f_streambuf->str()),
478 gSymTab->intern(theData.c_str()),
483 olias_attrs->add(newAttribute);
486 throw(CASTDPUDEXCEPT docParserUnexpectedData());
495 if ( orig_attrs == 0 ) {
500 if ( orig_olias_attrs == 0 ) {
511 DocParser::process_attribute(istream &input, ostringstream &output,
512 const Symbol &name, TagType tt)
516 //ON_DEBUG(cerr << "process_attribute: " << name << endl);
518 // If the attribute is OLIAS internal, we use DocParser's
519 // read_data(). This is to prevent the attribte value
520 // from change in a call to specific renderer engine's
523 // Example: LoutDocparser::read_data() quotes any '.' char
524 // which changes the graphic locator value if the element
525 // is OLIAS internal attribute #GRAPHIC.
527 if ( tt == OliasAttribute ) {
528 DocParser::read_data(input, output);
530 (void)read_data(input, output);
531 #if defined(SC3) || defined(__osf__)
532 char *data = f_output.str();
533 *(data + f_output.pcount()) = 0;
534 f_output.rdbuf()->freeze(0);
535 Attribute *attr = new Attribute(name, strdup(data));
537 data = f_output.str().c_str();
538 Attribute *attr = new Attribute(name, strdup(data.c_str()));
541 switch (read_tag(input, output))
544 case AttributeSection:
547 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
551 throw(CASTDPUDEXCEPT docParserUnexpectedData());
563 DocParser::read_tag(istream &input, ostringstream &output)
565 output.seekp(streampos(0));
567 TagType tt = StartTag;
571 // strip newlines before/after tags
572 while ((input >> c) && (c == '\n'));
574 throw(CASTDPUEEXCEPT docParserUnexpectedEof());
593 return AttributeSection ; // EXIT
596 tt = OliasAttribute ;
597 output << c; // keep char we just read
601 throw(CASTUTEXCEPT unknownTagException());
605 output << c ; // keep char we just read
610 // get (remainder of) tag name
611 while ((input >> c) && (c != '>'))
620 DocParser::read_data(istream &input, ostringstream &output)
624 output.seekp(streampos(0));
626 while ((input >> c) && (c != '<'))
632 unsigned int tmplen = 0;
633 while ((input >> c ) && (c != ';'))
635 tmpbuf[tmplen++] = c ;
638 cerr << "Temp Buf overflow (ampersand problem)" << endl;
639 throw(CASTEXCEPT Exception());
643 throw(CASTDPUEEXCEPT docParserUnexpectedEof());
648 cerr << "Entity: " << tmpbuf << endl;
651 if ((!strcmp(tmpbuf, "hardreturn")) ||
652 (!strcmp(tmpbuf, "lnfeed")))
655 if ((!strcmp(tmpbuf, "lang")) ||
656 (!strcmp(tmpbuf, "lt")))
659 if (!strcmp(tmpbuf, "amp"))
662 if (!strcmp(tmpbuf, "nbsp")) // non-break space
674 // can never run out of input while reading data, tags must be balanced
676 throw(CASTDPUEEXCEPT docParserUnexpectedEof());