/* * hddm-c : tool that reads in a HDDM document (Hall D Data Model) * and writes a c header file that embodies the model in * c structures. It also generates an input/output pair * of functions to translate the model between the memory * representation and a default binary representation that * is suitable for passing over a pipe or storing on disk. * * Version 1.2 - Richard Jones, December 2005. * - Updated code to use STL strings and vectors instead of old c-style * pre-allocated arrays and strXXX functions. * - Moved functions into classes grouped by function for better clarity. * * Version 1.1 - Richard Jones, September 2003. * - Updated code to work with the new DOM-2 implementation Xerces-c * from apache.org. Significant changes have taken place in the API * since DOM-1. * - Added support for new types "long" (int64), "string" (char arrays of * arbitrary length), and "anyURI" (special case of string). * - Switched from native encoding to the use of the XDR library to make * hddm files machine-independent. * * Original version - Richard Jones, May 25 2001. * * * Programmer's Notes: * ------------------- * 1. The HDDM specification describes data files using xml. For * information about the contents and structure of HDDM documents * see the web page that describes the data model. * * 2. Access by hddm-c to the xml source is through the industry- * standard Document Object Model (DOM) interface. * * 3. The code has been tested with the xerces-c DOM implementation from * Apache, and is intended to be used with the xerces-c library. * * 4. Output is sent to .h and .c where is * by default "hddm" and can be changed with the -o option. * * 5. As a by-product of using the DOM parser to access the xml source, * hddm-c verifies the source for well-formedness. Therefore it may * also be used to check the xml data model document. * * * Implementation Notes: * --------------------- * 1. The binary stream consists of the hddm data model in the form * of a well-formed xml header, followed by binary data. * * 2. The binary data consist of a sequence of event records, which are * repetitions of the basic data model in a serial representation. * * 3. Each element is output to the stream in the order it appears in * the data model, prefixed by an exclusive byte count. * * 4. Any c application compiled with the hddm header file that is * generated by hddm-c is able to read any hddm binary file that * was written using the same hddm class, ie. the * document tags must be a non-colliding set (see matching rules). * * 5. The input/output features of the c library produced by hddm-c * are implemented using the xdr binary i/o library written originally * by Sun Microsystems. This library provides basic serialization/ * deserialization of binary data using network byte-ordering * (RFC-1832) and is a part of many unix installations. */ #define MAX_POPLIST_LENGTH 99 #include "XString.hpp" #include "XParsers.hpp" #include #include #include #include #include #include #include #define X(str) XString(str).unicode_str() #define S(str) str.c_str() using namespace xercesc; XString classPrefix; void usage() { std::cerr << "\nUsage:\n" << " hddm-c [-v | -o ] {HDDM file}\n\n" << "Options:\n" << " -v validate only\n" << " -o write to .h" << std::endl; } class XtString : public XString { /* XString class with a few extra methods for creating type * strings that are useful in creating c structures */ public: XtString() {}; XtString(const char* s): XString(s) {}; XtString(const XMLCh* p): XString(p) {}; XtString(const std::string& s): XString(s) {}; XtString(const XString& x): XString(x) {}; XtString(const XtString& t): XString((XString&)t) {}; XtString plural(); XtString simpleType(); XtString listType(); }; class CodeBuilder { /* The methods in this class are used to write the c code that * implements the hddm structures i/o library. */ public: std::ofstream hFile; std::ofstream cFile; CodeBuilder() {}; ~CodeBuilder() {}; void checkConsistency(DOMElement* el, DOMElement* elref); void writeHeader(DOMElement* el); void constructGroup(DOMElement* el); void constructConstructors(); void constructUnpackers(); void constructReadFunc(DOMElement* topEl); void constructSkipFunc(); void constructPackers(); void constructFlushFunc(DOMElement* el); void writeMatcher(); void constructOpenFunc(DOMElement* el); void constructInitFunc(DOMElement* el); void constructCloseFunc(DOMElement* el); void constructDocument(DOMElement* el); private: std::vector tagList; }; int main(int argC, char* argV[]) { try { XMLPlatformUtils::Initialize(); } catch (const XMLException* toCatch) { XtString msg(toCatch->getMessage()); std::cerr << "hddm-c: Error during initialization! :\n" << msg << std::endl; return 1; } if (argC < 2) { usage(); return 1; } else if ((argC == 2) && (strcmp(argV[1], "-?") == 0)) { usage(); return 2; } XtString xmlFile; XtString hFilename; bool verifyOnly = false; int argInd; for (argInd = 1; argInd < argC; argInd++) { if (argV[argInd][0] != '-') { break; } if (strcmp(argV[argInd],"-v") == 0) { verifyOnly = true; } else if (strcmp(argV[argInd],"-o") == 0) { hFilename = XtString(argV[++argInd]); } else { std::cerr << "Unknown option \'" << argV[argInd] << "\', ignoring it\n" << std::endl; } } if (argInd != argC - 1) { usage(); return 1; } xmlFile = XtString(argV[argInd]); #if defined OLD_STYLE_XERCES_PARSER DOMDocument* document = parseInputDocument(xmlFile.c_str(),false); #else DOMDocument* document = buildDOMDocument(xmlFile.c_str(),false); #endif if (document == 0) { std::cerr << "hddm-c : Error parsing HDDM document, " << "cannot continue" << std::endl; return 1; } DOMElement* rootEl = document->getDocumentElement(); XtString rootS(rootEl->getTagName()); if (rootS != "HDDM") { std::cerr << "hddm-c error: root element of input document is " << "\"" << rootS << "\", expected \"HDDM\"" << std::endl; return 1; } XtString classS(rootEl->getAttribute(X("class"))); classPrefix = classS; XtString hname; if (verifyOnly) { hname = "/dev/null"; } else if (hFilename.size()) { hname = hFilename + ".h"; } else { hname = "hddm_" + classPrefix + ".h"; } CodeBuilder builder; builder.hFile.open(hname.c_str()); if (! builder.hFile.is_open()) { std::cerr << "hddm-c error: unable to open output file " << hname << std::endl; return 1; } XtString cname; if (verifyOnly) { cname = "/dev/null"; } else if (hFilename.size()) { cname = hFilename + ".c"; } else { cname = "hddm_" + classPrefix + ".c"; } builder.cFile.open(cname.c_str()); if (! builder.cFile.is_open()) { std::cerr << "hddm-c error: unable to open output file " << cname << std::endl; return 1; } builder.hFile << "/*" << std::endl << " * " << hname << " - DO NOT EDIT THIS FILE" << std::endl << " *" << std::endl << " * This file was generated automatically by hddm-c" << " from the file" << std::endl << " * " << xmlFile << std::endl << std::endl << " * This header file defines the c structures that" << " hold the data" << std::endl << " * described in the data model" << " (from " << xmlFile << "). " << std::endl << " *" << std::endl << " * The hddm data model tool set was written by" << std::endl << " * Richard Jones, University of Connecticut." << std::endl << " *" << std::endl << " * For more information see the following web site"<< std::endl << " *" << std::endl << " * http://zeus.phys.uconn.edu/halld/datamodel/doc" << std::endl << " *" << std::endl << " */" << std::endl << std::endl; builder.cFile << "/*" << std::endl << " * " << cname << " - DO NOT EDIT THIS FILE" << std::endl << " *" << std::endl << " * This file was generated automatically by hddm-c" << " from the file" << std::endl << " * " << xmlFile << std::endl << std::endl << " * This c file contains the i/o interface to" << " the c structures" << std::endl << " * described in the data model" << " (from " << xmlFile << "). " << std::endl << " *" << std::endl << " * The hddm data model tool set was written by" << std::endl << " * Richard Jones, University of Connecticut." << std::endl << " *" << std::endl << " * For more information see the following web site"<< std::endl << " *" << std::endl << " * http://zeus.phys.uconn.edu/halld/datamodel/doc" << std::endl << " */" << std::endl << std::endl; builder.hFile << "#include " << std::endl << "#include " << std::endl << "#include " << std::endl << "#include " << std::endl << "#include " << std::endl << "#include " << std::endl << "#include " << std::endl << std::endl << "typedef char* string_t; " << "// use this alias for string-valued attributes" << std::endl << std::endl << "/* Note to users: The option MALLOC_FREE_WITH_MEMCHECK" << std::endl << " * was created for debugging this hddm library, but it" << std::endl << " * is also useful for finding memory leaks in user" << std::endl << " * code. To use it, replace malloc(n) everywhere in" << std::endl << " * your code with MALLOC(n,\"some descriptive string\")" << std::endl << " * and free(p) with FREE(p) and include this header" << std::endl << " * and compile with -DMALLOC_FREE_WITH_MEMCHECK set." << std::endl << " * Any attempt to malloc memory already malloc'ed or" << std::endl << " * to free memory that has not yet been malloc'ed is" << std::endl << " * immediately flagged with an error message. A call" << std::endl << " * to checkpoint() anywhere in the user code reports" << std::endl << " * any memory that has been malloc'ed not freed." << std::endl << " */" << std::endl << "#if defined MALLOC_FREE_WITH_MEMCHECK" << std::endl << "# include " << std::endl << "# define MALLOC(N,S) (checkin(malloc(N),S))" << std::endl << "# define FREE(P) (checkout(P),free(P))" << std::endl << "#else" << std::endl << "# define MALLOC(N,S) malloc(N)" << std::endl << "# define FREE(P) free(P)" << std::endl << "#endif" << std::endl; builder.cFile << "int hddm_nullTarget=0;" << std::endl << "#define HDDM_NULL (void*)&hddm_nullTarget" << std::endl << std::endl << "#include \"" << hname << "\"" << std::endl << std::endl; builder.constructGroup(rootEl); builder.hFile << std::endl << "#ifdef __cplusplus" << std::endl << "extern \"C\" {" << std::endl << "#endif" << std::endl; builder.constructConstructors(); builder.hFile << std::endl << "#ifdef __cplusplus" << std::endl << "}" << std::endl << "#endif" << std::endl; builder.hFile << std::endl << "#ifndef " << classPrefix << "_DocumentString" << std::endl << "#define " << classPrefix << "_DocumentString" << std::endl << std::endl << "extern " << "char HDDM_" << classPrefix << "_DocumentString[];" << std::endl << std::endl << "#ifdef INLINE_PREPEND_UNDERSCORES" << std::endl << "#define inline __inline" << std::endl << "#endif" << std::endl << std::endl << "#endif /* " << classPrefix << "_DocumentString */" << std::endl; builder.cFile << std::endl << "char HDDM_" << classPrefix << "_DocumentString[]" << " = " << std::endl; builder.constructDocument(rootEl); builder.cFile << ";" << std::endl; builder.hFile << std::endl << "#ifndef HDDM_STREAM_INPUT" << std::endl << "#define HDDM_STREAM_INPUT -91" << std::endl << "#define HDDM_STREAM_OUTPUT -92" << std::endl << std::endl << "struct popNode_s {" << std::endl << " void* (*unpacker)(XDR*, struct popNode_s*);" << std::endl << " int inParent;" << std::endl << " int popListLength;" << std::endl << " struct popNode_s* popList[" << MAX_POPLIST_LENGTH << "];" << std::endl << "};" << std::endl << "typedef struct popNode_s popNode;" << std::endl << std::endl << "typedef struct {" << std::endl << " FILE* fd;" << std::endl << " int iomode;" << std::endl << " int lerrno;" << std::endl << " char* filename;" << std::endl << " XDR* xdrs;" << std::endl << " popNode* popTop;" << std::endl << "} " << classPrefix << "_iostream_t;" << std::endl << std::endl << "#endif /* HDDM_STREAM_INPUT */" << std::endl; builder.cFile << std::endl << "#ifndef _FILE_OFFSET_BITS" << std::endl << "# define _FILE_OFFSET_BITS 64" << std::endl << "#endif" << std::endl << std::endl << "static off_t xdr_getpos64(XDR *xdrs)" << std::endl << "{" << std::endl << " if (xdrs->x_base == 0) {" << std::endl << " return ftello((FILE *)xdrs->x_private);" << std::endl << " }" << std::endl << " off_t pos = xdr_getpos(xdrs);" << std::endl << " return pos;" << std::endl << "}" << std::endl << std::endl << "static bool_t xdr_setpos64(XDR *xdrs, off_t pos) " << std::endl << "{ " << std::endl << " if (xdrs->x_base == 0) {" << std::endl << " return ((fseeko((FILE *)xdrs->x_private, pos, 0) < 0)? FALSE : TRUE);" << std::endl << " }" << std::endl << " return xdr_setpos(xdrs,pos);" << std::endl << "}" << std::endl; builder.constructUnpackers(); builder.hFile << std::endl << "#ifdef __cplusplus" << std::endl << "extern \"C\" {" << std::endl << "#endif" << std::endl; builder.constructReadFunc(rootEl); builder.constructSkipFunc(); builder.constructFlushFunc(rootEl); builder.constructOpenFunc(rootEl); builder.constructInitFunc(rootEl); builder.constructCloseFunc(rootEl); builder.hFile << std::endl << "#ifdef __cplusplus" << std::endl << "}" << std::endl << "#endif" << std::endl << std::endl << "#if !defined HDDM_NULL" << std::endl << "extern int hddm_nullTarget;" << std::endl << "# define HDDM_NULL (void*)&hddm_nullTarget" << std::endl << "#endif" << std::endl; XMLPlatformUtils::Terminate(); return 0; } XtString XtString::plural() { XtString p(*this); XtString::size_type len = p.size(); if (len > 3 && p.substr(len-3,3) == "tum") { p.replace(len-3,3,"ta"); } else if (len > 1 && p.substr(len-3,3) == "ies") { p.replace(len-3,3,"iesList"); } else if (len > 2 && p.substr(len-2,2) == "ex") { p.replace(len-2,2,"ices"); } else if (len > 2 && p.substr(len-2,2) == "sh") { p.replace(len-2,2,"shes"); } else if (len > 1 && p.substr(len-1,1) == "s") { p.replace(len-1,1,"ses"); } else if (len > 1) { p += "s"; } return p; } /* Map from tag name to name of the corresponding c-structure * for the case of simple tags (those that do not repeat) */ XtString XtString::simpleType() { XtString p(*this); p[0] = toupper(p[0]); p = classPrefix + "_" + p + "_t"; return p; } /* Map from tag name to name of the corresponding c-structure * for the case of list tags (those that may repeat) */ XtString XtString::listType() { XtString r = plural(); r[0] = toupper(r[0]); r = classPrefix + "_" + r + "_t"; return r; } /* Verify that the tag group under this element does not collide * with existing tag group elref, otherwise exit with fatal error */ void CodeBuilder::checkConsistency(DOMElement* el, DOMElement* elref) { XtString tagS(el->getTagName()); if (el->getParentNode() == elref->getParentNode()) { std::cerr << "hddm-cpp error: tag " << "\"" << tagS << "\" is duplicated within one context in xml document." << std::endl; exit(1); } DOMNamedNodeMap* oldAttr = elref->getAttributes(); DOMNamedNodeMap* newAttr = el->getAttributes(); int listLength = oldAttr->getLength(); for (int n = 0; n < listLength; n++) { XtString nameS(oldAttr->item(n)->getNodeName()); XtString oldS(elref->getAttribute(X(nameS))); XtString newS(el->getAttribute(X(nameS))); if (nameS == "minOccurs") { continue; } else if (nameS == "maxOccurs") { int maxold = (oldS == "unbounded")? INT_MAX : atoi(S(oldS)); int maxnew = (newS == "unbounded")? INT_MAX : atoi(S(newS)); if (maxold < 2 && maxnew > 1 || maxold > 1 && maxnew < 2) { std::cerr << "hddm-c error: inconsistent maxOccurs usage by tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } } else if (newS != oldS) { std::cerr << "hddm-c error: inconsistent usage of attribute " << "\"" << nameS << "\" in tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } } listLength = newAttr->getLength(); for (int n = 0; n < listLength; n++) { XtString nameS(newAttr->item(n)->getNodeName()); XtString oldS(elref->getAttribute(X(nameS))); XtString newS(el->getAttribute(X(nameS))); if (nameS == "minOccurs") { continue; } else if (nameS == "maxOccurs") { int maxold = (oldS == "unbounded")? INT_MAX : atoi(S(oldS)); int maxnew = (newS == "unbounded")? INT_MAX : atoi(S(newS)); if (maxold < 2 && maxnew > 1 || maxold > 1 && maxnew < 2) { std::cerr << "hddm-c error: inconsistent maxOccurs usage by tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } } else if (newS != oldS) { std::cerr << "hddm-c error: inconsistent usage of attribute " << "\"" << nameS << "\" in tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } } DOMNodeList* oldList = elref->getChildNodes(); DOMNodeList* newList = el->getChildNodes(); listLength = oldList->getLength(); if (newList->getLength() != listLength) { std::cerr << "hddm-c error: inconsistent usage of tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } for (int n = 0; n < listLength; n++) { DOMNode* cont = oldList->item(n); XtString nameS(cont->getNodeName()); short type = cont->getNodeType(); if (type == DOMNode::ELEMENT_NODE) { DOMNodeList* contList = el->getElementsByTagName(X(nameS)); if (contList->getLength() != 1) { std::cerr << "hddm-c error: inconsistent usage of tag " << "\"" << tagS << "\" in xml document." << std::endl; exit(1); } } } } /* Write declaration of c-structure for this tag to c-header file */ void CodeBuilder::writeHeader(DOMElement* el) { XtString tagS(el->getTagName()); XtString ctypeDef = tagS.simpleType(); hFile << std::endl << "#ifndef SAW_" << ctypeDef << std::endl << "#define SAW_" << ctypeDef << std::endl << std::endl << "typedef struct {" << std::endl; DOMNamedNodeMap* varList = el->getAttributes(); int varCount = varList->getLength(); for (int v = 0; v < varCount; v++) { DOMNode* var = varList->item(v); XtString typeS(var->getNodeValue()); XtString nameS(var->getNodeName()); if (typeS == "int") { hFile << " int32_t " << nameS << ";" << std::endl; } else if (typeS == "long") { hFile << " int64_t " << nameS << ";" << std::endl; } else if (typeS == "float") { hFile << " float " << nameS << ";" << std::endl; } else if (typeS == "double") { hFile << " double " << nameS << ";" << std::endl; } else if (typeS == "boolean") { hFile << " bool_t " << nameS << ";" << std::endl; } else if (typeS == "string") { hFile << " string_t " << nameS << ";" << std::endl; } else if (typeS == "anyURI") { hFile << " string_t " << nameS << ";" << std::endl; } else if (typeS == "Particle_t") { hFile << " Particle_t " << nameS << ";" << std::endl; } else { /* ignore attributes with unrecognized values */ } } DOMNodeList* contList = el->getChildNodes(); int contLength = contList->getLength(); for (int c = 0; c < contLength; c++) { DOMNode* cont = contList->item(c); XtString nameS(cont->getNodeName()); short type = cont->getNodeType(); if (type == DOMNode::ELEMENT_NODE) { DOMElement* contEl = (DOMElement*) cont; XtString repS(contEl->getAttribute(X("maxOccurs"))); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); XtString ctypeRef = (rep > 1) ? nameS.listType() : nameS.simpleType(); XtString::size_type clen = ctypeRef.size(); hFile << " " << ctypeRef << "* "; for (int i = 0; i < 19-(int)clen; i++) { hFile << " "; } hFile << ((rep > 1) ? nameS.plural() : nameS) << ";" << std::endl; } } hFile << "} " << ctypeDef << ";" << std::endl; XtString repS(el->getAttribute(X("maxOccurs"))); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); if (rep > 1) { XtString ctypeRef = tagS.listType(); hFile << std::endl << "typedef struct {" << std::endl << " unsigned int mult;" << std::endl << " " << ctypeDef << " in[1];" << std::endl << "} " << ctypeRef << ";" << std::endl; } hFile << "#endif /* " << ctypeDef << " */" << std::endl; } /* Generate c-structure declarations for this tag and its descendants; * this function calls itself recursively */ void CodeBuilder::constructGroup(DOMElement* el) { XtString tagS(el->getTagName()); std::vector::iterator iter; for (iter = tagList.begin(); iter != tagList.end(); iter++) { XtString targS((*iter)->getTagName()); if (tagS == targS) { checkConsistency(el,*iter); return; } } tagList.push_back(el); DOMNodeList* contList = el->getChildNodes(); int contLength = contList->getLength(); for (int c = 0; c < contLength; c++) { DOMNode* cont = contList->item(c); short type = cont->getNodeType(); if (type == DOMNode::ELEMENT_NODE) { DOMElement* contEl = (DOMElement*) cont; constructGroup(contEl); } } writeHeader(el); } /* Generate c code for make__ functions */ void CodeBuilder::constructConstructors() { std::vector::iterator iter; for (iter = tagList.begin(); iter != tagList.end(); iter++) { DOMElement* tagEl = *iter; XtString tagS(tagEl->getTagName()); XtString listType = tagS.listType(); XtString simpleType = tagS.simpleType(); hFile << std::endl; cFile << std::endl; XtString repS = tagEl->getAttribute(X("maxOccurs")); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); if (rep > 1) { hFile << listType << "* "; cFile << listType << "* "; XtString listT(listType); listT.erase(listT.rfind('_')); hFile << "make_" << listT; cFile << "make_" << listT; hFile << "(int n);" << std::endl; cFile << "(int n)" << std::endl << "{" << std::endl << " int i;" << std::endl << " int rep = (n > 1) ? n-1 : 0;" << std::endl << " int size = sizeof(" << listType << ") + rep * sizeof(" << simpleType << ");" << std::endl << " " << listType << "* p = (" << listType << "*)MALLOC(size,\"" << listType << "\");" << std::endl << " p->mult = 0;" << std::endl << " for (i=0; iin[i];" << std::endl; DOMNamedNodeMap* varList = tagEl->getAttributes(); int varCount = varList->getLength(); for (int v = 0; v < varCount; v++) { DOMNode* var = varList->item(v); XtString typeS(var->getNodeValue()); XtString nameS(var->getNodeName()); if (typeS == "string" || typeS == "anyURI") { cFile << " pp->" << nameS << " = (string_t)&hddm_nullTarget;" << std::endl; } else if (typeS == "int" || typeS == "long" || typeS == "float" || typeS == "double" || typeS == "boolean") { cFile << " pp->" << nameS << " = 0;" << std::endl; } else if (typeS == "Particle_t") { cFile << " pp->" << nameS << " = (Particle_t)0;" << std::endl; } } DOMNodeList* contList = tagEl->getChildNodes(); for (int c = 0; c < contList->getLength(); c++) { DOMNode* cont = contList->item(c); short ctype = cont->getNodeType(); if (ctype == DOMNode::ELEMENT_NODE) { DOMElement* contEl = (DOMElement*) cont; XtString cnameS(contEl->getTagName()); XtString crepS(contEl->getAttribute(X("maxOccurs"))); int crep = (crepS == "unbounded")? INT_MAX : atoi(S(crepS)); if (crep > 1) { cFile << " pp->" << cnameS.plural() << " = (" << cnameS.listType() << "*)&hddm_nullTarget;" << std::endl; } else { cFile << " pp->" << cnameS << " = (" << cnameS.simpleType() << "*)&hddm_nullTarget;" << std::endl; } } } cFile << " }" << std::endl; } else { hFile << simpleType << "* "; cFile << simpleType << "* "; XtString simpleT(simpleType); simpleT.erase(simpleT.rfind('_')); hFile << "make_" << simpleT; cFile << "make_" << simpleT; hFile << "();" << std::endl; cFile << "()" << std::endl << "{" << std::endl << " int size = sizeof(" << simpleType << ");" << std::endl << " " << simpleType << "* p = " << "(" << simpleType << "*)MALLOC(size,\"" << simpleType << "\");" << std::endl; DOMNamedNodeMap* varList = tagEl->getAttributes(); int varCount = varList->getLength(); for (int v = 0; v < varCount; v++) { DOMNode* var = varList->item(v); XtString typeS(var->getNodeValue()); XtString nameS(var->getNodeName()); if (typeS == "string" || typeS == "anyURI") { cFile << " p->" << nameS << " = (string_t)&hddm_nullTarget;" << std::endl; } else if (typeS == "int" || typeS == "long" || typeS == "float" || typeS == "double" || typeS == "boolean") { cFile << " p->" << nameS << " = 0;" << std::endl; } else if (typeS == "Particle_t") { cFile << " p->" << nameS << " = (Particle_t)0;" << std::endl; } } DOMNodeList* contList = tagEl->getChildNodes(); for (int c = 0; c < contList->getLength(); c++) { DOMNode* cont = contList->item(c); short ctype = cont->getNodeType(); if (ctype == DOMNode::ELEMENT_NODE) { DOMElement* contEl = (DOMElement*) cont; XtString cnameS(contEl->getTagName()); XtString crepS(contEl->getAttribute(X("maxOccurs"))); int crep = (crepS == "unbounded")? INT_MAX : atoi(S(crepS)); if (crep > 1) { cFile << " p->" << cnameS.plural() << " = (" << cnameS.listType() << "*)&hddm_nullTarget;" << std::endl; } else { cFile << " p->" << cnameS << " = (" << cnameS.simpleType() << "*)&hddm_nullTarget;" << std::endl; } } } } cFile << " return p;" << std::endl << "}" << std::endl; } } /* Generate c functions for unpacking binary stream into c-structures */ void CodeBuilder::constructUnpackers() { cFile << std::endl; std::vector::iterator iter; for (iter = tagList.begin(); iter != tagList.end(); iter++) { DOMElement* tagEl = *iter; XtString tagS(tagEl->getTagName()); XtString listType = tagS.listType(); XtString simpleType = tagS.simpleType(); cFile << std::endl << "static "; XtString tagType; XtString repS = tagEl->getAttribute(X("maxOccurs")); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); if (rep > 1) { tagType = tagS.listType(); } else { tagType = tagS.simpleType(); } XtString tagT(tagType); tagT.erase(tagT.rfind('_')); cFile << tagType << "* unpack_" << tagT << "(XDR* xdrs, popNode* pop)" << std::endl << "{" << std::endl << " " << tagType << "* this1 = (" << tagType << "*)HDDM_NULL;" << std::endl << " unsigned int size;" << std::endl << " if (! xdr_u_int(xdrs,&size))" << std::endl << " {" << std::endl << " return this1;" << std::endl << " }" << std::endl << " else if (size == 1)" << std::endl << " {" << std::endl << " fprintf(stderr,\"hddm error - \"" << std::endl << " \"compressed data found in input stream.\\n\"" << std::endl << " \"Compression/decompression is not supported \"" << std::endl << " \"by the hddm c i/o interface.\\n\");" << std::endl << " fprintf(stderr,\"You must use the c++ \"" << std::endl << " \"interface to read this file.\\n\");" << std::endl << " exit(9);" << std::endl << " }" << std::endl << " else if (size > 0)" << std::endl << " {" << std::endl << " off_t start = xdr_getpos64(xdrs);" << std::endl; if (rep > 1) { cFile << " int m;" << std::endl << " unsigned int mult;" << std::endl << " xdr_u_int(xdrs,&mult);" << std::endl << " this1 = make_" << tagT << "(mult);" << std::endl << " this1->mult = mult;" << std::endl << " for (m = 0; m < mult; m++ )" << std::endl << " {" << std::endl; } else { cFile << " this1 = make_" << tagT << "();" << std::endl << " {" << std::endl; } int hasContents = 0; DOMNodeList* contList = tagEl->getChildNodes(); for (int c = 0; c < contList->getLength(); c++) { DOMNode* cont = contList->item(c); short type = cont->getNodeType(); if (type == DOMNode::ELEMENT_NODE) { hasContents = 1; DOMElement* contEl = (DOMElement*) cont; XtString nameS(contEl->getTagName()); XtString reS(contEl->getAttribute(X("maxOccurs"))); int re = (reS == "unbounded")? INT_MAX : atoi(S(reS)); cFile << " int p;" << std::endl << " void* (*ptr) = (void**) &this1->" << ((rep > 1) ? "in[m]." : "" ) << ((re > 1) ? nameS.plural() : nameS) << ";" << std::endl; break; } } DOMNamedNodeMap* attList = tagEl->getAttributes(); for (int a = 0; a < attList->getLength(); a++) { DOMNode* att = attList->item(a); XtString typeS(att->getNodeValue()); XtString nameS(att->getNodeName()); XtString nameStr(nameS); if (rep > 1) { nameStr = "in[m]." + nameS; } if (typeS == "int") { cFile << " xdr_int(xdrs,&this1->" << nameStr << ");" << std::endl; } else if (typeS == "long") { cFile << "#ifndef XDR_LONGLONG_MISSING" << std::endl << " xdr_longlong_t(xdrs,&this1->" << nameStr << ");" << std::endl << "#else" << std::endl << " {" << std::endl << " int* " << nameStr << "_ = " << "(int*)&this1->" << nameStr << ";" << std::endl << "# if __BIG_ENDIAN__" << std::endl << " xdr_int(xdrs,&" << nameStr << "_[0]);" << std::endl << " xdr_int(xdrs,&" << nameStr << "_[1]);" << std::endl << "# else" << std::endl << " xdr_int(xdrs,&" << nameStr << "_[1]);" << std::endl << " xdr_int(xdrs,&" << nameStr << "_[0]);" << std::endl << "# endif" << std::endl << " }" << std::endl << "#endif" << std::endl; } else if (typeS == "float") { cFile << " xdr_float(xdrs,&this1->" << nameStr << ");" << std::endl; } else if (typeS == "double") { cFile << " xdr_double(xdrs,&this1->" << nameStr << ");" << std::endl; } else if (typeS == "boolean") { cFile << " xdr_bool(xdrs,&this1->" << nameStr << ");" << std::endl; } else if (typeS == "Particle_t") { cFile << " xdr_int(xdrs,(int*)&this1->" << nameStr << ");" << std::endl; } else if (typeS == "string") { cFile << " this1->" << nameStr << " = 0;" << std::endl << " xdr_string(xdrs, &this1->" << nameStr << ", 1000000);" << std::endl; } else if (typeS == "anyURI") { cFile << " this1->" << nameStr << " = 0;" << std::endl << " xdr_string(xdrs, &this1->" << nameStr << ", 1000000);" << std::endl; } else { /* ignore attributes with unrecognized values */ } } if (hasContents) { cFile << " for (p = 0; p < pop->popListLength; p++)" << std::endl << " {" << std::endl << " popNode* pnode = pop->popList[p];" << std::endl << " if (pnode)" << std::endl << " {" << std::endl << " int kid = pnode->inParent;" << std::endl << " ptr[kid] = pnode->unpacker(xdrs,pnode);" << std::endl << " }" << std::endl << " else" << std::endl << " {" << std::endl << " unsigned int skip;" << std::endl << " xdr_u_int(xdrs,&skip);" << std::endl << " xdr_setpos64(xdrs,xdr_getpos64(xdrs)+skip);" << std::endl << " }" << std::endl << " }" << std::endl; } cFile << " }" << std::endl << " xdr_setpos64(xdrs,start+size);" << std::endl << " }" << std::endl << " return this1;" << std::endl << "}" << std::endl; } } /* Generate c function to read from binary stream into c-structures */ void CodeBuilder::constructReadFunc(DOMElement* topEl) { XtString topS(topEl->getTagName()); XtString topType = topS.simpleType(); XtString topT(topType); topT.erase(topT.rfind('_')); hFile << std::endl << topType << "* read_" << topT << "(" << classPrefix << "_iostream_t* fp" << ");" << std::endl; cFile << std::endl << topType << "* read_" << topT << "(" << classPrefix << "_iostream_t* fp" << ")" << std::endl << "{" << std::endl << " " << topType << "* nextEvent = " << "unpack_" << topT << "(fp->xdrs,fp->popTop);" << std::endl << " return (nextEvent == HDDM_NULL)? 0 : nextEvent;" << std::endl << "}" << std::endl; } /* Generate c function to skip over events in the binary stream */ void CodeBuilder::constructSkipFunc() { hFile << std::endl << "int skip_" << classPrefix << "_HDDM" << "(" << classPrefix << "_iostream_t* fp, int nskip);" << std::endl; cFile << std::endl << "int skip_" << classPrefix << "_HDDM" << "(" << classPrefix << "_iostream_t* fp, int nskip)" << std::endl << "{" << std::endl << " int skipped;" << std::endl << " for (skipped=0; skipped < nskip; ++skipped)" << std::endl << " {" << std::endl << " unsigned int size;" << std::endl << " if (! xdr_u_int(fp->xdrs,&size))" << std::endl << " {" << std::endl << " return skipped;" << std::endl << " }" << std::endl << " else if (size == 1)" << std::endl << " {" << std::endl << " fprintf(stderr,\"hddm error - \"" << std::endl << " \"compressed data found in input stream.\\n\"" << std::endl << " \"Compression/decompression is not supported \"" << std::endl << " \"by the hddm c i/o interface.\\n\");" << std::endl << " fprintf(stderr,\"You must use the c++ \"" << std::endl << " \"interface to read this file.\\n\");" << std::endl << " exit(9);" << std::endl << " }" << std::endl << " else if (size > 0)" << std::endl << " {" << std::endl << " off_t start = xdr_getpos64(fp->xdrs);" << std::endl << " if (xdr_setpos64(fp->xdrs,start+size) != 0) {" << std::endl << " fp->lerrno = errno;" << std::endl << " return skipped;" << std::endl << " }" << std::endl << " }" << std::endl << " }" << std::endl << " return skipped;" << std::endl << "}" << std::endl; } /* Generate streamers for packing c-structures onto a binary stream * and deleting them from memory when output is complete */ void CodeBuilder::constructPackers() { cFile << std::endl; std::vector::iterator iter; for (iter = tagList.begin(); iter != tagList.end(); iter++) { DOMElement* tagEl = *iter; XtString tagS(tagEl->getTagName()); XtString listType = tagS.listType(); XtString simpleType = tagS.simpleType(); cFile << "static "; XtString tagType; XtString repS(tagEl->getAttribute(X("maxOccurs"))); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); if (rep > 1) { tagType = listType; } else { tagType = simpleType; } XtString tagT(tagType); tagT.erase(tagT.rfind('_')); cFile << "int pack_" << tagT << "(XDR* xdrs, " << tagType << "* this1);" << std::endl; } for (iter = tagList.begin(); iter != tagList.end(); iter++) { DOMElement* tagEl = *iter; XtString tagS(tagEl->getTagName()); XtString listType = tagS.listType(); XtString simpleType = tagS.simpleType(); cFile << std::endl << "static "; XtString tagType; XtString repS(tagEl->getAttribute(X("maxOccurs"))); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); if (rep > 1) { tagType = listType; } else { tagType = simpleType; } XtString tagT(tagType); tagT.erase(tagT.rfind('_')); cFile << "int pack_" << tagT << "(XDR* xdrs, " << tagType << "* this1)" << std::endl << "{" << std::endl << " int m=0;" << std::endl << " unsigned int size=0;" << std::endl << " off_t base,start,end;" << std::endl << " base = xdr_getpos64(xdrs);" << std::endl << " xdr_u_int(xdrs,&size);" << std::endl << " start = xdr_getpos64(xdrs);" << std::endl << std::endl; if (rep > 1) { cFile << " xdr_u_int(xdrs,&this1->mult);" << std::endl << " for (m = 0; m < this1->mult; m++)" << std::endl << " {" << std::endl; } else { cFile << " {" << std::endl; } DOMNamedNodeMap* attList = tagEl->getAttributes(); for (int a = 0; a < attList->getLength(); a++) { DOMNode* att = attList->item(a); XtString typeS(att->getNodeValue()); XtString nameS(att->getNodeName()); XtString nameStr(nameS); if (rep > 1) { nameStr = "in[m]." + nameS; } if (typeS == "int") { cFile << " xdr_int(xdrs,&this1->" << nameStr << ");" << std::endl; } if (typeS == "long") { cFile << "#ifndef XDR_LONGLONG_MISSING" << std::endl << " xdr_longlong_t(xdrs,&this1->" << nameStr << ");" << std::endl << "#else" << std::endl << " {" << std::endl << " int* " << nameStr << "_ = " << "(int*)&this1->" << nameStr << ";" << std::endl << "# if __BIG_ENDIAN__" << std::endl << " xdr_int(xdrs,&" << nameStr << "_[0]);" << std::endl << " xdr_int(xdrs,&" << nameStr << "_[1]);" << std::endl << "# else" << std::endl << " xdr_int(xdrs,&" << nameStr << "_[1]);" << std::endl << " xdr_int(xdrs,&" << nameStr << "_[0]);" << std::endl << "# endif" << std::endl << " }" << std::endl << "#endif" << std::endl; } else if (typeS == "float") { cFile << " xdr_float(xdrs,&this1->" << nameStr << ");" << std::endl; } else if (typeS == "double") { cFile << " xdr_double(xdrs,&this1->" << nameStr << ");" << std::endl; } else if (typeS == "boolean") { cFile << " xdr_bool(xdrs,&this1->" << nameStr << ");" << std::endl; } else if (typeS == "Particle_t") { cFile << " xdr_int(xdrs,(int*)&this1->" << nameStr << ");" << std::endl; } else if (typeS == "string") { cFile << " xdr_string(xdrs,&this1->" << nameStr << ", 1000000);" << std::endl; cFile << " FREE(this1->" << nameStr << ");" << std::endl; } else if (typeS == "anyURI") { cFile << " xdr_string(xdrs,&this1->" << nameStr << ", 1000000);" << std::endl; cFile << " FREE(this1->" << nameStr << ");" << std::endl; } else { /* ignore attributes with unrecognized values */ } } DOMNodeList* contList = tagEl->getChildNodes(); for (int c = 0; c < contList->getLength(); c++) { DOMNode* cont = contList->item(c); short type = cont->getNodeType(); if (type == DOMNode::ELEMENT_NODE) { DOMElement* contEl = (DOMElement*) cont; XtString nameS(contEl->getTagName()); XtString reS(contEl->getAttribute(X("maxOccurs"))); int re = (reS == "unbounded")? INT_MAX : atoi(S(reS)); XtString contType; if (re > 1) { contType = nameS.listType(); } else { contType = nameS.simpleType(); } XtString contT(contType); contT.erase(contT.rfind('_')); cFile << " if (this1->" << ((rep > 1)? "in[m]." : "") << ((re > 1)? nameS.plural(): nameS) << " != (" << contType << "*)&hddm_nullTarget)" << std::endl << " {" << std::endl << " if (pack_" << contT << "(xdrs,this1->" << ((rep > 1)? "in[m]." : "") << ((re > 1)? nameS.plural() : nameS) << ") < 0) {" << std::endl << " return -1;" << std::endl << " }" << std::endl << " }" << std::endl << " else" << std::endl << " {" << std::endl << " int zero=0;" << std::endl << " xdr_int(xdrs,&zero);" << std::endl << " }" << std::endl; } } cFile << " }" << std::endl << " FREE(this1);" << std::endl << " end = xdr_getpos64(xdrs);" << std::endl << " xdr_setpos64(xdrs,base);" << std::endl << " size = end-start;" << std::endl << " xdr_u_int(xdrs,&size);" << std::endl << " xdr_setpos64(xdrs,end);" << std::endl << " return size;" << std::endl << "}" << std::endl; } } /* Generate c functions for exporting c-structures onto a binary stream */ void CodeBuilder::constructFlushFunc(DOMElement* el) { DOMElement* topEl = tagList[0]; XtString topS(topEl->getTagName()); XtString topType = topS.simpleType(); XtString topT(topType); topT.erase(topT.rfind('_')); constructPackers(); hFile << std::endl << "int flush_" << topT << "(" << topType << "* this1," << classPrefix << "_iostream_t* fp" << ");" << std::endl; cFile << std::endl << "int flush_" << topT << "(" << topType << "* this1," << classPrefix << "_iostream_t* fp" << ")" << std::endl << "{" << std::endl << " if (this1 == 0)" << std::endl << " {" << std::endl << " return 0;" << std::endl << " }" << std::endl << " else if (fp == 0)" << std::endl << " {" << std::endl << " XDR* xdrs = (XDR*)malloc(sizeof(XDR));" << std::endl << " int max_buffer_size = 1000000;" << std::endl << " char* dump = (char*)malloc(max_buffer_size);"<< std::endl << " xdrmem_create(xdrs,dump,max_buffer_size,XDR_ENCODE);" << std::endl << " pack_" << topT << "(xdrs,this1);" << std::endl << " xdr_destroy(xdrs);" << std::endl << " free(xdrs);" << std::endl << " free(dump);" << std::endl << " }" << std::endl << " else if (fp->iomode == HDDM_STREAM_OUTPUT)" << std::endl << " {" << std::endl << " if (pack_" << topT << "(fp->xdrs,this1) < 0) {" << std::endl << " fp->lerrno = errno;" << std::endl << " return -1;" << std::endl << " }" << std::endl << " }" << std::endl << " return 0;" << std::endl << "}" << std::endl; } /* Generate c functions that match up corresponding elements between * the c structures and the data model that appears on the input * binary stream. If successful, these routines build a hierarchical * structure (the "pop tree") that gives directions to the unpackers. * * The matching rules are as follows: * * 1) The attribute list for any given tag must be identical in content * and order wherever it appears, otherwise there is a collision. * * 2) The content list for any given tag must be internally consistent * within each model, but there are no requirements for agreement * between the c-structures and the binary stream models. Only the * contents which appear in both models will be unpacked, however. */ void CodeBuilder::writeMatcher() { cFile << std::endl << "static int getTag(char* d, char* tag)" << std::endl << "{" << std::endl << " int level;" << std::endl << " char* token;" << std::endl << " char line[500];" << std::endl << " strncpy(line,d,500);" << std::endl << " line[499] = 0;" << std::endl << " level = index(line,'<')-line;" << std::endl << " if (level < 500 &&" << std::endl << " (token = strtok(line+level+1,\" >\")))" << std::endl << " {" << std::endl << " strncpy(tag,token,500);" << std::endl << " return level/2;" << std::endl << " }" << std::endl << " return -1;" << std::endl << "}" << std::endl << std::endl << "static char* getEndTag(char* d, char* tag)" << std::endl << "{" << std::endl << " char line[500];" << std::endl << " char endTag[510];" << std::endl << " strncpy(line,d,500);" << std::endl << " line[499] = 0;" << std::endl << " if (strstr(strtok(line,\"\\n\"),\"/>\") == 0)" << std::endl << " {" << std::endl << " sprintf(endTag,\"\",tag);" << std::endl << " }" << std::endl << " else" << std::endl << " {" << std::endl << " strcpy(endTag,\"/>\");" << std::endl << " }" << std::endl << " return strstr(d,endTag);" << std::endl << "}" << std::endl << std::endl << "static void collide(char* b, char* c)" << std::endl << "{" << std::endl << " char btag[500];" << std::endl << " getTag(b,btag);" << std::endl << " b = index(b,'<');" << std::endl << " c = index(c,'<');" << std::endl << " *(index(b,'\\n')) = 0;" << std::endl << " *(index(c,'\\n')) = 0;" << std::endl << " fprintf(stderr,\"HDDM warning: \");" << std::endl << " fprintf(stderr,\"tag %s in input file \", btag);" << std::endl << " fprintf(stderr,\"does not match c header hddm_" << classPrefix << ".h\\n\");" << std::endl << " fprintf(stderr,\" input file: %s\\n\", b);" << std::endl << " fprintf(stderr,\" c header: %s\\n\", c);" << std::endl << " fprintf(stderr,\" === Tag %s will be ignored,\", btag);" << std::endl << " fprintf(stderr,\" rebuild to cure the problem ===\\n\");" << std::endl << " *(index(b,0)) = '\\n';" << std::endl << " *(index(c,0)) = '\\n';" << std::endl << "}" << std::endl << std::endl << "static popNode* matches(char* b, char* c)" << std::endl << "{" << std::endl << " char btag[500];" << std::endl << " char ctag[500];" << std::endl << " int blevel, clevel;" << std::endl << " int ptrSeqNo = 0;" << std::endl << " blevel = getTag(b,btag);" << std::endl << " while ((clevel = getTag(c,ctag)) == blevel)" << std::endl << " {" << std::endl << " if " << "((clevel == blevel) && (strcmp(ctag,btag) == 0))" << std::endl << " {" << std::endl << " popNode* this1 = " << "(popNode*)malloc(sizeof(popNode));" << std::endl << " int len = index(c+1,'\\n') - c;" << std::endl << " if (strncmp(c,b,len) != 0)" << std::endl << " {" << std::endl << " collide(b,c);" << std::endl << " return 0;" << std::endl << " }" << std::endl; std::vector::iterator iter; for (iter = tagList.begin(); iter != tagList.end(); iter++) { XtString tagS((*iter)->getTagName()); XtString repS((*iter)->getAttribute(X("maxOccurs"))); int rep = (repS == "unbounded")? INT_MAX : atoi(S(repS)); XtString tagType; if (rep > 1) { tagType = tagS.listType(); } else { tagType = tagS.simpleType(); } XtString tagT(tagType); tagT.erase(tagT.rfind('_')); cFile << " else if " << "(strcmp(btag,\"" << tagS << "\") == 0)" << std::endl << " {" << std::endl << " this1->unpacker = " << "(void*(*)(XDR*,popNode*))" << "unpack_" << tagT << ";" << std::endl << " }" << std::endl; } cFile << " this1->inParent = ptrSeqNo;" << std::endl << " this1->popListLength = 0;" << std::endl << " c = index(c+1,'\\n');" << std::endl << " b = index(b+1,'\\n');" << std::endl << " while (getTag(b,btag) > blevel)" << std::endl << " {" << std::endl << " this1->popList[this1->popListLength++] = matches(b,c);" << std::endl << " if (this1->popListLength > " << MAX_POPLIST_LENGTH << ")" << std::endl << " {" << std::endl << " fprintf(stderr," << "\"hddm error - popList overflow.\\n\");" << std::endl << " fprintf(stderr," << "\"Increase MAX_POPLIST_LENGTH and recompile.\\n\");" << std::endl << " exit(9);" << std::endl << " }" << std::endl << " b = getEndTag(b,btag);" << std::endl << " b = index(b+1,'\\n');" << std::endl << " }" << std::endl << " return this1;" << std::endl << " }" << std::endl << " else" << std::endl << " {" << std::endl << " c = getEndTag(c,ctag);" << std::endl << " c = index(c+1,'\\n');" << std::endl << " ++ptrSeqNo;" << std::endl << " }" << std::endl << " }" << std::endl << " return 0;" << std::endl << "}" << std::endl; } /* Generate c code to open a hddm file for reading */ void CodeBuilder::constructOpenFunc(DOMElement* el) { XtString tagS(el->getTagName()); XtString tagType = tagS.simpleType(); XtString tagT(tagType); tagT.erase(tagT.rfind('_')); hFile << std::endl << classPrefix << "_iostream_t* " << "open_" << tagT << "(char* filename);" << std::endl; writeMatcher(); cFile << std::endl << classPrefix << "_iostream_t* " << "open_" << tagT << "(char* filename)" << std::endl << "{" << std::endl << " " << classPrefix << "_iostream_t* fp = " << "(" << classPrefix << "_iostream_t*)" << "malloc(sizeof(" << classPrefix << "_iostream_t));" << std::endl << " char* p;" << std::endl << " char* head;" << std::endl << " if (filename)" << std::endl << " {" << std::endl << " fp->fd = fopen(filename,\"r\");" << std::endl << " }" << std::endl << " else" << std::endl << " {" << std::endl << " fp->fd = fdopen(0,\"r\");" << std::endl << " }" << std::endl << " if (fp->fd == 0)" << std::endl << " {" << std::endl << " free(fp);" << std::endl << " return 0;" << std::endl << " }" << std::endl << " fp->iomode = HDDM_STREAM_INPUT;" << std::endl << " head = (char*)malloc(1000000);" << std::endl << " *head = 0;" << std::endl << " for (p = head;" << std::endl << " strstr(head,\"\") == 0;" << std::endl << " p += strlen(p))" << std::endl << " {" << std::endl << " if (p-head < 999000)" << std::endl << " {" << std::endl << " char *pbuf;" << std::endl << " pbuf = fgets(p,1000,fp->fd);" << std::endl << " }" << std::endl << " else" << std::endl << " {" << std::endl << " break;" << std::endl << " }" << std::endl << " }" << std::endl << " fp->popTop = matches(head,HDDM_" << classPrefix << "_DocumentString);" << std::endl << " free(head);" << std::endl << " if (fp->popTop->popListLength == 0)" << std::endl << " {" << std::endl << " fprintf(stderr,\"HDDM Error: \");" << std::endl << " fprintf(stderr,\"input template model \");" << std::endl << " fprintf(stderr,\"does not match c header.\");"<< std::endl << " fprintf(stderr,\" Please recompile.\\n\");" << std::endl << " exit(9);" << std::endl << " }" << std::endl << " fp->filename = " << "(char*)malloc(strlen(filename) + 1);" << std::endl << " strcpy(fp->filename,filename);" << std::endl << " fp->xdrs = (XDR*)malloc(sizeof(XDR));" << std::endl << " xdrstdio_create(fp->xdrs,fp->fd,XDR_DECODE);" << std::endl << " return fp;" << std::endl << "}" << std::endl; } /* Generate the c code to open a hddm file for writing */ void CodeBuilder::constructInitFunc(DOMElement* el) { XtString tagS(el->getTagName()); XtString tagType = tagS.simpleType(); XtString tagT(tagType); tagT.erase(tagT.rfind('_')); hFile << std::endl << classPrefix << "_iostream_t* " << "init_" << tagT << "(char* filename);" << std::endl; cFile << std::endl << classPrefix << "_iostream_t* " << "init_" << tagT << "(char* filename)" << std::endl << "{" << std::endl << " int len;" << std::endl << " char* head;" << std::endl << " " << classPrefix << "_iostream_t* fp = " << "(" << classPrefix << "_iostream_t*)" << "malloc(sizeof(" << classPrefix << "_iostream_t));" << std::endl << " if (filename)" << std::endl << " {" << std::endl << " fp->fd = fopen(filename,\"w\");" << std::endl << " }" << std::endl << " else" << std::endl << " {" << std::endl << " fp->fd = fdopen(1,\"w\");" << std::endl << " }" << std::endl << " if (fp->fd == 0)" << std::endl << " {" << std::endl << " free(fp);" << std::endl << " return 0;" << std::endl << " }" << std::endl << " fp->iomode = HDDM_STREAM_OUTPUT;" << std::endl << " len = strlen(HDDM_" << classPrefix << "_DocumentString);" << std::endl << " head = (char*)malloc(len+1);" << std::endl << " strcpy(head,HDDM_" << classPrefix << "_DocumentString);" << std::endl << " if (fwrite(head,1,len,fp->fd) != len)" << std::endl << " {" << std::endl << " fprintf(stderr,\"HDDM Error: \");" << std::endl << " fprintf(stderr,\"error writing to \");" << std::endl << " fprintf(stderr,\"output file %s\\n\",filename);" << std::endl << " exit(9);" << std::endl << " }" << std::endl << " fp->filename = " << "(char*)malloc(strlen(filename) + 1);" << std::endl << " strcpy(fp->filename,filename);" << std::endl << " fp->popTop = 0;" << std::endl << " fp->xdrs = (XDR*)malloc(sizeof(XDR));" << std::endl << " xdrstdio_create(fp->xdrs,fp->fd,XDR_ENCODE);" << std::endl << " free(head);" << std::endl << " return fp;" << std::endl << "}" << std::endl; } /* Generate the c code to close an open hddm file */ void CodeBuilder::constructCloseFunc(DOMElement* el) { XtString tagS(el->getTagName()); XtString tagType = tagS.simpleType(); XtString tagT(tagType); tagT.erase(tagT.rfind('_')); hFile << std::endl << "void close_" << tagT << "(" << classPrefix << "_iostream_t* fp);" << std::endl; cFile << std::endl << "static void popaway(popNode* p)" << std::endl << "{" << std::endl << " if (p)" << std::endl << " {" << std::endl << " int n;" << std::endl << " for (n = 0; n < p->popListLength; n++)" << std::endl << " {" << std::endl << " popaway(p->popList[n]);" << std::endl << " }" << std::endl << " free(p);" << std::endl << " }" << std::endl << "}" << std::endl << std::endl << "void close_" << tagT << "(" << classPrefix << "_iostream_t* fp)" << std::endl << "{" << std::endl << " xdr_destroy(fp->xdrs);" << std::endl << " free(fp->xdrs);" << std::endl << " fclose(fp->fd);" << std::endl << " free(fp->filename);" << std::endl << " popaway(fp->popTop);" << std::endl << " free(fp);" << std::endl << "}" << std::endl; } /* Generate the xml template in normal form and store in a string */ void CodeBuilder::constructDocument(DOMElement* el) { static int indent = 0; cFile << "\""; for (int n = 0; n < indent; n++) { cFile << " "; } XtString tagS(el->getTagName()); cFile << "<" << tagS; DOMNamedNodeMap* attrList = el->getAttributes(); int attrListLength = attrList->getLength(); for (int a = 0; a < attrListLength; a++) { DOMNode* node = attrList->item(a); XtString nameS(node->getNodeName()); XtString valueS(node->getNodeValue()); cFile << " " << nameS << "=\\\"" << valueS << "\\\""; } DOMNodeList* contList = el->getChildNodes(); int contListLength = contList->getLength(); if (contListLength > 0) { cFile << ">\\n\"" << std::endl; indent++; for (int c = 0; c < contListLength; c++) { DOMNode* node = contList->item(c); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { DOMElement* contEl = (DOMElement*) node; constructDocument(contEl); } } indent--; cFile << "\""; for (int n = 0; n < indent; n++) { cFile << " "; } cFile << "\\n\"" << std::endl; } else { cFile << " />\\n\"" << std::endl; } }