ATLAS Offline Software
ExpatCoreParser.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include "ExpatCoreParser.h"
8 
9 #include <cstdio>
10 #include <cstdlib>
11 #include <cstring>
12 #include <expat.h>
13 
14 #include <string>
15 #include <vector>
16 #include <iostream>
17 #include <map>
18 
19 
20 
22 ExpatCoreParser::ExternalEntityMap ExpatCoreParser::s_entities;
23 ExpatCoreParser::ExternalEntityMap ExpatCoreParser::s_text_entities;
24 
26 public:
27  static bool get_debug_state() {
28  return ::getenv ("XMLDEBUG") != 0;
29  }
30  static bool debug () {
31  static const bool debug_state = get_debug_state();
32  return debug_state;
33  }
34 };
35 
36 
37 
38 #define BUFFSIZE 1000
39 
40 void
41 ExpatCoreParser::start (void* user_data, const char* el, const char** attr){
42  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
43  me.do_start (el, attr);
44 }
45 
46 void
47 ExpatCoreParser::end (void* user_data, const char* el){
48  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
49  me.do_end (el);
50 }
51 
52 void
53 ExpatCoreParser::char_data (void* user_data, const XML_Char* s, int len){
54  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
55  me.do_char_data (s, len);
56 }
57 
58 void
59 ExpatCoreParser::default_handler (void* user_data, const XML_Char* s, int len){
60  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
61  me.do_default_handler (s, len);
62 }
63 
64 void
65 ExpatCoreParser::comment (void* user_data, const XML_Char* s){
66  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
67  me.do_comment (s);
68 }
69 
70 int
72  const XML_Char* context,
73  const XML_Char* /*base*/,
74  const XML_Char* systemId,
75  const XML_Char* /*publicId*/){
76  void* user_data = XML_GetUserData (parser);
77  ExpatCoreParser& me = *reinterpret_cast<ExpatCoreParser*> (user_data);
78  return (me.do_external_entity (parser, context, systemId));
79 }
80 
81 void
82 ExpatCoreParser::register_external_entity (const std::string& name, const std::string& file_name) {
84  std::cout << "ExpatCoreParser::register_external_entity> name=" << name
85  << " file_name=" << file_name << std::endl;
86  }
87  lock_t lock (s_mutex);
88  s_entities[name] = file_name;
89 }
90 
91 void
92 ExpatCoreParser::register_text_entity (const std::string& name, const std::string& text) {
94  std::cout << "ExpatCoreParser::register_text_entity> name=" << name
95  << std::endl;
96  }
97  lock_t lock (s_mutex);
98  s_text_entities[name] = text;
99 }
100 
101 void
102 ExpatCoreParser::entity (void* /*userData*/,
103  const XML_Char* entityName,
104  int is_parameter_entity,
105  const XML_Char* value,
106  int value_length,
107  const XML_Char* base,
108  const XML_Char* systemId,
109  const XML_Char* publicId,
110  const XML_Char* /*notationName*/){
111  if (!base) base = "none";
112  if (!systemId) systemId = "none";
113  if (!publicId) publicId = "none";
114  std::string temp = "none";
115  if (value) {
116  char* t = (char*) malloc (value_length + 1);
117  strncpy (t, value, value_length);
118  t[value_length] = 0;
119  temp = (const char*) t;
120  free (t);
121  }
122 
124  std::cout << "ExpatCoreParser::entity[" << 0 << "]> " << entityName;
125  std::cout << " is_parameter=" << is_parameter_entity;
126  std::cout << " value=[" << temp << "]";
127  std::cout << " base=[" << base << "]";
128  std::cout << " systemId=[" << systemId << "]";
129  std::cout << " publicId=[" << publicId << "]";
130  std::cout << std::endl;
131  }
132 }
133 
134 std::unique_ptr<CoreParser::DOMNode>
136  return std::move(m_top);
137 }
138 
140  : m_top (nullptr),
141  m_last (nullptr),
142  m_prefix (prefix){
143 }
144 
145 void
146 ExpatCoreParser::do_start (const char* el, const char** attr){
147  int i;
148  std::map <std::string, std::string> a;
149  if (!m_top){
150  m_top = std::make_unique<CoreParser::DOMNode> ();
151  m_last = m_top.get();
152  }
155  std::cout << "ExpatCoreParser::do_start> el=" << el << " top=" << m_top.get() << " last=" << m_last << " node=" << node << std::endl;
156  }
157  m_last = node;
158  for (i = 0; attr[i]; i += 2) {
159  const char* name = attr[i];
160  const char* value = attr[i+1];
161  node->m_attributes[name] = value;
162  }
163 }
164 
165 void
168  std::cout << "ExpatCoreParser::do_end> el=" << el << std::endl;
169  }
171 }
172 
173 void
174 ExpatCoreParser::do_char_data (const XML_Char* s, int len){
175  if (len == 0) return;
176  while ((len > 0) && (s[len-1] == '\n')) len--;
177  if (len == 0) return;
178  char* temp = (char*) malloc (len + 1);
179  strncpy (temp, s, len);
180  temp[len] = 0;
182  std::cout << "ExpatCoreParser::do_char_data> [" << temp << "]" << std::endl;
183  }
184  free (temp);
185 }
186 
187 void
188 ExpatCoreParser::do_default_handler (const XML_Char* s, int len){
189  if (len == 0) return;
190  while ((len > 0) && (s[len-1] == '\n')) len--;
191  if (len == 0) return;
192  char* temp = (char*) malloc (len + 1);
193  strncpy (temp, s, len);
194  temp[len] = 0;
196  std::cout << "ExpatCoreParser::do_default_handler> [" << temp << "]" << std::endl;
197  }
198  free (temp);
199 }
200 
201 void
202 ExpatCoreParser::do_comment (const XML_Char* s){
203  if (!m_top) {
204  m_top = std::make_unique<CoreParser::DOMNode> ();
205  m_last = m_top.get();
206  }
209  std::cout << "ExpatCoreParser::do_comment> s=" << s << " top=" << m_top.get() << " last=" << m_last << " node=" << node << std::endl;
210  }
211  // Node is owned by m_last.
212  // cppcheck-suppress memleak
213  node = nullptr;
214 }
215 
216 int
217 ExpatCoreParser::generic_parse (XML_Parser p, const std::string& file_name){
218  FILE* docfd;
220  std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name << " prefix=" << m_prefix << std::endl;
221  }
222 
223  std::string temp_name = file_name;
224  docfd = fopen (temp_name.c_str (), "r");
225  if (!docfd){
226  temp_name = m_prefix + "/" + file_name;
227  docfd = fopen (temp_name.c_str (), "r");
228  }
229 
230  if (docfd == 0){
231  const char* xmlpathenv = ::getenv ("XMLPATH");
232  if (xmlpathenv == 0) return (0);
233  std::string xmlpath = xmlpathenv;
234  std::string::size_type pos = 0;
235  while (pos != std::string::npos){
236  std::string::size_type sep = xmlpath.find (":", pos);
237  if (sep == std::string::npos){
238  temp_name = xmlpath.substr (pos);
239  pos = std::string::npos;
240  } else {
241  temp_name = xmlpath.substr (pos, sep - pos);
242  pos = sep + 1;
243  }
244  if (temp_name.empty()) continue;
245  std::string last_temp_name = temp_name;
246  temp_name += "/";
247  temp_name += file_name;
249  std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name
250  << " xmlpath=" << xmlpath
251  << " temp_name=" << temp_name
252  << std::endl;
253  }
254 
255  docfd = fopen (temp_name.c_str (), "r");
256  if (docfd != 0) break;
257  // Test whether prefix is a relative path and if so use it
258  if (m_prefix != "" && '/' != m_prefix[0]) {
259  temp_name = last_temp_name;
260  temp_name += "/";
261  temp_name += m_prefix;
262  temp_name += "/";
263  temp_name += file_name;
265  std::cout << "ExpatCoreParser::generic_parse> file_name=" << file_name
266  << " xmlpath=" << xmlpath
267  << " temp_name=" << temp_name
268  << std::endl;
269  }
270  docfd = fopen (temp_name.c_str (), "r");
271  if (docfd != 0) break;
272  }
273  }
274  }
275 
276  if (docfd == 0){
277  return (0);
278  }
279  int result = 1;
280  XML_SetParamEntityParsing (p, XML_PARAM_ENTITY_PARSING_ALWAYS);
281  XML_SetElementHandler (p, start, end);
282  XML_SetCharacterDataHandler (p, char_data);
283  XML_SetExternalEntityRefHandler (p, external_entity);
284  XML_SetCommentHandler (p, comment);
285  XML_SetUserData (p, this);
287  std::cout << "ExpatCoreParser::generic_parse> starting" << std::endl;
288  }
289  for (;;) {
290  int items;
291  char* buff = (char*) XML_GetBuffer (p, BUFFSIZE + 1);
292  items = fread (buff, 1, BUFFSIZE, docfd);
293  if (ferror (docfd)){
294  std::cout << "Read error" << std::endl;
295  result = 0;
296  break;
297  }
298  int done = feof (docfd);
299  buff[items] = 0;
300  if (XML_ParseBuffer (p, BUFFSIZE, done) == XML_STATUS_ERROR) {
301  if (!done) {
302  std::cout << "ExpatCoreParser::Parse error at line " << XML_GetCurrentLineNumber(p)
303  << " of file " << file_name
304  << ":" << std::endl
305  << XML_ErrorString (XML_GetErrorCode(p)) << std::endl;
306  result = 0;
307  }
308  /* handle parse error */
309  }
310  if (done) break;
311  }
312  fclose (docfd);
313  return (result);
314 }
315 
316 int
317 ExpatCoreParser::generic_text_parse (XML_Parser p, const std::string& text){
319  std::cout << "ExpatCoreParser::generic_text_parse> " << std::endl;
320  }
321  int result = 1;
322  XML_SetParamEntityParsing (p, XML_PARAM_ENTITY_PARSING_ALWAYS);
323  XML_SetElementHandler (p, start, end);
324  XML_SetCharacterDataHandler (p, char_data);
325  XML_SetExternalEntityRefHandler (p, external_entity);
326  XML_SetCommentHandler (p, comment);
327  XML_SetUserData (p, this);
329  std::cout << "ExpatCoreParser::generic_text_parse> starting" << std::endl;
330  }
331  {
332  char* buff = (char*) XML_GetBuffer (p, text.size() + 1);
333  strcpy (buff, text.c_str ());
334  int done = 1;
335  if (XML_ParseBuffer (p, text.size(), done) == XML_STATUS_ERROR) {
336  std::cout << "ExpatCoreParser::Parse error at line " << XML_GetCurrentLineNumber(p)
337  << ":" << std::endl
338  << XML_ErrorString (XML_GetErrorCode(p)) << std::endl;
339  result = 0;
340  /* handle parse error */
341  }
342  }
343  return (result);
344 }
345 
346 int
348  const XML_Char* context, const XML_Char* systemId){
349  std::string context_str;
350  if (context == 0) context_str = "none";
351  else context_str = context;
352  bool done = false;
353  int status = 0;
354  if (context != 0) {
355  std::string replacement = find_text_entity (context_str);
356  if (replacement != "") {
358  std::cout << "ExpatCoreParser::do_external_entity> "
359  << " context=[" << context_str << "]"
360  << " replacement=[" << replacement << "]"
361  << std::endl;
362  }
363  XML_Parser p = XML_ExternalEntityParserCreate (parser, context, NULL);
364  status = generic_text_parse (p, replacement);
365  XML_ParserFree (p);
366  done = true;
367  }
368  }
369  if (!done) {
370  std::string replacement = find_external_entity (context_str);
371  if (replacement == "NULL") {
372  return (1);
373  }
374  if (replacement != "") {
375  systemId = replacement.c_str ();
376  }
377 
379  std::cout << "ExpatCoreParser::do_external_entity> "
380  << " context=[" << context_str << "]"
381  << " systemId=[" << systemId << "]"
382  << " replacement=[" << replacement << "]"
383  << std::endl;
384  }
385  XML_Parser p = XML_ExternalEntityParserCreate (parser, context, NULL);
387  XML_ParserFree (p);
388  }
389  return (status);
390 }
391 
392 const std::string&
394  lock_t lock (s_mutex);
395  ExternalEntityMap::const_iterator it = s_entities.find (name);
396  if (it == s_entities.end ()) {
397  static const std::string empty;
398  return (empty);
399  } else {
400  return ((*it).second);
401  }
402 }
403 
404 const std::string&
406  lock_t lock (s_mutex);
407  ExternalEntityMap::const_iterator it = s_text_entities.find (name);
408  if (it == s_text_entities.end ()) {
409  static const std::string empty;
410  return (empty);
411  } else {
412  return ((*it).second);
413  }
414 }
415 
416 std::unique_ptr<CoreParser::DOMNode>
417 ExpatCoreParser::parse (const std::string& file_name){
418  std::string name = file_name;
419  std::string::size_type pos = file_name.rfind ('/');
420  std::string prefix;
421  if (pos != std::string::npos){
422  prefix = file_name.substr (0, pos);
423  name = file_name.substr (pos + 1);
424  }
425  ExpatCoreParser me (prefix);
426  XML_Parser p = XML_ParserCreate (NULL);
427  if (!p) {
428  std::cout << "ExpatCoreParser::Couldn't allocate memory for parser" << std::endl;
429  std::abort();
430  }
431  int result = me.generic_parse (p, name);
432  XML_ParserFree (p);
433  if (result == 0) return nullptr;
434  return me.get_document ();
435 }
436 
ExpatCoreParser::external_entity
static int external_entity(XML_Parser parser, const XML_Char *context, const XML_Char *, const XML_Char *systemId, const XML_Char *)
Definition: ExpatCoreParser.cxx:71
base
std::string base
Definition: hcg.cxx:78
python.CaloScaleNoiseConfig.parser
parser
Definition: CaloScaleNoiseConfig.py:75
get_hdefs.buff
buff
Definition: get_hdefs.py:61
ExpatCoreParser::find_external_entity
static const std::string & find_external_entity(const std::string &name)
Definition: ExpatCoreParser.cxx:393
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
get_generator_info.result
result
Definition: get_generator_info.py:21
BUFFSIZE
#define BUFFSIZE
Definition: ExpatCoreParser.cxx:38
ExpatCoreParser::do_end
void do_end(const char *el)
Definition: ExpatCoreParser.cxx:166
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
ExpatCoreParser::do_external_entity
int do_external_entity(XML_Parser parser, const XML_Char *context, const XML_Char *systemId)
Definition: ExpatCoreParser.cxx:347
ExpatCoreParser::find_text_entity
static const std::string & find_text_entity(const std::string &name)
Definition: ExpatCoreParser.cxx:405
skel.it
it
Definition: skel.GENtoEVGEN.py:396
ExpatCoreParser::lock_t
std::lock_guard< std::mutex > lock_t
Definition: ExpatCoreParser.h:71
ExpatCoreParser::entity
static void entity(void *userData, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *)
Definition: ExpatCoreParser.cxx:102
athena.value
value
Definition: athena.py:124
CoreParser::DOMNode
Definition: DOMNode.h:21
ExpatCoreParser::ExternalEntityMap
std::map< std::string, std::string > ExternalEntityMap
Definition: ExpatCoreParser.h:19
ExpatCoreParser::do_char_data
void do_char_data(const XML_Char *s, int len)
Definition: ExpatCoreParser.cxx:174
ExpatCoreParser::m_prefix
std::string m_prefix
Definition: ExpatCoreParser.h:68
ExpatCoreParserDebugger
Definition: ExpatCoreParser.cxx:25
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
XMLCoreParser.h
empty
bool empty(TH1 *h)
Definition: computils.cxx:295
ExpatCoreParser::end
static void end(void *, const char *el)
Definition: ExpatCoreParser.cxx:47
ExpatCoreParser.h
ExpatCoreParser::ExpatCoreParser
ExpatCoreParser(const std::string &prefix)
Definition: ExpatCoreParser.cxx:139
ExpatCoreParser
Definition: ExpatCoreParser.h:16
physics_parameters.file_name
string file_name
Definition: physics_parameters.py:32
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
ExpatCoreParserDebugger::get_debug_state
static bool get_debug_state()
Definition: ExpatCoreParser.cxx:27
CoreParser::DOMNode::COMMENT_NODE
@ COMMENT_NODE
Definition: DOMNode.h:27
lumiFormat.i
int i
Definition: lumiFormat.py:85
ExpatCoreParser::register_text_entity
static void register_text_entity(const std::string &name, const std::string &text)
Definition: ExpatCoreParser.cxx:92
CoreParser::DOMNode::ELEMENT_NODE
@ ELEMENT_NODE
Definition: DOMNode.h:26
ExpatCoreParser::do_comment
void do_comment(const XML_Char *s)
Definition: ExpatCoreParser.cxx:202
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
ExpatCoreParser::m_last
CoreParser::DOMNode * m_last
Definition: ExpatCoreParser.h:67
plotIsoValidation.el
el
Definition: plotIsoValidation.py:197
CaloCondBlobAlgs_fillNoiseFromASCII.systemId
systemId
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:108
ExpatCoreParser::do_default_handler
void do_default_handler(const XML_Char *s, int len)
Definition: ExpatCoreParser.cxx:188
TrigInDetValidation_Base.malloc
malloc
Definition: TrigInDetValidation_Base.py:132
ExpatCoreParser::generic_parse
int generic_parse(XML_Parser p, const std::string &file_name)
Definition: ExpatCoreParser.cxx:217
PyPoolBrowser.node
node
Definition: PyPoolBrowser.py:131
ExpatCoreParserDebugger::debug
static bool debug()
Definition: ExpatCoreParser.cxx:30
ExpatCoreParser::get_document
std::unique_ptr< CoreParser::DOMNode > get_document()
Definition: ExpatCoreParser.cxx:135
ExpatCoreParser::start
static void start(void *, const char *el, const char **attr)
Definition: ExpatCoreParser.cxx:41
grepfile.sep
sep
Definition: grepfile.py:38
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
ExpatCoreParser::char_data
static void char_data(void *, const XML_Char *s, int len)
Definition: ExpatCoreParser.cxx:53
ExpatCoreParser::default_handler
static void default_handler(void *, const XML_Char *s, int len)
Definition: ExpatCoreParser.cxx:59
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
ExpatCoreParser::do_start
void do_start(const char *el, const char **attr)
Definition: ExpatCoreParser.cxx:146
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
a
TList * a
Definition: liststreamerinfos.cxx:10
SCT_ConditionsAlgorithms::CoveritySafe::getenv
std::string getenv(const std::string &variableName)
get an environment variable
Definition: SCT_ConditionsUtilities.cxx:17
ExpatCoreParser::parse
static std::unique_ptr< CoreParser::DOMNode > parse(const std::string &file_name)
Definition: ExpatCoreParser.cxx:417
ExpatCoreParser::generic_text_parse
int generic_text_parse(XML_Parser p, const std::string &text)
Definition: ExpatCoreParser.cxx:317
ExpatCoreParser::s_mutex
static std::mutex s_mutex
Definition: ExpatCoreParser.h:70
ExpatCoreParser::comment
static void comment(void *, const XML_Char *s)
Definition: ExpatCoreParser.cxx:65
makeTransCanvas.text
text
Definition: makeTransCanvas.py:11
ExpatCoreParser::register_external_entity
static void register_external_entity(const std::string &name, const std::string &file_name)
Definition: ExpatCoreParser.cxx:82
merge.status
status
Definition: merge.py:17
CoreParser::DOMNode::m_parent
DOMNode * m_parent
Definition: DOMNode.h:52
ExpatCoreParser::m_top
std::unique_ptr< CoreParser::DOMNode > m_top
Definition: ExpatCoreParser.h:66
node
Definition: memory_hooks-stdcmalloc.h:74