Skip to content

Commit e4ba45b

Browse files
committed
xml_parsert: construct with message handler
This both avoids an object of static lifetime as well as it fixes the (transitive) use of the deprecated messaget() constructor. Avoid global objects in the lexer (as side-effect making it reentrant) as initialisation is required. The parser continues to have global state, so guard against reentrant use.
1 parent fd28cb2 commit e4ba45b

File tree

4 files changed

+52
-24
lines changed

4 files changed

+52
-24
lines changed

src/xmllang/parser.y

+8-4
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33

44
#include "xml_parser.h"
55

6-
int yyxmllex();
7-
extern char *yyxmltext;
6+
int yyxmllex(void *);
7+
char *yyxmlget_text(void *);
88

9-
int yyxmlerror(const std::string &error)
9+
int yyxmlerror(xml_parsert &xml_parser, void *scanner, const std::string &error)
1010
{
11-
xml_parser.parse_error(error, yyxmltext);
11+
xml_parser.parse_error(error, yyxmlget_text(scanner));
1212
return 0;
1313
}
1414

@@ -26,6 +26,10 @@ int yyxmlerror(const std::string &error)
2626
#endif
2727
%}
2828

29+
%parse-param {xml_parsert &xml_parser}
30+
%parse-param {void *scanner}
31+
%lex-param {void *scanner}
32+
2933
%union {char *s;}
3034

3135
%token STARTXMLDECL

src/xmllang/scanner.l

+5-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
%option noinput
44
%option nounistd
55
%option never-interactive
6+
%option noyywrap
7+
%option reentrant
8+
%option extra-type="xml_parsert *"
69

710
%{
811

@@ -19,7 +22,7 @@
1922
#include "xml_parser.h"
2023
#include "xml_y.tab.h"
2124

22-
#define PARSER xml_parser
25+
#define PARSER (*yyextra)
2326

2427
//static int keep; /* To store start condition */
2528

@@ -87,9 +90,5 @@ string \"([^"&]|{esc})*\"|\'([^'&]|{esc})*\'
8790
<DTD>. {/* skip */}
8891
<DTD>\]{close} {BEGIN(INITIAL); /* skip */}
8992

90-
. { yyxmlerror("unexpected character"); }
93+
. { yyxmlerror(*yyextra, yyscanner, "unexpected character"); }
9194
{nl} {/* skip, must be an extra one at EOF */;}
92-
93-
%%
94-
95-
int yywrap() { return 1; }

src/xmllang/xml_parser.cpp

+17-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,20 @@ Author: Daniel Kroening, [email protected]
1010

1111
#include <fstream>
1212

13-
xml_parsert xml_parser;
13+
int xml_parsert::instance_count = 0;
14+
15+
int yyxmllex_init_extra(xml_parsert *, void **);
16+
int yyxmllex_destroy(void *);
17+
int yyxmlparse(xml_parsert &, void *);
18+
19+
bool xml_parsert::parse()
20+
{
21+
void *scanner;
22+
yyxmllex_init_extra(this, &scanner);
23+
bool parse_fail = yyxmlparse(*this, scanner) != 0;
24+
yyxmllex_destroy(scanner);
25+
return parse_fail;
26+
}
1427

1528
// 'do it all' function
1629
bool parse_xml(
@@ -19,12 +32,12 @@ bool parse_xml(
1932
message_handlert &message_handler,
2033
xmlt &dest)
2134
{
22-
xml_parser.clear();
35+
xml_parsert xml_parser{message_handler};
36+
2337
xml_parser.set_file(filename);
2438
xml_parser.in=&in;
25-
xml_parser.log.set_message_handler(message_handler);
2639

27-
bool result=yyxmlparse()!=0;
40+
bool result = xml_parser.parse();
2841

2942
// save result
3043
xml_parser.parse_tree.element.swap(dest);

src/xmllang/xml_parser.h

+22-10
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,25 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include "xml_parse_tree.h"
1616

17-
int yyxmlparse();
18-
1917
class xml_parsert:public parsert
2018
{
2119
public:
20+
explicit xml_parsert(message_handlert &message_handler)
21+
: parsert(message_handler)
22+
{
23+
// Simplistic check that we don't attempt to do reentrant parsing as the
24+
// Bison-generated parser has global state.
25+
PRECONDITION(++instance_count == 1);
26+
clear();
27+
}
28+
29+
xml_parsert(const xml_parsert &) = delete;
30+
31+
~xml_parsert() override
32+
{
33+
--instance_count;
34+
}
35+
2236
xml_parse_treet parse_tree;
2337

2438
std::list<xmlt *> stack;
@@ -28,29 +42,27 @@ class xml_parsert:public parsert
2842
return *stack.back();
2943
}
3044

31-
virtual bool parse()
32-
{
33-
return yyxmlparse()!=0;
34-
}
45+
bool parse() override;
3546

3647
void new_level()
3748
{
3849
current().elements.push_back(xmlt());
3950
stack.push_back(&current().elements.back());
4051
}
4152

42-
virtual void clear()
53+
void clear() override
4354
{
4455
parse_tree.clear();
4556
// set up stack
4657
stack.clear();
4758
stack.push_back(&parse_tree.element);
4859
}
49-
};
5060

51-
extern xml_parsert xml_parser;
61+
protected:
62+
static int instance_count;
63+
};
5264

53-
int yyxmlerror(const std::string &error);
65+
int yyxmlerror(xml_parsert &, void *, const std::string &);
5466

5567
// 'do it all' functions
5668
bool parse_xml(

0 commit comments

Comments
 (0)