Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@
/lttoolbox/lt-append
/lttoolbox/lsx-comp
/lttoolbox/lt-paradigm
/lttoolbox/lt-invert
/lttoolbox/lt-restrict
/python/Makefile
/python/Makefile.in
/python/lttoolbox.i
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ AC_PREREQ(2.52)

m4_define([PKG_VERSION_MAJOR], [3])
m4_define([PKG_VERSION_MINOR], [6])
m4_define([PKG_VERSION_PATCH], [9])
m4_define([PKG_VERSION_PATCH], [10])

AC_INIT([lttoolbox], [PKG_VERSION_MAJOR.PKG_VERSION_MINOR.PKG_VERSION_PATCH], [apertium-stuff@lists.sourceforge.net], [lttoolbox], [https://wiki.apertium.org/wiki/Lttoolbox])

Expand Down
8 changes: 5 additions & 3 deletions lttoolbox/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

h_sources = alphabet.h att_compiler.h buffer.h compiler.h compression.h \
h_sources = acx.h alphabet.h att_compiler.h buffer.h cli.h compiler.h compression.h \
deserialiser.h entry_token.h expander.h file_utils.h fst_processor.h input_file.h lt_locale.h \
match_exe.h match_node.h match_state.h my_stdio.h node.h \
pattern_list.h regexp_compiler.h serialiser.h sorted_vector.h state.h string_utils.h \
transducer.h trans_exe.h xml_parse_util.h xml_walk_util.h exception.h tmx_compiler.h \
ustring.h sorted_vector.hpp
cc_sources = alphabet.cc att_compiler.cc compiler.cc compression.cc entry_token.cc \
cc_sources = acx.cc alphabet.cc att_compiler.cc cli.cc compiler.cc compression.cc entry_token.cc \
expander.cc file_utils.cc fst_processor.cc input_file.cc lt_locale.cc match_exe.cc \
match_node.cc match_state.cc node.cc pattern_list.cc \
regexp_compiler.cc sorted_vector.cc state.cc string_utils.cc transducer.cc \
Expand All @@ -14,7 +14,7 @@ cc_sources = alphabet.cc att_compiler.cc compiler.cc compression.cc entry_token.
library_includedir = $(includedir)/$(PACKAGE_NAME)-$(VERSION_API)/$(PACKAGE_NAME)
library_include_HEADERS = $(h_sources)

bin_PROGRAMS = lt-comp lt-proc lt-expand lt-paradigm lt-tmxcomp lt-tmxproc lt-print lt-trim lt-append lsx-comp
bin_PROGRAMS = lt-comp lt-proc lt-expand lt-paradigm lt-tmxcomp lt-tmxproc lt-print lt-trim lt-append lsx-comp lt-invert lt-restrict
instdir = lttoolbox

lib_LTLIBRARIES= liblttoolbox3.la
Expand All @@ -41,6 +41,8 @@ lt_paradigm_SOURCES = lt_paradigm.cc
lt_tmxcomp_SOURCES = lt_tmxcomp.cc
lt_tmxproc_SOURCES = lt_tmxproc.cc
lsx_comp_SOURCES = lt_comp.cc
lt_invert_SOURCES = lt_invert.cc
lt_restrict_SOURCES = lt_restrict.cc

#lt-validate-dictionary: Makefile.am validate-header.sh
# @echo "Creating lt-validate-dictionary script"
Expand Down
61 changes: 61 additions & 0 deletions lttoolbox/acx.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2022 Apertium
*
* 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <lttoolbox/acx.h>
#include <lttoolbox/xml_walk_util.h>

const xmlChar* CHAR_NODE = (const xmlChar*)"char";
const xmlChar* EQUIV_NODE = (const xmlChar*)"equiv-char";
const char* VALUE_ATTR = "value";

int32_t get_val(xmlNode* node)
{
UString s = getattr(node, VALUE_ATTR);
if (s.empty()) {
error_and_die(node, "Missing value attribute.");
}
std::vector<int32_t> v;
ustring_to_vec32(s, v);
if (v.size() > 1) {
error_and_die(node, "Expected a single character in value attribute, but found %d.", v.size());
}
return v[0];
}

std::map<int32_t, sorted_vector<int32_t>> readACX(const char* file)
{
std::map<int32_t, sorted_vector<int32_t>> acx;
xmlNode* top_node = load_xml(file);
for (auto char_node : children(top_node)) {
if (xmlStrEqual(char_node->name, CHAR_NODE)) {
error_and_die(char_node, "Expected <char> but found <%s>.",
(const char*)char_node->name);
}
int32_t key = get_val(char_node);
sorted_vector<int32_t> vec;
for (auto equiv_node : children(char_node)) {
if (xmlStrEqual(equiv_node->name, EQUIV_NODE)) {
error_and_die(char_node, "Expected <equiv-char> but found <%s>.",
(const char*)equiv_node->name);
}
vec.insert(get_val(equiv_node));
}
if (!vec.empty()) {
acx.insert(std::make_pair(key, vec));
}
}
return acx;
}
25 changes: 25 additions & 0 deletions lttoolbox/acx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2022 Apertium
*
* 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _ACXPARSEUTIL_
#define _ACXPARSEUTIL_

#include <lttoolbox/sorted_vector.hpp>
#include <map>

std::map<int32_t, sorted_vector<int32_t>> readACX(const char* file);

#endif
184 changes: 184 additions & 0 deletions lttoolbox/cli.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*
* Copyright (C) 2022 Apertium
*
* 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/

#include <lttoolbox/cli.h>

#include <cstdlib>
#include <iostream>
#include <libgen.h>
#include <string>
#include <getopt.h>

CLI::CLI(std::string desc, std::string version)
{
description = " v" + version + ": " + desc;
}

CLI::CLI(std::string desc)
{
description = ": " + desc;
}

CLI::~CLI()
{
}

void CLI::add_str_arg(char short_flag, std::string long_flag,
std::string desc, std::string arg)
{
options.push_back({.short_opt=short_flag, .long_opt=long_flag,
.desc=desc, .is_bool=false, .var=arg});
}

void CLI::add_bool_arg(char short_flag, std::string long_flag,
std::string desc)
{
options.push_back({.short_opt=short_flag, .long_opt=long_flag,
.desc=desc, .is_bool=true, .var=""});
}

void CLI::add_file_arg(std::string name, bool optional)
{
file_args.push_back(std::make_pair(name, optional));
if (!optional) min_file_args++;
}

void CLI::set_epilog(std::string e)
{
epilog = e;
}

void CLI::print_usage()
{
if (!prog_name.empty()) {
std::cout << prog_name << description << std::endl;
std::cout << "USAGE: " << prog_name;
std::string bargs;
std::string sargs;
for (auto& it : options) {
if (it.is_bool) {
bargs += it.short_opt;
} else {
sargs += " [-";
sargs += it.short_opt;
sargs += ' ';
sargs += it.var;
sargs += ']';
}
}
if (!bargs.empty()) {
std::cout << " [-" << bargs << "]";
}
std::cout << sargs;
int depth = 0;
for (auto& it : file_args) {
std::cout << ' ';
if (it.second) {
std::cout << '[';
depth += 1;
}
std::cout << it.first;
}
while (depth-- > 0) std::cout << "]";
std::cout << std::endl;
for (auto& it : options) {
std::cout << " -" << it.short_opt;
#if HAVE_GETOPT_LONG
std::cout << ", --" << it.long_opt << ':';
for (size_t i = it.long_opt.size(); i < 20; i++) {
std::cout << ' ';
}
#else
std::cout << ": ";
#endif
std::cout << it.desc << std::endl;
}
if (!epilog.empty()) {
std::cout << epilog << std::endl;
}
}
exit(EXIT_FAILURE);
}

void CLI::parse_args(int argc, char* argv[])
{
prog_name = basename(argv[0]);
std::string arg_str;
#if HAVE_GETOPT_LONG
struct option long_options[options.size()];
int option_index = 0;
#endif
for (size_t i = 0; i < options.size(); i++) {
arg_str += options[i].short_opt;
if (!options[i].is_bool) arg_str += ':';
#if HAVE_GETOPT_LONG
long_options[i].name = options[i].long_opt.c_str();
long_options[i].has_arg = (options[i].is_bool ? no_argument : required_argument);
long_options[i].flag = 0;
long_options[i].val = options[i].short_opt;
#endif
}

while (true) {
#if HAVE_GETOPT_LONG
int cnt = getopt_long(argc, argv, arg_str.c_str(), long_options, &option_index);
#else
int cnt = getopt(argc, argv, arg_str.c_str());
#endif
if (cnt == -1) break;

bool found = false;
for (auto& it : options) {
if (it.short_opt == cnt) {
found = true;
if (it.is_bool) {
bools[it.long_opt] = true;
} else {
strs[it.long_opt].push_back(optarg);
}
break;
}
}
if (!found || cnt == 'h') {
print_usage();
}
}
while (optind < argc) {
files.push_back(argv[optind++]);
}
if (files.size() < min_file_args || files.size() > file_args.size()) {
print_usage();
}
while (files.size() < file_args.size()) {
files.push_back("");
}
}

std::map<std::string, std::vector<std::string>>& CLI::get_strs()
{
return strs;
}

std::map<std::string, bool>& CLI::get_bools()
{
return bools;
}

std::vector<std::string>& CLI::get_files()
{
return files;
}
59 changes: 59 additions & 0 deletions lttoolbox/cli.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (C) 2022 Apertium
*
* 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/

#include <string>
#include <vector>
#include <map>

class CLI {
private:
struct CLIOption {
char short_opt;
std::string long_opt;
std::string desc;
bool is_bool;
std::string var;
};

std::string description;
std::string epilog;

std::vector<CLIOption> options;
std::vector<std::pair<std::string, bool>> file_args;
size_t min_file_args = 0;

std::map<std::string, std::vector<std::string>> strs;
std::map<std::string, bool> bools;
std::vector<std::string> files;

std::string prog_name;

public:
CLI(std::string desc, std::string version);
CLI(std::string desc);
~CLI();
void add_str_arg(char short_flag, std::string long_flag, std::string desc,
std::string arg);
void add_bool_arg(char short_flag, std::string long_flag, std::string desc);
void add_file_arg(std::string name, bool optional = true);
void set_epilog(std::string e);
void print_usage();
void parse_args(int argc, char* argv[]);
std::map<std::string, std::vector<std::string>>& get_strs();
std::map<std::string, bool>& get_bools();
std::vector<std::string>& get_files();
};
Loading