84 #ifdef FIX8_HAVE_GETOPT_H
93 const string Ctxt::_exts[count] {
"_types.c",
"_types.h",
"_traits.c",
"_classes.c",
94 "_classes.h",
"_router.h",
"_session.h" },
95 Ctxt::_exts_ver[2] {
"pp",
"xx" };
102 extern const string GETARGLIST(
"hvVo:p:dikn:rst:x:NRc:fbCIWPF:UeH:SDu");
121 ostream *
open_ofile(
const string&
odir,
const string& fname,
string& target);
122 void process_value_enums(FieldSpecMap::const_iterator itr, ostream& ost_hpp, ostream& ost_cpp);
123 const string&
mkel(
const string& base,
const string& compon,
string& where);
124 const string&
filepart(
const string& source,
string& where);
125 void generate_preamble(ostream& to,
const string& fname,
bool isheader,
bool donotedit=
true);
134 const string& msname, ostream& outp, ostream& outh,
const CommonGroupMap& globmap,
const std::string& fixns,
const string cls_prefix=
string());
147 int main(
int argc,
char **argv)
150 bool dump(
false), keep_failed(
false), retain_precomp(
false), second_only(
false), nounique(
false);
153 #ifdef FIX8_HAVE_GETOPT_LONG
154 option long_options[]
156 {
"help", 0, 0,
'h' },
157 {
"version", 0, 0,
'v' },
158 {
"verbose", 0, 0,
'V' },
159 {
"nounique", 0, 0,
'N' },
160 {
"norealm", 0, 0,
'R' },
161 {
"incpath", 0, 0,
'P' },
162 {
"nowarn", 0, 0,
'W' },
163 {
"odir", 1, 0,
'o' },
164 {
"dump", 0, 0,
'd' },
165 {
"extension", 0, 0,
'e' },
166 {
"ignore", 0, 0,
'i' },
167 {
"nocheck", 0, 0,
'C' },
168 {
"noconst", 0, 0,
'U' },
169 {
"info", 0, 0,
'I' },
170 {
"unused", 0, 0,
'u' },
171 {
"fields", 0, 0,
'f' },
172 {
"xfields", 1, 0,
'F' },
173 {
"keep", 0, 0,
'k' },
174 {
"retain", 0, 0,
'r' },
175 {
"binary", 0, 0,
'b' },
176 {
"classes", 1, 0,
'c' },
177 {
"pch", 1, 0,
'H' },
178 {
"second", 0, 0,
's' },
179 {
"defaulted", 0, 0,
'D' },
180 {
"noshared", 0, 0,
'S' },
181 {
"prefix", 1, 0,
'p' },
182 {
"namespace", 1, 0,
'n' },
183 {
"tabsize", 1, 0,
't' },
184 {
"fixt", 1, 0,
'x' },
188 while ((val = getopt_long (argc, argv,
GETARGLIST.c_str(), long_options, 0)) != -1)
190 while ((val = getopt (argc, argv,
GETARGLIST.c_str())) != -1)
196 cout <<
"f8c for " << Session::copyright_string() << endl;
200 cout << pp.first <<
": " << pp.second << endl;
202 case 'V':
verbose =
true;
break;
204 case 'N': nounique =
true;
break;
205 case 'R':
norealm =
true;
break;
206 case 'C':
nocheck =
true;
break;
212 case ':':
case '?':
return 1;
214 case 'd': dump =
true;
break;
217 case 'P':
incpath =
false;
break;
218 case 'k': keep_failed =
true;
break;
219 case 'r': retain_precomp =
true;
break;
220 case 's': second_only =
true;
break;
223 case 't':
tabsize = stoul(optarg);
break;
224 case 'p':
prefix = optarg;
break;
227 case 'x':
fixt = optarg;
break;
228 case 'n': ctxt.
_fixns = optarg;
break;
244 cerr <<
"no input xml file specified" << endl;
251 cerr <<
"Error: " <<
gen_classes <<
" not a valid role for class generation. Choose 'server' or 'client'." << endl;
256 unique_ptr<XmlElement> cfr;
262 cerr <<
"Error reading file \'" <<
inputFile <<
'\'';
264 cerr <<
" (" << strerror(errno) <<
')';
271 cout <<
"expanding " <<
shortName <<
' ';
276 cerr << endl <<
"Error opening: " <<
odir <<
'/' <<
shortName;
278 cerr <<
" (" << strerror(errno) <<
')';
287 cerr <<
" (" << strerror(errno) <<
')';
291 unsigned xmlsz(pcmp->GetLineCnt()), fixtsz(0);
297 cerr <<
"Error reading file \'" <<
fixt <<
'\'';
299 cerr <<
" (" << strerror(errno) <<
')';
303 fixtsz = pcmpfixt->GetLineCnt();
305 cout << (fixtsz + xmlsz) <<
" => ";
313 cout << cfr->GetLineCnt() <<
" lines" << endl;
318 if (cfr->GetErrorCnt())
320 cerr << cfr->GetErrorCnt() <<
" error"
321 << (cfr->GetErrorCnt() == 1 ?
" " :
"s ") <<
"found in \'" <<
shortName <<
'\'' << endl;
335 cerr <<
"Error: " << ctxt.
_beginstr <<
" requires an additional FIXT schema specification." << endl;
339 for (
unsigned ii(0); ii < Ctxt::count; ++ii)
342 ctxt.
_out[ii].first.first = ctxt.
_out[ii].first.second +
".p2";
343 remove(ctxt.
_out[ii].first.first.c_str());
352 cout <<
"compiling " <<
shortName << endl;
357 XmlElement *flds(const_cast<XmlElement*>(cfr->find(
"fix/fields"))),
358 *msgs(const_cast<XmlElement*>(cfr->find(
"fix/messages")));
361 const RegExp rMS(
"([^:]+):(Y|N)");
366 unique_ptr<XmlElement> nel(
new XmlElement(istr, 0, flds));
368 if (nel->GetTag().empty() || !nel->GetAttr(
"messages", what) || !flds->Insert(nel.get()))
375 string msg_name, mandatory;
376 rMS.
SubExpr(match, what, msg_name, 0, 1);
377 rMS.
SubExpr(match, what, mandatory, 0, 2);
379 rMS.
Erase(match, what);
380 const string name_tag(
"name");
381 XmlElement *tmsg(const_cast<XmlElement*>(msgs->
find(
"messages/message", &name_tag, &msg_name)));
385 cerr <<
"message: " << msg_name <<
" not found for custom specification" << endl;
391 nel->GetAttr(name_tag, field_name);
392 ostr <<
"<field name='" << field_name <<
"' required='" << mandatory <<
"' />";
393 istringstream mistr(ostr.str());
394 unique_ptr<XmlElement> mel(
new XmlElement(mistr, 0, msgs));
395 if (!mel->GetTag().empty() && tmsg->
Insert(mel.get()))
404 cout << added <<
" candidate custom fields found" << endl;
410 for (
unsigned ii(0); ii < Ctxt::count; ++ii)
412 delete ctxt.
_out[ii].second;
416 remove(ctxt.
_out[ii].first.first.c_str());
423 string backup(ctxt.
_out[ii].first.second +
".old");
424 remove(backup.c_str());
425 rename(ctxt.
_out[ii].first.second.c_str(), backup.c_str());
426 if (rename(ctxt.
_out[ii].first.first.c_str(), ctxt.
_out[ii].first.second.c_str()))
428 cerr <<
"Error renaming files \'" << ctxt.
_out[ii].first.first <<
"' to '" << ctxt.
_out[ii].first.second;
430 cerr <<
" (" << strerror(errno) <<
')';
435 remove(ctxt.
_out[Ctxt::session_hpp].first.second.c_str());
439 cerr <<
"exception: " << e.
what() << endl;
456 if (!xf.
find(
"fix/fields/field", flist))
458 cerr <<
"error: No fields found in " <<
shortName << endl;
464 for(
const auto *pp : flist)
466 string number, name, type;
467 if (pp->GetAttr(
"number", number) && pp->GetAttr(
"name", name) && pp->GetAttr(
"type", type))
473 const auto bmitr(FieldSpec::_baseTypeMap.find(type));
474 FieldTrait::FieldType ft(bmitr == FieldSpec::_baseTypeMap.end() ? FieldTrait::ft_untyped : bmitr->second);
475 pair<FieldSpecMap::iterator, bool> result;
476 if (ft != FieldTrait::ft_untyped)
480 result = fspec.insert({stoul(number),
FieldSpec(name, ft)});
484 cerr <<
shortName <<
':' <<
recover_line(*pp) <<
": error: Failed to convert (stoul) number " << number <<
" in " << name << endl;
491 cerr <<
shortName <<
':' <<
recover_line(*pp) <<
": warning: Unknown field type: " << type <<
" in " << name << endl;
496 pp->GetAttr(
"description", result.first->second._description);
497 pp->GetAttr(
"comment", result.first->second._comment);
502 if (pp->find(
"field/value", realmlist))
504 for(
const auto *pp : realmlist)
506 string enum_str, description;
507 if (pp->GetAttr(
"enum", enum_str))
509 if (!pp->GetAttr(
"description", description) || description.empty())
510 description = enum_str;
512 if (!result.first->second._dvals)
513 result.first->second._dvals =
new RealmMap;
515 bool isRange(pp->GetAttr(
"range", rangeend) && (rangeend ==
"lower" || rangeend ==
"upper"));
516 RealmObject *realmval(RealmObject::create(enum_str, ft, isRange));
518 result.first->second._dtype = RealmBase::dt_range;
520 result.first->second._dvals->insert({realmval, description});
524 cerr <<
shortName <<
':' <<
recover_line(*pp) <<
": error: field value element missing required attribute (enum)." << endl;
532 cerr <<
shortName <<
':' <<
recover_line(*pp) <<
": error: field definition element missing required attributes (number, name or type)" << endl;
544 int msgssLoaded(0), grpsparsed(0);
547 if (!xf.
find(
"fix/messages/message", mlist))
549 cerr <<
"error: No messages found in " <<
shortName << endl;
554 if (!xf.
find(
"fix/header", mlist))
556 cerr <<
"error: No header element found in " <<
shortName << endl;
561 if (!xf.
find(
"fix/trailer", mlist))
563 cerr <<
"error: No trailer element found in " <<
shortName << endl;
569 FieldSpecMap::const_iterator fsitr(fspec.find(35));
570 if (fsitr == fspec.end() || !fsitr->second._dvals)
572 cerr <<
"error: Could not locate MsgType realm defintions in '" <<
shortName
573 <<
"'. See FAQ for more details." << endl;
578 for(
const auto *pp : mlist)
580 string msgcat, name, msgtype, elname;
581 if (pp->GetTag() ==
"header")
582 msgtype = name = elname =
"header";
583 else if (pp->GetTag() ==
"trailer")
584 msgtype = name = elname =
"trailer";
585 else if (pp->GetAttr(
"msgtype", msgtype) && pp->GetAttr(
"name", name) && pp->GetAttr(
"msgcat", msgcat))
588 RealmMap::const_iterator ditr(fsitr->second._dvals->find(&srealm));
589 if (ditr == fsitr->second._dvals->end())
592 << name <<
"' does not have corrresponding entry in MsgType field realm. See FAQ for more details." << endl;
601 cerr <<
shortName <<
':' <<
recover_line(*pp) <<
": error: Message element missing required attributes" << endl;
606 pair<MessageSpecMap::iterator, bool> result(mspec.insert({msgtype, MessageSpec(name, msgcat %
"admin")}));
609 cerr <<
shortName <<
':' <<
recover_line(*pp) <<
": error: Could not add message '" << name <<
"' (" << msgtype <<
")" << endl;
616 if (pp->find(
mkel(elname,
"group", elpart), grplist))
617 grpsparsed +=
parse_groups(result.first->second, name, ftonSpec, fspec, grplist, compon, globmap);
619 pp->GetAttr(
"comment", result.first->second._comment);
627 cout << grpsparsed <<
" repeating groups defined" << endl;
639 for(
const auto *pp : grplist)
641 string gname, required;
642 if (pp->GetAttr(
"name", gname) && pp->GetAttr(
"required", required))
645 unsigned compidx(pp->GetAttr(
"component", compname) ?
lookup_component(compon, compname) : 0);
648 FieldToNumMap::const_iterator ftonItr(ftonSpec.find(gname));
649 FieldSpecMap::const_iterator fs_itr;
650 if (ftonItr != ftonSpec.end() && (fs_itr = fspec.find(ftonItr->second)) != fspec.end())
653 required ==
"Y",
true, compidx)))
656 cerr <<
"warning: Could not add group trait object '" << gname <<
"' (duplicate ?)" << endl;
661 fs_itr->second._used =
true;
662 pair<GroupMap::iterator, bool> gresult(ritr.
_groups.insert({fs_itr->first, MessageSpec(gname)}));
668 if (pp->find(
"group/group", comlist))
669 result +=
parse_groups(gresult.first->second, gname, ftonSpec, fspec, comlist, compon, globmap);
670 CommonGroupMap::iterator cgitr(globmap.find(fs_itr->first));
671 if (cgitr == globmap.end())
672 cgitr = globmap.insert(make_pair(fs_itr->first,
CommonGroups())).first;
673 const uint32_t hv(
group_hash(gresult.first->second));
674 gresult.first->second._hash = hv;
675 cgitr->second.insert(make_pair(hv, gresult.first->second));
676 CommonGroups::iterator cghitr(cgitr->second.find(hv));
677 if (cghitr != cgitr->second.end())
679 cghitr->second._group_refcnt++;
680 cghitr->second._hash = hv;
686 cerr <<
"warning: Could not add group map '" << fs_itr->first <<
"' (duplicate ?)" << endl;
694 <<
": error: Could not locate group Field '" << gname <<
"' from known field types in " <<
shortName << endl;
701 cerr <<
shortName <<
':' <<
recover_line(*pp) <<
": error: group element missing required attributes (name or required)" << endl;
715 const string dspacer(depth *
tabsize,
' '), d2spacer((depth + 1) * tabsize,
' ');
717 outh << dspacer <<
"GroupBase *create_nested_group(unsigned short fnum) const" << endl;
720 outh << dspacer <<
'{' << endl;
721 outh << dspacer <<
spacer <<
"switch(fnum)" << endl << dspacer <<
spacer <<
'{' << endl;
722 for (
const auto& pp : ms.
_groups)
724 FieldSpecMap::const_iterator gsitr(fspec.find(pp.first));
725 outh << dspacer <<
spacer <<
"case " << gsitr->first <<
": return new " << gsitr->second._name <<
';' << endl;
727 outh << dspacer <<
spacer <<
"default: return nullptr;" << endl;
728 outh << dspacer <<
spacer <<
'}' << endl;
729 outh << dspacer <<
'}' << endl;
733 const auto& pp(*ms.
_groups.cbegin());
734 FieldSpecMap::const_iterator gsitr(fspec.find(pp.first));
735 outh << dspacer <<
spacer <<
"{ return fnum == " << gsitr->first <<
" ? new "
736 << gsitr->second._name <<
" : nullptr; }" << endl;
743 ostream& outp, ostream& outh,
const CommonGroupMap& globmap,
const std::string& fixns,
const string cls_prefix)
745 const string dspacer(depth *
tabsize,
' '), d2spacer((depth + 1) * tabsize,
' ');
748 if (!cls_prefix.empty())
749 prefix = cls_prefix +
"::";
751 for (
const auto& pp : ms.
_groups)
753 FieldSpecMap::const_iterator gsitr(fspec.find(pp.first));
760 cout << pp.first <<
" not found" << endl;
765 rnme << gsitr->second._name;
770 outp <<
"const FieldTrait *" << prefix << ms.
_name <<
"::" << gsitr->second._name <<
"::_traits("
771 << rnme.str() <<
"_traits);" << endl;
777 outp <<
"const FieldTrait_Hash_Array" <<
"& " << prefix << ms.
_name <<
"::" << gsitr->second._name <<
"::_ftha("
778 << rnme.str() <<
"_ftha);" << endl;
779 outp <<
"const MsgType" <<
"& " << prefix << ms.
_name <<
"::" << gsitr->second._name <<
"::_msgtype("
780 << rnme.str() <<
"_msgtype);" << endl;
783 outp <<
"const MsgType " << prefix << ms.
_name <<
"::" << gsitr->second._name <<
"::_msgtype("
784 <<
'"' << gsitr->second._name <<
"\");" << endl;
787 outh << endl << dspacer <<
"/// " << tgroup->
_name <<
" (" << pp.first <<
"), "
790 << tgroup->
_groups.size() <<
" grou" << (tgroup->
_groups.size() == 1 ?
"p, " :
"ps, ")
791 << (tgroup->
_group_refcnt > 1 ?
"shares static data" :
"is unique") <<
", hash: 0x"
792 << hex << tgroup->
_hash << dec << endl;
793 outh << dspacer <<
"// " << prefix << ms.
_name <<
"::" << gsitr->second._name << endl;
794 outh << dspacer <<
"class " << gsitr->second._name
795 <<
" : public GroupBase // depth: " << depth << endl << dspacer <<
'{' << endl;
798 outh << d2spacer <<
"static F8_" << fixns <<
"_API const FieldTrait *_traits;" << endl;
799 outh << d2spacer <<
"static F8_" << fixns <<
"_API const FieldTrait_Hash_Array& _ftha;" << endl;
800 outh << d2spacer <<
"static F8_" << fixns <<
"_API const MsgType& _msgtype;" << endl;
804 outh << d2spacer <<
"static F8_" << fixns <<
"_API const FieldTrait _traits[];" << endl;
805 outh << d2spacer <<
"static F8_" << fixns <<
"_API const FieldTrait_Hash_Array _ftha;" << endl;
806 outh << d2spacer <<
"static F8_" << fixns <<
"_API const MsgType _msgtype;" << endl;
808 outh << d2spacer <<
"static const unsigned _fieldcnt = " << tgroup->
_fields.
get_presence().
size() <<
';' << endl << endl;
809 outh << dspacer <<
"public:" << endl;
810 outh << d2spacer <<
"enum { _fnum = " << gsitr->first <<
" };" << endl << endl;
811 outh << d2spacer << gsitr->second._name <<
"() : GroupBase(_fnum) {}" << endl;
812 outh << d2spacer <<
"~" << gsitr->second._name <<
"() = default;" << endl;
814 outh << d2spacer <<
"MessageBase *create_group(bool) const { return new MessageBase(ctx(), _msgtype(), _traits, _fieldcnt, &_ftha); }" << endl;
817 outh << d2spacer <<
"MessageBase *create_group(bool deepctor) const" << endl << d2spacer <<
'{' << endl;
818 outh << d2spacer <<
spacer <<
"MessageBase *mb(new MessageBase(ctx(), _msgtype(), _traits, _fieldcnt, &_ftha));" << endl;
819 outh << d2spacer <<
spacer <<
"if (deepctor)" << endl;
820 outh << d2spacer <<
spacer <<
spacer <<
"mb->get_groups().insert({";
821 if (tgroup->
_groups.size() == 1)
822 outh << tgroup->
_groups.begin()->first <<
", new " << tgroup->
_groups.begin()->second._name <<
" });" << endl;
826 for (
const auto& qq : tgroup->
_groups)
827 outh << d2spacer << spacer << spacer << spacer <<
"{ " << qq.first <<
", new " << qq.second._name <<
" }," << endl;
828 outh << d2spacer << spacer << spacer <<
"});" << endl;
831 outh << d2spacer << spacer <<
"return mb;" << endl;
832 outh << d2spacer <<
'}' << endl;
834 outh << endl << d2spacer <<
"static const " << msname <<
"& get_msgtype() { return _msgtype; }" << endl;
835 #if defined FIX8_HAVE_EXTENDED_METADATA
836 outh << d2spacer <<
"static const FieldTrait *get_traits() { return _traits; };" << endl;
837 outh << d2spacer <<
"static const unsigned get_fieldcnt() { return _fieldcnt; };" << endl;
848 outh << dspacer <<
"};" << endl;
856 outp <<
"const FieldTrait " << gname <<
"_traits[]"
859 outp <<
"const FieldTrait " << prefix << gname <<
"::_traits[]" << endl <<
'{' << endl;
875 tostr <<
"0x" << setfill(
'0') << setw(2) << hex << flitr->_field_traits.get();
876 outp << (spaceme ?
spacer :
" ");
877 outp <<
'{' << setw(4) << right << flitr->_fnum <<
',' << setw(2)
878 << right << flitr->_ftype <<
',' << setw(3) << right << flitr->_pos <<
879 ',' << setw(3) << right << flitr->_component <<
',' << tostr.str();
880 #if defined FIX8_HAVE_EXTENDED_METADATA
884 FieldSpecMap::const_iterator gsitr(fspec.find(flitr->_fnum));
885 outp << gsitr->second._name <<
"::get_traits(), " << gsitr->second._name <<
"::get_fieldcnt()";
886 outp << endl << spacer <<
'}';
893 outp << endl <<
"};" << endl;
896 outp <<
"const FieldTrait_Hash_Array " << gname <<
"_ftha(" << gname <<
"_traits, "
898 outp <<
"const MsgType " << gname <<
"_msgtype(\"" << gname <<
"\");" << endl;
901 outp <<
"const FieldTrait_Hash_Array " << endl <<
spacer << prefix << gname
902 <<
"::_ftha(" << prefix << gname <<
"::_traits, " << gname <<
"::_fieldcnt);" << endl;
908 for (
const auto& pp : globmap)
911 for (
const auto& ii : pp.second)
913 if (ii.second._group_refcnt > 1)
915 FieldSpecMap::const_iterator gsitr(fspec.find(pp.first));
918 gostr << gsitr->second._name <<
'V' << vers;
930 ostream& ost_cpp(*ctxt.
_out[Ctxt::types_cpp].second);
931 ostream& ost_hpp(*ctxt.
_out[Ctxt::types_hpp].second);
932 ostream& osr_cpp(*ctxt.
_out[Ctxt::traits_cpp].second);
933 ostream& osc_hpp(*ctxt.
_out[Ctxt::classes_hpp].second);
934 ostream& osc_cpp(*ctxt.
_out[Ctxt::classes_cpp].second);
935 ostream& osu_hpp(*ctxt.
_out[Ctxt::router_hpp].second);
936 ostream& oss_hpp(*ctxt.
_out[Ctxt::session_hpp].second);
945 cout << fields <<
" fields defined" << endl;
950 for (
const auto& pp : fspec)
951 ftonSpec.insert({pp.second._name, pp.first});
955 xf.
find(
"fix/components/component", comlist);
961 int msgsloaded(
load_messages(xf, mspec, ftonSpec, fspec, components, globmap));
966 cout << msgsloaded <<
" messages defined" << endl;
967 if (components.size())
968 cout << components.size() <<
" components defined" << endl;
971 unsigned cgs(0), ugs(0), vars(0);
972 for (
const auto& pp : globmap)
974 vars +=
static_cast<unsigned>(pp.second.size());
975 for (
const auto& ii : pp.second)
977 if (ii.second._group_refcnt > 1)
978 ugs += ii.second._group_refcnt;
983 cout << globmap.size() <<
" repeating group catagories (" << vars <<
" variants, "
984 << ugs <<
" common, " << cgs <<
" unique) processed" << endl;
993 osu_hpp <<
"#ifndef " <<
bintoaschex(ctxt.
_out[Ctxt::router_hpp].first.second) << endl;
994 osu_hpp <<
"#define " <<
bintoaschex(ctxt.
_out[Ctxt::router_hpp].first.second) << endl << endl;
996 osu_hpp <<
"namespace " << ctxt.
_fixns <<
" {" << endl;
1000 osc_hpp <<
"#ifndef " <<
bintoaschex(ctxt.
_out[Ctxt::classes_hpp].first.second) << endl;
1001 osc_hpp <<
"#define " <<
bintoaschex(ctxt.
_out[Ctxt::classes_hpp].first.second) << endl << endl;
1004 osc_hpp << endl <<
"extern \"C\"" << endl <<
'{' << endl
1005 <<
spacer <<
"F8_" << ctxt.
_fixns <<
"_API const F8MetaCntx& " << ctxt.
_fixns <<
"_ctx();" << endl <<
'}' << endl << endl;
1006 osc_hpp <<
"namespace " << ctxt.
_fixns <<
" {" << endl;
1009 osc_hpp <<
"using " << ctxt.
_clname <<
"_BaseMsgEntry = MsgTable;" << endl;
1010 osc_hpp <<
"/// Compiler generated metadata object, accessed through this function." << endl;
1011 osc_hpp <<
"F8_" << ctxt.
_fixns <<
"_API " <<
"const F8MetaCntx& ctx();" << endl;
1012 osc_hpp <<
"class " << ctxt.
_clname <<
"_Router;" << endl;
1018 osc_cpp <<
"#include \"" << ctxt.
_out[Ctxt::types_hpp].first.second <<
'"' << endl;
1019 osc_cpp <<
"#include \"" << ctxt.
_out[Ctxt::router_hpp].first.second <<
'"' << endl;
1020 osc_cpp <<
"#include \"" << ctxt.
_out[Ctxt::classes_hpp].first.second <<
'"' << endl;
1023 osc_cpp <<
"namespace " << ctxt.
_fixns <<
" {" << endl << endl;
1030 osr_cpp <<
"#include \"" << ctxt.
_out[Ctxt::types_hpp].first.second <<
'"' << endl;
1031 osr_cpp <<
"#include \"" << ctxt.
_out[Ctxt::router_hpp].first.second <<
'"' << endl;
1032 osr_cpp <<
"#include \"" << ctxt.
_out[Ctxt::classes_hpp].first.second <<
'"' << endl;
1035 osr_cpp <<
"namespace " << ctxt.
_fixns <<
" {" << endl << endl;
1043 osr_cpp <<
"// Common group traits" << endl;
1044 osr_cpp <<
"namespace {" << endl;
1046 osr_cpp <<
"} // namespace" << endl << endl;
1048 #if defined FIX8_HAVE_EXTENDED_METADATA
1051 osr_cpp <<
"//" << endl;
1052 osr_cpp <<
"// Shared groups disabled (--noshared). Static traits are now exposed." << endl;
1053 osr_cpp <<
"//" << endl;
1057 osr_cpp <<
"// Message traits" << endl;
1059 FieldSpecMap::const_iterator fsitr(fspec.find(35));
1060 for (
const auto& pp : mspec)
1062 bool isTrailer(pp.second._name ==
"trailer");
1063 bool isHeader(pp.second._name ==
"header");
1064 osc_hpp <<
"/// " << pp.second._name <<
" (" << pp.first <<
"), "
1065 << (pp.second._is_admin ?
"admin" :
"application")
1066 <<
", " << pp.second._fields.get_presence().size() <<
" fiel"
1067 << (pp.second._fields.get_presence().size() == 1 ?
"d, " :
"ds, ")
1068 << pp.second._groups.size() <<
" grou" << (pp.second._groups.size() == 1 ?
"p." :
"ps.");
1069 if (!pp.second._comment.empty())
1070 osc_hpp <<
' ' << pp.second._comment;
1072 osc_hpp <<
"class " << pp.second._name <<
" : public "
1073 << (isTrailer || isHeader ?
"MessageBase" :
"Message") << endl <<
'{' << endl;
1075 if (pp.second._fields.get_presence().size())
1078 osr_cpp <<
"const FieldTrait " << pp.second._name <<
"::_traits[]"
1079 << endl <<
'{' << endl;
1082 flitr != pp.second._fields.get_presence().end(); ++flitr, ++felpos)
1085 if (flitr != pp.second._fields.get_presence().begin())
1088 if (felpos % 4 == 0)
1094 ostringstream tostr;
1095 tostr <<
"0x" << setfill(
'0') << setw(2) << hex << flitr->_field_traits.get();
1096 osr_cpp << (spaceme ?
spacer :
" ");
1097 osr_cpp <<
'{' << setw(4) << right << flitr->_fnum <<
','
1098 << setw(2) << right << flitr->_ftype <<
',' << setw(3) << right
1099 << flitr->_pos <<
',' << setw(3) << right << flitr->_component <<
',' << tostr.str();
1100 #if defined FIX8_HAVE_EXTENDED_METADATA
1104 FieldSpecMap::const_iterator gsitr(fspec.find(flitr->_fnum));
1105 osr_cpp << gsitr->second._name <<
"::get_traits(), " << gsitr->second._name <<
"::get_fieldcnt()";
1106 osr_cpp << endl << spacer <<
'}';
1113 osr_cpp << endl <<
"};" << endl;
1114 osr_cpp <<
"const FieldTrait_Hash_Array " << pp.second._name <<
"::_ftha(" << pp.second._name <<
"::_traits, "
1115 << pp.second._name <<
"::_fieldcnt);" << endl;
1116 osr_cpp <<
"const MsgType " << pp.second._name <<
"::_msgtype(\"" << pp.first <<
"\");" << endl;
1117 osc_hpp <<
spacer <<
"static F8_" << ctxt.
_fixns <<
"_API const FieldTrait _traits[];" << endl;
1118 osc_hpp <<
spacer <<
"static F8_" << ctxt.
_fixns <<
"_API const FieldTrait_Hash_Array _ftha; " << endl;
1119 osc_hpp <<
spacer <<
"static F8_" << ctxt.
_fixns <<
"_API const MsgType _msgtype;" << endl;
1120 osc_hpp <<
spacer <<
"static F8_" << ctxt.
_fixns <<
"_API const unsigned _fieldcnt = " << pp.second._fields.get_presence().size() <<
';' << endl;
1125 osc_hpp << endl <<
spacer <<
"begin_string *_begin_string;" << endl;
1126 osc_hpp <<
spacer <<
"body_length *_body_length;" << endl;
1127 osc_hpp <<
spacer <<
"msg_type *_msg_type;" << endl;
1130 osc_hpp << endl <<
spacer <<
"check_sum *_check_sum;" << endl;
1134 osc_hpp <<
"public:" << endl;
1135 osc_hpp <<
spacer <<
"explicit " << pp.second._name <<
"(bool deepctor=true)";
1136 if (pp.second._fields.get_presence().size())
1137 osc_hpp <<
" : " << (isTrailer || isHeader ?
"MessageBase" :
"Message")
1138 <<
"(ctx(), _msgtype(), _traits, _fieldcnt, &_ftha)";
1139 if (isHeader || isTrailer)
1143 osc_hpp <<
"_begin_string(new begin_string(ctx()._beginStr)), _body_length(new body_length), _msg_type(new msg_type)";
1145 osc_hpp <<
"_check_sum(new check_sum)";
1146 osc_hpp <<
" { add_preamble(); }" << endl;
1148 else if (!pp.second._groups.empty())
1150 osc_hpp << endl <<
spacer <<
'{' << endl;
1151 osc_hpp <<
spacer <<
spacer <<
"if (deepctor)" << endl;
1153 if (pp.second._groups.size() == 1)
1154 osc_hpp << pp.second._groups.begin()->first <<
", new " << pp.second._groups.begin()->second._name <<
" });" << endl;
1158 for (
const auto& ii : pp.second._groups)
1160 FieldSpecMap::const_iterator gsitr(fspec.find(ii.first));
1161 osc_hpp << spacer << spacer << spacer << spacer <<
"{ " << gsitr->first <<
", new " << gsitr->second._name <<
" }," << endl;
1163 osc_hpp << spacer << spacer << spacer <<
"});" << endl;
1165 osc_hpp << spacer <<
'}' << endl;
1168 osc_hpp <<
" {}" << endl;
1170 osc_hpp <<
spacer <<
"~" << pp.second._name <<
"() = default;" << endl;
1171 if (!isHeader && !isTrailer)
1173 osc_hpp <<
spacer <<
"bool process(Router& rt) const { return (static_cast<" << ctxt.
_clname <<
"_Router&>(rt))(this); }" << endl;
1174 if (pp.second._is_admin)
1175 osc_hpp <<
spacer <<
"bool is_admin() const { return true; }" << endl;
1178 osc_hpp << endl <<
spacer <<
"static const " << fsitr->second._name <<
"& get_msgtype() { return _msgtype; }" << endl;
1179 #if defined FIX8_HAVE_EXTENDED_METADATA
1180 osc_hpp <<
spacer <<
"static const FieldTrait *get_traits() { return _traits; };" << endl;
1181 osc_hpp <<
spacer <<
"static const unsigned get_fieldcnt() { return _fieldcnt; };" << endl;
1193 osc_hpp <<
"};" << endl << endl;
1201 osc_cpp <<
"const char *cn[] // Component names" << endl <<
'{' << endl;
1202 osc_cpp <<
spacer <<
"\"\"," << endl;
1203 for (Components::iterator citr(components.begin()); citr != components.end(); ++citr)
1204 osc_cpp <<
spacer <<
'"' << citr->first <<
"\", // " << (1 + distance(components.begin(), citr)) << endl;
1205 osc_cpp <<
"};" << endl;
1210 osc_cpp <<
"const " << ctxt.
_fixns <<
"::" << ctxt.
_clname <<
"_BaseMsgEntry::Pair "
1211 <<
"msgpairs[] " << endl <<
'{' << endl;
1212 for (MessageSpecMap::const_iterator mitr(mspec.begin()); mitr != mspec.end(); ++mitr)
1214 if (mitr != mspec.begin())
1215 osc_cpp <<
',' << endl;
1216 osc_cpp <<
spacer <<
"{ \"" << mitr->first <<
"\", { ";
1217 if (mitr->second._name ==
"trailer" || mitr->second._name ==
"header")
1218 osc_cpp <<
"Type2Type<" << ctxt.
_fixns <<
"::" << mitr->second._name <<
", bool>()";
1220 osc_cpp <<
"Type2Type<" << ctxt.
_fixns <<
"::" << mitr->second._name <<
">()";
1221 osc_cpp <<
", \"" << mitr->second._name <<
'"';
1222 if (!mitr->second._comment.empty())
1223 osc_cpp <<
',' << endl <<
spacer <<
spacer <<
'"' << mitr->second._comment <<
"\" }";
1228 osc_cpp << endl <<
"}; // " << mspec.size() << endl;
1230 size_t fields_generated(0);
1231 for (
const auto& pp : fspec)
1235 osc_cpp << endl <<
"extern const " << ctxt.
_clname <<
"_BaseEntry::Pair fldpairs[];" << endl << endl
1236 <<
"/// Compiler generated metadata object, accessed through this function." << endl
1237 <<
"const F8MetaCntx& ctx() // avoid SIOF" << endl <<
'{' << endl
1238 <<
spacer <<
"static const " << ctxt.
_clname <<
"_BaseMsgEntry "
1239 <<
"bme(msgpairs, " << mspec.size() <<
");" << endl
1240 <<
spacer <<
"static const " << ctxt.
_clname <<
"_BaseEntry "
1241 <<
"be(fldpairs, " << fields_generated <<
");" << endl
1242 <<
spacer <<
"static const F8MetaCntx _ctx(" << ctxt.
_version <<
", bme, be, cn, \"" << ctxt.
_beginstr <<
"\");" << endl
1243 <<
spacer <<
"return _ctx;" << endl <<
'}' << endl;
1244 osc_cpp << endl <<
"} // namespace " << ctxt.
_fixns << endl;
1248 osu_hpp <<
"class " << ctxt.
_clname <<
"_Router : public Router" << endl
1249 <<
'{' << endl <<
"public:" << endl;
1250 osu_hpp <<
spacer << ctxt.
_clname <<
"_Router() {}" << endl;
1251 osu_hpp <<
spacer <<
"virtual ~" << ctxt.
_clname <<
"_Router() {}" << endl << endl;
1252 osu_hpp <<
spacer <<
"virtual bool operator() (const class Message *msg) ";
1254 osu_hpp <<
"const ";
1255 osu_hpp <<
"{ return false; }" << endl;
1256 for (
const auto& pp : mspec)
1258 if (pp.second._name ==
"trailer" || pp.second._name ==
"header")
1260 osu_hpp << spacer <<
"virtual bool operator() (const class " << pp.second._name <<
" *msg)";
1262 osu_hpp <<
';' << endl;
1266 osu_hpp <<
" const";
1267 osu_hpp <<
" { return " << (pp.second._is_admin ?
"true" :
"false") <<
"; }" << endl;
1270 osu_hpp <<
"};" << endl;
1273 osc_hpp << endl <<
"} // namespace " << ctxt.
_fixns << endl;
1275 osc_hpp <<
"#endif // " <<
bintoaschex(ctxt.
_out[Ctxt::classes_hpp].first.second) << endl;
1276 osu_hpp << endl <<
"} // namespace " << ctxt.
_fixns << endl;
1278 osu_hpp <<
"#endif // " <<
bintoaschex(ctxt.
_out[Ctxt::router_hpp].first.second) << endl;
1279 osr_cpp << endl <<
"} // namespace " << ctxt.
_fixns << endl;
1281 osc_cpp << endl <<
"// Compiler generated metadata object accessible outside namespace through this function." << endl;
1282 osc_cpp <<
"extern \"C\"" << endl <<
'{' << endl
1283 << spacer <<
"const F8MetaCntx& " << ctxt.
_fixns <<
"_ctx() { return " << ctxt.
_fixns <<
"::ctx(); }"
1284 << endl <<
'}' << endl << endl;
1294 oss_hpp <<
"#ifndef " <<
bintoaschex(ctxt.
_out[Ctxt::session_hpp].first.second) << endl;
1295 oss_hpp <<
"#define " <<
bintoaschex(ctxt.
_out[Ctxt::session_hpp].first.second) << endl;
1298 oss_hpp <<
"// " <<
gen_classes <<
" session and router classes" << endl;
1301 oss_hpp <<
"class " << ctxt.
_clname <<
"_session_" <<
gen_classes <<
';' << endl << endl;
1303 <<
" : public FIX8::" << ctxt.
_fixns <<
"::" << ctxt.
_clname <<
"_Router" << endl <<
'{' << endl;
1304 oss_hpp << spacer << ctxt.
_clname <<
"_session_" <<
gen_classes <<
"& _session; " << endl << endl;
1305 oss_hpp <<
"public:" << endl;
1307 <<
'(' << ctxt.
_clname <<
"_session_" <<
gen_classes <<
"& session) : _session(session) {}" << endl;
1308 oss_hpp << spacer <<
"virtual ~" << ctxt.
_clname <<
"_router_" <<
gen_classes <<
"() {}" << endl << endl;
1309 oss_hpp << spacer <<
"// Override these methods to receive specific message callbacks." << endl;
1310 for (
const auto& pp : mspec)
1312 if (pp.second._name ==
"trailer" || pp.second._name ==
"header")
1314 oss_hpp << spacer <<
"// bool operator() (const FIX8::"
1315 << ctxt.
_fixns <<
"::" << pp.second._name <<
" *msg) const;" << endl;
1317 oss_hpp <<
"};" << endl;
1321 <<
" : public FIX8::Session" << endl <<
'{' << endl;
1322 oss_hpp << spacer << ctxt.
_clname <<
"_router_" <<
gen_classes <<
" _router; " << endl << endl;
1323 oss_hpp <<
"public:" << endl;
1327 oss_hpp <<
"(const FIX8::F8MetaCntx& ctx, FIX8::Persister *persist=0," << endl;
1328 oss_hpp << spacer << spacer <<
"FIX8::Logger *logger=0, FIX8::Logger *plogger=0) : Session"
1329 "(ctx, persist, logger, plogger), _router(*this) {} " << endl << endl;
1333 oss_hpp <<
"(const FIX8::F8MetaCntx& ctx, const FIX8::SessionID& sid, FIX8::Persister *persist=0," << endl;
1334 oss_hpp << spacer << spacer <<
"FIX8::Logger *logger=0, FIX8::Logger *plogger=0) : Session"
1335 "(ctx, sid, persist, logger, plogger), _router(*this) {} " << endl << endl;
1338 oss_hpp << spacer <<
"// Override these methods if required but remember to call the base class method first." << endl
1339 << spacer <<
"// bool handle_logon(const unsigned seqnum, const FIX8::Message *msg);" << endl
1340 << spacer <<
"// Message *generate_logon(const unsigned heartbeat_interval, const f8String davi=f8String());" << endl
1341 << spacer <<
"// bool handle_logout(const unsigned seqnum, const FIX8::Message *msg);" << endl
1342 << spacer <<
"// Message *generate_logout();" << endl
1343 << spacer <<
"// bool handle_heartbeat(const unsigned seqnum, const FIX8::Message *msg);" << endl
1344 << spacer <<
"// Message *generate_heartbeat(const f8String& testReqID);" << endl
1345 << spacer <<
"// bool handle_resend_request(const unsigned seqnum, const FIX8::Message *msg);" << endl
1346 << spacer <<
"// Message *generate_resend_request(const unsigned begin, const unsigned end=0);" << endl
1347 << spacer <<
"// bool handle_sequence_reset(const unsigned seqnum, const FIX8::Message *msg);" << endl
1348 << spacer <<
"// Message *generate_sequence_reset(const unsigned newseqnum, const bool gapfillflag=false);" << endl
1349 << spacer <<
"// bool handle_test_request(const unsigned seqnum, const FIX8::Message *msg);" << endl
1350 << spacer <<
"// Message *generate_test_request(const f8String& testReqID);" << endl
1351 << spacer <<
"// bool handle_reject(const unsigned seqnum, const FIX8::Message *msg);" << endl
1352 << spacer <<
"// Message *generate_reject(const unsigned seqnum, const char *what);" << endl
1353 << spacer <<
"// bool handle_admin(const unsigned seqnum, const FIX8::Message *msg);" << endl
1354 << spacer <<
"// void modify_outbound(FIX8::Message *msg);" << endl
1355 << spacer <<
"// bool authenticate(SessionID& id, const FIX8::Message *msg);" << endl << endl;
1357 oss_hpp << spacer <<
"// Override these methods to intercept admin and application methods." << endl
1358 << spacer <<
"// bool handle_admin(const unsigned seqnum, const FIX8::Message *msg);" << endl << endl
1359 << spacer <<
"bool handle_application(const unsigned seqnum, const FIX8::Message *&msg);" << endl
1360 << spacer <<
"/* In your compilation unit, this should be implemented with something like the following:" << endl
1361 << spacer <<
"bool " << ctxt.
_clname <<
"_session_" <<
gen_classes <<
"::handle_application(const unsigned seqnum, const FIX8::Message *&msg)" << endl
1362 << spacer <<
'{' << endl << spacer << spacer <<
"return enforce(seqnum, msg) || msg->process(_router);" << endl
1363 << spacer <<
'}' << endl << spacer <<
"*/" << endl;
1365 oss_hpp <<
"};" << endl;
1367 oss_hpp << endl <<
"#endif // " <<
bintoaschex(ctxt.
_out[Ctxt::session_hpp].first.second) << endl;
1374 ost_hpp <<
"#ifndef " <<
bintoaschex(ctxt.
_out[Ctxt::types_hpp].first.second) << endl;
1375 ost_hpp <<
"#define " <<
bintoaschex(ctxt.
_out[Ctxt::types_hpp].first.second) << endl << endl;
1377 ost_hpp <<
"namespace " << ctxt.
_fixns <<
" {" << endl;
1383 ost_cpp <<
"#include \"" << ctxt.
_out[Ctxt::types_hpp].first.second <<
'"' << endl;
1386 ost_cpp <<
"namespace " << ctxt.
_fixns <<
" {" << endl << endl;
1391 for (FieldSpecMap::const_iterator fitr(fspec.begin()); fitr != fspec.end(); ++fitr)
1395 if (!fitr->second._comment.empty())
1396 ost_hpp <<
"// " << fitr->second._comment << endl;
1397 const auto tyitr(FieldSpec::_typeToCPP.find(fitr->second._ftype));
1398 ost_hpp <<
"using " << fitr->second._name <<
" = Field<"
1399 << (tyitr == FieldSpec::_typeToCPP.end() ?
"unknown" : tyitr->second.first) <<
", " << fitr->first <<
">;" << endl;
1400 if (fitr->second._dvals)
1407 ost_cpp <<
"const RealmBase realmbases[] " << endl <<
'{' << endl;
1409 for (
auto& pp : fspec)
1411 if ((!pp.second._used && !
gen_fields) || !pp.second._dvals)
1413 const auto tyitr(FieldSpec::_typeToCPP.find(pp.second._ftype));
1414 ost_cpp << spacer <<
"{ reinterpret_cast<const void *>(" << pp.second._name <<
"_realm), "
1415 <<
"RealmBase::" << (pp.second._dtype == RealmBase::dt_set ?
"dt_set" :
"dt_range") <<
", "
1416 <<
"FieldTrait::" << tyitr->second.second <<
", "
1417 << pp.second._dvals->size() <<
", " << pp.second._name <<
"_descriptions }," << endl;
1418 pp.second._doffset = dcnt++;
1420 ost_cpp <<
"};" << endl;
1427 ost_hpp <<
"using " << ctxt.
_clname <<
"_BaseEntry = FieldTable;" << endl;
1430 ost_cpp <<
"extern const " << ctxt.
_clname <<
"_BaseEntry::Pair fldpairs[];" << endl;
1431 ost_cpp <<
"const " << ctxt.
_clname <<
"_BaseEntry::Pair fldpairs[] "
1432 << endl <<
'{' << endl;
1433 for (FieldSpecMap::const_iterator fitr(fspec.begin()); fitr != fspec.end(); ++fitr)
1437 if (fitr != fspec.begin())
1438 ost_cpp <<
',' << endl;
1439 ost_cpp << spacer <<
"{ " << fitr->first <<
", { ";
1440 if (fitr->second._dvals && !
norealm)
1442 ost_cpp <<
"Type2Type<" << ctxt.
_fixns <<
"::" << fitr->second._name <<
", ";
1444 if (!FieldTrait::get_type_string(fitr->second._ftype, ttype).empty())
1448 ost_cpp <<
"unknown";
1449 cerr <<
shortName <<
": error: unknown FieldTrait::type in realm '" << fitr->second._name <<
'\'' << endl;
1454 ost_cpp <<
"Type2Type<" << ctxt.
_fixns <<
"::" << fitr->second._name;
1455 ost_cpp <<
">(), \"" << fitr->second._name <<
"\", " << fitr->first;
1456 if (fitr->second._dvals)
1457 ost_cpp <<
", &" << ctxt.
_fixns <<
"::realmbases[" << fitr->second._doffset <<
']';
1458 if (!fitr->second._comment.empty())
1461 if (!fitr->second._dvals)
1462 ost_cpp <<
"nullptr, ";
1463 ost_cpp << endl << spacer << spacer <<
'"' << fitr->second._comment <<
'"';
1467 ost_cpp << endl <<
"}; // " << fields_generated << endl;
1470 ost_cpp <<
"} // namespace " << ctxt.
_fixns << endl;
1471 ost_hpp << endl <<
"} // namespace " << ctxt.
_fixns << endl;
1473 ost_hpp <<
"#endif // " <<
bintoaschex(ctxt.
_out[Ctxt::types_hpp].first.second) << endl;
1478 unsigned cnt(0), ucnt(0);
1479 for (
const auto& pp : fspec)
1481 if (pp.second._used)
1488 cout <<
"Unused fields: ";
1489 cout << pp.second._name <<
'(' << pp.first <<
')';
1494 cout << cnt <<
" of " << fspec.size() <<
" fields used in messages" << endl;
1503 #if defined __GNUG__
1504 #if defined __GNUC_MINOR__ && __GNUC_PATCHLEVEL__
1505 cout <<
"Compiled with gcc version " << __GNUG__ <<
'.' << __GNUC_MINOR__ <<
'.' <<__GNUC_PATCHLEVEL__ << endl;
1508 const size_t confbufsz(256);
1509 char confbuf[confbufsz];
1510 if (confstr(_CS_GNU_LIBC_VERSION, confbuf, confbufsz))
1512 cout <<
"GNU glibc version is " << confbuf << endl;
1514 if (confstr(_CS_GNU_LIBPTHREAD_VERSION, confbuf, confbufsz))
1516 cout <<
"GNU libpthread version is " << confbuf << endl;
1519 #if defined __GXX_ABI_VERSION
1520 cout <<
"GXX ABI version is " << __GXX_ABI_VERSION << endl;
1523 cout <<
"GCC not used. No information available." << endl;
1530 Components::const_iterator citr(compon.find(name));
1531 return citr != compon.end() ? 1 + distance(compon.begin(), citr) : 0;
1539 static uint32_t result(0);
1546 result =
rothash(result, pp._fnum);
1547 for (
const auto& pp : p1.
_groups)
1556 CommonGroupMap::const_iterator tp_result(globmap.find(tp));
1557 if (tp_result == globmap.end())
1559 CommonGroups::const_iterator key_result(tp_result->second.find(key));
1560 if (key_result == tp_result->second.end())
1562 vers = 1 + distance(tp_result->second.begin(), key_result);
1563 return &key_result->second;
1584 to <<
'"' << precompHdr <<
'"';
1587 to <<
"#include " << (
incpath ?
"<fix8/" :
"<") <<
"f8config.h" <<
'>' << endl;
1590 to <<
"#if defined FIX8_MAGIC_NUM && FIX8_MAGIC_NUM > " <<
FIX8_MAGIC_NUM <<
'L' << endl;
1591 to <<
"#error " << fname <<
" version " <<
FIX8_PACKAGE_VERSION <<
" is out of date. Please regenerate with f8c." << endl;
1592 to <<
"#endif" << endl;
1595 to <<
"// " << fname << endl;
1602 "#if defined(_MSC_VER) && defined(F8_" << ns <<
"_API_SHARED)\n"
1603 " #if defined(BUILD_F8_" << ns <<
"_API)\n"
1604 " #define F8_" << ns <<
"_API __declspec(dllexport)\n"
1606 " #define F8_" << ns <<
"_API __declspec(dllimport)\n"
1609 " #define F8_" << ns <<
"_API\n"
static F8API XmlElement * Factory(std::istream &istr, const char *docpath=nullptr)
int load_fields(XmlElement &xf, FieldSpecMap &fspec)
const MessageSpec * find_group(const CommonGroupMap &globmap, int &vers, unsigned tp, uint32_t key)
int precompfixt(XmlElement &xft, XmlElement &xf, ostream &outf, bool nounique)
int load_fix_version(XmlElement &xf, Ctxt &ctxt)
void process_group_ordering(const CommonGroupMap &gm)
static std::string & SubExpr(RegMatch &match, const std::string &source, std::string &target, const int offset=0, const int num=0)
POSIX regex wrapper class.
void generate_group_traits(const FieldSpecMap &fspec, const MessageSpec &ms, const string &gname, const string &prefix, ostream &outp)
bool no_shared_groups(false)
const string & filepart(const string &source, string &where)
unsigned glob_warnings(0)
std::string trim(const std::string &source, const std::string &ws=" \t")
bool nconst_router(false)
void load_components(const XmlElement::XmlSet &comlist, Components &components)
std::map< std::string, const XmlElement * > Components
static const std::string _exts_ver[2]
bool no_default_routers(false)
unsigned lookup_component(const Components &compon, const f8String &name)
f8c internal message representation.
void generate_nested_group(const MessageSpec &ms, const FieldSpecMap &fspec, int depth, ostream &outh, const std::string &fixns)
#define FIX8_PACKAGE_VERSION
int process_message_fields(const std::string &where, const XmlElement *xt, FieldTraits &fts, const FieldToNumMap &ftonSpec, FieldSpecMap &fspec, const Components &compon)
void generate_includes(ostream &to)
unsigned rothash(unsigned result, unsigned value)
const Presence & get_presence() const
static const std::string _exts[count]
void generate_preamble(ostream &to, const string &fname, bool isheader, bool donotedit=true)
int recover_line(const XmlElement &xf)
void process_value_enums(FieldSpecMap::const_iterator itr, ostream &ost_hpp, ostream &ost_cpp)
int process(XmlElement &xf, Ctxt &ctxt)
Used for static trait interrogation.
ostream * open_ofile(const string &odir, const string &fname, string &target)
const string & mkel(const string &base, const string &compon, string &where)
F8API bool Insert(XmlElement *what)
std::map< unsigned, struct FieldSpec > FieldSpecMap
int load_messages(XmlElement &xf, MessageSpecMap &mspec, const FieldToNumMap &ftonSpec, FieldSpecMap &fspec, Components &compon, CommonGroupMap &globmap)
A simple xml parser with Xpath style lookup.
f8c range or set domain realm.
F8API const Package_info & package_info()
string bintoaschex(const string &from)
std::set< const XmlElement *, EntityOrderComp > XmlSet
std::map< std::string, unsigned > FieldToNumMap
F8API const std::string & GetTimeAsStringMS(std::string &result, const class Tickval *tv=0, const unsigned dplaces=6, bool use_gm=false)
std::map< RealmObject *, std::string, RealmObject::less > RealmMap
int SearchString(RegMatch &match, const std::string &source, const int subExpr, const int offset=0) const
int main(int argc, char **argv)
bool report_unused(false)
unsigned parse_groups(MessageSpec &ritr, const string &name, const FieldToNumMap &ftonSpec, FieldSpecMap &fspec, XmlElement::XmlSet &grplist, const Components &compon, CommonGroupMap &globmap)
f8c internal field representation.
void generate_group_bodies(const MessageSpec &ms, const FieldSpecMap &fspec, int depth, const string &msname, ostream &outp, ostream &outh, const CommonGroupMap &globmap, const std::string &fixns, const string cls_prefix=string())
void generate_common_group_bodies(const FieldSpecMap &fspec, ostream &outp, CommonGroupMap &globmap)
std::map< const std::string, MessageSpec > MessageSpecMap
static std::string & Erase(RegMatch &match, std::string &source, const int num=0)
F8API std::string & InPlaceStrToUpper(std::string &src)
const string GETARGLIST("hvVo:p:dikn:rst:x:NRc:fbCIWPF:UeH:SDu")
F8API std::string & CheckAddTrailingSlash(std::string &source)
std::map< unsigned, CommonGroups > CommonGroupMap
bool add(const FieldTrait &what)
A collection of FieldTraits for a message. Which fields are required, which are present.
void process_ordering(MessageSpecMap &mspec)
A class to contain regex matches using RegExp.
std::map< uint32_t, struct MessageSpec > CommonGroups
const char * what() const
uint32_t group_hash(const MessageSpec &p1)
int precomp(XmlElement &xf, ostream &outf)
F8API const XmlElement * find(const std::string &what, const std::string *atag=nullptr, const std::string *aval=nullptr, const char delim='/') const
void generate_export(ostream &to, const string &ns)
void process_special_traits(const unsigned short field, FieldTraits &fts)