64 void process_value_enums(FieldSpecMap::const_iterator itr, ostream& ost_hpp, ostream& ost_cpp);
65 const string&
mkel(
const string& base,
const string& compon,
string& where);
73 const string ident_set(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789");
85 unique_ptr<ofstream> os(
new ofstream(target.c_str()));
88 cerr <<
"Error opening file \'" << target <<
'\'';
90 cerr <<
" (" << strerror(errno) <<
')';
100 const string&
mkel(
const string& base,
const string& compon,
string& where)
103 ostr << base <<
'/' << compon;
104 return where = ostr.str();
108 const string&
filepart(
const string& source,
string& where)
110 string::size_type pos(source.find_last_of(
'/'));
111 return pos == string::npos ? where = source : where = source.substr(pos + 1);
120 cerr <<
"No fix header element found in " <<
shortName << endl;
124 string major, minor, revision(
"0"), type(
"FIX");
126 if (!fix->GetAttr(
"major", major) || !fix->GetAttr(
"minor", minor))
128 cerr <<
"Missing required attributes (major/minor) from fix header in " <<
shortName << endl;
132 if (!fix->GetAttr(
"revision", revision))
133 fix->GetAttr(
"servicepack", revision);
134 fix->GetAttr(
"type", type);
137 ctxt.
_version = stoi(major) * 1000 + stoi(minor) * 100 + stoi(revision);
138 if (type ==
"FIX" && ctxt.
_version < 4000)
140 cerr <<
"Unsupported FIX version " << ctxt.
_version <<
" from fix header in " <<
shortName << endl;
152 ostr << type <<
'.' << major <<
'.' << minor;
166 fts.
set(field, FieldTrait::suppress);
168 fts.
set(field, FieldTrait::automatic);
169 fts.
clear(field, FieldTrait::mandatory);
179 if (FieldTrait::get_type_string(itr->second._ftype, typestr).empty())
181 typestr.insert(0,
"const ");
184 ost_cpp << typestr << itr->second._name <<
"_realm[] " << endl <<
spacer <<
"{ ";
186 for (RealmMap::const_iterator ditr(itr->second._dvals->begin()); ditr != itr->second._dvals->end(); ++ditr)
190 ost_cpp << *ditr->first;
191 string transdesc(ditr->second);
194 ost_hpp << typestr << itr->second._name <<
'_';
195 if (ditr->first->is_range())
196 ost_hpp << (cnt == 0 ?
"lower" :
"upper");
197 else if (transdesc.empty())
198 ost_hpp << *ditr->first;
200 ost_hpp << transdesc;
201 ost_hpp <<
'(' << *ditr->first <<
");" << endl;
204 ost_hpp <<
"const size_t " << itr->second._name <<
"_realm_els(" << itr->second._dvals->size() <<
");" << endl;
205 ost_cpp <<
" };" << endl;
207 ost_cpp <<
"const char *" << itr->second._name <<
"_descriptions[] " << endl << spacer <<
"{ ";
209 for (RealmMap::const_iterator ditr(itr->second._dvals->begin()); ditr != itr->second._dvals->end(); ++ditr)
213 ost_cpp <<
'"' << ditr->second <<
'"';
216 ost_cpp <<
" };" << endl;
223 unsigned processed(0);
225 if (xt->
find(where, flist))
227 for(
const auto *pp : flist)
229 string fname, required;
230 if (pp->GetAttr(
"name", fname) && pp->GetAttr(
"required", required))
232 FieldToNumMap::const_iterator ftonItr(ftonSpec.find(fname));
233 FieldSpecMap::iterator fs_itr;
234 if (ftonItr == ftonSpec.end() || (fs_itr = fspec.find(ftonItr->second)) == fspec.end())
236 cerr <<
shortName <<
':' <<
recover_line(*pp) <<
": error: Field element missing required attributes" << endl;
242 unsigned compidx(pp->GetAttr(
"component", compname) ?
lookup_component(compon, compname) : 0);
245 if (!fts.
add(
FieldTrait(fs_itr->first, fs_itr->second._ftype, pp->GetSubIdx(), required ==
"Y",
false, compidx)))
248 cerr <<
shortName <<
':' <<
recover_line(*pp) <<
": warning: Could not add trait object '" << fname <<
"' (duplicate ?)" << endl;
255 fs_itr->second.set_used();
260 cerr <<
shortName <<
':' <<
recover_line(*pp) <<
": error: Field element missing required attributes" << endl;
272 ostringstream result;
273 for (
const auto& cc : from)
274 result << uppercase << hex << setw(2) << setfill('0') << static_cast<unsigned short>(cc);
275 return "FIX8_" + result.str() +
'_';
281 for (
const auto& pp : mspec)
284 for (
const auto& ii : pp.second._fields.get_presence())
296 for (
const auto& pp : gm)
299 for (
const auto& ii : pp.second._fields.get_presence())
306 if (!pp.second._groups.empty())
314 for (
const auto& pp : globmap)
315 for (
const auto& ii : pp.second)
323 um.
setdesc(
"f8c -- compile FIX xml schema");
324 um.
add(
'o',
"odir <dir>",
"output target directory (default ./)");
325 um.
add(
'p',
"prefix <prefix>",
"output filename prefix (default Myfix)");
326 um.
add(
'H',
"pch <filename>",
"use specified precompiled header name for Windows (default none)");
327 um.
add(
'd',
"dump",
"dump 1st pass parsed source xml file, exit");
328 um.
add(
'e',
"extension",
"Generate with .cxx/.hxx extensions (default .cpp/.hpp)");
329 um.
add(
'f',
"fields",
"generate code for all defined fields even if they are not used in any message (default no)");
330 um.
add(
'F',
"xfields",
"specify additional fields with associated messages (see documentation for details)");
331 um.
add(
'h',
"help",
"help, this screen");
332 um.
add(
'i',
"ignore",
"ignore errors, attempt to generate code anyhow (default no)");
333 um.
add(
'k',
"keep",
"retain generated temporaries even if there are errors (.*.tmp)");
334 um.
add(
'v',
"version",
"print version, exit");
335 um.
add(
'I',
"info",
"print package info, exit");
336 um.
add(
's',
"second",
"2nd pass only, no precompile (default both)");
337 um.
add(
'S',
"noshared",
"Treat every group as unique and expose all static traits. Do not share metadata in message classes (default shared)");
338 um.
add(
'N',
"nounique",
"do not enforce unique field parsing (default false)");
339 um.
add(
'R',
"norealm",
"do not generate realm constructed field instantiators (default false)");
340 um.
add(
'W',
"nowarn",
"suppress warning messages (default false)");
341 um.
add(
'C',
"nocheck",
"do not embed version checking in generated code (default false)");
342 um.
add(
'D',
"defaulted",
"do not generate default router bodies. Application must provide all router definitions (default false)");
343 um.
add(
'U',
"noconst",
"Generate non-const Router method declarations (default false, const)");
344 um.
add(
'u',
"unused",
"Report unused fields, requires verbose option (default false)");
345 um.
add(
'r',
"retain",
"retain 1st pass code (default delete)");
346 um.
add(
'b',
"binary",
"print binary/ABI details, exit");
347 um.
add(
'P',
"incpath",
"prefix system include path with \"fix8\" in generated compilation units (default yes)");
348 um.
add(
'c',
"classes <server|client>",
"generate user session classes (default neither)");
349 um.
add(
't',
"tabwidth",
"tabwidth for generated code (default 3 spaces)");
350 um.
add(
'x',
"fixt <file>",
"For FIXT hosted transports or for FIX5.0 and above, the input FIXT schema file");
351 um.
add(
'V',
"verbose",
"be more verbose when processing");
352 um.
add(
'n',
"namespace <ns>",
"namespace to place generated code in (default FIXMmvv e.g. FIX4400)");
354 um.
add(
"@f8c -p Texfix -n TEX myfix.xml");
355 um.
add(
"@f8c -rp Texfix -n TEX -x ../schema/FIXT11.xml myfix.xml");
356 um.
add(
"@f8c -p Texfix -n TEX -c client -x ../schema/FIXT11.xml myfix.xml");
357 um.
add(
"@f8c -p Texfix -n TEX -c client -x ../schema/FIXT11.xml myfix.xml -F \"<field number='9999' name='SampleUserField' type='STRING' messages='NewOrderSingle:Y ExecutionReport:Y OrderCancelRequest:N' />");
364 if (FieldTrait::is_int(ftype))
366 if (FieldTrait::is_char(ftype))
368 if (FieldTrait::is_float(ftype))
370 if (FieldTrait::is_string(ftype))
381 ptim = localtime (&now);
384 localtime_r(&now, &tim);
389 ostr << setw(2) << (ptim->tm_year - 100);
396 static const vector<string> incfiles
412 to <<
"// f8 includes" << endl;
413 for (
const auto& pp : incfiles)
414 to <<
"#include " << (
incpath ?
"<fix8/" :
"<") << pp <<
'>' << endl;
420 os <<
"Name:" << what.
_name;
425 os <<
" isadmin:" << boolalpha << what.
_is_admin << endl;
426 os <<
"Fields:" << endl << what.
_fields;
427 for (
const auto& pp : what.
_groups)
428 os <<
"Group (" << pp.first <<
"): " << endl << pp.second << endl;
const unsigned short Common_CheckSum(10)
void clear(const unsigned short field, Presence::const_iterator &itr, FieldTrait::TraitTypes type=FieldTrait::present)
const string & mkel(const string &base, const string &compon, string &where)
F8API std::string & InPlaceReplaceInSet(const std::string &iset, std::string &src, const char repl='_')
std::map< std::string, const XmlElement * > Components
bool add(const char sw, const std::string &lsw, const std::string &help)
f8c internal message representation.
std::map< unsigned, struct MessageSpec > GroupMap
string bintoaschex(const string &from)
const string & filepart(const string &source, string &where)
std::ostream & operator<<(std::ostream &os, const GroupBase &what)
ostream * open_ofile(const string &odir, const string &fname, string &target)
int recover_line(const XmlElement &xf)
unsigned lookup_component(const Components &compon, const f8String &name)
void process_special_traits(const unsigned short field, FieldTraits &fts)
f8c character realm type.
Used for static trait interrogation.
void generate_includes(ostream &to)
int load_messages(XmlElement &xf, MessageSpecMap &mspec, const FieldToNumMap &ftonSpec, FieldSpecMap &fspec)
std::map< unsigned, struct FieldSpec > FieldSpecMap
void setdesc(const std::string &desc)
A simple xml parser with Xpath style lookup.
void print(std::ostream &os) const
f8c range or set domain realm.
int process(XmlElement &xf, Ctxt &ctxt)
std::multiset< const FieldTrait *, FieldTrait::PosCompare > FieldTraitOrder
const unsigned short Common_MsgType(35)
void process_value_enums(FieldSpecMap::const_iterator itr, ostream &ost_hpp, ostream &ost_cpp)
std::set< const XmlElement *, EntityOrderComp > XmlSet
std::map< std::string, unsigned > FieldToNumMap
const unsigned short Common_BodyLength(9)
std::map< const std::string, MessageSpec > MessageSpecMap
const unsigned short Common_BeginString(8)
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.
int load_fix_version(XmlElement &xf, Ctxt &ctxt)
int load_fields(XmlElement &xf, FieldSpecMap &fspec)
bool exist(const std::string &fname)
F8API const XmlElement * find(const std::string &what, const std::string *atag=nullptr, const std::string *aval=nullptr, const char delim='/') const
int process_message_fields(const std::string &where, XmlElement *xt, FieldTraits &fts, const FieldToNumMap &ftonSpec, FieldSpecMap &fspec, const Components &compon)
Convenient program help/usage wrapper. Generates a standardised usage message.
void set(const unsigned short field, Presence::const_iterator &itr, FieldTrait::TraitTypes type)
void process_ordering(MessageSpecMap &mspec)
void process_message_group_ordering(const GroupMap &gm)
void process_group_ordering(const CommonGroupMap &gm)