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 librararies 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* string = ost.str();
43 *(string + ost.pcount()) = 0;
49 DocParser::DocParser(Resolver &r)
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 strstreambuf(DATA_BUF_SIZ)),
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)
84 input.unsetf(ios::skipws);
86 f_ignoring_element = 0 ;
88 switch(read_tag(input, f_output))
92 #if defined(SC3) || defined(__osf__)
93 Symbol name(gElemSymTab->intern(terminate(f_output).str()));
94 f_output.rdbuf()->freeze(0);
96 char *data = f_streambuf->str();
99 MESSAGE(cerr, "StartTag case:");
100 debug(cerr, f_streambuf->pcount());
104 #if !defined(SC3) && !defined(__osf__)
105 data[f_streambuf->pcount()] = 0;
107 f_streambuf->freeze(0);
108 Symbol name(gElemSymTab->intern(data));
110 process(input, f_output, name, 1, 1);
114 case AttributeSection:
116 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
119 throw(CASTDPUDEXCEPT docParserUnexpectedData());
127 update_last_seen_child_name(Symbol*& last_seen_child_name, unsigned int& child_relative_sibling_number, const Symbol& new_child_name)
129 if ( last_seen_child_name == 0 ||
130 !(*last_seen_child_name == Symbol(new_child_name))
133 delete last_seen_child_name ;
134 last_seen_child_name = new Symbol(new_child_name);
135 child_relative_sibling_number= 1;
137 child_relative_sibling_number++;
143 DocParser::process(istream &input, ostream &output,
145 unsigned int sibling_number, unsigned int this_sibling_number)
147 ON_DEBUG(cerr << "process(" << name << ") -> " << sibling_number << endl);
149 Symbol* last_seen_child_name = 0;
151 unsigned int child_relative_sibling_number = 0;
153 unsigned int child = 1 ; // sibling numbers for child elements
156 while ((input >> c) && (c == '\n'));
160 throw(CASTDPUEEXCEPT docParserUnexpectedEof());
166 // process whatever comes right after start tag
167 TagType tt = read_tag(input, output);
172 ON_DEBUG(cerr << "beginElement" << endl);
173 // have to begin this element before processing child elements
174 if (!f_ignoring_element)
176 ignore = f_resolver.beginElement(new Element(name,
179 this_sibling_number));
180 f_ignoring_element = ignore ;
184 /////////////////////////////
185 // first child of this node
186 /////////////////////////////
187 #if defined(SC3) || defined(__osf__)
188 Symbol name(gElemSymTab->intern(terminate(f_output).str()));
190 update_last_seen_child_name(last_seen_child_name,
191 child_relative_sibling_number, name);
193 f_output.rdbuf()->freeze(0);
195 process(input, output, name, child++, child_relative_sibling_number);
197 char *data = f_streambuf->str();
198 #if !defined(SC3) && !defined(__osf__)
199 data[f_streambuf->pcount()] = 0;
201 Symbol name(gElemSymTab->intern(data));
202 update_last_seen_child_name(last_seen_child_name,
203 child_relative_sibling_number, name);
205 f_streambuf->freeze(0);
206 process(input, output, name,
207 child++, child_relative_sibling_number);
212 // hit an end tag right after start tag
215 #if defined(SC3) || defined(__osf__)
216 char *data = terminate(f_output).str();
217 f_output.rdbuf()->freeze(0);
219 char *data = f_streambuf->str();
221 #if !defined(SC3) && !defined(__osf__)
222 data[f_streambuf->pcount()] = 0;
224 f_streambuf->freeze(0);
226 cerr << "EndTag: " << data << endl;
227 assert(gElemSymTab->intern(data) == name);
232 if (!f_ignoring_element)
234 int ignore = f_resolver.beginElement(new Element(name,
236 0, 0, this_sibling_number));
238 f_resolver.endElement(name);
240 return ; // EXIT FUNCTION
242 case AttributeSection:
244 #if !defined(SC3) && \
245 !defined(__osf__) && \
246 !defined(_IBMR2) && \
247 !defined(__uxp__) && \
252 AttributeList *attrs = 0;
253 #if !defined(SC3) && \
254 !defined(__osf__) && \
255 !defined(_IBMR2) && \
256 !defined(__uxp__) && \
261 AttributeList *olias_attrs = 0;
265 process_attributes(input, output, attrs, olias_attrs);
267 if (!f_ignoring_element)
269 //////////////////////////////
270 // this node with attributes
271 //////////////////////////////
272 ignore = f_resolver.beginElement(new Element(name,
278 f_ignoring_element = ignore ;
294 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
299 if (!f_ignoring_element)
302 ignore = f_resolver.beginElement(new Element(name,
304 0, 0, this_sibling_number));
305 f_ignoring_element = ignore ;
308 read_data(input, output);
310 if (!f_ignoring_element)
312 // the str() call seems to add the null byte to the stream
313 // and increment the pcount, so we must make sure it gets
315 #if defined(SC3) || defined(__osf__)
316 char *string = terminate(f_output).str();
317 int size = f_output.pcount();
318 f_resolver.data(string, size);
319 f_output.rdbuf()->freeze(0);
321 char *string = f_streambuf->str();
323 #if !defined(SC3) && !defined(__osf__)
324 string[f_streambuf->pcount()] = 0;
325 int size = f_streambuf->pcount() ;
327 int size = f_streambuf->pcount() - 1 ;
329 f_resolver.data(string, size);
330 f_streambuf->freeze(0); // unfreeze buffer frozen by str() call
337 while ((tt = read_tag(input, output)) != EndTag)
342 /////////////////////////////
343 // second child and beyond.
344 /////////////////////////////
345 #if defined(SC3) || defined(__osf__)
346 char *data = f_output.str();
347 *(data + f_output.pcount()) = 0;
348 f_output.rdbuf()->freeze(0);
350 char *data = f_streambuf->str();
352 #if !defined(SC3) && !defined(__osf__)
353 data[f_streambuf->pcount ()] = 0;
355 f_streambuf->freeze(0);
359 MESSAGE(cerr, "StartTag case2");
361 debug(cerr, f_streambuf->pcount ());
364 Symbol name(gElemSymTab->intern(data));
365 update_last_seen_child_name(last_seen_child_name,
366 child_relative_sibling_number, name);
368 process(input, output, name, child++, child_relative_sibling_number);
371 case EndTag: // should never get this
373 // we have already processed these for this tag
374 case AttributeSection:
376 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
380 read_data(input, output);
382 if (!f_ignoring_element)
384 // the str() call seems to add the null byte to the stream
385 // and increment the pcount, so we must make sure it gets
387 #if defined(SC3) || defined(__osf__)
388 char *string = f_output.str();
389 int size = f_output.pcount();
390 *(string + size) = 0;
391 f_resolver.data(string, size);
392 f_output.rdbuf()->freeze(0);
394 char *string = f_streambuf->str();
396 #if !defined(SC3) && !defined(__osf__)
397 string[f_streambuf->pcount()] = 0;
398 int size = f_streambuf->pcount() ;
400 int size = f_streambuf->pcount() - 1 ;
402 f_resolver.data(string, size);
403 f_streambuf->freeze(0); // unfreeze buffer frozen by str() call
410 #if defined(SC3) || defined(__osf__)
411 char *data = terminate(f_output).str();
412 f_output.rdbuf()->freeze(0);
414 char *data = f_streambuf->str();
416 #if !defined(SC3) && !defined(__osf__)
417 data[f_streambuf->pcount ()] = 0;
419 f_streambuf->freeze(0);
421 cerr << "EndTag: " << data << endl;
422 assert(gElemSymTab->intern(data) == name);
425 // hit end tag, end processing
426 if (!f_ignoring_element)
427 f_resolver.endElement(name);
429 // if we set ignore flag, unset it
431 f_ignoring_element = 0;
438 ON_DEBUG(cerr << "exit process: " << name << endl);
439 delete last_seen_child_name;
444 DocParser::process_attributes(istream &input, ostream &output,
445 AttributeList *&attrs,
446 AttributeList *&olias_attrs)
450 Attribute* newAttribute = 0;
452 AttributeList* orig_attrs = attrs;
453 AttributeList* orig_olias_attrs = olias_attrs;
458 while ((tt = read_tag(input,output)) != NoTag)
465 #if !defined(SC3) && !defined(__osf__)
466 theData = f_streambuf->str ();
467 theData[f_streambuf->pcount()] = 0;
470 attrs = new AttributeList ;
473 process_attribute(input, output,
474 #if defined(SC3) || defined(__osf__)
475 gSymTab->intern(terminate(f_output).str()),
478 #if !defined(SC3) && !defined(__osf__)
479 gSymTab->intern(theData),
481 gSymTab->intern(f_streambuf->str()),
486 attrs->add(newAttribute);
490 return ; // EXIT FUNCTION
492 case AttributeSection:
493 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
497 #if !defined(SC3) && !defined(__osf__)
498 theData = f_streambuf->str ();
499 theData[f_streambuf->pcount()] = 0;
503 olias_attrs = new AttributeList ;
506 process_attribute(input, output,
507 #if defined(SC3) || defined(__osf__)
508 gSymTab->intern(terminate(f_output).str()),
511 #if !defined(SC3) && !defined(__osf__)
512 gSymTab->intern(theData),
514 gSymTab->intern(f_streambuf->str()),
520 olias_attrs->add(newAttribute);
523 throw(CASTDPUDEXCEPT docParserUnexpectedData());
532 if ( orig_attrs == 0 ) {
537 if ( orig_olias_attrs == 0 ) {
548 DocParser::process_attribute(istream &input, ostream &output,
549 const Symbol &name, TagType tt)
551 //ON_DEBUG(cerr << "process_attribute: " << name << endl);
553 // If the attribute is OLIAS internal, we use DocParser's
554 // read_data(). This is to prevent the attribte value
555 // from change in a call to specific renderer engine's
558 // Example: LoutDocparser::read_data() quotes any '.' char
559 // which changes the graphic locator value if the element
560 // is OLIAS internal attribute #GRAPHIC.
562 if ( tt == OliasAttribute ) {
563 DocParser::read_data(input, output);
565 (void)read_data(input, output);
566 #if defined(SC3) || defined(__osf__)
567 char *data = f_output.str();
568 *(data + f_output.pcount()) = 0;
569 f_output.rdbuf()->freeze(0);
571 char *data = f_streambuf->str();
573 #if !defined(SC3) && !defined(__osf__)
574 data[f_streambuf->pcount ()] = 0;
576 f_streambuf->freeze(0);
578 Attribute *attr = new Attribute(name, strdup(data));
580 switch (read_tag(input, output))
583 case AttributeSection:
586 throw(CASTDPUTEXCEPT docParserUnexpectedTag());
590 throw(CASTDPUDEXCEPT docParserUnexpectedData());
602 DocParser::read_tag(istream &input, ostream &output)
604 output.seekp(streampos(0));
606 TagType tt = StartTag;
610 // strip newlines before/after tags
611 while ((input >> c) && (c == '\n'));
613 throw(CASTDPUEEXCEPT docParserUnexpectedEof());
632 return AttributeSection ; // EXIT
635 tt = OliasAttribute ;
636 output << c; // keep char we just read
640 throw(CASTUTEXCEPT unknownTagException());
644 output << c ; // keep char we just read
649 // get (remainder of) tag name
650 while ((input >> c) && (c != '>'))
658 DocParser::read_data(istream &input, ostream &output)
662 output.seekp(streampos(0));
664 while ((input >> c) && (c != '<'))
670 unsigned int tmplen = 0;
671 while ((input >> c ) && (c != ';'))
673 tmpbuf[tmplen++] = c ;
676 cerr << "Temp Buf overflow (ampersand problem)" << endl;
677 throw(CASTEXCEPT Exception());
681 throw(CASTDPUEEXCEPT docParserUnexpectedEof());
686 cerr << "Entity: " << tmpbuf << endl;
689 if ((!strcmp(tmpbuf, "hardreturn")) ||
690 (!strcmp(tmpbuf, "lnfeed")))
693 if ((!strcmp(tmpbuf, "lang")) ||
694 (!strcmp(tmpbuf, "lt")))
697 if (!strcmp(tmpbuf, "amp"))
700 if (!strcmp(tmpbuf, "nbsp")) // non-break space
710 // can never run out of input while reading data, tags must be balanced
712 throw(CASTDPUEEXCEPT docParserUnexpectedEof());