Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hddm-c.cpp
Go to the documentation of this file.
1 /*
2  * hddm-c : tool that reads in a HDDM document (Hall D Data Model)
3  * and writes a c header file that embodies the model in
4  * c structures. It also generates an input/output pair
5  * of functions to translate the model between the memory
6  * representation and a default binary representation that
7  * is suitable for passing over a pipe or storing on disk.
8  *
9  * Version 1.2 - Richard Jones, December 2005.
10  * - Updated code to use STL strings and vectors instead of old c-style
11  * pre-allocated arrays and strXXX functions.
12  * - Moved functions into classes grouped by function for better clarity.
13  *
14  * Version 1.1 - Richard Jones, September 2003.
15  * - Updated code to work with the new DOM-2 implementation Xerces-c
16  * from apache.org. Significant changes have taken place in the API
17  * since DOM-1.
18  * - Added support for new types "long" (int64), "string" (char arrays of
19  * arbitrary length), and "anyURI" (special case of string).
20  * - Switched from native encoding to the use of the XDR library to make
21  * hddm files machine-independent.
22  *
23  * Original version - Richard Jones, May 25 2001.
24  *
25  *
26  * Programmer's Notes:
27  * -------------------
28  * 1. The HDDM specification describes data files using xml. For
29  * information about the contents and structure of HDDM documents
30  * see the web page that describes the data model.
31  *
32  * 2. Access by hddm-c to the xml source is through the industry-
33  * standard Document Object Model (DOM) interface.
34  *
35  * 3. The code has been tested with the xerces-c DOM implementation from
36  * Apache, and is intended to be used with the xerces-c library.
37  *
38  * 4. Output is sent to <filename>.h and <filename>.c where <filename> is
39  * by default "hddm" and can be changed with the -o option.
40  *
41  * 5. As a by-product of using the DOM parser to access the xml source,
42  * hddm-c verifies the source for well-formedness. Therefore it may
43  * also be used to check the xml data model document.
44  *
45  *
46  * Implementation Notes:
47  * ---------------------
48  * 1. The binary stream consists of the hddm data model in the form
49  * of a well-formed xml header, followed by binary data.
50  *
51  * 2. The binary data consist of a sequence of event records, which are
52  * repetitions of the basic data model in a serial representation.
53  *
54  * 3. Each element is output to the stream in the order it appears in
55  * the data model, prefixed by an exclusive byte count.
56  *
57  * 4. Any c application compiled with the hddm header file that is
58  * generated by hddm-c is able to read any hddm binary file that
59  * was written using the same hddm class, ie. the <HDDM class="x">
60  * document tags must be a non-colliding set (see matching rules).
61  *
62  * 5. The input/output features of the c library produced by hddm-c
63  * are implemented using the xdr binary i/o library written originally
64  * by Sun Microsystems. This library provides basic serialization/
65  * deserialization of binary data using network byte-ordering
66  * (RFC-1832) and is a part of many unix installations.
67  */
68 
69 #define MAX_POPLIST_LENGTH 99
70 
71 #include "XString.hpp"
72 #include "XParsers.hpp"
73 
74 #include <assert.h>
75 #include <ctype.h>
76 #include <stdlib.h>
77 #include <stdio.h>
78 
79 #include <string>
80 #include <vector>
81 #include <fstream>
82 
83 #define X(str) XString(str).unicode_str()
84 #define S(str) str.c_str()
85 
86 using namespace xercesc;
87 
89 
90 void usage()
91 {
92  std::cerr
93  << "\nUsage:\n"
94  << " hddm-c [-v | -o <filename>] {HDDM file}\n\n"
95  << "Options:\n"
96  << " -v validate only\n"
97  << " -o <filename> write to <filename>.h, <filename>.c"
98  << std::endl;
99 }
100 
101 class XtString : public XString
102 {
103 /* XString class with a few extra methods for creating type
104  * strings that are useful in creating c structures
105  */
106  public:
107  XtString() {};
108  XtString(const char* s): XString(s) {};
109  XtString(const XMLCh* p): XString(p) {};
110  XtString(const std::string& s): XString(s) {};
111  XtString(const XString& x): XString(x) {};
112  XtString(const XtString& t): XString((XString&)t) {};
113 
114  XtString plural();
115  XtString simpleType();
116  XtString listType();
117 };
118 
120 {
121 /* The methods in this class are used to write the c code that
122  * implements the hddm structures i/o library.
123  */
124  public:
125  std::ofstream hFile;
126  std::ofstream cFile;
127 
130 
131  void checkConsistency(DOMElement* el, DOMElement* elref);
132  void writeHeader(DOMElement* el);
133  void constructGroup(DOMElement* el);
134  void constructConstructors();
135  void constructUnpackers();
136  void constructReadFunc(DOMElement* topEl);
137  void constructSkipFunc();
138  void constructPackers();
139  void constructFlushFunc(DOMElement* el);
140  void writeMatcher();
141  void constructOpenFunc(DOMElement* el);
142  void constructInitFunc(DOMElement* el);
143  void constructCloseFunc(DOMElement* el);
144  void constructDocument(DOMElement* el);
145 
146  private:
147  std::vector<DOMElement*> tagList;
148 };
149 
150 
151 int main(int argC, char* argV[])
152 {
153  try
154  {
155  XMLPlatformUtils::Initialize();
156  }
157  catch (const XMLException* toCatch)
158  {
159  XtString msg(toCatch->getMessage());
160  std::cerr
161  << "hddm-c: Error during initialization! :\n"
162  << msg << std::endl;
163  return 1;
164  }
165 
166  if (argC < 2)
167  {
168  usage();
169  return 1;
170  }
171  else if ((argC == 2) && (strcmp(argV[1], "-?") == 0))
172  {
173  usage();
174  return 2;
175  }
176 
177  XtString xmlFile;
178  XtString hFilename;
179  bool verifyOnly = false;
180  int argInd;
181  for (argInd = 1; argInd < argC; argInd++)
182  {
183  if (argV[argInd][0] != '-')
184  {
185  break;
186  }
187  if (strcmp(argV[argInd],"-v") == 0)
188  {
189  verifyOnly = true;
190  }
191  else if (strcmp(argV[argInd],"-o") == 0)
192  {
193  hFilename = XtString(argV[++argInd]);
194  }
195  else
196  {
197  std::cerr
198  << "Unknown option \'" << argV[argInd]
199  << "\', ignoring it\n" << std::endl;
200  }
201  }
202 
203  if (argInd != argC - 1)
204  {
205  usage();
206  return 1;
207  }
208  xmlFile = XtString(argV[argInd]);
209 
210 #if defined OLD_STYLE_XERCES_PARSER
211  DOMDocument* document = parseInputDocument(xmlFile.c_str(),false);
212 #else
213  DOMDocument* document = buildDOMDocument(xmlFile.c_str(),false);
214 #endif
215  if (document == 0)
216  {
217  std::cerr
218  << "hddm-c : Error parsing HDDM document, "
219  << "cannot continue" << std::endl;
220  return 1;
221  }
222 
223  DOMElement* rootEl = document->getDocumentElement();
224  XtString rootS(rootEl->getTagName());
225  if (rootS != "HDDM")
226  {
227  std::cerr
228  << "hddm-c error: root element of input document is "
229  << "\"" << rootS << "\", expected \"HDDM\""
230  << std::endl;
231  return 1;
232  }
233 
234  XtString classS(rootEl->getAttribute(X("class")));
235  classPrefix = classS;
236 
237  XtString hname;
238  if (verifyOnly)
239  {
240  hname = "/dev/null";
241  }
242  else if (hFilename.size())
243  {
244  hname = hFilename + ".h";
245  }
246  else
247  {
248  hname = "hddm_" + classPrefix + ".h";
249  }
250 
251  CodeBuilder builder;
252  builder.hFile.open(hname.c_str());
253  if (! builder.hFile.is_open())
254  {
255  std::cerr
256  << "hddm-c error: unable to open output file "
257  << hname << std::endl;
258  return 1;
259  }
260 
261  XtString cname;
262  if (verifyOnly)
263  {
264  cname = "/dev/null";
265  }
266  else if (hFilename.size())
267  {
268  cname = hFilename + ".c";
269  }
270  else
271  {
272  cname = "hddm_" + classPrefix + ".c";
273  }
274 
275  builder.cFile.open(cname.c_str());
276  if (! builder.cFile.is_open())
277  {
278  std::cerr
279  << "hddm-c error: unable to open output file "
280  << cname << std::endl;
281  return 1;
282  }
283 
284  builder.hFile
285  << "/*" << std::endl
286  << " * " << hname << " - DO NOT EDIT THIS FILE" << std::endl
287  << " *" << std::endl
288  << " * This file was generated automatically by hddm-c"
289  << " from the file" << std::endl
290  << " * " << xmlFile << std::endl
291  << std::endl
292  << " * This header file defines the c structures that"
293  << " hold the data" << std::endl
294  << " * described in the data model"
295  << " (from " << xmlFile << "). " << std::endl
296  << " *" << std::endl
297  << " * The hddm data model tool set was written by" << std::endl
298  << " * Richard Jones, University of Connecticut." << std::endl
299  << " *" << std::endl
300  << " * For more information see the following web site"<< std::endl
301  << " *" << std::endl
302  << " * http://zeus.phys.uconn.edu/halld/datamodel/doc" << std::endl
303  << " *" << std::endl
304  << " */" << std::endl
305  << std::endl;
306 
307  builder.cFile
308  << "/*" << std::endl
309  << " * " << cname << " - DO NOT EDIT THIS FILE" << std::endl
310  << " *" << std::endl
311  << " * This file was generated automatically by hddm-c"
312  << " from the file" << std::endl
313  << " * " << xmlFile << std::endl
314  << std::endl
315  << " * This c file contains the i/o interface to"
316  << " the c structures" << std::endl
317  << " * described in the data model"
318  << " (from " << xmlFile << "). " << std::endl
319  << " *" << std::endl
320  << " * The hddm data model tool set was written by" << std::endl
321  << " * Richard Jones, University of Connecticut." << std::endl
322  << " *" << std::endl
323  << " * For more information see the following web site"<< std::endl
324  << " *" << std::endl
325  << " * http://zeus.phys.uconn.edu/halld/datamodel/doc" << std::endl
326  << " */" << std::endl
327  << std::endl;
328 
329  builder.hFile
330  << "#include <stdlib.h>" << std::endl
331  << "#include <stdio.h>" << std::endl
332  << "#include <errno.h>" << std::endl
333  << "#include <rpc/rpc.h>" << std::endl
334  << "#include <string.h>" << std::endl
335  << "#include <strings.h>" << std::endl
336  << "#include <particleType.h>" << std::endl
337  << std::endl
338  << "typedef char* string_t; "
339  << "// use this alias for string-valued attributes" << std::endl
340  << std::endl
341  << "/* Note to users: The option MALLOC_FREE_WITH_MEMCHECK" << std::endl
342  << " * was created for debugging this hddm library, but it" << std::endl
343  << " * is also useful for finding memory leaks in user" << std::endl
344  << " * code. To use it, replace malloc(n) everywhere in" << std::endl
345  << " * your code with MALLOC(n,\"some descriptive string\")" << std::endl
346  << " * and free(p) with FREE(p) and include this header" << std::endl
347  << " * and compile with -DMALLOC_FREE_WITH_MEMCHECK set." << std::endl
348  << " * Any attempt to malloc memory already malloc'ed or" << std::endl
349  << " * to free memory that has not yet been malloc'ed is" << std::endl
350  << " * immediately flagged with an error message. A call" << std::endl
351  << " * to checkpoint() anywhere in the user code reports" << std::endl
352  << " * any memory that has been malloc'ed not freed." << std::endl
353  << " */" << std::endl
354  << "#if defined MALLOC_FREE_WITH_MEMCHECK" << std::endl
355  << "# include <memcheck.h>" << std::endl
356  << "# define MALLOC(N,S) (checkin(malloc(N),S))" << std::endl
357  << "# define CHECK(P,S) (checkin(P,S))" << std::endl
358  << "# define FREE(P) (checkout(P),free(P))" << std::endl
359  << "#else" << std::endl
360  << "# define MALLOC(N,S) malloc(N)" << std::endl
361  << "# define CHECK(P,S) assert(1 == 1)" << std::endl
362  << "# define FREE(P) free(P)" << std::endl
363  << "#endif" << std::endl;
364 
365  builder.cFile
366  << "int hddm_" + classPrefix + "_nullTarget=0;" << std::endl
367  << "#define HDDM_NULL (void*)&hddm_" + classPrefix + "_nullTarget"
368  << std::endl
369  << std::endl
370  << "#include \"" << hname << "\"" << std::endl
371  << "#include <assert.h>" << std::endl
372  << std::endl
373  << "int hddm_" + classPrefix + "_buffersize = 1000000;"
374  << std::endl
375  << "int hddm_" + classPrefix + "_stringsize = 1000000;"
376  << std::endl
377  << "int hddm_" + classPrefix + "_headersize = 1000000;"
378  << std::endl
379  << std::endl
380  << "void set_" + classPrefix + "_HDDM_buffersize(int size)"
381  << std::endl
382  << "{" << std::endl
383  << " hddm_" + classPrefix + "_buffersize = size;" << std::endl
384  << "}" << std::endl
385  << std::endl
386  << "int get_" + classPrefix + "_HDDM_buffersize()" << std::endl
387  << "{" << std::endl
388  << " return hddm_" + classPrefix + "_buffersize;" << std::endl
389  << "}" << std::endl
390  << std::endl
391  << "void set_" + classPrefix + "_HDDM_stringsize(int size)"
392  << std::endl
393  << "{" << std::endl
394  << " hddm_" + classPrefix + "_stringsize = size;" << std::endl
395  << "}" << std::endl
396  << std::endl
397  << "int get_" + classPrefix + "_HDDM_stringsize()" << std::endl
398  << "{" << std::endl
399  << " return hddm_" + classPrefix + "_stringsize;" << std::endl
400  << "}" << std::endl
401  << std::endl
402  << "void set_" + classPrefix + "_HDDM_headersize(int size)"
403  << std::endl
404  << "{" << std::endl
405  << " hddm_" + classPrefix + "_headersize = size;" << std::endl
406  << "}" << std::endl
407  << std::endl
408  << "int get_" + classPrefix + "_HDDM_headersize()" << std::endl
409  << "{" << std::endl
410  << " return hddm_" + classPrefix + "_headersize;" << std::endl
411  << "}" << std::endl
412  << std::endl
413  << "static int XDRerror()" << std::endl
414  << "{" << std::endl
415  << " fprintf(stderr,\"hddm xdr library error - \"" << std::endl
416  << " \"data buffering has failed for some reason,\"" << std::endl
417  << " \" probably buffer overflow.\\n\"" << std::endl
418  << " \"Try increasing the size of the hddm i/o\"" << std::endl
419  << " \" buffers or maximum string size.\\n\");" << std::endl
420  << " exit(9);" << std::endl
421  << " return 0;" << std::endl
422  << "}" << std::endl;
423 
424  builder.constructGroup(rootEl);
425 
426  builder.hFile << std::endl
427  << "#ifdef __cplusplus" << std::endl
428  << "extern \"C\" {" << std::endl
429  << "#endif" << std::endl;
430  builder.constructConstructors();
431  builder.hFile << std::endl
432  << "#ifdef __cplusplus" << std::endl
433  << "}" << std::endl
434  << "#endif" << std::endl;
435 
436  builder.hFile << std::endl
437  << "#ifndef " << classPrefix << "_DocumentString" << std::endl
438  << "#define " << classPrefix << "_DocumentString" << std::endl
439  << std::endl
440  << "extern "
441  << "char HDDM_" << classPrefix << "_DocumentString[];" << std::endl
442  << std::endl
443  << "#ifdef INLINE_PREPEND_UNDERSCORES" << std::endl
444  << "#define inline __inline" << std::endl
445  << "#endif" << std::endl
446  << std::endl
447  << "#endif /* " << classPrefix << "_DocumentString */" << std::endl;
448 
449  builder.cFile << std::endl
450  << "char HDDM_" << classPrefix << "_DocumentString[]"
451  << " = " << std::endl;
452  builder.constructDocument(rootEl);
453  builder.cFile << ";" << std::endl;
454 
455  builder.hFile << std::endl
456  << "#ifndef HDDM_STREAM_INPUT" << std::endl
457  << "#define HDDM_STREAM_INPUT -91" << std::endl
458  << "#define HDDM_STREAM_OUTPUT -92" << std::endl
459  << std::endl
460  << "struct popNode_s {" << std::endl
461  << " void* (*unpacker)(XDR*, struct popNode_s*);" << std::endl
462  << " int inParent;" << std::endl
463  << " int popListLength;" << std::endl
464  << " struct popNode_s* popList["
465  << MAX_POPLIST_LENGTH << "];" << std::endl
466  << "};" << std::endl
467  << "typedef struct popNode_s popNode;" << std::endl
468  << std::endl
469  << "typedef struct {" << std::endl
470  << " FILE* fd;" << std::endl
471  << " int iomode;" << std::endl
472  << " int lerrno;" << std::endl
473  << " char* filename;" << std::endl
474  << " XDR* xdrs;" << std::endl
475  << " popNode* popTop;" << std::endl
476  << " char* iobuffer;" << std::endl
477  << " int iobuffer_size;" << std::endl
478  << "} " << classPrefix << "_iostream_t;" << std::endl
479  << std::endl
480  << "#endif /* HDDM_STREAM_INPUT */" << std::endl;
481 
482  builder.cFile << std::endl
483  << "#ifndef _FILE_OFFSET_BITS" << std::endl
484  << "# define _FILE_OFFSET_BITS 64" << std::endl
485  << "#endif" << std::endl
486  << std::endl
487  << "static off_t xdr_getpos64(XDR *xdrs)" << std::endl
488  << "{" << std::endl
489  << " if (xdrs->x_base == 0) {" << std::endl
490  << " return ftello((FILE *)xdrs->x_private);" << std::endl
491  << " }" << std::endl
492  << " off_t pos = xdr_getpos(xdrs);" << std::endl
493  << " return pos;" << std::endl
494  << "}" << std::endl
495  << std::endl
496  << "static bool_t xdr_setpos64(XDR *xdrs, off_t pos) " << std::endl
497  << "{ " << std::endl
498  << " if (xdrs->x_base == 0) {" << std::endl
499  << " return ((fseeko((FILE *)xdrs->x_private, pos, 0) < 0)? FALSE : TRUE);"
500  << std::endl
501  << " }" << std::endl
502  << " return xdr_setpos(xdrs,pos);" << std::endl
503  << "}" << std::endl;
504 
505  builder.constructUnpackers();
506 
507  builder.hFile << std::endl
508  << "#ifdef __cplusplus" << std::endl
509  << "extern \"C\" {" << std::endl
510  << "#endif" << std::endl
511  << std::endl
512  << "void set_" + classPrefix + "_HDDM_buffersize(int size);"
513  << std::endl
514  << "int get_" + classPrefix + "_HDDM_buffersize();" << std::endl
515  << "void set_" + classPrefix + "_HDDM_stringsize(int size);"
516  << std::endl
517  << "int get_" + classPrefix + "_HDDM_stringsize();" << std::endl
518  << "void set_" + classPrefix + "_HDDM_headersize(int size);"
519  << std::endl
520  << "int get_" + classPrefix + "_HDDM_headersize();" << std::endl;
521  builder.constructReadFunc(rootEl);
522  builder.constructSkipFunc();
523  builder.constructFlushFunc(rootEl);
524  builder.constructOpenFunc(rootEl);
525  builder.constructInitFunc(rootEl);
526  builder.constructCloseFunc(rootEl);
527  builder.hFile << std::endl
528  << "#ifdef __cplusplus" << std::endl
529  << "}" << std::endl
530  << "#endif" << std::endl
531  << std::endl
532  << "#if !defined HDDM_NULL" << std::endl
533  << "extern int hddm_" + classPrefix + "_nullTarget;" << std::endl
534  << "# define HDDM_NULL (void*)&hddm_" + classPrefix + "_nullTarget"
535  << std::endl
536  << "#endif" << std::endl;
537 
538  XMLPlatformUtils::Terminate();
539  return 0;
540 }
541 
543 {
544  XtString p(*this);
545  XtString::size_type len = p.size();
546  if (len > 3 && p.substr(len-3,3) == "tum")
547  {
548  p.replace(len-3,3,"ta");
549  }
550  else if (len > 1 && p.substr(len-3,3) == "ies")
551  {
552  p.replace(len-3,3,"iesList");
553  }
554  else if (len > 2 && p.substr(len-2,2) == "ex")
555  {
556  p.replace(len-2,2,"ices");
557  }
558  else if (len > 2 && p.substr(len-2,2) == "sh")
559  {
560  p.replace(len-2,2,"shes");
561  }
562  else if (len > 1 && p.substr(len-1,1) == "s")
563  {
564  p.replace(len-1,1,"ses");
565  }
566  else if (len > 1)
567  {
568  p += "s";
569  }
570  return p;
571 }
572 
573 /* Map from tag name to name of the corresponding c-structure
574  * for the case of simple tags (those that do not repeat)
575  */
577 {
578  XtString p(*this);
579  p[0] = toupper(p[0]);
580  p = classPrefix + "_" + p + "_t";
581  return p;
582 }
583 
584 /* Map from tag name to name of the corresponding c-structure
585  * for the case of list tags (those that may repeat)
586  */
588 {
589  XtString r = plural();
590  r[0] = toupper(r[0]);
591  r = classPrefix + "_" + r + "_t";
592  return r;
593 }
594 
595 /* Verify that the tag group under this element does not collide
596  * with existing tag group elref, otherwise exit with fatal error
597  */
598 void CodeBuilder::checkConsistency(DOMElement* el, DOMElement* elref)
599 {
600  XtString tagS(el->getTagName());
601  if (el->getParentNode() == elref->getParentNode())
602  {
603  std::cerr
604  << "hddm-cpp error: tag " << "\"" << tagS
605  << "\" is duplicated within one context in xml document."
606  << std::endl;
607  exit(1);
608  }
609 
610  DOMNamedNodeMap* oldAttr = elref->getAttributes();
611  DOMNamedNodeMap* newAttr = el->getAttributes();
612  unsigned int listLength = oldAttr->getLength();
613  for (unsigned int n = 0; n < listLength; n++)
614  {
615  XtString nameS(oldAttr->item(n)->getNodeName());
616  XtString oldS(elref->getAttribute(X(nameS)));
617  XtString newS(el->getAttribute(X(nameS)));
618  if (nameS == "minOccurs")
619  {
620  continue;
621  }
622  else if (nameS == "maxOccurs")
623  {
624  int maxold = (oldS == "unbounded")? INT_MAX : atoi(S(oldS));
625  int maxnew = (newS == "unbounded")? INT_MAX : atoi(S(newS));
626  if ((maxold < 2 && maxnew > 1) || (maxold > 1 && maxnew < 2))
627  {
628  std::cerr
629  << "hddm-c error: inconsistent maxOccurs usage by tag "
630  << "\"" << tagS << "\" in xml document." << std::endl;
631  exit(1);
632  }
633  }
634  else if (newS != oldS)
635  {
636  std::cerr
637  << "hddm-c error: inconsistent usage of attribute "
638  << "\"" << nameS << "\" in tag "
639  << "\"" << tagS << "\" in xml document." << std::endl;
640  exit(1);
641  }
642  }
643  listLength = newAttr->getLength();
644  for (unsigned int n = 0; n < listLength; n++)
645  {
646  XtString nameS(newAttr->item(n)->getNodeName());
647  XtString oldS(elref->getAttribute(X(nameS)));
648  XtString newS(el->getAttribute(X(nameS)));
649  if (nameS == "minOccurs")
650  {
651  continue;
652  }
653  else if (nameS == "maxOccurs")
654  {
655  int maxold = (oldS == "unbounded")? INT_MAX : atoi(S(oldS));
656  int maxnew = (newS == "unbounded")? INT_MAX : atoi(S(newS));
657  if ((maxold < 2 && maxnew > 1) || (maxold > 1 && maxnew < 2))
658  {
659  std::cerr
660  << "hddm-c error: inconsistent maxOccurs usage by tag "
661  << "\"" << tagS << "\" in xml document." << std::endl;
662  exit(1);
663  }
664  }
665  else if (newS != oldS)
666  {
667  std::cerr
668  << "hddm-c error: inconsistent usage of attribute "
669  << "\"" << nameS << "\" in tag "
670  << "\"" << tagS << "\" in xml document." << std::endl;
671  exit(1);
672  }
673  }
674  DOMNodeList* oldList = elref->getChildNodes();
675  DOMNodeList* newList = el->getChildNodes();
676  listLength = oldList->getLength();
677  if (newList->getLength() != listLength)
678  {
679  std::cerr
680  << "hddm-c error: inconsistent usage of tag "
681  << "\"" << tagS << "\" in xml document." << std::endl;
682  exit(1);
683  }
684  for (unsigned int n = 0; n < listLength; n++)
685  {
686  DOMNode* cont = oldList->item(n);
687  XtString nameS(cont->getNodeName());
688  short type = cont->getNodeType();
689  if (type == DOMNode::ELEMENT_NODE)
690  {
691  DOMNodeList* contList = el->getElementsByTagName(X(nameS));
692  if (contList->getLength() != 1)
693  {
694  std::cerr
695  << "hddm-c error: inconsistent usage of tag "
696  << "\"" << tagS << "\" in xml document." << std::endl;
697  exit(1);
698  }
699  }
700  }
701 }
702 
703 /* Write declaration of c-structure for this tag to c-header file */
704 
705 void CodeBuilder::writeHeader(DOMElement* el)
706 {
707  XtString tagS(el->getTagName());
708  XtString ctypeDef = tagS.simpleType();
709  hFile << std::endl
710  << "#ifndef SAW_" << ctypeDef << std::endl
711  << "#define SAW_" << ctypeDef << std::endl
712  << std::endl
713  << "typedef struct {" << std::endl;
714 
715  DOMNamedNodeMap* varList = el->getAttributes();
716  int varCount = varList->getLength();
717  for (int v = 0; v < varCount; v++)
718  {
719  DOMNode* var = varList->item(v);
720  XtString typeS(var->getNodeValue());
721  XtString nameS(var->getNodeName());
722  if (typeS == "int")
723  {
724  hFile << " int32_t " << nameS << ";" << std::endl;
725  }
726  else if (typeS == "long")
727  {
728  hFile << " int64_t " << nameS << ";" << std::endl;
729  }
730  else if (typeS == "float")
731  {
732  hFile << " float " << nameS << ";" << std::endl;
733  }
734  else if (typeS == "double")
735  {
736  hFile << " double " << nameS << ";" << std::endl;
737  }
738  else if (typeS == "boolean")
739  {
740  hFile << " bool_t " << nameS << ";" << std::endl;
741  }
742  else if (typeS == "string")
743  {
744  hFile << " string_t " << nameS << ";" << std::endl;
745  }
746  else if (typeS == "anyURI")
747  {
748  hFile << " string_t " << nameS << ";" << std::endl;
749  }
750  else if (typeS == "Particle_t")
751  {
752  hFile << " Particle_t " << nameS << ";" << std::endl;
753  }
754  else
755  {
756  /* ignore attributes with unrecognized values */
757  }
758  }
759 
760  DOMNodeList* contList = el->getChildNodes();
761  int contLength = contList->getLength();
762  for (int c = 0; c < contLength; c++)
763  {
764  DOMNode* cont = contList->item(c);
765  XtString nameS(cont->getNodeName());
766  short type = cont->getNodeType();
767  if (type == DOMNode::ELEMENT_NODE)
768  {
769  DOMElement* contEl = (DOMElement*) cont;
770  XtString repS(contEl->getAttribute(X("maxOccurs")));
771  int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS));
772  XtString ctypeRef = (rep > 1) ? nameS.listType()
773  : nameS.simpleType();
774  XtString::size_type clen = ctypeRef.size();
775 
776  hFile << " " << ctypeRef << "* ";
777  for (int i = 0; i < 19-(int)clen; i++)
778  {
779  hFile << " ";
780  }
781  hFile << ((rep > 1) ? nameS.plural() : nameS) << ";" << std::endl;
782  }
783  }
784 
785  hFile << "} " << ctypeDef << ";" << std::endl;
786 
787  XtString repS(el->getAttribute(X("maxOccurs")));
788  int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS));
789  if (rep > 1)
790  {
791  XtString ctypeRef = tagS.listType();
792  hFile << std::endl << "typedef struct {" << std::endl
793  << " unsigned int mult;" << std::endl
794  << " " << ctypeDef << " in[1];" << std::endl
795  << "} " << ctypeRef << ";" << std::endl;
796  }
797 
798  hFile << "#endif /* " << ctypeDef << " */" << std::endl;
799 }
800 
801 /* Generate c-structure declarations for this tag and its descendants;
802  * this function calls itself recursively
803  */
804 void CodeBuilder::constructGroup(DOMElement* el)
805 {
806  XtString tagS(el->getTagName());
807  std::vector<DOMElement*>::iterator iter;
808  for (iter = tagList.begin(); iter != tagList.end(); iter++)
809  {
810  XtString targS((*iter)->getTagName());
811  if (tagS == targS)
812  {
813  checkConsistency(el,*iter);
814  return;
815  }
816  }
817 
818  tagList.push_back(el);
819 
820  DOMNodeList* contList = el->getChildNodes();
821  int contLength = contList->getLength();
822  for (int c = 0; c < contLength; c++)
823  {
824  DOMNode* cont = contList->item(c);
825  short type = cont->getNodeType();
826  if (type == DOMNode::ELEMENT_NODE)
827  {
828  DOMElement* contEl = (DOMElement*) cont;
829  constructGroup(contEl);
830  }
831  }
832 
833  writeHeader(el);
834 }
835 
836 /* Generate c code for make_<class letter>_<group name> functions */
837 
839 {
840  std::vector<DOMElement*>::iterator iter;
841  for (iter = tagList.begin(); iter != tagList.end(); iter++)
842  {
843  DOMElement* tagEl = *iter;
844  XtString tagS(tagEl->getTagName());
845  XtString listType = tagS.listType();
846  XtString simpleType = tagS.simpleType();
847 
848  hFile << std::endl;
849  cFile << std::endl;
850 
851  XtString repS = tagEl->getAttribute(X("maxOccurs"));
852  int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS));
853  if (rep > 1)
854  {
855  hFile << listType << "* ";
856  cFile << listType << "* ";
857  XtString listT(listType);
858  listT.erase(listT.rfind('_'));
859  hFile << "make_" << listT;
860  cFile << "make_" << listT;
861  hFile << "(int n);" << std::endl;
862  cFile << "(int n)" << std::endl
863  << "{" << std::endl
864  << " int i;" << std::endl
865  << " int rep = (n > 1) ? n-1 : 0;" << std::endl
866  << " int size = sizeof(" << listType
867  << ") + rep * sizeof(" << simpleType << ");" << std::endl
868  << " " << listType
869  << "* p = (" << listType << "*)MALLOC(size,\""
870  << listType << "\");" << std::endl
871  << " p->mult = 0;" << std::endl
872  << " for (i=0; i<n; i++) {" << std::endl
873  << " " << simpleType << "* pp = &p->in[i];" << std::endl;
874  DOMNamedNodeMap* varList = tagEl->getAttributes();
875  int varCount = varList->getLength();
876  for (int v = 0; v < varCount; v++)
877  {
878  DOMNode* var = varList->item(v);
879  XtString typeS(var->getNodeValue());
880  XtString nameS(var->getNodeName());
881  if (typeS == "string" ||
882  typeS == "anyURI")
883  {
884  cFile << " pp->" << nameS
885  << " = (string_t)&hddm_" + classPrefix + "_nullTarget;"
886  << std::endl;
887  }
888  else if (typeS == "int" ||
889  typeS == "long" ||
890  typeS == "float" ||
891  typeS == "double" ||
892  typeS == "boolean")
893  {
894  cFile << " pp->" << nameS << " = 0;" << std::endl;
895  }
896  else if (typeS == "Particle_t")
897  {
898  cFile << " pp->" << nameS
899  << " = (Particle_t)0;" << std::endl;
900  }
901  }
902  DOMNodeList* contList = tagEl->getChildNodes();
903  for (unsigned int c = 0; c < contList->getLength(); c++)
904  {
905  DOMNode* cont = contList->item(c);
906  short ctype = cont->getNodeType();
907  if (ctype == DOMNode::ELEMENT_NODE)
908  {
909  DOMElement* contEl = (DOMElement*) cont;
910  XtString cnameS(contEl->getTagName());
911  XtString crepS(contEl->getAttribute(X("maxOccurs")));
912  int crep = (crepS == "unbounded")? INT_MAX : atoi(S(crepS));
913  if (crep > 1)
914  {
915  cFile << " pp->" << cnameS.plural()
916  << " = (" << cnameS.listType()
917  << "*)&hddm_" + classPrefix + "_nullTarget;"
918  << std::endl;
919  }
920  else
921  {
922  cFile << " pp->" << cnameS
923  << " = (" << cnameS.simpleType()
924  << "*)&hddm_" + classPrefix + "_nullTarget;"
925  << std::endl;
926  }
927  }
928  }
929  cFile << " }" << std::endl;
930  }
931  else
932  {
933  hFile << simpleType << "* ";
934  cFile << simpleType << "* ";
935  XtString simpleT(simpleType);
936  simpleT.erase(simpleT.rfind('_'));
937  hFile << "make_" << simpleT;
938  cFile << "make_" << simpleT;
939  hFile << "();" << std::endl;
940  cFile << "()" << std::endl
941  << "{" << std::endl
942  << " int size = sizeof(" << simpleType << ");" << std::endl
943  << " " << simpleType << "* p = "
944  << "(" << simpleType << "*)MALLOC(size,\""
945  << simpleType << "\");" << std::endl;
946  DOMNamedNodeMap* varList = tagEl->getAttributes();
947  int varCount = varList->getLength();
948  for (int v = 0; v < varCount; v++)
949  {
950  DOMNode* var = varList->item(v);
951  XtString typeS(var->getNodeValue());
952  XtString nameS(var->getNodeName());
953  if (typeS == "string" ||
954  typeS == "anyURI")
955  {
956  cFile << " p->" << nameS
957  << " = (string_t)&hddm_" + classPrefix + "_nullTarget;"
958  << std::endl;
959  }
960  else if (typeS == "int" ||
961  typeS == "long" ||
962  typeS == "float" ||
963  typeS == "double" ||
964  typeS == "boolean")
965  {
966  cFile << " p->" << nameS << " = 0;" << std::endl;
967  }
968  else if (typeS == "Particle_t")
969  {
970  cFile << " p->" << nameS
971  << " = (Particle_t)0;" << std::endl;
972  }
973  }
974  DOMNodeList* contList = tagEl->getChildNodes();
975  for (unsigned int c = 0; c < contList->getLength(); c++)
976  {
977  DOMNode* cont = contList->item(c);
978  short ctype = cont->getNodeType();
979  if (ctype == DOMNode::ELEMENT_NODE)
980  {
981  DOMElement* contEl = (DOMElement*) cont;
982  XtString cnameS(contEl->getTagName());
983  XtString crepS(contEl->getAttribute(X("maxOccurs")));
984  int crep = (crepS == "unbounded")? INT_MAX : atoi(S(crepS));
985  if (crep > 1)
986  {
987  cFile << " p->" << cnameS.plural()
988  << " = (" << cnameS.listType()
989  << "*)&hddm_" + classPrefix + "_nullTarget;"
990  << std::endl;
991  }
992  else
993  {
994  cFile << " p->" << cnameS
995  << " = (" << cnameS.simpleType()
996  << "*)&hddm_" + classPrefix + "_nullTarget;"
997  << std::endl;
998  }
999  }
1000  }
1001  }
1002  cFile << " return p;" << std::endl
1003  << "}" << std::endl;
1004  }
1005 }
1006 
1007 /* Generate c functions for unpacking binary stream into c-structures */
1008 
1010 {
1011  cFile << std::endl;
1012  std::vector<DOMElement*>::iterator iter;
1013  for (iter = tagList.begin(); iter != tagList.end(); iter++)
1014  {
1015  DOMElement* tagEl = *iter;
1016  XtString tagS(tagEl->getTagName());
1017  XtString listType = tagS.listType();
1018  XtString simpleType = tagS.simpleType();
1019 
1020  cFile << std::endl << "static ";
1021 
1022  XtString tagType;
1023  XtString repS = tagEl->getAttribute(X("maxOccurs"));
1024  int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS));
1025  if (rep > 1)
1026  {
1027  tagType = tagS.listType();
1028  }
1029  else
1030  {
1031  tagType = tagS.simpleType();
1032  }
1033  XtString tagT(tagType);
1034  tagT.erase(tagT.rfind('_'));
1035  cFile << tagType << "* unpack_" << tagT
1036  << "(XDR* xdrs, popNode* pop)"
1037  << std::endl
1038  << "{" << std::endl
1039  << " " << tagType << "* this1 = (" << tagType
1040  << "*)HDDM_NULL;" << std::endl
1041  << " unsigned int size;" << std::endl
1042  << " if (! xdr_u_int(xdrs,&size))" << std::endl
1043  << " {" << std::endl
1044  << " return this1;" << std::endl
1045  << " }" << std::endl
1046  << " else if (size > 0)" << std::endl
1047  << " {" << std::endl
1048  << " off_t start = xdr_getpos64(xdrs);" << std::endl;
1049 
1050  if (rep > 1)
1051  {
1052  cFile << " int m;" << std::endl
1053  << " unsigned int mult;" << std::endl
1054  << " if (! xdr_u_int(xdrs,&mult))" << std::endl
1055  << " XDRerror();" << std::endl;
1056  cFile << " this1 = make_" << tagT << "(mult);" << std::endl;
1057 
1058  cFile << " this1->mult = mult;" << std::endl
1059  << " for (m = 0; m < mult; m++ )" << std::endl
1060  << " {" << std::endl;
1061  }
1062  else
1063  {
1064  cFile << " this1 = make_" << tagT << "();" << std::endl
1065  << " {" << std::endl;
1066  }
1067 
1068  int hasContents = 0;
1069  DOMNodeList* contList = tagEl->getChildNodes();
1070  for (unsigned int c = 0; c < contList->getLength(); c++)
1071  {
1072  DOMNode* cont = contList->item(c);
1073  short type = cont->getNodeType();
1074  if (type == DOMNode::ELEMENT_NODE)
1075  {
1076  hasContents = 1;
1077  DOMElement* contEl = (DOMElement*) cont;
1078  XtString nameS(contEl->getTagName());
1079  XtString reS(contEl->getAttribute(X("maxOccurs")));
1080  int re = (reS == "unbounded")? INT_MAX : atoi(S(reS));
1081  cFile << " int p;" << std::endl
1082  << " void* (*ptr) = (void**) &this1->"
1083  << ((rep > 1) ? "in[m]." : "" )
1084  << ((re > 1) ? nameS.plural() : nameS) << ";" << std::endl;
1085  break;
1086  }
1087  }
1088 
1089  DOMNamedNodeMap* attList = tagEl->getAttributes();
1090  for (unsigned int a = 0; a < attList->getLength(); a++)
1091  {
1092  DOMNode* att = attList->item(a);
1093  XtString typeS(att->getNodeValue());
1094  XtString nameS(att->getNodeName());
1095  XtString nameStr(nameS);
1096  if (rep > 1)
1097  {
1098  nameStr = "in[m]." + nameS;
1099  }
1100  if (typeS == "int")
1101  {
1102  cFile << " if (! xdr_int(xdrs,&this1->"
1103  << nameStr << "))" << std::endl
1104  << " XDRerror();" << std::endl;
1105  }
1106  else if (typeS == "long")
1107  {
1108  cFile << "#ifndef XDR_LONGLONG_MISSING" << std::endl
1109  << " if (! xdr_longlong_t(xdrs,&this1->"
1110  << nameStr << "))" << std::endl
1111  << " XDRerror();" << std::endl
1112  << "#else" << std::endl
1113  << " {" << std::endl
1114  << " int* " << nameStr << "_ = "
1115  << "(int*)&this1->" << nameStr << ";" << std::endl
1116  << "# if __BIG_ENDIAN__" << std::endl
1117  << " if (! xdr_int(xdrs,&"
1118  << nameStr << "_[0]))" << std::endl
1119  << " XDRerror();" << std::endl
1120  << " if (! xdr_int(xdrs,&"
1121  << nameStr << "_[1]))" << std::endl
1122  << " XDRerror();" << std::endl
1123  << "# else" << std::endl
1124  << " if (! xdr_int(xdrs,&"
1125  << nameStr << "_[1]))" << std::endl
1126  << " XDRerror();" << std::endl
1127  << " if (! xdr_int(xdrs,&"
1128  << nameStr << "_[0]))" << std::endl
1129  << " XDRerror();" << std::endl
1130  << "# endif" << std::endl
1131  << " }" << std::endl
1132  << "#endif" << std::endl;
1133  }
1134  else if (typeS == "float")
1135  {
1136  cFile << " if (! xdr_float(xdrs,&this1->"
1137  << nameStr << "))" << std::endl
1138  << " XDRerror();" << std::endl;
1139  }
1140  else if (typeS == "double")
1141  {
1142  cFile << " if (! xdr_double(xdrs,&this1->"
1143  << nameStr << "))" << std::endl
1144  << " XDRerror();" << std::endl;
1145  }
1146  else if (typeS == "boolean")
1147  {
1148  cFile << " if (! xdr_bool(xdrs,&this1->"
1149  << nameStr << "))" << std::endl
1150  << " XDRerror();" << std::endl;
1151  }
1152  else if (typeS == "Particle_t")
1153  {
1154  cFile << " if (! xdr_int(xdrs,(int*)&this1->"
1155  << nameStr << "))" << std::endl
1156  << " XDRerror();" << std::endl;
1157  }
1158  else if (typeS == "string")
1159  {
1160  cFile << " this1->" << nameStr << " = 0;" << std::endl
1161  << " if (! xdr_string(xdrs, &this1->"
1162  << nameStr << ", hddm_" + classPrefix
1163  << "_stringsize))" << std::endl
1164  << " XDRerror();" << std::endl;
1165  cFile << " CHECK(this1->" << nameStr << ","
1166  << "\"string_t\");" << std::endl;
1167  }
1168  else if (typeS == "anyURI")
1169  {
1170  cFile << " this1->" << nameStr << " = 0;" << std::endl
1171  << " if (! xdr_string(xdrs, &this1->"
1172  << nameStr << ", hddm_" + classPrefix
1173  << "_stringsize))" << std::endl
1174  << " XDRerror();" << std::endl;
1175  cFile << " CHECK(this1->" << nameStr << ","
1176  << "\"string_t\");" << std::endl;
1177  }
1178  else
1179  {
1180  /* ignore attributes with unrecognized values */
1181  }
1182  }
1183 
1184  if (hasContents)
1185  {
1186  cFile << " for (p = 0; p < pop->popListLength; p++)" << std::endl
1187  << " {" << std::endl
1188  << " popNode* pnode = pop->popList[p];" << std::endl
1189  << " if (pnode)" << std::endl
1190  << " {" << std::endl
1191  << " int kid = pnode->inParent;" << std::endl
1192  << " ptr[kid] = pnode->unpacker(xdrs,pnode);"
1193  << std::endl
1194  << " }" << std::endl
1195  << " else" << std::endl
1196  << " {" << std::endl
1197  << " unsigned int skip;" << std::endl
1198  << " if (! xdr_u_int(xdrs,&skip))" << std::endl
1199  << " XDRerror();" << std::endl
1200  << " xdr_setpos64(xdrs,xdr_getpos64(xdrs)+skip);"
1201  << std::endl
1202  << " }" << std::endl
1203  << " }" << std::endl;
1204  }
1205  cFile << " }" << std::endl
1206  << " xdr_setpos64(xdrs,start+size);" << std::endl
1207  << " }" << std::endl
1208  << " return this1;" << std::endl
1209  << "}" << std::endl;
1210  }
1211 }
1212 
1213 /* Generate c function to read from binary stream into c-structures */
1214 
1215 void CodeBuilder::constructReadFunc(DOMElement* topEl)
1216 {
1217  XtString topS(topEl->getTagName());
1218  XtString topType = topS.simpleType();
1219  XtString topT(topType);
1220  topT.erase(topT.rfind('_'));
1221  hFile << std::endl
1222  << topType << "* read_" << topT
1223  << "(" << classPrefix << "_iostream_t* fp" << ");" << std::endl;
1224 
1225  cFile << std::endl
1226  << topType << "* read_" << topT
1227  << "(" << classPrefix << "_iostream_t* fp" << ")" << std::endl
1228  << "{" << std::endl
1229  << " off_t base;" << std::endl
1230  << " unsigned int size;" << std::endl
1231  << " xdrmem_create(fp->xdrs,fp->iobuffer,fp->iobuffer_size,XDR_DECODE);"
1232  << std::endl
1233  << " base = xdr_getpos64(fp->xdrs);" << std::endl
1234  << " if (fread(fp->iobuffer,1,4,fp->fd) != 4 || ! xdr_u_int(fp->xdrs,&size))"
1235  << std::endl
1236  << " {" << std::endl
1237  << " xdr_destroy(fp->xdrs);" << std::endl
1238  << " return 0;" << std::endl
1239  << " }" << std::endl
1240  << " else if (size == 1)" << std::endl
1241  << " {" << std::endl
1242  << " fprintf(stderr,\"hddm error - \"" << std::endl
1243  << " \"stream compression and/or integrity checks"
1244  " found in input stream.\\n\"" << std::endl
1245  << " \"These features are not supported by the"
1246  " hddm c i/o interface.\\n\");" << std::endl
1247  << " fprintf(stderr,\"You must use the c++ interface"
1248  " to read this file.\\n\");" << std::endl
1249  << " exit(9);" << std::endl
1250  << " }" << std::endl
1251  << " else if (size + 4 > fp->iobuffer_size)" << std::endl
1252  << " {" << std::endl
1253  << " xdr_destroy(fp->xdrs);" << std::endl
1254  << " char *newbuf = (char*)malloc(fp->iobuffer_size *= 2);"
1255  << std::endl
1256  << " memcpy(newbuf,fp->iobuffer,4);" << std::endl
1257  << " free(fp->iobuffer);" << std::endl
1258  << " fp->iobuffer = newbuf;" << std::endl
1259  << " xdrmem_create(fp->xdrs,fp->iobuffer,fp->iobuffer_size,XDR_DECODE);"
1260  << std::endl
1261  << " base = xdr_getpos64(fp->xdrs);" << std::endl
1262  << " }" << std::endl
1263  << " if (fread(fp->iobuffer+4,1,size,fp->fd) != size)" << std::endl
1264  << " {" << std::endl
1265  << " fprintf(stderr,\"hddm error - \"" << std::endl
1266  << " \"read failed on input hddm stream, \"" << std::endl
1267  << " \"cannot continue.\\n\");" << std::endl
1268  << " exit(9);" << std::endl
1269  << " }" << std::endl
1270  << " xdr_setpos64(fp->xdrs,base);" << std::endl
1271  << " " << topType << "* nextEvent = "
1272  << "unpack_" << topT << "(fp->xdrs,fp->popTop);" << std::endl
1273  << " xdr_destroy(fp->xdrs);" << std::endl
1274  << " return (nextEvent == HDDM_NULL)? 0 : nextEvent;" << std::endl
1275  << "}" << std::endl;
1276 }
1277 
1278 /* Generate c function to skip over events in the binary stream */
1279 
1281 {
1282  hFile << std::endl
1283  << "int skip_" << classPrefix << "_HDDM"
1284  << "(" << classPrefix << "_iostream_t* fp, int nskip);" << std::endl;
1285 
1286  cFile << std::endl
1287  << "int skip_" << classPrefix << "_HDDM"
1288  << "(" << classPrefix << "_iostream_t* fp, int nskip)" << std::endl
1289  << "{" << std::endl
1290  << " int skipped;" << std::endl
1291  << " for (skipped=0; skipped < nskip; ++skipped)" << std::endl
1292  << " {" << std::endl
1293  << " unsigned int size;" << std::endl
1294  << " xdrmem_create(fp->xdrs,fp->iobuffer,fp->iobuffer_size,XDR_DECODE);"
1295  << std::endl
1296  << " if (fread(fp->iobuffer,1,4,fp->fd) != 4 || ! xdr_u_int(fp->xdrs,&size))"
1297  << std::endl
1298  << " {" << std::endl
1299  << " break;" << std::endl
1300  << " }" << std::endl
1301  << " else if (size == 1)" << std::endl
1302  << " {" << std::endl
1303  << " fprintf(stderr,\"hddm error - \"" << std::endl
1304  << " \"stream compression and/or integrity "
1305  "checks found in input stream.\\n\"" << std::endl
1306  << " \"These features are not supported "
1307  "by the hddm c i/o interface.\\n\");" << std::endl
1308  << " fprintf(stderr,\"You must use the c++ "
1309  << "interface to read this file.\\n\");" << std::endl
1310  << " exit(9);" << std::endl
1311  << " }" << std::endl
1312  << " else if (size + 4 > fp->iobuffer_size)" << std::endl
1313  << " {" << std::endl
1314  << " xdr_destroy(fp->xdrs);" << std::endl
1315  << " char *newbuf = (char*)malloc(fp->iobuffer_size *= 2);"
1316  << std::endl
1317  << " memcpy(newbuf,fp->iobuffer,4);" << std::endl
1318  << " free(fp->iobuffer);" << std::endl
1319  << " fp->iobuffer = newbuf;" << std::endl
1320  << " xdrmem_create(fp->xdrs,fp->iobuffer,fp->iobuffer_size,XDR_DECODE);"
1321  << std::endl
1322  << " }" << std::endl
1323  << " if (fread(fp->iobuffer+4,1,size,fp->fd) != size)" << std::endl
1324  << " {" << std::endl
1325  << " fprintf(stderr,\"hddm error - \"" << std::endl
1326  << " \"read failed on input hddm stream, \"" << std::endl
1327  << " \"cannot continue.\\n\");" << std::endl
1328  << " exit(9);" << std::endl
1329  << " }" << std::endl
1330  << " }" << std::endl
1331  << " xdr_destroy(fp->xdrs);" << std::endl
1332  << " return skipped;" << std::endl
1333  << "}" << std::endl;
1334 }
1335 
1336 /* Generate streamers for packing c-structures onto a binary stream
1337  * and deleting them from memory when output is complete
1338  */
1339 
1341 {
1342  cFile << std::endl;
1343  std::vector<DOMElement*>::iterator iter;
1344  for (iter = tagList.begin(); iter != tagList.end(); iter++)
1345  {
1346  DOMElement* tagEl = *iter;
1347  XtString tagS(tagEl->getTagName());
1348  XtString listType = tagS.listType();
1349  XtString simpleType = tagS.simpleType();
1350 
1351  cFile << "static ";
1352 
1353  XtString tagType;
1354  XtString repS(tagEl->getAttribute(X("maxOccurs")));
1355  int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS));
1356  if (rep > 1)
1357  {
1358  tagType = listType;
1359  }
1360  else
1361  {
1362  tagType = simpleType;
1363  }
1364  XtString tagT(tagType);
1365  tagT.erase(tagT.rfind('_'));
1366  cFile << "int pack_" << tagT << "(XDR* xdrs, "
1367  << tagType << "* this1);" << std::endl;
1368  }
1369 
1370  for (iter = tagList.begin(); iter != tagList.end(); iter++)
1371  {
1372  DOMElement* tagEl = *iter;
1373  XtString tagS(tagEl->getTagName());
1374  XtString listType = tagS.listType();
1375  XtString simpleType = tagS.simpleType();
1376 
1377  cFile << std::endl << "static ";
1378 
1379  XtString tagType;
1380  XtString repS(tagEl->getAttribute(X("maxOccurs")));
1381  int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS));
1382  if (rep > 1)
1383  {
1384  tagType = listType;
1385  }
1386  else
1387  {
1388  tagType = simpleType;
1389  }
1390  XtString tagT(tagType);
1391  tagT.erase(tagT.rfind('_'));
1392  cFile << "int pack_" << tagT << "(XDR* xdrs, "
1393  << tagType << "* this1)" << std::endl
1394  << "{" << std::endl;
1395  if (rep > 1)
1396  {
1397  cFile << " int m=0;" << std::endl;
1398  }
1399  cFile << " unsigned int size=0;" << std::endl
1400  << " off_t base,start,end;" << std::endl
1401  << " base = xdr_getpos64(xdrs);" << std::endl;
1402  if (tagT.find("_HDDM") != tagT.npos)
1403  {
1404  cFile
1405  << " if (base == -1)" << std::endl
1406  << " {" << std::endl
1407  << " fprintf(stderr,\"hddm error - \"" << std::endl
1408  << " \"stream offset request failed "
1409  "on output hddm stream, \"" << std::endl
1410  << " \"cannot continue.\\n\");" << std::endl
1411  << " return -1;" << std::endl
1412  << " }" << std::endl;
1413  }
1414  cFile << " if (! xdr_u_int(xdrs,&size))" << std::endl
1415  << " XDRerror();" << std::endl
1416  << " start = xdr_getpos64(xdrs);" << std::endl
1417  << std::endl;
1418  if (rep > 1)
1419  {
1420  cFile << " if (! xdr_u_int(xdrs,&this1->mult))" << std::endl
1421  << " XDRerror();" << std::endl
1422  << " for (m = 0; m < this1->mult; m++)" << std::endl
1423  << " {" << std::endl;
1424  }
1425  else
1426  {
1427  cFile << " {" << std::endl;
1428  }
1429 
1430  DOMNamedNodeMap* attList = tagEl->getAttributes();
1431  for (unsigned int a = 0; a < attList->getLength(); a++)
1432  {
1433  DOMNode* att = attList->item(a);
1434  XtString typeS(att->getNodeValue());
1435  XtString nameS(att->getNodeName());
1436  XtString nameStr(nameS);
1437  if (rep > 1)
1438  {
1439  nameStr = "in[m]." + nameS;
1440  }
1441  if (typeS == "int")
1442  {
1443  cFile << " if (! xdr_int(xdrs,&this1->"
1444  << nameStr << "))" << std::endl
1445  << " XDRerror();" << std::endl;
1446  }
1447  if (typeS == "long")
1448  {
1449  cFile << "#ifndef XDR_LONGLONG_MISSING" << std::endl
1450  << " if (! xdr_longlong_t(xdrs,&this1->"
1451  << nameStr << "))" << std::endl
1452  << " XDRerror();" << std::endl
1453  << "#else" << std::endl
1454  << " {" << std::endl
1455  << " int* " << nameStr << "_ = "
1456  << "(int*)&this1->" << nameStr << ";" << std::endl
1457  << "# if __BIG_ENDIAN__" << std::endl
1458  << " if (! xdr_int(xdrs,&"
1459  << nameStr << "_[0]))" << std::endl
1460  << " XDRerror();" << std::endl
1461  << " if (! xdr_int(xdrs,&"
1462  << nameStr << "_[1]))" << std::endl
1463  << " XDRerror();" << std::endl
1464  << "# else" << std::endl
1465  << " if (! xdr_int(xdrs,&"
1466  << nameStr << "_[1]))" << std::endl
1467  << " XDRerror();" << std::endl
1468  << " if (! xdr_int(xdrs,&"
1469  << nameStr << "_[0]))" << std::endl
1470  << " XDRerror();" << std::endl
1471  << "# endif" << std::endl
1472  << " }" << std::endl
1473  << "#endif" << std::endl;
1474  }
1475  else if (typeS == "float")
1476  {
1477  cFile << " if (! xdr_float(xdrs,&this1->"
1478  << nameStr << "))" << std::endl
1479  << " XDRerror();" << std::endl;
1480  }
1481  else if (typeS == "double")
1482  {
1483  cFile << " if (! xdr_double(xdrs,&this1->"
1484  << nameStr << "))" << std::endl
1485  << " XDRerror();" << std::endl;
1486  }
1487  else if (typeS == "boolean")
1488  {
1489  cFile << " if (! xdr_bool(xdrs,&this1->"
1490  << nameStr << "))" << std::endl
1491  << " XDRerror();" << std::endl;
1492  }
1493  else if (typeS == "Particle_t")
1494  {
1495  cFile << " if (! xdr_int(xdrs,(int*)&this1->"
1496  << nameStr << "))" << std::endl
1497  << " XDRerror();" << std::endl;
1498  }
1499  else if (typeS == "string")
1500  {
1501  cFile << " if (! xdr_string(xdrs,&this1->"
1502  << nameStr << ", hddm_" + classPrefix
1503  << "_stringsize))" << std::endl
1504  << " XDRerror();" << std::endl;
1505  cFile << " FREE(this1->" << nameStr << ");" << std::endl;
1506  }
1507  else if (typeS == "anyURI")
1508  {
1509  cFile << " if (! xdr_string(xdrs,&this1->"
1510  << nameStr << ", hddm_" + classPrefix
1511  << "_stringsize))" << std::endl
1512  << " XDRerror();" << std::endl;
1513  cFile << " FREE(this1->" << nameStr << ");" << std::endl;
1514  }
1515  else
1516  {
1517  /* ignore attributes with unrecognized values */
1518  }
1519  }
1520 
1521  DOMNodeList* contList = tagEl->getChildNodes();
1522  for (unsigned int c = 0; c < contList->getLength(); c++)
1523  {
1524  DOMNode* cont = contList->item(c);
1525  short type = cont->getNodeType();
1526  if (type == DOMNode::ELEMENT_NODE)
1527  {
1528  DOMElement* contEl = (DOMElement*) cont;
1529  XtString nameS(contEl->getTagName());
1530  XtString reS(contEl->getAttribute(X("maxOccurs")));
1531  int re = (reS == "unbounded")? INT_MAX : atoi(S(reS));
1532  XtString contType;
1533  if (re > 1)
1534  {
1535  contType = nameS.listType();
1536  }
1537  else
1538  {
1539  contType = nameS.simpleType();
1540  }
1541  XtString contT(contType);
1542  contT.erase(contT.rfind('_'));
1543  cFile << " if (this1->"
1544  << ((rep > 1)? "in[m]." : "")
1545  << ((re > 1)? nameS.plural(): nameS) << " != ("
1546  << contType << "*)&hddm_" + classPrefix + "_nullTarget)"
1547  << std::endl
1548  << " {" << std::endl
1549 
1550  << " if (pack_" << contT << "(xdrs,this1->"
1551  << ((rep > 1)? "in[m]." : "")
1552  << ((re > 1)? nameS.plural() : nameS) << ") < 0) {"
1553  << std::endl
1554  << " return -1;" << std::endl
1555  << " }" << std::endl
1556  << " }" << std::endl
1557  << " else" << std::endl
1558  << " {" << std::endl
1559  << " int zero=0;" << std::endl
1560  << " if (! xdr_int(xdrs,&zero))" << std::endl
1561  << " XDRerror();" << std::endl
1562  << " }" << std::endl;
1563  }
1564  }
1565 
1566  cFile << " }" << std::endl
1567  << " end = xdr_getpos64(xdrs);" << std::endl
1568  << " xdr_setpos64(xdrs,base);" << std::endl
1569  << " size = end-start;" << std::endl;
1570  if (tagT.find("_HDDM") != tagT.npos)
1571  {
1572  cFile
1573  << " if (size + 4 > hddm_" + classPrefix + "_buffersize) {"
1574  << std::endl
1575  << " fprintf(stderr,\"hddm error - \"" << std::endl
1576  << " \"output buffer overflow on hddm stream,"
1577  " cannot continue.\\n\");" << std::endl
1578  << " fprintf(stderr,\"Please increase buffer"
1579  " size using \"" << std::endl
1580  << " \"set_" + classPrefix + "_HDDM_buffersize(s) with"
1581  " s > %d.\", hddm_" + classPrefix + "_buffersize);"
1582  << std::endl
1583  << " exit(9);" << std::endl
1584  << " }" << std::endl;
1585  }
1586  cFile << " if (! xdr_u_int(xdrs,&size))" << std::endl
1587  << " XDRerror();" << std::endl
1588  << " xdr_setpos64(xdrs,end);" << std::endl
1589  << " FREE(this1);" << std::endl
1590  << " return size;" << std::endl
1591  << "}" << std::endl;
1592  }
1593 }
1594 
1595 /* Generate c functions for exporting c-structures onto a binary stream */
1596 
1598 {
1599  DOMElement* topEl = tagList[0];
1600  XtString topS(topEl->getTagName());
1601  XtString topType = topS.simpleType();
1602  XtString topT(topType);
1603  topT.erase(topT.rfind('_'));
1604 
1605  constructPackers();
1606 
1607  hFile << std::endl
1608  << "int flush_" << topT << "(" << topType << "* this1,"
1609  << classPrefix << "_iostream_t* fp" << ");" << std::endl;
1610 
1611  cFile << std::endl
1612  << "int flush_" << topT << "(" << topType << "* this1,"
1613  << classPrefix << "_iostream_t* fp" << ")" << std::endl
1614  << "{" << std::endl
1615  << " if (this1 == 0)" << std::endl
1616  << " {" << std::endl
1617  << " return 0;" << std::endl
1618  << " }" << std::endl
1619  << " else if (fp == 0)" << std::endl
1620  << " {" << std::endl
1621  << " XDR* xdrs = (XDR*)malloc(sizeof(XDR));" << std::endl
1622  << " char* dump = (char*)malloc(hddm_"
1623  + classPrefix + "_buffersize);" << std::endl
1624  << " xdrmem_create(xdrs,dump,hddm_"
1625  + classPrefix + "_buffersize,XDR_ENCODE);" << std::endl
1626  << " pack_" << topT << "(xdrs,this1);" << std::endl
1627  << " xdr_destroy(xdrs);" << std::endl
1628  << " free(xdrs);" << std::endl
1629  << " free(dump);" << std::endl
1630  << " }" << std::endl
1631  << " else if (fp->iomode == HDDM_STREAM_OUTPUT)" << std::endl
1632  << " {" << std::endl
1633  << " int size;" << std::endl
1634  << " xdrmem_create(fp->xdrs,fp->iobuffer,"
1635  "fp->iobuffer_size,XDR_ENCODE);" << std::endl
1636  << " size = pack_" + classPrefix + "_HDDM(fp->xdrs,this1);"
1637  << std::endl
1638  << " if (size < 0)" << std::endl
1639  << " {" << std::endl
1640  << " fp->lerrno = errno;" << std::endl
1641  << " xdr_destroy(fp->xdrs);" << std::endl
1642  << " return -1;" << std::endl
1643  << " }" << std::endl
1644  << " else if (size > 0)" << std::endl
1645  << " {" << std::endl
1646  << " int wsize = fwrite(fp->iobuffer,1,size+4,fp->fd);"
1647  << std::endl
1648  << " if (wsize != size + 4)" << std::endl
1649  << " {" << std::endl
1650  << " fprintf(stderr,\"HDDM Error: error writing to \""
1651  << std::endl
1652  << " \"output hddm file.\\n\");" << std::endl
1653  << " fprintf(stderr,\"%d bytes of %d "
1654  "actually written.\\n\"," << std::endl
1655  << " wsize, size+4);" << std::endl
1656  << " exit(9);" << std::endl
1657  << " }" << std::endl
1658  << " }" << std::endl
1659  << " xdr_destroy(fp->xdrs);" << std::endl
1660  << " }" << std::endl
1661  << " return 0;" << std::endl
1662  << "}" << std::endl;
1663 }
1664 
1665 /* Generate c functions that match up corresponding elements between
1666  * the c structures and the data model that appears on the input
1667  * binary stream. If successful, these routines build a hierarchical
1668  * structure (the "pop tree") that gives directions to the unpackers.
1669  *
1670  * The matching rules are as follows:
1671  *
1672  * 1) The attribute list for any given tag must be identical in content
1673  * and order wherever it appears, otherwise there is a collision.
1674  *
1675  * 2) The content list for any given tag must be internally consistent
1676  * within each model, but there are no requirements for agreement
1677  * between the c-structures and the binary stream models. Only the
1678  * contents which appear in both models will be unpacked, however.
1679  */
1680 
1682 {
1683  cFile << std::endl
1684  << "static int getTag(char* d, char* tag)" << std::endl
1685  << "{" << std::endl
1686  << " int level;" << std::endl
1687  << " char* token;" << std::endl
1688  << " char line[500];" << std::endl
1689  << " strncpy(line,d,500);" << std::endl
1690  << " line[499] = 0;" << std::endl
1691  << " level = index(line,'<')-line;" << std::endl
1692  << " if (level < 500 &&" << std::endl
1693  << " (token = strtok(line+level+1,\" >\")))" << std::endl
1694  << " {" << std::endl
1695  << " strncpy(tag,token,500);" << std::endl
1696  << " return level/2;" << std::endl
1697  << " }" << std::endl
1698  << " return -1;" << std::endl
1699  << "}" << std::endl
1700  << std::endl
1701  << "static char* getEndTag(char* d, char* tag)" << std::endl
1702  << "{" << std::endl
1703  << " char line[500];" << std::endl
1704  << " char endTag[510];" << std::endl
1705  << " strncpy(line,d,500);" << std::endl
1706  << " line[499] = 0;" << std::endl
1707  << " if (strstr(strtok(line,\"\\n\"),\"/>\") == 0)" << std::endl
1708  << " {" << std::endl
1709  << " sprintf(endTag,\"</%s>\",tag);" << std::endl
1710  << " }" << std::endl
1711  << " else" << std::endl
1712  << " {" << std::endl
1713  << " strcpy(endTag,\"/>\");" << std::endl
1714  << " }" << std::endl
1715  << " return strstr(d,endTag);" << std::endl
1716  << "}" << std::endl
1717  << std::endl
1718  << "static void collide(char* b, char* c)" << std::endl
1719  << "{" << std::endl
1720  << " char btag[500];" << std::endl
1721  << " getTag(b,btag);" << std::endl
1722  << " b = index(b,'<');" << std::endl
1723  << " c = index(c,'<');" << std::endl
1724  << " *(index(b,'\\n')) = 0;" << std::endl
1725  << " *(index(c,'\\n')) = 0;" << std::endl
1726  << " fprintf(stderr,\"HDDM warning: \");" << std::endl
1727  << " fprintf(stderr,\"tag %s in input file \", btag);" << std::endl
1728  << " fprintf(stderr,\"does not match c header hddm_"
1729  << classPrefix << ".h\\n\");" << std::endl
1730  << " fprintf(stderr,\" input file: %s\\n\", b);" << std::endl
1731  << " fprintf(stderr,\" c header: %s\\n\", c);" << std::endl
1732  << " fprintf(stderr,\" === Tag %s will be ignored,\", btag);"
1733  << std::endl
1734  << " fprintf(stderr,\" rebuild to cure the problem ===\\n\");"
1735  << std::endl
1736  << " *(index(b,0)) = '\\n';" << std::endl
1737  << " *(index(c,0)) = '\\n';" << std::endl
1738  << "}" << std::endl
1739  << std::endl
1740  << "static int tag_strncmp(char* a, char* b, int len)" << std::endl
1741  << "{" << std::endl
1742  << " if (strncmp(a,b,len) == 0) {" << std::endl
1743  << " return 0;" << std::endl
1744  << " }" << std::endl
1745  << " else {" << std::endl
1746  << " for (; *a == *b; ++a, ++b, --len) {}" << std::endl
1747  << " for (; *a == ' '; ++a, --len) {}" << std::endl
1748  << " for (; *a == '/'; ++a, --len) {}" << std::endl
1749  << " for (; *b == ' '; ++b) {}" << std::endl
1750  << " for (; *b == '/'; ++b) {}" << std::endl
1751  << " return strncmp(a,b,len);" << std::endl
1752  << " }" << std::endl
1753  << "}" << std::endl
1754  << std::endl
1755  << "static popNode* matches(char* b, char* c)" << std::endl
1756  << "{" << std::endl
1757  << " char btag[500];" << std::endl
1758  << " char ctag[500];" << std::endl
1759  << " int blevel, clevel;" << std::endl
1760  << " int ptrSeqNo = 0;" << std::endl
1761  << " blevel = getTag(b,btag);" << std::endl
1762  << " while ((clevel = getTag(c,ctag)) == blevel)" << std::endl
1763  << " {" << std::endl
1764  << " if "
1765  << "((clevel == blevel) && (strcmp(ctag,btag) == 0))" << std::endl
1766  << " {" << std::endl
1767  << " popNode* this1 = "
1768  << "(popNode*)malloc(sizeof(popNode));" << std::endl
1769  << " int len = index(c+1,'\\n') - c;" << std::endl
1770  << " if (tag_strncmp(c,b,len) != 0)" << std::endl
1771  << " {" << std::endl
1772  << " collide(b,c);" << std::endl
1773  << " free(this1);" << std::endl
1774  << " return 0;" << std::endl
1775  << " }" << std::endl;
1776 
1777  std::vector<DOMElement*>::iterator iter;
1778  for (iter = tagList.begin(); iter != tagList.end(); iter++)
1779  {
1780  XtString tagS((*iter)->getTagName());
1781  XtString repS((*iter)->getAttribute(X("maxOccurs")));
1782  int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS));
1783  XtString tagType;
1784  if (rep > 1)
1785  {
1786  tagType = tagS.listType();
1787  }
1788  else
1789  {
1790  tagType = tagS.simpleType();
1791  }
1792  XtString tagT(tagType);
1793  tagT.erase(tagT.rfind('_'));
1794 
1795  cFile << " else if "
1796  << "(strcmp(btag,\"" << tagS << "\") == 0)" << std::endl
1797  << " {" << std::endl
1798  << " this1->unpacker = "
1799  << "(void*(*)(XDR*,popNode*))"
1800  << "unpack_" << tagT << ";" << std::endl
1801  << " }" << std::endl;
1802  }
1803 
1804  cFile << " this1->inParent = ptrSeqNo;" << std::endl
1805  << " this1->popListLength = 0;" << std::endl
1806  << " c = index(c+1,'\\n');" << std::endl
1807  << " b = index(b+1,'\\n');" << std::endl
1808  << " while (getTag(b,btag) > blevel)" << std::endl
1809  << " {" << std::endl
1810  << " this1->popList[this1->popListLength++] = matches(b,c);"
1811  << std::endl
1812  << " if (this1->popListLength > "
1813  << MAX_POPLIST_LENGTH << ")" << std::endl
1814  << " {" << std::endl
1815  << " fprintf(stderr,"
1816  << "\"hddm error - popList overflow.\\n\");" << std::endl
1817  << " fprintf(stderr,"
1818  << "\"Increase MAX_POPLIST_LENGTH and recompile.\\n\");" << std::endl
1819  << " exit(9);" << std::endl
1820  << " }" << std::endl
1821  << " b = getEndTag(b,btag);" << std::endl
1822  << " b = index(b+1,'\\n');" << std::endl
1823  << " }" << std::endl
1824  << " return this1;" << std::endl
1825  << " }" << std::endl
1826  << " else" << std::endl
1827  << " {" << std::endl
1828  << " c = getEndTag(c,ctag);" << std::endl
1829  << " c = index(c+1,'\\n');" << std::endl
1830  << " ++ptrSeqNo;" << std::endl
1831  << " }" << std::endl
1832  << " }" << std::endl
1833  << " return 0;" << std::endl
1834  << "}" << std::endl;
1835 }
1836 
1837 /* Generate c code to open a hddm file for reading */
1838 
1840 {
1841  XtString tagS(el->getTagName());
1842  XtString tagType = tagS.simpleType();
1843  XtString tagT(tagType);
1844  tagT.erase(tagT.rfind('_'));
1845  hFile << std::endl
1846  << classPrefix << "_iostream_t* "
1847  << "open_" << tagT << "(char* filename);" << std::endl;
1848 
1849  writeMatcher();
1850 
1851  cFile << std::endl
1852  << classPrefix << "_iostream_t* "
1853  << "open_" << tagT << "(char* filename)" << std::endl
1854  << "{" << std::endl
1855  << " " << classPrefix << "_iostream_t* fp = "
1856  << "(" << classPrefix << "_iostream_t*)"
1857  << "malloc(sizeof(" << classPrefix << "_iostream_t));" << std::endl
1858  << " char* p;" << std::endl
1859  << " char* head;" << std::endl
1860  << " char* nullfilename=(char*)\"\";" << std::endl
1861  << " if (filename)" << std::endl
1862  << " {" << std::endl
1863  << " fp->fd = fopen(filename,\"r\");" << std::endl
1864  << " }" << std::endl
1865  << " else" << std::endl
1866  << " {" << std::endl
1867  << " fp->fd = fdopen(0,\"r\");" << std::endl
1868  << " filename = nullfilename;" << std::endl
1869  << " }" << std::endl
1870  << " if (fp->fd == 0)" << std::endl
1871  << " {" << std::endl
1872  << " free(fp);" << std::endl
1873  << " return 0;" << std::endl
1874  << " }" << std::endl
1875  << " fp->iomode = HDDM_STREAM_INPUT;" << std::endl
1876  << " head = (char*)malloc(hddm_" + classPrefix + "_headersize);"
1877  << std::endl
1878  << " if ((fgets(head,7,fp->fd) != 0) &&" << std::endl
1879  << " (strstr(head,\"<HDDM \") != head))" << std::endl
1880  << " {" << std::endl
1881  << " fprintf(stderr,\"HDDM Error: input file \");" << std::endl
1882  << " fprintf(stderr,\"file does not have a \");" << std::endl
1883  << " fprintf(stderr,\"valid HDDM header.\");" << std::endl
1884  << " fprintf(stderr,\" Please check.\\n\");" << std::endl
1885  << " exit(9);" << std::endl
1886  << " }" << std::endl
1887  << " for (p = head+6;" << std::endl
1888  << " strstr(head,\"</HDDM>\") == 0;" << std::endl
1889  << " p += strlen(p))" << std::endl
1890  << " {" << std::endl
1891  << " if (p-head + 10 > hddm_" + classPrefix + "_headersize)"
1892  << std::endl
1893  << " {" << std::endl
1894  << " fprintf(stderr,\"HDDM Error: \");" << std::endl
1895  << " fprintf(stderr,\"input template model overflows \""
1896  << std::endl
1897  << " \"the hddm header input buffer, cannot continue.\\n\");"
1898  << std::endl
1899  << " fprintf(stderr,\"Please increase header"
1900  " buffer size using \"" << std::endl
1901  << " \"set_" + classPrefix + "_HDDM_headersize(s) with "
1902  "s > %d.\\n\", hddm_" + classPrefix + "_headersize);"
1903  << std::endl
1904  << " exit(9);" << std::endl
1905  << " }" << std::endl
1906  << " if (fgets(p,1000,fp->fd) == 0)" << std::endl
1907  << " {" << std::endl
1908  << " break;" << std::endl
1909  << " }" << std::endl
1910  << " }" << std::endl
1911  << " fp->popTop = matches(head,HDDM_" << classPrefix
1912  << "_DocumentString);" << std::endl
1913  << " free(head);" << std::endl
1914  << " if (fp->popTop == 0"
1915  << " || fp->popTop->popListLength == 0)" << std::endl
1916  << " {" << std::endl
1917  << " fprintf(stderr,\"HDDM Error: \");" << std::endl
1918  << " fprintf(stderr,\"input template model \");" << std::endl
1919  << " fprintf(stderr,\"does not match c header.\");" << std::endl
1920  << " fprintf(stderr,\" Please recompile.\\n\");" << std::endl
1921  << " exit(9);" << std::endl
1922  << " }" << std::endl
1923  << " fp->filename = "
1924  << "(char*)malloc(strlen(filename) + 1);" << std::endl
1925  << " strcpy(fp->filename,filename);" << std::endl
1926  << " fp->xdrs = (XDR*)malloc(sizeof(XDR));" << std::endl
1927  << " fp->iobuffer = (char*)malloc(fp->iobuffer_size"
1928  " = hddm_" + classPrefix + "_buffersize);" << std::endl
1929  << " return fp;" << std::endl
1930  << "}" << std::endl;
1931 }
1932 
1933 /* Generate the c code to open a hddm file for writing */
1934 
1936 {
1937  XtString tagS(el->getTagName());
1938  XtString tagType = tagS.simpleType();
1939  XtString tagT(tagType);
1940  tagT.erase(tagT.rfind('_'));
1941  hFile << std::endl
1942  << classPrefix << "_iostream_t* "
1943  << "init_" << tagT << "(char* filename);" << std::endl;
1944  cFile << std::endl
1945  << classPrefix << "_iostream_t* "
1946  << "init_" << tagT << "(char* filename)" << std::endl
1947  << "{" << std::endl
1948  << " int len;" << std::endl
1949  << " char* head;" << std::endl
1950  << " char* nullfilename=(char*)\"\";" << std::endl
1951  << " " << classPrefix << "_iostream_t* fp = "
1952  << "(" << classPrefix << "_iostream_t*)"
1953  << "malloc(sizeof(" << classPrefix << "_iostream_t));" << std::endl
1954  << " if (filename)" << std::endl
1955  << " {" << std::endl
1956  << " fp->fd = fopen(filename,\"w\");" << std::endl
1957  << " }" << std::endl
1958  << " else" << std::endl
1959  << " {" << std::endl
1960  << " fp->fd = fdopen(1,\"w\");" << std::endl
1961  << " filename = nullfilename;" << std::endl
1962  << " }" << std::endl
1963  << " if (fp->fd == 0)" << std::endl
1964  << " {" << std::endl
1965  << " free(fp);" << std::endl
1966  << " return 0;" << std::endl
1967  << " }" << std::endl
1968  << " fp->iomode = HDDM_STREAM_OUTPUT;" << std::endl
1969  << " len = strlen(HDDM_"
1970  << classPrefix << "_DocumentString);" << std::endl
1971  << " head = (char*)malloc(len+1);" << std::endl
1972  << " strcpy(head,HDDM_"
1973  << classPrefix << "_DocumentString);" << std::endl
1974  << " if (fwrite(head,1,len,fp->fd) != len)" << std::endl
1975  << " {" << std::endl
1976  << " fprintf(stderr,\"HDDM Error: \");" << std::endl
1977  << " fprintf(stderr,\"error writing to \");" << std::endl
1978  << " fprintf(stderr,\"output file %s\\n\",filename);" << std::endl
1979  << " exit(9);" << std::endl
1980  << " }" << std::endl
1981  << " fp->filename = "
1982  << "(char*)malloc(strlen(filename) + 1);" << std::endl
1983  << " strcpy(fp->filename,filename);" << std::endl
1984  << " fp->popTop = 0;" << std::endl
1985  << " fp->xdrs = (XDR*)malloc(sizeof(XDR));" << std::endl
1986  << " fp->iobuffer = (char*)malloc(fp->iobuffer_size"
1987  " = hddm_" + classPrefix + "_buffersize);" << std::endl
1988  << " free(head);" << std::endl
1989  << " return fp;" << std::endl
1990  << "}" << std::endl;
1991 }
1992 
1993 /* Generate the c code to close an open hddm file */
1994 
1996 {
1997  XtString tagS(el->getTagName());
1998  XtString tagType = tagS.simpleType();
1999  XtString tagT(tagType);
2000  tagT.erase(tagT.rfind('_'));
2001  hFile << std::endl
2002  << "void close_" << tagT << "("
2003  << classPrefix << "_iostream_t* fp);" << std::endl;
2004 
2005  cFile << std::endl
2006  << "static void popaway(popNode* p)" << std::endl
2007  << "{" << std::endl
2008  << " if (p)" << std::endl
2009  << " {" << std::endl
2010  << " int n;" << std::endl
2011  << " for (n = 0; n < p->popListLength; n++)" << std::endl
2012  << " {" << std::endl
2013  << " popaway(p->popList[n]);" << std::endl
2014  << " }" << std::endl
2015  << " free(p);" << std::endl
2016  << " }" << std::endl
2017  << "}" << std::endl
2018  << std::endl
2019  << "void close_" << tagT
2020  << "(" << classPrefix << "_iostream_t* fp)" << std::endl
2021  << "{" << std::endl
2022  << " free(fp->xdrs);" << std::endl
2023  << " free(fp->iobuffer);" << std::endl
2024  << " fclose(fp->fd);" << std::endl
2025  << " free(fp->filename);" << std::endl
2026  << " popaway(fp->popTop);" << std::endl
2027  << " free(fp);" << std::endl
2028  << "}" << std::endl;
2029 }
2030 
2031 /* Generate the xml template in normal form and store in a string */
2032 
2034 {
2035  static int indent = 0;
2036  cFile << "\"";
2037  for (int n = 0; n < indent; n++)
2038  {
2039  cFile << " ";
2040  }
2041 
2042  XtString tagS(el->getTagName());
2043  cFile << "<" << tagS;
2044  DOMNamedNodeMap* attrList = el->getAttributes();
2045  int attrListLength = attrList->getLength();
2046  for (int a = 0; a < attrListLength; a++)
2047  {
2048  DOMNode* node = attrList->item(a);
2049  XtString nameS(node->getNodeName());
2050  XtString valueS(node->getNodeValue());
2051  cFile << " " << nameS << "=\\\"" << valueS << "\\\"";
2052  }
2053 
2054  DOMNodeList* contList = el->getChildNodes();
2055  int contListLength = contList->getLength();
2056  if (contListLength > 0)
2057  {
2058  cFile << ">\\n\"" << std::endl;
2059  indent++;
2060  for (int c = 0; c < contListLength; c++)
2061  {
2062  DOMNode* node = contList->item(c);
2063  if (node->getNodeType() == DOMNode::ELEMENT_NODE)
2064  {
2065  DOMElement* contEl = (DOMElement*) node;
2066  constructDocument(contEl);
2067  }
2068  }
2069  indent--;
2070  cFile << "\"";
2071  for (int n = 0; n < indent; n++)
2072  {
2073  cFile << " ";
2074  }
2075  cFile << "</" << tagS << ">\\n\"" << std::endl;
2076  }
2077  else
2078  {
2079  cFile << " />\\n\"" << std::endl;
2080  }
2081 }
void constructGroup(DOMElement *el)
Definition: hddm-c.cpp:804
#define MAX_POPLIST_LENGTH
Definition: hddm-c.cpp:69
XString classPrefix
Definition: hddm-c.cpp:88
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
char string[256]
void constructConstructors()
Definition: hddm-c.cpp:838
#define c
xercesc::DOMDocument * buildDOMDocument(const XString &xmlFile, bool keep)
Definition: XParsers.cpp:142
void checkConsistency(DOMElement *el, DOMElement *elref)
Definition: hddm-c.cpp:598
std::ofstream cFile
Definition: hddm-c.cpp:126
XtString(const XString &x)
Definition: hddm-c.cpp:111
void constructCloseFunc(DOMElement *el)
Definition: hddm-c.cpp:1995
std::vector< DOMElement * > tagList
Definition: hddm-c.cpp:147
void usage()
Definition: t_rest.cxx:114
XtString(const XMLCh *p)
Definition: hddm-c.cpp:109
xercesc::DOMDocument * parseInputDocument(const XString &xmlFile, bool keep)
Definition: XParsers.cpp:73
#define X(str)
Definition: hddm-c.cpp:83
void writeMatcher()
Definition: hddm-c.cpp:1681
void constructOpenFunc(DOMElement *el)
Definition: hddm-c.cpp:1839
std::ofstream hFile
Definition: hddm-c.cpp:125
XtString simpleType()
Definition: hddm-c.cpp:576
XtString(const XtString &t)
Definition: hddm-c.cpp:112
void constructReadFunc(DOMElement *topEl)
Definition: hddm-c.cpp:1215
XtString plural()
Definition: hddm-c.cpp:542
void constructSkipFunc()
Definition: hddm-c.cpp:1280
void constructInitFunc(DOMElement *el)
Definition: hddm-c.cpp:1935
XtString listType()
Definition: hddm-c.cpp:587
void constructUnpackers()
Definition: hddm-c.cpp:1009
#define S(str)
Definition: hddm-c.cpp:84
~CodeBuilder()
Definition: hddm-c.cpp:129
void constructDocument(DOMElement *el)
Definition: hddm-c.cpp:2033
XtString(const char *s)
Definition: hddm-c.cpp:108
void constructFlushFunc(DOMElement *el)
Definition: hddm-c.cpp:1597
XtString()
Definition: hddm-c.cpp:107
void constructPackers()
Definition: hddm-c.cpp:1340
XtString(const std::string &s)
Definition: hddm-c.cpp:110
void writeHeader(DOMElement *el)
Definition: hddm-c.cpp:705
int main(int argc, char *argv[])
Definition: gendoc.cc:6