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) && \
248 !defined(__uxp__) && \
251 !defined(CSRG_BASED) && \
255 AttributeList *attrs = 0;
256 #if !defined(SC3) && \
257 !defined(__osf__) && \
258 !defined(_IBMR2) && \
259 !defined(__uxp__) && \
262 !defined(CSRG_BASED) && \
266 AttributeList *olias_attrs = 0;
270 process_attributes(input, output, attrs, olias_attrs);
272 if (!f_ignoring_element)
274 //////////////////////////////
275 // this node with attributes
276 //////////////////////////////
277 ignore = f_resolver.beginElement(new Element(name,
283 f_ignoring_element = ignore ;
299 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
304 if (!f_ignoring_element)
307 ignore = f_resolver.beginElement(new Element(name,
309 0, 0, this_sibling_number));
310 f_ignoring_element = ignore ;
313 read_data(input, output);
315 if (!f_ignoring_element)
317 // the str() call seems to add the null byte to the stream
318 // and increment the pcount, so we must make sure it gets
320 #if defined(SC3) || defined(__osf__)
321 char *pstring = terminate(f_output).str();
322 int size = f_output.pcount();
323 f_resolver.data(pstring, size);
324 f_output.rdbuf()->freeze(0);
326 pstring = f_output.str().c_str();
327 int size = pstring.size() + 1;
328 f_resolver.data(pstring.c_str(), size);
335 while ((tt = read_tag(input, output)) != EndTag)
340 /////////////////////////////
341 // second child and beyond.
342 /////////////////////////////
343 data = f_output.str().c_str();
344 #if defined(SC3) || defined(__osf__)
345 f_output.rdbuf()->freeze(0);
349 MESSAGE(cerr, "StartTag case2");
351 debug(cerr, f_output.str().size());
354 Symbol name(gElemSymTab->intern(data.c_str()));
355 update_last_seen_child_name(last_seen_child_name,
356 child_relative_sibling_number, name);
358 process(input, output, name, child++, child_relative_sibling_number);
361 case EndTag: // should never get this
363 // we have already processed these for this tag
364 case AttributeSection:
366 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
370 read_data(input, output);
372 if (!f_ignoring_element)
374 // the str() call seems to add the null byte to the stream
375 // and increment the pcount, so we must make sure it gets
377 #if defined(SC3) || defined(__osf__)
378 char *pstring = f_output.str();
379 int size = f_output.pcount();
380 *(pstring + size) = 0;
381 f_resolver.data(pstring, size);
382 f_output.rdbuf()->freeze(0);
384 pstring = f_output.str().c_str();
385 int size = pstring.size() + 1;
386 f_resolver.data(pstring.c_str(), size);
393 #if defined(SC3) || defined(__osf__)
394 data = terminate(f_output).str();
395 f_output.rdbuf()->freeze(0);
397 data = f_output.str().c_str();
399 cerr << "EndTag: " << data.c_str() << endl;
400 assert(gElemSymTab->intern(data.c_str()) == name);
403 // hit end tag, end processing
404 if (!f_ignoring_element)
405 f_resolver.endElement(name);
407 // if we set ignore flag, unset it
409 f_ignoring_element = 0;
416 ON_DEBUG(cerr << "exit process: " << name << endl);
417 delete last_seen_child_name;
422 DocParser::process_attributes(istream &input, ostringstream &output,
423 AttributeList *&attrs,
424 AttributeList *&olias_attrs)
426 #if !defined(SC3) && !defined(__osf__)
431 Attribute* newAttribute = 0;
433 AttributeList* orig_attrs = attrs;
434 AttributeList* orig_olias_attrs = olias_attrs;
437 while ((tt = read_tag(input,output)) != NoTag)
443 #if !defined(SC3) && !defined(__osf__)
444 theData = f_output.str().c_str();
447 attrs = new AttributeList ;
450 process_attribute(input, output,
451 #if defined(SC3) || defined(__osf__)
452 gSymTab->intern(terminate(f_output).str()),
453 gSymTab->intern(f_streambuf->str()),
455 gSymTab->intern(theData.c_str()),
459 attrs->add(newAttribute);
463 return ; // EXIT FUNCTION
465 case AttributeSection:
466 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
469 #if !defined(SC3) && !defined(__osf__)
470 theData = f_output.str().c_str();
474 olias_attrs = new AttributeList ;
477 process_attribute(input, output,
478 #if defined(SC3) || defined(__osf__)
479 gSymTab->intern(terminate(f_output).str()),
480 gSymTab->intern(f_streambuf->str()),
482 gSymTab->intern(theData.c_str()),
487 olias_attrs->add(newAttribute);
490 throw(CASTDPUDEXCEPT docParserUnexpectedData());
499 if ( orig_attrs == 0 ) {
504 if ( orig_olias_attrs == 0 ) {
515 DocParser::process_attribute(istream &input, ostringstream &output,
516 const Symbol &name, TagType tt)
520 //ON_DEBUG(cerr << "process_attribute: " << name << endl);
522 // If the attribute is OLIAS internal, we use DocParser's
523 // read_data(). This is to prevent the attribte value
524 // from change in a call to specific renderer engine's
527 // Example: LoutDocparser::read_data() quotes any '.' char
528 // which changes the graphic locator value if the element
529 // is OLIAS internal attribute #GRAPHIC.
531 if ( tt == OliasAttribute ) {
532 DocParser::read_data(input, output);
534 (void)read_data(input, output);
535 #if defined(SC3) || defined(__osf__)
536 char *data = f_output.str();
537 *(data + f_output.pcount()) = 0;
538 f_output.rdbuf()->freeze(0);
539 Attribute *attr = new Attribute(name, strdup(data));
541 data = f_output.str().c_str();
542 Attribute *attr = new Attribute(name, strdup(data.c_str()));
545 switch (read_tag(input, output))
548 case AttributeSection:
551 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
555 throw(CASTDPUDEXCEPT docParserUnexpectedData());
567 DocParser::read_tag(istream &input, ostringstream &output)
569 output.seekp(streampos(0));
571 TagType tt = StartTag;
575 // strip newlines before/after tags
576 while ((input >> c) && (c == '\n'));
578 throw(CASTDPUEEXCEPT docParserUnexpectedEof());
597 return AttributeSection ; // EXIT
600 tt = OliasAttribute ;
601 output << c; // keep char we just read
605 throw(CASTUTEXCEPT unknownTagException());
609 output << c ; // keep char we just read
614 // get (remainder of) tag name
615 while ((input >> c) && (c != '>'))
624 DocParser::read_data(istream &input, ostringstream &output)
628 output.seekp(streampos(0));
630 while ((input >> c) && (c != '<'))
636 unsigned int tmplen = 0;
637 while ((input >> c ) && (c != ';'))
639 tmpbuf[tmplen++] = c ;
642 cerr << "Temp Buf overflow (ampersand problem)" << endl;
643 throw(CASTEXCEPT Exception());
647 throw(CASTDPUEEXCEPT docParserUnexpectedEof());
652 cerr << "Entity: " << tmpbuf << endl;
655 if ((!strcmp(tmpbuf, "hardreturn")) ||
656 (!strcmp(tmpbuf, "lnfeed")))
659 if ((!strcmp(tmpbuf, "lang")) ||
660 (!strcmp(tmpbuf, "lt")))
663 if (!strcmp(tmpbuf, "amp"))
666 if (!strcmp(tmpbuf, "nbsp")) // non-break space
678 // can never run out of input while reading data, tags must be balanced
680 throw(CASTDPUEEXCEPT docParserUnexpectedEof());