/* * 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. * * Original version - Richard Jones, May 25 2001. * * * Programmer's Notes: * ------------------- * 1. The HDDM specification is in the form of an xml document. For * information about the contents and structure of HDDM documents * see the web pages in ./doc that describes the data model. * * 2. Access by hddm-c to the xml source is through the industry- * standard DOM-1 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 document, 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 word (4-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 match. */ #include #include #include #include #include #include #include "hddm-c.hpp" #include #include #include #include #include char* hFilename = 0; char* classPrefix; DOM_Element* tagList[100000]; char* tagListName[100000]; int tagListLength = 0; int tagStack[100000]; int tagStackLength = 0; bool verifyOnly = false; void usage() { cerr << "\nUsage:\n" << " hddm-c [-v | -o ] {HDDM file}\n\n" << "Options:\n" << " -v validate only\n" << " -o write to .h" << endl; } char* plural(char* str) { int len = strlen(str); char* p = new char [len+10]; strcpy(p,str); if ((len > 3) && (strcmp(&p[len-3],"tum") == 0)) { strcpy(&p[len-3],"ta"); } else if ((len > 2) && (strcmp(&p[len-2],"ex") == 0)) { strcpy(&p[len-2],"ices"); } else if ((len > 2) && (strcmp(&p[len-2],"sh") == 0)) { strcpy(&p[len-2],"shes"); } else if ((len > 1) && (strcmp(&p[len-1],"s") == 0)) { strcpy(&p[len-1],"ses"); } else if (len > 1) { strcat(p,"s"); } return p; } char* basicStructType(char* tag) { int len = strlen(tag) + strlen(classPrefix); char* p = new char [len + 10]; char* q = new char [len]; strcpy(q,tag); q[0] = toupper(q[0]); sprintf(p,"%s_%s_t",classPrefix,q); delete [] q; return p; } char* containerStructType(char* tag) { int len = strlen(tag) + strlen(classPrefix); char* p = new char [len + 10]; char* tags = plural(tag); tags[0] = toupper(tags[0]); sprintf(p,"%s_%s_t",classPrefix,tags); delete [] tags; return p; } int constructGroup(DOM_Element& el, ofstream& hFile, ofstream& cFile) { char* tagStr = el.getTagName().transcode(); int t; for (t=0; t < tagListLength; t++) { if (strcmp(tagStr,tagListName[t]) == 0) break; } if (t < tagListLength) { DOM_NamedNodeMap oldAttr = tagList[t]->getAttributes(); DOM_NamedNodeMap newAttr = el.getAttributes(); int listLength = oldAttr.getLength(); if (newAttr.getLength() != listLength) { cerr << "hddm-c error: inconsistent usage of tag " << "\"" << tagStr << "\" in xml document." << endl; exit(1); } for (int n = 0; n < listLength; n++) { char* name = oldAttr.item(n).getNodeName().transcode(); char* value = oldAttr.item(n).getNodeValue().transcode(); short type = oldAttr.item(n).getNodeType(); char* was = tagList[t]->getAttribute(name).transcode(); char* is = el.getAttribute(name).transcode(); if (strcmp(was,is) != 0) { cerr << "hddm-c error: inconsistent usage of attribute " << "\"" << name << "\" in tag " << "\"" << tagStr << "\" in xml document." << endl; exit(1); } delete [] name; delete [] value; delete [] was; delete [] is; } DOM_NodeList oldList = tagList[t]->getChildNodes(); DOM_NodeList newList = el.getChildNodes(); listLength = oldList.getLength(); if (newList.getLength() != listLength) { cerr << "hddm-c error: inconsistent usage of tag " << "\"" << tagStr << "\" in xml document." << endl; exit(1); } for (int n = 0; n < listLength; n++) { DOM_Node cont = oldList.item(n); char* name = cont.getNodeName().transcode(); short type = cont.getNodeType(); if (type == ELEMENT_NODE) { DOM_NodeList contList = el.getElementsByTagName(name); if (contList.getLength() != 1) { cerr << "hddm-c error: inconsistent usage of tag " << "\"" << tagStr << "\" in xml document." << endl; exit(1); } } delete [] name; } delete [] tagStr; return t; } tagList[t] = new DOM_Element(el); tagListName[t] = new char [strlen(tagStr)+1]; strcpy(tagListName[t],tagStr); tagListLength++; DOM_NodeList contList = el.getChildNodes(); int contLength = contList.getLength(); for (int c = 0; c < contLength; c++) { DOM_Node cont = contList.item(c); short type = cont.getNodeType(); if (type == ELEMENT_NODE) { DOM_Element contEl = (DOM_Element&) cont; constructGroup(contEl,hFile,cFile); } } char* ctypeDef = basicStructType(tagStr); hFile << endl << "#ifndef SAW_" << ctypeDef << endl << "#define SAW_" << ctypeDef << endl << endl << "typedef struct {" << endl; tagStack[tagStackLength++] = t; // this tag int& repFlag = tagStack[tagStackLength++]; // repeat flag int& wcount = tagStack[tagStackLength++]; // words of data int& pcount = tagStack[tagStackLength++]; // words of pointers wcount = 0; DOM_NamedNodeMap varList = el.getAttributes(); int varCount = varList.getLength(); for (int v = 0; v < varCount; v++) { DOM_Node var = varList.item(v); char* name = var.getNodeName().transcode(); char* typeStr = var.getNodeValue().transcode(); if (strcmp(typeStr,"int") == 0) { hFile << " int " << name << ";" << endl; wcount += 1; } else if (strcmp(typeStr,"float") == 0) { hFile << " float " << name << ";" << endl; wcount += 1; } else if (strcmp(typeStr,"double") == 0) { hFile << " double " << name << ";" << endl; wcount += 2; } else if (strcmp(typeStr,"bool") == 0) { hFile << " int " << name << ";" << endl; wcount += 1; } else if (strcmp(typeStr,"Particle_t") == 0) { hFile << " Particle_t " << name << ";" << endl; wcount += 1; } else { /* ignore attributes with unrecognized values */ } delete [] typeStr; delete [] name; } pcount = 0; for (int c = 0; c < contLength; c++) { DOM_Node cont = contList.item(c); char* name = cont.getNodeName().transcode(); short type = cont.getNodeType(); if (type == ELEMENT_NODE) { DOM_Element contEl = (DOM_Element&) cont; DOMString rep = contEl.getAttribute("repeat"); char* ctypeRef = (rep == 0) ? basicStructType(name) : containerStructType(name); hFile << " " << ctypeRef << "*"; for (int i=0; i < 20-strlen(ctypeRef); i++) { hFile << " "; } char* names = plural(name); hFile << ((rep == 0) ? name : names) << ";" << endl; tagStack[tagStackLength++] = constructGroup(contEl,hFile,cFile); ++pcount; delete [] ctypeRef; delete [] names; } delete [] name; } hFile << "} " << ctypeDef << ";" << endl; repFlag = 0; DOMString rep = el.getAttribute("repeat"); if (rep != 0) { repFlag = 1; char* ctypeRef = containerStructType(tagStr); hFile << endl << "typedef struct {" << endl << " int mult;" << endl << " " << ctypeDef << " in[1];" << endl << "} " << ctypeRef << ";" << endl; delete [] ctypeRef; } hFile << "#endif /* " << ctypeDef << " */" << endl; delete [] ctypeDef; delete [] tagStr; return t; } void constructMakeFuncs(DOM_Element& el, ofstream& hFile, ofstream& cFile) { for (int s=0; s < tagStackLength; ) { int t = tagStack[s++]; int repFlag = tagStack[s++]; int wcount = tagStack[s++]; int pcount = tagStack[s++]; DOM_Element tagEl = *tagList[t]; char* tagStr = tagListName[t]; char* containerType = containerStructType(tagStr); char* basicType = basicStructType(tagStr); hFile << endl; cFile << endl; if (repFlag) { hFile << containerType << "* "; cFile << containerType << "* "; char containerT[500]; strncpy(containerT,containerType,500); char* term = rindex(containerT,'_'); *term = 0; hFile << "make_" << containerT; cFile << "make_" << containerT; hFile << "(int n);" << endl; cFile << "(int n)" << endl << "{" << endl << " int rep = (n > 1) ? n-1 : 0;" << endl << " int size = sizeof(" << containerType << ") + rep * sizeof(" << basicType << ");" << endl << " " << containerType << "* p = malloc(size);" << endl; } else { hFile << basicType << "* "; cFile << basicType << "* "; char basicT[500]; strncpy(basicT,basicType,500); char* term = rindex(basicT,'_'); *term = 0; hFile << "make_" << basicT; cFile << "make_" << basicT; hFile << "();" << endl; cFile << "()" << endl << "{" << endl << " int size = sizeof(" << basicType << ");" << endl << " " << basicType << "* p = malloc(size);" << endl; } cFile << " memset(p,0,size);" << endl << " return p;" << endl << "}" << endl; delete [] containerType; delete [] basicType; s += pcount; } } void constructReadFunc(DOM_Element& el, ofstream& hFile, ofstream& cFile) { DOM_Element topEl = *tagList[0]; char* topStr = topEl.getTagName().transcode(); char* topType = basicStructType(topStr); char topT[500]; strncpy(topT,topType,500); char* term = rindex(topT,'_'); *term = 0; hFile << endl << "#ifndef HDDM_STREAM_INPUT" << endl << "#define HDDM_STREAM_INPUT -91" << endl << "#define HDDM_STREAM_OUTPUT -92" << endl << endl << "typedef struct {" << endl << " FILE* fd;" << endl << " int iomode;" << endl << " char* hddm;" << endl << " char* filename;" << endl << " int sections;" << endl << " void* (*unpacker[10000])();" << endl << " int modelLevel[10000];" << endl << " int ptrOffset[10000];" << endl << "} " << classPrefix << "_iostream;" << endl << endl << "#endif /* HDDM_STREAM_INPUT */" << endl; cFile << endl << "int* sp;" << endl << "int* dp;" << endl; for (int s=0; s < tagStackLength; ) { int t = tagStack[s++]; int repFlag = tagStack[s++]; int wcount = tagStack[s++]; int pcount = tagStack[s++]; s += pcount; DOM_Element tagEl = *tagList[t]; char* tagStr = tagListName[t]; char* containerType = containerStructType(tagStr); char* basicType = basicStructType(tagStr); cFile << endl << "static "; char* tagType; if (repFlag) { tagType = containerType; } else { tagType = basicType; } char tagT[500]; strncpy(tagT,tagType,500); char* term = rindex(tagT,'_'); *term = 0; cFile << tagType << "* unpack_" << tagT << "()" << endl << "{" << endl << " int size = *(sp++);" << endl; if (repFlag) { cFile << " int rep = *(sp++);" << endl << " " << tagType << "* his = 0;" << endl << " if (size > 0)" << endl << " {" << endl << " int r;" << endl << " his = make_" << tagT << "(rep);" << endl << " his->mult = rep;" << endl << " for (r = 0; r < rep; r++ )" << endl << " {" << endl << " dp = (int*) his;" << endl; } else { cFile << " " << tagType << "* his = 0;" << endl << " if (size > 0)" << endl << " {" << endl << " his = make_" << tagT << "();" << endl << " {" << endl << " dp = (int*) his;" << endl; } for (int w = 0; w < wcount; w++) { cFile << " *(dp++) = *(sp++);" << endl; } cFile << " }" << endl << " }" << endl << " return his;" << endl << "}" << endl; delete [] containerType; delete [] basicType; } cFile << endl << "void* unpack_NULL()" << endl << "{" << endl << " int size = *(sp++);" << endl << " sp += size;" << endl << " return 0;" << endl << "}" << endl; hFile << endl << topType << "* read_" << topT << "(" << classPrefix << "_iostream* fp" << ");" << endl; cFile << endl << topType << "* read_" << topT << "(" << classPrefix << "_iostream* fp" << ")" << endl << "{" << endl << " " << topType << "* this = 0;" << endl << " int ret = 0;" << endl << " int* buff = malloc(1000000);" << endl << " sp = buff;" << endl << endl << " if (fp && (fp->iomode == HDDM_STREAM_INPUT))" << endl << " {" << endl << " ret = fread(buff,sizeof(int),1,fp->fd);" << endl << " }" << endl << " if (ret)" << endl << " {" << endl << " ret = *buff;" << endl << " ret -= fread(&sp[1],sizeof(int),ret,fp->fd);"<< endl << " }" << endl << " else" << endl << " {" << endl << " free(buff);" << endl << " return 0;" << endl << " }" << endl << " if (ret == 0)" << endl << " {" << endl << " int s;" << endl << " void* ptrStack[10000];" << endl << " void* (*unpacker)() = fp->unpacker[0];" << endl << " ptrStack[0] = (*unpacker)();" << endl << " for (s = 1; s < fp->sections; s++)" << endl << " {" << endl << " int ptrOffset = fp->ptrOffset[s];" << endl << " int level = fp->modelLevel[s];" << endl << " int* ptr = ptrStack[level - 1];" << endl << " if (ptr != 0)" << endl << " {" << endl << " void** pp = (void**) &ptr[ptrOffset];" << endl << " unpacker = fp->unpacker[s];" << endl << " ptrStack[level] = (*unpacker)();" << endl << " *pp = ptrStack[level];" << endl << " }" << endl << " else" << endl << " {" << endl << " ptrStack[level] = 0;" << endl << " }" << endl << " }" << endl << " }" << endl << " free(buff);" << endl << " return this;" << endl << "}" << endl; delete [] topType; delete [] topStr; } void constructFlushFunc(DOM_Element& el, ofstream& hFile, ofstream& cFile) { DOM_Element topEl = *tagList[0]; char* topStr = tagListName[0]; char* topType = basicStructType(topStr); char topT[500]; strncpy(topT,topType,500); char* term = rindex(topT,'_'); *term = 0; for (int s=0; s < tagStackLength; ) { int t = tagStack[s++]; int repFlag = tagStack[s++]; int wcount = tagStack[s++]; int pcount = tagStack[s++]; DOM_Element tagEl = *tagList[t]; char* tagStr = tagListName[t]; char* containerType = containerStructType(tagStr); char* basicType = basicStructType(tagStr); cFile << endl << "static "; char* tagType; if (repFlag) { tagType = containerType; } else { tagType = basicType; } char tagT[500]; strncpy(tagT,tagType,500); char* term = rindex(tagT,'_'); *term = 0; cFile << "int pack_" << tagT; cFile << "(" << tagType << "* pp, " << classPrefix << "_iostream* fp" << ")" << endl << "{" << endl << " int* dpp = dp++;" << endl << " int* spp = (int*) pp;" << endl; if (repFlag) { cFile << " int* dpm = dp++;" << endl << " if (spp != 0)" << endl << " {" << endl << " int n;" << endl << " *dpm = *(spp++);" << endl << " for (n = 0; n < *dpm; n++ )" << endl; } else { cFile << " if (spp != 0)" << endl << " {" << endl; } cFile << " {" << endl; for (int w = 0; w < wcount; w++) { cFile << " *(dp++) = *(spp++);" << endl; } for (int c = 0; c < pcount; c++) { int t = tagStack[s++]; DOM_Element* contEl = tagList[t]; char* contTag = tagListName[t]; DOMString repAttr = contEl->getAttribute("repeat"); char* contType; if (repAttr == 0) { contType = basicStructType(contTag); } else { contType = containerStructType(contTag); } char contT[500]; strncpy(contT,contType,500); char* term = rindex(contT,'_'); *term = 0; cFile << " pack_" << contT; cFile << "(*(" << contType << "**) spp++, fp);" << endl; delete [] contType; } cFile << " }" << endl << " free(pp);" << endl << " }" << endl << " *dpp = dp - dpp - 1;" << endl << " return *dpp;" << endl << "}" << endl; delete [] containerType; delete [] basicType; } hFile << endl << "int flush_" << topT << "(" << topType << "* p," << classPrefix << "_iostream* fp" << ");" << endl; cFile << endl << "int flush_" << topT << "(" << topType << "* p," << classPrefix << "_iostream* fp" << ")" << endl << "{" << endl << " int ret = 0;" << endl << " int* buff = malloc(1000000);" << endl << " dp = buff;" << endl << " sp = (int*) p;" << endl << endl << " if (p != 0)" << endl << " {" << endl << " pack_" << topT << "((" << topType << "*) (sp++), fp);" << endl << " }" << endl << " if (fp && (fp->iomode == HDDM_STREAM_OUTPUT))" << endl << " {" << endl << " ret = fwrite(buff,sizeof(int),*buff+1,fp->fd);" << endl << " }" << endl << " free(buff);" << endl << " return ret;" << endl << "}" << endl; delete [] topType; } void writeMatcher(ofstream& cFile) { cFile << endl << "static int getTag(char* d, char* tag)" << endl << "{" << endl << " int level;" << endl << " char line[500];" << endl << " strncpy(line,d,500);" << endl << " line[499] = 0;" << endl << " level = strlen(strtok(line,\"<\"));" << endl << " strncpy(tag,strtok(NULL,\" >\"),500);" << endl << " return level/2;" << endl << "}" << endl << endl << "static char* getEndTag(char* d, char* tag)" << endl << "{" << endl << " char line[500];" << endl << " char endTag[510];" << endl << " strncpy(line,d,500);" << endl << " line[499] = 0;" << endl << " if (strstr(strtok(line,\"\\n\"),\"/>\") == 0)" << endl << " {" << endl << " sprintf(endTag,\"\",tag);" << endl << " }" << endl << " else" << endl << " {" << endl << " strcpy(endTag,\"/>\");" << endl << " }" << endl << " return strstr(d,endTag);" << endl << "}" << endl; cFile << endl << "static int matches(char* d, char* c, " << classPrefix << "_iostream* fp)" << endl << "{" << endl << " char ctag[500];" << endl << " char dtag[500];" << endl << " int clevel, dlevel;" << endl << " dlevel = getTag(d,dtag);" << endl << " while ((clevel = getTag(c,ctag)) == dlevel)" << endl << " {" << endl << " int ptrSeqNo = 0;" << endl << " if " << "((clevel == dlevel) && (strcmp(ctag,dtag) == 0))" << endl << " {" << endl << " int len = index(c+1,'\\n') - c;" << endl << " if (strncmp(c,d,len) != 0)" << endl << " {" << endl << " return -1;" << endl << " }" << endl << " fp->modelLevel[fp->sections] = dlevel;" << endl; int firstTag = 1; for (int s=0; s < tagStackLength; ) { int t = tagStack[s++]; int repFlag = tagStack[s++]; int wcount = tagStack[s++]; int pcount = tagStack[s++]; s += pcount; char* tagStr = tagListName[t]; char* tagType; if (repFlag) { tagType = containerStructType(tagStr); } else { tagType = basicStructType(tagStr); } char tagT[500]; strncpy(tagT,tagType,500); char* term = rindex(tagT,'_'); *term = 0; if (firstTag) { firstTag = 0; cFile << " if "; } else { cFile << " else if "; } cFile << "(strcmp(dtag,\"" << tagStr << "\") == 0)" << endl << " {" << endl << " fp->unpacker[fp->sections] = " << "(void*) unpack_" << tagT << ";" << endl << " fp->ptrOffset[fp->sections] = " << wcount << " + ptrSeqNo*sizeof(int*)/sizeof(int);" << endl << " ++fp->sections;" << endl << " }" << endl; } cFile << " else" << endl << " {" << endl << " return -1;" << endl << " }" << endl << " c = index(c+1,'\\n');" << endl << " d = index(d+1,'\\n');" << endl << " while (getTag(d,dtag) > dlevel)" << endl << " {" << endl << " if (matches(d,c,fp))" << endl << " {" << endl << " return -1;" << endl << " }" << endl << " else" << endl << " {" << endl << " d = getEndTag(d,dtag);" << endl << " }" << endl << " d = index(d+1,'\\n');" << endl << " }" << endl << " return 0;" << endl << " }" << endl << " else" << endl << " {" << endl << " c = getEndTag(c,ctag);" << endl << " ++ptrSeqNo;" << endl << " }" << endl << " c = index(c+1,'\\n');" << endl << " }" << endl << " fp->unpacker[fp->sections++] = unpack_NULL;" << endl << " return 0;" << endl << "}" << endl; } void constructOpenFunc(DOM_Element& el, ofstream& hFile, ofstream& cFile) { char* tagStr = el.getTagName().transcode(); char* tagType = basicStructType(tagStr); char tagT[500]; strncpy(tagT,tagType,500); char* term = rindex(tagT,'_'); *term = 0; hFile << endl << classPrefix << "_iostream* " << "open_" << tagT << "(char* filename);" << endl; writeMatcher(cFile); cFile << endl << classPrefix << "_iostream* " << "open_" << tagT << "(char* filename)" << endl << "{" << endl << " " << classPrefix << "_iostream* fp = " << "malloc(sizeof(" << classPrefix << "_iostream));" << endl << " char* p;" << endl << " fp->fd = fopen(filename,\"r\");" << endl << " if (fp->fd == 0)" << endl << " {" << endl << " free(fp);" << endl << " return 0;" << endl << " }" << endl << " fp->iomode = HDDM_STREAM_INPUT;" << endl << " fp->hddm = malloc(1000000);" << endl << " p = fp->hddm;" << endl << " *p = 0;" << endl << " while (strcmp(p,\"\\n\") != 0)" << endl << " {" << endl << " int len = strlen(fp->hddm);" << endl << " if (len < 990000)" << endl << " {" << endl << " p = fp->hddm + len;" << endl << " fgets(p,10000,fp->fd);" << endl << " }" << endl << " else" << endl << " {" << endl << " break;" << endl << " }" << endl << " }" << endl << " fp->sections = 0;" << endl << " if (matches(fp->hddm,HDDM_" << classPrefix << "_DocumentString,fp) != 0)" << endl << " {" << endl << " fprintf(stderr,\"HDDM Error: \");" << endl << " fprintf(stderr,\"input file data model \");" << endl << " fprintf(stderr,\"does not match \");" << endl << " fprintf(stderr,\"compiled code.\\n\");" << endl << " fprintf(stderr,\"Please recompile.\\n\");" << endl << " exit(9);" << endl << " }" << endl << " fp->filename = malloc(strlen(filename) + 1);" << endl << " strcpy(fp->filename,filename);" << endl << " return fp;" << endl << "}" << endl; delete [] tagStr; delete [] tagType; } void constructInitFunc(DOM_Element& el, ofstream& hFile, ofstream& cFile) { char* tagStr = el.getTagName().transcode(); char* tagType = basicStructType(tagStr); char tagT[500]; strncpy(tagT,tagType,500); char* term = rindex(tagT,'_'); *term = 0; hFile << endl << classPrefix << "_iostream* " << "init_" << tagT << "(char* filename);" << endl; cFile << endl << classPrefix << "_iostream* " << "init_" << tagT << "(char* filename)" << endl << "{" << endl << " int len;" << endl << " " << classPrefix << "_iostream* fp = " << "malloc(sizeof(" << classPrefix << "_iostream));" << endl << " fp->fd = fopen(filename,\"w\");" << endl << " if (fp->fd == 0)" << endl << " {" << endl << " free(fp);" << endl << " return 0;" << endl << " }" << endl << " fp->iomode = HDDM_STREAM_OUTPUT;" << endl << " len = strlen(HDDM_" << classPrefix << "_DocumentString);" << endl << " fp->hddm = malloc(len + 1);" << endl << " strcpy(fp->hddm,HDDM_" << classPrefix << "_DocumentString);" << endl << " if (fwrite(fp->hddm,1,len,fp->fd) != len)" << endl << " {" << endl << " fprintf(stderr,\"HDDM Error: \");" << endl << " fprintf(stderr,\"error writing to \");" << endl << " fprintf(stderr,\"output file %s\",filename);"<< endl << " exit(9);" << endl << " }" << endl << " fp->filename = malloc(strlen(filename) + 1);" << endl << " strcpy(fp->filename,filename);" << endl << " return fp;" << endl << "}" << endl; delete [] tagStr; delete [] tagType; } void constructCloseFunc(DOM_Element& el, ofstream& hFile, ofstream& cFile) { char* tagStr = el.getTagName().transcode(); char* tagType = basicStructType(tagStr); char tagT[500]; strncpy(tagT,tagType,500); char* term = rindex(tagT,'_'); *term = 0; hFile << endl << "void close_" << tagT << "(" << classPrefix << "_iostream* fp);" << endl; cFile << endl << "void close_" << tagT << "(" << classPrefix << "_iostream* fp)" << endl << "{" << endl << " fclose(fp->fd);" << endl << " free(fp->hddm);" << endl << " free(fp->filename);" << endl << " free(fp);" << endl << "}" << endl; delete [] tagStr; delete [] tagType; } void constructDocument(DOM_Element& el, ofstream& hFile, ofstream& cFile) { static int indent = 0; for (int n = 0; n < indent; n++) { cFile << " "; } char* tagStr = el.getTagName().transcode(); cFile << "<" << tagStr; DOM_NamedNodeMap attrList = el.getAttributes(); int attrListLength = attrList.getLength(); for (int a = 0; a < attrListLength; a++) { DOM_Node node = attrList.item(a); char* name = node.getNodeName().transcode(); char* value = node.getNodeValue().transcode(); cFile << " " << name << "=\\\"" << value << "\\\""; delete [] name; delete [] value; } DOM_NodeList contList = el.getChildNodes(); int contListLength = contList.getLength(); if (contListLength > 0) { cFile << ">" << endl; indent++; for (int c = 0; c < contListLength; c++) { DOM_Node node = contList.item(c); if (node.getNodeType() == ELEMENT_NODE) { DOM_Element contEl = (DOM_Element&) node; constructDocument(contEl,hFile,cFile); } } indent--; for (int n = 0; n < indent; n++) { cFile << " "; } cFile << "" << endl; } else { cFile << " />" << endl; } delete [] tagStr; } int main(int argC, char* argV[]) { try { XMLPlatformUtils::Initialize(); } catch (const XMLException& toCatch) { cerr << "hddm-c: Error during initialization! :\n" << StrX(toCatch.getMessage()) << endl; return 1; } if (argC < 2) { usage(); return 1; } else if ((argC == 2) && (strcmp(argV[1], "-?") == 0)) { usage(); return 2; } const char* xmlFile = 0; 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 = argV[++argInd]; } else { cerr << "Unknown option \'" << argV[argInd] << "\', ignoring it\n" << endl; } } if (argInd != argC - 1) { usage(); return 1; } xmlFile = argV[argInd]; DOMParser parser; parser.setValidationScheme(DOMParser::Val_Never); parser.setCreateEntityReferenceNodes(false); parser.setDoNamespaces(false); MyOwnErrorHandler errorHandler; parser.setErrorHandler(&errorHandler); try { parser.parse(xmlFile); } catch (const XMLException& toCatch) { cerr << "\nhddm-c: Error during parsing: '" << xmlFile << "'\n" << "Exception message is: \n" << StrX(toCatch.getMessage()) << "\n" << endl; return -1; } catch (const DOM_DOMException& toCatch) { cerr << "\nhddm-c: Error during parsing: '" << xmlFile << "'\n" << "Exception message is: \n" << toCatch.msg.transcode() << "\n" << endl; XMLPlatformUtils::Terminate(); return 4; } catch (...) { cerr << "\nhddm-c: Unexpected exception during parsing: '" << xmlFile << "'\n"; XMLPlatformUtils::Terminate(); return 4; } if (errorHandler.getSawErrors()) { cerr << "\nErrors occured, no output available\n" << endl; } DOM_Document doc = parser.getDocument(); DOM_Element rootEl = doc.getDocumentElement(); char* rootStr = rootEl.getTagName().transcode(); if (strcmp(rootStr,"HDDM") != 0) { cerr << "hddm-c error: root element of input document is " << "\"" << rootStr << "\", expected \"HDDM\"" << endl; delete [] rootStr; return 1; } delete [] rootStr; classPrefix = rootEl.getAttribute("class").transcode(); char hname[510]; if (verifyOnly) { sprintf(hname,"/dev/null"); } else if (hFilename) { sprintf(hname,"%s.h",hFilename); } else { sprintf(hname,"hddm_%s.h",classPrefix); } ofstream hFile(hname); if (hFile == 0) { cerr << "hddm-c error: unable to open output file " << hname << endl; return 1; } char cname[510]; if (verifyOnly) { sprintf(cname,"/dev/null"); } else if (hFilename) { sprintf(cname,"%s.c",hFilename); } else { sprintf(cname,"hddm_%s.c",classPrefix); } ofstream cFile(cname); if (cFile == 0) { cerr << "hddm-c error: unable to open output file " << cname << endl; return 1; } hFile << "/*" << endl << " * " << hname << " - DO NOT EDIT THIS FILE" << endl << " *" << endl << " * This file was generated automatically from the" << " file " << xmlFile << " by hddm-c." << endl << " * This header file defines the c structures that" << " hold the data described" << endl << " * in the data model (from " << xmlFile << "). " << " Any program that needs access to the" << endl << " * data described in the model can include" << " this header file, and make use" << endl << " * of the input/output services provided in" << cname << endl << " *" << endl << " * The hddm data model tool set was written by" << endl << " * Richard Jones, University of Connecticut." << endl << " *" << endl << " * For more information see the following web site"<< endl << " *" << endl << " * http://zeus.phys.uconn.edu/halld/datamodel/doc" << endl << " *" << endl << " */" << endl << endl; cFile << "/*" << endl << " * " << cname << " - DO NOT EDIT THIS FILE" << endl << " *" << endl << " * This file was generated automatically from the" << " file " << xmlFile << " by hddm-c." << endl << " * This c file contains the i/o interface to the" << " c structures described" << endl << " * in the data model (from " << xmlFile << "). " << " Any program that needs access to the" << endl << " * data described in the model can compile" << " this c source file, and make use" << endl << " * of the input/output services provided." << endl << " *" << endl << " * The hddm data model tool set was written by" << endl << " * Richard Jones, University of Connecticut." << endl << " *" << endl << " * For more information see the following web site"<< endl << " *" << endl << " * http://zeus.phys.uconn.edu/halld/datamodel/doc" << endl << " */" << endl << endl; hFile << "#include " << endl << "#include " << endl << "#include " << endl << "#include " << endl; cFile << "#include \"" << hname << "\"" << endl; constructGroup(rootEl,hFile,cFile); constructMakeFuncs(rootEl,hFile,cFile); hFile << endl << "#ifndef " << classPrefix << "_DocumentString" << endl << "#define " << classPrefix << "_DocumentString" << endl << endl << "extern " << "char HDDM_" << classPrefix << "_DocumentString[];" << endl << endl << "#endif /* " << classPrefix << "_DocumentString */" << endl; cFile << endl << "char HDDM_" << classPrefix << "_DocumentString[]" << " = \"" << endl; constructDocument(rootEl,hFile,cFile); cFile << "\";" << endl; constructReadFunc(rootEl,hFile,cFile); constructFlushFunc(rootEl,hFile,cFile); constructOpenFunc(rootEl,hFile,cFile); constructInitFunc(rootEl,hFile,cFile); constructCloseFunc(rootEl,hFile,cFile); XMLPlatformUtils::Terminate(); return 0; } MyOwnErrorHandler::MyOwnErrorHandler() : fSawErrors(false) { } MyOwnErrorHandler::~MyOwnErrorHandler() { } /* Overrides of the SAX ErrorHandler interface */ void MyOwnErrorHandler::error(const SAXParseException& e) { fSawErrors = true; cerr << "\nhddm-c: Error at file " << StrX(e.getSystemId()) << ", line " << e.getLineNumber() << ", char " << e.getColumnNumber() << "\n Message: " << StrX(e.getMessage()) << endl; } void MyOwnErrorHandler::fatalError(const SAXParseException& e) { fSawErrors = true; cerr << "\nhddm-c: Fatal Error at file " << StrX(e.getSystemId()) << ", line " << e.getLineNumber() << ", char " << e.getColumnNumber() << "\n Message: " << StrX(e.getMessage()) << endl; } void MyOwnErrorHandler::warning(const SAXParseException& e) { cerr << "\nhddm-c: Warning at file " << StrX(e.getSystemId()) << ", line " << e.getLineNumber() << ", char " << e.getColumnNumber() << "\n Message: " << StrX(e.getMessage()) << endl; } void MyOwnErrorHandler::resetErrors() { }