/* * This file part of makedict - convertor from any dictionary format to any * http://xdxf.sourceforge.net * Copyright (C) 2005-2006 Evgeniy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include using namespace std; #include "utils.hpp" #include "generator.hpp" //#define DEBUG Str2StrTable makedict_generator::xml_spec_seq; map makedict_generator::tag_table; class xml_parser { public: xml_parser(XML_StartElementHandler on_start, XML_EndElementHandler on_end, XML_CharacterDataHandler on_char, void *data); ~xml_parser() { XML_ParserFree(xmlp); } bool parse_line(const string& line) { if (XML_Parse(xmlp, &line[0], line.size(), 0)!=XML_STATUS_OK) { cerr<<_("xml parser error: ")<"]=">"; xml_spec_seq["&"]="&"; xml_spec_seq["\""]="""; tag_table["full_name"]=FULL_NAME; tag_table["description"]=DESCRIPTION; tag_table["abr_def"]=ABR_DEF; tag_table["ar"]=AR; tag_table["k"]=K; tag_table["v"]=V; tag_table["opt"]=OPT; } int makedict_generator::run(int argc, char *argv[]) { static const char *shortopts = "hob:w:"; static const option lopts[]= { {"version", no_argument, NULL, 0 }, {"help", no_argument, NULL, 'h' }, {"output-format", no_argument, NULL, 'o'}, {"basename", required_argument, NULL, 'b'}, {"work-dir", required_argument, NULL, 'w'}, {NULL, 0, NULL, 0}, }; int option_index, optc; string help = _("Usage: program -b name [-w dir]" "-h, --help display this help and exit\n" "--version output version information and exit\n" "-o, --output-format display supported output format and exit\n" "-b, --basename name use 'name' as base for newly created dictionary\n" "-w, --work-dir dir use 'dir' as current directory"); string basename, workdir; while ((optc = getopt_long(argc, argv, shortopts, &lopts[0], &option_index))!=-1) { switch (optc) { case 'h': cout<(userData); if (strcmp(name, "icon")==0) mg->meta_mode=mmICON; } void XMLCALL makedict_generator::on_meta_end(void *userData, const XML_Char *name) { makedict_generator *mg=static_cast(userData); if (strcmp(name, "icon")==0) mg->meta_mode=mmNONE; } void XMLCALL makedict_generator::on_meta_data(void *userData, const XML_Char *s, int len) { makedict_generator *mg=static_cast(userData); if (mg->meta_mode==mmICON) mg->dict_info["icon"]+=string(s, len); } bool makedict_generator::handle_meta() { string line; xml_parser meta_parser(on_meta_start, on_meta_end, on_meta_data, this); while (getline(cin, line) && line.find("")==string::npos) { line+='\n'; if (!meta_parser.parse_line(line)) return false; } if (!meta_parser.finish(line)) return false; return true; } bool makedict_generator::handle_input() { string line; if (!handle_meta()) return false; xml_parser xdxf_parser(xml_start, xml_end, xml_char_data, this); while (getline(cin, line)) { line+='\n'; if (!xdxf_parser.parse_line(line)) return false; } if (!xdxf_parser.finish(line)) return false; return true; } void XMLCALL makedict_generator::xml_start(void *userData, const XML_Char *name, const XML_Char **atts) { #ifdef DEBUG cerr<<"xml_start: name="<(userData); map::const_iterator it = tag_table.find(name); if (it==tag_table.end() && gen->state.empty()) return; if (it==tag_table.end()) { gen->data += string("<")+name; for (int i = 0; atts[i]; i += 2) gen->data += string(" ")+atts[i]+"=\""+atts[i+1]+"\""; gen->data += ">"; } else { switch (it->second) { case K: if (gen->state.top()==AR) gen->data += string("<")+name+">"; gen->key.parts.push_back(string()); break; case V: gen->data.clear(); break; case OPT: gen->data += string("<")+name+">"; gen->key.opts.push_back(string()); gen->key.parts.push_back(string()); break; default: /*nothing*/; } gen->state.push(it->second); #ifdef DEBUG cerr<<"xml_start: tag added, data="<data<"; } else { switch (gen->state.top()) { case FULL_NAME: case DESCRIPTION: gen->dict_info[it->first]=gen->data; gen->data.clear(); break; case OPT: gen->data += string(""; break; case K: gen->data += string(""; gen->generate_keys(); gen->key.clear(); break; case AR: case ABR_DEF: gen->on_have_data(); gen->keys.clear(); gen->data.clear(); break; default: /*nothing*/; } gen->state.pop(); } } void XMLCALL makedict_generator::xml_char_data(void *userData, const XML_Char *s, int len) { makedict_generator *gen=static_cast(userData); if (gen->state.empty()) return; #ifdef DEBUG cerr<<"xml_char_data, data="<data<data += data; switch (gen->state.top()) { case K: gen->key.parts.back() += string(s, len); break; case OPT: gen->key.opts.back() += string(s, len); break; default: /*nothing*/; } } void makedict_generator::sample(vector::size_type n) { if (n==0) { string res = accumulate(sample_data.begin(), sample_data.end(), string()); keys.push_back(res); return; } sample_data.push_back(key.parts[n+1-key.opts.size()]); sample(n-1); sample_data.pop_back(); sample_data.push_back(key.opts[key.opts.size()-n]); sample_data.push_back(key.parts[key.opts.size()-n+1]); sample(n-1); sample_data.pop_back(); sample_data.pop_back(); } void makedict_generator::generate_keys() { if (key.parts.empty()) { cerr<<_("makedict_generator::generate_keys: internal error, there is no parts of key")<