libixion-0.17.0/0000775000175000017500000000000014136644733010432 500000000000000libixion-0.17.0/src/0000775000175000017500000000000014136644732011220 500000000000000libixion-0.17.0/src/table_handler.cpp0000644000175000017500000000675313273351727014441 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "table_handler.hpp" namespace ixion { table_handler::entry::entry() : name(empty_string_id), range(abs_range_t::invalid), totals_row_count(0) {} table_handler::~table_handler() {} abs_range_t table_handler::get_range( const abs_address_t& pos, string_id_t column_first, string_id_t column_last, table_areas_t areas) const { entries_type::const_iterator it = m_entries.begin(), it_end = m_entries.end(); for (; it != it_end; ++it) { const entry& e = *it->second; if (!e.range.contains(pos)) continue; return get_column_range(e, column_first, column_last, areas); } return abs_range_t(abs_range_t::invalid); } abs_range_t table_handler::get_range( string_id_t table, string_id_t column_first, string_id_t column_last, table_areas_t areas) const { entries_type::const_iterator it = m_entries.find(table); if (it == m_entries.end()) // Table name not found. return abs_range_t(abs_range_t::invalid); const entry& e = *it->second; return get_column_range(e, column_first, column_last, areas); } void table_handler::insert(std::unique_ptr& p) { if (!p) return; string_id_t name = p->name; m_entries.insert( entries_type::value_type( name, std::unique_ptr(p.release()))); } void adjust_table_area(abs_range_t& range, const table_handler::entry& e, table_areas_t areas) { bool headers = (areas & table_area_headers); bool data = (areas & table_area_data); bool totals = (areas & table_area_totals); if (headers) { if (data) { if (totals) { // All areas. return; } // Headers + data areas range.last.row -= e.totals_row_count; return; } // Headers only. range.last.row = range.first.row; return; } // No header row. --range.first.row; if (data) { if (totals) { // Data + totals areas return; } // Data area only. range.last.row -= e.totals_row_count; return; } // Totals area only. if (e.totals_row_count <= 0) { range = abs_range_t(abs_range_t::invalid); return; } range.first.row = range.last.row; range.first.row -= e.totals_row_count - 1; } abs_range_t table_handler::get_column_range( const entry& e, string_id_t column_first, string_id_t column_last, table_areas_t areas) const { if (column_first == empty_string_id) { // Area specifiers only. abs_range_t ret = e.range; adjust_table_area(ret, e, areas); return ret; } for (size_t i = 0, n = e.columns.size(); i < n; ++i) { if (e.columns[i] == column_first) { // Matching column name found. abs_range_t ret = e.range; col_t col = e.range.first.column + i; ret.first.column = col; ret.last.column = col; adjust_table_area(ret, e, areas); return ret; } } return abs_range_t(abs_range_t::invalid); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/sort_input_parser.hpp0000664000175000017500000000233614122770261015427 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef __IXION_SORT_INPUT_PARSER_HXX__ #define __IXION_SORT_INPUT_PARSER_HXX__ #include "ixion/exceptions.hpp" #include "depth_first_search.hpp" #include "mem_str_buf.hpp" #include namespace ixion { class sort_input_parser { class parse_error : public general_error { public: parse_error(const ::std::string& msg); virtual ~parse_error() throw(); }; using dfs_type = depth_first_search; public: sort_input_parser(const ::std::string& filepath); ~sort_input_parser(); void parse(); void print(); private: void remove_duplicate_cells(); void insert_depend(const mem_str_buf& cell, const mem_str_buf& dep); private: dfs_type::relations m_set; ::std::string m_content; ::std::vector m_all_cells; const char* mp; const char* mp_last; }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/session_handler.hpp0000664000175000017500000000407214122770261015024 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_SESSION_HANDLER_HPP #define INCLUDED_IXION_SESSION_HANDLER_HPP #include "ixion/interface/session_handler.hpp" #include "ixion/model_context.hpp" #include namespace ixion { class session_handler : public iface::session_handler { struct impl; std::unique_ptr mp_impl; public: session_handler(const model_context& cxt, bool show_sheet_name); virtual ~session_handler(); virtual void begin_cell_interpret(const abs_address_t& pos) override; virtual void end_cell_interpret() override; virtual void set_result(const formula_result& result) override; virtual void set_invalid_expression(std::string_view msg) override; virtual void set_formula_error(std::string_view msg) override; virtual void push_token(fopcode_t fop) override; virtual void push_value(double val) override; virtual void push_string(size_t sid) override; virtual void push_single_ref(const address_t& addr, const abs_address_t& pos) override; virtual void push_range_ref(const range_t& range, const abs_address_t& pos) override; virtual void push_table_ref(const table_t& table) override; virtual void push_function(formula_function_t foc) override; class factory : public model_context::session_handler_factory { const model_context& m_context; bool m_show_sheet_name; public: factory(const model_context& cxt); virtual ~factory() override; virtual std::unique_ptr create() override; void show_sheet_name(bool b); }; /** * Print string to stdout in a thread-safe way. * * @param msg string to print to stdout. */ static void print(const std::string& msg); }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/session_handler.cpp0000664000175000017500000000763014122770261015022 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "session_handler.hpp" #include "app_common.hpp" #include "ixion/formula_name_resolver.hpp" #include "ixion/formula_result.hpp" #include "ixion/formula_tokens.hpp" #include "ixion/config.hpp" #include #include #include #include using namespace std; namespace ixion { session_handler::factory::factory(const model_context& cxt) : m_context(cxt), m_show_sheet_name(false) {} session_handler::factory::~factory() {} std::unique_ptr session_handler::factory::create() { return std::make_unique(m_context, m_show_sheet_name); } void session_handler::factory::show_sheet_name(bool b) { m_show_sheet_name = b; } struct session_handler::impl { const model_context& m_context; std::unique_ptr mp_resolver; std::string m_cell_name; std::ostringstream m_buf; bool m_show_sheet_name; impl(const model_context& cxt, bool show_sheet_name) : m_context(cxt), mp_resolver(formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt)), m_show_sheet_name(show_sheet_name) {} }; session_handler::session_handler(const model_context& cxt, bool show_sheet_name) : mp_impl(std::make_unique(cxt, show_sheet_name)) {} session_handler::~session_handler() {} void session_handler::begin_cell_interpret(const abs_address_t& pos) { // Convert absolute to relative address, which looks better when printed. address_t pos_display(pos); pos_display.set_absolute(false); mp_impl->m_cell_name = mp_impl->mp_resolver->get_name(pos_display, abs_address_t(), mp_impl->m_show_sheet_name); mp_impl->m_buf << detail::get_formula_result_output_separator() << endl; mp_impl->m_buf << mp_impl->m_cell_name << ": "; } void session_handler::end_cell_interpret() { print(mp_impl->m_buf.str()); } void session_handler::set_result(const formula_result& result) { mp_impl->m_buf << endl << mp_impl->m_cell_name << ": result = " << result.str(mp_impl->m_context) << endl; } void session_handler::set_invalid_expression(std::string_view msg) { mp_impl->m_buf << endl << mp_impl->m_cell_name << ": invalid expression: " << msg << endl; } void session_handler::set_formula_error(std::string_view msg) { mp_impl->m_buf << endl << mp_impl->m_cell_name << ": result = " << msg << endl; } void session_handler::push_token(fopcode_t fop) { if (fop == fop_sep) mp_impl->m_buf << mp_impl->m_context.get_config().sep_function_arg; else mp_impl->m_buf << get_formula_opcode_string(fop); } void session_handler::push_value(double val) { mp_impl->m_buf << val; } void session_handler::push_string(size_t sid) { const string* p = mp_impl->m_context.get_string(sid); mp_impl->m_buf << '"'; if (p) mp_impl->m_buf << *p; else mp_impl->m_buf << "(null string)"; mp_impl->m_buf << '"'; } void session_handler::push_single_ref(const address_t& addr, const abs_address_t& pos) { mp_impl->m_buf << mp_impl->mp_resolver->get_name(addr, pos, false); } void session_handler::push_range_ref(const range_t& range, const abs_address_t& pos) { mp_impl->m_buf << mp_impl->mp_resolver->get_name(range, pos, false); } void session_handler::push_table_ref(const table_t& table) { mp_impl->m_buf << mp_impl->mp_resolver->get_name(table); } void session_handler::push_function(formula_function_t foc) { mp_impl->m_buf << get_formula_function_name(foc); } void session_handler::print(const std::string& msg) { static std::mutex mtx; std::lock_guard lock(mtx); cout << msg; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/sort_input_parser.cpp0000664000175000017500000000673014122770261015424 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "sort_input_parser.hpp" #include "app_common.hpp" #include "ixion/global.hpp" #include #include #include using namespace std; namespace ixion { size_t hash_value(const ixion::mem_str_buf& s) { size_t n = s.size(); size_t hash_val = 0; for (size_t i = 0; i < n; ++i) hash_val += (s[i] << i); return hash_val; } namespace { struct mem_str_buf_printer { void operator() (const mem_str_buf& r) const { cout << r.str() << endl; } }; } sort_input_parser::parse_error::parse_error(const string& msg) : general_error(msg) {} sort_input_parser::parse_error::~parse_error() throw() {} // ---------------------------------------------------------------------------- sort_input_parser::sort_input_parser(const string& filepath) : m_content(detail::load_file_content(filepath)), mp(nullptr), mp_last(nullptr) { } sort_input_parser::~sort_input_parser() { } void sort_input_parser::parse() { if (m_content.empty()) return; mp = &m_content[0]; mp_last = &m_content[m_content.size()-1]; mem_str_buf cell, dep; bool in_name = true; for (;mp != mp_last; ++mp) { switch (*mp) { case ' ': // Let's skip blanks for now. break; case '\n': // end of line. if (cell.empty()) { if (!dep.empty()) throw parse_error("cell name is emtpy but dependency name isn't."); } else { if (dep.empty()) throw parse_error("dependency name is empty."); else insert_depend(cell, dep); } cell.clear(); dep.clear(); in_name = true; break; case ':': if (!dep.empty()) throw parse_error("more than one separator in a single line!"); if (cell.empty()) throw parse_error("cell name is empty"); in_name = false; break; default: if (in_name) cell.append(mp); else dep.append(mp); } } } void sort_input_parser::print() { remove_duplicate_cells(); // Run the depth first search. vector sorted; sorted.reserve(m_all_cells.size()); dfs_type::back_inserter handler(sorted); dfs_type dfs(m_all_cells.begin(), m_all_cells.end(), m_set, handler); dfs.run(); // Print the result. for_each(sorted.begin(), sorted.end(), mem_str_buf_printer()); } void sort_input_parser::remove_duplicate_cells() { sort(m_all_cells.begin(), m_all_cells.end()); vector::iterator itr = unique(m_all_cells.begin(), m_all_cells.end()); m_all_cells.erase(itr, m_all_cells.end()); } void sort_input_parser::insert_depend(const mem_str_buf& cell, const mem_str_buf& dep) { m_set.insert(cell, dep); m_all_cells.push_back(cell); m_all_cells.push_back(dep); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/app_common.hpp0000664000175000017500000000120114122770261013763 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_SRC_APP_COMMON_HPP #define INCLUDED_IXION_SRC_APP_COMMON_HPP #include namespace ixion { namespace detail { std::string_view get_formula_result_output_separator(); std::string load_file_content(const std::string& filepath); }} // namespace ixion::detail #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/app_common.cpp0000664000175000017500000000172714122770261013773 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "app_common.hpp" #include #include #include namespace ixion { namespace detail { std::string_view get_formula_result_output_separator() { static const char* sep = "---------------------------------------------------------"; return sep; } std::string load_file_content(const std::string& filepath) { std::ifstream file(filepath.c_str()); if (!file) // failed to open the specified file. throw file_not_found(filepath); std::ostringstream os; os << file.rdbuf(); file.close(); return os.str(); } }} // namespace ixion::detail /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/Makefile.in0000664000175000017500000013416114136644552013213 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = ixion-parser$(EXEEXT) ixion-sorter$(EXEEXT) \ ixion-formula-tokenizer$(EXEEXT) subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_ixion_formula_tokenizer_OBJECTS = \ ixion_formula_tokenizer.$(OBJEXT) ixion_formula_tokenizer_OBJECTS = \ $(am_ixion_formula_tokenizer_OBJECTS) am__DEPENDENCIES_1 = ixion_formula_tokenizer_DEPENDENCIES = \ libixion/libixion-@IXION_API_VERSION@.la $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_ixion_parser_OBJECTS = ixion_parser.$(OBJEXT) \ model_parser.$(OBJEXT) app_common.$(OBJEXT) \ session_handler.$(OBJEXT) table_handler.$(OBJEXT) ixion_parser_OBJECTS = $(am_ixion_parser_OBJECTS) ixion_parser_DEPENDENCIES = libixion/libixion-@IXION_API_VERSION@.la \ $(am__DEPENDENCIES_1) am_ixion_sorter_OBJECTS = ixion_sorter.$(OBJEXT) app_common.$(OBJEXT) \ sort_input_parser.$(OBJEXT) ixion_sorter_OBJECTS = $(am_ixion_sorter_OBJECTS) ixion_sorter_DEPENDENCIES = libixion/libixion-@IXION_API_VERSION@.la \ $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/app_common.Po \ ./$(DEPDIR)/ixion_formula_tokenizer.Po \ ./$(DEPDIR)/ixion_parser.Po ./$(DEPDIR)/ixion_sorter.Po \ ./$(DEPDIR)/model_parser.Po ./$(DEPDIR)/session_handler.Po \ ./$(DEPDIR)/sort_input_parser.Po ./$(DEPDIR)/table_handler.Po am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(ixion_formula_tokenizer_SOURCES) $(ixion_parser_SOURCES) \ $(ixion_sorter_SOURCES) DIST_SOURCES = $(ixion_formula_tokenizer_SOURCES) \ $(ixion_parser_SOURCES) $(ixion_sorter_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ check recheck distdir distdir-am am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ BOOST_LDPATH = @BOOST_LDPATH@ BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ BOOST_ROOT = @BOOST_ROOT@ BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX17 = @HAVE_CXX17@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IXION_API_VERSION = @IXION_API_VERSION@ IXION_MAJOR_API_VERSION = @IXION_MAJOR_API_VERSION@ IXION_MAJOR_VERSION = @IXION_MAJOR_VERSION@ IXION_MICRO_VERSION = @IXION_MICRO_VERSION@ IXION_MINOR_API_VERSION = @IXION_MINOR_API_VERSION@ IXION_MINOR_VERSION = @IXION_MINOR_VERSION@ IXION_VERSION = @IXION_VERSION@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MDDS_CFLAGS = @MDDS_CFLAGS@ MDDS_LIBS = @MDDS_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POW_LIB = @POW_LIB@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ VULKAN_CFLAGS = @VULKAN_CFLAGS@ VULKAN_LIBS = @VULKAN_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = include libixion python AM_CPPFLAGS = \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/include \ $(MDDS_CFLAGS) $(BOOST_CPPFLAGS) ixion_parser_SOURCES = \ ixion_parser.cpp \ model_parser.hpp \ model_parser.cpp \ app_common.hpp \ app_common.cpp \ session_handler.hpp \ session_handler.cpp \ table_handler.hpp \ table_handler.cpp ixion_parser_LDADD = libixion/libixion-@IXION_API_VERSION@.la \ $(BOOST_PROGRAM_OPTIONS_LIBS) ixion_sorter_SOURCES = \ ixion_sorter.cpp \ app_common.cpp \ sort_input_parser.hpp \ sort_input_parser.cpp ixion_sorter_LDADD = libixion/libixion-@IXION_API_VERSION@.la \ $(BOOST_PROGRAM_OPTIONS_LIBS) ixion_formula_tokenizer_SOURCES = \ ixion_formula_tokenizer.cpp ixion_formula_tokenizer_LDADD = libixion/libixion-@IXION_API_VERSION@.la \ $(BOOST_PROGRAM_OPTIONS_LIBS) AM_TESTS_ENVIRONMENT = PATH=.libs$${PATH:+:$${PATH}}; export PATH; \ LD_LIBRARY_PATH=libixion/.libs$${LD_LIBRARY_PATH:+:$${LD_LIBRARY_PATH}}; export LD_LIBRARY_PATH; \ DYLD_LIBRARY_PATH=$${LD_LIBRARY_PATH}}; export DYLD_LIBRARY_PATH; TESTS = \ ../test/parser-test-t0.sh \ ../test/parser-test-t1.sh \ ../test/parser-test-t2.sh \ ../test/parser-test-t3.sh \ ../test/parser-test-t4.sh \ ../test/parser-test-t5.sh \ ../test/parser-test-t6.sh \ ../test/parser-test-t7.sh \ ../test/parser-test-t8.sh all: all-recursive .SUFFIXES: .SUFFIXES: .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list ixion-formula-tokenizer$(EXEEXT): $(ixion_formula_tokenizer_OBJECTS) $(ixion_formula_tokenizer_DEPENDENCIES) $(EXTRA_ixion_formula_tokenizer_DEPENDENCIES) @rm -f ixion-formula-tokenizer$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(ixion_formula_tokenizer_OBJECTS) $(ixion_formula_tokenizer_LDADD) $(LIBS) ixion-parser$(EXEEXT): $(ixion_parser_OBJECTS) $(ixion_parser_DEPENDENCIES) $(EXTRA_ixion_parser_DEPENDENCIES) @rm -f ixion-parser$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(ixion_parser_OBJECTS) $(ixion_parser_LDADD) $(LIBS) ixion-sorter$(EXEEXT): $(ixion_sorter_OBJECTS) $(ixion_sorter_DEPENDENCIES) $(EXTRA_ixion_sorter_DEPENDENCIES) @rm -f ixion-sorter$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(ixion_sorter_OBJECTS) $(ixion_sorter_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/app_common.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_formula_tokenizer.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_parser.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_sorter.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_parser.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session_handler.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sort_input_parser.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/table_handler.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? ../test/parser-test-t0.sh.log: ../test/parser-test-t0.sh @p='../test/parser-test-t0.sh'; \ b='../test/parser-test-t0.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ../test/parser-test-t1.sh.log: ../test/parser-test-t1.sh @p='../test/parser-test-t1.sh'; \ b='../test/parser-test-t1.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ../test/parser-test-t2.sh.log: ../test/parser-test-t2.sh @p='../test/parser-test-t2.sh'; \ b='../test/parser-test-t2.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ../test/parser-test-t3.sh.log: ../test/parser-test-t3.sh @p='../test/parser-test-t3.sh'; \ b='../test/parser-test-t3.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ../test/parser-test-t4.sh.log: ../test/parser-test-t4.sh @p='../test/parser-test-t4.sh'; \ b='../test/parser-test-t4.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ../test/parser-test-t5.sh.log: ../test/parser-test-t5.sh @p='../test/parser-test-t5.sh'; \ b='../test/parser-test-t5.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ../test/parser-test-t6.sh.log: ../test/parser-test-t6.sh @p='../test/parser-test-t6.sh'; \ b='../test/parser-test-t6.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ../test/parser-test-t7.sh.log: ../test/parser-test-t7.sh @p='../test/parser-test-t7.sh'; \ b='../test/parser-test-t7.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ../test/parser-test-t8.sh.log: ../test/parser-test-t8.sh @p='../test/parser-test-t8.sh'; \ b='../test/parser-test-t8.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-recursive all-am: Makefile $(PROGRAMS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f ./$(DEPDIR)/app_common.Po -rm -f ./$(DEPDIR)/ixion_formula_tokenizer.Po -rm -f ./$(DEPDIR)/ixion_parser.Po -rm -f ./$(DEPDIR)/ixion_sorter.Po -rm -f ./$(DEPDIR)/model_parser.Po -rm -f ./$(DEPDIR)/session_handler.Po -rm -f ./$(DEPDIR)/sort_input_parser.Po -rm -f ./$(DEPDIR)/table_handler.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/app_common.Po -rm -f ./$(DEPDIR)/ixion_formula_tokenizer.Po -rm -f ./$(DEPDIR)/ixion_parser.Po -rm -f ./$(DEPDIR)/ixion_sorter.Po -rm -f ./$(DEPDIR)/model_parser.Po -rm -f ./$(DEPDIR)/session_handler.Po -rm -f ./$(DEPDIR)/sort_input_parser.Po -rm -f ./$(DEPDIR)/table_handler.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--depfiles check check-TESTS check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libixion-0.17.0/src/model_parser.hpp0000664000175000017500000000711114122770261014315 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_MODEL_PARSER_HPP #define INCLUDED_IXION_MODEL_PARSER_HPP #include "ixion/exceptions.hpp" #include "ixion/model_context.hpp" #include "ixion/formula_result.hpp" #include "session_handler.hpp" #include "table_handler.hpp" #include "mem_str_buf.hpp" #include #include #include #include namespace ixion { class model_parser { enum parse_mode_type { parse_mode_unknown = 0, parse_mode_init, parse_mode_result, parse_mode_result_cache, parse_mode_edit, parse_mode_table, parse_mode_session, parse_mode_named_expression, parse_mode_exit }; using parsed_assignment_type = std::pair; struct named_expression_type { std::string name; std::string expression; abs_address_t origin; sheet_t scope = global_scope; }; /** * Right-hand-side cell content type. */ enum cell_type { ct_unknown = 0, ct_formula, ct_value, ct_string, ct_boolean }; struct cell_def_type { mem_str_buf name; mem_str_buf value; cell_type type; abs_range_t pos; bool matrix_value = false; }; public: typedef std::unordered_map< ::std::string, formula_result> results_type; class parse_error : public general_error { public: explicit parse_error(const std::string& msg); }; class check_error : public general_error { public: check_error(const ::std::string& msg); }; model_parser() = delete; model_parser(const model_parser&) = delete; model_parser& operator= (model_parser) = delete; model_parser(const ::std::string& filepath, size_t thread_count); ~model_parser(); void parse(); private: void init_model(); void parse_command(); void parse_session(); void parse_init(); void parse_edit(); void parse_result(); void parse_result_cache(); void parse_table(); void parse_table_columns(const mem_str_buf& str); void push_table(); void parse_named_expression(); void push_named_expression(); void print_dependency(); /** * Parse a simple left=right assignment line. */ parsed_assignment_type parse_assignment(); cell_def_type parse_cell_definition(); void check(); std::string get_display_cell_string(const abs_address_t& pos) const; std::string get_display_range_string(const abs_range_t& pos) const; private: model_context m_context; table_handler m_table_handler; session_handler::factory m_session_handler_factory; std::unique_ptr mp_table_entry; std::unique_ptr mp_name_resolver; std::unique_ptr mp_named_expression; std::string m_filepath; std::string m_strm; size_t m_thread_count; abs_range_set_t m_dirty_formula_cells; abs_range_set_t m_modified_cells; results_type m_formula_results; const char* mp_head; const char* mp_end; const char* mp_char; sheet_t m_current_sheet; parse_mode_type m_parse_mode; bool m_print_separator:1; bool m_print_sheet_name:1; }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/include/0000775000175000017500000000000014136644732012643 500000000000000libixion-0.17.0/src/include/Makefile.in0000664000175000017500000003301514136644552014632 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/include ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ BOOST_LDPATH = @BOOST_LDPATH@ BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ BOOST_ROOT = @BOOST_ROOT@ BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX17 = @HAVE_CXX17@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IXION_API_VERSION = @IXION_API_VERSION@ IXION_MAJOR_API_VERSION = @IXION_MAJOR_API_VERSION@ IXION_MAJOR_VERSION = @IXION_MAJOR_VERSION@ IXION_MICRO_VERSION = @IXION_MICRO_VERSION@ IXION_MINOR_API_VERSION = @IXION_MINOR_API_VERSION@ IXION_MINOR_VERSION = @IXION_MINOR_VERSION@ IXION_VERSION = @IXION_VERSION@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MDDS_CFLAGS = @MDDS_CFLAGS@ MDDS_LIBS = @MDDS_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POW_LIB = @POW_LIB@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ VULKAN_CFLAGS = @VULKAN_CFLAGS@ VULKAN_LIBS = @VULKAN_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ depth_first_search.hpp \ mem_str_buf.hpp \ test_global.hpp all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/include/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/include/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libixion-0.17.0/src/include/depth_first_search.hpp0000644000175000017500000001420413356770726017141 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_DEPTH_FIRST_SEARCH_HPP #define INCLUDED_IXION_DEPTH_FIRST_SEARCH_HPP #include "ixion/exceptions.hpp" #include #include #include #include #include #include namespace ixion { template class depth_first_search { public: typedef _ValueType value_type; typedef _ValueHashType value_hash_type; private: typedef std::unordered_map value_index_map_type; enum cell_color_type { white, gray, black }; class dfs_error : public general_error { public: dfs_error(const std::string& msg) : general_error(msg) {} }; struct node_data { cell_color_type color; value_type node; size_t time_visited; size_t time_finished; node_data() : color(white), time_visited(0), time_finished(0) {} }; public: typedef std::set precedent_cells_type; typedef std::map precedent_map_type; class back_inserter { std::vector& m_sorted; public: back_inserter(std::vector& sorted) : m_sorted(sorted) {} void operator()(const value_type& v) { m_sorted.push_back(v); } }; /** * Stores all precedent-dependent relations which are to be used to * perform topological sort. */ class relations { friend class depth_first_search; public: void insert(value_type pre, value_type dep) { typename precedent_map_type::iterator itr = m_map.find(pre); if (itr == m_map.end()) { // First dependent for this precedent. std::pair r = m_map.insert( typename precedent_map_type::value_type(pre, precedent_cells_type())); if (!r.second) throw dfs_error("failed to insert a new set instance"); itr = r.first; } itr->second.insert(dep); } private: const precedent_map_type& get() const { return m_map; } precedent_map_type m_map; }; template depth_first_search( const _Iter& begin, const _Iter& end, const relations& rels, back_inserter handler); void run(); private: void init(); void visit(size_t cell_index); size_t get_cell_index(const value_type& p) const; const precedent_cells_type* get_precedent_cells(value_type cell); private: const precedent_map_type& m_precedent_map; back_inserter m_handler; size_t m_value_count; value_index_map_type m_value_indices; size_t m_time_stamp; std::vector m_values; }; template template depth_first_search<_ValueType,_ValueHashType>::depth_first_search( const _Iter& begin, const _Iter& end, const relations& rels, back_inserter handler) : m_precedent_map(rels.get()), m_handler(std::move(handler)), m_value_count(std::distance(begin, end)), m_time_stamp(0), m_values(m_value_count) { // Construct value node to index mapping. size_t i = 0; for (_Iter it = begin; it != end; ++it, ++i) m_value_indices.insert( typename value_index_map_type::value_type(*it, i)); } template void depth_first_search<_ValueType,_ValueHashType>::init() { std::vector values(m_value_count); // Now, construct index to cell node mapping. for (const auto& vi : m_value_indices) values[vi.second].node = vi.first; m_values.swap(values); m_time_stamp = 0; } template void depth_first_search<_ValueType,_ValueHashType>::run() { init(); try { for (size_t i = 0; i < m_value_count; ++i) if (m_values[i].color == white) visit(i); } catch(const dfs_error& e) { std::cout << "dfs error: " << e.what() << std::endl; } } template void depth_first_search<_ValueType,_ValueHashType>::visit(size_t cell_index) { value_type p = m_values[cell_index].node; m_values[cell_index].color = gray; m_values[cell_index].time_visited = ++m_time_stamp; do { const precedent_cells_type* depends = get_precedent_cells(p); if (!depends) // No dependent cells. break; for (const value_type& dcell : *depends) { size_t dcell_id = get_cell_index(dcell); if (m_values[dcell_id].color == white) { visit(dcell_id); } } } while (false); m_values[cell_index].color = black; m_values[cell_index].time_finished = ++m_time_stamp; m_handler(m_values[cell_index].node); } template size_t depth_first_search<_ValueType,_ValueHashType>::get_cell_index(const value_type& p) const { typename value_index_map_type::const_iterator itr = m_value_indices.find(p); if (itr == m_value_indices.end()) throw dfs_error("cell ptr to index mapping failed."); return itr->second; } template const typename depth_first_search<_ValueType,_ValueHashType>::precedent_cells_type* depth_first_search<_ValueType,_ValueHashType>::get_precedent_cells(value_type cell) { typename precedent_map_type::const_iterator itr = m_precedent_map.find(cell); if (itr == m_precedent_map.end()) // This cell has no dependent cells. return nullptr; return &itr->second; } } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/include/Makefile.am0000664000175000017500000000011614122770261014605 00000000000000 EXTRA_DIST = \ depth_first_search.hpp \ mem_str_buf.hpp \ test_global.hpp libixion-0.17.0/src/include/mem_str_buf.hpp0000664000175000017500000000334114122770261015567 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef __IXION_MEM_STR_BUF_HPP__ #define __IXION_MEM_STR_BUF_HPP__ #include #include #include namespace ixion { /** * String buffer that only stores the first char position in memory and the * size of the string. */ class IXION_DLLPUBLIC mem_str_buf { public: struct IXION_DLLPUBLIC hash { size_t operator() (const mem_str_buf& s) const; }; mem_str_buf(); mem_str_buf(const char* p); mem_str_buf(const char* p, size_t n); mem_str_buf(const mem_str_buf& r); void append(const char* p); void set_start(const char* p); void inc(); void dec(); void pop_front(); bool empty() const; size_t size() const; const char* get() const; void clear(); void swap(mem_str_buf& r); bool equals(const char* s) const; ::std::string str() const; mem_str_buf& operator= (const mem_str_buf& r); char operator[] (size_t pos) const; bool operator== (const mem_str_buf& r) const; bool operator!= (const mem_str_buf& r) const { return !operator==(r); } char back() const; private: const char* mp_buf; size_t m_size; }; IXION_DLLPUBLIC bool operator< (const mem_str_buf& left, const mem_str_buf& right); IXION_DLLPUBLIC bool operator> (const mem_str_buf& left, const mem_str_buf& right); IXION_DLLPUBLIC std::ostream& operator<< (std::ostream& os, const mem_str_buf& str); } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/include/test_global.hpp0000664000175000017500000000106414120006337015556 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_SRC_TEST_GLOBAL_HPP #define INCLUDED_IXION_SRC_TEST_GLOBAL_HPP #ifdef NDEBUG // release build #undef NDEBUG #include #define NDEBUG #else // debug build #include #endif #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/table_handler.hpp0000664000175000017500000000271414122770261014431 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef IXION_TABLE_HANDLER_HPP #define IXION_TABLE_HANDLER_HPP #include "ixion/interface/table_handler.hpp" #include "ixion/types.hpp" #include "ixion/address.hpp" #include #include #include namespace ixion { class table_handler : public iface::table_handler { public: /** single table entry */ struct entry { string_id_t name; abs_range_t range; std::vector columns; row_t totals_row_count; entry(); }; typedef std::map> entries_type; virtual ~table_handler(); virtual abs_range_t get_range( const abs_address_t& pos, string_id_t column_first, string_id_t column_last, table_areas_t areas) const; virtual abs_range_t get_range( string_id_t table, string_id_t column_first, string_id_t column_last, table_areas_t areas) const; void insert(std::unique_ptr& p); private: abs_range_t get_column_range( const entry& e, string_id_t column_first, string_id_t column_last, table_areas_t areas) const; entries_type m_entries; }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/0000775000175000017500000000000014136644732013035 500000000000000libixion-0.17.0/src/libixion/exceptions.cpp0000664000175000017500000000541414122770261015636 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/exceptions.hpp" #include namespace ixion { general_error::general_error() : m_msg() {} general_error::general_error(const std::string& msg) : m_msg(msg) {} general_error::~general_error() {} const char* general_error::what() const noexcept { return m_msg.c_str(); } void general_error::set_message(const std::string& msg) { m_msg = msg; } struct formula_error::impl { formula_error_t error; std::string msg; std::string buffer; impl(formula_error_t _error) : error(_error) {} impl(formula_error_t _error, std::string _msg) : error(_error), msg(std::move(_msg)) {} }; formula_error::formula_error(formula_error_t fe) : mp_impl(std::make_unique(fe)) {} formula_error::formula_error(formula_error_t fe, std::string msg) : mp_impl(std::make_unique(fe, std::move(msg))) {} formula_error::formula_error(formula_error&& other) : mp_impl(std::move(other.mp_impl)) { other.mp_impl = std::make_unique(formula_error_t::no_error); } formula_error::~formula_error() { } const char* formula_error::what() const noexcept { std::string_view error_name = get_formula_error_name(mp_impl->error); if (mp_impl->msg.empty()) return error_name.data(); std::ostringstream os; os << mp_impl->msg << " (type: " << error_name << ")"; mp_impl->buffer = os.str(); return mp_impl->buffer.data(); } formula_error_t formula_error::get_error() const { return mp_impl->error; } formula_registration_error::formula_registration_error(const std::string& msg) { std::ostringstream os; os << "formula_registration_error: " << msg; set_message(os.str()); } formula_registration_error::~formula_registration_error() {} file_not_found::file_not_found(const std::string& fpath) : general_error(fpath) { std::ostringstream os; os << "specified file not found: " << fpath; set_message(os.str()); } file_not_found::~file_not_found() {} model_context_error::model_context_error(const std::string& msg, error_type type) : general_error(msg), m_type(type) {} model_context_error::~model_context_error() {} model_context_error::error_type model_context_error::get_error_type() const { return m_type; } not_implemented_error::not_implemented_error(const std::string& msg) { std::ostringstream os; os << "not_implemented_error: " << msg; set_message(os.str()); } not_implemented_error::~not_implemented_error() {} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/queue_entry.hpp0000644000175000017500000000115613356770726016042 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_QUEUE_ENTRY_HPP #define INCLUDED_QUEUE_ENTRY_HPP #include "ixion/address.hpp" namespace ixion { class formula_cell; struct queue_entry { formula_cell* p; abs_address_t pos; queue_entry(formula_cell* _p, const abs_address_t& _pos); }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/model_context_impl.hpp0000664000175000017500000001454414122770261017353 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_MODEL_CONTEXT_IMPL_HPP #define INCLUDED_MODEL_CONTEXT_IMPL_HPP #include "ixion/model_context.hpp" #include "ixion/types.hpp" #include "ixion/config.hpp" #include "ixion/dirty_cell_tracker.hpp" #include "mem_str_buf.hpp" #include "workbook.hpp" #include "column_store_type.hpp" #include #include #include #include namespace ixion { namespace detail { class safe_string_pool { using string_pool_type = std::vector>; using string_map_type = std::unordered_map; std::mutex m_mtx; string_pool_type m_strings; string_map_type m_string_map; std::string m_empty_string; string_id_t append_string_unsafe(std::string_view s); public: string_id_t append_string(std::string_view s); string_id_t add_string(std::string_view s); const std::string* get_string(string_id_t identifier) const; size_t size() const; void dump_strings() const; string_id_t get_identifier_from_string(std::string_view s) const; }; class model_context_impl { typedef std::vector strings_type; public: model_context_impl() = delete; model_context_impl(const model_context_impl&) = delete; model_context_impl& operator= (model_context_impl) = delete; model_context_impl(model_context& parent, const rc_size_t& sheet_size); ~model_context_impl(); formula_result_wait_policy_t get_formula_result_wait_policy() const { return m_formula_res_wait_policy; } void notify(formula_event_t event); const config& get_config() const { return m_config; } void set_config(const config& cfg) { m_config = cfg; } void set_sheet_size(const rc_size_t& sheet_size); dirty_cell_tracker& get_cell_tracker() { return m_tracker; } const dirty_cell_tracker& get_cell_tracker() const { return m_tracker; } std::unique_ptr create_session_handler(); void set_session_handler_factory(model_context::session_handler_factory* factory) { mp_session_factory = factory; } iface::table_handler* get_table_handler() { return mp_table_handler; } const iface::table_handler* get_table_handler() const { return mp_table_handler; } void set_table_handler(iface::table_handler* handler) { mp_table_handler = handler; } void empty_cell(const abs_address_t& addr); void set_numeric_cell(const abs_address_t& addr, double val); void set_boolean_cell(const abs_address_t& addr, bool val); void set_string_cell(const abs_address_t& addr, std::string_view s); void set_string_cell(const abs_address_t& addr, string_id_t identifier); void fill_down_cells(const abs_address_t& src, size_t n_dst); formula_cell* set_formula_cell(const abs_address_t& addr, const formula_tokens_store_ptr_t& tokens); formula_cell* set_formula_cell(const abs_address_t& addr, const formula_tokens_store_ptr_t& tokens, formula_result result); void set_grouped_formula_cells(const abs_range_t& group_range, formula_tokens_t tokens); void set_grouped_formula_cells(const abs_range_t& group_range, formula_tokens_t tokens, formula_result result); abs_range_t get_data_range(sheet_t sheet) const; bool is_empty(const abs_address_t& addr) const; celltype_t get_celltype(const abs_address_t& addr) const; double get_numeric_value(const abs_address_t& addr) const; bool get_boolean_value(const abs_address_t& addr) const; string_id_t get_string_identifier(const abs_address_t& addr) const; std::string_view get_string_value(const abs_address_t& addr) const; string_id_t get_identifier_from_string(std::string_view s) const; const formula_cell* get_formula_cell(const abs_address_t& addr) const; formula_cell* get_formula_cell(const abs_address_t& addr); formula_result get_formula_result(const abs_address_t& addr) const; void set_named_expression(std::string name, const abs_address_t& origin, formula_tokens_t&& expr); void set_named_expression(sheet_t sheet, std::string name, const abs_address_t& origin, formula_tokens_t&& expr); const named_expression_t* get_named_expression(std::string_view name) const; const named_expression_t* get_named_expression(sheet_t sheet, std::string_view name) const; sheet_t get_sheet_index(std::string_view name) const; std::string get_sheet_name(sheet_t sheet) const; rc_size_t get_sheet_size() const; size_t get_sheet_count() const; sheet_t append_sheet(std::string&& name); void set_cell_values(sheet_t sheet, std::initializer_list&& rows); string_id_t append_string(std::string_view s); string_id_t add_string(std::string_view s); const std::string* get_string(string_id_t identifier) const; size_t get_string_count() const; void dump_strings() const; const column_store_t* get_column(sheet_t sheet, col_t col) const; const column_stores_t* get_columns(sheet_t sheet) const; double count_range(const abs_range_t& range, const values_t& values_type) const; bool empty() const; const worksheet* fetch_sheet(sheet_t sheet_index) const; column_store_t::const_position_type get_cell_position(const abs_address_t& addr) const; const detail::named_expressions_t& get_named_expressions() const; const detail::named_expressions_t& get_named_expressions(sheet_t sheet) const; model_iterator get_model_iterator( sheet_t sheet, rc_direction_t dir, const abs_rc_range_t& range) const; private: model_context& m_parent; rc_size_t m_sheet_size; workbook m_sheets; config m_config; dirty_cell_tracker m_tracker; iface::table_handler* mp_table_handler; detail::named_expressions_t m_named_expressions; model_context::session_handler_factory* mp_session_factory; strings_type m_sheet_names; ///< index to sheet name map. safe_string_pool m_str_pool; formula_result_wait_policy_t m_formula_res_wait_policy; }; }} #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/dirty_cell_tracker_test.cpp0000644000175000017500000002474713612422767020401 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include using namespace ixion; using namespace std; using ranks_type = std::unordered_map; ranks_type create_ranks(const std::vector& sorted) { ranks_type ranks; size_t rank = 0; for (const abs_range_t& r : sorted) ranks.insert({r, rank++}); return ranks; } void test_empty_query() { cout << "--" << endl << __FUNCTION__ << endl; dirty_cell_tracker tracker; // Empty query. abs_range_set_t mod_cells; abs_range_set_t res = tracker.query_dirty_cells(mod_cells); assert(res.empty()); // A "modified" cell is outside existing sheet range. Make sure we don't // crash here. mod_cells.emplace(1, 1, 1); res = tracker.query_dirty_cells(mod_cells); assert(res.empty()); auto sorted = tracker.query_and_sort_dirty_cells(mod_cells); assert(sorted.empty()); // Dirty cells are like newly entered formula cells that need to be // calculated regardless. abs_range_set_t dirty_cells; dirty_cells.emplace(0, 0, 0); // A1 dirty_cells.emplace(0, 1, 0); // A2 dirty_cells.emplace(0, 0, 1); // B1 dirty_cells.emplace(0, 1, 1); // B2 sorted = tracker.query_and_sort_dirty_cells(mod_cells, &dirty_cells); assert(sorted.size() == 4); } void test_cell_to_cell() { cout << "--" << endl << __FUNCTION__ << endl; dirty_cell_tracker tracker; // A2 to listen to A1. abs_address_t A1(0, 0, 0); abs_address_t A2(0, 1, 0); tracker.add(A2, A1); // A1 is modified. A2 should be updated. abs_range_set_t mod_cells; mod_cells.insert(A1); abs_range_set_t res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 1); abs_range_t cell = *res.cbegin(); assert(cell.first == A2); // A3 to listen to A2. abs_address_t A3(0, 2, 0); tracker.add(A3, A2); // A1 is modified. Both A2 and A3 should be updated. res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 2); assert(res.count(A2) > 0); assert(res.count(A3) > 0); // A2 should be ranked lower than A3. auto sorted = tracker.query_and_sort_dirty_cells(mod_cells); auto ranks = create_ranks(sorted); assert(ranks[A2] < ranks[A3]); // A2 no longer tracks A1, and because of this, a modification of A1 // should not trigger any updates. tracker.remove(A2, A1); res = tracker.query_dirty_cells(mod_cells); assert(res.empty()); // Add A2->A1 once again, to re-establish the previous chain. tracker.add(A2, A1); res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 2); assert(res.count(A2) > 0); assert(res.count(A3) > 0); } void test_cell_to_range() { cout << "--" << endl << __FUNCTION__ << endl; dirty_cell_tracker tracker; // B2 listens to C1:D4. abs_address_t B2(0, 1, 1); abs_range_t C1_D4(0, 0, 2, 4, 2); tracker.add(B2, C1_D4); // D3 gets modified. B2 should be updated. abs_range_set_t mod_cells; mod_cells.emplace(0, 2, 3); abs_range_set_t res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 1); assert(res.count(B2) > 0); // E10 listens to A1:B4 which includes B2. abs_address_t E10(0, 9, 4); abs_range_t A1_B4(0, 0, 0, 4, 2); tracker.add(E10, A1_B4); // D3 gets modified again. This time both B2 and E10 need updating. res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 2); assert(res.count(B2) > 0); assert(res.count(E10) > 0); // B2 no longer listens to C1:D4. tracker.remove(B2, C1_D4); // D3 gets modified again, but no cells need updating. res = tracker.query_dirty_cells(mod_cells); assert(res.empty()); // B3 gets modified. E10 should be updated. mod_cells.clear(); abs_address_t B3(0, 2, 1); mod_cells.insert(B3); res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 1); assert(res.count(E10) > 0); } void test_volatile_cells() { cout << "--" << endl << __FUNCTION__ << endl; dirty_cell_tracker tracker; // We use sheet 2 in this test. abs_address_t A1(1, 0, 0); abs_address_t B2(1, 1, 1); abs_address_t C3(1, 2, 2); tracker.add_volatile(A1); // No cells have been modified. abs_range_set_t mod_cells; abs_range_set_t res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 1); assert(res.count(A1) > 0); tracker.add_volatile(B2); res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 2); assert(res.count(A1) > 0); assert(res.count(B2) > 0); tracker.add_volatile(C3); res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 3); assert(res.count(A1) > 0); assert(res.count(B2) > 0); assert(res.count(C3) > 0); // Start removing the volatile cells one by one. tracker.remove_volatile(B2); res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 2); assert(res.count(A1) > 0); assert(res.count(C3) > 0); tracker.remove_volatile(C3); res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 1); assert(res.count(A1) > 0); tracker.remove_volatile(A1); res = tracker.query_dirty_cells(mod_cells); assert(res.empty()); } void test_volatile_cells_2() { cout << "--" << endl << __FUNCTION__ << endl; dirty_cell_tracker tracker; abs_address_t A1(1, 0, 0); abs_address_t B2(1, 1, 1); abs_address_t C3(1, 2, 2); // B2 tracks A1 and C3 tracks B2. tracker.add(B2, A1); tracker.add(C3, B2); // No cells have been modified. abs_range_set_t mod_cells; abs_range_set_t res = tracker.query_dirty_cells(mod_cells); assert(res.empty()); // Set A1 as volatile cell. All of A2, B2 and C3 should be dirty. tracker.add_volatile(A1); res = tracker.query_dirty_cells(mod_cells); assert(res.size() == 3); auto sorted = tracker.query_and_sort_dirty_cells(mod_cells); assert(sorted.size() == 3); auto ranks = create_ranks(sorted); assert(ranks[A1] < ranks[B2]); assert(ranks[B2] < ranks[C3]); // Remove A1 as volatile cell. Now no cells should be dirty. tracker.remove_volatile(A1); sorted = tracker.query_and_sort_dirty_cells(mod_cells); assert(sorted.empty()); // Now, declare A1 as a dirty cell. abs_range_set_t dirty_cells; dirty_cells.insert(A1); sorted = tracker.query_and_sort_dirty_cells(mod_cells, &dirty_cells); assert(sorted.size() == 3); } void test_multi_sheets() { cout << "--" << endl << __FUNCTION__ << endl; dirty_cell_tracker tracker; // B2 on sheet 2 tracks A10 on sheet 1. abs_address_t s2_B2(1, 1, 1); abs_address_t s1_A10(0, 9, 0); tracker.add(s2_B2, s1_A10); // A10 on sheet 1 gets modified. abs_range_set_t res = tracker.query_dirty_cells(s1_A10); assert(res.size() == 1); assert(res.count(s2_B2) > 0); // A10 on sheet 2 gets modified. This should trigger no updates. abs_address_t s2_A10(1, 9, 0); res = tracker.query_dirty_cells(s2_A10); assert(res.empty()); } void test_recursive_tracking() { cout << "--" << endl << __FUNCTION__ << endl; dirty_cell_tracker tracker; abs_address_t A1(0, 0, 0), B1(0, 0, 1); // A1 and B1 track each other. tracker.add(A1, B1); tracker.add(B1, A1); abs_range_set_t res = tracker.query_dirty_cells(A1); assert(res.size() == 2); assert(res.count(A1) > 0); assert(res.count(B1) > 0); } void test_listen_to_cell_in_range() { cout << "--" << endl << __FUNCTION__ << endl; dirty_cell_tracker tracker; abs_address_t A2(0, 1, 0), E7(0, 6, 4), G11(0, 10, 6); abs_range_t C5_E7(0, 4, 2, 3, 3); abs_range_t A1_A3(0, 0, 0, 3, 1); abs_range_t C1_E1(0, 0, 2, 1, 3); abs_range_t G5_H7(0, 4, 6, 3, 2); abs_range_t E7_G9(0, 6, 4, 3, 3); tracker.add(G11, E7); tracker.add(C5_E7, A1_A3); tracker.add(C5_E7, C1_E1); cout << "--" << endl; cout << tracker.to_string() << endl; abs_range_set_t res = tracker.query_dirty_cells(A2); assert(res.size() == 2); assert(res.count(C5_E7) > 0); assert(res.count(G11) > 0); tracker.add(G5_H7, A1_A3); tracker.remove(G11, E7); tracker.add(G11, E7_G9); cout << "--" << endl; cout << tracker.to_string() << endl; res = tracker.query_dirty_cells(A2); assert(res.size() == 3); assert(res.count(C5_E7) > 0); assert(res.count(G5_H7) > 0); assert(res.count(G11) > 0); // Test topological sort results, and make sure they are ranked correctly. std::vector sorted = tracker.query_and_sort_dirty_cells(A2); auto ranks = create_ranks(sorted); assert(ranks[C5_E7] < ranks[G11]); assert(ranks[G5_H7] < ranks[G11]); } void test_listen_to_3d_range() { cout << "--" << endl << __FUNCTION__ << endl; dirty_cell_tracker tracker; abs_address_t E7(0, 6, 4); abs_range_t C1_E5_sheets_0_2(0, 0, 2, 5, 3); C1_E5_sheets_0_2.last.sheet += 2; tracker.add(E7, C1_E5_sheets_0_2); cout << "--" << endl; cout << tracker.to_string() << endl; abs_address_t D3(0, 2, 3); for (sheet_t s = 0; s <= 4; ++s) { D3.sheet = s; auto cells = tracker.query_dirty_cells(D3); if (s <= 2) { assert(cells.size() == 1); assert(E7 == *cells.begin()); } else assert(cells.empty()); } for (sheet_t s = 0; s <= 4; ++s) { abs_range_t E5_F6(0, 4, 4, 2, 2); E5_F6.first.sheet = E5_F6.last.sheet = s; auto cells = tracker.query_dirty_cells(E5_F6); if (s <= 2) { assert(cells.size() == 1); assert(E7 == *cells.begin()); } else assert(cells.empty()); } // Remove the multi-sheet listener, and make sure the tracker is empty. tracker.remove(E7, C1_E5_sheets_0_2); assert(tracker.empty()); } int main() { test_empty_query(); test_cell_to_cell(); test_cell_to_range(); test_volatile_cells(); test_volatile_cells_2(); test_multi_sheets(); test_recursive_tracking(); test_listen_to_cell_in_range(); test_listen_to_3d_range(); return EXIT_SUCCESS; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/concrete_formula_tokens.cpp0000664000175000017500000001127414105607506020372 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/formula_function_opcode.hpp" #include "concrete_formula_tokens.hpp" #include "utils.hpp" #include namespace ixion { // ============================================================================ opcode_token::opcode_token(fopcode_t oc) : formula_token(oc) { } opcode_token::opcode_token(const opcode_token& r) : formula_token(r) { } opcode_token::~opcode_token() { } void opcode_token::write_string(std::ostream& os) const { os << "opcode token: (name=" << get_opcode_name(get_opcode()) << "; s='" << get_formula_opcode_string(get_opcode()) << "')"; } // ============================================================================ value_token::value_token(double value) : formula_token(fop_value), m_value(value) { } value_token::~value_token() { } double value_token::get_value() const { return m_value; } void value_token::write_string(std::ostream& os) const { os << "value token: " << m_value; } string_token::string_token(string_id_t str_identifier) : formula_token(fop_string), m_str_identifier(str_identifier) { #ifdef IXION_DEBUG_UTILS detail::ensure_max_size<4>(str_identifier); #endif } string_token::~string_token() {} uint32_t string_token::get_uint32() const { return m_str_identifier; } void string_token::write_string(std::ostream& os) const { os << "string token: (identifier=" << m_str_identifier << ")"; } // ============================================================================ single_ref_token::single_ref_token(const address_t& addr) : formula_token(fop_single_ref), m_address(addr) { } single_ref_token::single_ref_token(const single_ref_token& r) : formula_token(r), m_address(r.m_address) { } single_ref_token::~single_ref_token() { } address_t single_ref_token::get_single_ref() const { return m_address; } void single_ref_token::write_string(std::ostream& os) const { os << "single ref token: " << m_address; } // ============================================================================ range_ref_token::range_ref_token(const range_t& range) : formula_token(fop_range_ref), m_range(range) { } range_ref_token::range_ref_token(const range_ref_token& r) : formula_token(r), m_range(r.m_range) { } range_ref_token::~range_ref_token() { } range_t range_ref_token::get_range_ref() const { return m_range; } void range_ref_token::write_string(std::ostream& os) const { os << "range ref token: " << m_range; } table_ref_token::table_ref_token(const table_t& table) : formula_token(fop_table_ref), m_table(table) {} table_ref_token::table_ref_token(const table_ref_token& r) : formula_token(r), m_table(r.m_table) {} table_ref_token::~table_ref_token() {} table_t table_ref_token::get_table_ref() const { return m_table; } void table_ref_token::write_string(std::ostream& os) const { os << "table ref token: " << "TODO"; } named_exp_token::named_exp_token(const char* p, size_t n) : formula_token(fop_named_expression), m_name(p, n) {} named_exp_token::named_exp_token(const named_exp_token& r) : formula_token(r), m_name(r.m_name) {} named_exp_token::~named_exp_token() {} std::string named_exp_token::get_name() const { return m_name; } void named_exp_token::write_string(std::ostream& os) const { os << "named expression token: '" << m_name << "'"; } // ============================================================================ function_token::function_token(formula_function_t func_oc) : formula_token(fop_function), m_func_oc(func_oc) { #ifdef IXION_DEBUG_UTILS detail::ensure_max_size<4>(func_oc); #endif } function_token::function_token(const function_token& r) : formula_token(r), m_func_oc(r.m_func_oc) { } function_token::~function_token() { } uint32_t function_token::get_uint32() const { return static_cast(m_func_oc); } void function_token::write_string(std::ostream& os) const { os << "function token: (opcode=" << uint32_t(m_func_oc) << "; name='" << get_formula_function_name(m_func_oc) << "')"; } error_token::error_token(uint32_t n_msgs) : formula_token(fop_error), m_n_msgs(n_msgs) {} error_token::error_token(const error_token& other) : formula_token(fop_error), m_n_msgs(other.m_n_msgs) {} error_token::~error_token() {} uint32_t error_token::get_uint32() const { return m_n_msgs; } } // namespace ixion /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_parser.hpp0000644000175000017500000000432713273351731016506 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_FORMULA_PARSER_HPP #define INCLUDED_IXION_FORMULA_PARSER_HPP #include "ixion/exceptions.hpp" #include "ixion/formula_tokens.hpp" #include "lexer_tokens.hpp" #include namespace ixion { namespace iface { class formula_model_access; } class formula_name_resolver; /** * Class formula_parser parses a series of primitive (or lexer) tokens * passed on from the lexer, and turn them into a series of formula tokens. * It also picks up a list of cells that it depends on. */ class formula_parser { formula_parser() = delete; formula_parser(const formula_parser&) = delete; formula_parser& operator=(const formula_parser&) = delete; public: class parse_error : public general_error { public: parse_error(const ::std::string& msg); }; formula_parser(const lexer_tokens_t& tokens, iface::formula_model_access& cxt, const formula_name_resolver& resolver); ~formula_parser(); void set_origin(const abs_address_t& pos); void parse(); void print_tokens() const; formula_tokens_t& get_tokens(); private: void primitive(lexer_opcode_t oc); void name(const lexer_token_base& t); void literal(const lexer_token_base& t); void value(const lexer_token_base& t); void less(const lexer_token_base& t); void greater(const lexer_token_base& t); const lexer_token_base& get_token() const; bool has_token() const; bool has_next() const; void next(); void prev(); private: lexer_tokens_t::const_iterator m_itr_cur; lexer_tokens_t::const_iterator m_itr_end; const lexer_tokens_t& m_tokens; // lexer tokens of this expression iface::formula_model_access& m_context; formula_tokens_t m_formula_tokens; abs_address_t m_pos; // reference position (usually current cell). always absolute. const formula_name_resolver& m_resolver; }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/model_types.cpp0000664000175000017500000000070213722272744016004 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "model_types.hpp" namespace ixion { namespace detail { const std::string empty_string = ""; }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_interpreter.hpp0000644000175000017500000000705513616122226017552 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_FORMULA_INTERPRETER_HPP #define INCLUDED_IXION_FORMULA_INTERPRETER_HPP #include "ixion/global.hpp" #include "ixion/formula_tokens.hpp" #include "ixion/formula_result.hpp" #include "formula_value_stack.hpp" #include #include #include namespace ixion { class formula_cell; namespace iface { class formula_model_access; class session_handler; } /** * The formula interpreter parses a series of formula tokens representing a * formula expression, and calculates the result of that expression. * *

Intermediate result of each handler is pushed onto the stack and * popped from it for the calling method to retrieve. By the end of the * interpretation there should only be one result left on the stack which is * the final result of the interpretation of the expression. The number of * intermediate results (or stack values) on the stack is normally one at * the end of each handler, except for the function handler where the number * of stack values may be more than one when the function may take more than * one argument.

*/ class formula_interpreter { using name_set = std::unordered_set; using fv_stacks_type = std::deque; public: typedef ::std::vector local_tokens_type; formula_interpreter() = delete; formula_interpreter(const formula_interpreter&) = delete; formula_interpreter& operator= (formula_interpreter) = delete; formula_interpreter(const formula_cell* cell, iface::formula_model_access& cxt); ~formula_interpreter(); void set_origin(const abs_address_t& pos); bool interpret(); formula_result transfer_result(); formula_error_t get_error() const; private: /** * Expand all named expressions into a flat set of tokens. This is also * where we detect circular referencing of named expressions. */ void init_tokens(); void pop_result(); void expand_named_expression(const named_expression_t* expr, name_set& used_names); void ensure_token_exists() const; bool has_token() const; void next(); const formula_token& token() const; const formula_token& token_or_throw() const; const formula_token& next_token(); // The following methods are handlers. In each handler, the initial // position is always set to the first unprocessed token. Each handler is // responsible for setting the token position to the next unprocessed // position when it finishes. void expression(); void term(); void factor(); bool sign(); void paren(); void single_ref(); void range_ref(); void table_ref(); void constant(); void literal(); void function(); void clear_stacks(); void push_stack(); void pop_stack(); formula_value_stack& get_stack(); private: const formula_cell* m_parent_cell; iface::formula_model_access& m_context; std::unique_ptr mp_handler; abs_address_t m_pos; fv_stacks_type m_stacks; local_tokens_type m_tokens; local_tokens_type::const_iterator m_cur_token_itr; local_tokens_type::const_iterator m_end_token_pos; formula_result m_result; formula_error_t m_error; }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/cell_access.cpp0000664000175000017500000001372014122770261015714 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/cell_access.hpp" #include "ixion/global.hpp" #include "ixion/model_context.hpp" #include "ixion/formula_result.hpp" #include "model_context_impl.hpp" #include "workbook.hpp" #include "utils.hpp" #include "model_types.hpp" namespace ixion { struct cell_access::impl { const model_context& cxt; column_store_t::const_position_type pos; impl(const model_context& _cxt) : cxt(_cxt) {} }; cell_access::cell_access(const model_context& cxt, const abs_address_t& addr) : mp_impl(std::make_unique(cxt)) { mp_impl->pos = cxt.mp_impl->get_cell_position(addr); } cell_access::cell_access(cell_access&& other) : mp_impl(std::move(other.mp_impl)) { other.mp_impl = std::make_unique(mp_impl->cxt); } cell_access& cell_access::operator= (cell_access&& other) { mp_impl = std::move(other.mp_impl); other.mp_impl = std::make_unique(mp_impl->cxt); return *this; } cell_access::~cell_access() {} celltype_t cell_access::get_type() const { return detail::to_celltype(mp_impl->pos.first->type); } cell_value_t cell_access::get_value_type() const { celltype_t raw_type = get_type(); if (raw_type != celltype_t::formula) // celltype_t and cell_result_t are numerically equivalent except for the formula slot. return static_cast(raw_type); const formula_cell* fc = formula_element_block::at(*mp_impl->pos.first->data, mp_impl->pos.second); formula_result res = fc->get_result_cache(mp_impl->cxt.get_formula_result_wait_policy()); // by calling this we should not get a matrix result. switch (res.get_type()) { case formula_result::result_type::value: return cell_value_t::numeric; case formula_result::result_type::string: return cell_value_t::string; case formula_result::result_type::error: return cell_value_t::error; case formula_result::result_type::matrix: throw std::logic_error("we shouldn't be getting a matrix result type here."); } return cell_value_t::unknown; } const formula_cell* cell_access::get_formula_cell() const { if (mp_impl->pos.first->type != element_type_formula) return nullptr; return formula_element_block::at(*mp_impl->pos.first->data, mp_impl->pos.second); } formula_result cell_access::get_formula_result() const { const formula_cell* fc = get_formula_cell(); if (!fc) throw general_error("cell is not a formula cell."); return fc->get_result_cache(mp_impl->cxt.get_formula_result_wait_policy()); } double cell_access::get_numeric_value() const { switch (mp_impl->pos.first->type) { case element_type_numeric: return numeric_element_block::at(*mp_impl->pos.first->data, mp_impl->pos.second); case element_type_boolean: { auto it = boolean_element_block::cbegin(*mp_impl->pos.first->data); std::advance(it, mp_impl->pos.second); return *it ? 1.0 : 0.0; } case element_type_formula: { const formula_cell* p = formula_element_block::at(*mp_impl->pos.first->data, mp_impl->pos.second); return p->get_value(mp_impl->cxt.get_formula_result_wait_policy()); } default: ; } return 0.0; } bool cell_access::get_boolean_value() const { switch (mp_impl->pos.first->type) { case element_type_numeric: return numeric_element_block::at(*mp_impl->pos.first->data, mp_impl->pos.second) != 0.0 ? true : false; case element_type_boolean: { auto it = boolean_element_block::cbegin(*mp_impl->pos.first->data); std::advance(it, mp_impl->pos.second); return *it; } case element_type_formula: { const formula_cell* p = formula_element_block::at(*mp_impl->pos.first->data, mp_impl->pos.second); return p->get_value(mp_impl->cxt.get_formula_result_wait_policy()) == 0.0 ? false : true; } default: ; } return false; } std::string_view cell_access::get_string_value() const { switch (mp_impl->pos.first->type) { case element_type_string: { string_id_t sid = string_element_block::at(*mp_impl->pos.first->data, mp_impl->pos.second); const std::string* p = mp_impl->cxt.get_string(sid); return p ? *p : std::string_view{}; } case element_type_formula: { const formula_cell* p = formula_element_block::at(*mp_impl->pos.first->data, mp_impl->pos.second); return p->get_string(mp_impl->cxt.get_formula_result_wait_policy()); } case element_type_empty: return detail::empty_string; default: ; } return std::string_view{}; } string_id_t cell_access::get_string_identifier() const { switch (mp_impl->pos.first->type) { case element_type_string: return string_element_block::at(*mp_impl->pos.first->data, mp_impl->pos.second); default: ; } return empty_string_id; } formula_error_t cell_access::get_error_value() const { if (mp_impl->pos.first->type != element_type_formula) // this is not a formula cell. return formula_error_t::no_error; const formula_cell* fc = formula_element_block::at(*mp_impl->pos.first->data, mp_impl->pos.second); formula_result res = fc->get_result_cache(mp_impl->cxt.get_formula_result_wait_policy()); if (res.get_type() != formula_result::result_type::error) // this formula cell doesn't have an error result. return formula_error_t::no_error; return res.get_error(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/ixion_test_track_deps.cpp0000664000175000017500000001114014122770261020032 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/model_context.hpp" #include "ixion/macros.hpp" #include "ixion/formula_name_resolver.hpp" #include "ixion/formula.hpp" #include #include using namespace ixion; using namespace std; void test_single_cell_dependency() { model_context cxt{{400, 200}}; cxt.append_sheet("One"); auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); cxt.set_numeric_cell(abs_address_t(0,0,0), 1.0); // A1 // A2 abs_address_t pos(0,1,0); formula_tokens_t tokens = parse_formula_string(cxt, pos, *resolver, "A1*2"); formula_tokens_store_ptr_t store = formula_tokens_store::create(); store->get() = std::move(tokens); cxt.set_formula_cell(pos, store); register_formula_cell(cxt, pos); // A3 pos.row = 2; tokens = parse_formula_string(cxt, pos, *resolver, "A2*2"); store = formula_tokens_store::create(); store->get() = std::move(tokens); cxt.set_formula_cell(pos, store); register_formula_cell(cxt, pos); // If A1 is modified, then both A2 and A3 should get updated. abs_address_set_t mod_cells = { { 0, 0, 0 } }; abs_address_set_t cells = query_dirty_cells(cxt, mod_cells); assert(cells.size() == 2); assert(cells.count(abs_address_t(0,1,0)) == 1); assert(cells.count(abs_address_t(0,2,0)) == 1); } void test_range_dependency() { model_context cxt{{400, 200}}; cxt.append_sheet("One"); cxt.set_numeric_cell(abs_address_t(0,0,0), 1.0); // A1 cxt.set_numeric_cell(abs_address_t(0,0,0), 2.0); // A2 cxt.set_numeric_cell(abs_address_t(0,0,0), 3.0); // A3 cxt.set_numeric_cell(abs_address_t(0,0,2), 4.0); // C1 cxt.set_numeric_cell(abs_address_t(0,0,2), 5.0); // D1 cxt.set_numeric_cell(abs_address_t(0,0,2), 6.0); // E1 auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); // C5 abs_address_t pos(0,4,2); formula_tokens_t tokens = parse_formula_string(cxt, pos, *resolver, "SUM(A1:A3,C1:E1)"); auto ts = formula_tokens_store::create(); ts->get() = std::move(tokens); cxt.set_formula_cell(pos, ts); register_formula_cell(cxt, pos); // A10 pos.row = 9; pos.column = 0; tokens = parse_formula_string(cxt, pos, *resolver, "C5*2"); ts = formula_tokens_store::create(); ts->get() = std::move(tokens); cxt.set_formula_cell(pos, ts); register_formula_cell(cxt, pos); // If A1 is modified, both C5 and A10 should get updated. abs_address_set_t addrs = { abs_address_t(0,0,0) }; abs_address_set_t cells = query_dirty_cells(cxt, addrs); assert(cells.count(abs_address_t(0,4,2)) == 1); assert(cells.count(abs_address_t(0,9,0)) == 1); } void test_matrix_dependency() { model_context cxt{{400, 200}}; cxt.append_sheet("One"); cxt.set_numeric_cell(abs_address_t(0,0,0), 1.0); // A1 cxt.set_numeric_cell(abs_address_t(0,0,0), 2.0); // A2 cxt.set_numeric_cell(abs_address_t(0,0,0), 3.0); // A3 cxt.set_numeric_cell(abs_address_t(0,0,2), 4.0); // C1 cxt.set_numeric_cell(abs_address_t(0,0,2), 5.0); // D1 cxt.set_numeric_cell(abs_address_t(0,0,2), 6.0); // E1 abs_range_t range; range.first = abs_address_t(0,4,2); // C5 range.last = abs_address_t(0,6,4); // E7 auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); // C5:E7 formula_tokens_t tokens = parse_formula_string( cxt, range.first, *resolver, "MMULT(A1:A3,C1:E1)"); cxt.set_grouped_formula_cells(range, std::move(tokens)); register_formula_cell(cxt, range.first); // Register only the top-left cell. // A10 abs_address_t pos(0,9,0); tokens = parse_formula_string(cxt, pos, *resolver, "C5*2"); auto ts = formula_tokens_store::create(); ts->get() = std::move(tokens); cxt.set_formula_cell(pos, ts); register_formula_cell(cxt, pos); // If A1 is modified, both C5 and A10 should get updated. abs_address_set_t addrs = { abs_address_t(0,0,0) }; abs_address_set_t cells = query_dirty_cells(cxt, addrs); assert(cells.count(abs_address_t(0,4,2)) == 1); assert(cells.count(abs_address_t(0,9,0)) == 1); } int main() { test_single_cell_dependency(); test_range_dependency(); test_matrix_dependency(); return EXIT_SUCCESS; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_functions.hpp0000664000175000017500000000443214122770261017216 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef __IXION_FORMULA_FUNCTIONS_HPP__ #define __IXION_FORMULA_FUNCTIONS_HPP__ #include "ixion/global.hpp" #include "ixion/exceptions.hpp" #include "ixion/formula_function_opcode.hpp" #include "formula_value_stack.hpp" #include #include namespace ixion { class formula_token; namespace iface { class formula_model_access; } /** * Collection of built-in cell function implementations. Note that those * functions that return a string result may modify the state of the * model context when the result string is not yet in the shared string * pool. */ class formula_functions { public: class invalid_arg : public general_error { public: invalid_arg(const ::std::string& msg); }; formula_functions(iface::formula_model_access& cxt); ~formula_functions(); static formula_function_t get_function_opcode(const formula_token& token); static formula_function_t get_function_opcode(std::string_view s); static std::string_view get_function_name(formula_function_t oc); void interpret(formula_function_t oc, formula_value_stack& args); private: void fnc_max(formula_value_stack& args) const; void fnc_min(formula_value_stack& args) const; void fnc_sum(formula_value_stack& args) const; void fnc_counta(formula_value_stack& args) const; void fnc_average(formula_value_stack& args) const; void fnc_mmult(formula_value_stack& args) const; void fnc_pi(formula_value_stack& args) const; void fnc_int(formula_value_stack& args) const; void fnc_if(formula_value_stack& args) const; void fnc_len(formula_value_stack& args) const; void fnc_concatenate(formula_value_stack& args) const; void fnc_left(formula_value_stack& args) const; void fnc_now(formula_value_stack& args) const; void fnc_wait(formula_value_stack& args) const; void fnc_subtotal(formula_value_stack& args) const; private: iface::formula_model_access& m_context; }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/model_types.hpp0000664000175000017500000000126613722272744016017 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_MODEL_TYPES_HPP #define INCLUDED_IXION_MODEL_TYPES_HPP #include #include #include #include "ixion/formula_tokens.hpp" namespace ixion { class formula_cell; namespace detail { typedef std::map named_expressions_t; extern const std::string empty_string; }} #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/dirty_cell_tracker.cpp0000664000175000017500000003152513735106106017324 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/dirty_cell_tracker.hpp" #include "ixion/global.hpp" #include "ixion/formula_name_resolver.hpp" #include "depth_first_search.hpp" #include "debug.hpp" #include #include #include namespace ixion { namespace { using rtree_type = mdds::rtree; using rtree_array_type = std::deque; } // anonymous namespace struct dirty_cell_tracker::impl { rtree_array_type m_grids; abs_range_set_t m_volatile_cells; mutable std::unique_ptr m_resolver; impl() {} rtree_type& fetch_grid_or_resize(size_t n) { if (m_grids.size() <= n) m_grids.resize(n+1); return m_grids[n]; } const rtree_type* fetch_grid(size_t n) const { return (n < m_grids.size()) ? &m_grids[n] : nullptr; } rtree_type* fetch_grid(size_t n) { return (n < m_grids.size()) ? &m_grids[n] : nullptr; } /** * Given a modified cell range, return all ranges that are directly * affected by it. * * @param range modified cell range. * * @return collection of ranges that are directly affected by the modified * cell range. */ abs_range_set_t get_affected_cell_ranges(const abs_range_t& range) const { const rtree_type* grid = fetch_grid(range.first.sheet); if (!grid) return abs_range_set_t(); rtree_type::const_search_results res = grid->search( {{range.first.row, range.first.column}, {range.last.row, range.last.column}}, rtree_type::search_type::overlap); abs_range_set_t ranges; for (const abs_range_set_t& range_set : res) ranges.insert(range_set.begin(), range_set.end()); return ranges; } std::string print(const abs_range_t& range) const { if (!m_resolver) m_resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, nullptr); abs_address_t origin(0, 0, 0); range_t rrange = range; rrange.set_absolute(false); std::ostringstream os; os << "Sheet" << (rrange.first.sheet+1) << '!'; if (rrange.first == rrange.last) os << m_resolver->get_name(rrange.first, origin, false); else os << m_resolver->get_name(rrange, origin, false); return os.str(); } }; dirty_cell_tracker::dirty_cell_tracker() : mp_impl(std::make_unique()) {} dirty_cell_tracker::~dirty_cell_tracker() {} void dirty_cell_tracker::add(const abs_range_t& src, const abs_range_t& dest) { if (!src.valid() || src.first.sheet != src.last.sheet) { // source range must be on one sheet. std::ostringstream os; os << "dirty_cell_tracker::add: invalid source range: src=" << src; throw std::invalid_argument(os.str()); } if (!dest.valid()) { std::ostringstream os; os << "dirty_cell_tracker::add: invalid destination range: src=" << src << "; dest=" << dest; throw std::invalid_argument(os.str()); } if (dest.all_columns() || dest.all_rows()) { std::ostringstream os; os << "dirty_cell_tracker::add: unset column or row range is not allowed " << dest; throw std::invalid_argument(os.str()); } for (sheet_t sheet = dest.first.sheet; sheet <= dest.last.sheet; ++sheet) { rtree_type& tree = mp_impl->fetch_grid_or_resize(sheet); rtree_type::extent_type search_box( {{dest.first.row, dest.first.column}, {dest.last.row, dest.last.column}}); rtree_type::search_results res = tree.search(search_box, rtree_type::search_type::match); if (res.begin() == res.end()) { // No listener for this destination range. Insert a new one. abs_range_set_t listener; listener.emplace(src); tree.insert(search_box, std::move(listener)); } else { // A listener already exists for this destination cell. abs_range_set_t& listener = *res.begin(); listener.emplace(src); } } } void dirty_cell_tracker::remove(const abs_range_t& src, const abs_range_t& dest) { if (!src.valid() || src.first.sheet != src.last.sheet) { // source range must be on one sheet. std::ostringstream os; os << "dirty_cell_tracker::add: invalid source range: src=" << src; throw std::invalid_argument(os.str()); } if (!dest.valid()) { std::ostringstream os; os << "dirty_cell_tracker::remove: invalid destination range: src=" << src << "; dest=" << dest; throw std::invalid_argument(os.str()); } if (dest.all_columns() || dest.all_rows()) { std::ostringstream os; os << "dirty_cell_tracker::remove: unset column or row range is not allowed " << dest; throw std::invalid_argument(os.str()); } for (sheet_t sheet = dest.first.sheet; sheet <= dest.last.sheet; ++sheet) { rtree_type* tree = mp_impl->fetch_grid(sheet); if (!tree) { IXION_DEBUG("Nothing is tracked on sheet " << sheet << "."); continue; } rtree_type::extent_type search_box( {{dest.first.row, dest.first.column}, {dest.last.row, dest.last.column}}); rtree_type::search_results res = tree->search(search_box, rtree_type::search_type::match); if (res.begin() == res.end()) { // No listener for this destination cell. Nothing to remove. IXION_DEBUG(dest << " is not being tracked by anybody on sheet " << sheet << "."); continue; } rtree_type::iterator it_listener = res.begin(); abs_range_set_t& listener = *it_listener; size_t n_removed = listener.erase(src); if (!n_removed) { IXION_DEBUG(src << " was not tracking " << dest << " on sheet " << sheet << "."); } if (listener.empty()) // Remove this from the R-tree. tree->erase(it_listener); } } void dirty_cell_tracker::add_volatile(const abs_range_t& pos) { mp_impl->m_volatile_cells.insert(pos); } void dirty_cell_tracker::remove_volatile(const abs_range_t& pos) { mp_impl->m_volatile_cells.erase(pos); } abs_range_set_t dirty_cell_tracker::query_dirty_cells(const abs_range_t& modified_cell) const { abs_range_set_t mod_cells; mod_cells.insert(modified_cell); return query_dirty_cells(mod_cells); } abs_range_set_t dirty_cell_tracker::query_dirty_cells(const abs_range_set_t& modified_cells) const { abs_range_set_t dirty_formula_cells; // Volatile cells are in theory always formula cells and therefore always // should be included. dirty_formula_cells.insert( mp_impl->m_volatile_cells.begin(), mp_impl->m_volatile_cells.end()); abs_range_set_t cur_modified_cells = modified_cells; for (const abs_range_t& r : mp_impl->m_volatile_cells) cur_modified_cells.insert(r); while (!cur_modified_cells.empty()) { abs_range_set_t next_modified_cells; for (const abs_range_t& mc : cur_modified_cells) { abs_range_set_t affected_ranges = mp_impl->get_affected_cell_ranges(mc); for (const abs_range_t& r : affected_ranges) { auto res = dirty_formula_cells.insert(r); if (res.second) // This affected range has not yet been visited. Put it // in the chain for the next round of checks. next_modified_cells.insert(r); } } cur_modified_cells.swap(next_modified_cells); } return dirty_formula_cells; } std::vector dirty_cell_tracker::query_and_sort_dirty_cells(const abs_range_t& modified_cell) const { abs_range_set_t mod_cells; mod_cells.insert(modified_cell); return query_and_sort_dirty_cells(mod_cells); } std::vector dirty_cell_tracker::query_and_sort_dirty_cells( const abs_range_set_t& modified_cells, const abs_range_set_t* dirty_formula_cells) const { abs_range_set_t cur_modified_cells = modified_cells; abs_range_set_t final_dirty_formula_cells; // Get the initial set of formula cells affected by the modified cells. // Note that these modified cells are not dirty formula cells. if (!cur_modified_cells.empty()) { abs_range_set_t next_modified_cells; for (const abs_range_t& mc : cur_modified_cells) { for (const abs_range_t& r : mp_impl->get_affected_cell_ranges(mc)) { auto res = final_dirty_formula_cells.insert(r); if (res.second) // This affected range has not yet been visited. Put it // in the chain for the next round of checks. next_modified_cells.insert(r); } } cur_modified_cells.swap(next_modified_cells); } // Because the modified cells in the subsequent rounds are all dirty // formula cells, we need to track precedent-dependent relationships for // later sorting. cur_modified_cells.insert(mp_impl->m_volatile_cells.begin(), mp_impl->m_volatile_cells.end()); if (dirty_formula_cells) cur_modified_cells.insert(dirty_formula_cells->begin(), dirty_formula_cells->end()); using dfs_type = depth_first_search; dfs_type::relations rels; while (!cur_modified_cells.empty()) { abs_range_set_t next_modified_cells; for (const abs_range_t& mc : cur_modified_cells) { for (const abs_range_t& r : mp_impl->get_affected_cell_ranges(mc)) { // Record each precedent-dependent relationship (r = // precedent; mc = dependent). rels.insert(r, mc); auto res = final_dirty_formula_cells.insert(r); if (res.second) // This affected range has not yet been visited. Put it // in the chain for the next round of checks. next_modified_cells.insert(r); } } cur_modified_cells.swap(next_modified_cells); } // Volatile cells are always formula cells and therefore always should be // included. final_dirty_formula_cells.insert( mp_impl->m_volatile_cells.begin(), mp_impl->m_volatile_cells.end()); if (dirty_formula_cells) { final_dirty_formula_cells.insert( dirty_formula_cells->begin(), dirty_formula_cells->end()); } // Perform topological sort on the dirty formula cell ranges. std::vector retval; dfs_type sorter(final_dirty_formula_cells.begin(), final_dirty_formula_cells.end(), rels, dfs_type::back_inserter(retval)); sorter.run(); return retval; } std::string dirty_cell_tracker::to_string() const { auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, nullptr); const abs_address_t origin(0, 0, 0); rc_t max_val = std::numeric_limits::max(); std::vector lines; for (rc_t i = 0, n = mp_impl->m_grids.size(); i < n; ++i) { const rtree_type& grid = mp_impl->m_grids[i]; rtree_type::const_search_results res = grid.search({{0, 0}, {max_val, max_val}}, rtree_type::search_type::overlap); for (auto it = res.cbegin(); it != res.cend(); ++it) { const rtree_type::extent_type& ext = it.extent(); const abs_range_set_t& srcs = *it; range_t dest( address_t(i, ext.start.d[0], ext.start.d[1]), address_t(i, ext.end.d[0], ext.end.d[1])); dest.set_absolute(false); std::string dest_name = ext.is_point() ? resolver->get_name(dest.first, origin, false) : resolver->get_name(dest, origin, false); for (const abs_range_t& src : srcs) { std::ostringstream os; os << mp_impl->print(src); os << " -> Sheet" << (dest.first.sheet+1) << '!' << dest_name; lines.push_back(os.str()); } } } if (lines.empty()) return std::string(); std::ostringstream os; auto it = lines.begin(); os << *it; for (++it; it != lines.end(); ++it) os << std::endl << *it; return os.str(); } bool dirty_cell_tracker::empty() const { for (const rtree_type& grid : mp_impl->m_grids) { if (!grid.empty()) return false; } return true; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/Makefile.in0000664000175000017500000017005314136644552015030 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @BUILD_VULKAN_TRUE@am__append_1 = -DBUILD_VULKAN check_PROGRAMS = document-test$(EXEEXT) ixion-test$(EXEEXT) \ ixion-test-track-deps$(EXEEXT) compute-engine-test$(EXEEXT) \ dirty-cell-tracker-test$(EXEEXT) @IXION_THREADS_TRUE@am__append_2 = \ @IXION_THREADS_TRUE@ cell_queue_manager.hpp \ @IXION_THREADS_TRUE@ cell_queue_manager.cpp TESTS = document-test$(EXEEXT) ixion-test$(EXEEXT) \ ixion-test-track-deps$(EXEEXT) compute-engine-test$(EXEEXT) \ dirty-cell-tracker-test$(EXEEXT) subdir = src/libixion ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = constants.inl CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkglibdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = @BUILD_VULKAN_TRUE@ixion_@IXION_API_VERSION@_vulkan_la_DEPENDENCIES = \ @BUILD_VULKAN_TRUE@ libixion-@IXION_API_VERSION@.la \ @BUILD_VULKAN_TRUE@ $(am__DEPENDENCIES_1) am__ixion_@IXION_API_VERSION@_vulkan_la_SOURCES_DIST = \ compute_engine_vulkan.hpp compute_engine_vulkan.cpp \ vulkan_obj.hpp vulkan_obj.cpp @BUILD_VULKAN_TRUE@am_ixion_@IXION_API_VERSION@_vulkan_la_OBJECTS = ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.lo \ @BUILD_VULKAN_TRUE@ ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.lo ixion_@IXION_API_VERSION@_vulkan_la_OBJECTS = \ $(am_ixion_@IXION_API_VERSION@_vulkan_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = ixion_@IXION_API_VERSION@_vulkan_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ $(ixion_@IXION_API_VERSION@_vulkan_la_LDFLAGS) $(LDFLAGS) -o \ $@ @BUILD_VULKAN_TRUE@am_ixion_@IXION_API_VERSION@_vulkan_la_rpath = \ @BUILD_VULKAN_TRUE@ -rpath $(pkglibdir) libixion_@IXION_API_VERSION@_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am__libixion_@IXION_API_VERSION@_la_SOURCES_DIST = address.cpp \ address_iterator.cpp calc_status.hpp calc_status.cpp cell.cpp \ cell_access.cpp column_store_type.hpp compute_engine.cpp \ concrete_formula_tokens.hpp concrete_formula_tokens.cpp \ config.cpp debug.hpp debug.cpp dirty_cell_tracker.cpp \ document.cpp exceptions.cpp formula.cpp formula_calc.cpp \ formula_function_opcode.cpp formula_functions.hpp \ formula_functions.cpp formula_interpreter.hpp \ formula_interpreter.cpp formula_lexer.hpp formula_lexer.cpp \ formula_name_resolver.cpp formula_parser.hpp \ formula_parser.cpp formula_result.cpp formula_tokens.cpp \ formula_value_stack.hpp formula_value_stack.cpp global.cpp \ info.cpp lexer_tokens.hpp lexer_tokens.cpp matrix.cpp \ mem_str_buf.cpp model_context.cpp model_context_impl.hpp \ model_context_impl.cpp model_iterator.cpp model_types.hpp \ model_types.cpp module.cpp named_expressions_iterator.cpp \ queue_entry.hpp queue_entry.cpp table.cpp types.cpp utils.hpp \ utils.cpp workbook.hpp workbook.cpp interface.cpp \ cell_queue_manager.hpp cell_queue_manager.cpp @IXION_THREADS_TRUE@am__objects_1 = cell_queue_manager.lo am_libixion_@IXION_API_VERSION@_la_OBJECTS = address.lo \ address_iterator.lo calc_status.lo cell.lo cell_access.lo \ compute_engine.lo concrete_formula_tokens.lo config.lo \ debug.lo dirty_cell_tracker.lo document.lo exceptions.lo \ formula.lo formula_calc.lo formula_function_opcode.lo \ formula_functions.lo formula_interpreter.lo formula_lexer.lo \ formula_name_resolver.lo formula_parser.lo formula_result.lo \ formula_tokens.lo formula_value_stack.lo global.lo info.lo \ lexer_tokens.lo matrix.lo mem_str_buf.lo model_context.lo \ model_context_impl.lo model_iterator.lo model_types.lo \ module.lo named_expressions_iterator.lo queue_entry.lo \ table.lo types.lo utils.lo workbook.lo interface.lo \ $(am__objects_1) libixion_@IXION_API_VERSION@_la_OBJECTS = \ $(am_libixion_@IXION_API_VERSION@_la_OBJECTS) libixion_@IXION_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(AM_CXXFLAGS) $(CXXFLAGS) \ $(libixion_@IXION_API_VERSION@_la_LDFLAGS) $(LDFLAGS) -o $@ am_compute_engine_test_OBJECTS = compute_engine_test.$(OBJEXT) compute_engine_test_OBJECTS = $(am_compute_engine_test_OBJECTS) compute_engine_test_DEPENDENCIES = libixion-@IXION_API_VERSION@.la am_dirty_cell_tracker_test_OBJECTS = \ dirty_cell_tracker_test.$(OBJEXT) dirty_cell_tracker_test_OBJECTS = \ $(am_dirty_cell_tracker_test_OBJECTS) dirty_cell_tracker_test_DEPENDENCIES = \ libixion-@IXION_API_VERSION@.la am_document_test_OBJECTS = document_test.$(OBJEXT) document_test_OBJECTS = $(am_document_test_OBJECTS) document_test_DEPENDENCIES = libixion-@IXION_API_VERSION@.la am_ixion_test_OBJECTS = ixion_test.$(OBJEXT) ixion_test_OBJECTS = $(am_ixion_test_OBJECTS) ixion_test_DEPENDENCIES = libixion-@IXION_API_VERSION@.la \ $(am__DEPENDENCIES_1) am_ixion_test_track_deps_OBJECTS = ixion_test_track_deps.$(OBJEXT) ixion_test_track_deps_OBJECTS = $(am_ixion_test_track_deps_OBJECTS) ixion_test_track_deps_DEPENDENCIES = libixion-@IXION_API_VERSION@.la \ $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/address.Plo \ ./$(DEPDIR)/address_iterator.Plo ./$(DEPDIR)/calc_status.Plo \ ./$(DEPDIR)/cell.Plo ./$(DEPDIR)/cell_access.Plo \ ./$(DEPDIR)/cell_queue_manager.Plo \ ./$(DEPDIR)/compute_engine.Plo \ ./$(DEPDIR)/compute_engine_test.Po \ ./$(DEPDIR)/concrete_formula_tokens.Plo ./$(DEPDIR)/config.Plo \ ./$(DEPDIR)/debug.Plo ./$(DEPDIR)/dirty_cell_tracker.Plo \ ./$(DEPDIR)/dirty_cell_tracker_test.Po \ ./$(DEPDIR)/document.Plo ./$(DEPDIR)/document_test.Po \ ./$(DEPDIR)/exceptions.Plo ./$(DEPDIR)/formula.Plo \ ./$(DEPDIR)/formula_calc.Plo \ ./$(DEPDIR)/formula_function_opcode.Plo \ ./$(DEPDIR)/formula_functions.Plo \ ./$(DEPDIR)/formula_interpreter.Plo \ ./$(DEPDIR)/formula_lexer.Plo \ ./$(DEPDIR)/formula_name_resolver.Plo \ ./$(DEPDIR)/formula_parser.Plo ./$(DEPDIR)/formula_result.Plo \ ./$(DEPDIR)/formula_tokens.Plo \ ./$(DEPDIR)/formula_value_stack.Plo ./$(DEPDIR)/global.Plo \ ./$(DEPDIR)/info.Plo ./$(DEPDIR)/interface.Plo \ ./$(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.Plo \ ./$(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.Plo \ ./$(DEPDIR)/ixion_test.Po ./$(DEPDIR)/ixion_test_track_deps.Po \ ./$(DEPDIR)/lexer_tokens.Plo ./$(DEPDIR)/matrix.Plo \ ./$(DEPDIR)/mem_str_buf.Plo ./$(DEPDIR)/model_context.Plo \ ./$(DEPDIR)/model_context_impl.Plo \ ./$(DEPDIR)/model_iterator.Plo ./$(DEPDIR)/model_types.Plo \ ./$(DEPDIR)/module.Plo \ ./$(DEPDIR)/named_expressions_iterator.Plo \ ./$(DEPDIR)/queue_entry.Plo ./$(DEPDIR)/table.Plo \ ./$(DEPDIR)/types.Plo ./$(DEPDIR)/utils.Plo \ ./$(DEPDIR)/workbook.Plo am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(ixion_@IXION_API_VERSION@_vulkan_la_SOURCES) \ $(libixion_@IXION_API_VERSION@_la_SOURCES) \ $(compute_engine_test_SOURCES) \ $(dirty_cell_tracker_test_SOURCES) $(document_test_SOURCES) \ $(ixion_test_SOURCES) $(ixion_test_track_deps_SOURCES) DIST_SOURCES = \ $(am__ixion_@IXION_API_VERSION@_vulkan_la_SOURCES_DIST) \ $(am__libixion_@IXION_API_VERSION@_la_SOURCES_DIST) \ $(compute_engine_test_SOURCES) \ $(dirty_cell_tracker_test_SOURCES) $(document_test_SOURCES) \ $(ixion_test_SOURCES) $(ixion_test_track_deps_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/constants.inl.in \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ BOOST_LDPATH = @BOOST_LDPATH@ BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ BOOST_ROOT = @BOOST_ROOT@ BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX17 = @HAVE_CXX17@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IXION_API_VERSION = @IXION_API_VERSION@ IXION_MAJOR_API_VERSION = @IXION_MAJOR_API_VERSION@ IXION_MAJOR_VERSION = @IXION_MAJOR_VERSION@ IXION_MICRO_VERSION = @IXION_MICRO_VERSION@ IXION_MINOR_API_VERSION = @IXION_MINOR_API_VERSION@ IXION_MINOR_VERSION = @IXION_MINOR_VERSION@ IXION_VERSION = @IXION_VERSION@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MDDS_CFLAGS = @MDDS_CFLAGS@ MDDS_LIBS = @MDDS_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POW_LIB = @POW_LIB@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ VULKAN_CFLAGS = @VULKAN_CFLAGS@ VULKAN_LIBS = @VULKAN_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src/include \ -DIXION_BUILD $(MDDS_CFLAGS) $(BOOST_CPPFLAGS) $(am__append_1) lib_LTLIBRARIES = libixion-@IXION_API_VERSION@.la libixion_@IXION_API_VERSION@_la_SOURCES = address.cpp \ address_iterator.cpp calc_status.hpp calc_status.cpp cell.cpp \ cell_access.cpp column_store_type.hpp compute_engine.cpp \ concrete_formula_tokens.hpp concrete_formula_tokens.cpp \ config.cpp debug.hpp debug.cpp dirty_cell_tracker.cpp \ document.cpp exceptions.cpp formula.cpp formula_calc.cpp \ formula_function_opcode.cpp formula_functions.hpp \ formula_functions.cpp formula_interpreter.hpp \ formula_interpreter.cpp formula_lexer.hpp formula_lexer.cpp \ formula_name_resolver.cpp formula_parser.hpp \ formula_parser.cpp formula_result.cpp formula_tokens.cpp \ formula_value_stack.hpp formula_value_stack.cpp global.cpp \ info.cpp lexer_tokens.hpp lexer_tokens.cpp matrix.cpp \ mem_str_buf.cpp model_context.cpp model_context_impl.hpp \ model_context_impl.cpp model_iterator.cpp model_types.hpp \ model_types.cpp module.cpp named_expressions_iterator.cpp \ queue_entry.hpp queue_entry.cpp table.cpp types.cpp utils.hpp \ utils.cpp workbook.hpp workbook.cpp interface.cpp \ $(am__append_2) # VULKAN module @BUILD_VULKAN_TRUE@pkglib_LTLIBRARIES = ixion-@IXION_API_VERSION@-vulkan.la @BUILD_VULKAN_TRUE@ixion_@IXION_API_VERSION@_vulkan_la_SOURCES = \ @BUILD_VULKAN_TRUE@ compute_engine_vulkan.hpp \ @BUILD_VULKAN_TRUE@ compute_engine_vulkan.cpp \ @BUILD_VULKAN_TRUE@ vulkan_obj.hpp \ @BUILD_VULKAN_TRUE@ vulkan_obj.cpp @BUILD_VULKAN_TRUE@ixion_@IXION_API_VERSION@_vulkan_la_LDFLAGS = \ @BUILD_VULKAN_TRUE@ -module -avoid-version -export-symbols-regex \ @BUILD_VULKAN_TRUE@ register_module @BUILD_VULKAN_TRUE@ixion_@IXION_API_VERSION@_vulkan_la_LIBADD = \ @BUILD_VULKAN_TRUE@ libixion-@IXION_API_VERSION@.la \ @BUILD_VULKAN_TRUE@ $(VULKAN_LIBS) @BUILD_VULKAN_TRUE@ixion_@IXION_API_VERSION@_vulkan_la_CPPFLAGS = \ @BUILD_VULKAN_TRUE@ $(AM_CPPFLAGS) \ @BUILD_VULKAN_TRUE@ $(VULKAN_CPPFLAGS) libixion_@IXION_API_VERSION@_la_LDFLAGS = \ -no-undefined \ -Wl,-rpath,'$$ORIGIN' -Wl,-rpath,'$$ORIGIN/$(PACKAGE)' \ $(BOOST_FILESYSTEM_LDFLAGS) libixion_@IXION_API_VERSION@_la_LIBADD = \ $(BOOST_FILESYSTEM_LIBS) EXTRA_DIST = makefile.mk document_test_SOURCES = document_test.cpp document_test_LDADD = \ libixion-@IXION_API_VERSION@.la ixion_test_SOURCES = ixion_test.cpp ixion_test_LDADD = \ libixion-@IXION_API_VERSION@.la \ $(BOOST_PROGRAM_OPTIONS_LIBS) ixion_test_track_deps_SOURCES = ixion_test_track_deps.cpp ixion_test_track_deps_LDADD = \ libixion-@IXION_API_VERSION@.la \ $(BOOST_PROGRAM_OPTIONS_LIBS) compute_engine_test_SOURCES = compute_engine_test.cpp compute_engine_test_LDADD = \ libixion-@IXION_API_VERSION@.la dirty_cell_tracker_test_SOURCES = dirty_cell_tracker_test.cpp dirty_cell_tracker_test_LDADD = \ libixion-@IXION_API_VERSION@.la AM_TESTS_ENVIRONMENT = all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/libixion/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/libixion/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): constants.inl: $(top_builddir)/config.status $(srcdir)/constants.inl.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } ixion-@IXION_API_VERSION@-vulkan.la: $(ixion_@IXION_API_VERSION@_vulkan_la_OBJECTS) $(ixion_@IXION_API_VERSION@_vulkan_la_DEPENDENCIES) $(EXTRA_ixion_@IXION_API_VERSION@_vulkan_la_DEPENDENCIES) $(AM_V_CXXLD)$(ixion_@IXION_API_VERSION@_vulkan_la_LINK) $(am_ixion_@IXION_API_VERSION@_vulkan_la_rpath) $(ixion_@IXION_API_VERSION@_vulkan_la_OBJECTS) $(ixion_@IXION_API_VERSION@_vulkan_la_LIBADD) $(LIBS) libixion-@IXION_API_VERSION@.la: $(libixion_@IXION_API_VERSION@_la_OBJECTS) $(libixion_@IXION_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libixion_@IXION_API_VERSION@_la_DEPENDENCIES) $(AM_V_CXXLD)$(libixion_@IXION_API_VERSION@_la_LINK) -rpath $(libdir) $(libixion_@IXION_API_VERSION@_la_OBJECTS) $(libixion_@IXION_API_VERSION@_la_LIBADD) $(LIBS) compute-engine-test$(EXEEXT): $(compute_engine_test_OBJECTS) $(compute_engine_test_DEPENDENCIES) $(EXTRA_compute_engine_test_DEPENDENCIES) @rm -f compute-engine-test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(compute_engine_test_OBJECTS) $(compute_engine_test_LDADD) $(LIBS) dirty-cell-tracker-test$(EXEEXT): $(dirty_cell_tracker_test_OBJECTS) $(dirty_cell_tracker_test_DEPENDENCIES) $(EXTRA_dirty_cell_tracker_test_DEPENDENCIES) @rm -f dirty-cell-tracker-test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(dirty_cell_tracker_test_OBJECTS) $(dirty_cell_tracker_test_LDADD) $(LIBS) document-test$(EXEEXT): $(document_test_OBJECTS) $(document_test_DEPENDENCIES) $(EXTRA_document_test_DEPENDENCIES) @rm -f document-test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(document_test_OBJECTS) $(document_test_LDADD) $(LIBS) ixion-test$(EXEEXT): $(ixion_test_OBJECTS) $(ixion_test_DEPENDENCIES) $(EXTRA_ixion_test_DEPENDENCIES) @rm -f ixion-test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(ixion_test_OBJECTS) $(ixion_test_LDADD) $(LIBS) ixion-test-track-deps$(EXEEXT): $(ixion_test_track_deps_OBJECTS) $(ixion_test_track_deps_DEPENDENCIES) $(EXTRA_ixion_test_track_deps_DEPENDENCIES) @rm -f ixion-test-track-deps$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(ixion_test_track_deps_OBJECTS) $(ixion_test_track_deps_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/address.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/address_iterator.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/calc_status.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cell.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cell_access.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cell_queue_manager.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compute_engine.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compute_engine_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/concrete_formula_tokens.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirty_cell_tracker.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirty_cell_tracker_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/document.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/document_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exceptions.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formula.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formula_calc.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formula_function_opcode.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formula_functions.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formula_interpreter.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formula_lexer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formula_name_resolver.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formula_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formula_result.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formula_tokens.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formula_value_stack.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/global.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interface.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_test_track_deps.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lexer_tokens.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matrix.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem_str_buf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_context.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_context_impl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_iterator.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_types.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/module.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/named_expressions_iterator.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/queue_entry.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/table.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/types.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/workbook.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.lo: compute_engine_vulkan.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_@IXION_API_VERSION@_vulkan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.lo -MD -MP -MF $(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.Tpo -c -o ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.lo `test -f 'compute_engine_vulkan.cpp' || echo '$(srcdir)/'`compute_engine_vulkan.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.Tpo $(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='compute_engine_vulkan.cpp' object='ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_@IXION_API_VERSION@_vulkan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.lo `test -f 'compute_engine_vulkan.cpp' || echo '$(srcdir)/'`compute_engine_vulkan.cpp ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.lo: vulkan_obj.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_@IXION_API_VERSION@_vulkan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.lo -MD -MP -MF $(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.Tpo -c -o ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.lo `test -f 'vulkan_obj.cpp' || echo '$(srcdir)/'`vulkan_obj.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.Tpo $(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='vulkan_obj.cpp' object='ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_@IXION_API_VERSION@_vulkan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.lo `test -f 'vulkan_obj.cpp' || echo '$(srcdir)/'`vulkan_obj.cpp mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: $(check_PROGRAMS) @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? document-test.log: document-test$(EXEEXT) @p='document-test$(EXEEXT)'; \ b='document-test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ixion-test.log: ixion-test$(EXEEXT) @p='ixion-test$(EXEEXT)'; \ b='ixion-test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ixion-test-track-deps.log: ixion-test-track-deps$(EXEEXT) @p='ixion-test-track-deps$(EXEEXT)'; \ b='ixion-test-track-deps'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) compute-engine-test.log: compute-engine-test$(EXEEXT) @p='compute-engine-test$(EXEEXT)'; \ b='compute-engine-test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) dirty-cell-tracker-test.log: dirty-cell-tracker-test$(EXEEXT) @p='dirty-cell-tracker-test$(EXEEXT)'; \ b='dirty-cell-tracker-test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkglibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-pkglibLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/address.Plo -rm -f ./$(DEPDIR)/address_iterator.Plo -rm -f ./$(DEPDIR)/calc_status.Plo -rm -f ./$(DEPDIR)/cell.Plo -rm -f ./$(DEPDIR)/cell_access.Plo -rm -f ./$(DEPDIR)/cell_queue_manager.Plo -rm -f ./$(DEPDIR)/compute_engine.Plo -rm -f ./$(DEPDIR)/compute_engine_test.Po -rm -f ./$(DEPDIR)/concrete_formula_tokens.Plo -rm -f ./$(DEPDIR)/config.Plo -rm -f ./$(DEPDIR)/debug.Plo -rm -f ./$(DEPDIR)/dirty_cell_tracker.Plo -rm -f ./$(DEPDIR)/dirty_cell_tracker_test.Po -rm -f ./$(DEPDIR)/document.Plo -rm -f ./$(DEPDIR)/document_test.Po -rm -f ./$(DEPDIR)/exceptions.Plo -rm -f ./$(DEPDIR)/formula.Plo -rm -f ./$(DEPDIR)/formula_calc.Plo -rm -f ./$(DEPDIR)/formula_function_opcode.Plo -rm -f ./$(DEPDIR)/formula_functions.Plo -rm -f ./$(DEPDIR)/formula_interpreter.Plo -rm -f ./$(DEPDIR)/formula_lexer.Plo -rm -f ./$(DEPDIR)/formula_name_resolver.Plo -rm -f ./$(DEPDIR)/formula_parser.Plo -rm -f ./$(DEPDIR)/formula_result.Plo -rm -f ./$(DEPDIR)/formula_tokens.Plo -rm -f ./$(DEPDIR)/formula_value_stack.Plo -rm -f ./$(DEPDIR)/global.Plo -rm -f ./$(DEPDIR)/info.Plo -rm -f ./$(DEPDIR)/interface.Plo -rm -f ./$(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.Plo -rm -f ./$(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.Plo -rm -f ./$(DEPDIR)/ixion_test.Po -rm -f ./$(DEPDIR)/ixion_test_track_deps.Po -rm -f ./$(DEPDIR)/lexer_tokens.Plo -rm -f ./$(DEPDIR)/matrix.Plo -rm -f ./$(DEPDIR)/mem_str_buf.Plo -rm -f ./$(DEPDIR)/model_context.Plo -rm -f ./$(DEPDIR)/model_context_impl.Plo -rm -f ./$(DEPDIR)/model_iterator.Plo -rm -f ./$(DEPDIR)/model_types.Plo -rm -f ./$(DEPDIR)/module.Plo -rm -f ./$(DEPDIR)/named_expressions_iterator.Plo -rm -f ./$(DEPDIR)/queue_entry.Plo -rm -f ./$(DEPDIR)/table.Plo -rm -f ./$(DEPDIR)/types.Plo -rm -f ./$(DEPDIR)/utils.Plo -rm -f ./$(DEPDIR)/workbook.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/address.Plo -rm -f ./$(DEPDIR)/address_iterator.Plo -rm -f ./$(DEPDIR)/calc_status.Plo -rm -f ./$(DEPDIR)/cell.Plo -rm -f ./$(DEPDIR)/cell_access.Plo -rm -f ./$(DEPDIR)/cell_queue_manager.Plo -rm -f ./$(DEPDIR)/compute_engine.Plo -rm -f ./$(DEPDIR)/compute_engine_test.Po -rm -f ./$(DEPDIR)/concrete_formula_tokens.Plo -rm -f ./$(DEPDIR)/config.Plo -rm -f ./$(DEPDIR)/debug.Plo -rm -f ./$(DEPDIR)/dirty_cell_tracker.Plo -rm -f ./$(DEPDIR)/dirty_cell_tracker_test.Po -rm -f ./$(DEPDIR)/document.Plo -rm -f ./$(DEPDIR)/document_test.Po -rm -f ./$(DEPDIR)/exceptions.Plo -rm -f ./$(DEPDIR)/formula.Plo -rm -f ./$(DEPDIR)/formula_calc.Plo -rm -f ./$(DEPDIR)/formula_function_opcode.Plo -rm -f ./$(DEPDIR)/formula_functions.Plo -rm -f ./$(DEPDIR)/formula_interpreter.Plo -rm -f ./$(DEPDIR)/formula_lexer.Plo -rm -f ./$(DEPDIR)/formula_name_resolver.Plo -rm -f ./$(DEPDIR)/formula_parser.Plo -rm -f ./$(DEPDIR)/formula_result.Plo -rm -f ./$(DEPDIR)/formula_tokens.Plo -rm -f ./$(DEPDIR)/formula_value_stack.Plo -rm -f ./$(DEPDIR)/global.Plo -rm -f ./$(DEPDIR)/info.Plo -rm -f ./$(DEPDIR)/interface.Plo -rm -f ./$(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-compute_engine_vulkan.Plo -rm -f ./$(DEPDIR)/ixion_@IXION_API_VERSION@_vulkan_la-vulkan_obj.Plo -rm -f ./$(DEPDIR)/ixion_test.Po -rm -f ./$(DEPDIR)/ixion_test_track_deps.Po -rm -f ./$(DEPDIR)/lexer_tokens.Plo -rm -f ./$(DEPDIR)/matrix.Plo -rm -f ./$(DEPDIR)/mem_str_buf.Plo -rm -f ./$(DEPDIR)/model_context.Plo -rm -f ./$(DEPDIR)/model_context_impl.Plo -rm -f ./$(DEPDIR)/model_iterator.Plo -rm -f ./$(DEPDIR)/model_types.Plo -rm -f ./$(DEPDIR)/module.Plo -rm -f ./$(DEPDIR)/named_expressions_iterator.Plo -rm -f ./$(DEPDIR)/queue_entry.Plo -rm -f ./$(DEPDIR)/table.Plo -rm -f ./$(DEPDIR)/types.Plo -rm -f ./$(DEPDIR)/utils.Plo -rm -f ./$(DEPDIR)/workbook.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-pkglibLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ check-am clean clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am \ install-pkglibLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-libLTLIBRARIES \ uninstall-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libixion-0.17.0/src/libixion/formula_tokens.cpp0000664000175000017500000001406414122770261016506 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include namespace ixion { std::string_view get_opcode_name(fopcode_t oc) { // Make sure the names are ordered identically to the ordering of the enum members. static const std::string_view names[] = { "unknown", // fop_unknown "single ref", // fop_single_ref "range ref", // fop_range_ref "table ref", // fop_table_ref "named expression", // fop_named_expression "string", // fop_string "value", // fop_value "function", // fop_function "plus", // fop_plus "minus", // fop_minus "divide", // fop_divide "multiply", // fop_multiply "exponent", // fop_exponent "concat", // fop_concat "equal", // fop_equal "not equal", // fop_not_equal "less", // fop_less "greater", // fop_greater "less equal", // fop_less_equal "greater equal", // fop_greater_equal "open", // fop_open "close", // fop_close "sep", // fop_sep "error", // fop_error }; if (std::size_t(oc) >= IXION_N_ELEMENTS(names)) return "???"; return names[oc]; } std::string_view get_formula_opcode_string(fopcode_t oc) { static const char* empty = ""; // Make sure the names are ordered identically to the ordering of the enum members. static const std::string_view names[] = { empty, // fop_unknown empty, // fop_single_ref empty, // fop_range_ref empty, // fop_table_ref empty, // fop_named_expression empty, // fop_string empty, // fop_value empty, // fop_function "+", // fop_plus "-", // fop_minus "/", // fop_divide "*", // fop_multiply "^", // fop_exponent "&", // fop_concat "=", // fop_equal "<>", // fop_not_equal "<", // fop_less ">", // fop_greater "<=", // fop_less_equal ">=", // fop_greater_equal "(", // fop_open ")", // fop_close empty, // fop_sep empty, // fop_error }; if (std::size_t(oc) >= IXION_N_ELEMENTS(names)) return empty; return names[oc]; } // ============================================================================ formula_token::formula_token(fopcode_t op) : m_opcode(op) { } formula_token::formula_token(const formula_token& r) : m_opcode(r.m_opcode) { } formula_token::~formula_token() { } fopcode_t formula_token::get_opcode() const { return m_opcode; } bool formula_token::operator== (const formula_token& r) const { if (m_opcode != r.m_opcode) return false; switch (m_opcode) { case fop_close: case fop_divide: case fop_minus: case fop_multiply: case fop_exponent: case fop_concat: case fop_open: case fop_plus: case fop_sep: return true; case fop_single_ref: return get_single_ref() == r.get_single_ref(); case fop_range_ref: return get_range_ref() == r.get_range_ref(); case fop_named_expression: return get_name() == r.get_name(); case fop_string: return get_uint32() == r.get_uint32(); case fop_value: return get_value() == r.get_value(); case fop_function: return get_uint32() == r.get_uint32(); default: ; } return false; } bool formula_token::operator!= (const formula_token& r) const { return !operator== (r); } address_t formula_token::get_single_ref() const { return address_t(); } range_t formula_token::get_range_ref() const { return range_t(); } table_t formula_token::get_table_ref() const { return table_t(); } double formula_token::get_value() const { return 0.0; } uint32_t formula_token::get_uint32() const { return 0; } std::string formula_token::get_name() const { return std::string(); } void formula_token::write_string(std::ostream& /*os*/) const { } struct formula_tokens_store::impl { formula_tokens_t m_tokens; size_t m_refcount; impl() : m_refcount(0) {} }; formula_tokens_store::formula_tokens_store() : mp_impl(std::make_unique()) { } formula_tokens_store::~formula_tokens_store() { } formula_tokens_store_ptr_t formula_tokens_store::create() { return formula_tokens_store_ptr_t(new formula_tokens_store); } void formula_tokens_store::add_ref() { ++mp_impl->m_refcount; } void formula_tokens_store::release_ref() { if (--mp_impl->m_refcount == 0) delete this; } size_t formula_tokens_store::get_reference_count() const { return mp_impl->m_refcount; } formula_tokens_t& formula_tokens_store::get() { return mp_impl->m_tokens; } const formula_tokens_t& formula_tokens_store::get() const { return mp_impl->m_tokens; } named_expression_t::named_expression_t() {} named_expression_t::named_expression_t(const abs_address_t& _origin, formula_tokens_t _tokens) : origin(_origin), tokens(std::move(_tokens)) {} named_expression_t::named_expression_t(named_expression_t&& other) : origin(other.origin), tokens(std::move(other.tokens)) {} named_expression_t::~named_expression_t() {} bool operator== (const formula_tokens_t& left, const formula_tokens_t& right) { size_t n = left.size(); if (n != right.size()) return false; formula_tokens_t::const_iterator itr = left.begin(), itr_end = left.end(), itr2 = right.begin(); for (; itr != itr_end; ++itr, ++itr2) { if (*itr != *itr2) return false; } return true; } std::ostream& operator<< (std::ostream& os, const formula_token& ft) { ft.write_string(os); return os; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/compute_engine_vulkan.cpp0000664000175000017500000001624714122770261020044 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "compute_engine_vulkan.hpp" #include "ixion/module.hpp" #include "ixion/env.hpp" #include "ixion/exceptions.hpp" #include "debug.hpp" #include #include #include namespace ixion { namespace draft { namespace { std::size_t get_byte_size(const array& io) { switch (io.type) { case array_type::uint32: return sizeof(uint32_t) * io.size; case array_type::float32: return sizeof(float) * io.size; case array_type::float64: return sizeof(double) * io.size; case array_type::unknown: IXION_DEBUG("array type is unknown."); } return 0; } } /** * This function first writes the source data array to host buffer, then * creates a device local buffer, and create and execute a command to copy * the data in the host buffer to the device local buffer. */ void compute_engine_vulkan::copy_to_device_local_buffer( array& io, vk_buffer& host_buffer, vk_buffer& device_buffer) { vk_command_buffer cmd_copy = m_cmd_pool.create_command_buffer(); cmd_copy.begin(); cmd_copy.copy_buffer(host_buffer, device_buffer, sizeof(uint32_t)*io.size); cmd_copy.end(); vk_fence fence(m_device, 0); vk_queue q = m_device.get_queue(); q.submit(cmd_copy, fence); fence.wait(); } compute_engine_vulkan::compute_engine_vulkan() : compute_engine(), m_instance(), m_device(m_instance), m_cmd_pool(m_device) { } compute_engine_vulkan::~compute_engine_vulkan() { } std::string_view compute_engine_vulkan::get_name() const { return "vulkan"; } void compute_engine_vulkan::compute_fibonacci(array& io) { runtime_context cxt; cxt.input_buffer_size = io.size; std::size_t data_byte_size = get_byte_size(io); vk_buffer host_buffer( m_device, data_byte_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); host_buffer.write_to_memory(io.data, data_byte_size); vk_buffer device_buffer( m_device, data_byte_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); copy_to_device_local_buffer(io, host_buffer, device_buffer); // Create a descriptor pool, by specifying the number of descriptors for // each type that can be allocated in a single set, as well as the max // number of sets. Here, we are specifying that we will only allocate one // set, and each set will contain only one storage buffer. vk_descriptor_pool desc_pool(m_device, 1u, { { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u }, } ); // Create a descriptor set layout. This specifies what descriptor type is // bound to what binding location and how many units (in case the // descriptor is an array), and which stages can access it. Here, we are // binding one storage buffer to the binding location of 0, for the // compute stage. vk_descriptor_set_layout ds_layout(m_device, { // binding id, descriptor type, descriptor count, stage flags, sampler (optional) { 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_COMPUTE_BIT, nullptr }, } ); // Create a pipeline layout. A pipeline layout consists of one or more // descriptor set layouts as well as one or more push constants. It // describes the entire resources the pipeline will have access to. Here // we only have one descriptor set layout and no push constants. vk_pipeline_layout pl_layout(m_device, ds_layout); // Allocate a descriptor set from the descriptor set layout. This will // get bound to command buffer later as part of the recorded commands. vk_descriptor_set desc_set = desc_pool.allocate(ds_layout); // Update the descriptor set with the content of the device-local buffer. // You always have to create a descriptor set first, then update it // afterward. Here, we are binding the actual device buffer instance to // the binding location of 0, just like we specified above. desc_set.update(m_device, 0u, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, device_buffer); // Create pipeline cache. You need to create this so that you can // optinally save the cached pipeline state to disk for re-use, which we // don't do here. vk_pipeline_cache pl_cache(m_device); // Load shader module for fibonnaci. vk_shader_module fibonnaci_module(m_device, vk_shader_module::module_type::fibonacci); // Create a compute pipeline. vk_pipeline pipeline(cxt, m_device, pl_layout, pl_cache, fibonnaci_module); // allocate command buffer. vk_command_buffer cmd = m_cmd_pool.create_command_buffer(); // Record command buffer. cmd.begin(); // Ensure that the write to the device buffer gets finished before the // compute shader stage. cmd.buffer_memory_barrier( device_buffer, VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT ); // Bind the pipeline and descriptor set to the compute pipeline. cmd.bind_pipeline(pipeline, VK_PIPELINE_BIND_POINT_COMPUTE); cmd.bind_descriptor_set(VK_PIPELINE_BIND_POINT_COMPUTE, pl_layout, desc_set); // Trigger compute work for data size of (n, 1, 1). cmd.dispatch(cxt.input_buffer_size, 1, 1); // Ensure that the compute stages finishes before buffer gets copied. cmd.buffer_memory_barrier( device_buffer, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT ); // Copy the data from the device local buffer to the host buffer. cmd.copy_buffer(device_buffer, host_buffer, data_byte_size); // Ensure that the buffer copying gets done before data is read on the // host cpu side. cmd.buffer_memory_barrier( host_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT ); cmd.end(); // Submit the command and wait. vk_fence fence(m_device, VK_FENCE_CREATE_SIGNALED_BIT); fence.reset(); vk_queue q = m_device.get_queue(); q.submit(cmd, fence, VK_PIPELINE_STAGE_TRANSFER_BIT); fence.wait(); // Read the values from the host memory. host_buffer.read_from_memory(io.data, data_byte_size); } compute_engine* create() { return new compute_engine_vulkan(); } void destroy(const compute_engine* p) { delete static_cast(p); } }} extern "C" { IXION_MOD_EXPORT ixion::draft::module_def* register_module() { static ixion::draft::module_def md = { ixion::draft::create, ixion::draft::destroy }; return &md; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/address.cpp0000644000175000017500000003364613612422767015120 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/address.hpp" #include #include using namespace std; namespace ixion { static const row_t row_max = numeric_limits::max(); static const col_t column_max = numeric_limits::max(); const row_t row_unset = row_max - 9; const row_t row_upper_bound = row_max - 10; const col_t column_unset = column_max - 9; const col_t column_upper_bound = column_max / 26 - 26; abs_address_t::abs_address_t() : sheet(0), row(0), column(0) {} abs_address_t::abs_address_t(init_invalid) : sheet(-1), row(-1), column(-1) {} abs_address_t::abs_address_t(sheet_t _sheet, row_t _row, col_t _column) : sheet(_sheet), row(_row), column(_column) {} abs_address_t::abs_address_t(const abs_address_t& r) : sheet(r.sheet), row(r.row), column(r.column) {} bool abs_address_t::valid() const { return sheet >= 0 && row >= 0 && column >= 0 && row <= row_unset && column <= column_unset; } string abs_address_t::get_name() const { ostringstream os; os << "(sheet=" << sheet << "; row=" << row << "; column=" << column << ")"; return os.str(); } size_t abs_address_t::hash::operator()(const abs_address_t& addr) const { return addr.sheet + addr.row + addr.column; } bool operator== (const abs_address_t& left, const abs_address_t& right) { return left.sheet == right.sheet && left.row == right.row && left.column == right.column; } bool operator!= (const abs_address_t& left, const abs_address_t& right) { return !operator==(left, right); } bool operator< (const abs_address_t& left, const abs_address_t& right) { if (left.sheet != right.sheet) return left.sheet < right.sheet; if (left.row != right.row) return left.row < right.row; return left.column < right.column; } address_t::address_t() : sheet(0), row(0), column(0), abs_sheet(true), abs_row(true), abs_column(true) {} address_t::address_t(sheet_t _sheet, row_t _row, col_t _column, bool _abs_sheet, bool _abs_row, bool _abs_column) : sheet(_sheet), row(_row), column(_column), abs_sheet(_abs_sheet), abs_row(_abs_row), abs_column(_abs_column) {} address_t::address_t(const address_t& r) : sheet(r.sheet), row(r.row), column(r.column), abs_sheet(r.abs_sheet), abs_row(r.abs_row), abs_column(r.abs_column) {} address_t::address_t(const abs_address_t& r) : sheet(r.sheet), row(r.row), column(r.column), abs_sheet(true), abs_row(true), abs_column(true) {} bool address_t::valid() const { if (abs_sheet) { if (sheet < 0) return false; } if (row > row_unset) return false; if (abs_row) { if (row < 0) return false; } else { if (row < -row_upper_bound) return false; } if (column > column_unset) return false; if (abs_column) { if (column < 0) return false; } else { if (column < -column_upper_bound) return false; } return true; } abs_address_t address_t::to_abs(const abs_address_t& origin) const { abs_address_t abs_addr; abs_addr.sheet = sheet; abs_addr.row = row; abs_addr.column = column; if (!is_valid_sheet(origin.sheet)) // If the origin sheet is invalid, then any sheet position relative to that should be invalid. abs_addr.sheet = origin.sheet; else if (!abs_sheet) abs_addr.sheet += origin.sheet; if (!abs_row && row <= row_upper_bound) abs_addr.row += origin.row; if (!abs_column && column <= column_upper_bound) abs_addr.column += origin.column; return abs_addr; } string address_t::get_name() const { ostringstream os; os << "(row=" << row << " ["; if (abs_row) os << "abs"; else os << "rel"; os << "]; column=" << column << " ["; if (abs_column) os << "abs"; else os << "rel"; os << "])"; return os.str(); } void address_t::set_absolute(bool abs) { abs_sheet = abs; abs_row = abs; abs_column = abs; } size_t address_t::hash::operator()(const address_t& addr) const { return 0; } bool operator== (const address_t& left, const address_t& right) { return left.sheet == right.sheet && left.row == right.row && left.column == right.column && left.abs_sheet == right.abs_sheet && left.abs_row == right.abs_row && left.abs_column == right.abs_column; } bool operator!=(const address_t& left, const address_t& right) { return !operator==(left, right); } bool operator< (const address_t& left, const address_t& right) { // Not sure how to compare absolute and relative addresses, but let's make // absolute address always greater than relative one until we find a // better way. if (left.abs_sheet != right.abs_sheet) return left.abs_sheet < right.abs_sheet; if (left.abs_row != right.abs_row) return left.abs_row < right.abs_row; if (left.abs_column != right.abs_column) return left.abs_column < right.abs_column; if (left.sheet != right.sheet) return left.sheet < right.sheet; if (left.row != right.row) return left.row < right.row; return left.column < right.column; } abs_rc_address_t::abs_rc_address_t() : row(0), column(0) { } abs_rc_address_t::abs_rc_address_t(init_invalid) : row(-1), column(-1) {} abs_rc_address_t::abs_rc_address_t(row_t _row, col_t _column) : row(_row), column(_column) {} abs_rc_address_t::abs_rc_address_t(const abs_rc_address_t& r) : row(r.row), column(r.column) {} abs_rc_address_t::abs_rc_address_t(const abs_address_t& r) : row(r.row), column(r.column) {} bool abs_rc_address_t::valid() const { return row >= 0 && column >= 0 && row <= row_unset && column <= column_unset; } size_t abs_rc_address_t::hash::operator() (const abs_rc_address_t& addr) const { size_t hv = addr.column; hv <<= 16; hv += addr.row; return hv; } bool operator== (const abs_rc_address_t& left, const abs_rc_address_t& right) { return left.row == right.row && left.column == right.column; } bool operator!= (const abs_rc_address_t& left, const abs_rc_address_t& right) { return !operator==(left, right); } bool operator< (const abs_rc_address_t& left, const abs_rc_address_t& right) { if (left.row != right.row) return left.row < right.row; return left.column < right.column; } rc_address_t::rc_address_t() : row(0), column(0), abs_row(true), abs_column(true) {} rc_address_t::rc_address_t(row_t _row, col_t _column, bool _abs_row, bool _abs_column) : row(_row), column(_column), abs_row(_abs_row), abs_column(_abs_column) {} rc_address_t::rc_address_t(const rc_address_t& r) : row(r.row), column(r.column), abs_row(r.abs_row), abs_column(r.abs_column) {} size_t rc_address_t::hash::operator()(const rc_address_t& addr) const { size_t hv = addr.column; hv <<= 16; hv += addr.row; return hv; } abs_range_t::abs_range_t() {} abs_range_t::abs_range_t(init_invalid) : first(abs_address_t::invalid), last(abs_address_t::invalid) {} abs_range_t::abs_range_t(sheet_t _sheet, row_t _row, col_t _col) : first(_sheet, _row, _col), last(_sheet, _row, _col) {} abs_range_t::abs_range_t(sheet_t _sheet, row_t _row, col_t _col, row_t _row_span, col_t _col_span) : first(_sheet, _row, _col), last(_sheet, _row + _row_span - 1, _col + _col_span - 1) { if (_row_span < 1 || _col_span < 1) { std::ostringstream os; os << "abs_range_t: invalid span (row=" << _row_span << "; col=" << _col_span << ")"; throw std::range_error(os.str()); } } abs_range_t::abs_range_t(const abs_address_t& addr, row_t row_span, col_t col_span) : first(addr), last(addr) { if (row_span > 0) last.row += row_span - 1; if (col_span > 0) last.column += col_span - 1; } abs_range_t::abs_range_t(const abs_address_t& addr) : first(addr), last(addr) {} size_t abs_range_t::hash::operator() (const abs_range_t& range) const { abs_address_t::hash adr_hash; return adr_hash(range.first) + 65536*adr_hash(range.last); } bool abs_range_t::valid() const { return first.valid() && last.valid() && first.sheet <= last.sheet && first.column <= last.column && first.row <= last.row; } void abs_range_t::set_all_columns() { first.column = column_unset; last.column = column_unset; } void abs_range_t::set_all_rows() { first.row = row_unset; last.row = row_unset; } bool abs_range_t::all_columns() const { return first.column == column_unset && last.column == column_unset; } bool abs_range_t::all_rows() const { return first.row == row_unset && last.row == row_unset; } bool abs_range_t::contains(const abs_address_t& addr) const { return first.sheet <= addr.sheet && addr.sheet <= last.sheet && first.row <= addr.row && addr.row <= last.row && first.column <= addr.column && addr.column <= last.column; } void abs_range_t::reorder() { if (first.sheet > last.sheet) std::swap(first.sheet, last.sheet); if (first.row > last.row) std::swap(first.row, last.row); if (first.column > last.column) std::swap(first.column, last.column); } bool operator==(const abs_range_t& left, const abs_range_t& right) { return left.first == right.first && left.last == right.last; } bool operator!=(const abs_range_t& left, const abs_range_t& right) { return !operator==(left, right); } bool operator<(const abs_range_t& left, const abs_range_t& right) { if (left.first != right.first) return left.first < right.first; return left.last < right.last; } abs_rc_range_t::abs_rc_range_t() {} abs_rc_range_t::abs_rc_range_t(init_invalid) : first(abs_rc_address_t::invalid), last(abs_rc_address_t::invalid) {} abs_rc_range_t::abs_rc_range_t(const abs_rc_range_t& other) : first(other.first), last(other.last) {} abs_rc_range_t::abs_rc_range_t(const abs_range_t& other) : first(other.first), last(other.last) {} size_t abs_rc_range_t::hash::operator() (const abs_rc_range_t& range) const { abs_rc_address_t::hash adr_hash; return adr_hash(range.first) + 65536*adr_hash(range.last); } bool abs_rc_range_t::valid() const { if (!first.valid() || !last.valid()) return false; if (first.row != row_unset && last.row != row_unset) { if (first.row > last.row) return false; } if (first.column != column_unset && last.column != column_unset) { if (first.column > last.column) return false; } return true; } void abs_rc_range_t::set_all_columns() { first.column = column_unset; last.column = column_unset; } void abs_rc_range_t::set_all_rows() { first.row = row_unset; last.row = row_unset; } bool abs_rc_range_t::all_columns() const { return first.column == column_unset && last.column == column_unset; } bool abs_rc_range_t::all_rows() const { return first.row == row_unset && last.row == row_unset; } bool abs_rc_range_t::contains(const abs_rc_address_t& addr) const { return first.row <= addr.row && addr.row <= last.row && first.column <= addr.column && addr.column <= last.column; } bool operator==(const abs_rc_range_t& left, const abs_rc_range_t& right) { return left.first == right.first && left.last == right.last; } bool operator!=(const abs_rc_range_t& left, const abs_rc_range_t& right) { return !operator==(left, right); } bool operator<(const abs_rc_range_t& left, const abs_rc_range_t& right) { if (left.first != right.first) return left.first < right.first; return left.last < right.last; } range_t::range_t() {} range_t::range_t(const address_t& _first, const address_t& _last) : first(_first), last(_last) {} range_t::range_t(const range_t& r) : first(r.first), last(r.last) {} range_t::range_t(const abs_range_t& r) : first(r.first), last(r.last) {} bool range_t::valid() const { return first.valid() && last.valid(); } void range_t::set_all_columns() { first.column = column_unset; last.column = column_unset; } void range_t::set_all_rows() { first.row = row_unset; last.row = row_unset; } bool range_t::all_columns() const { return first.column == column_unset && last.column == column_unset; } bool range_t::all_rows() const { return first.row == row_unset && last.row == row_unset; } abs_range_t range_t::to_abs(const abs_address_t& origin) const { abs_range_t ret; ret.first = first.to_abs(origin); ret.last = last.to_abs(origin); return ret; } void range_t::set_absolute(bool abs) { first.set_absolute(abs); last.set_absolute(abs); } size_t range_t::hash::operator() (const range_t& range) const { address_t::hash adr_hash; return adr_hash(range.first) + 65536*adr_hash(range.last); } bool operator==(const range_t& left, const range_t& right) { return left.first == right.first && left.last == right.last; } bool operator!=(const range_t& left, const range_t& right) { return !operator==(left, right); } std::ostream& operator<<(std::ostream& os, const abs_address_t& addr) { os << "(sheet:" << addr.sheet << "; row:" << addr.row << "; column:" << addr.column << ")"; return os; } std::ostream& operator<<(std::ostream& os, const address_t& addr) { os << "(sheet:" << addr.sheet << " " << (addr.abs_sheet?"abs":"rel") << "; row:" << addr.row << " " << (addr.abs_row?"abs":"rel") <<"; column:" << addr.column << " " << (addr.abs_column?"abs":"rel") << ")"; return os; } std::ostream& operator<<(std::ostream& os, const abs_range_t& range) { os << range.first << "-" << range.last; return os; } std::ostream& operator<<(std::ostream& os, const range_t& range) { os << range.first << "-" << range.last; return os; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/ixion_test.cpp0000664000175000017500000023366114122770261015651 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/formula_name_resolver.hpp" #include "ixion/address.hpp" #include "ixion/formula.hpp" #include "ixion/model_context.hpp" #include "ixion/model_iterator.hpp" #include "ixion/named_expressions_iterator.hpp" #include "ixion/global.hpp" #include "ixion/macros.hpp" #include "ixion/interface/table_handler.hpp" #include "ixion/config.hpp" #include "ixion/matrix.hpp" #include "ixion/cell.hpp" #include "ixion/cell_access.hpp" #include "ixion/formula_result.hpp" #include #include #include #include #include #include #include using namespace std; using namespace ixion; namespace { void test_size() { cout << "test size" << endl; cout << "* int: " << sizeof(int) << endl; cout << "* long: " << sizeof(long) << endl; cout << "* double: " << sizeof(double) << endl; cout << "* size_t: " << sizeof(size_t) << endl; cout << "* string_id_t: " << sizeof(string_id_t) << " (min:" << std::numeric_limits::min() << "; max:" << std::numeric_limits::max() << ")" << endl; cout << "* celltype_t: " << sizeof(celltype_t) << endl; cout << "* formula_cell: " << sizeof(formula_cell) << endl; cout << "* formula_tokens_t: " << sizeof(formula_tokens_t) << endl; } void test_string_to_double() { cout << "test string to double" << endl; struct { const char* s; double v; } tests[] = { { "12", 12.0 }, { "0", 0.0 }, { "1.3", 1.3 }, { "1234.00983", 1234.00983 }, { "-123.3", -123.3 } }; size_t n = sizeof(tests) / sizeof(tests[0]); for (size_t i = 0; i < n; ++i) { double v = to_double(tests[i].s); assert(v == tests[i].v); } } void test_string_pool() { cout << "test string pool" << endl; model_context cxt; string_id_t s_table1 = cxt.append_string("Table1"); string_id_t s_table2 = cxt.append_string("Table2"); string_id_t s_cat = cxt.append_string("Category"); string_id_t s_val = cxt.append_string("Value"); cxt.dump_strings(); // Make sure these work correctly before proceeding further with the test. assert(s_table1 == cxt.get_identifier_from_string("Table1")); assert(s_table2 == cxt.get_identifier_from_string("Table2")); assert(s_cat == cxt.get_identifier_from_string("Category")); assert(s_val == cxt.get_identifier_from_string("Value")); } void test_formula_tokens_store() { formula_tokens_store_ptr_t p = formula_tokens_store::create(); assert(p->get_reference_count() == 1); auto p2 = p; assert(p->get_reference_count() == 2); assert(p2->get_reference_count() == 2); auto p3(p); assert(p->get_reference_count() == 3); assert(p2->get_reference_count() == 3); assert(p3->get_reference_count() == 3); p3.reset(); assert(p->get_reference_count() == 2); assert(p2->get_reference_count() == 2); p2.reset(); assert(p->get_reference_count() == 1); p.reset(); } void test_matrix() { struct check { size_t row; size_t col; double val; }; std::vector checks = { { 0, 0, 1.0 }, { 0, 1, 2.0 }, { 1, 0, 3.0 }, { 1, 1, 4.0 }, }; numeric_matrix num_mtx(2, 2); for (const check& c : checks) num_mtx(c.row, c.col) = c.val; for (const check& c : checks) assert(num_mtx(c.row, c.col) == c.val); matrix mtx(num_mtx); for (const check& c : checks) { matrix::element e = mtx.get(c.row, c.col); assert(e.type == matrix::element_type::numeric); assert(std::get(e.value) == c.val); } } void test_matrix_non_numeric_values() { matrix mtx(2, 2); mtx.set(0, 0, 1.1); mtx.set(1, 0, formula_error_t::division_by_zero); mtx.set(0, 1, std::string("foo")); mtx.set(1, 1, true); assert(mtx.get_numeric(0, 0) == 1.1); matrix::element elem = mtx.get(1, 0); assert(elem.type == matrix::element_type::error); assert(std::get(elem.value) == formula_error_t::division_by_zero); elem = mtx.get(0, 1); assert(elem.type == matrix::element_type::string); assert(std::get(elem.value) == "foo"); elem = mtx.get(1, 1); assert(elem.type == matrix::element_type::boolean); assert(std::get(elem.value) == true); } struct ref_name_entry { const char* name; bool sheet_name; }; void test_name_resolver_calc_a1() { cout << "test name resolver calc a1" << endl; model_context cxt; cxt.append_sheet("One"); cxt.append_sheet("Two"); cxt.append_sheet("Three"); cxt.append_sheet("A B C"); // name with space auto resolver = formula_name_resolver::get(formula_name_resolver_t::calc_a1, &cxt); assert(resolver); { // Parse single cell addresses. ref_name_entry names[] = { { "A1", false }, { "$A1", false }, { "A$1", false }, { "$A$1", false }, { "Z1", false }, { "AA23", false }, { "AB23", false }, { "$AB23", false }, { "AB$23", false }, { "$AB$23", false }, { "BA1", false }, { "AAA2", false }, { "ABA1", false }, { "BAA1", false }, { "XFD1048576", false }, { "One.A1", true }, { "One.XFD1048576", true }, { "Two.B10", true }, { "Two.$B10", true }, { "Two.B$10", true }, { "Two.$B$10", true }, { "Three.CFD234", true }, { "$Three.CFD234", true }, { "'A B C'.Z12", true }, { "$'A B C'.Z12", true }, { 0, false } }; for (size_t i = 0; names[i].name; ++i) { const char* p = names[i].name; string name_a1(p); cout << "single cell address: " << name_a1 << endl; formula_name_t res = resolver->resolve(name_a1, abs_address_t()); if (res.type != formula_name_t::cell_reference) { cerr << "failed to resolve cell address: " << name_a1 << endl; assert(false); } address_t addr = std::get(res.value); string test_name = resolver->get_name(addr, abs_address_t(), names[i].sheet_name); if (name_a1 != test_name) { cerr << "failed to compile name from address: (name expected: " << name_a1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } } { // Parse range addresses. ref_name_entry names[] = { { "A1:B2", false }, { "$D10:G$24", false }, { "One.C$1:Z$400", true }, { "Two.$C1:$Z400", true }, { "Three.$C1:Z$400", true }, { "$Three.$C1:Z$400", true }, { "'A B C'.$C4:$Z256", true }, { "$'A B C'.$C4:$Z256", true }, { "One.C4:Three.Z100", true }, { "One.C4:$Three.Z100", true }, { "$One.C4:Three.Z100", true }, { "$One.C4:$Three.Z100", true }, { 0, false }, }; for (sheet_t sheet = 0; sheet <= 3; ++sheet) { for (size_t i = 0; names[i].name; ++i) { abs_address_t pos{sheet, 0, 0}; string name_a1(names[i].name); cout << "range address: " << name_a1 << endl; formula_name_t res = resolver->resolve(name_a1, pos); if (res.type != formula_name_t::range_reference) { cerr << "failed to resolve range address: " << name_a1 << endl; assert(false); } std::string test_name = resolver->get_name( std::get(res.value), pos, names[i].sheet_name); if (name_a1 != test_name) { cerr << "failed to compile name from range: (pos: " << pos << "; name expected: " << name_a1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } } } struct { const char* name; sheet_t sheet1; row_t row1; col_t col1; sheet_t sheet2; row_t row2; col_t col2; } range_tests[] = { { "A1:B2", 0, 0, 0, 0, 1, 1 }, { "D10:G24", 0, 9, 3, 0, 23, 6 }, { "One.C1:Z400", 0, 0, 2, 0, 399, 25 }, { "Two.C1:Z400", 1, 0, 2, 1, 399, 25 }, { "Three.C1:Z400", 2, 0, 2, 2, 399, 25 }, { 0, 0, 0, 0, 0, 0, 0 } }; for (size_t i = 0; range_tests[i].name; ++i) { string name_a1(range_tests[i].name); cout << "range address: " << name_a1 << endl; formula_name_t res = resolver->resolve(name_a1, abs_address_t()); auto range = std::get(res.value); assert(res.type == formula_name_t::range_reference); assert(range.first.sheet == range_tests[i].sheet1); assert(range.first.row == range_tests[i].row1); assert(range.first.column == range_tests[i].col1); assert(range.last.sheet == range_tests[i].sheet2); assert(range.last.row == range_tests[i].row2); assert(range.last.column == range_tests[i].col2); } { formula_name_t res = resolver->resolve("B1", abs_address_t(0,1,1)); auto addr = std::get(res.value); assert(res.type == formula_name_t::cell_reference); assert(addr.sheet == 0); assert(addr.row == -1); assert(addr.column == 0); } { formula_name_t res = resolver->resolve("B2:B4", abs_address_t(0,0,3)); auto range = std::get(res.value); assert(res.type == formula_name_t::range_reference); assert(range.first.sheet == 0); assert(range.first.row == 1); assert(range.first.column == -2); assert(range.last.sheet == 0); assert(range.last.row == 3); assert(range.last.column == -2); } { formula_name_t res = resolver->resolve("Three.B2", abs_address_t(2,0,0)); auto addr = std::get(res.value); assert(res.type == formula_name_t::cell_reference); assert(!addr.abs_sheet); assert(!addr.abs_row); assert(!addr.abs_column); assert(addr.sheet == 0); assert(addr.row == 1); assert(addr.column == 1); } { abs_address_t pos(2, 0, 0); std::string name("One.B2:Three.C4"); formula_name_t res = resolver->resolve(name, pos); auto range = std::get(res.value); assert(res.type == formula_name_t::range_reference); assert(!range.first.abs_sheet); assert(!range.first.abs_row); assert(!range.first.abs_column); assert(range.first.sheet == -2); assert(range.first.row == 1); assert(range.first.column == 1); assert(!range.last.abs_sheet); assert(!range.last.abs_row); assert(!range.last.abs_column); assert(range.last.sheet == 0); assert(range.last.row == 3); assert(range.last.column == 2); std::string s = resolver->get_name(range, pos, true); assert(s == name); } } void test_name_resolver_excel_a1() { cout << "test name resolver excel a1" << endl; model_context cxt; cxt.append_sheet("One"); cxt.append_sheet("Two"); cxt.append_sheet("Three"); cxt.append_sheet("A B C"); // name with space cxt.append_sheet("'quote'"); // quoted name auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); assert(resolver); { // Parse single cell addresses. ref_name_entry names[] = { { "A1", false }, { "$A1", false }, { "A$1", false }, { "$A$1", false }, { "Z1", false }, { "AA23", false }, { "AB23", false }, { "$AB23", false }, { "AB$23", false }, { "$AB$23", false }, { "BA1", false }, { "AAA2", false }, { "ABA1", false }, { "BAA1", false }, { "XFD1048576", false }, { "One!A1", true }, { "One!XFD1048576", true }, { "Two!B10", true }, { "Two!$B10", true }, { "Two!B$10", true }, { "Two!$B$10", true }, { "Three!CFD234", true }, { "'A B C'!Z12", true }, { "'''quote'''!Z12", true }, { 0, false } }; for (size_t i = 0; names[i].name; ++i) { const char* p = names[i].name; string name_a1(p); formula_name_t res = resolver->resolve(name_a1, abs_address_t()); if (res.type != formula_name_t::cell_reference) { cerr << "failed to resolve cell address: " << name_a1 << endl; assert(false); } address_t addr = std::get(res.value); string test_name = resolver->get_name(addr, abs_address_t(), names[i].sheet_name); if (name_a1 != test_name) { cerr << "failed to compile name from address: (name expected: " << name_a1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } } { // Parse range addresses. ref_name_entry names[] = { { "A1:B2", false }, { "$D10:G$24", false }, { "One!C$1:Z$400", true }, { "Two!$C1:$Z400", true }, { "Three!$C1:Z$400", true }, { "'A B C'!$C4:$Z256", true }, { 0, false }, }; for (size_t i = 0; names[i].name; ++i) { const char* p = names[i].name; string name_a1(p); cout << "range address: " << name_a1 << endl; formula_name_t res = resolver->resolve(name_a1, abs_address_t()); if (res.type != formula_name_t::range_reference) { cerr << "failed to resolve range address: " << name_a1 << endl; assert(false); } range_t range = std::get(res.value); std::string test_name = resolver->get_name(range, abs_address_t(), names[i].sheet_name); if (name_a1 != test_name) { cerr << "failed to compile name from range: (name expected: " << name_a1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } } // Parse range addresses. struct { const char* name; sheet_t sheet1; row_t row1; col_t col1; sheet_t sheet2; row_t row2; col_t col2; } range_tests[] = { { "A1:B2", 0, 0, 0, 0, 1, 1 }, { "D10:G24", 0, 9, 3, 0, 23, 6 }, { "One!C1:Z400", 0, 0, 2, 0, 399, 25 }, { "Two!C1:Z400", 1, 0, 2, 1, 399, 25 }, { "Three!C1:Z400", 2, 0, 2, 2, 399, 25 }, { 0, 0, 0, 0, 0, 0, 0 } }; for (size_t i = 0; range_tests[i].name; ++i) { string name_a1(range_tests[i].name); formula_name_t res = resolver->resolve(name_a1, abs_address_t()); auto range = std::get(res.value); assert(res.type == formula_name_t::range_reference); assert(range.first.sheet == range_tests[i].sheet1); assert(range.first.row == range_tests[i].row1); assert(range.first.column == range_tests[i].col1); assert(range.last.sheet == range_tests[i].sheet2); assert(range.last.row == range_tests[i].row2); assert(range.last.column == range_tests[i].col2); } { formula_name_t res = resolver->resolve("B1", abs_address_t(0,1,1)); auto addr = std::get(res.value); assert(res.type == formula_name_t::cell_reference); assert(addr.sheet == 0); assert(addr.row == -1); assert(addr.column == 0); } { formula_name_t res = resolver->resolve("B2:B4", abs_address_t(0,0,3)); auto range = std::get(res.value); assert(res.type == formula_name_t::range_reference); assert(range.first.sheet == 0); assert(range.first.row == 1); assert(range.first.column == -2); assert(range.last.sheet == 0); assert(range.last.row == 3); assert(range.last.column == -2); } // Parse name without row index. struct { const char* name; formula_name_t::name_type type; } name_tests[] = { { "H:H", formula_name_t::range_reference }, { "ABC", formula_name_t::named_expression }, { "H", formula_name_t::named_expression }, { "MAX", formula_name_t::function }, { 0, formula_name_t::invalid } }; for (size_t i = 0; name_tests[i].name; ++i) { string name_a1(name_tests[i].name); formula_name_t res = resolver->resolve(name_a1, abs_address_t()); assert(res.type == name_tests[i].type); } { // Parse address with non-existing sheet name. It should be flagged invalid. formula_name_t res = resolver->resolve("NotExists!A1", abs_address_t()); assert(res.type == formula_name_t::invalid); } } void test_name_resolver_named_expression() { cout << "Testing the name resolvers for parsing named expressions." << endl; model_context cxt; cxt.append_sheet("Sheet"); const std::vector resolver_types = { formula_name_resolver_t::excel_a1, formula_name_resolver_t::excel_r1c1, // TODO : add more resolver types. }; const std::vector names = { "MyRange", "MyRange2", }; for (formula_name_resolver_t rt : resolver_types) { cout << "formula resolver type: " << int(rt) << endl; // TODO : map the enum value to string name. auto resolver = formula_name_resolver::get(rt, &cxt); assert(resolver); for (const std::string& name : names) { cout << "parsing '" << name << "'..." << endl; formula_name_t res = resolver->resolve(name, abs_address_t(0,0,0)); assert(res.type == formula_name_t::name_type::named_expression); } } } void test_name_resolver_table_excel_a1() { cout << "Testing the Excel A1 name resolver for parsing table references." << endl; model_context cxt; cxt.append_sheet("Sheet"); string_id_t s_table1 = cxt.append_string("Table1"); string_id_t s_table2 = cxt.append_string("Table2"); string_id_t s_cat = cxt.append_string("Category"); string_id_t s_val = cxt.append_string("Value"); // Make sure these work correctly before proceeding further with the test. assert(s_table1 == cxt.get_identifier_from_string("Table1")); assert(s_table2 == cxt.get_identifier_from_string("Table2")); assert(s_cat == cxt.get_identifier_from_string("Category")); assert(s_val == cxt.get_identifier_from_string("Value")); auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); assert(resolver); struct { const char* exp; size_t len; sheet_t sheet; row_t row; col_t col; string_id_t table_name; string_id_t column_first; string_id_t column_last; table_areas_t areas; } tests[] = { { IXION_ASCII("[Value]"), 0, 9, 2, empty_string_id, s_val, empty_string_id, table_area_data }, { IXION_ASCII("Table1[Category]"), 0, 9, 2, s_table1, s_cat, empty_string_id, table_area_data }, { IXION_ASCII("Table1[Value]"), 0, 9, 2, s_table1, s_val, empty_string_id, table_area_data }, { IXION_ASCII("Table1[[#Headers],[Value]]"), 0, 9, 2, s_table1, s_val, empty_string_id, table_area_headers }, { IXION_ASCII("Table1[[#Headers],[#Data],[Value]]"), 0, 9, 2, s_table1, s_val, empty_string_id, table_area_headers | table_area_data }, { IXION_ASCII("Table1[[#All],[Category]]"), 0, 9, 2, s_table1, s_cat, empty_string_id, table_area_all }, { IXION_ASCII("Table1[[#Totals],[Category]]"), 0, 9, 2, s_table1, s_cat, empty_string_id, table_area_totals }, { IXION_ASCII("Table1[[#Data],[#Totals],[Value]]"), 0, 9, 2, s_table1, s_val, empty_string_id, table_area_data | table_area_totals }, { IXION_ASCII("Table1[#All]"), 0, 9, 2, s_table1, empty_string_id, empty_string_id, table_area_all }, { IXION_ASCII("Table1[#Headers]"), 0, 9, 2, s_table1, empty_string_id, empty_string_id, table_area_headers }, { IXION_ASCII("Table1[#Data]"), 0, 9, 2, s_table1, empty_string_id, empty_string_id, table_area_data }, { IXION_ASCII("Table1[#Totals]"), 0, 9, 2, s_table1, empty_string_id, empty_string_id, table_area_totals }, { IXION_ASCII("Table1[[#Headers],[#Data]]"), 0, 9, 2, s_table1, empty_string_id, empty_string_id, table_area_headers | table_area_data }, { IXION_ASCII("Table1[[#Totals],[Category]:[Value]]"), 0, 9, 2, s_table1, s_cat, s_val, table_area_totals }, { IXION_ASCII("Table1[[#Data],[#Totals],[Category]:[Value]]"), 0, 9, 2, s_table1, s_cat, s_val, table_area_data | table_area_totals }, }; for (size_t i = 0, n = IXION_N_ELEMENTS(tests); i < n; ++i) { cout << "* table reference: " << tests[i].exp << endl; abs_address_t pos(tests[i].sheet, tests[i].row, tests[i].col); formula_name_t res = resolver->resolve({tests[i].exp, tests[i].len}, pos); if (res.type != formula_name_t::table_reference) assert(!"table reference expected."); auto table = std::get(res.value); string_id_t table_name = cxt.get_identifier_from_string(table.name); string_id_t column_first = cxt.get_identifier_from_string(table.column_first); string_id_t column_last = cxt.get_identifier_from_string(table.column_last); assert(table_name == tests[i].table_name); assert(column_first == tests[i].column_first); assert(column_last == tests[i].column_last); assert(table.areas == tests[i].areas); // Make sure we get the same name back. table_t tb; tb.name = table_name; tb.column_first = column_first; tb.column_last = column_last; tb.areas = table.areas; string original(tests[i].exp, tests[i].len); string returned = resolver->get_name(tb); cout << " original: " << original << endl; cout << " returned: " << returned << endl; assert(original == returned); } } void test_name_resolver_excel_r1c1() { cout << "test name resolver excel r1c1" << endl; model_context cxt; cxt.append_sheet("One"); cxt.append_sheet("Two"); cxt.append_sheet("A B C"); // name with space cxt.append_sheet("80's Music"); auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_r1c1, &cxt); assert(resolver); // Parse single cell addresses for round-tripping. ref_name_entry single_ref_names[] = { { "R2", false }, { "R[3]", false }, { "R[-10]", false }, { "C2", false }, { "C[3]", false }, { "C[-10]", false }, { "R1C1", false }, { "R[1]C2", false }, { "R2C[-2]", false }, { "R1C", false }, { "R[-3]C", false }, { "RC2", false }, { "One!R10C", true }, { "Two!C[-2]", true }, { "'A B C'!R100", true }, { 0, false } }; for (size_t i = 0; single_ref_names[i].name; ++i) { const char* p = single_ref_names[i].name; string name_r1c1(p); cout << "Parsing " << name_r1c1 << endl; formula_name_t res = resolver->resolve(name_r1c1, abs_address_t()); if (res.type != formula_name_t::cell_reference) { cerr << "failed to resolve cell address: " << name_r1c1 << endl; assert(false); } address_t addr = std::get(res.value); string test_name = resolver->get_name(addr, abs_address_t(), single_ref_names[i].sheet_name); if (name_r1c1 != test_name) { cerr << "failed to compile name from address: (name expected: " << name_r1c1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } // These are supposed to be all invalid or named expression. const char* invalid_address[] = { "F", "RR", "RC", "R", "C", "R0C1", "R[-2]C-1", "R1C2:", "R:", "R2:", "R[-3]:", "C:", "C3:", "C[-4]:", 0 }; for (size_t i = 0; invalid_address[i]; ++i) { const char* p = invalid_address[i]; string name_r1c1(p); formula_name_t res = resolver->resolve(name_r1c1, abs_address_t()); if (res.type != formula_name_t::invalid && res.type != formula_name_t::named_expression) { cerr << "address " << name_r1c1 << " is expected to be invalid." << endl; assert(false); } } // These are supposed to be all valid. const char* valid_address[] = { "r1c2", "r[-2]", "c10", 0 }; for (size_t i = 0; valid_address[i]; ++i) { const char* p = valid_address[i]; string name_r1c1(p); formula_name_t res = resolver->resolve(name_r1c1, abs_address_t()); if (res.type != formula_name_t::cell_reference) { cerr << "address " << name_r1c1 << " is expected to be valid." << endl; assert(false); } } // Parse range addresses. struct { const char* name; sheet_t sheet1; row_t row1; col_t col1; sheet_t sheet2; row_t row2; col_t col2; bool abs_sheet1; bool abs_row1; bool abs_col1; bool abs_sheet2; bool abs_row2; bool abs_col2; } range_tests[] = { { "R1C1:R2C2", 0, 0, 0, 0, 1, 1, true, true, true, true, true, true }, { "R[-3]C[2]:R[1]C[4]", 0, -3, 2, 0, 1, 4, true, false, false, true, false, false }, { "R2:R4", 0, 1, column_unset, 0, 3, column_unset, true, true, false, true, true, false }, { "R[2]:R[4]", 0, 2, column_unset, 0, 4, column_unset, true, false, false, true, false, false }, { "C3:C6", 0, row_unset, 2, 0, row_unset, 5, true, false, true, true, false, true }, { "C[3]:C[6]", 0, row_unset, 3, 0, row_unset, 6, true, false, false, true, false, false }, { "Two!R2C2:R2C[100]", 1, 1, 1, 1, 1, 100, true, true, true, true, true, false }, { "'A B C'!R[2]:R[4]", 2, 2, column_unset, 2, 4, column_unset, true, false, false, true, false, false }, { 0, 0, 0, 0, 0, 0, 0, false, false, false, false, false, false } }; for (size_t i = 0; range_tests[i].name; ++i) { string name_r1c1(range_tests[i].name); cout << "Parsing " << name_r1c1 << endl; formula_name_t res = resolver->resolve(name_r1c1, abs_address_t()); auto range = std::get(res.value); assert(res.type == formula_name_t::range_reference); assert(range.first.sheet == range_tests[i].sheet1); assert(range.first.row == range_tests[i].row1); assert(range.first.column == range_tests[i].col1); assert(range.first.abs_sheet == range_tests[i].abs_sheet1); if (range.first.row != row_unset) // When row is unset, whether it's relative or absolute is not relevant. assert(range.first.abs_row == range_tests[i].abs_row1); if (range.first.column != column_unset) // Same with unset column. assert(range.first.abs_column == range_tests[i].abs_col1); assert(range.last.sheet == range_tests[i].sheet2); assert(range.last.row == range_tests[i].row2); assert(range.last.column == range_tests[i].col2); assert(range.last.abs_sheet == range_tests[i].abs_sheet2); if (range.last.row != row_unset) assert(range.last.abs_row == range_tests[i].abs_row2); if (range.last.column != column_unset) assert(range.last.abs_column == range_tests[i].abs_col2); } ref_name_entry range_ref_names[] = { { "R2C2:R3C3", false }, { "R[-3]C2:R[-1]C3", false }, { "R[-5]C:R[-1]C", false }, { "'A B C'!R2:R4", true }, { "'80''s Music'!C[2]:C[4]", true }, { 0, false }, }; for (size_t i = 0; range_ref_names[i].name; ++i) { const char* p = range_ref_names[i].name; string name_r1c1(p); cout << "Parsing " << name_r1c1 << endl; formula_name_t res = resolver->resolve(name_r1c1, abs_address_t()); if (res.type != formula_name_t::range_reference) { cerr << "failed to resolve range address: " << name_r1c1 << endl; assert(false); } auto range = std::get(res.value); string test_name = resolver->get_name(range, abs_address_t(), range_ref_names[i].sheet_name); if (name_r1c1 != test_name) { cerr << "failed to compile name from range: (name expected: " << name_r1c1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } struct { col_t col; string name; } colnames[] = { { 0, "1" }, { 1, "2" }, { 10, "11" }, { 123, "124" }, }; for (size_t i = 0, n = IXION_N_ELEMENTS(colnames); i < n; ++i) { string colname = resolver->get_column_name(colnames[i].col); if (colname != colnames[i].name) { cerr << "column name: expected='" << colnames[i].name << "', actual='" << colname << "'" << endl; assert(false); } } } void test_name_resolver_odff() { cout << "test name resolver odff" << endl; model_context cxt; cxt.append_sheet("One"); cxt.append_sheet("Two"); cxt.append_sheet("A B C"); // name with space cxt.append_sheet("80's Music"); auto resolver = formula_name_resolver::get(formula_name_resolver_t::odff, &cxt); assert(resolver); // Parse single cell addresses. ref_name_entry single_ref_names[] = { { "[.A1]", false }, { "[.$A1]", false }, { "[.A$1]", false }, { "[.$A$1]", false }, { 0, false } }; for (size_t i = 0; single_ref_names[i].name; ++i) { const char* p = single_ref_names[i].name; string name_a1(p); formula_name_t res = resolver->resolve(name_a1, abs_address_t()); if (res.type != formula_name_t::cell_reference) { cerr << "failed to resolve cell address: " << name_a1 << endl; assert(false); } address_t addr = std::get(res.value); string test_name = resolver->get_name(addr, abs_address_t(), single_ref_names[i].sheet_name); if (name_a1 != test_name) { cerr << "failed to compile name from address: (name expected: " << name_a1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } // Parse cell range addresses. ref_name_entry range_ref_names[] = { { "[.A1:.A3]", false }, { "[.$B5:.$D10]", false }, { 0, false } }; for (size_t i = 0; range_ref_names[i].name; ++i) { const char* p = range_ref_names[i].name; string name_a1(p); formula_name_t res = resolver->resolve(name_a1, abs_address_t()); if (res.type != formula_name_t::range_reference) { cerr << "failed to resolve range address: " << name_a1 << endl; assert(false); } auto range = std::get(res.value); string test_name = resolver->get_name(range, abs_address_t(), range_ref_names[i].sheet_name); if (name_a1 != test_name) { cerr << "failed to compile name from range: (name expected: " << name_a1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } // single cell addresses with sheet names ref_name_entry addr_with_sheet_names[] = { { "[One.$B$1]", true }, { "[$One.$B$1]", true }, { "[Two.$B$2]", true }, { "[$Two.$B$4]", true }, { "['A B C'.$B$4]", true }, { "[$'A B C'.$B$4]", true }, { 0, false }, }; for (size_t i = 0; addr_with_sheet_names[i].name; ++i) { const char* p = addr_with_sheet_names[i].name; std::string name_a1(p); formula_name_t res = resolver->resolve(name_a1, abs_address_t()); if (res.type != formula_name_t::cell_reference) { cerr << "failed to resolve cell address: " << name_a1 << endl; assert(false); } address_t addr = std::get(res.value); std::string test_name = resolver->get_name(addr, abs_address_t(), addr_with_sheet_names[i].sheet_name); if (name_a1 != test_name) { cerr << "failed to compile name from cell address: (name expected: " << name_a1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } // range addresses with sheet names ref_name_entry ref_with_sheet_names[] = { { "[One.$B$1:.$B$30]", true }, { "[$One.$B$1:.$B$30]", true }, { "[Two.$B$2:.$D30]", true }, { "[$Two.$B$4:.F$35]", true }, { "['A B C'.$B$4:.F$35]", true }, { "[$'A B C'.$B$4:.F$35]", true }, { "[$One.B$4:$Two.F35]", true }, { "[$One.B$4:'A B C'.F35]", true }, { "[One.B$4:$'A B C'.F35]", true }, { 0, false }, }; for (size_t i = 0; ref_with_sheet_names[i].name; ++i) { const char* p = ref_with_sheet_names[i].name; std::string name_a1(p); formula_name_t res = resolver->resolve(name_a1, abs_address_t()); if (res.type != formula_name_t::range_reference) { cerr << "failed to resolve range address: " << name_a1 << endl; assert(false); } auto range = std::get(res.value); std::string test_name = resolver->get_name(range, abs_address_t(), ref_with_sheet_names[i].sheet_name); if (name_a1 != test_name) { cerr << "failed to compile name from range: (name expected: " << name_a1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } { std::string name = "[.H2:.I2]"; abs_address_t pos(2, 1, 9); formula_name_t res = resolver->resolve(name, pos); assert(res.type == formula_name_t::range_reference); abs_range_t range = std::get(res.value).to_abs(pos); abs_range_t range_expected(abs_address_t(pos.sheet, 1, 7), 1, 2); assert(range == range_expected); } { std::string name = "[Two.$B$2:.$B$10]"; abs_address_t pos(3, 2, 1); formula_name_t res = resolver->resolve(name, pos); assert(res.type == formula_name_t::range_reference); abs_range_t range = std::get(res.value).to_abs(pos); abs_range_t range_expected(abs_address_t(1, 1, 1), 9, 1); assert(range == range_expected); } { std::string name = "MyRange"; abs_address_t pos(3, 2, 1); formula_name_t res = resolver->resolve(name, pos); assert(res.type == formula_name_t::named_expression); } } void test_name_resolver_odf_cra() { cout << "test name resolver odf-cra" << endl; model_context cxt; cxt.append_sheet("One"); cxt.append_sheet("Two"); cxt.append_sheet("Three"); cxt.append_sheet("A B C"); // name with space auto resolver = formula_name_resolver::get(formula_name_resolver_t::odf_cra, &cxt); assert(resolver); { // Parse single cell addresses. ref_name_entry names[] = { { ".A1", false }, { ".$A1", false }, { ".A$1", false }, { ".$A$1", false }, { ".Z1", false }, { ".AA23", false }, { ".AB23", false }, { ".$AB23", false }, { ".AB$23", false }, { ".$AB$23", false }, { ".BA1", false }, { ".AAA2", false }, { ".ABA1", false }, { ".BAA1", false }, { ".XFD1048576", false }, { "One.A1", true }, { "One.XFD1048576", true }, { "Two.B10", true }, { "Two.$B10", true }, { "Two.B$10", true }, { "Two.$B$10", true }, { "Three.CFD234", true }, { "$Three.CFD234", true }, { "'A B C'.Z12", true }, { "$'A B C'.Z12", true }, { 0, false } }; for (size_t i = 0; names[i].name; ++i) { const char* p = names[i].name; string name_a1(p); cout << "single cell address: " << name_a1 << endl; formula_name_t res = resolver->resolve(name_a1, abs_address_t()); if (res.type != formula_name_t::cell_reference) { cerr << "failed to resolve cell address: " << name_a1 << endl; assert(false); } address_t addr = std::get(res.value); string test_name = resolver->get_name(addr, abs_address_t(), names[i].sheet_name); if (name_a1 != test_name) { cerr << "failed to compile name from address: (name expected: " << name_a1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } } { // Parse range addresses. ref_name_entry names[] = { { ".A1:.B2", false }, { ".$D10:.G$24", false }, { "One.C$1:.Z$400", true }, { "Two.$C1:.$Z400", true }, { "Three.$C1:.Z$400", true }, { "$Three.$C1:.Z$400", true }, { "'A B C'.$C4:.$Z256", true }, { "$'A B C'.$C4:.$Z256", true }, { "One.C4:Three.Z100", true }, { "One.C4:$Three.Z100", true }, { "$One.C4:Three.Z100", true }, { "$One.C4:$Three.Z100", true }, { 0, false }, }; for (sheet_t sheet = 0; sheet <= 3; ++sheet) { for (size_t i = 0; names[i].name; ++i) { abs_address_t pos{sheet, 0, 0}; string name_a1(names[i].name); cout << "range address: " << name_a1 << endl; formula_name_t res = resolver->resolve(name_a1, pos); if (res.type != formula_name_t::range_reference) { cerr << "failed to resolve range address: " << name_a1 << endl; assert(false); } auto range = std::get(res.value); std::string test_name = resolver->get_name(range, pos, names[i].sheet_name); if (name_a1 != test_name) { cerr << "failed to compile name from range: (pos: " << pos << "; name expected: " << name_a1 << "; actual name created: " << test_name << ")" << endl; assert(false); } } } } } void test_address() { cout << "test address" << endl; { address_t addr(-1, 0, 0, false, false, false); abs_address_t pos(1, 0, 0); abs_address_t abs_addr = addr.to_abs(pos); assert(abs_addr.sheet == 0 && abs_addr.row == 0 && abs_addr.column == 0); abs_address_t pos_invalid_sheet(invalid_sheet, 2, 3); auto test = addr.to_abs(pos_invalid_sheet); assert(test.sheet == invalid_sheet); assert(test.row == 2); assert(test.column == 3); } // Default constructor makes valid address. assert(abs_address_t().valid()); assert(abs_range_t().valid()); // These are invalid addresses. assert(!abs_address_t(abs_address_t::invalid).valid()); assert(!abs_range_t(abs_range_t::invalid).valid()); { abs_range_t range(1, 1, 2, 3, 3); assert(range.first.sheet == 1); assert(range.first.row == 1); assert(range.first.column == 2); assert(range.last.sheet == 1); assert(range.last.row == 3); assert(range.last.column == 4); abs_range_t range2(range); assert(range2 == range); abs_rc_range_t rc_range(range); assert(rc_range.first.row == 1); assert(rc_range.first.column == 2); assert(rc_range.last.row == 3); assert(rc_range.last.column == 4); } } bool check_formula_expression( model_context& cxt, const formula_name_resolver& resolver, const char* p) { size_t n = strlen(p); cout << "testing formula expression '" << p << "'" << endl; formula_tokens_t tokens = parse_formula_string(cxt, abs_address_t(), resolver, {p, n}); std::string expression = print_formula_tokens(cxt, abs_address_t(), resolver, tokens); int res = strcmp(p, expression.data()); if (res) { cout << "formula expressions differ: '" << p << "' (before) -> '" << expression << "' (after)" << endl; return false; } std::ostringstream os; for (const auto& t : tokens) os << print_formula_token(cxt, abs_address_t(), resolver, *t); std::string individual_tokens = os.str(); if (expression != individual_tokens) { cout << "whole expression differs from individual token strings:" << endl << " * expression='" << expression << "'" << endl << " * individual-tokens='" << individual_tokens << "'" << endl; return false; } return true; } /** * Make sure the public API works as advertized. */ void test_parse_and_print_expressions() { cout << "test public formula api" << endl; // Excel A1 std::vector exps = { "\" \"", "1/3*1.4", "2.3*(1+2)/(34*(3-2))", "SUM(1,2,3)", "A1", "B10", "XFD1048576", "C10:D20", "A1:XFD1048576", "H:H", "B:D", "AB:AD", "2:2", "3:5", "34:36", "1>2", "1>=2", "1<2", "1<=2", "1<>2", "1=2", "Table1[Category]", "Table1[Value]", "Table1[#Headers]", "Table1[[#Headers],[Category]:[Value]]", "Table1[[#Headers],[#Data],[Category]:[Value]]", "IF(A1=\"\",\"empty\",\"not empty\")", "$'Ying & Yang'.$A$1:$H$54", }; model_context cxt; cxt.append_sheet("Test"); cxt.append_string("Table1"); cxt.append_string("Category"); cxt.append_string("Value"); cxt.append_sheet("Ying & Yang"); // name with '&' auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); assert(resolver); for (const char* exp : exps) { bool result = check_formula_expression(cxt, *resolver, exp); assert(result); } // Excel R1C1 exps = { "SUM(R[-5]C:R[-1]C)", }; resolver = formula_name_resolver::get(formula_name_resolver_t::excel_r1c1, &cxt); assert(resolver); for (const char* exp : exps) { bool result = check_formula_expression(cxt, *resolver, exp); assert(result); } // ODFF exps = { "\" \"", "SUM([.A1];[.B1])", "CONCATENATE([.A6];\" \";[.B6])", "IF(['Ying & Yang'.$A$1:.$O$200];2;0)", }; resolver = formula_name_resolver::get(formula_name_resolver_t::odff, &cxt); assert(resolver); config cfg = cxt.get_config(); cfg.sep_function_arg = ';'; cxt.set_config(cfg); for (const char* exp : exps) { bool result = check_formula_expression(cxt, *resolver, exp); assert(result); } } /** * Function name must be resolved case-insensitively. */ void test_function_name_resolution() { cout << "test function name resolution" << endl; const char* valid_names[] = { "SUM", "sum", "Sum", "Average", "max", "min" }; const char* invalid_names[] = { "suma", "foo", "", "su", "maxx", "minmin" }; model_context cxt; cxt.append_sheet("Test"); auto resolver = formula_name_resolver::get(ixion::formula_name_resolver_t::excel_a1, &cxt); size_t n = IXION_N_ELEMENTS(valid_names); for (size_t i = 0; i < n; ++i) { const char* name = valid_names[i]; cout << "valid name: " << name << endl; formula_name_t t = resolver->resolve(name, abs_address_t()); assert(t.type == formula_name_t::function); } n = IXION_N_ELEMENTS(invalid_names); for (size_t i = 0; i < n; ++i) { const char* name = invalid_names[i]; cout << "invalid name: " << name << endl; formula_name_t t = resolver->resolve(name, abs_address_t()); assert(t.type != formula_name_t::function); } } formula_cell* insert_formula( model_context& cxt, const abs_address_t& pos, const char* exp, const formula_name_resolver& resolver) { formula_tokens_t tokens = parse_formula_string(cxt, pos, resolver, exp); auto ts = formula_tokens_store::create(); ts->get() = std::move(tokens); formula_cell* p_inserted = cxt.set_formula_cell(pos, ts); assert(p_inserted); register_formula_cell(cxt, pos); formula_cell* p = cxt.get_formula_cell(pos); assert(p); assert(p == p_inserted); return p; } void test_model_context_storage() { cout << "test model context storage" << endl; { model_context cxt; auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); assert(resolver); cxt.append_sheet("test"); // Test empty cell access. cell_access ca = cxt.get_cell_access(abs_address_t(0, 0, 0)); assert(ca.get_type() == celltype_t::empty); assert(ca.get_value_type() == cell_value_t::empty); // String value on an empty cell should be an empty string. std::string_view s = ca.get_string_value(); assert(s.empty()); // Likewise... s = cxt.get_string_value(abs_address_t(0, 0, 0)); assert(s.empty()); // Test storage of numeric values. volatile double val = 0.1; for (col_t col = 0; col < 3; ++col) { for (row_t row = 0; row < 3; ++row) { abs_address_t pos(0, row, col); cxt.set_numeric_cell(pos, val); double test = cxt.get_numeric_value(pos); assert(test == val); ca = cxt.get_cell_access(pos); assert(ca.get_type() == celltype_t::numeric); assert(ca.get_value_type() == cell_value_t::numeric); test = ca.get_numeric_value(); assert(test == val); val += 0.2; } } // Test formula cells. abs_address_t pos(0,3,0); const char* exp = "SUM(1,2,3)"; formula_tokens_t tokens = parse_formula_string(cxt, pos, *resolver, exp); auto ts = formula_tokens_store::create(); ts->get() = std::move(tokens); formula_cell* p_inserted = cxt.set_formula_cell(pos, ts); assert(p_inserted); formula_cell* p = cxt.get_formula_cell(pos); assert(p); assert(p_inserted == p); p->interpret(cxt, pos); ca = cxt.get_cell_access(pos); assert(ca.get_type() == celltype_t::formula); assert(ca.get_value_type() == cell_value_t::numeric); assert(ca.get_numeric_value() == 6.0); } { model_context cxt; auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); assert(resolver); cxt.append_sheet("test"); string exp = "1"; cxt.set_formula_cell(abs_address_t(0,0,0), parse_formula_string(cxt, abs_address_t(0,0,0), *resolver, exp)); cxt.set_formula_cell(abs_address_t(0,2,0), parse_formula_string(cxt, abs_address_t(0,2,0), *resolver, exp)); cxt.set_formula_cell(abs_address_t(0,1,0), parse_formula_string(cxt, abs_address_t(0,1,0), *resolver, exp)); } { // Test data area. model_context cxt; cxt.append_sheet("test"); abs_range_t area = cxt.get_data_range(0); assert(!area.valid()); cxt.set_numeric_cell(abs_address_t(0, 6, 5), 1.1); area = cxt.get_data_range(0); assert(area.first == area.last); assert(area.first.sheet == 0); assert(area.first.row == 6); assert(area.first.column == 5); cxt.set_numeric_cell(abs_address_t(0, 2, 3), 1.1); area = cxt.get_data_range(0); assert(area.first.sheet == 0); assert(area.first.row == 2); assert(area.first.column == 3); assert(area.last.sheet == 0); assert(area.last.row == 6); assert(area.last.column == 5); cxt.set_numeric_cell(abs_address_t(0, 7, 1), 1.1); area = cxt.get_data_range(0); assert(area.first.sheet == 0); assert(area.first.row == 2); assert(area.first.column == 1); assert(area.last.sheet == 0); assert(area.last.row == 7); assert(area.last.column == 5); // This shouldn't change the data range. cxt.set_numeric_cell(abs_address_t(0, 5, 5), 1.1); abs_range_t test = cxt.get_data_range(0); assert(test == area); } { // Fill up the document model and make sure the data range is still // correct. const row_t row_size = 5; const col_t col_size = 4; model_context cxt({row_size, col_size}); cxt.append_sheet("test"); for (row_t row = 0; row < row_size; ++row) for (col_t col = 0; col < col_size; ++col) cxt.set_numeric_cell(abs_address_t(0,row,col), 1.0); abs_range_t test = cxt.get_data_range(0); assert(test.first.sheet == 0); assert(test.first.row == 0); assert(test.first.column == 0); assert(test.last.sheet == 0); assert(test.last.row == row_size-1); assert(test.last.column == col_size-1); } { const row_t row_size = 5; const col_t col_size = 4; model_context cxt({row_size, col_size}); cxt.append_sheet("test"); cxt.set_numeric_cell(abs_address_t(0,0,0), 1.0); cxt.set_numeric_cell(abs_address_t(0,row_size-1,0), 1.0); cxt.set_numeric_cell(abs_address_t(0,row_size/2,col_size/2), 1.0); abs_range_t test = cxt.get_data_range(0); assert(test.first.sheet == 0); assert(test.first.row == 0); assert(test.first.column == 0); assert(test.last.sheet == 0); assert(test.last.row == row_size-1); assert(test.last.column == col_size/2); } } void test_model_context_direct_string_access() { cout << "test model context direct string access" << endl; model_context cxt{{400, 20}}; cxt.append_sheet("test"); // regular string cell abs_address_t B2(0, 1, 1); cxt.set_string_cell(B2, "string cell"); std::string_view s = cxt.get_string_value(B2); assert(s == "string cell"); cell_access ca = cxt.get_cell_access(B2); assert(ca.get_type() == celltype_t::string); assert(ca.get_value_type() == cell_value_t::string); s = ca.get_string_value(); assert(s == "string cell"); // formula cell containing a string result. abs_address_t C4(0, 3, 2); auto resolver = formula_name_resolver::get(formula_name_resolver_t::calc_a1, &cxt); assert(resolver); // Insert a formula containing one literal string token. formula_tokens_t tokens = parse_formula_string(cxt, C4, *resolver, "\"string value in formula\""); assert(tokens.size() == 1); cxt.set_formula_cell(C4, std::move(tokens)); // no need to register formula cell since it does not reference other cells. abs_range_set_t formula_cells{C4}; auto sorted = query_and_sort_dirty_cells(cxt, abs_range_set_t(), &formula_cells); calculate_sorted_cells(cxt, sorted, 1); s = cxt.get_string_value(C4); assert(s == "string value in formula"); ca = cxt.get_cell_access(C4); assert(ca.get_type() == celltype_t::formula); assert(ca.get_value_type() == cell_value_t::string); s = ca.get_string_value(); assert(s == "string value in formula"); } void test_model_context_named_expression() { model_context cxt{{400, 20}}; cxt.append_sheet("test"); auto resolver = formula_name_resolver::get(formula_name_resolver_t::calc_a1, &cxt); assert(resolver); abs_address_t B3(0, 2, 1); struct test_case { std::string name; std::string formula; abs_address_t origin; }; std::vector tcs = { { "LeftAndAbove", "A3+B2", B3 }, { "SumAboveRow", "SUM(A2:D2)", B3 }, }; for (const test_case& tc : tcs) { formula_tokens_t tokens = parse_formula_string(cxt, tc.origin, *resolver, tc.formula); std::string test = print_formula_tokens(cxt, tc.origin, *resolver, tokens); assert(test == tc.formula); cxt.set_named_expression(tc.name, tc.origin, std::move(tokens)); } for (const test_case& tc : tcs) { const named_expression_t* exp = cxt.get_named_expression(0, tc.name); assert(exp); assert(exp->origin == tc.origin); std::string test = print_formula_tokens(cxt, exp->origin, *resolver, exp->tokens); assert(test == tc.formula); } // invalid names should be rejected. struct name_test_case { std::string name; bool valid; }; std::vector invalid_names = { { "Name 1", false }, { "Name_1", true }, { "123Name", false }, { "Name123", true }, { "", false }, { "Name.1", true }, { ".Name.2", false }, }; for (const name_test_case& tc : invalid_names) { abs_address_t origin; std::string formula = "1+2"; if (tc.valid) { formula_tokens_t tokens = parse_formula_string(cxt, origin, *resolver, formula); cxt.set_named_expression(tc.name, origin, std::move(tokens)); tokens = parse_formula_string(cxt, origin, *resolver, formula); cxt.set_named_expression(0, tc.name, origin, std::move(tokens)); } else { try { formula_tokens_t tokens = parse_formula_string(cxt, origin, *resolver, formula); cxt.set_named_expression(tc.name, origin, std::move(tokens)); assert(!"named expression with invalid name should have been rejected!"); } catch (const model_context_error& e) { assert(e.get_error_type() == model_context_error::invalid_named_expression); } try { formula_tokens_t tokens = parse_formula_string(cxt, origin, *resolver, formula); cxt.set_named_expression(0, tc.name, origin, std::move(tokens)); assert(!"named expression with invalid name should have been rejected!"); } catch (const model_context_error& e) { assert(e.get_error_type() == model_context_error::invalid_named_expression); } } } } bool check_model_iterator_output(model_iterator& iter, const std::vector& checks) { for (const model_iterator::cell& c : checks) { if (!iter.has()) { cerr << "a cell value was expected, but none found." << endl; return false; } if (iter.get() != c) { cerr << "unexpected cell value: expected=" << c << "; observed=" << iter.get() << endl; return false; } iter.next(); } if (iter.has()) { cerr << "an additional cell value was found, but none was expected." << endl; return false; } return true; } void test_model_context_iterator_horizontal() { const row_t row_size = 5; const col_t col_size = 2; model_context cxt{{row_size, col_size}}; model_iterator iter; abs_rc_range_t whole_range; whole_range.set_all_columns(); whole_range.set_all_rows(); // It should not crash or throw an exception on empty model. iter = cxt.get_model_iterator(0, rc_direction_t::horizontal, whole_range); assert(!iter.has()); // Insert an actual sheet and try again. cxt.append_sheet("empty sheet"); iter = cxt.get_model_iterator(0, rc_direction_t::horizontal, whole_range); // Make sure the cell position iterates correctly. size_t cell_count = 0; for (row_t row = 0; row < row_size; ++row) { for (col_t col = 0; col < col_size; ++cell_count, ++col, iter.next()) { assert(iter.has()); assert(iter.get().row == row); assert(iter.get().col == col); assert(iter.get().type == celltype_t::empty); } } assert(!iter.has()); // There should be no more cells on this sheet. assert(cell_count == 10); cxt.append_sheet("values"); cxt.set_string_cell(abs_address_t(1, 0, 0), "F1"); cxt.set_string_cell(abs_address_t(1, 0, 1), "F2"); cxt.set_boolean_cell(abs_address_t(1, 1, 0), true); cxt.set_boolean_cell(abs_address_t(1, 1, 1), false); cxt.set_numeric_cell(abs_address_t(1, 2, 0), 3.14); cxt.set_numeric_cell(abs_address_t(1, 2, 1), -12.5); auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); abs_range_set_t modified_cells; abs_address_t pos(1, 3, 0); formula_tokens_t tokens = parse_formula_string(cxt, pos, *resolver, "SUM(1, 2, 3)"); formula_cell* p = cxt.set_formula_cell(pos, std::move(tokens)); assert(p); const formula_tokens_t& t = p->get_tokens()->get(); assert(t.size() == 8); // there should be 8 tokens. register_formula_cell(cxt, pos, p); modified_cells.insert(pos); pos.column = 1; tokens = parse_formula_string(cxt, pos, *resolver, "5 + 6 - 7"); p = cxt.set_formula_cell(pos, std::move(tokens)); register_formula_cell(cxt, pos, p); modified_cells.insert(pos); // Calculate the formula cells. auto sorted = query_and_sort_dirty_cells(cxt, abs_range_set_t(), &modified_cells); calculate_sorted_cells(cxt, sorted, 1); std::vector checks = { // row, column, value { 0, 0, cxt.get_identifier_from_string("F1") }, { 0, 1, cxt.get_identifier_from_string("F2") }, { 1, 0, true }, { 1, 1, false }, { 2, 0, 3.14 }, { 2, 1, -12.5 }, { 3, 0, cxt.get_formula_cell(abs_address_t(1, 3, 0)) }, { 3, 1, cxt.get_formula_cell(abs_address_t(1, 3, 1)) }, { 4, 0 }, { 4, 1 }, }; // Iterator and check the individual cell values. iter = cxt.get_model_iterator(1, rc_direction_t::horizontal, whole_range); assert(check_model_iterator_output(iter, checks)); } void test_model_context_iterator_horizontal_range() { nullptr_t empty = nullptr; model_context cxt{{10, 5}}; cxt.append_sheet("Values"); cxt.set_cell_values(0, { { "F1", "F2", "F3", "F4", "F5" }, { 1.0, true, "s1", empty, empty }, { 1.1, false, empty, "s2", empty }, { 1.2, false, empty, "s3", empty }, { 1.3, true, empty, "s4", empty }, { 1.4, false, empty, "s5", empty }, { 1.5, "NA", empty, "s6", empty }, { 1.6, 99.9, empty, "s7", empty }, { 1.7, 199.9, empty, "s8", empty }, { 1.8, 299.9, empty, "s9", "end" }, }); // Only iterate over the first two rows. abs_rc_range_t range; range.set_all_columns(); range.first.row = 0; range.last.row = 1; model_iterator iter = cxt.get_model_iterator(0, rc_direction_t::horizontal, range); std::vector checks = { // row, column, value { 0, 0, cxt.get_identifier_from_string("F1") }, { 0, 1, cxt.get_identifier_from_string("F2") }, { 0, 2, cxt.get_identifier_from_string("F3") }, { 0, 3, cxt.get_identifier_from_string("F4") }, { 0, 4, cxt.get_identifier_from_string("F5") }, { 1, 0, 1.0 }, { 1, 1, true }, { 1, 2, cxt.get_identifier_from_string("s1") }, { 1, 3 }, { 1, 4 }, }; assert(check_model_iterator_output(iter, checks)); // Only iterate over rows 2:4. range.first.row = 2; range.last.row = 4; iter = cxt.get_model_iterator(0, rc_direction_t::horizontal, range); checks = { // row, column, value { 2, 0, 1.1 }, { 2, 1, false }, { 2, 2 }, { 2, 3, cxt.get_identifier_from_string("s2") }, { 2, 4 }, { 3, 0, 1.2 }, { 3, 1, false }, { 3, 2 }, { 3, 3, cxt.get_identifier_from_string("s3") }, { 3, 4 }, { 4, 0, 1.3 }, { 4, 1, true }, { 4, 2 }, { 4, 3, cxt.get_identifier_from_string("s4") }, { 4, 4 }, }; assert(check_model_iterator_output(iter, checks)); // Only iterate over columns 1:3 and only down to row 4. range.set_all_rows(); range.first.column = 1; range.last.column = 3; range.last.row = 4; iter = cxt.get_model_iterator(0, rc_direction_t::horizontal, range); checks = { // row, column, value { 0, 1, cxt.get_identifier_from_string("F2") }, { 0, 2, cxt.get_identifier_from_string("F3") }, { 0, 3, cxt.get_identifier_from_string("F4") }, { 1, 1, true }, { 1, 2, cxt.get_identifier_from_string("s1") }, { 1, 3 }, { 2, 1, false }, { 2, 2 }, { 2, 3, cxt.get_identifier_from_string("s2") }, { 3, 1, false }, { 3, 2 }, { 3, 3, cxt.get_identifier_from_string("s3") }, { 4, 1, true }, { 4, 2 }, { 4, 3, cxt.get_identifier_from_string("s4") }, }; assert(check_model_iterator_output(iter, checks)); } void test_model_context_iterator_vertical() { const row_t row_size = 5; const col_t col_size = 2; model_context cxt{{row_size, col_size}}; model_iterator iter; abs_rc_range_t whole_range; whole_range.set_all_columns(); whole_range.set_all_rows(); // It should not crash or throw an exception on empty model. iter = cxt.get_model_iterator(0, rc_direction_t::vertical, whole_range); assert(!iter.has()); // Insert an actual sheet and try again. cxt.append_sheet("empty sheet"); iter = cxt.get_model_iterator(0, rc_direction_t::vertical, whole_range); // Make sure the cell position iterates correctly. size_t cell_count = 0; for (col_t col = 0; col < col_size; ++col) { for (row_t row = 0; row < row_size; ++cell_count, ++row, iter.next()) { const model_iterator::cell& cell = iter.get(); assert(iter.has()); assert(cell.row == row); assert(cell.col == col); assert(cell.type == celltype_t::empty); } } assert(!iter.has()); // There should be no more cells on this sheet. assert(cell_count == 10); cxt.append_sheet("values"); cxt.set_string_cell(abs_address_t(1, 0, 0), "F1"); cxt.set_string_cell(abs_address_t(1, 0, 1), "F2"); cxt.set_boolean_cell(abs_address_t(1, 1, 0), true); cxt.set_boolean_cell(abs_address_t(1, 1, 1), false); cxt.set_numeric_cell(abs_address_t(1, 2, 0), 3.14); cxt.set_numeric_cell(abs_address_t(1, 2, 1), -12.5); auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); abs_range_set_t modified_cells; abs_address_t pos(1, 3, 0); formula_tokens_t tokens = parse_formula_string(cxt, pos, *resolver, "SUM(1, 2, 3)"); cxt.set_formula_cell(pos, std::move(tokens)); register_formula_cell(cxt, pos); modified_cells.insert(pos); pos.column = 1; tokens = parse_formula_string(cxt, pos, *resolver, "5 + 6 - 7"); cxt.set_formula_cell(pos, std::move(tokens)); register_formula_cell(cxt, pos); modified_cells.insert(pos); // Calculate the formula cells. auto sorted = query_and_sort_dirty_cells(cxt, abs_range_set_t(), &modified_cells); calculate_sorted_cells(cxt, sorted, 1); std::vector checks = { // row, column, value { 0, 0, cxt.get_identifier_from_string("F1") }, { 1, 0, true }, { 2, 0, 3.14 }, { 3, 0, cxt.get_formula_cell(abs_address_t(1, 3, 0)) }, { 4, 0 }, { 0, 1, cxt.get_identifier_from_string("F2") }, { 1, 1, false }, { 2, 1, -12.5 }, { 3, 1, cxt.get_formula_cell(abs_address_t(1, 3, 1)) }, { 4, 1 }, }; iter = cxt.get_model_iterator(1, rc_direction_t::vertical, whole_range); assert(check_model_iterator_output(iter, checks)); } void test_model_context_iterator_vertical_range() { nullptr_t empty = nullptr; model_context cxt{{10, 5}}; cxt.append_sheet("Values"); cxt.set_cell_values(0, { { "F1", "F2", "F3", "F4", "F5" }, { 1.0, true, "s1", empty, empty }, { 1.1, false, empty, "s2", empty }, { 1.2, false, empty, "s3", empty }, { 1.3, true, empty, "s4", empty }, { 1.4, false, empty, "s5", empty }, { 1.5, "NA", empty, "s6", empty }, { 1.6, 99.9, empty, "s7", empty }, { 1.7, 199.9, empty, "s8", empty }, { 1.8, 299.9, empty, "s9", "end" }, }); // Iterate over the top 2 rows. abs_rc_range_t range; range.set_all_columns(); range.set_all_rows(); range.last.row = 1; model_iterator iter = cxt.get_model_iterator(0, rc_direction_t::vertical, range); std::vector checks = { // row, column, value { 0, 0, cxt.get_identifier_from_string("F1") }, { 1, 0, 1.0 }, { 0, 1, cxt.get_identifier_from_string("F2") }, { 1, 1, true }, { 0, 2, cxt.get_identifier_from_string("F3") }, { 1, 2, cxt.get_identifier_from_string("s1") }, { 0, 3, cxt.get_identifier_from_string("F4") }, { 1, 3 }, { 0, 4, cxt.get_identifier_from_string("F5") }, { 1, 4 }, }; assert(check_model_iterator_output(iter, checks)); // Iterate over the bottom 2 rows. range.set_all_rows(); range.first.row = 8; iter = cxt.get_model_iterator(0, rc_direction_t::vertical, range); checks = { // row, column, value { 8, 0, 1.7 }, { 9, 0, 1.8 }, { 8, 1, 199.9 }, { 9, 1, 299.9 }, { 8, 2 }, { 9, 2 }, { 8, 3, cxt.get_identifier_from_string("s8") }, { 9, 3, cxt.get_identifier_from_string("s9") }, { 8, 4 }, { 9, 4, cxt.get_identifier_from_string("end") }, }; assert(check_model_iterator_output(iter, checks)); // Iterate over the bottom-left corners. range.last.column = 2; iter = cxt.get_model_iterator(0, rc_direction_t::vertical, range); checks = { // row, column, value { 8, 0, 1.7 }, { 9, 0, 1.8 }, { 8, 1, 199.9 }, { 9, 1, 299.9 }, { 8, 2 }, { 9, 2 }, }; assert(check_model_iterator_output(iter, checks)); // Iterate over the top-right corners. range.first.column = 3; range.last.column = column_unset; range.first.row = row_unset; range.last.row = 1; iter = cxt.get_model_iterator(0, rc_direction_t::vertical, range); checks = { { 0, 3, cxt.get_identifier_from_string("F4") }, { 1, 3 }, { 0, 4, cxt.get_identifier_from_string("F5") }, { 1, 4 }, }; assert(check_model_iterator_output(iter, checks)); // Iterate over only one cell in the middle. range.first.row = 5; range.last.row = 5; range.first.column = 3; range.last.column = 3; iter = cxt.get_model_iterator(0, rc_direction_t::vertical, range); checks = { { 5, 3, cxt.get_identifier_from_string("s5") }, }; assert(check_model_iterator_output(iter, checks)); } void test_model_context_iterator_named_exps() { struct check { std::string name; const named_expression_t* exp; }; model_context cxt{{100, 10}}; cxt.append_sheet("test1"); cxt.append_sheet("test2"); named_expressions_iterator iter; assert(!iter.has()); assert(iter.size() == 0); iter = cxt.get_named_expressions_iterator(); assert(!iter.has()); assert(iter.size() == 0); auto resolver = formula_name_resolver::get(formula_name_resolver_t::calc_a1, &cxt); assert(resolver); auto tokenize = [&](const char* p) -> formula_tokens_t { return parse_formula_string(cxt, abs_address_t(), *resolver, p); }; auto validate = [](named_expressions_iterator _iter, const std::vector& _expected) -> bool { if (_iter.size() != _expected.size()) { cout << "iterator's size() returns wrong value." << endl; return false; } for (const check& c : _expected) { if (!_iter.has()) { cout << "iterator has no more element, but it is expected to." << endl; return false; } if (c.name != *_iter.get().name) { cout << "names differ: expected='" << c.name << "'; actual='" << *_iter.get().name << endl; return false; } if (c.exp != _iter.get().expression) { cout << "expressions differ." << endl; return false; } _iter.next(); } if (_iter.has()) { cout << "the iterator has more elements, but it is not expected to." << endl; return false; } return true; }; cxt.set_named_expression("MyCalc", tokenize("(1+2)/3")); std::vector expected = { { "MyCalc", cxt.get_named_expression(0, "MyCalc") }, }; iter = cxt.get_named_expressions_iterator(); assert(validate(iter, expected)); cxt.set_named_expression("RefToRight", tokenize("B1")); expected = { { "MyCalc", cxt.get_named_expression(0, "MyCalc") }, { "RefToRight", cxt.get_named_expression(0, "RefToRight") }, }; iter = cxt.get_named_expressions_iterator(); assert(validate(iter, expected)); cxt.set_named_expression(1, "MyCalc2", tokenize("(B1+C1)/D1")); cxt.set_named_expression(1, "MyCalc3", tokenize("B1/(PI()*2)")); iter = cxt.get_named_expressions_iterator(0); assert(!iter.has()); iter = cxt.get_named_expressions_iterator(1); expected = { { "MyCalc2", cxt.get_named_expression(1, "MyCalc2") }, { "MyCalc3", cxt.get_named_expression(1, "MyCalc3") }, }; assert(validate(iter, expected)); } void test_model_context_fill_down() { nullptr_t empty = nullptr; model_context cxt{{100, 10}}; cxt.append_sheet("test"); cxt.set_cell_values(0, { { "numeric", "bool", "string", "empty" }, { 12.3, true, "foo", empty }, { empty, empty, empty, 1.1 }, { empty, empty, empty, 1.1 }, { empty, empty, empty, 1.1 }, { empty, empty, empty, 1.1 }, { empty, empty, empty, 1.1 }, }); abs_address_t pos(0, 1, 0); cxt.fill_down_cells(pos, 2); assert(cxt.get_numeric_value(abs_address_t(0, 1, 0)) == 12.3); assert(cxt.get_numeric_value(abs_address_t(0, 2, 0)) == 12.3); assert(cxt.get_numeric_value(abs_address_t(0, 3, 0)) == 12.3); assert(cxt.is_empty(abs_address_t(0, 4, 0))); pos.column = 1; cxt.fill_down_cells(pos, 1); assert(cxt.get_boolean_value(abs_address_t(0, 1, 1)) == true); assert(cxt.get_boolean_value(abs_address_t(0, 2, 1)) == true); assert(cxt.is_empty(abs_address_t(0, 3, 1))); pos.column = 2; string_id_t s_foo = cxt.get_string_identifier(pos); const std::string* p = cxt.get_string(s_foo); assert(p && *p == "foo"); cxt.fill_down_cells(pos, 3); assert(cxt.get_string_identifier(abs_address_t(0, 2, 2)) == s_foo); assert(cxt.get_string_identifier(abs_address_t(0, 3, 2)) == s_foo); assert(cxt.get_string_identifier(abs_address_t(0, 4, 2)) == s_foo); assert(cxt.is_empty(abs_address_t(0, 5, 2))); pos.column = 3; cxt.fill_down_cells(pos, 2); assert(cxt.is_empty(pos)); assert(cxt.is_empty(abs_address_t(0, 2, 3))); assert(cxt.is_empty(abs_address_t(0, 3, 3))); assert(cxt.get_numeric_value(abs_address_t(0, 4, 3)) == 1.1); } void test_model_context_error_value() { cout << "test model context error value" << endl; model_context cxt{{100, 10}}; cxt.append_sheet("test"); auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); assert(resolver); abs_address_t pos(0,3,0); const char* exp = "10/0"; formula_tokens_t tokens = parse_formula_string(cxt, pos, *resolver, exp); formula_cell* fc = cxt.set_formula_cell(pos, std::move(tokens)); fc->interpret(cxt, pos); cell_access ca = cxt.get_cell_access(pos); assert(ca.get_type() == celltype_t::formula); assert(ca.get_value_type() == cell_value_t::error); assert(ca.get_error_value() == formula_error_t::division_by_zero); } void test_volatile_function() { cout << "test volatile function" << endl; model_context cxt{{1048576, 16384}}; auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); assert(resolver); cxt.append_sheet("test"); abs_range_set_t dirty_cells; abs_range_set_t modified_cells; // Set values into A1:A3. cxt.set_numeric_cell(abs_address_t(0,0,0), 1.0); cxt.set_numeric_cell(abs_address_t(0,1,0), 2.0); cxt.set_numeric_cell(abs_address_t(0,2,0), 3.0); // Set formula in A4 that references A1:A3. formula_cell* p = insert_formula(cxt, abs_address_t(0,3,0), "SUM(A1:A3)", *resolver); assert(p); dirty_cells.insert(abs_address_t(0,3,0)); // Initial full calculation. auto sorted = ixion::query_and_sort_dirty_cells(cxt, modified_cells, &dirty_cells); ixion::calculate_sorted_cells(cxt, sorted, 0); double val = cxt.get_numeric_value(abs_address_t(0,3,0)); assert(val == 6); modified_cells.clear(); dirty_cells.clear(); // Modify the value of A2. This should flag A4 dirty. cxt.set_numeric_cell(abs_address_t(0,1,0), 10.0); modified_cells.insert(abs_address_t(0,1,0)); sorted = ixion::query_and_sort_dirty_cells(cxt, modified_cells, &dirty_cells); assert(sorted.size() == 1); // Partial recalculation. ixion::calculate_sorted_cells(cxt, sorted, 0); val = cxt.get_numeric_value(abs_address_t(0, 3, 0)); assert(val == 14); modified_cells.clear(); dirty_cells.clear(); // Insert a volatile cell into B1. At this point B1 should be the only dirty cell. p = insert_formula(cxt, abs_address_t(0,0,1), "NOW()", *resolver); assert(p); dirty_cells.insert(abs_address_t(0,0,1)); sorted = ixion::query_and_sort_dirty_cells(cxt, modified_cells, &dirty_cells); assert(sorted.size() == 1); // Partial recalc again. ixion::calculate_sorted_cells(cxt, sorted, 0); double t1 = cxt.get_numeric_value(abs_address_t(0,0,1)); // Pause for 0.2 second. std::this_thread::sleep_for(std::chrono::milliseconds(200)); // No modification, but B1 should still be flagged dirty. modified_cells.clear(); dirty_cells.clear(); sorted = ixion::query_and_sort_dirty_cells(cxt, modified_cells, &dirty_cells); assert(sorted.size() == 1); ixion::calculate_sorted_cells(cxt, sorted, 0); double t2 = cxt.get_numeric_value(abs_address_t(0,0,1)); double delta = (t2-t1)*24*60*60; cout << "delta = " << delta << endl; // The delta should be close to 0.2. It may be a little larger depending // on the CPU speed. assert(0.2 <= delta && delta <= 0.3); } void test_invalid_formula_tokens() { model_context cxt; std::string_view invalid_formula("invalid formula"); std::string_view error_msg("failed to parse formula"); formula_tokens_t tokens = create_formula_error_tokens(cxt, invalid_formula, error_msg); assert(tokens[0]->get_opcode() == fop_error); assert(tokens.size() == (tokens[0]->get_uint32() + 1)); assert(tokens[1]->get_opcode() == fop_string); string_id_t sid = tokens[1]->get_uint32(); const std::string* s = cxt.get_string(sid); assert(invalid_formula == *s); assert(tokens[2]->get_opcode() == fop_string); sid = tokens[2]->get_uint32(); s = cxt.get_string(sid); assert(error_msg == *s); } void test_grouped_formula_string_results() { model_context cxt; cxt.append_sheet("test"); auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); assert(resolver); abs_range_t A1B2(0, 0, 0, 2, 2); formula_tokens_t tokens = parse_formula_string(cxt, A1B2.first, *resolver, "\"literal string\""); matrix res_value(2, 2, std::string("literal string")); formula_result res(std::move(res_value)); cxt.set_grouped_formula_cells(A1B2, std::move(tokens), std::move(res)); std::string_view s = cxt.get_string_value(A1B2.last); assert(s == "literal string"); } } // anonymous namespace int main() { test_size(); test_string_to_double(); test_string_pool(); test_formula_tokens_store(); test_matrix(); test_matrix_non_numeric_values(); test_name_resolver_calc_a1(); test_name_resolver_excel_a1(); test_name_resolver_named_expression(); test_name_resolver_table_excel_a1(); test_name_resolver_excel_r1c1(); test_name_resolver_odff(); test_name_resolver_odf_cra(); test_address(); test_parse_and_print_expressions(); test_function_name_resolution(); test_model_context_storage(); test_model_context_direct_string_access(); test_model_context_named_expression(); test_model_context_iterator_horizontal(); test_model_context_iterator_horizontal_range(); test_model_context_iterator_vertical(); test_model_context_iterator_vertical_range(); test_model_context_iterator_named_exps(); test_model_context_fill_down(); test_model_context_error_value(); test_volatile_function(); test_invalid_formula_tokens(); test_grouped_formula_string_results(); return EXIT_SUCCESS; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/global.cpp0000664000175000017500000000451214122770261014713 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/global.hpp" #include "ixion/address.hpp" #include "ixion/matrix.hpp" #include "ixion/cell.hpp" #include "ixion/exceptions.hpp" #include "ixion/formula_result.hpp" #include "ixion/interface/formula_model_access.hpp" #include "mem_str_buf.hpp" #include #include #include #include #include using namespace std; namespace ixion { double get_current_time() { unsigned long usec_since_epoch = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); return usec_since_epoch / 1000000.0; } double to_double(std::string_view s) { const char* p = s.data(); std::size_t n = s.size(); if (!n) return 0.0; // First, use the standard C API. const char* p_last_check = p + n; char* p_last; double val = strtod(p, &p_last); if (p_last == p_last_check) return val; // If that fails, do the manual conversion, which may introduce rounding // errors. Revise this to reduce the amount of rounding error. bool dot = false; double frac = 1.0; double sign = 1.0; for (size_t i = 0; i < n; ++i, ++p) { if (i == 0) { if (*p == '+') // Skip this. continue; if (*p == '-') { sign = -1.0; continue; } } if (*p == '.') { if (dot) // Second dot is not allowed. break; dot = true; continue; } if (*p < '0' || '9' < *p) // not a digit. End the parse. break; int digit = *p - '0'; if (dot) { frac *= 0.1; val += digit * frac; } else { val *= 10.0; val += digit; } } return sign*val; } bool to_bool(std::string_view s) { return s == "true"; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_functions.cpp0000664000175000017500000010250014122770261017204 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "formula_functions.hpp" #include "debug.hpp" #include "mem_str_buf.hpp" #include "ixion/formula_tokens.hpp" #include "ixion/matrix.hpp" #include "ixion/interface/formula_model_access.hpp" #include "ixion/macros.hpp" #ifdef max #undef max #endif #ifdef min #undef min #endif #include #include #include #include #include #include #include using namespace std; namespace ixion { namespace { namespace builtin_funcs { typedef mdds::sorted_string_map map_type; // Keys must be sorted. const std::vector entries = { { IXION_ASCII("ABS"), formula_function_t::func_abs }, { IXION_ASCII("ACOS"), formula_function_t::func_acos }, { IXION_ASCII("ACOSH"), formula_function_t::func_acosh }, { IXION_ASCII("ACOT"), formula_function_t::func_acot }, { IXION_ASCII("ACOTH"), formula_function_t::func_acoth }, { IXION_ASCII("ADDRESS"), formula_function_t::func_address }, { IXION_ASCII("AGGREGATE"), formula_function_t::func_aggregate }, { IXION_ASCII("AND"), formula_function_t::func_and }, { IXION_ASCII("ARABIC"), formula_function_t::func_arabic }, { IXION_ASCII("AREAS"), formula_function_t::func_areas }, { IXION_ASCII("ASC"), formula_function_t::func_asc }, { IXION_ASCII("ASIN"), formula_function_t::func_asin }, { IXION_ASCII("ASINH"), formula_function_t::func_asinh }, { IXION_ASCII("ATAN"), formula_function_t::func_atan }, { IXION_ASCII("ATAN2"), formula_function_t::func_atan2 }, { IXION_ASCII("ATANH"), formula_function_t::func_atanh }, { IXION_ASCII("AVEDEV"), formula_function_t::func_avedev }, { IXION_ASCII("AVERAGE"), formula_function_t::func_average }, { IXION_ASCII("AVERAGEA"), formula_function_t::func_averagea }, { IXION_ASCII("AVERAGEIF"), formula_function_t::func_averageif }, { IXION_ASCII("AVERAGEIFS"), formula_function_t::func_averageifs }, { IXION_ASCII("B"), formula_function_t::func_b }, { IXION_ASCII("BAHTTEXT"), formula_function_t::func_bahttext }, { IXION_ASCII("BASE"), formula_function_t::func_base }, { IXION_ASCII("BETADIST"), formula_function_t::func_betadist }, { IXION_ASCII("BETAINV"), formula_function_t::func_betainv }, { IXION_ASCII("BINOMDIST"), formula_function_t::func_binomdist }, { IXION_ASCII("BITAND"), formula_function_t::func_bitand }, { IXION_ASCII("BITLSHIFT"), formula_function_t::func_bitlshift }, { IXION_ASCII("BITOR"), formula_function_t::func_bitor }, { IXION_ASCII("BITRSHIFT"), formula_function_t::func_bitrshift }, { IXION_ASCII("BITXOR"), formula_function_t::func_bitxor }, { IXION_ASCII("CEILING"), formula_function_t::func_ceiling }, { IXION_ASCII("CELL"), formula_function_t::func_cell }, { IXION_ASCII("CHAR"), formula_function_t::func_char }, { IXION_ASCII("CHIDIST"), formula_function_t::func_chidist }, { IXION_ASCII("CHIINV"), formula_function_t::func_chiinv }, { IXION_ASCII("CHISQDIST"), formula_function_t::func_chisqdist }, { IXION_ASCII("CHISQINV"), formula_function_t::func_chisqinv }, { IXION_ASCII("CHITEST"), formula_function_t::func_chitest }, { IXION_ASCII("CHOOSE"), formula_function_t::func_choose }, { IXION_ASCII("CLEAN"), formula_function_t::func_clean }, { IXION_ASCII("CODE"), formula_function_t::func_code }, { IXION_ASCII("COLOR"), formula_function_t::func_color }, { IXION_ASCII("COLUMN"), formula_function_t::func_column }, { IXION_ASCII("COLUMNS"), formula_function_t::func_columns }, { IXION_ASCII("COMBIN"), formula_function_t::func_combin }, { IXION_ASCII("COMBINA"), formula_function_t::func_combina }, { IXION_ASCII("CONCAT"), formula_function_t::func_concat }, { IXION_ASCII("CONCATENATE"), formula_function_t::func_concatenate }, { IXION_ASCII("CONFIDENCE"), formula_function_t::func_confidence }, { IXION_ASCII("CORREL"), formula_function_t::func_correl }, { IXION_ASCII("COS"), formula_function_t::func_cos }, { IXION_ASCII("COSH"), formula_function_t::func_cosh }, { IXION_ASCII("COT"), formula_function_t::func_cot }, { IXION_ASCII("COTH"), formula_function_t::func_coth }, { IXION_ASCII("COUNT"), formula_function_t::func_count }, { IXION_ASCII("COUNTA"), formula_function_t::func_counta }, { IXION_ASCII("COUNTBLANK"), formula_function_t::func_countblank }, { IXION_ASCII("COUNTIF"), formula_function_t::func_countif }, { IXION_ASCII("COUNTIFS"), formula_function_t::func_countifs }, { IXION_ASCII("COVAR"), formula_function_t::func_covar }, { IXION_ASCII("CRITBINOM"), formula_function_t::func_critbinom }, { IXION_ASCII("CSC"), formula_function_t::func_csc }, { IXION_ASCII("CSCH"), formula_function_t::func_csch }, { IXION_ASCII("CUMIPMT"), formula_function_t::func_cumipmt }, { IXION_ASCII("CUMPRINC"), formula_function_t::func_cumprinc }, { IXION_ASCII("CURRENT"), formula_function_t::func_current }, { IXION_ASCII("DATE"), formula_function_t::func_date }, { IXION_ASCII("DATEDIF"), formula_function_t::func_datedif }, { IXION_ASCII("DATEVALUE"), formula_function_t::func_datevalue }, { IXION_ASCII("DAVERAGE"), formula_function_t::func_daverage }, { IXION_ASCII("DAY"), formula_function_t::func_day }, { IXION_ASCII("DAYS"), formula_function_t::func_days }, { IXION_ASCII("DAYS360"), formula_function_t::func_days360 }, { IXION_ASCII("DB"), formula_function_t::func_db }, { IXION_ASCII("DCOUNT"), formula_function_t::func_dcount }, { IXION_ASCII("DCOUNTA"), formula_function_t::func_dcounta }, { IXION_ASCII("DDB"), formula_function_t::func_ddb }, { IXION_ASCII("DDE"), formula_function_t::func_dde }, { IXION_ASCII("DECIMAL"), formula_function_t::func_decimal }, { IXION_ASCII("DEGREES"), formula_function_t::func_degrees }, { IXION_ASCII("DEVSQ"), formula_function_t::func_devsq }, { IXION_ASCII("DGET"), formula_function_t::func_dget }, { IXION_ASCII("DMAX"), formula_function_t::func_dmax }, { IXION_ASCII("DMIN"), formula_function_t::func_dmin }, { IXION_ASCII("DOLLAR"), formula_function_t::func_dollar }, { IXION_ASCII("DPRODUCT"), formula_function_t::func_dproduct }, { IXION_ASCII("DSTDEV"), formula_function_t::func_dstdev }, { IXION_ASCII("DSTDEVP"), formula_function_t::func_dstdevp }, { IXION_ASCII("DSUM"), formula_function_t::func_dsum }, { IXION_ASCII("DVAR"), formula_function_t::func_dvar }, { IXION_ASCII("DVARP"), formula_function_t::func_dvarp }, { IXION_ASCII("EASTERSUNDAY"), formula_function_t::func_eastersunday }, { IXION_ASCII("EFFECT"), formula_function_t::func_effect }, { IXION_ASCII("ENCODEURL"), formula_function_t::func_encodeurl }, { IXION_ASCII("ERRORTYPE"), formula_function_t::func_errortype }, { IXION_ASCII("EUROCONVERT"), formula_function_t::func_euroconvert }, { IXION_ASCII("EVEN"), formula_function_t::func_even }, { IXION_ASCII("EXACT"), formula_function_t::func_exact }, { IXION_ASCII("EXP"), formula_function_t::func_exp }, { IXION_ASCII("EXPONDIST"), formula_function_t::func_expondist }, { IXION_ASCII("FACT"), formula_function_t::func_fact }, { IXION_ASCII("FALSE"), formula_function_t::func_false }, { IXION_ASCII("FDIST"), formula_function_t::func_fdist }, { IXION_ASCII("FILTERXML"), formula_function_t::func_filterxml }, { IXION_ASCII("FIND"), formula_function_t::func_find }, { IXION_ASCII("FINDB"), formula_function_t::func_findb }, { IXION_ASCII("FINV"), formula_function_t::func_finv }, { IXION_ASCII("FISHER"), formula_function_t::func_fisher }, { IXION_ASCII("FISHERINV"), formula_function_t::func_fisherinv }, { IXION_ASCII("FIXED"), formula_function_t::func_fixed }, { IXION_ASCII("FLOOR"), formula_function_t::func_floor }, { IXION_ASCII("FORECAST"), formula_function_t::func_forecast }, { IXION_ASCII("FORMULA"), formula_function_t::func_formula }, { IXION_ASCII("FOURIER"), formula_function_t::func_fourier }, { IXION_ASCII("FREQUENCY"), formula_function_t::func_frequency }, { IXION_ASCII("FTEST"), formula_function_t::func_ftest }, { IXION_ASCII("FV"), formula_function_t::func_fv }, { IXION_ASCII("GAMMA"), formula_function_t::func_gamma }, { IXION_ASCII("GAMMADIST"), formula_function_t::func_gammadist }, { IXION_ASCII("GAMMAINV"), formula_function_t::func_gammainv }, { IXION_ASCII("GAMMALN"), formula_function_t::func_gammaln }, { IXION_ASCII("GAUSS"), formula_function_t::func_gauss }, { IXION_ASCII("GCD"), formula_function_t::func_gcd }, { IXION_ASCII("GEOMEAN"), formula_function_t::func_geomean }, { IXION_ASCII("GETPIVOTDATA"), formula_function_t::func_getpivotdata }, { IXION_ASCII("GOALSEEK"), formula_function_t::func_goalseek }, { IXION_ASCII("GROWTH"), formula_function_t::func_growth }, { IXION_ASCII("HARMEAN"), formula_function_t::func_harmean }, { IXION_ASCII("HLOOKUP"), formula_function_t::func_hlookup }, { IXION_ASCII("HOUR"), formula_function_t::func_hour }, { IXION_ASCII("HYPERLINK"), formula_function_t::func_hyperlink }, { IXION_ASCII("HYPGEOMDIST"), formula_function_t::func_hypgeomdist }, { IXION_ASCII("IF"), formula_function_t::func_if }, { IXION_ASCII("IFERROR"), formula_function_t::func_iferror }, { IXION_ASCII("IFNA"), formula_function_t::func_ifna }, { IXION_ASCII("IFS"), formula_function_t::func_ifs }, { IXION_ASCII("INDEX"), formula_function_t::func_index }, { IXION_ASCII("INDIRECT"), formula_function_t::func_indirect }, { IXION_ASCII("INFO"), formula_function_t::func_info }, { IXION_ASCII("INT"), formula_function_t::func_int }, { IXION_ASCII("INTERCEPT"), formula_function_t::func_intercept }, { IXION_ASCII("IPMT"), formula_function_t::func_ipmt }, { IXION_ASCII("IRR"), formula_function_t::func_irr }, { IXION_ASCII("ISBLANK"), formula_function_t::func_isblank }, { IXION_ASCII("ISERR"), formula_function_t::func_iserr }, { IXION_ASCII("ISERROR"), formula_function_t::func_iserror }, { IXION_ASCII("ISEVEN"), formula_function_t::func_iseven }, { IXION_ASCII("ISFORMULA"), formula_function_t::func_isformula }, { IXION_ASCII("ISLOGICAL"), formula_function_t::func_islogical }, { IXION_ASCII("ISNA"), formula_function_t::func_isna }, { IXION_ASCII("ISNONTEXT"), formula_function_t::func_isnontext }, { IXION_ASCII("ISNUMBER"), formula_function_t::func_isnumber }, { IXION_ASCII("ISODD"), formula_function_t::func_isodd }, { IXION_ASCII("ISOWEEKNUM"), formula_function_t::func_isoweeknum }, { IXION_ASCII("ISPMT"), formula_function_t::func_ispmt }, { IXION_ASCII("ISREF"), formula_function_t::func_isref }, { IXION_ASCII("ISTEXT"), formula_function_t::func_istext }, { IXION_ASCII("JIS"), formula_function_t::func_jis }, { IXION_ASCII("KURT"), formula_function_t::func_kurt }, { IXION_ASCII("LARGE"), formula_function_t::func_large }, { IXION_ASCII("LCM"), formula_function_t::func_lcm }, { IXION_ASCII("LEFT"), formula_function_t::func_left }, { IXION_ASCII("LEFTB"), formula_function_t::func_leftb }, { IXION_ASCII("LEN"), formula_function_t::func_len }, { IXION_ASCII("LENB"), formula_function_t::func_lenb }, { IXION_ASCII("LINEST"), formula_function_t::func_linest }, { IXION_ASCII("LN"), formula_function_t::func_ln }, { IXION_ASCII("LOG"), formula_function_t::func_log }, { IXION_ASCII("LOG10"), formula_function_t::func_log10 }, { IXION_ASCII("LOGEST"), formula_function_t::func_logest }, { IXION_ASCII("LOGINV"), formula_function_t::func_loginv }, { IXION_ASCII("LOGNORMDIST"), formula_function_t::func_lognormdist }, { IXION_ASCII("LOOKUP"), formula_function_t::func_lookup }, { IXION_ASCII("LOWER"), formula_function_t::func_lower }, { IXION_ASCII("MATCH"), formula_function_t::func_match }, { IXION_ASCII("MAX"), formula_function_t::func_max }, { IXION_ASCII("MAXA"), formula_function_t::func_maxa }, { IXION_ASCII("MAXIFS"), formula_function_t::func_maxifs }, { IXION_ASCII("MDETERM"), formula_function_t::func_mdeterm }, { IXION_ASCII("MEDIAN"), formula_function_t::func_median }, { IXION_ASCII("MID"), formula_function_t::func_mid }, { IXION_ASCII("MIDB"), formula_function_t::func_midb }, { IXION_ASCII("MIN"), formula_function_t::func_min }, { IXION_ASCII("MINA"), formula_function_t::func_mina }, { IXION_ASCII("MINIFS"), formula_function_t::func_minifs }, { IXION_ASCII("MINUTE"), formula_function_t::func_minute }, { IXION_ASCII("MINVERSE"), formula_function_t::func_minverse }, { IXION_ASCII("MIRR"), formula_function_t::func_mirr }, { IXION_ASCII("MMULT"), formula_function_t::func_mmult }, { IXION_ASCII("MOD"), formula_function_t::func_mod }, { IXION_ASCII("MODE"), formula_function_t::func_mode }, { IXION_ASCII("MONTH"), formula_function_t::func_month }, { IXION_ASCII("MULTIRANGE"), formula_function_t::func_multirange }, { IXION_ASCII("MUNIT"), formula_function_t::func_munit }, { IXION_ASCII("MVALUE"), formula_function_t::func_mvalue }, { IXION_ASCII("N"), formula_function_t::func_n }, { IXION_ASCII("NA"), formula_function_t::func_na }, { IXION_ASCII("NEG"), formula_function_t::func_neg }, { IXION_ASCII("NEGBINOMDIST"), formula_function_t::func_negbinomdist }, { IXION_ASCII("NETWORKDAYS"), formula_function_t::func_networkdays }, { IXION_ASCII("NOMINAL"), formula_function_t::func_nominal }, { IXION_ASCII("NORMDIST"), formula_function_t::func_normdist }, { IXION_ASCII("NORMINV"), formula_function_t::func_norminv }, { IXION_ASCII("NORMSDIST"), formula_function_t::func_normsdist }, { IXION_ASCII("NORMSINV"), formula_function_t::func_normsinv }, { IXION_ASCII("NOT"), formula_function_t::func_not }, { IXION_ASCII("NOW"), formula_function_t::func_now }, { IXION_ASCII("NPER"), formula_function_t::func_nper }, { IXION_ASCII("NPV"), formula_function_t::func_npv }, { IXION_ASCII("NUMBERVALUE"), formula_function_t::func_numbervalue }, { IXION_ASCII("ODD"), formula_function_t::func_odd }, { IXION_ASCII("OFFSET"), formula_function_t::func_offset }, { IXION_ASCII("OR"), formula_function_t::func_or }, { IXION_ASCII("PDURATION"), formula_function_t::func_pduration }, { IXION_ASCII("PEARSON"), formula_function_t::func_pearson }, { IXION_ASCII("PERCENTILE"), formula_function_t::func_percentile }, { IXION_ASCII("PERCENTRANK"), formula_function_t::func_percentrank }, { IXION_ASCII("PERMUT"), formula_function_t::func_permut }, { IXION_ASCII("PERMUTATIONA"), formula_function_t::func_permutationa }, { IXION_ASCII("PHI"), formula_function_t::func_phi }, { IXION_ASCII("PI"), formula_function_t::func_pi }, { IXION_ASCII("PMT"), formula_function_t::func_pmt }, { IXION_ASCII("POISSON"), formula_function_t::func_poisson }, { IXION_ASCII("POWER"), formula_function_t::func_power }, { IXION_ASCII("PPMT"), formula_function_t::func_ppmt }, { IXION_ASCII("PROB"), formula_function_t::func_prob }, { IXION_ASCII("PRODUCT"), formula_function_t::func_product }, { IXION_ASCII("PROPER"), formula_function_t::func_proper }, { IXION_ASCII("PV"), formula_function_t::func_pv }, { IXION_ASCII("QUARTILE"), formula_function_t::func_quartile }, { IXION_ASCII("RADIANS"), formula_function_t::func_radians }, { IXION_ASCII("RAND"), formula_function_t::func_rand }, { IXION_ASCII("RANK"), formula_function_t::func_rank }, { IXION_ASCII("RATE"), formula_function_t::func_rate }, { IXION_ASCII("RAWSUBTRACT"), formula_function_t::func_rawsubtract }, { IXION_ASCII("REGEX"), formula_function_t::func_regex }, { IXION_ASCII("REPLACE"), formula_function_t::func_replace }, { IXION_ASCII("REPLACEB"), formula_function_t::func_replaceb }, { IXION_ASCII("REPT"), formula_function_t::func_rept }, { IXION_ASCII("RIGHT"), formula_function_t::func_right }, { IXION_ASCII("RIGHTB"), formula_function_t::func_rightb }, { IXION_ASCII("ROMAN"), formula_function_t::func_roman }, { IXION_ASCII("ROUND"), formula_function_t::func_round }, { IXION_ASCII("ROUNDDOWN"), formula_function_t::func_rounddown }, { IXION_ASCII("ROUNDSIG"), formula_function_t::func_roundsig }, { IXION_ASCII("ROUNDUP"), formula_function_t::func_roundup }, { IXION_ASCII("ROW"), formula_function_t::func_row }, { IXION_ASCII("ROWS"), formula_function_t::func_rows }, { IXION_ASCII("RRI"), formula_function_t::func_rri }, { IXION_ASCII("RSQ"), formula_function_t::func_rsq }, { IXION_ASCII("SEARCH"), formula_function_t::func_search }, { IXION_ASCII("SEARCHB"), formula_function_t::func_searchb }, { IXION_ASCII("SEC"), formula_function_t::func_sec }, { IXION_ASCII("SECH"), formula_function_t::func_sech }, { IXION_ASCII("SECOND"), formula_function_t::func_second }, { IXION_ASCII("SHEET"), formula_function_t::func_sheet }, { IXION_ASCII("SHEETS"), formula_function_t::func_sheets }, { IXION_ASCII("SIGN"), formula_function_t::func_sign }, { IXION_ASCII("SIN"), formula_function_t::func_sin }, { IXION_ASCII("SINH"), formula_function_t::func_sinh }, { IXION_ASCII("SKEW"), formula_function_t::func_skew }, { IXION_ASCII("SKEWP"), formula_function_t::func_skewp }, { IXION_ASCII("SLN"), formula_function_t::func_sln }, { IXION_ASCII("SLOPE"), formula_function_t::func_slope }, { IXION_ASCII("SMALL"), formula_function_t::func_small }, { IXION_ASCII("SQRT"), formula_function_t::func_sqrt }, { IXION_ASCII("STANDARDIZE"), formula_function_t::func_standardize }, { IXION_ASCII("STDEV"), formula_function_t::func_stdev }, { IXION_ASCII("STDEVA"), formula_function_t::func_stdeva }, { IXION_ASCII("STDEVP"), formula_function_t::func_stdevp }, { IXION_ASCII("STDEVPA"), formula_function_t::func_stdevpa }, { IXION_ASCII("STEYX"), formula_function_t::func_steyx }, { IXION_ASCII("STYLE"), formula_function_t::func_style }, { IXION_ASCII("SUBSTITUTE"), formula_function_t::func_substitute }, { IXION_ASCII("SUBTOTAL"), formula_function_t::func_subtotal }, { IXION_ASCII("SUM"), formula_function_t::func_sum }, { IXION_ASCII("SUMIF"), formula_function_t::func_sumif }, { IXION_ASCII("SUMIFS"), formula_function_t::func_sumifs }, { IXION_ASCII("SUMPRODUCT"), formula_function_t::func_sumproduct }, { IXION_ASCII("SUMSQ"), formula_function_t::func_sumsq }, { IXION_ASCII("SUMX2MY2"), formula_function_t::func_sumx2my2 }, { IXION_ASCII("SUMX2PY2"), formula_function_t::func_sumx2py2 }, { IXION_ASCII("SUMXMY2"), formula_function_t::func_sumxmy2 }, { IXION_ASCII("SWITCH"), formula_function_t::func_switch }, { IXION_ASCII("SYD"), formula_function_t::func_syd }, { IXION_ASCII("T"), formula_function_t::func_t }, { IXION_ASCII("TAN"), formula_function_t::func_tan }, { IXION_ASCII("TANH"), formula_function_t::func_tanh }, { IXION_ASCII("TDIST"), formula_function_t::func_tdist }, { IXION_ASCII("TEXT"), formula_function_t::func_text }, { IXION_ASCII("TEXTJOIN"), formula_function_t::func_textjoin }, { IXION_ASCII("TIME"), formula_function_t::func_time }, { IXION_ASCII("TIMEVALUE"), formula_function_t::func_timevalue }, { IXION_ASCII("TINV"), formula_function_t::func_tinv }, { IXION_ASCII("TODAY"), formula_function_t::func_today }, { IXION_ASCII("TRANSPOSE"), formula_function_t::func_transpose }, { IXION_ASCII("TREND"), formula_function_t::func_trend }, { IXION_ASCII("TRIM"), formula_function_t::func_trim }, { IXION_ASCII("TRIMMEAN"), formula_function_t::func_trimmean }, { IXION_ASCII("TRUE"), formula_function_t::func_true }, { IXION_ASCII("TRUNC"), formula_function_t::func_trunc }, { IXION_ASCII("TTEST"), formula_function_t::func_ttest }, { IXION_ASCII("TYPE"), formula_function_t::func_type }, { IXION_ASCII("UNICHAR"), formula_function_t::func_unichar }, { IXION_ASCII("UNICODE"), formula_function_t::func_unicode }, { IXION_ASCII("UPPER"), formula_function_t::func_upper }, { IXION_ASCII("VALUE"), formula_function_t::func_value }, { IXION_ASCII("VAR"), formula_function_t::func_var }, { IXION_ASCII("VARA"), formula_function_t::func_vara }, { IXION_ASCII("VARP"), formula_function_t::func_varp }, { IXION_ASCII("VARPA"), formula_function_t::func_varpa }, { IXION_ASCII("VDB"), formula_function_t::func_vdb }, { IXION_ASCII("VLOOKUP"), formula_function_t::func_vlookup }, { IXION_ASCII("WAIT"), formula_function_t::func_wait }, { IXION_ASCII("WEBSERVICE"), formula_function_t::func_webservice }, { IXION_ASCII("WEEKDAY"), formula_function_t::func_weekday }, { IXION_ASCII("WEEKNUM"), formula_function_t::func_weeknum }, { IXION_ASCII("WEIBULL"), formula_function_t::func_weibull }, { IXION_ASCII("XOR"), formula_function_t::func_xor }, { IXION_ASCII("YEAR"), formula_function_t::func_year }, { IXION_ASCII("ZTEST"), formula_function_t::func_ztest }, }; const map_type& get() { static map_type mt(entries.data(), entries.size(), formula_function_t::func_unknown); return mt; } } // builtin_funcs namespace std::string_view unknown_func_name = "unknown"; /** * Traverse all elements of a passed matrix to sum up their values. */ double sum_matrix_elements(const matrix& mx) { double sum = 0.0; size_t rows = mx.row_size(); size_t cols = mx.col_size(); for (size_t row = 0; row < rows; ++row) for (size_t col = 0; col < cols; ++col) sum += mx.get_numeric(row, col); return sum; } numeric_matrix multiply_matrices(const matrix& left, const matrix& right) { // The column size of the left matrix must equal the row size of the right // matrix. size_t n = left.col_size(); if (n != right.row_size()) throw formula_error(formula_error_t::invalid_expression); numeric_matrix left_nm = left.as_numeric(); numeric_matrix right_nm = right.as_numeric(); numeric_matrix output(left_nm.row_size(), right_nm.col_size()); for (size_t row = 0; row < output.row_size(); ++row) { for (size_t col = 0; col < output.col_size(); ++col) { double v = 0.0; for (size_t i = 0; i < n; ++i) v += left_nm(row, i) * right_nm(i, col); output(row, col) = v; } } return output; } } // anonymous namespace // ============================================================================ formula_functions::invalid_arg::invalid_arg(const string& msg) : general_error(msg) {} formula_function_t formula_functions::get_function_opcode(const formula_token& token) { assert(token.get_opcode() == fop_function); return static_cast(token.get_uint32()); } formula_function_t formula_functions::get_function_opcode(std::string_view s) { std::string upper; for (char c : s) { if (c > 'Z') { // Convert to upper case. c -= 'a' - 'A'; } upper.push_back(c); } return builtin_funcs::get().find(upper.data(), upper.size()); } std::string_view formula_functions::get_function_name(formula_function_t oc) { for (const builtin_funcs::map_type::entry& e : builtin_funcs::entries) { if (e.value == oc) return e.key; } return unknown_func_name; } formula_functions::formula_functions(iface::formula_model_access& cxt) : m_context(cxt) { } formula_functions::~formula_functions() { } void formula_functions::interpret(formula_function_t oc, formula_value_stack& args) { switch (oc) { case formula_function_t::func_average: fnc_average(args); break; case formula_function_t::func_concatenate: fnc_concatenate(args); break; case formula_function_t::func_counta: fnc_counta(args); break; case formula_function_t::func_if: fnc_if(args); break; case formula_function_t::func_int: fnc_int(args); break; case formula_function_t::func_left: fnc_left(args); break; case formula_function_t::func_len: fnc_len(args); break; case formula_function_t::func_max: fnc_max(args); break; case formula_function_t::func_min: fnc_min(args); break; case formula_function_t::func_mmult: fnc_mmult(args); break; case formula_function_t::func_now: fnc_now(args); break; case formula_function_t::func_pi: fnc_pi(args); break; case formula_function_t::func_subtotal: fnc_subtotal(args); break; case formula_function_t::func_sum: fnc_sum(args); break; case formula_function_t::func_wait: fnc_wait(args); break; case formula_function_t::func_unknown: default: { std::ostringstream os; os << "formula function not implemented yet (name=" << get_formula_function_name(oc) << ")"; throw not_implemented_error(os.str()); } } } void formula_functions::fnc_max(formula_value_stack& args) const { if (args.empty()) throw formula_functions::invalid_arg("MAX requires one or more arguments."); double ret = args.pop_value(); while (!args.empty()) { double v = args.pop_value(); if (v > ret) ret = v; } args.push_value(ret); } void formula_functions::fnc_min(formula_value_stack& args) const { if (args.empty()) throw formula_functions::invalid_arg("MIN requires one or more arguments."); double ret = args.pop_value(); while (!args.empty()) { double v = args.pop_value(); if (v < ret) ret = v; } args.push_value(ret); } void formula_functions::fnc_sum(formula_value_stack& args) const { IXION_TRACE("function: sum"); if (args.empty()) throw formula_functions::invalid_arg("SUM requires one or more arguments."); double ret = 0; while (!args.empty()) { switch (args.get_type()) { case stack_value_t::range_ref: ret += sum_matrix_elements(args.pop_range_value()); break; case stack_value_t::single_ref: case stack_value_t::string: case stack_value_t::value: default: ret += args.pop_value(); } } args.push_value(ret); IXION_TRACE("function: sum end (result=" << ret << ")"); } void formula_functions::fnc_counta(formula_value_stack& args) const { if (args.empty()) throw formula_functions::invalid_arg("COUNTA requires one or more arguments."); double ret = 0; while (!args.empty()) { switch (args.get_type()) { case stack_value_t::string: case stack_value_t::value: args.pop_value(); ++ret; break; case stack_value_t::range_ref: { abs_range_t range = args.pop_range_ref(); ret += m_context.count_range(range, value_numeric | value_boolean | value_string); } break; case stack_value_t::single_ref: { abs_address_t pos = args.pop_single_ref(); abs_range_t range; range.first = range.last = pos; ret += m_context.count_range(range, value_numeric | value_boolean | value_string); } break; default: args.pop_value(); } } args.push_value(ret); } void formula_functions::fnc_average(formula_value_stack& args) const { if (args.empty()) throw formula_functions::invalid_arg("AVERAGE requires one or more arguments."); double ret = 0; double count = 0.0; while (!args.empty()) { switch (args.get_type()) { case stack_value_t::range_ref: { matrix mx = args.pop_range_value(); size_t rows = mx.row_size(); size_t cols = mx.col_size(); for (size_t r = 0; r < rows; ++r) { for (size_t c = 0; c < cols; ++c) { if (!mx.is_numeric(r, c)) continue; ret += mx.get_numeric(r, c); ++count; } } } break; case stack_value_t::single_ref: case stack_value_t::string: case stack_value_t::value: default: ret += args.pop_value(); ++count; } } args.push_value(ret/count); } void formula_functions::fnc_mmult(formula_value_stack& args) const { matrix mx[2]; matrix* mxp = mx; const matrix* mxp_end = mxp + 2; bool is_arg_invalid = false; // NB : the stack is LIFO i.e. the first matrix is the right matrix and // the second one is the left one. while (!args.empty()) { switch (args.get_type()) { case stack_value_t::range_ref: { if (mxp == mxp_end) { is_arg_invalid = true; break; } matrix m = args.pop_range_value(); mxp->swap(m); ++mxp; break; } default: is_arg_invalid = true; } if (is_arg_invalid) break; } if (mxp != mxp_end) is_arg_invalid = true; if (is_arg_invalid) throw formula_functions::invalid_arg("MMULT requires exactly two ranges."); mx[0].swap(mx[1]); // Make it so that 0 -> left and 1 -> right. if (!mx[0].is_numeric() || !mx[1].is_numeric()) throw formula_functions::invalid_arg( "MMULT requires two numeric ranges. At least one range is not numeric."); numeric_matrix ans = multiply_matrices(mx[0], mx[1]); args.push_matrix(ans); } void formula_functions::fnc_pi(formula_value_stack& args) const { if (!args.empty()) throw formula_functions::invalid_arg("PI takes no arguments."); args.push_value(M_PI); } void formula_functions::fnc_int(formula_value_stack& args) const { if (args.size() != 1) throw formula_functions::invalid_arg("INT requires exactly 1 argument."); double v = args.pop_value(); args.push_value(std::floor(v)); } void formula_functions::fnc_if(formula_value_stack& args) const { if (args.size() != 3) throw formula_functions::invalid_arg("IF requires exactly 3 arguments."); formula_value_stack::iterator pos = args.begin(); bool eval = args.get_value(0) != 0.0; if (eval) std::advance(pos, 1); else std::advance(pos, 2); formula_value_stack ret(m_context); ret.push_back(args.release(pos)); args.swap(ret); } void formula_functions::fnc_len(formula_value_stack& args) const { if (args.size() != 1) throw formula_functions::invalid_arg("LEN requires exactly one argument."); string s = args.pop_string(); args.clear(); args.push_value(s.size()); } void formula_functions::fnc_concatenate(formula_value_stack& args) const { string s; while (!args.empty()) s = args.pop_string() + s; args.push_string(std::move(s)); } void formula_functions::fnc_left(formula_value_stack& args) const { if (args.empty() || args.size() > 2) throw formula_functions::invalid_arg( "LEFT requires at least one argument but no more than 2."); size_t n = 1; // when the 2nd arg is skipped, it defaults to 1. if (args.size() == 2) n = std::floor(args.pop_value()); string s = args.pop_string(); // Resize ONLY when the desired length is lower than the original string length. if (n < s.size()) s.resize(n); args.push_string(std::move(s)); } void formula_functions::fnc_now(formula_value_stack& args) const { if (!args.empty()) throw formula_functions::invalid_arg("NOW takes no arguments."); // TODO: this value is currently not accurate since we don't take into // account the zero date yet. double cur_time = get_current_time(); cur_time /= 86400.0; // convert seconds to days. args.push_value(cur_time); } void formula_functions::fnc_wait(formula_value_stack& args) const { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); args.clear(); args.push_value(1); } void formula_functions::fnc_subtotal(formula_value_stack& args) const { if (args.size() != 2) throw formula_functions::invalid_arg("SUBTOTAL requires exactly 2 arguments."); abs_range_t range = args.pop_range_ref(); int subtype = args.pop_value(); switch (subtype) { case 109: { // SUM matrix mx = m_context.get_range_value(range); args.push_value(sum_matrix_elements(mx)); break; } default: { std::ostringstream os; os << "SUBTOTAL: function type " << subtype << " not implemented yet"; throw formula_functions::invalid_arg(os.str()); } } } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/model_context.cpp0000664000175000017500000002466714122770261016334 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/model_context.hpp" #include "ixion/formula_result.hpp" #include "ixion/matrix.hpp" #include "ixion/model_iterator.hpp" #include "ixion/interface/session_handler.hpp" #include "ixion/named_expressions_iterator.hpp" #include "ixion/cell_access.hpp" #include "model_context_impl.hpp" namespace ixion { model_context::input_cell::input_cell(std::nullptr_t) : type(celltype_t::empty) {} model_context::input_cell::input_cell(bool b) : type(celltype_t::boolean) { value = b; } model_context::input_cell::input_cell(const char* s) : type(celltype_t::string) { value = std::string_view(s); } model_context::input_cell::input_cell(double v) : type(celltype_t::numeric) { value = v; } model_context::input_cell::input_cell(const input_cell& other) : type(other.type), value(other.value) { } model_context::input_row::input_row(std::initializer_list cells) : m_cells(std::move(cells)) { } const std::initializer_list& model_context::input_row::cells() const { return m_cells; } std::unique_ptr model_context::session_handler_factory::create() { return std::unique_ptr(); } model_context::session_handler_factory::~session_handler_factory() {} model_context::model_context() : mp_impl(new detail::model_context_impl(*this, {1048576, 16384})) {} model_context::model_context(const rc_size_t& sheet_size) : mp_impl(new detail::model_context_impl(*this, sheet_size)) {} model_context::~model_context() { } formula_result_wait_policy_t model_context::get_formula_result_wait_policy() const { return mp_impl->get_formula_result_wait_policy(); } void model_context::notify(formula_event_t event) { mp_impl->notify(event); } const config& model_context::get_config() const { return mp_impl->get_config(); } dirty_cell_tracker& model_context::get_cell_tracker() { return mp_impl->get_cell_tracker(); } const dirty_cell_tracker& model_context::get_cell_tracker() const { return mp_impl->get_cell_tracker(); } void model_context::empty_cell(const abs_address_t& addr) { mp_impl->empty_cell(addr); } void model_context::set_numeric_cell(const abs_address_t& addr, double val) { mp_impl->set_numeric_cell(addr, val); } void model_context::set_boolean_cell(const abs_address_t& addr, bool val) { mp_impl->set_boolean_cell(addr, val); } void model_context::set_string_cell(const abs_address_t& addr, std::string_view s) { mp_impl->set_string_cell(addr, s); } cell_access model_context::get_cell_access(const abs_address_t& addr) const { return cell_access(*this, addr); } void model_context::fill_down_cells(const abs_address_t& src, size_t n_dst) { mp_impl->fill_down_cells(src, n_dst); } void model_context::set_string_cell(const abs_address_t& addr, string_id_t identifier) { mp_impl->set_string_cell(addr, identifier); } formula_cell* model_context::set_formula_cell(const abs_address_t& addr, formula_tokens_t tokens) { formula_tokens_store_ptr_t ts = formula_tokens_store::create(); ts->get() = std::move(tokens); return mp_impl->set_formula_cell(addr, ts); } formula_cell* model_context::set_formula_cell( const abs_address_t& addr, const formula_tokens_store_ptr_t& tokens) { return mp_impl->set_formula_cell(addr, tokens); } formula_cell* model_context::set_formula_cell( const abs_address_t& addr, const formula_tokens_store_ptr_t& tokens, formula_result result) { return mp_impl->set_formula_cell(addr, tokens, std::move(result)); } void model_context::set_grouped_formula_cells( const abs_range_t& group_range, formula_tokens_t tokens) { mp_impl->set_grouped_formula_cells(group_range, std::move(tokens)); } void model_context::set_grouped_formula_cells( const abs_range_t& group_range, formula_tokens_t tokens, formula_result result) { mp_impl->set_grouped_formula_cells(group_range, std::move(tokens), std::move(result)); } abs_range_t model_context::get_data_range(sheet_t sheet) const { return mp_impl->get_data_range(sheet); } bool model_context::is_empty(const abs_address_t& addr) const { return mp_impl->is_empty(addr); } celltype_t model_context::get_celltype(const abs_address_t& addr) const { return mp_impl->get_celltype(addr); } double model_context::get_numeric_value(const abs_address_t& addr) const { return mp_impl->get_numeric_value(addr); } bool model_context::get_boolean_value(const abs_address_t& addr) const { return mp_impl->get_boolean_value(addr); } void model_context::set_sheet_size(const rc_size_t& sheet_size) { mp_impl->set_sheet_size(sheet_size); } void model_context::set_config(const config& cfg) { mp_impl->set_config(cfg); } string_id_t model_context::get_string_identifier(const abs_address_t& addr) const { return mp_impl->get_string_identifier(addr); } std::string_view model_context::get_string_value(const abs_address_t& addr) const { return mp_impl->get_string_value(addr); } const formula_cell* model_context::get_formula_cell(const abs_address_t& addr) const { return mp_impl->get_formula_cell(addr); } formula_cell* model_context::get_formula_cell(const abs_address_t& addr) { return mp_impl->get_formula_cell(addr); } formula_result model_context::get_formula_result(const abs_address_t& addr) const { return mp_impl->get_formula_result(addr); } double model_context::count_range(const abs_range_t& range, const values_t& values_type) const { return mp_impl->count_range(range, values_type); } matrix model_context::get_range_value(const abs_range_t& range) const { if (range.first.sheet != range.last.sheet) throw general_error("multi-sheet range is not allowed."); if (!range.valid()) { std::ostringstream os; os << "invalid range: " << range; throw std::invalid_argument(os.str()); } rc_size_t sheet_size = get_sheet_size(); abs_range_t range_clipped = range; if (range_clipped.all_rows()) { range_clipped.first.row = 0; range_clipped.last.row = sheet_size.row - 1; } if (range_clipped.all_columns()) { range_clipped.first.column = 0; range_clipped.last.column = sheet_size.column - 1; } row_t rows = range_clipped.last.row - range_clipped.first.row + 1; col_t cols = range_clipped.last.column - range_clipped.first.column + 1; matrix ret(rows, cols); for (row_t i = 0; i < rows; ++i) { for (col_t j = 0; j < cols; ++j) { row_t row = i + range_clipped.first.row; col_t col = j + range_clipped.first.column; double val = get_numeric_value(abs_address_t(range_clipped.first.sheet, row, col)); // TODO: we need to handle string types when that becomes available. ret.set(i, j, val); } } return ret; } std::unique_ptr model_context::create_session_handler() { return mp_impl->create_session_handler(); } iface::table_handler* model_context::get_table_handler() { return mp_impl->get_table_handler(); } const iface::table_handler* model_context::get_table_handler() const { return mp_impl->get_table_handler(); } string_id_t model_context::append_string(std::string_view s) { return mp_impl->append_string(s); } string_id_t model_context::add_string(std::string_view s) { return mp_impl->add_string(s); } const std::string* model_context::get_string(string_id_t identifier) const { return mp_impl->get_string(identifier); } sheet_t model_context::get_sheet_index(std::string_view name) const { return mp_impl->get_sheet_index(name); } std::string model_context::get_sheet_name(sheet_t sheet) const { return mp_impl->get_sheet_name(sheet); } rc_size_t model_context::get_sheet_size() const { return mp_impl->get_sheet_size(); } size_t model_context::get_sheet_count() const { return mp_impl->get_sheet_count(); } void model_context::set_named_expression(std::string name, formula_tokens_t expr) { abs_address_t origin(0, 0, 0); mp_impl->set_named_expression(std::move(name), origin, std::move(expr)); } void model_context::set_named_expression(std::string name, const abs_address_t& origin, formula_tokens_t expr) { mp_impl->set_named_expression(std::move(name), origin, std::move(expr)); } void model_context::set_named_expression(sheet_t sheet, std::string name, formula_tokens_t expr) { abs_address_t origin(0, 0, 0); mp_impl->set_named_expression(sheet, std::move(name), origin, std::move(expr)); } void model_context::set_named_expression( sheet_t sheet, std::string name, const abs_address_t& origin, formula_tokens_t expr) { mp_impl->set_named_expression(sheet, std::move(name), origin, std::move(expr)); } const named_expression_t* model_context::get_named_expression(sheet_t sheet, std::string_view name) const { return mp_impl->get_named_expression(sheet, name); } sheet_t model_context::append_sheet(std::string name) { return mp_impl->append_sheet(std::move(name)); } void model_context::set_cell_values(sheet_t sheet, std::initializer_list rows) { mp_impl->set_cell_values(sheet, std::move(rows)); } void model_context::set_session_handler_factory(session_handler_factory* factory) { mp_impl->set_session_handler_factory(factory); } void model_context::set_table_handler(iface::table_handler* handler) { mp_impl->set_table_handler(handler); } size_t model_context::get_string_count() const { return mp_impl->get_string_count(); } void model_context::dump_strings() const { mp_impl->dump_strings(); } string_id_t model_context::get_identifier_from_string(std::string_view s) const { return mp_impl->get_identifier_from_string(s); } model_iterator model_context::get_model_iterator( sheet_t sheet, rc_direction_t dir, const abs_rc_range_t& range) const { return mp_impl->get_model_iterator(sheet, dir, range); } named_expressions_iterator model_context::get_named_expressions_iterator() const { return named_expressions_iterator(*this, -1); } named_expressions_iterator model_context::get_named_expressions_iterator(sheet_t sheet) const { return named_expressions_iterator(*this, sheet); } bool model_context::empty() const { return mp_impl->empty(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/mem_str_buf.cpp0000664000175000017500000000601314122770261015753 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mem_str_buf.hpp" #include #include #include using namespace std; namespace ixion { size_t mem_str_buf::hash::operator() (const mem_str_buf& s) const { // copied from the hash function for pstring from orcus. size_t hash_val = s.size(); size_t loop_size = std::min(hash_val, 20); // prevent too much looping. const char* p = s.get(); for (size_t i = 0; i < loop_size; ++i, ++p) { hash_val += static_cast(*p); hash_val *= 2; } return hash_val; } mem_str_buf::mem_str_buf() : mp_buf(NULL), m_size(0) {} mem_str_buf::mem_str_buf(const char* p) : mp_buf(p), m_size(strlen(p)) {} mem_str_buf::mem_str_buf(const char* p, size_t n) : mp_buf(p), m_size(n) {} mem_str_buf::mem_str_buf(const mem_str_buf& r) : mp_buf(r.mp_buf), m_size(r.m_size) {} void mem_str_buf::append(const char* p) { if (m_size) inc(); else set_start(p); } void mem_str_buf::set_start(const char* p) { mp_buf = p; m_size = 1; } void mem_str_buf::inc() { assert(mp_buf); ++m_size; } void mem_str_buf::dec() { assert(mp_buf); --m_size; } void mem_str_buf::pop_front() { ++mp_buf; --m_size; } bool mem_str_buf::empty() const { return m_size == 0; } size_t mem_str_buf::size() const { return m_size; } const char* mem_str_buf::get() const { return mp_buf; } void mem_str_buf::clear() { mp_buf = NULL; m_size = 0; } void mem_str_buf::swap(mem_str_buf& r) { ::std::swap(mp_buf, r.mp_buf); ::std::swap(m_size, r.m_size); } bool mem_str_buf::equals(const char* s) const { if (strlen(s) != m_size) return false; return ::std::strncmp(mp_buf, s, m_size) == 0; } string mem_str_buf::str() const { return string(mp_buf, m_size); } mem_str_buf& mem_str_buf::operator= (const mem_str_buf& r) { mp_buf = r.mp_buf; m_size = r.m_size; return *this; } char mem_str_buf::operator[] (size_t pos) const { return mp_buf[pos]; } bool mem_str_buf::operator== (const mem_str_buf& r) const { if (m_size != r.m_size) return false; for (size_t i = 0; i < m_size; ++i) if (mp_buf[i] != r.mp_buf[i]) return false; return true; } char mem_str_buf::back() const { if (!m_size) return '\0'; return mp_buf[m_size-1]; } bool operator< (const mem_str_buf& left, const mem_str_buf& right) { // TODO: optimize this. return left.str() < right.str(); } bool operator> (const mem_str_buf& left, const mem_str_buf& right) { // TODO: optimize this. return left.str() > right.str(); } std::ostream& operator<< (std::ostream& os, const mem_str_buf& str) { os << str.str(); return os; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/address_iterator.cpp0000644000175000017500000001653013735106106017012 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/address_iterator.hpp" #include "ixion/address.hpp" #include "ixion/global.hpp" #include #include namespace ixion { namespace { bool inc_sheet(const abs_range_t& range, abs_address_t& pos) { if (pos.sheet < range.last.sheet) { ++pos.sheet; pos.row = range.first.row; pos.column = range.first.column; return true; } return false; } bool dec_sheet(const abs_range_t& range, abs_address_t& pos) { if (range.first.sheet < pos.sheet) { --pos.sheet; pos.row = range.last.row; pos.column = range.last.column; return true; } return false; } void inc_vertical(const abs_range_t& range, abs_address_t& pos, bool& end_pos) { if (end_pos) throw std::out_of_range("attempting to increment past the end position."); if (pos.row < range.last.row) { ++pos.row; return; } if (pos.column < range.last.column) { ++pos.column; pos.row = range.first.row; return; } if (inc_sheet(range, pos)) return; assert(pos == range.last); end_pos = true; } void dec_vertical(const abs_range_t& range, abs_address_t& pos, bool& end_pos) { if (end_pos) { end_pos = false; assert(pos == range.last); return; } if (range.first.row < pos.row) { --pos.row; return; } assert(pos.row == range.first.row); if (range.first.column < pos.column) { --pos.column; pos.row = range.last.row; return; } assert(pos.column == range.first.column); if (dec_sheet(range, pos)) return; assert(pos == range.first); throw std::out_of_range("Attempting to decrement beyond the first position."); } void inc_horizontal(const abs_range_t& range, abs_address_t& pos, bool& end_pos) { if (end_pos) throw std::out_of_range("attempting to increment past the end position."); if (pos.column < range.last.column) { ++pos.column; return; } if (pos.row < range.last.row) { ++pos.row; pos.column = range.first.column; return; } if (inc_sheet(range, pos)) return; assert(pos == range.last); end_pos = true; } void dec_horizontal(const abs_range_t& range, abs_address_t& pos, bool& end_pos) { if (end_pos) { end_pos = false; assert(pos == range.last); return; } if (range.first.column < pos.column) { --pos.column; return; } assert(pos.column == range.first.column); if (range.first.row < pos.row) { --pos.row; pos.column = range.last.column; return; } assert(pos.row == range.first.row); if (dec_sheet(range, pos)) return; assert(pos == range.first); throw std::out_of_range("Attempting to decrement beyond the first position."); } using update_func_type = std::function; } // anonymous namespace struct abs_address_iterator::impl { const abs_range_t m_range; rc_direction_t m_dir; impl(const abs_range_t& range, rc_direction_t dir) : m_range(range), m_dir(dir) {} }; struct abs_address_iterator::const_iterator::impl_node { const abs_range_t* mp_range; abs_address_t m_pos; bool m_end_pos; //< flag that indicates whether the node is at the position past the last valid address. update_func_type m_func_inc; update_func_type m_func_dec; impl_node() : mp_range(nullptr), m_pos(abs_address_t::invalid), m_end_pos(false) {} impl_node(const abs_range_t& range, rc_direction_t dir, bool end) : mp_range(&range), m_pos(end ? range.last : range.first), m_end_pos(end) { switch (dir) { case rc_direction_t::horizontal: m_func_inc = inc_horizontal; m_func_dec = dec_horizontal; break; case rc_direction_t::vertical: m_func_inc = inc_vertical; m_func_dec = dec_vertical; break; default: throw std::logic_error("unhandled direction value."); } } impl_node(const impl_node& r) : mp_range(r.mp_range), m_pos(r.m_pos), m_end_pos(r.m_end_pos), m_func_inc(r.m_func_inc), m_func_dec(r.m_func_dec) {} bool equals(const impl_node& r) const { return mp_range == r.mp_range && m_pos == r.m_pos && m_end_pos == r.m_end_pos; } void inc() { m_func_inc(*mp_range, m_pos, m_end_pos); } void dec() { m_func_dec(*mp_range, m_pos, m_end_pos); } }; abs_address_iterator::const_iterator::const_iterator() : mp_impl(std::make_unique()) {} abs_address_iterator::const_iterator::const_iterator( const abs_range_t& range, rc_direction_t dir, bool end) : mp_impl(std::make_unique(range, dir, end)) {} abs_address_iterator::const_iterator::const_iterator(const const_iterator& r) : mp_impl(std::make_unique(*r.mp_impl)) {} abs_address_iterator::const_iterator::const_iterator(const_iterator&& r) : mp_impl(std::move(r.mp_impl)) {} abs_address_iterator::const_iterator::~const_iterator() {} abs_address_iterator::const_iterator& abs_address_iterator::const_iterator::operator++() { mp_impl->inc(); return *this; } abs_address_iterator::const_iterator abs_address_iterator::const_iterator::operator++(int) { auto saved = *this; mp_impl->inc(); return saved; } abs_address_iterator::const_iterator& abs_address_iterator::const_iterator::operator--() { mp_impl->dec(); return *this; } abs_address_iterator::const_iterator abs_address_iterator::const_iterator::operator--(int) { auto saved = *this; mp_impl->dec(); return saved; } const abs_address_iterator::const_iterator::value_type& abs_address_iterator::const_iterator::operator*() const { return mp_impl->m_pos; } const abs_address_iterator::const_iterator::value_type* abs_address_iterator::const_iterator::operator->() const { return &mp_impl->m_pos; } bool abs_address_iterator::const_iterator::operator== (const const_iterator& r) const { return mp_impl->equals(*r.mp_impl); } bool abs_address_iterator::const_iterator::operator!= (const const_iterator& r) const { return !operator==(r); } abs_address_iterator::abs_address_iterator(const abs_range_t& range, rc_direction_t dir) : mp_impl(std::make_unique(range, dir)) {} abs_address_iterator::~abs_address_iterator() {} abs_address_iterator::const_iterator abs_address_iterator::begin() const { return cbegin(); } abs_address_iterator::const_iterator abs_address_iterator::end() const { return cend(); } abs_address_iterator::const_iterator abs_address_iterator::cbegin() const { return const_iterator(mp_impl->m_range, mp_impl->m_dir, false); } abs_address_iterator::const_iterator abs_address_iterator::cend() const { return const_iterator(mp_impl->m_range, mp_impl->m_dir, true); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_name_resolver.cpp0000664000175000017500000013655314135564272020063 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/formula_name_resolver.hpp" #include "ixion/interface/formula_model_access.hpp" #include "ixion/table.hpp" #include "formula_functions.hpp" #include "debug.hpp" #include "mem_str_buf.hpp" #include #include #include #include #include #include #include using namespace std; namespace ixion { namespace { bool check_address_by_sheet_bounds(const iface::formula_model_access* cxt, const address_t& pos) { rc_size_t ss(row_upper_bound, column_upper_bound); if (cxt && pos.sheet >= 0 && size_t(pos.sheet) < cxt->get_sheet_count()) { // Make sure the address is within the sheet size. ss = cxt->get_sheet_size(); } row_t row_check = pos.row >= 0 ? pos.row : -pos.row; if (pos.row != row_unset && row_check >= ss.row) return false; col_t col_check = pos.column >= 0 ? pos.column : -pos.column; if (pos.column != column_unset && col_check >= ss.column) return false; return true; } bool resolve_function(const char* p, size_t n, formula_name_t& ret) { formula_function_t func_oc = formula_functions::get_function_opcode({p, n}); if (func_oc != formula_function_t::func_unknown) { // This is a built-in function. ret.type = formula_name_t::function; ret.value = func_oc; return true; } return false; } /** * Table reference can be either one of: * *
    *
  • Table[Column]
  • *
  • [Column]
  • *
  • Table[[#Area],[Column]]
  • *
  • Table[[#Area1],[#Area2],[Column]]
  • *
* * where the #Area (area specifier) can be one or more of * *
    *
  • #Header
  • *
  • #Data
  • *
  • #Totals
  • *
  • #All
  • *
*/ bool resolve_table(const iface::formula_model_access* cxt, const char* p, size_t n, formula_name_t& ret) { if (!cxt) return false; short scope = 0; size_t last_column_pos = std::numeric_limits::max(); mem_str_buf buf; std::string_view table_name; std::vector names; bool table_detected = false; const char* p_end = p + n; for (; p != p_end; ++p) { switch (*p) { case '[': { if (scope >= 2) return false; table_detected = true; if (!buf.empty()) { if (scope != 0) return false; table_name = { buf.get(), buf.size() }; buf.clear(); } ++scope; } break; case ']': { if (scope <= 0) // non-matching brace. return false; if (!buf.empty()) { names.emplace_back(buf.get(), buf.size()); buf.clear(); } --scope; } break; case ',': { if (!buf.empty()) return false; } break; case ':': { if (scope != 1) // allowed only inside the first scope. return false; if (!buf.empty()) return false; if (names.empty()) return false; last_column_pos = names.size(); } break; default: if (buf.empty()) buf.set_start(p); else buf.inc(); } } if (!buf.empty()) return false; if (!table_detected) return false; if (names.empty()) return false; formula_name_t::table_type table; table.areas = table_area_none; table.name = table_name; table.column_first = std::string_view(); table.column_last = std::string_view(); for (std::size_t i = 0; i < names.size(); ++i) { std::string_view name = names[i]; assert(!name.empty()); if (name[0] == '#') { // area specifier. name.remove_prefix(1); if (name == "Headers") table.areas |= table_area_headers; else if (name == "Data") table.areas |= table_area_data; else if (name == "Totals") table.areas |= table_area_totals; else if (name == "All") table.areas = table_area_all; } else if (!table.column_first.empty()) { // This is a second column name. if (!table.column_last.empty()) return false; if (i != last_column_pos) return false; table.column_last = name; } else { // first column name. if (!table.areas) table.areas = table_area_data; table.column_first = name; } } ret.type = formula_name_t::table_reference; ret.value = table; return true; } /** * Check if the name is a built-in function, or else it's considered a named * expression. * * @param name name to be resolved * @param ret resolved name type */ void resolve_function_or_name(const char* p, size_t n, formula_name_t& ret) { if (resolve_function(p, n, ret)) return; // Everything else is assumed to be a named expression. ret.type = formula_name_t::named_expression; } void set_cell_reference(formula_name_t& ret, const address_t& addr) { ret.type = formula_name_t::cell_reference; ret.value = addr; } enum class resolver_parse_mode { column, row }; void append_sheet_name(ostringstream& os, const ixion::iface::formula_model_access& cxt, sheet_t sheet) { if (!is_valid_sheet(sheet)) { IXION_DEBUG("invalid sheet index (" << sheet << ")"); return; } string sheet_name = cxt.get_sheet_name(sheet); string buffer; // used only when the sheet name contains at least one single quote. const char* p = sheet_name.data(); const char* p_end = p + sheet_name.size(); bool quote = false; const char* p0 = nullptr; for (; p != p_end; ++p) { if (!p0) p0 = p; switch (*p) { case ' ': quote = true; break; case '\'': quote = true; buffer += string(p0, p-p0); buffer.push_back(*p); buffer.push_back(*p); p0 = nullptr; break; } } if (quote) os << '\''; if (buffer.empty()) os << sheet_name; else { if (p0) buffer += string(p0, p-p0); os << buffer; } if (quote) os << '\''; } void append_sheet_name_calc_a1( std::ostringstream& os, const ixion::iface::formula_model_access* cxt, const address_t& addr, const abs_address_t& origin) { if (!cxt) return; sheet_t sheet = addr.sheet; if (addr.abs_sheet) os << '$'; else sheet += origin.sheet; append_sheet_name(os, *cxt, sheet); os << '.'; } void append_sheet_name_odf_cra( std::ostringstream& os, const ixion::iface::formula_model_access* cxt, const address_t& addr, const abs_address_t& origin) { if (cxt) { sheet_t sheet = addr.sheet; if (addr.abs_sheet) os << '$'; else sheet += origin.sheet; append_sheet_name(os, *cxt, sheet); } os << '.'; } void append_column_name_a1(ostringstream& os, col_t col) { const col_t div = 26; string col_name; while (true) { col_t rem = col % div; char c = 'A' + rem; col_name.push_back(c); if (col < div) break; col -= rem; col /= div; col -= 1; } std::reverse(col_name.begin(), col_name.end()); os << col_name; } void append_column_address_a1(std::ostringstream& os, col_t col, col_t origin, bool absolute) { if (col == column_unset) return; if (absolute) os << '$'; else col += origin; append_column_name_a1(os, col); } void append_row_address_a1(std::ostringstream& os, row_t row, row_t origin, bool absolute) { if (row == row_unset) return; if (absolute) os << '$'; else row += origin; os << (row + 1); } void append_address_a1( std::ostringstream& os, const ixion::iface::formula_model_access* cxt, const address_t& addr, const abs_address_t& pos, char sheet_name_sep) { assert(sheet_name_sep); col_t col = addr.column; row_t row = addr.row; sheet_t sheet = addr.sheet; if (!addr.abs_column) col += pos.column; if (!addr.abs_row) row += pos.row; if (!addr.abs_sheet) sheet += pos.sheet; if (cxt) { append_sheet_name(os, *cxt, sheet); os << sheet_name_sep; } if (addr.abs_column) os << '$'; append_column_name_a1(os, col); if (addr.abs_row) os << '$'; os << (row + 1); } /** * Almost identical to append_address_a1, but it always appends a sheet name * separator even if a sheet name is not appended. */ void append_address_a1_with_sheet_name_sep( std::ostringstream& os, const ixion::iface::formula_model_access* cxt, const address_t& addr, const abs_address_t& pos, char sheet_name_sep) { if (!cxt) os << sheet_name_sep; append_address_a1(os, cxt, addr, pos, sheet_name_sep); } void append_address_r1c1( ostringstream& os, const address_t& addr, const abs_address_t& pos) { if (addr.row != row_unset) { os << 'R'; if (addr.abs_row) // absolute row address. os << (addr.row+1); else if (addr.row) { // relative row address different from origin. os << '['; os << addr.row; os << ']'; } } if (addr.column != column_unset) { os << 'C'; if (addr.abs_column) os << (addr.column+1); else if (addr.column) { os << '['; os << addr.column; os << ']'; } } } void append_name_string(ostringstream& os, const iface::formula_model_access* cxt, string_id_t sid) { if (!cxt) return; const string* p = cxt->get_string(sid); if (p) os << *p; } char append_table_areas(ostringstream& os, const table_t& table) { if (table.areas == table_area_all) { os << "[#All]"; return 1; } bool headers = (table.areas & table_area_headers); bool data = (table.areas & table_area_data); bool totals = (table.areas & table_area_totals); char count = 0; if (headers) { os << "[#Headers]"; ++count; } if (data) { if (count > 0) os << ','; os << "[#Data]"; ++count; } if (totals) { if (count > 0) os << ','; os << "[#Totals]"; ++count; } return count; } enum parse_address_result_type { invalid = 0, valid_address, range_expected /// valid address followed by a ':'. }; struct parse_address_result { parse_address_result_type result; bool sheet_name = false; }; #if IXION_LOGGING std::ostream& operator<< (std::ostream& os, parse_address_result_type rt) { static const char* names[] = { "invalid", "valid address", "range expected" }; os << names[rt]; return os; } std::string to_string(parse_address_result_type rt) { std::ostringstream os; os << rt; return os.str(); } #endif bool parse_sheet_name_quoted( const ixion::iface::formula_model_access& cxt, const char sep, const char*& p, const char* p_last, sheet_t& sheet) { ++p; // skip the open quote. size_t len = 0; string buffer; // used only when the name contains at least one single quote. const char* p1 = p; // parse until the closing quote is reached. while (true) { if (*p == '\'') { if (p == p_last) break; if (*(p+1) == '\'') { // next character is a quote too. Store the parsed string // segment to the buffer and move on. ++p; ++len; buffer += string(p1, len); ++p; p1 = p; len = 0; continue; } if (*(p+1) != sep) // the next char must be the separator. Parse failed. break; if (buffer.empty()) // Name contains no single quotes. sheet = cxt.get_sheet_index({p1, len}); else { buffer += string(p1, len); sheet = cxt.get_sheet_index({buffer.data(), buffer.size()}); } ++p; // skip the closing quote. if (p != p_last) ++p; // skip the separator. return true; } if (p == p_last) break; ++p; ++len; } return false; } /** * Try to parse a sheet name prefix in the string. If this fails, revert * the current position back to the original position prior to the call. * * @return true if the string contains a valid sheet name, false otherwise. */ bool parse_sheet_name( const ixion::iface::formula_model_access& cxt, const char sep, const char*& p, const char* p_last, sheet_t& sheet) { assert(p <= p_last); const char* p_old = p; // old position to revert to in case we fail to parse a sheet name. if (*p == '$') ++p; if (*p == '\'') { bool success = parse_sheet_name_quoted(cxt, sep, p, p_last, sheet); if (!success) p = p_old; return success; } const char* p0 = p; size_t len = 0; // parse until we hit the sheet-address separator. while (true) { if (*p == sep) { sheet = cxt.get_sheet_index({p0, len}); if (p != p_last) ++p; // skip the separator. return true; } if (p == p_last) break; ++p; ++len; } p = p_old; return false; } /** * If there is no number to parse, it returns 0 and the p will not * increment. Otherwise, p will point to the last digit of the number when * the call returns. */ template T parse_number(const char*&p, const char* p_last) { T num = 0; bool sign = false; if (*p == '+') ++p; else if (*p == '-') { ++p; sign = true; } bool all_digits = false; while (std::isdigit(*p)) { // Parse number. num *= 10; num += *p - '0'; if (p == p_last) { all_digits = true; break; } ++p; } if (!all_digits) --p; if (sign) num *= -1; return num; } /** * Parse A1-style single cell address. * * @param p it must point to the first character of a cell address. * @param p_last it must point to the last character of a whole string * sequence. It doesn't have to be the last character of a * cell address. * @param addr resolved cell address. * * @return parsing result. */ parse_address_result_type parse_address_a1(const char*& p, const char* p_last, address_t& addr) { // NOTE: Row and column IDs are 1-based during parsing, while 0 is used as // the state of a value-not-set. They are subtracted by one before // returning. resolver_parse_mode mode = resolver_parse_mode::column; while (true) { char c = *p; if ('a' <= c && c <= 'z') { // Convert to upper case. c -= 'a' - 'A'; } if ('A' <= c && c <= 'Z') { // Column digit if (mode != resolver_parse_mode::column) return invalid; if (addr.column) addr.column *= 26; addr.column += static_cast(c - 'A' + 1); if (addr.column > column_upper_bound) return invalid; } else if (std::isdigit(c)) { if (mode == resolver_parse_mode::column) { // First digit of a row. if (c == '0') // Leading zeros not allowed. return invalid; mode = resolver_parse_mode::row; } if (addr.row) addr.row *= 10; addr.row += static_cast(c - '0'); } else if (c == ':') { if (mode == resolver_parse_mode::row) { if (!addr.row) return invalid; --addr.row; if (addr.column) --addr.column; else addr.column = column_unset; return range_expected; } else if (mode == resolver_parse_mode::column) { // row number is not given. if (addr.column) --addr.column; else // neither row number nor column number is given. return invalid; addr.row = row_unset; return range_expected; } else return invalid; } else if (c == '$') { // Absolute position. if (mode == resolver_parse_mode::column) { if (addr.column) { // Column position has been already parsed. mode = resolver_parse_mode::row; addr.abs_row = true; } else { // Column position has not yet been parsed. addr.abs_column = true; } } else return invalid; } else return invalid; if (p == p_last) // last character reached. break; ++p; } if (mode == resolver_parse_mode::row) { if (!addr.row) return invalid; --addr.row; if (addr.column) --addr.column; else addr.column = column_unset; } else if (mode == resolver_parse_mode::column) { // row number is not given. if (addr.column) --addr.column; else // neither row number nor column number is given. return invalid; addr.row = row_unset; } return valid_address; } parse_address_result_type parse_address_r1c1(const char*& p, const char* p_last, address_t& addr) { addr.row = row_unset; addr.column = column_unset; if (*p == 'R' || *p == 'r') { addr.row = 0; addr.abs_row = false; if (p == p_last) // Just 'R'. Not sure if this is valid or invalid, but let's call it invalid for now. return parse_address_result_type::invalid; ++p; if (*p != 'C' && *p != 'c') { addr.abs_row = (*p != '['); if (!addr.abs_row) { // Relative row address. ++p; if (!std::isdigit(*p) && *p != '-' && *p != '+') return parse_address_result_type::invalid; addr.row = parse_number(p, p_last); ++p; if (p == p_last) return (*p == ']') ? parse_address_result_type::valid_address : parse_address_result_type::invalid; ++p; } else if (std::isdigit(*p)) { // Absolute row address. addr.row = parse_number(p, p_last); if (addr.row <= 0) // absolute address with 0 or negative value is invalid. return parse_address_result_type::invalid; --addr.row; // 1-based to 0-based. if (p == p_last && std::isdigit(*p)) // 'R' followed by a number without 'C' is valid. return parse_address_result_type::valid_address; ++p; } } } if (*p == 'C' || *p == 'c') { addr.column = 0; addr.abs_column = false; if (p == p_last) { if (addr.row == row_unset) // Just 'C'. Row must be set. return parse_address_result_type::invalid; if (!addr.abs_row && addr.row == 0) // 'RC' is invalid as it references itself. return parse_address_result_type::invalid; return parse_address_result_type::valid_address; } ++p; if (*p == '[') { // Relative column address. ++p; if (!std::isdigit(*p) && *p != '-' && *p != '+') return parse_address_result_type::invalid; addr.column = parse_number(p, p_last); ++p; if (p == p_last) return (*p == ']') ? parse_address_result_type::valid_address : parse_address_result_type::invalid; ++p; } else if (std::isdigit(*p)) { // Absolute column address. addr.abs_column = true; addr.column = parse_number(p, p_last); if (addr.column <= 0) // absolute address with 0 or negative value is invalid. return parse_address_result_type::invalid; --addr.column; // 1-based to 0-based. if (p == p_last) return parse_address_result_type::valid_address; ++p; } } if (*p == ':') return (p == p_last) ? parse_address_result_type::invalid : parse_address_result_type::range_expected; return parse_address_result_type::invalid; } parse_address_result parse_address_calc_a1( const ixion::iface::formula_model_access* cxt, const char*& p, const char* p_last, address_t& addr) { parse_address_result res; addr.row = 0; addr.column = 0; addr.abs_row = false; addr.abs_column = false; if (cxt) { // Overwrite the sheet index *only when* the sheet name is parsed successfully. const char* p0 = p; res.sheet_name = parse_sheet_name(*cxt, '.', p, p_last, addr.sheet); if (res.sheet_name) addr.abs_sheet = (*p0 == '$'); } res.result = parse_address_a1(p, p_last, addr); return res; } /** * Parse a single cell address in ODF cell-range-address syntax. This is * almost identical to Calc A1 except that it allows a leading '.' as in * '.E1' as opposed to just 'E1'. */ parse_address_result parse_address_odf_cra( const ixion::iface::formula_model_access* cxt, const char*& p, const char* p_last, address_t& addr) { if (*p == '.') { // Skip the '.', and assume absence of sheet name. ++p; cxt = nullptr; } return parse_address_calc_a1(cxt, p, p_last, addr); } parse_address_result_type parse_address_excel_a1( const ixion::iface::formula_model_access* cxt, const char*& p, const char* p_last, address_t& addr) { addr.row = 0; addr.column = 0; addr.abs_sheet = true; // Excel's sheet position is always absolute. addr.abs_row = false; addr.abs_column = false; if (cxt) // Overwrite the sheet index *only when* the sheet name is parsed successfully. parse_sheet_name(*cxt, '!', p, p_last, addr.sheet); return parse_address_a1(p, p_last, addr); } parse_address_result_type parse_address_excel_r1c1( const iface::formula_model_access* cxt, const char*& p, const char* p_last, address_t& addr) { addr.row = 0; addr.column = 0; addr.abs_sheet = true; // Excel's sheet position is always absolute. addr.abs_row = false; addr.abs_column = false; if (cxt) // Overwrite the sheet index *only when* the sheet name is parsed successfully. parse_sheet_name(*cxt, '!', p, p_last, addr.sheet); return parse_address_r1c1(p, p_last, addr); } parse_address_result parse_address_odff( const ixion::iface::formula_model_access* cxt, const char*& p, const char* p_last, address_t& addr) { parse_address_result res; assert(p <= p_last); addr.row = 0; addr.column = 0; addr.abs_row = false; addr.abs_column = false; if (*p == '.') { // This address doesn't contain a sheet name. ++p; } else if (cxt) { // This address DOES contain a sheet name. res.sheet_name = true; addr.abs_sheet = false; addr.sheet = invalid_sheet; // Overwrite the sheet index *only when* the sheet name is parsed successfully. if (*p == '$') { addr.abs_sheet = true; ++p; } if (p <= p_last) parse_sheet_name(*cxt, '.', p, p_last, addr.sheet); } res.result = parse_address_a1(p, p_last, addr); return res; } void to_relative_address(address_t& addr, const abs_address_t& pos, bool sheet) { if (!addr.abs_sheet && sheet) addr.sheet -= pos.sheet; if (!addr.abs_row && addr.row <= row_upper_bound) addr.row -= pos.row; if (!addr.abs_column && addr.column <= column_upper_bound) addr.column -= pos.column; } string to_string(const iface::formula_model_access* cxt, const table_t& table) { ostringstream os; append_name_string(os, cxt, table.name); if (table.column_first == empty_string_id) { // Area specifier(s) only. bool headers = (table.areas & table_area_headers); bool data = (table.areas & table_area_data); bool totals = (table.areas & table_area_totals); short count = 0; if (headers) ++count; if (data) ++count; if (totals) ++count; bool multiple = count == 2; if (multiple) os << '['; append_table_areas(os, table); if (multiple) os << ']'; } else if (table.column_last == empty_string_id) { // single column. os << '['; bool multiple = false; if (table.areas && table.areas != table_area_data) { if (append_table_areas(os, table)) { os << ','; multiple = true; } } if (multiple) os << '['; append_name_string(os, cxt, table.column_first); if (multiple) os << ']'; os << ']'; } else { // column range. os << '['; if (table.areas && table.areas != table_area_data) { if (append_table_areas(os, table)) os << ','; } os << '['; append_name_string(os, cxt, table.column_first); os << "]:["; append_name_string(os, cxt, table.column_last); os << "]]"; } return os.str(); } } // anonymous namespace formula_name_t::formula_name_t() : type(invalid), value(formula_function_t::func_unknown) {} string formula_name_t::to_string() const { std::ostringstream os; switch (type) { case cell_reference: os << "cell reference: " << std::get(value); break; case function: { auto v = std::get(value); os << "function: " << get_formula_function_name(v); break; } case invalid: os << "invalid"; break; case named_expression: os << "named expression"; break; case range_reference: os << "range raference: " << std::get(value); break; case table_reference: os << "table reference"; break; default: os << "unknown foromula name type"; } return os.str(); } formula_name_resolver::formula_name_resolver() {} formula_name_resolver::~formula_name_resolver() {} namespace { string get_column_name_a1(col_t col) { ostringstream os; append_column_name_a1(os, col); return os.str(); } class excel_a1 : public formula_name_resolver { public: excel_a1(const iface::formula_model_access* cxt) : formula_name_resolver(), mp_cxt(cxt) {} virtual ~excel_a1() {} virtual formula_name_t resolve(std::string_view s, const abs_address_t& pos) const { const char* p = s.data(); std::size_t n = s.size(); formula_name_t ret; if (!n) return ret; if (resolve_function(p, n, ret)) return ret; if (resolve_table(mp_cxt, p, n, ret)) return ret; const char* p_last = p; std::advance(p_last, n-1); // Use the sheet where the cell is unless sheet name is explicitly given. address_t parsed_addr(pos.sheet, 0, 0, false, false, false); parse_address_result_type parse_res = parse_address_excel_a1(mp_cxt, p, p_last, parsed_addr); if (parse_res != invalid) { // This is a valid A1-style address syntax-wise. if (parsed_addr.sheet == invalid_sheet) // sheet name is not found in the model. Report back as invalid. return ret; if (!check_address_by_sheet_bounds(mp_cxt, parsed_addr)) parse_res = invalid; } // prevent for example H to be recognized as column address if (parse_res == valid_address && parsed_addr.row != row_unset) { // This is a single cell address. to_relative_address(parsed_addr, pos, true); set_cell_reference(ret, parsed_addr); return ret; } if (parse_res == range_expected) { if (p == p_last) // ':' occurs as the last character. This is not allowed. return ret; ++p; // skip ':' range_t v; to_relative_address(parsed_addr, pos, true); v.first = parsed_addr; // For now, we assume the sheet index of the end address is identical // to that of the begin address. parse_res = parse_address_excel_a1(NULL, p, p_last, parsed_addr); if (parse_res != valid_address) { // The 2nd part after the ':' is not valid. ret.value = v; return ret; } to_relative_address(parsed_addr, pos, true); v.last = parsed_addr; v.last.sheet = v.first.sheet; // re-use the sheet index of the begin address. ret.value = v; ret.type = formula_name_t::range_reference; return ret; } resolve_function_or_name(p, n, ret); return ret; } virtual string get_name(const address_t& addr, const abs_address_t& pos, bool sheet_name) const { ostringstream os; append_address_a1(os, sheet_name ? mp_cxt : nullptr, addr, pos, '!'); return os.str(); } virtual string get_name(const range_t& range, const abs_address_t& pos, bool sheet_name) const { // For now, sheet index of the end-range address is ignored. ostringstream os; col_t col = range.first.column; row_t row = range.first.row; sheet_t sheet = range.first.sheet; if (!range.first.abs_sheet) sheet += pos.sheet; if (sheet_name && mp_cxt) { append_sheet_name(os, *mp_cxt, sheet); os << '!'; } append_column_address_a1(os, col, pos.column, range.first.abs_column); append_row_address_a1(os, row, pos.row, range.first.abs_row); os << ":"; col = range.last.column; row = range.last.row; append_column_address_a1(os, col, pos.column, range.last.abs_column); if (row != row_unset) { if (range.last.abs_row) os << '$'; else row += pos.row; os << (row + 1); } return os.str(); } virtual string get_name(const table_t& table) const { return to_string(mp_cxt, table); } virtual string get_column_name(col_t col) const { return get_column_name_a1(col); } private: const iface::formula_model_access* mp_cxt; }; class excel_r1c1 : public formula_name_resolver { const iface::formula_model_access* mp_cxt; void write_sheet_name(ostringstream& os, const address_t& addr, const abs_address_t& pos) const { if (mp_cxt) { sheet_t sheet = addr.sheet; if (!addr.abs_sheet) sheet += pos.sheet; append_sheet_name(os, *mp_cxt, sheet); os << '!'; } } public: excel_r1c1(const iface::formula_model_access* cxt) : mp_cxt(cxt) {} virtual formula_name_t resolve(std::string_view s, const abs_address_t& pos) const { const char* p = s.data(); std::size_t n = s.size(); formula_name_t ret; if (!n) return ret; if (resolve_function(p, n, ret)) return ret; const char* p_end = p + n; const char* p_last = p; std::advance(p_last, n-1); // Use the sheet where the cell is unless sheet name is explicitly given. address_t parsed_addr(pos.sheet, 0, 0); parse_address_result_type parse_res = parse_address_excel_r1c1(mp_cxt, p, p_last, parsed_addr); if (parse_res != invalid) { // This is a valid R1C1-style address syntax-wise. if (parsed_addr.sheet == invalid_sheet) // sheet name is not found in the model. Report back as invalid. return ret; if (!check_address_by_sheet_bounds(mp_cxt, parsed_addr)) parse_res = invalid; } switch (parse_res) { case parse_address_result_type::valid_address: { set_cell_reference(ret, parsed_addr); return ret; } case parse_address_result_type::range_expected: { ++p; // skip ':' if (p == p_end) return ret; address_t parsed_addr2(0, 0, 0); parse_address_result_type parse_res2 = parse_address_excel_r1c1(nullptr, p, p_last, parsed_addr2); if (parse_res2 != parse_address_result_type::valid_address) return ret; // For now, we assume the sheet index of the end address is identical // to that of the begin address. parsed_addr2.sheet = parsed_addr.sheet; ret.type = formula_name_t::range_reference; range_t v; v.first = parsed_addr; v.last = parsed_addr2; ret.value = v; return ret; } default: ; } resolve_function_or_name(p, n, ret); return ret; } virtual std::string get_name(const address_t& addr, const abs_address_t& pos, bool sheet_name) const { ostringstream os; if (sheet_name) write_sheet_name(os, addr, pos); append_address_r1c1(os, addr, pos); return os.str(); } virtual std::string get_name(const range_t& range, const abs_address_t& pos, bool sheet_name) const { ostringstream os; if (sheet_name) write_sheet_name(os, range.first, pos); append_address_r1c1(os, range.first, pos); os << ':'; append_address_r1c1(os, range.last, pos); return os.str(); } virtual std::string get_name(const table_t& table) const { return to_string(mp_cxt, table); } virtual std::string get_column_name(col_t col) const { ostringstream os; os << (col+1); return os.str(); } }; class dot_a1_resolver : public formula_name_resolver { using func_parse_address_type = std::function; using func_append_address_type = std::function; using func_append_sheet_name_type = std::function; const iface::formula_model_access* mp_cxt; func_parse_address_type m_func_parse_address; func_append_address_type m_func_append_address; func_append_sheet_name_type m_func_append_sheet_name; static bool display_last_sheet(const range_t& range, const abs_address_t& pos) { if (range.first.abs_sheet != range.last.abs_sheet) return true; abs_range_t abs = range.to_abs(pos); return abs.first.sheet != abs.last.sheet; } public: dot_a1_resolver( const iface::formula_model_access* cxt, func_parse_address_type func_parse_address, func_append_address_type func_append_address, func_append_sheet_name_type func_append_sheet_name) : formula_name_resolver(), mp_cxt(cxt), m_func_parse_address(func_parse_address), m_func_append_address(func_append_address), m_func_append_sheet_name(func_append_sheet_name) {} virtual formula_name_t resolve(std::string_view s, const abs_address_t &pos) const override { const char* p = s.data(); std::size_t n = s.size(); formula_name_t ret; if (!n) return ret; if (resolve_function(p, n, ret)) return ret; const char* p_last = p + n -1; // Use the sheet where the cell is unless sheet name is explicitly given. address_t parsed_addr(pos.sheet, 0, 0, false, false, false); parse_address_result parse_res = m_func_parse_address(mp_cxt, p, p_last, parsed_addr); IXION_TRACE("parse address result on 1st address (" << to_string(parse_res.result) << ")"); if (parse_res.result != invalid) { // This is a valid A1-style address syntax-wise. if (parsed_addr.sheet == invalid_sheet) { IXION_DEBUG("Sheet name is not found in the model context."); return ret; } if (!check_address_by_sheet_bounds(mp_cxt, parsed_addr)) { IXION_DEBUG("Address is outside the sheet bounds."); parse_res.result = invalid; } } // prevent for example H to be recognized as column address if (parse_res.result == valid_address && parsed_addr.row != row_unset) { // This is a single cell address. to_relative_address(parsed_addr, pos, true); set_cell_reference(ret, parsed_addr); return ret; } if (parse_res.result == range_expected) { if (p == p_last) { IXION_DEBUG("':' occurs as the last character. This is not allowed."); return ret; } ++p; // skip ':' to_relative_address(parsed_addr, pos, true); range_t v; v.first = parsed_addr; parse_res = m_func_parse_address(mp_cxt, p, p_last, parsed_addr); IXION_TRACE("parse address result on 2nd address (" << to_string(parse_res.result) << ")"); if (parse_res.result != valid_address) { IXION_DEBUG("2nd part after the ':' is not valid."); return ret; } to_relative_address(parsed_addr, pos, parse_res.sheet_name); v.last = parsed_addr; ret.type = formula_name_t::range_reference; ret.value = v; return ret; } resolve_function_or_name(p, n, ret); return ret; } virtual std::string get_name(const address_t &addr, const abs_address_t &pos, bool sheet_name) const override { std::ostringstream os; if (sheet_name && addr.abs_sheet) os << '$'; m_func_append_address(os, sheet_name ? mp_cxt : nullptr, addr, pos, '.'); return os.str(); } virtual std::string get_name(const range_t& range, const abs_address_t& pos, bool sheet_name) const override { ostringstream os; col_t col = range.first.column; row_t row = range.first.row; m_func_append_sheet_name(os, sheet_name ? mp_cxt : nullptr, range.first, pos); append_column_address_a1(os, col, pos.column, range.first.abs_column); append_row_address_a1(os, row, pos.row, range.first.abs_row); os << ":"; if (!display_last_sheet(range, pos)) sheet_name = false; m_func_append_sheet_name(os, sheet_name ? mp_cxt : nullptr, range.last, pos); col = range.last.column; row = range.last.row; append_column_address_a1(os, col, pos.column, range.last.abs_column); append_row_address_a1(os, row, pos.row, range.last.abs_row); return os.str(); } virtual std::string get_name(const table_t &table) const override { // TODO : find out how Calc A1 handles table reference. return std::string(); } virtual std::string get_column_name(col_t col) const override { return get_column_name_a1(col); } }; /** * Name resolver for ODFF formula expressions. */ class odff_resolver : public formula_name_resolver { public: odff_resolver(const iface::formula_model_access* cxt) : formula_name_resolver(), mp_cxt(cxt) {} virtual ~odff_resolver() {} virtual formula_name_t resolve(std::string_view s, const abs_address_t& pos) const { const char* p = s.data(); std::size_t n = s.size(); formula_name_t ret; if (resolve_function(p, n, ret)) return ret; if (!n) // Empty string. return ret; // First character must be '[' for this to be a reference. if (*p != '[') { ret.type = formula_name_t::named_expression; return ret; } ++p; const char* p_last = p; std::advance(p_last, n-2); // Last character must be ']'. if (*p_last != ']') return ret; --p_last; // Use the sheet where the cell is unless sheet name is explicitly given. address_t parsed_addr(pos.sheet, 0, 0, true, false, false); parse_address_result parse_res = parse_address_odff(mp_cxt, p, p_last, parsed_addr); // prevent for example H to be recognized as column address if (parse_res.result == valid_address && parsed_addr.row != row_unset) { // This is a single cell address. to_relative_address(parsed_addr, pos, true); set_cell_reference(ret, parsed_addr); return ret; } if (parse_res.result == range_expected) { if (p == p_last) // ':' occurs as the last character. This is not allowed. return ret; ++p; // skip ':' range_t v; to_relative_address(parsed_addr, pos, true); v.first = parsed_addr; parse_res = parse_address_odff(mp_cxt, p, p_last, parsed_addr); if (parse_res.result != valid_address) // The 2nd part after the ':' is not valid. return ret; to_relative_address(parsed_addr, pos, parse_res.sheet_name); v.last = parsed_addr; ret.type = formula_name_t::range_reference; ret.value = v; return ret; } resolve_function_or_name(p, n, ret); return ret; } virtual string get_name(const address_t& addr, const abs_address_t& pos, bool sheet_name) const { if (!mp_cxt) sheet_name = false; ostringstream os; os << '['; if (sheet_name) { if (addr.abs_sheet) os << '$'; append_address_a1(os, mp_cxt, addr, pos, '.'); } else { os << '.'; append_address_a1(os, nullptr, addr, pos, '.'); } os << ']'; return os.str(); } virtual string get_name(const range_t& range, const abs_address_t& pos, bool sheet_name) const { if (!mp_cxt) sheet_name = false; ostringstream os; os << '['; if (sheet_name) { const iface::formula_model_access* cxt = mp_cxt; if (range.first.abs_sheet) os << '$'; append_address_a1(os, cxt, range.first, pos, '.'); os << ':'; if (range.last.sheet != range.first.sheet || range.last.abs_sheet != range.first.abs_sheet) { // sheet indices differ between the first and last addresses. if (range.last.abs_sheet) os << '$'; } else { // sheet indices are identical. cxt = nullptr; os << '.'; } append_address_a1(os, cxt, range.last, pos, '.'); } else { os << '.'; append_address_a1(os, nullptr, range.first, pos, '.'); os << ":."; append_address_a1(os, nullptr, range.last, pos, '.'); } os << ']'; return os.str(); } virtual string get_name(const table_t& table) const { // TODO : ODF doesn't support table reference yet. return string(); } virtual string get_column_name(col_t col) const { return get_column_name_a1(col); } private: const iface::formula_model_access* mp_cxt; }; } std::unique_ptr formula_name_resolver::get( formula_name_resolver_t type, const iface::formula_model_access* cxt) { switch (type) { case formula_name_resolver_t::excel_a1: return std::unique_ptr(new excel_a1(cxt)); case formula_name_resolver_t::excel_r1c1: return std::unique_ptr(new excel_r1c1(cxt)); case formula_name_resolver_t::odff: return std::unique_ptr(new odff_resolver(cxt)); case formula_name_resolver_t::calc_a1: return std::unique_ptr( new dot_a1_resolver( cxt, parse_address_calc_a1, append_address_a1, append_sheet_name_calc_a1)); case formula_name_resolver_t::odf_cra: return std::unique_ptr( new dot_a1_resolver( cxt, parse_address_odf_cra, append_address_a1_with_sheet_name_sep, append_sheet_name_odf_cra)); case formula_name_resolver_t::unknown: default: ; } return std::unique_ptr(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_value_stack.cpp0000664000175000017500000002705114122752275017511 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "formula_value_stack.hpp" #include "debug.hpp" #include "ixion/address.hpp" #include "ixion/cell.hpp" #include "ixion/matrix.hpp" #include "ixion/formula_result.hpp" #include "ixion/interface/formula_model_access.hpp" #include "ixion/config.hpp" #include #include namespace ixion { namespace { double get_numeric_value(const iface::formula_model_access& cxt, const stack_value& v) { double ret = 0.0; switch (v.get_type()) { case stack_value_t::value: case stack_value_t::matrix: ret = v.get_value(); break; case stack_value_t::single_ref: { // reference to a single cell. const abs_address_t& addr = v.get_address(); ret = cxt.get_numeric_value(addr); break; } default: IXION_DEBUG("value is being popped, but the stack value type is not appropriate."); throw formula_error(formula_error_t::stack_error); } return ret; } } stack_value::stack_value(double val) : m_type(stack_value_t::value), m_value(val) {} stack_value::stack_value(std::string str) : m_type(stack_value_t::string), m_str(new std::string(std::move(str))) {} stack_value::stack_value(const abs_address_t& val) : m_type(stack_value_t::single_ref), m_address(new abs_address_t(val)) {} stack_value::stack_value(const abs_range_t& val) : m_type(stack_value_t::range_ref), m_range(new abs_range_t(val)) {} stack_value::stack_value(matrix mtx) : m_type(stack_value_t::matrix), m_matrix(new matrix(std::move(mtx))) {} stack_value::stack_value(stack_value&& other) : m_type(other.m_type) { other.m_type = stack_value_t::value; switch (m_type) { case stack_value_t::matrix: m_matrix = other.m_matrix; other.m_matrix = nullptr; break; case stack_value_t::range_ref: m_range = other.m_range; other.m_range = nullptr; break; case stack_value_t::single_ref: m_address = other.m_address; other.m_address = nullptr; break; case stack_value_t::string: m_str = other.m_str; other.m_str = nullptr; break; case stack_value_t::value: m_value = other.m_value; break; default: ; } } stack_value::~stack_value() { switch (m_type) { case stack_value_t::range_ref: delete m_range; break; case stack_value_t::single_ref: delete m_address; break; case stack_value_t::matrix: delete m_matrix; break; case stack_value_t::string: delete m_str; break; case stack_value_t::value: default: ; // do nothing } } stack_value& stack_value::operator= (stack_value&& other) { other.m_type = stack_value_t::value; switch (m_type) { case stack_value_t::matrix: m_matrix = other.m_matrix; other.m_matrix = nullptr; break; case stack_value_t::range_ref: m_range = other.m_range; other.m_range = nullptr; break; case stack_value_t::single_ref: m_address = other.m_address; other.m_address = nullptr; break; case stack_value_t::string: m_str = other.m_str; other.m_str = nullptr; break; case stack_value_t::value: m_value = other.m_value; break; default: ; } return *this; } stack_value_t stack_value::get_type() const { return m_type; } double stack_value::get_value() const { switch (m_type) { case stack_value_t::value: return m_value; case stack_value_t::matrix: return m_matrix->get_numeric(0, 0); default: ; } return 0.0; } const std::string& stack_value::get_string() const { return *m_str; } const abs_address_t& stack_value::get_address() const { return *m_address; } const abs_range_t& stack_value::get_range() const { return *m_range; } matrix stack_value::pop_matrix() { switch (m_type) { case stack_value_t::value: { matrix mtx(1, 1); mtx.set(0, 0, m_value); return mtx; } case stack_value_t::matrix: { matrix mtx; mtx.swap(*m_matrix); return mtx; } default: throw formula_error(formula_error_t::stack_error); } } formula_value_stack::formula_value_stack(const iface::formula_model_access& cxt) : m_context(cxt) {} formula_value_stack::iterator formula_value_stack::begin() { return m_stack.begin(); } formula_value_stack::iterator formula_value_stack::end() { return m_stack.end(); } formula_value_stack::const_iterator formula_value_stack::begin() const { return m_stack.begin(); } formula_value_stack::const_iterator formula_value_stack::end() const { return m_stack.end(); } formula_value_stack::value_type formula_value_stack::release(iterator pos) { auto tmp = std::move(*pos); m_stack.erase(pos); return tmp; } formula_value_stack::value_type formula_value_stack::release_back() { assert(!m_stack.empty()); auto tmp = std::move(m_stack.back()); m_stack.pop_back(); return tmp; } bool formula_value_stack::empty() const { return m_stack.empty(); } size_t formula_value_stack::size() const { return m_stack.size(); } void formula_value_stack::clear() { return m_stack.clear(); } void formula_value_stack::swap(formula_value_stack& other) { m_stack.swap(other.m_stack); } stack_value& formula_value_stack::back() { return m_stack.back(); } const stack_value& formula_value_stack::back() const { return m_stack.back(); } const stack_value& formula_value_stack::operator[](size_t pos) const { return m_stack[pos]; } double formula_value_stack::get_value(size_t pos) const { const stack_value& v = m_stack[pos]; return get_numeric_value(m_context, v); } void formula_value_stack::push_back(value_type&& val) { IXION_TRACE("push_back"); m_stack.push_back(std::move(val)); } void formula_value_stack::push_value(double val) { IXION_TRACE("val=" << val); m_stack.emplace_back(val); } void formula_value_stack::push_string(std::string str) { IXION_TRACE("str='" << str << "'"); m_stack.emplace_back(std::move(str)); } void formula_value_stack::push_single_ref(const abs_address_t& val) { IXION_TRACE("val=" << val.get_name()); m_stack.emplace_back(val); } void formula_value_stack::push_range_ref(const abs_range_t& val) { assert(val.valid()); IXION_TRACE("start=" << val.first.get_name() << "; end=" << val.last.get_name()); m_stack.emplace_back(val); } void formula_value_stack::push_matrix(matrix mtx) { IXION_TRACE("push_matrix"); m_stack.emplace_back(std::move(mtx)); } double formula_value_stack::pop_value() { double ret = 0.0; if (m_stack.empty()) throw formula_error(formula_error_t::stack_error); const stack_value& v = m_stack.back(); ret = get_numeric_value(m_context, v); m_stack.pop_back(); IXION_TRACE("ret=" << ret); return ret; } const std::string formula_value_stack::pop_string() { IXION_TRACE("pop_string"); if (m_stack.empty()) throw formula_error(formula_error_t::stack_error); const stack_value& v = m_stack.back(); switch (v.get_type()) { case stack_value_t::string: { const std::string str = v.get_string(); m_stack.pop_back(); return str; } break; case stack_value_t::value: { std::ostringstream os; os << v.get_value(); m_stack.pop_back(); return os.str(); } break; case stack_value_t::single_ref: { // reference to a single cell. abs_address_t addr = v.get_address(); m_stack.pop_back(); switch (m_context.get_celltype(addr)) { case celltype_t::empty: return std::string(); case celltype_t::formula: { formula_result res = m_context.get_formula_result(addr); switch (res.get_type()) { case formula_result::result_type::error: throw formula_error(res.get_error()); case formula_result::result_type::string: return res.get_string(); case formula_result::result_type::value: { std::ostringstream os; os << res.get_value(); return os.str(); } default: throw formula_error(formula_error_t::stack_error); } } break; case celltype_t::numeric: { std::ostringstream os; os << m_context.get_numeric_value(addr); return os.str(); } case celltype_t::string: { const std::string* ps = m_context.get_string(m_context.get_string_identifier(addr)); if (!ps) throw formula_error(formula_error_t::stack_error); return *ps; } break; default: throw formula_error(formula_error_t::stack_error); } } break; default: ; } throw formula_error(formula_error_t::stack_error); } abs_address_t formula_value_stack::pop_single_ref() { IXION_TRACE("pop_single_ref"); if (m_stack.empty()) throw formula_error(formula_error_t::stack_error); const stack_value& v = m_stack.back(); if (v.get_type() != stack_value_t::single_ref) throw formula_error(formula_error_t::stack_error); abs_address_t addr = v.get_address(); m_stack.pop_back(); return addr; } abs_range_t formula_value_stack::pop_range_ref() { IXION_TRACE("pop_range_ref"); if (m_stack.empty()) throw formula_error(formula_error_t::stack_error); const stack_value& v = m_stack.back(); if (v.get_type() != stack_value_t::range_ref) throw formula_error(formula_error_t::stack_error); abs_range_t range = v.get_range(); m_stack.pop_back(); return range; } matrix formula_value_stack::pop_range_value() { IXION_TRACE("pop_range_value"); if (m_stack.empty()) throw formula_error(formula_error_t::stack_error); const stack_value& v = m_stack.back(); if (v.get_type() != stack_value_t::range_ref) throw formula_error(formula_error_t::stack_error); matrix ret = m_context.get_range_value(v.get_range()); m_stack.pop_back(); return ret; } stack_value_t formula_value_stack::get_type() const { if (m_stack.empty()) throw formula_error(formula_error_t::stack_error); return m_stack.back().get_type(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/cell_queue_manager.cpp0000644000175000017500000000717313735106106017274 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "cell_queue_manager.hpp" #include "queue_entry.hpp" #include "ixion/cell.hpp" #include "ixion/interface/formula_model_access.hpp" #include #include #include #include #if !IXION_THREADS #error "This file is not to be compiled when the threads are disabled." #endif namespace ixion { namespace { class scoped_guard { std::thread m_thread; public: scoped_guard(std::thread thread) : m_thread(std::move(thread)) {} scoped_guard(scoped_guard&& other) : m_thread(std::move(other.m_thread)) {} scoped_guard(const scoped_guard&) = delete; scoped_guard& operator= (const scoped_guard&) = delete; ~scoped_guard() { m_thread.join(); } }; class interpreter_queue { using future_type = std::future; iface::formula_model_access& m_context; std::queue m_futures; std::mutex m_mtx; std::condition_variable m_cond; size_t m_max_queue; void interpret(formula_cell* p, const abs_address_t& pos) { p->interpret(m_context, pos); } public: interpreter_queue(iface::formula_model_access& cxt, size_t max_queue) : m_context(cxt), m_max_queue(max_queue) {} /** * Push one formula cell to the interpreter queue for future * intepretation. * * @param p pointer to formula cell instance. * @param pos position of the formual cell. */ void push(formula_cell* p, const abs_address_t& pos) { std::unique_lock lock(m_mtx); while (m_futures.size() >= m_max_queue) m_cond.wait(lock); future_type f = std::async( std::launch::async, &interpreter_queue::interpret, this, p, pos); m_futures.push(std::move(f)); lock.unlock(); m_cond.notify_one(); } /** * Wait for one formula cell to finish its interpretation. */ void wait_one() { std::unique_lock lock(m_mtx); while (m_futures.empty()) m_cond.wait(lock); future_type ret = std::move(m_futures.front()); m_futures.pop(); lock.unlock(); ret.get(); // This may throw if an exception was thrown on the thread. m_cond.notify_one(); } }; } struct formula_cell_queue::impl { iface::formula_model_access& m_context; std::vector m_cells; size_t m_thread_count; impl(iface::formula_model_access& cxt, std::vector&& cells, size_t thread_count) : m_context(cxt), m_cells(cells), m_thread_count(thread_count) {} void thread_launch(interpreter_queue* queue) { for (queue_entry& e : m_cells) queue->push(e.p, e.pos); } void run() { interpreter_queue queue(m_context, m_thread_count); std::thread t(&formula_cell_queue::impl::thread_launch, this, &queue); scoped_guard guard(std::move(t)); for (size_t i = 0, n = m_cells.size(); i < n; ++i) queue.wait_one(); } }; formula_cell_queue::formula_cell_queue( iface::formula_model_access& cxt, std::vector&& cells, size_t thread_count) : mp_impl(std::make_unique(cxt, std::move(cells), thread_count)) {} formula_cell_queue::~formula_cell_queue() {} void formula_cell_queue::run() { mp_impl->run(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/named_expressions_iterator.cpp0000644000175000017500000000442413735106106021112 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/named_expressions_iterator.hpp" #include "ixion/global.hpp" #include "model_types.hpp" #include "model_context_impl.hpp" namespace ixion { struct named_expressions_iterator::impl { const detail::named_expressions_t* named_exps; detail::named_expressions_t::const_iterator it; detail::named_expressions_t::const_iterator it_end; impl() : named_exps(nullptr) {} impl(const model_context& cxt, sheet_t scope) : named_exps(scope >=0 ? &cxt.mp_impl->get_named_expressions(scope) : &cxt.mp_impl->get_named_expressions()), it(named_exps->cbegin()), it_end(named_exps->cend()) {} impl(const impl& other) : named_exps(other.named_exps), it(other.it), it_end(other.it_end) {} }; named_expressions_iterator::named_expressions_iterator() : mp_impl(std::make_unique()) {} named_expressions_iterator::named_expressions_iterator(const model_context& cxt, sheet_t scope) : mp_impl(std::make_unique(cxt, scope)) {} named_expressions_iterator::named_expressions_iterator(const named_expressions_iterator& other) : mp_impl(std::make_unique(*other.mp_impl)) {} named_expressions_iterator::~named_expressions_iterator() { } size_t named_expressions_iterator::size() const { if (!mp_impl->named_exps) return 0; return mp_impl->named_exps->size(); } bool named_expressions_iterator::has() const { if (!mp_impl->named_exps) return false; return mp_impl->it != mp_impl->it_end; } void named_expressions_iterator::next() { ++mp_impl->it; } named_expressions_iterator::named_expression named_expressions_iterator::get() const { named_expression ret; ret.name = &mp_impl->it->first; ret.expression = &mp_impl->it->second; return ret; } named_expressions_iterator& named_expressions_iterator::operator= (const named_expressions_iterator& other) { mp_impl = std::make_unique(*other.mp_impl); return *this; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/utils.hpp0000664000175000017500000000140514105607506014620 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_DETAIL_UTILS_HPP #define INCLUDED_IXION_DETAIL_UTILS_HPP #include "ixion/types.hpp" #include "column_store_type.hpp" #include namespace ixion { namespace detail { celltype_t to_celltype(mdds::mtv::element_t mtv_type); template void ensure_max_size(const T& v) { static_assert(sizeof(T) <= S, "The size of the value exceeded allowed size limit."); } }} #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/utils.cpp0000644000175000017500000000205213655534235014617 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "utils.hpp" #include "ixion/exceptions.hpp" #include namespace ixion { namespace detail { celltype_t to_celltype(mdds::mtv::element_t mtv_type) { switch (mtv_type) { case element_type_empty: return celltype_t::empty; case element_type_numeric: return celltype_t::numeric; case element_type_boolean: return celltype_t::boolean; case element_type_string: return celltype_t::string; case element_type_formula: return celltype_t::formula; default: ; } std::ostringstream os; os << "unknown cell type (" << mtv_type << ")"; throw general_error(os.str()); } }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/constants.inl.in0000644000175000017500000000041413273351731016072 00000000000000 #define IXION_MAJOR_VERSION @IXION_MAJOR_VERSION@ #define IXION_MINOR_VERSION @IXION_MINOR_VERSION@ #define IXION_MICRO_VERSION @IXION_MICRO_VERSION@ #define IXION_MAJOR_API_VERSION @IXION_MAJOR_API_VERSION@ #define IXION_MINOR_API_VERSION @IXION_MINOR_API_VERSION@ libixion-0.17.0/src/libixion/document.cpp0000664000175000017500000001344114122770261015272 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/document.hpp" #include "ixion/global.hpp" #include "ixion/model_context.hpp" #include "ixion/formula_name_resolver.hpp" #include "ixion/formula.hpp" #include "ixion/cell_access.hpp" #include #include namespace ixion { namespace { abs_address_t to_address( const model_context& cxt, const formula_name_resolver& resolver, const document::cell_pos& pos) { switch (pos.type) { case document::cell_pos::cp_type::string: { std::string_view s = std::get(pos.value); formula_name_t name = resolver.resolve(s, abs_address_t()); if (name.type != formula_name_t::cell_reference) { std::ostringstream os; os << "invalid cell address: " << s; throw std::invalid_argument(os.str()); } return std::get(name.value).to_abs(abs_address_t()); } case document::cell_pos::cp_type::address: { return std::get(pos.value); } } throw std::logic_error("unrecognized cell position type."); } } // anonymous namespace document::cell_pos::cell_pos(const char* p) : type(cp_type::string), value(p) { } document::cell_pos::cell_pos(const char* p, size_t n) : type(cp_type::string), value(std::string_view(p, n)) { } document::cell_pos::cell_pos(const std::string& s) : type(cp_type::string), value(s) { } document::cell_pos::cell_pos(const abs_address_t& addr) : type(cp_type::address), value(addr) { } struct document::impl { model_context cxt; std::unique_ptr resolver; abs_range_set_t modified_cells; abs_range_set_t modified_formula_cells; impl() : cxt(), resolver(formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt)) {} impl(formula_name_resolver_t cell_address_type) : cxt(), resolver(formula_name_resolver::get(cell_address_type, &cxt)) {} void append_sheet(std::string name) { cxt.append_sheet(std::move(name)); } cell_access get_cell_access(cell_pos pos) const { abs_address_t addr = to_address(cxt, *resolver, pos); return cxt.get_cell_access(addr); } void set_numeric_cell(cell_pos pos, double val) { abs_address_t addr = to_address(cxt, *resolver, pos); unregister_formula_cell(cxt, addr); cxt.set_numeric_cell(addr, val); modified_cells.insert(addr); } void set_string_cell(cell_pos pos, std::string_view s) { abs_address_t addr = to_address(cxt, *resolver, pos); unregister_formula_cell(cxt, addr); cxt.set_string_cell(addr, s); modified_cells.insert(addr); } void set_boolean_cell(cell_pos pos, bool val) { abs_address_t addr = to_address(cxt, *resolver, pos); unregister_formula_cell(cxt, addr); cxt.set_boolean_cell(addr, val); modified_cells.insert(addr); } void empty_cell(cell_pos pos) { abs_address_t addr = to_address(cxt, *resolver, pos); unregister_formula_cell(cxt, addr); cxt.empty_cell(addr); modified_cells.insert(addr); } double get_numeric_value(cell_pos pos) const { abs_address_t addr = to_address(cxt, *resolver, pos); return cxt.get_numeric_value(addr); } std::string_view get_string_value(cell_pos pos) const { abs_address_t addr = to_address(cxt, *resolver, pos); return cxt.get_string_value(addr); } void set_formula_cell(cell_pos pos, std::string_view formula) { abs_address_t addr = to_address(cxt, *resolver, pos); unregister_formula_cell(cxt, addr); auto tokens = parse_formula_string(cxt, addr, *resolver, formula); formula_cell* fc = cxt.set_formula_cell(addr, std::move(tokens)); register_formula_cell(cxt, addr, fc); modified_formula_cells.insert(addr); } void calculate(size_t thread_count) { auto sorted_cells = query_and_sort_dirty_cells(cxt, modified_cells, &modified_formula_cells); calculate_sorted_cells(cxt, sorted_cells, thread_count); modified_cells.clear(); modified_formula_cells.clear(); } }; document::document() : mp_impl(std::make_unique()) {} document::document(formula_name_resolver_t cell_address_type) : mp_impl(std::make_unique(cell_address_type)) {} document::~document() {} void document::append_sheet(std::string name) { mp_impl->append_sheet(std::move(name)); } cell_access document::get_cell_access(cell_pos pos) const { return mp_impl->get_cell_access(pos); } void document::set_numeric_cell(cell_pos pos, double val) { mp_impl->set_numeric_cell(pos, val); } void document::set_string_cell(cell_pos pos, std::string_view s) { mp_impl->set_string_cell(pos, s); } void document::set_boolean_cell(cell_pos pos, bool val) { mp_impl->set_boolean_cell(pos, val); } void document::empty_cell(cell_pos pos) { mp_impl->empty_cell(pos); } double document::get_numeric_value(cell_pos pos) const { return mp_impl->get_numeric_value(pos); } std::string_view document::get_string_value(cell_pos pos) const { return mp_impl->get_string_value(pos); } void document::set_formula_cell(cell_pos pos, std::string_view formula) { mp_impl->set_formula_cell(pos, formula); } void document::calculate(size_t thread_count) { mp_impl->calculate(thread_count); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/lexer_tokens.hpp0000664000175000017500000000573114122770261016166 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_LEXER_TOKENS_HPP #define INCLUDED_IXION_LEXER_TOKENS_HPP #include "ixion/env.hpp" #include "mem_str_buf.hpp" #include #include namespace ixion { class lexer_token_base; typedef std::vector> lexer_tokens_t; std::string print_tokens(const lexer_tokens_t& tokens, bool verbose); // ============================================================================ enum class lexer_opcode_t { // data types value, string, name, // arithmetic operators plus, minus, divide, multiply, exponent, // string operators concat, // relational operators equal, less, greater, // parentheses, separators open, close, sep, }; const char* get_opcode_name(lexer_opcode_t oc); // ============================================================================ class lexer_token_base { public: lexer_token_base(lexer_opcode_t oc); lexer_token_base(const lexer_token_base& r); virtual ~lexer_token_base(); virtual double get_value() const; virtual mem_str_buf get_string() const; virtual ::std::string print() const = 0; lexer_opcode_t get_opcode() const; private: lexer_opcode_t m_opcode; }; // ============================================================================ class lexer_token : public lexer_token_base { public: lexer_token(lexer_opcode_t oc); virtual ~lexer_token(); virtual ::std::string print() const; }; // ============================================================================ class lexer_value_token : public lexer_token_base { public: lexer_value_token(double val); lexer_value_token(const lexer_value_token& r); virtual ~lexer_value_token(); virtual double get_value() const; virtual ::std::string print() const; private: double m_val; }; // ============================================================================ class lexer_string_token : public lexer_token_base { public: lexer_string_token(const char* p, size_t n); lexer_string_token(const lexer_string_token& r); virtual ~lexer_string_token(); virtual mem_str_buf get_string() const; virtual ::std::string print() const; private: mem_str_buf m_str; }; // ============================================================================ class lexer_name_token : public lexer_token_base { public: lexer_name_token(const char* p, size_t n); lexer_name_token(const lexer_name_token& r); virtual ~lexer_name_token(); virtual mem_str_buf get_string() const; virtual ::std::string print() const; private: mem_str_buf m_str; }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_calc.cpp0000664000175000017500000000416313722500074016102 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/formula.hpp" #include "ixion/address.hpp" #include "ixion/cell.hpp" #include "ixion/formula_name_resolver.hpp" #include "queue_entry.hpp" #include "debug.hpp" #if IXION_THREADS #include "cell_queue_manager.hpp" #endif #include namespace ixion { namespace { class calc_scope { iface::formula_model_access& m_cxt; public: calc_scope(iface::formula_model_access& cxt) : m_cxt(cxt) { m_cxt.notify(formula_event_t::calculation_begins); } ~calc_scope() { m_cxt.notify(formula_event_t::calculation_ends); } }; } void calculate_sorted_cells( iface::formula_model_access& cxt, const std::vector& formula_cells, size_t thread_count) { #if IXION_THREADS == 0 thread_count = 0; // threads are disabled thus not to be used. #endif calc_scope cs(cxt); std::vector entries; entries.reserve(formula_cells.size()); for (const abs_range_t& r : formula_cells) entries.emplace_back(cxt.get_formula_cell(r.first), r.first); // Reset cell status. for (queue_entry& e : entries) { e.p->reset(); IXION_TRACE("pos=" << e.pos.get_name() << " formula=" << detail::print_formula_expression(cxt, e.pos, *e.p)); } // First, detect circular dependencies and mark those circular // dependent cells with appropriate error flags. for (queue_entry& e : entries) e.p->check_circular(cxt, e.pos); if (!thread_count) { // Interpret cells using just a single thread. for (queue_entry& e : entries) e.p->interpret(cxt, e.pos); return; } #if IXION_THREADS // Interpret cells in topological order using threads. formula_cell_queue queue(cxt, std::move(entries), thread_count); queue.run(); #endif } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/workbook.cpp0000644000175000017500000000223513616122226015305 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/global.hpp" #include "workbook.hpp" namespace ixion { worksheet::worksheet() {} worksheet::worksheet(size_t row_size, size_t col_size) { m_pos_hints.reserve(col_size); for (size_t i = 0; i < col_size; ++i) { m_columns.emplace_back(row_size); m_pos_hints.push_back(m_columns.back().begin()); } } worksheet::~worksheet() {} workbook::workbook() {} workbook::workbook(size_t sheet_size, size_t row_size, size_t col_size) { for (size_t i = 0; i < sheet_size; ++i) m_sheets.emplace_back(row_size, col_size); } workbook::~workbook() {} void workbook::push_back(size_t row_size, size_t col_size) { m_sheets.emplace_back(row_size, col_size); } size_t workbook::size() const { return m_sheets.size(); } bool workbook::empty() const { return m_sheets.empty(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_lexer.hpp0000664000175000017500000000252714122770261016330 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_FORMULA_LEXER_HPP #define INCLUDED_IXION_FORMULA_LEXER_HPP #include #include #include "ixion/exceptions.hpp" #include "ixion/config.hpp" #include "lexer_tokens.hpp" #include "mem_str_buf.hpp" namespace ixion { class formula_lexer { formula_lexer() = delete; formula_lexer(const formula_lexer&) = delete; formula_lexer& operator= (const formula_lexer&) = delete; public: class tokenize_error : public general_error { public: tokenize_error(const std::string& msg); }; formula_lexer(const config& config, const char* p, size_t n); ~formula_lexer(); void tokenize(); /** * Note that this will empty the tokens stored inside the lexer instance. * * @param tokens token container to move the tokens to. */ void swap_tokens(lexer_tokens_t& tokens); private: const config& m_config; lexer_tokens_t m_tokens; const char* mp_first; size_t m_size; mem_str_buf m_formula; }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/cell_queue_manager.hpp0000644000175000017500000000176113356770726017314 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_CELL_QUEUE_MANAGER_HPP #define INCLUDED_IXION_CELL_QUEUE_MANAGER_HPP #include "ixion/global.hpp" #include #include namespace ixion { class formula_cell; struct queue_entry; namespace iface { class formula_model_access; } /** * Class that manages multi-threaded calculation of formula cells. */ class formula_cell_queue { struct impl; std::unique_ptr mp_impl; public: formula_cell_queue() = delete; formula_cell_queue( iface::formula_model_access& cxt, std::vector&& cells, size_t thread_count); ~formula_cell_queue(); void run(); }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/queue_entry.cpp0000644000175000017500000000075113356770726016035 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "queue_entry.hpp" namespace ixion { queue_entry::queue_entry(formula_cell* _p, const abs_address_t& _pos) : p(_p), pos(_pos) {} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_parser.cpp0000664000175000017500000001605314122770261016477 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "formula_parser.hpp" #include "ixion/formula_name_resolver.hpp" #include "ixion/interface/formula_model_access.hpp" #include "formula_functions.hpp" #include "concrete_formula_tokens.hpp" #include #include using namespace std; namespace ixion { namespace { class ref_error : public general_error { public: ref_error(const string& msg) : general_error(msg) {} }; } // ---------------------------------------------------------------------------- formula_parser::parse_error::parse_error(const string& msg) : general_error(msg) {} // ---------------------------------------------------------------------------- formula_parser::formula_parser( const lexer_tokens_t& tokens, iface::formula_model_access& cxt, const formula_name_resolver& resolver) : m_itr_cur(tokens.end()), m_itr_end(tokens.end()), m_tokens(tokens), m_context(cxt), m_resolver(resolver) { } formula_parser::~formula_parser() { } void formula_parser::set_origin(const abs_address_t& pos) { m_pos = pos; } void formula_parser::parse() { for (m_itr_cur = m_tokens.begin(); has_token(); next()) { const lexer_token_base& t = get_token(); lexer_opcode_t oc = t.get_opcode(); switch (oc) { case lexer_opcode_t::open: case lexer_opcode_t::close: case lexer_opcode_t::plus: case lexer_opcode_t::minus: case lexer_opcode_t::multiply: case lexer_opcode_t::exponent: case lexer_opcode_t::concat: case lexer_opcode_t::equal: case lexer_opcode_t::divide: case lexer_opcode_t::sep: primitive(oc); break; case lexer_opcode_t::name: name(t); break; case lexer_opcode_t::string: literal(t); break; case lexer_opcode_t::value: value(t); break; case lexer_opcode_t::less: less(t); break; case lexer_opcode_t::greater: greater(t); break; default: ; } } } void formula_parser::print_tokens() const { } formula_tokens_t& formula_parser::get_tokens() { return m_formula_tokens; } void formula_parser::primitive(lexer_opcode_t oc) { fopcode_t foc = fop_unknown; switch (oc) { case lexer_opcode_t::close: foc = fop_close; break; case lexer_opcode_t::divide: foc = fop_divide; break; case lexer_opcode_t::minus: foc = fop_minus; break; case lexer_opcode_t::multiply: foc = fop_multiply; break; case lexer_opcode_t::exponent: foc = fop_exponent; break; case lexer_opcode_t::concat: foc = fop_concat; break; case lexer_opcode_t::equal: foc = fop_equal; break; case lexer_opcode_t::open: foc = fop_open; break; case lexer_opcode_t::plus: foc = fop_plus; break; case lexer_opcode_t::sep: foc = fop_sep; break; default: throw parse_error("unknown primitive token received"); } m_formula_tokens.push_back(make_unique(foc)); } void formula_parser::name(const lexer_token_base& t) { mem_str_buf name = t.get_string(); formula_name_t fn = m_resolver.resolve({name.get(), name.size()}, m_pos); switch (fn.type) { case formula_name_t::cell_reference: m_formula_tokens.push_back( make_unique(std::get(fn.value))); break; case formula_name_t::range_reference: { m_formula_tokens.push_back( make_unique(std::get(fn.value))); break; } case formula_name_t::table_reference: { table_t table; formula_name_t::table_type src_table = std::get(fn.value); table.name = m_context.add_string(src_table.name); table.column_first = m_context.add_string(src_table.column_first); table.column_last = m_context.add_string(src_table.column_last); table.areas = src_table.areas; m_formula_tokens.push_back(make_unique(table)); break; } case formula_name_t::function: m_formula_tokens.push_back(make_unique(std::get(fn.value))); break; case formula_name_t::named_expression: m_formula_tokens.push_back( make_unique(name.get(), name.size())); break; default: { std::ostringstream os; os << "failed to resolve a name token '" << name.str() << "'."; throw parse_error(os.str()); } } } void formula_parser::literal(const lexer_token_base& t) { mem_str_buf s = t.get_string(); string_id_t sid = m_context.add_string({s.get(), s.size()}); m_formula_tokens.push_back(make_unique(sid)); } void formula_parser::value(const lexer_token_base& t) { double val = t.get_value(); m_formula_tokens.push_back(make_unique(val)); } void formula_parser::less(const lexer_token_base& t) { if (has_next()) { next(); switch (get_token().get_opcode()) { case lexer_opcode_t::equal: m_formula_tokens.push_back(make_unique(fop_less_equal)); return; case lexer_opcode_t::greater: m_formula_tokens.push_back(make_unique(fop_not_equal)); return; default: ; } prev(); } m_formula_tokens.push_back(make_unique(fop_less)); } void formula_parser::greater(const lexer_token_base& t) { if (has_next()) { next(); if (get_token().get_opcode() == lexer_opcode_t::equal) { m_formula_tokens.push_back(make_unique(fop_greater_equal)); return; } prev(); } m_formula_tokens.push_back(make_unique(fop_greater)); } const lexer_token_base& formula_parser::get_token() const { return **m_itr_cur; } bool formula_parser::has_token() const { return m_itr_cur != m_itr_end; } bool formula_parser::has_next() const { return (m_itr_cur+1) != m_itr_end; } void formula_parser::next() { ++m_itr_cur; } void formula_parser::prev() { --m_itr_cur; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/table.cpp0000644000175000017500000000103413273351731014537 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/table.hpp" namespace ixion { table_t::table_t() : name(empty_string_id), column_first(empty_string_id), column_last(empty_string_id), areas(table_area_none) {} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_interpreter.cpp0000664000175000017500000005735214122770261017555 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "formula_interpreter.hpp" #include "formula_functions.hpp" #include "concrete_formula_tokens.hpp" #include "debug.hpp" #include "ixion/cell.hpp" #include "ixion/global.hpp" #include "ixion/matrix.hpp" #include "ixion/formula.hpp" #include "ixion/interface/formula_model_access.hpp" #include "ixion/interface/session_handler.hpp" #include "ixion/interface/table_handler.hpp" #include "ixion/config.hpp" #include #include #include #include #include using namespace std; namespace ixion { namespace { class invalid_expression : public general_error { public: invalid_expression(const string& msg) : general_error(msg) {} }; opcode_token paren_open = opcode_token(fop_open); opcode_token paren_close = opcode_token(fop_close); } formula_interpreter::formula_interpreter(const formula_cell* cell, iface::formula_model_access& cxt) : m_parent_cell(cell), m_context(cxt), m_error(formula_error_t::no_error) { } formula_interpreter::~formula_interpreter() { } void formula_interpreter::set_origin(const abs_address_t& pos) { m_pos = pos; } bool formula_interpreter::interpret() { mp_handler = m_context.create_session_handler(); if (mp_handler) mp_handler->begin_cell_interpret(m_pos); try { init_tokens(); if (m_tokens.empty()) { IXION_DEBUG("interpreter has no tokens to interpret"); return false; } m_cur_token_itr = m_tokens.begin(); m_error = formula_error_t::no_error; m_result.reset(); expression(); if (m_cur_token_itr != m_tokens.end()) { if (mp_handler) mp_handler->set_invalid_expression("formula token interpretation ended prematurely."); return false; } pop_result(); IXION_TRACE("interpretation successfully finished"); if (mp_handler) mp_handler->end_cell_interpret(); return true; } catch (const invalid_expression& e) { if (mp_handler) mp_handler->set_invalid_expression(e.what()); m_error = formula_error_t::invalid_expression; } catch (const formula_error& e) { IXION_DEBUG("formula error: " << e.what()); if (mp_handler) mp_handler->set_formula_error(e.what()); m_error = e.get_error(); } if (mp_handler) mp_handler->end_cell_interpret(); return false; } formula_result formula_interpreter::transfer_result() { return std::move(m_result); } formula_error_t formula_interpreter::get_error() const { return m_error; } void formula_interpreter::init_tokens() { clear_stacks(); name_set used_names; m_tokens.clear(); const formula_tokens_store_ptr_t& ts = m_parent_cell->get_tokens(); if (!ts) return; const formula_tokens_t& src_tokens = ts->get(); for (const std::unique_ptr& p : src_tokens) { if (p->get_opcode() == fop_named_expression) { // Named expression. Expand it. const named_expression_t* expr = m_context.get_named_expression( m_pos.sheet, p->get_name()); used_names.insert(p->get_name()); expand_named_expression(expr, used_names); } else // Normal token. m_tokens.push_back(p.get()); } m_end_token_pos = m_tokens.end(); } namespace { void get_result_from_cell(const iface::formula_model_access& cxt, const abs_address_t& addr, formula_result& res) { switch (cxt.get_celltype(addr)) { case celltype_t::formula: { res = cxt.get_formula_result(addr); break; } case celltype_t::boolean: // TODO : treat this as a numeric value for now. Later we need to // decide whether we need to treat this as a distinct boolean // type. case celltype_t::numeric: res.set_value(cxt.get_numeric_value(addr)); break; case celltype_t::string: { std::string_view s = cxt.get_string_value(addr); res.set_string_value(std::string{s}); break; } case celltype_t::unknown: default: ; } } } void formula_interpreter::pop_result() { // there should only be one stack value left for the result value. assert(get_stack().size() == 1); stack_value& res = get_stack().back(); switch (res.get_type()) { case stack_value_t::range_ref: { const abs_range_t& range = res.get_range(); get_result_from_cell(m_context, range.first, m_result); break; } case stack_value_t::single_ref: { get_result_from_cell(m_context, res.get_address(), m_result); break; } case stack_value_t::string: { m_result.set_string_value(res.get_string()); break; } case stack_value_t::value: IXION_TRACE("value=" << res.get_value()); m_result.set_value(res.get_value()); break; case stack_value_t::matrix: m_result.set_matrix(res.pop_matrix()); break; default: ; } if (mp_handler) mp_handler->set_result(m_result); } void formula_interpreter::expand_named_expression(const named_expression_t* expr, name_set& used_names) { if (!expr) throw formula_error(formula_error_t::name_not_found); m_tokens.push_back(&paren_open); for (const auto& token : expr->tokens) { const formula_token& t = *token; if (t.get_opcode() == fop_named_expression) { string expr_name = t.get_name(); if (used_names.count(expr_name) > 0) { // Circular reference detected. throw invalid_expression("circular referencing of named expressions"); } const named_expression_t* this_expr = m_context.get_named_expression(m_pos.sheet, expr_name); used_names.insert(expr_name); expand_named_expression(this_expr, used_names); } else m_tokens.push_back(&t); } m_tokens.push_back(&paren_close); } void formula_interpreter::ensure_token_exists() const { if (!has_token()) throw invalid_expression("formula expression ended prematurely"); } bool formula_interpreter::has_token() const { return m_cur_token_itr != m_end_token_pos; } void formula_interpreter::next() { ++m_cur_token_itr; } const formula_token& formula_interpreter::token() const { assert(m_cur_token_itr != m_end_token_pos); return *(*m_cur_token_itr); } const formula_token& formula_interpreter::token_or_throw() const { ensure_token_exists(); return *(*m_cur_token_itr); } const formula_token& formula_interpreter::next_token() { next(); if (!has_token()) throw invalid_expression("expecting a token but no more tokens found."); return token(); } namespace { bool valid_expression_op(fopcode_t oc) { switch (oc) { case fop_plus: case fop_minus: case fop_equal: case fop_not_equal: case fop_less: case fop_less_equal: case fop_greater: case fop_greater_equal: return true; default: ; } return false; } bool pop_stack_value_or_string(const iface::formula_model_access& cxt, formula_value_stack& stack, stack_value_t& vt, double& val, string& str) { vt = stack.get_type(); switch (vt) { case stack_value_t::value: val = stack.pop_value(); break; case stack_value_t::string: str = stack.pop_string(); break; case stack_value_t::single_ref: { const abs_address_t& addr = stack.pop_single_ref(); switch (cxt.get_celltype(addr)) { case celltype_t::empty: { // empty cell has a value of 0. vt = stack_value_t::value; val = 0.0; return true; } case celltype_t::boolean: // TODO : Decide whether we need to treat this as a // distinct boolean value. For now, let's treat this as a // numeric value equivalent. case celltype_t::numeric: { vt = stack_value_t::value; val = cxt.get_numeric_value(addr); return true; } case celltype_t::string: { vt = stack_value_t::string; size_t strid = cxt.get_string_identifier(addr); const string* ps = cxt.get_string(strid); if (!ps) return false; str = *ps; return true; } case celltype_t::formula: { formula_result res = cxt.get_formula_result(addr); switch (res.get_type()) { case formula_result::result_type::value: { vt = stack_value_t::value; val = res.get_value(); return true; } case formula_result::result_type::string: { vt = stack_value_t::string; str = res.get_string(); return true; } case formula_result::result_type::error: default: return false; } } default: return false; } break; } case stack_value_t::range_ref: default: return false; } return true; } void compare_values(formula_value_stack& vs, fopcode_t oc, double val1, double val2) { switch (oc) { case fop_plus: vs.push_value(val1 + val2); break; case fop_minus: vs.push_value(val1 - val2); break; case fop_equal: vs.push_value(val1 == val2); break; case fop_not_equal: vs.push_value(val1 != val2); break; case fop_less: vs.push_value(val1 < val2); break; case fop_less_equal: vs.push_value(val1 <= val2); break; case fop_greater: vs.push_value(val1 > val2); break; case fop_greater_equal: vs.push_value(val1 >= val2); break; default: throw invalid_expression("unknown expression operator."); } } void compare_strings(formula_value_stack& vs, fopcode_t oc, const std::string& str1, const std::string& str2) { switch (oc) { case fop_plus: case fop_minus: throw formula_error(formula_error_t::invalid_expression); case fop_equal: vs.push_value(str1 == str2); break; case fop_not_equal: vs.push_value(str1 != str2); break; case fop_less: vs.push_value(str1 < str2); break; case fop_less_equal: vs.push_value(str1 <= str2); break; case fop_greater: vs.push_value(str1 > str2); break; case fop_greater_equal: vs.push_value(str1 >= str2); break; default: throw invalid_expression("unknown expression operator."); } } void compare_value_to_string( formula_value_stack& vs, fopcode_t oc, double /*val1*/, const std::string& /*str2*/) { // Value 1 is numeric while value 2 is string. String is // always greater than numeric value. switch (oc) { case fop_plus: case fop_minus: throw formula_error(formula_error_t::invalid_expression); case fop_equal: vs.push_value(false); break; case fop_not_equal: vs.push_value(true); break; case fop_less: case fop_less_equal: // val1 < str2 vs.push_value(true); break; case fop_greater: case fop_greater_equal: // val1 > str2 vs.push_value(false); break; default: throw invalid_expression("unknown expression operator."); } } void compare_string_to_value( formula_value_stack& vs, fopcode_t oc, const std::string& /*str1*/, double /*val2*/) { switch (oc) { case fop_plus: case fop_minus: throw formula_error(formula_error_t::invalid_expression); case fop_equal: vs.push_value(false); break; case fop_not_equal: vs.push_value(true); break; case fop_less: case fop_less_equal: // str1 < val2 vs.push_value(false); break; case fop_greater: case fop_greater_equal: // str1 > val2 vs.push_value(true); break; default: throw invalid_expression("unknown expression operator."); } } } void formula_interpreter::expression() { // + + + ... + // valid operators are: +, -, =, <, >, <=, >=, <>. term(); while (has_token()) { fopcode_t oc = token().get_opcode(); if (!valid_expression_op(oc)) return; double val1 = 0.0, val2 = 0.0; string str1, str2; bool is_val1 = true, is_val2 = true; stack_value_t vt; if (!pop_stack_value_or_string(m_context, get_stack(), vt, val1, str1)) throw formula_error(formula_error_t::general_error); is_val1 = vt == stack_value_t::value; if (mp_handler) mp_handler->push_token(oc); next(); term(); if (!pop_stack_value_or_string(m_context, get_stack(), vt, val2, str2)) throw formula_error(formula_error_t::general_error); is_val2 = vt == stack_value_t::value; if (is_val1) { if (is_val2) { // Both are numeric values. compare_values(get_stack(), oc, val1, val2); } else { compare_value_to_string(get_stack(), oc, val1, str2); } } else { if (is_val2) { // Value 1 is string while value 2 is numeric. compare_string_to_value(get_stack(), oc, str1, val2); } else { // Both are strings. compare_strings(get_stack(), oc, str1, str2); } } } } void formula_interpreter::term() { // || * factor(); if (!has_token()) return; fopcode_t oc = token().get_opcode(); switch (oc) { case fop_multiply: { if (mp_handler) mp_handler->push_token(oc); next(); double val = get_stack().pop_value(); term(); get_stack().push_value(val*get_stack().pop_value()); return; } case fop_exponent: { if (mp_handler) mp_handler->push_token(oc); next(); double base = get_stack().pop_value(); term(); double exp = get_stack().pop_value(); get_stack().push_value(std::pow(base, exp)); return; } case fop_concat: { if (mp_handler) mp_handler->push_token(oc); next(); std::string s1 = get_stack().pop_string(); term(); std::string s2 = get_stack().pop_string(); std::string s = s1 + s2; get_stack().push_string(std::move(s)); return; } case fop_divide: { if (mp_handler) mp_handler->push_token(oc); next(); double val = get_stack().pop_value(); term(); double val2 = get_stack().pop_value(); if (val2 == 0.0) throw formula_error(formula_error_t::division_by_zero); get_stack().push_value(val/val2); return; } default: ; } } void formula_interpreter::factor() { // || || '(' ')' || bool negative_sign = sign(); // NB: may be precedeed by a '+' or '-' sign. fopcode_t oc = token().get_opcode(); switch (oc) { case fop_open: paren(); break; case fop_named_expression: { // All named expressions are supposed to be expanded prior to interpretation. IXION_DEBUG("named expression encountered in factor."); throw formula_error(formula_error_t::general_error); } case fop_value: { constant(); break; } case fop_single_ref: single_ref(); break; case fop_range_ref: range_ref(); break; case fop_table_ref: table_ref(); break; case fop_function: function(); break; case fop_string: literal(); break; default: ostringstream os; os << "factor: unexpected token type: <" << get_opcode_name(oc) << ">"; throw invalid_expression(os.str()); } if (negative_sign) { double v = get_stack().pop_value(); get_stack().push_value(v * -1.0); } } bool formula_interpreter::sign() { ensure_token_exists(); fopcode_t oc = token().get_opcode(); bool sign_set = false; switch (oc) { case fop_minus: sign_set = true; // fall through case fop_plus: { if (mp_handler) mp_handler->push_token(oc); next(); if (!has_token()) throw invalid_expression("sign: a sign cannot be the last token"); } default: ; } return sign_set; } void formula_interpreter::paren() { if (mp_handler) mp_handler->push_token(fop_open); next(); expression(); if (token_or_throw().get_opcode() != fop_close) throw invalid_expression("paren: expected close paren"); if (mp_handler) mp_handler->push_token(fop_close); next(); } void formula_interpreter::single_ref() { address_t addr = token().get_single_ref(); IXION_TRACE("ref=" << addr.get_name() << "; origin=" << m_pos.get_name()); if (mp_handler) mp_handler->push_single_ref(addr, m_pos); abs_address_t abs_addr = addr.to_abs(m_pos); IXION_TRACE("ref=" << abs_addr.get_name() << " (converted to absolute)"); if (abs_addr == m_pos) { // self-referencing is not permitted. throw formula_error(formula_error_t::ref_result_not_available); } get_stack().push_single_ref(abs_addr); next(); } void formula_interpreter::range_ref() { range_t range = token().get_range_ref(); IXION_TRACE("ref-start=" << range.first.get_name() << "; ref-end=" << range.last.get_name() << "; origin=" << m_pos.get_name()); if (mp_handler) mp_handler->push_range_ref(range, m_pos); abs_range_t abs_range = range.to_abs(m_pos); abs_range.reorder(); IXION_TRACE("ref-start=" << abs_range.first.get_name() << "; ref-end=" << abs_range.last.get_name() << " (converted to absolute)"); // Check the reference range to make sure it doesn't include the parent cell. if (abs_range.contains(m_pos)) { // Referenced range contains the address of this cell. Not good. throw formula_error(formula_error_t::ref_result_not_available); } get_stack().push_range_ref(abs_range); next(); } void formula_interpreter::table_ref() { const iface::table_handler* table_hdl = m_context.get_table_handler(); if (!table_hdl) { IXION_DEBUG("failed to get a table_handler instance."); throw formula_error(formula_error_t::ref_result_not_available); } table_t table = token().get_table_ref(); if (mp_handler) mp_handler->push_table_ref(table); abs_range_t range(abs_range_t::invalid); if (table.name != empty_string_id) { range = table_hdl->get_range(table.name, table.column_first, table.column_last, table.areas); } else { // Table name is not given. Use the current cell position to infer // which table to use. range = table_hdl->get_range(m_pos, table.column_first, table.column_last, table.areas); } get_stack().push_range_ref(range); next(); } void formula_interpreter::constant() { double val = token().get_value(); next(); get_stack().push_value(val); if (mp_handler) mp_handler->push_value(val); } void formula_interpreter::literal() { string_id_t sid = token().get_uint32(); const std::string* p = m_context.get_string(sid); if (!p) throw general_error("no string found for the specified string ID."); next(); get_stack().push_string(*p); if (mp_handler) mp_handler->push_string(sid); } void formula_interpreter::function() { // '(' ',' ',' ... ',' ')' ensure_token_exists(); assert(token().get_opcode() == fop_function); formula_function_t func_oc = formula_functions::get_function_opcode(token()); if (mp_handler) mp_handler->push_function(func_oc); push_stack(); IXION_TRACE("function='" << get_formula_function_name(func_oc) << "'"); assert(get_stack().empty()); if (next_token().get_opcode() != fop_open) throw invalid_expression("expecting a '(' after a function name."); if (mp_handler) mp_handler->push_token(fop_open); fopcode_t oc = next_token().get_opcode(); bool expect_sep = false; while (oc != fop_close) { if (expect_sep) { if (oc != fop_sep) throw invalid_expression("argument separator is expected, but not found."); next(); expect_sep = false; if (mp_handler) mp_handler->push_token(oc); } else { expression(); expect_sep = true; } oc = token_or_throw().get_opcode(); } if (mp_handler) mp_handler->push_token(oc); next(); // Function call pops all stack values pushed onto the stack this far, and // pushes the result onto the stack. formula_functions(m_context).interpret(func_oc, get_stack()); assert(get_stack().size() == 1); pop_stack(); } void formula_interpreter::clear_stacks() { m_stacks.clear(); m_stacks.emplace_back(m_context); } void formula_interpreter::push_stack() { m_stacks.emplace_back(m_context); } void formula_interpreter::pop_stack() { assert(m_stacks.size() >= 2); assert(m_stacks.back().size() == 1); auto tmp = m_stacks.back().release_back(); m_stacks.pop_back(); m_stacks.back().push_back(std::move(tmp)); } formula_value_stack& formula_interpreter::get_stack() { assert(!m_stacks.empty()); return m_stacks.back(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/matrix.cpp0000664000175000017500000002056214122770261014762 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/matrix.hpp" #include "ixion/global.hpp" #include "column_store_type.hpp" #include #include #include namespace ixion { const double nan = std::numeric_limits::quiet_NaN(); struct matrix::impl { matrix_store_t m_data; impl() {} impl(size_t rows, size_t cols) : m_data(rows, cols) {} impl(size_t rows, size_t cols, double numeric) : m_data(rows, cols, numeric) {} impl(size_t rows, size_t cols, bool boolean) : m_data(rows, cols, boolean) {} impl(size_t rows, size_t cols, const std::string& str) : m_data(rows, cols, str) {} impl(size_t rows, size_t cols, formula_error_t error) : m_data(rows, cols, -static_cast(error)) {} impl(const std::vector& array, size_t rows, size_t cols) : m_data(rows, cols, array.begin(), array.end()) {} impl(const impl& other) : m_data(other.m_data) {} }; struct numeric_matrix::impl { std::vector m_array; size_t m_rows; size_t m_cols; impl() : m_rows(0), m_cols(0) {} impl(size_t rows, size_t cols) : m_array(rows * cols, 0.0), m_rows(rows), m_cols(cols) {} impl(std::vector array, size_t rows, size_t cols) : m_array(std::move(array)), m_rows(rows), m_cols(cols) {} size_t to_array_pos(size_t row, size_t col) const { return m_rows * col + row; } }; matrix::matrix() : mp_impl(std::make_unique()) {} matrix::matrix(size_t rows, size_t cols) : mp_impl(std::make_unique(rows, cols)) {} matrix::matrix(size_t rows, size_t cols, double numeric) : mp_impl(std::make_unique(rows, cols, numeric)) {} matrix::matrix(size_t rows, size_t cols, bool boolean) : mp_impl(std::make_unique(rows, cols, boolean)) {} matrix::matrix(size_t rows, size_t cols, const std::string& str) : mp_impl(std::make_unique(rows, cols, str)) {} matrix::matrix(size_t rows, size_t cols, formula_error_t error) : mp_impl(std::make_unique(rows, cols, error)) {} matrix::matrix(const matrix& other) : mp_impl(std::make_unique(*other.mp_impl)) { } matrix::matrix(matrix&& other) : mp_impl(std::move(other.mp_impl)) { } matrix::matrix(const numeric_matrix& other) : mp_impl(std::make_unique( other.mp_impl->m_array, other.row_size(), other.col_size())) { } matrix::~matrix() {} matrix& matrix::operator= (matrix other) { matrix t(std::move(other)); swap(t); return *this; } bool matrix::is_numeric() const { return mp_impl->m_data.numeric(); } bool matrix::is_numeric(size_t row, size_t col) const { switch (mp_impl->m_data.get_type(row, col)) { case mdds::mtm::element_numeric: case mdds::mtm::element_boolean: return true; default: ; } return false; } double matrix::get_numeric(size_t row, size_t col) const { return mp_impl->m_data.get_numeric(row, col); } void matrix::set(size_t row, size_t col, double val) { mp_impl->m_data.set(row, col, val); } void matrix::set(size_t row, size_t col, bool val) { mp_impl->m_data.set(row, col, val); } void matrix::set(size_t row, size_t col, const std::string& str) { mp_impl->m_data.set(row, col, str); } void matrix::set(size_t row, size_t col, formula_error_t val) { int64_t encoded = -static_cast(val); mp_impl->m_data.set(row, col, encoded); } matrix::element matrix::get(size_t row, size_t col) const { element me; me.type = element_type::empty; switch (mp_impl->m_data.get_type(row, col)) { case mdds::mtm::element_numeric: me.type = element_type::numeric; me.value = mp_impl->m_data.get_numeric(row, col); break; case mdds::mtm::element_integer: { // This is an error value, which must be negative. auto v = mp_impl->m_data.get_integer(row, col); if (v >= 0) break; me.type = element_type::error; me.value = static_cast(-v); break; } case mdds::mtm::element_string: { me.type = element_type::string; me.value = mp_impl->m_data.get_string(row, col); break; } case mdds::mtm::element_boolean: { me.type = element_type::boolean; me.value = mp_impl->m_data.get_boolean(row, col); break; } default: ; } return me; } size_t matrix::row_size() const { return mp_impl->m_data.size().row; } size_t matrix::col_size() const { return mp_impl->m_data.size().column; } void matrix::swap(matrix& r) { mp_impl.swap(r.mp_impl); } numeric_matrix matrix::as_numeric() const { matrix_store_t::size_pair_type mtx_size = mp_impl->m_data.size(); std::vector num_array(mtx_size.row*mtx_size.column, nan); double* dest = num_array.data(); std::function f = [&](const matrix_store_t::element_block_node_type& node) { assert(node.offset == 0); switch (node.type) { case mdds::mtm::element_integer: { // String and error values will be handled as numeric values of 0.0. #ifndef __STDC_IEC_559__ throw std::runtime_error("IEEE 754 is not fully supported."); #endif std::memset(dest, 0, sizeof(double)*node.size); // IEEE 754 defines 0.0 to be 8 zero bytes. std::advance(dest, node.size); break; } case mdds::mtm::element_boolean: { using block_type = matrix_store_t::boolean_block_type; auto it = block_type::begin(*node.data); auto ite = block_type::end(*node.data); for (; it != ite; ++it) *dest++ = *it ? 1.0 : 0.0; break; } case mdds::mtm::element_numeric: { using block_type = matrix_store_t::numeric_block_type; const double* src = &block_type::at(*node.data, 0); std::memcpy(dest, src, sizeof(double)*node.size); std::advance(dest, node.size); break; } case mdds::mtm::element_string: { // Skip string blocks. std::advance(dest, node.size); break; } default: ; } }; mp_impl->m_data.walk(f); return numeric_matrix(std::move(num_array), mtx_size.row, mtx_size.column); } bool matrix::operator== (const matrix& r) const { return mp_impl->m_data == r.mp_impl->m_data; } bool matrix::operator!= (const matrix& r) const { return !operator==(r); } numeric_matrix::numeric_matrix() : mp_impl(std::make_unique()) {} numeric_matrix::numeric_matrix(size_t rows, size_t cols) : mp_impl(std::make_unique(rows, cols)) {} numeric_matrix::numeric_matrix(std::vector array, size_t rows, size_t cols) : mp_impl(std::make_unique(std::move(array), rows, cols)) {} numeric_matrix::numeric_matrix(numeric_matrix&& r) : mp_impl(std::move(r.mp_impl)) {} numeric_matrix::~numeric_matrix() {} numeric_matrix& numeric_matrix::operator= (numeric_matrix other) { numeric_matrix t(std::move(other)); swap(t); return *this; } double& numeric_matrix::operator() (size_t row, size_t col) { size_t pos = mp_impl->to_array_pos(row, col); return mp_impl->m_array[pos]; } const double& numeric_matrix::operator() (size_t row, size_t col) const { size_t pos = mp_impl->to_array_pos(row, col); return mp_impl->m_array[pos]; } void numeric_matrix::swap(numeric_matrix& r) { mp_impl.swap(r.mp_impl); } size_t numeric_matrix::row_size() const { return mp_impl->m_rows; } size_t numeric_matrix::col_size() const { return mp_impl->m_cols; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_value_stack.hpp0000664000175000017500000000653613775503625017531 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_FORMULA_VALUE_STACK_HPP #define INCLUDED_IXION_FORMULA_VALUE_STACK_HPP #include "ixion/global.hpp" #include namespace ixion { namespace iface { class formula_model_access; } struct abs_address_t; struct abs_range_t; class matrix; /** * Type of stack value which can be used as intermediate value during * formula interpretation. */ enum class stack_value_t { value, string, single_ref, range_ref, matrix, }; /** * Individual stack value storage. */ class stack_value { stack_value_t m_type; union { double m_value; abs_address_t* m_address; abs_range_t* m_range; matrix* m_matrix; std::string* m_str; }; public: stack_value() = delete; stack_value(const stack_value&) = delete; stack_value& operator= (const stack_value&) = delete; explicit stack_value(double val); explicit stack_value(std::string str); explicit stack_value(const abs_address_t& val); explicit stack_value(const abs_range_t& val); explicit stack_value(matrix mtx); stack_value(stack_value&& other); ~stack_value(); stack_value& operator= (stack_value&& other); stack_value_t get_type() const; double get_value() const; const std::string& get_string() const; const abs_address_t& get_address() const; const abs_range_t& get_range() const; /** * Move the matrix value out from storage. The internal matrix content * will be empty after this call. */ matrix pop_matrix(); }; /** * FILO stack of values; last pushed value gets popped first. */ class formula_value_stack { typedef std::deque store_type; store_type m_stack; const iface::formula_model_access& m_context; public: formula_value_stack() = delete; formula_value_stack(const formula_value_stack&) = delete; formula_value_stack& operator= (const formula_value_stack&) = delete; explicit formula_value_stack(const iface::formula_model_access& cxt); typedef store_type::value_type value_type; typedef store_type::iterator iterator; typedef store_type::const_iterator const_iterator; iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; value_type release(iterator pos); value_type release_back(); bool empty() const; size_t size() const; void clear(); void swap(formula_value_stack& other); stack_value& back(); const stack_value& back() const; const stack_value& operator[](size_t pos) const; double get_value(size_t pos) const; void push_back(value_type&& val); void push_value(double val); void push_string(std::string str); void push_single_ref(const abs_address_t& val); void push_range_ref(const abs_range_t& val); void push_matrix(matrix mtx); double pop_value(); const std::string pop_string(); abs_address_t pop_single_ref(); abs_range_t pop_range_ref(); matrix pop_range_value(); stack_value_t get_type() const; }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/model_iterator.cpp0000664000175000017500000003056114122770261016467 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/model_iterator.hpp" #include "ixion/global.hpp" #include "ixion/exceptions.hpp" #include "model_context_impl.hpp" #include #include #include namespace ixion { model_iterator::cell::cell() : row(0), col(0), type(celltype_t::empty), value(false) {} model_iterator::cell::cell(row_t _row, col_t _col) : row(_row), col(_col), type(celltype_t::empty), value(false) {} model_iterator::cell::cell(row_t _row, col_t _col, bool _b) : row(_row), col(_col), type(celltype_t::boolean), value(_b) {} model_iterator::cell::cell(row_t _row, col_t _col, string_id_t _s) : row(_row), col(_col), type(celltype_t::string), value(_s) {} model_iterator::cell::cell(row_t _row, col_t _col, double _v) : row(_row), col(_col), type(celltype_t::numeric), value(_v) {} model_iterator::cell::cell(row_t _row, col_t _col, const formula_cell* _f) : row(_row), col(_col), type(celltype_t::formula), value(_f) {} bool model_iterator::cell::operator== (const cell& other) const { if (type != other.type || row != other.row || col != other.col) return false; return value == other.value; } bool model_iterator::cell::operator!= (const cell& other) const { return !operator==(other); } class model_iterator::impl { public: virtual bool has() const = 0; virtual void next() = 0; virtual const model_iterator::cell& get() const = 0; virtual ~impl() {} }; namespace { class iterator_core_empty : public model_iterator::impl { model_iterator::cell m_cell; public: bool has() const override { return false; } void next() override {} const model_iterator::cell& get() const override { return m_cell; } }; class iterator_core_horizontal : public model_iterator::impl { using collection_type = mdds::mtv::collection; collection_type m_collection; mutable model_iterator::cell m_current_cell; mutable bool m_update_current_cell; collection_type::const_iterator m_current_pos; collection_type::const_iterator m_end; void update_current() const { m_current_cell.col = m_current_pos->index; m_current_cell.row = m_current_pos->position; switch (m_current_pos->type) { case element_type_boolean: m_current_cell.type = celltype_t::boolean; m_current_cell.value = m_current_pos->get(); break; case element_type_numeric: m_current_cell.type = celltype_t::numeric; m_current_cell.value = m_current_pos->get(); break; case element_type_string: m_current_cell.type = celltype_t::string; m_current_cell.value = m_current_pos->get(); break; case element_type_formula: m_current_cell.type = celltype_t::formula; m_current_cell.value = m_current_pos->get(); break; case element_type_empty: m_current_cell.type = celltype_t::empty; m_current_cell.value = false; default: ; } m_update_current_cell = false; } public: iterator_core_horizontal(const detail::model_context_impl& cxt, sheet_t sheet, const abs_rc_range_t& range) : m_update_current_cell(true) { const column_stores_t* cols = cxt.get_columns(sheet); if (cols && !cols->empty()) { collection_type c = mdds::mtv::collection(cols->begin(), cols->end()); if (range.valid()) { if (!range.all_columns()) { col_t c1 = range.first.column == column_unset ? 0 : range.first.column; col_t c2 = range.last.column == column_unset ? (cols->size() - 1) : range.last.column; assert(c1 >= 0); assert(c1 <= c2); size_t start = c1; size_t size = c2 - c1 + 1; c.set_collection_range(start, size); } if (!range.all_rows()) { const column_store_t& col = (*cols)[0]; row_t r1 = range.first.row == row_unset ? 0 : range.first.row; row_t r2 = range.last.row == row_unset ? (col.size() - 1) : range.last.row; assert(r1 >= 0); assert(r1 <= r2); size_t start = r1; size_t size = r2 - r1 + 1; c.set_element_range(start, size); } } m_collection.swap(c); } m_current_pos = m_collection.begin(); m_end = m_collection.end(); } virtual bool has() const override { return m_current_pos != m_end; } virtual void next() override { ++m_current_pos; m_update_current_cell = true; } virtual const model_iterator::cell& get() const override { if (m_update_current_cell) update_current(); return m_current_cell; } }; class iterator_core_vertical : public model_iterator::impl { const column_stores_t* m_cols; mutable model_iterator::cell m_current_cell; mutable bool m_update_current_cell; column_stores_t::const_iterator m_it_cols; column_stores_t::const_iterator m_it_cols_begin; column_stores_t::const_iterator m_it_cols_end; column_store_t::const_position_type m_current_pos; column_store_t::const_position_type m_end_pos; row_t m_row_first; row_t m_row_last; void update_current() const { column_store_t::const_iterator blk_pos = m_current_pos.first; switch (blk_pos->type) { case element_type_empty: m_current_cell.type = celltype_t::empty; m_current_cell.value = false; break; case element_type_boolean: m_current_cell.type = celltype_t::boolean; m_current_cell.value = column_store_t::get(m_current_pos); break; case element_type_numeric: m_current_cell.type = celltype_t::numeric; m_current_cell.value = column_store_t::get(m_current_pos); break; case element_type_string: m_current_cell.type = celltype_t::string; m_current_cell.value = column_store_t::get(m_current_pos); break; case element_type_formula: m_current_cell.type = celltype_t::formula; m_current_cell.value = column_store_t::get(m_current_pos); break; default: throw std::logic_error("unhandled element type."); } m_current_cell.row = column_store_t::logical_position(m_current_pos); m_current_cell.col = std::distance(m_it_cols_begin, m_it_cols); m_update_current_cell = false; } public: iterator_core_vertical(const detail::model_context_impl& cxt, sheet_t sheet, const abs_rc_range_t& range) : m_update_current_cell(true), m_row_first(0), m_row_last(row_unset) { m_cols = cxt.get_columns(sheet); if (!m_cols) return; m_it_cols_begin = m_cols->begin(); m_it_cols = m_it_cols_begin; m_it_cols_end = m_cols->end(); if (m_it_cols_begin == m_it_cols_end) return; m_row_last = (*m_cols)[0].size() - 1; if (range.valid()) { col_t last_col = m_cols->size() - 1; if (range.last.column != column_unset && range.last.column < last_col) { // Shrink the tail end. col_t diff = range.last.column - last_col; assert(diff < 0); std::advance(m_it_cols_end, diff); last_col += diff; } if (range.first.column != column_unset) { if (range.first.column <= last_col) std::advance(m_it_cols, range.first.column); else { // First column is past the last column. Nothing to parse. m_it_cols_begin = m_it_cols_end; return; } } if (range.last.row != row_unset && range.last.row < m_row_last) { // Shrink the tail end. m_row_last = range.last.row; } if (range.first.row != row_unset) { if (range.first.row <= m_row_last) m_row_first = range.first.row; else { // First row is past the last row. Set it to an empty // range and bail out. m_it_cols_begin = m_it_cols_end; return; } } } const column_store_t& col = *m_it_cols; m_current_pos = col.position(m_row_first); m_end_pos = col.position(m_row_last+1); } bool has() const override { if (!m_cols) return false; return m_it_cols != m_it_cols_end; } void next() override { m_update_current_cell = true; m_current_pos = column_store_t::next_position(m_current_pos); const column_store_t* col = &*m_it_cols; if (m_current_pos != m_end_pos) // It hasn't reached the end of the current column yet. return; ++m_it_cols; // Move to the next column. if (m_it_cols == m_it_cols_end) return; // Reset the position to the first cell in the new column. col = &*m_it_cols; m_current_pos = col->position(m_row_first); m_end_pos = col->position(m_row_last+1); } const model_iterator::cell& get() const override { if (m_update_current_cell) update_current(); return m_current_cell; } }; } // anonymous namespace model_iterator::model_iterator() : mp_impl(std::make_unique()) {} model_iterator::model_iterator(const detail::model_context_impl& cxt, sheet_t sheet, const abs_rc_range_t& range, rc_direction_t dir) { switch (dir) { case rc_direction_t::horizontal: mp_impl = std::make_unique(cxt, sheet, range); break; case rc_direction_t::vertical: mp_impl = std::make_unique(cxt, sheet, range); break; } } model_iterator::model_iterator(model_iterator&& other) : mp_impl(std::move(other.mp_impl)) {} model_iterator::~model_iterator() {} model_iterator& model_iterator::operator= (model_iterator&& other) { mp_impl = std::move(other.mp_impl); other.mp_impl = std::make_unique(); return *this; } bool model_iterator::has() const { return mp_impl->has(); } void model_iterator::next() { mp_impl->next(); } const model_iterator::cell& model_iterator::get() const { return mp_impl->get(); } std::ostream& operator<< (std::ostream& os, const model_iterator::cell& c) { os << "(row=" << c.row << "; col=" << c.col << "; type=" << short(c.type); switch (c.type) { case celltype_t::boolean: os << "; boolean=" << std::get(c.value); break; case celltype_t::formula: os << "; formula=" << std::get(c.value); break; case celltype_t::numeric: os << "; numeric=" << std::get(c.value); break; case celltype_t::string: os << "; string=" << std::get(c.value); break; case celltype_t::empty: os << "; empty"; break; case celltype_t::unknown: default: ; } os << ')'; return os; } } // namespace ixion /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/makefile.mk0000644000175000017500000000150213273351731015052 00000000000000EXTERNAL_WARNINGS_NOT_ERRORS := TRUE PRJ=..$/..$/..$/..$/..$/.. PRJNAME=libixion TARGET=ixionlib ENABLE_EXCEPTIONS=TRUE LIBTARGET=NO .INCLUDE : settings.mk CFLAGS+=-I..$/..$/inc .IF "$(GUI)"=="WNT" CFLAGS+=-GR .ENDIF .IF "$(COM)"=="GCC" CFLAGSCXX+=-frtti .ENDIF SLOFILES= \ $(SLO)$/cell.obj \ $(SLO)$/cell_queue_manager.obj \ $(SLO)$/depends_tracker.obj \ $(SLO)$/formula_functions.obj \ $(SLO)$/formula_interpreter.obj \ $(SLO)$/formula_lexer.obj \ $(SLO)$/formula_parser.obj \ $(SLO)$/formula_result.obj \ $(SLO)$/formula_tokens.obj \ $(SLO)$/global.obj \ $(SLO)$/lexer_tokens.obj \ $(SLO)$/mem_str_buf.obj \ $(SLO)$/model_parser.obj \ $(SLO)$/sort_input_parser.obj \ LIB1ARCHIV=$(LB)$/libixionlib.a LIB1TARGET=$(SLB)$/$(TARGET).lib LIB1OBJFILES= $(SLOFILES) .INCLUDE : target.mk libixion-0.17.0/src/libixion/interface.cpp0000644000175000017500000000176213273351731015420 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/interface/table_handler.hpp" #include "ixion/interface/session_handler.hpp" #include "ixion/interface/formula_model_access.hpp" namespace ixion { namespace iface { table_handler::~table_handler() {} session_handler::~session_handler() {} formula_model_access::formula_model_access() {} formula_model_access::~formula_model_access() {} std::unique_ptr formula_model_access::create_session_handler() { return std::unique_ptr(); } table_handler* formula_model_access::get_table_handler() { return nullptr; } const table_handler* formula_model_access::get_table_handler() const { return nullptr; } }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/cell.cpp0000664000175000017500000004504114122770261014374 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/cell.hpp" #include "ixion/address.hpp" #include "ixion/exceptions.hpp" #include "ixion/formula_result.hpp" #include "ixion/formula_tokens.hpp" #include "ixion/interface/formula_model_access.hpp" #include "ixion/interface/session_handler.hpp" #include "ixion/global.hpp" #include "ixion/matrix.hpp" #include "ixion/formula_name_resolver.hpp" #include "ixion/formula.hpp" #include "formula_interpreter.hpp" #include "debug.hpp" #include #include #include #include #include #include #include "calc_status.hpp" #define FORMULA_CIRCULAR_SAFE 0x01 #define FORMULA_SHARED_TOKENS 0x02 using namespace std; namespace ixion { namespace { #if IXION_LOGGING std::string gen_trace_output(const formula_cell& fc, const iface::formula_model_access& cxt, const abs_address_t& pos) { auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); std::ostringstream os; os << "pos=" << pos.get_name() << "; formula='" << print_formula_tokens(cxt, pos, *resolver, fc.get_tokens()->get()) << "'"; return os.str(); } #endif } struct formula_cell::impl { mutable calc_status_ptr_t m_calc_status; formula_tokens_store_ptr_t m_tokens; rc_address_t m_group_pos; impl() : impl(-1, -1, new calc_status, formula_tokens_store_ptr_t()) {} impl(const formula_tokens_store_ptr_t& tokens) : impl(-1, -1, new calc_status, tokens) {} impl(row_t row, col_t col, const calc_status_ptr_t& cs, const formula_tokens_store_ptr_t& tokens) : m_calc_status(cs), m_tokens(tokens), m_group_pos(row, col, false, false) {} /** * Block until the result becomes available. * * @param lock mutex lock associated with the result cache data. */ void wait_for_interpreted_result(std::unique_lock& lock) const { IXION_TRACE("Wait for the interpreted result"); while (!m_calc_status->result) { IXION_TRACE("Waiting..."); m_calc_status->cond.wait(lock); } } void reset_flag() { m_calc_status->circular_safe = false; } /** * Check if this cell contains a circular reference. * * @return true if this cell contains no circular reference, hence * considered "safe", false otherwise. */ bool is_circular_safe() const { return m_calc_status->circular_safe; } bool check_ref_for_circular_safety(const formula_cell& ref, const abs_address_t& pos) { if (!ref.mp_impl->is_circular_safe()) { // Circular dependency detected !! IXION_DEBUG("Circular dependency detected !!"); assert(!m_calc_status->result); m_calc_status->result = std::make_unique(formula_error_t::ref_result_not_available); return false; } return true; } void check_calc_status_or_throw() const { if (!m_calc_status->result) { // Result not cached yet. Reference error. IXION_DEBUG("Result not cached yet. This is a reference error."); throw formula_error(formula_error_t::ref_result_not_available); } if (m_calc_status->result->get_type() == formula_result::result_type::error) { // Error condition. IXION_DEBUG("Error in result."); throw formula_error(m_calc_status->result->get_error()); } } double fetch_value_from_result() const { check_calc_status_or_throw(); switch (m_calc_status->result->get_type()) { case formula_result::result_type::value: return m_calc_status->result->get_value(); case formula_result::result_type::matrix: { IXION_TRACE("Fetching a matrix result."); const matrix& m = m_calc_status->result->get_matrix(); row_t row_size = m.row_size(); col_t col_size = m.col_size(); if (m_group_pos.row >= row_size || m_group_pos.column >= col_size) throw formula_error(formula_error_t::invalid_value_type); matrix::element elem = m.get(m_group_pos.row, m_group_pos.column); switch (elem.type) { case matrix::element_type::numeric: return std::get(elem.value); case matrix::element_type::empty: return 0.0; case matrix::element_type::boolean: return std::get(elem.value) ? 1.0 : 0.0; case matrix::element_type::string: case matrix::element_type::error: default: throw formula_error(formula_error_t::invalid_value_type); } } default: { std::ostringstream os; os << "numeric result was requested, but the actual result is of " << m_calc_status->result->get_type() << " type."; throw formula_error( formula_error_t::invalid_value_type, os.str() ); } } } std::string_view fetch_string_from_result() const { check_calc_status_or_throw(); switch (m_calc_status->result->get_type()) { case formula_result::result_type::string: return m_calc_status->result->get_string(); case formula_result::result_type::matrix: { const matrix& m = m_calc_status->result->get_matrix(); row_t row_size = m.row_size(); col_t col_size = m.col_size(); if (m_group_pos.row >= row_size || m_group_pos.column >= col_size) throw formula_error(formula_error_t::invalid_value_type); matrix::element elem = m.get(m_group_pos.row, m_group_pos.column); switch (elem.type) { case matrix::element_type::string: return std::get(elem.value); case matrix::element_type::numeric: case matrix::element_type::empty: case matrix::element_type::boolean: case matrix::element_type::error: default: throw formula_error(formula_error_t::invalid_value_type); } } default: { std::ostringstream os; os << "string result was requested, but the actual result is of " << m_calc_status->result->get_type() << " type."; throw formula_error( formula_error_t::invalid_value_type, os.str() ); } } return std::string_view{}; } bool is_grouped() const { return m_group_pos.column >= 0 && m_group_pos.row >= 0; } bool is_group_parent() const { return m_group_pos.column == 0 && m_group_pos.row == 0; } bool calc_allowed() const { if (!is_grouped()) return true; return is_group_parent(); } formula_result get_single_formula_result(const formula_result& src) const { if (!is_grouped()) return src; // returns a copy. if (src.get_type() != formula_result::result_type::matrix) // A grouped cell should have a matrix result whose size equals the // size of the group. But in case of anything else, just return the // stored value. return src; const matrix& m = src.get_matrix(); row_t row_size = m.row_size(); col_t col_size = m.col_size(); if (m_group_pos.row >= row_size || m_group_pos.column >= col_size) return formula_result(formula_error_t::invalid_value_type); matrix::element elem = m.get(m_group_pos.row, m_group_pos.column); switch (elem.type) { case matrix::element_type::numeric: return formula_result(std::get(elem.value)); case matrix::element_type::string: { std::string s{std::get(elem.value)}; return formula_result(std::move(s)); } case matrix::element_type::error: return formula_result(std::get(elem.value)); case matrix::element_type::empty: return formula_result(); case matrix::element_type::boolean: return formula_result(std::get(elem.value) ? 1.0 : 0.0); default: throw std::logic_error("unhandled element type of a matrix result value."); } } void set_single_formula_result(formula_result result) { if (is_grouped()) { std::unique_lock lock(m_calc_status->mtx); if (!m_calc_status->result) { m_calc_status->result = std::make_unique( matrix(m_calc_status->group_size.row, m_calc_status->group_size.column)); } matrix& m = m_calc_status->result->get_matrix(); assert(m_group_pos.row < row_t(m.row_size())); assert(m_group_pos.column < col_t(m.col_size())); switch (result.get_type()) { case formula_result::result_type::value: m.set(m_group_pos.row, m_group_pos.column, result.get_value()); break; case formula_result::result_type::string: m.set(m_group_pos.row, m_group_pos.column, result.get_string()); break; case formula_result::result_type::error: m.set(m_group_pos.row, m_group_pos.column, result.get_error()); break; case formula_result::result_type::matrix: throw std::logic_error("setting a cached result of matrix value directly is not yet supported."); } return; } std::unique_lock lock(m_calc_status->mtx); m_calc_status->result = std::make_unique(std::move(result)); } }; formula_cell::formula_cell() : mp_impl(std::make_unique()) {} formula_cell::formula_cell(const formula_tokens_store_ptr_t& tokens) : mp_impl(std::make_unique(tokens)) {} formula_cell::formula_cell( row_t group_row, col_t group_col, const calc_status_ptr_t& cs, const formula_tokens_store_ptr_t& tokens) : mp_impl(std::make_unique(group_row, group_col, cs, tokens)) {} formula_cell::~formula_cell() { } const formula_tokens_store_ptr_t& formula_cell::get_tokens() const { return mp_impl->m_tokens; } void formula_cell::set_tokens(const formula_tokens_store_ptr_t& tokens) { mp_impl->m_tokens = tokens; } double formula_cell::get_value(formula_result_wait_policy_t policy) const { std::unique_lock lock(mp_impl->m_calc_status->mtx); if (policy == formula_result_wait_policy_t::block_until_done) mp_impl->wait_for_interpreted_result(lock); return mp_impl->fetch_value_from_result(); } std::string_view formula_cell::get_string(formula_result_wait_policy_t policy) const { std::unique_lock lock(mp_impl->m_calc_status->mtx); if (policy == formula_result_wait_policy_t::block_until_done) mp_impl->wait_for_interpreted_result(lock); return mp_impl->fetch_string_from_result(); } void formula_cell::interpret(iface::formula_model_access& context, const abs_address_t& pos) { IXION_TRACE(gen_trace_output(*this, context, pos)); if (!mp_impl->calc_allowed()) throw std::logic_error("Calculation on this formula cell is not allowed."); calc_status& status = *mp_impl->m_calc_status; { std::lock_guard lock(status.mtx); if (mp_impl->m_calc_status->result) { // When the result is already cached before the cell is interpreted, // it can mean the cell has circular dependency. if (status.result->get_type() == formula_result::result_type::error) { auto handler = context.create_session_handler(); if (handler) { handler->begin_cell_interpret(pos); std::string_view msg = get_formula_error_name(status.result->get_error()); handler->set_formula_error(msg); handler->end_cell_interpret(); } } return; } formula_interpreter fin(this, context); fin.set_origin(pos); status.result = std::make_unique(); if (fin.interpret()) { // Successful interpretation. *status.result = fin.transfer_result(); } else { // Interpretation ended with an error condition. status.result->set_error(fin.get_error()); } } status.cond.notify_all(); } void formula_cell::check_circular(const iface::formula_model_access& cxt, const abs_address_t& pos) { // TODO: Check to make sure this is being run on the main thread only. const formula_tokens_t& tokens = mp_impl->m_tokens->get(); for (const std::unique_ptr& t : tokens) { switch (t->get_opcode()) { case fop_single_ref: { abs_address_t addr = t->get_single_ref().to_abs(pos); const formula_cell* ref = cxt.get_formula_cell(addr); if (!ref) continue; if (!mp_impl->check_ref_for_circular_safety(*ref, addr)) return; break; } case fop_range_ref: { abs_range_t range = t->get_range_ref().to_abs(pos); for (sheet_t sheet = range.first.sheet; sheet <= range.last.sheet; ++sheet) { rc_size_t sheet_size = cxt.get_sheet_size(); col_t col_first = range.first.column, col_last = range.last.column; if (range.all_columns()) { col_first = 0; col_last = sheet_size.column - 1; } for (col_t col = col_first; col <= col_last; ++col) { row_t row_first = range.first.row, row_last = range.last.row; if (range.all_rows()) { assert(row_last == row_unset); row_first = 0; row_last = sheet_size.row - 1; } for (row_t row = row_first; row <= row_last; ++row) { abs_address_t addr(sheet, row, col); if (cxt.get_celltype(addr) != celltype_t::formula) continue; if (!mp_impl->check_ref_for_circular_safety(*cxt.get_formula_cell(addr), addr)) return; } } } break; } default: ; } } // No circular dependencies. Good. mp_impl->m_calc_status->circular_safe = true; } void formula_cell::reset() { std::lock_guard lock(mp_impl->m_calc_status->mtx); mp_impl->m_calc_status->result.reset(); mp_impl->reset_flag(); } std::vector formula_cell::get_ref_tokens( const iface::formula_model_access& cxt, const abs_address_t& pos) const { std::vector ret; std::function get_refs = [&](const formula_tokens_t::value_type& t) { switch (t->get_opcode()) { case fop_single_ref: case fop_range_ref: ret.push_back(t.get()); break; case fop_named_expression: { const named_expression_t* named_exp = cxt.get_named_expression(pos.sheet, t->get_name()); if (!named_exp) // silently ignore non-existing names. break; // recursive call. std::for_each(named_exp->tokens.begin(), named_exp->tokens.end(), get_refs); break; } default: ; // ignore the rest. } }; const formula_tokens_t& this_tokens = mp_impl->m_tokens->get(); std::for_each(this_tokens.begin(), this_tokens.end(), get_refs); return ret; } const formula_result& formula_cell::get_raw_result_cache(formula_result_wait_policy_t policy) const { std::unique_lock lock(mp_impl->m_calc_status->mtx); if (policy == formula_result_wait_policy_t::block_until_done) mp_impl->wait_for_interpreted_result(lock); if (!mp_impl->m_calc_status->result) { IXION_DEBUG("Result not yet available."); throw formula_error(formula_error_t::ref_result_not_available); } return *mp_impl->m_calc_status->result; } formula_result formula_cell::get_result_cache(formula_result_wait_policy_t policy) const { const formula_result& src = get_raw_result_cache(policy); return mp_impl->get_single_formula_result(src); } void formula_cell::set_result_cache(formula_result result) { mp_impl->set_single_formula_result(result); } formula_group_t formula_cell::get_group_properties() const { uintptr_t identity = reinterpret_cast(mp_impl->m_calc_status.get()); return formula_group_t(mp_impl->m_calc_status->group_size, identity, mp_impl->is_grouped()); } abs_address_t formula_cell::get_parent_position(const abs_address_t& pos) const { if (!mp_impl->is_grouped()) return pos; abs_address_t parent_pos = pos; parent_pos.column -= mp_impl->m_group_pos.column; parent_pos.row -= mp_impl->m_group_pos.row; return parent_pos; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/calc_status.cpp0000644000175000017500000000135413357222626015765 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "calc_status.hpp" namespace ixion { calc_status::calc_status() : result(nullptr), circular_safe(false), refcount(0) {} calc_status::calc_status(const rc_size_t& _group_size) : result(nullptr), group_size(_group_size), circular_safe(false), refcount(0) {} void calc_status::add_ref() { ++refcount; } void calc_status::release_ref() { if (--refcount == 0) delete this; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/document_test.cpp0000664000175000017500000000672714122770261016342 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/document.hpp" #include "ixion/address.hpp" #include "ixion/macros.hpp" #include "ixion/cell_access.hpp" #include #include #include using namespace std; using namespace ixion; namespace { bool equal(double v1, double v2) { // To work around the floating point rounding errors, convert the values to // strings then compare as string numbers. std::ostringstream os1, os2; os1 << v1; os2 << v2; return os1.str() == os2.str(); } } void test_basic_calc() { abs_address_t A1(0, 0, 0); abs_address_t A2(0, 1, 0); abs_address_t A3(0, 2, 0); document doc; doc.append_sheet("test"); doc.set_numeric_cell("A1", 1.1); doc.set_numeric_cell(A2, 1.2); doc.set_numeric_cell({IXION_ASCII("A3")}, 1.3); assert(doc.get_numeric_value(A1) == 1.1); assert(doc.get_numeric_value("A2") == 1.2); assert(doc.get_numeric_value(A3) == 1.3); doc.set_formula_cell("B4", "SUM(A1:A3)"); doc.calculate(0); double v = doc.get_numeric_value("B4"); assert(equal(v, 3.6)); doc.empty_cell(A2); doc.calculate(0); v = doc.get_numeric_value("B4"); assert(equal(v, 2.4)); } void test_string_io() { document doc; doc.append_sheet("test"); std::string B3("B3"), C4("C4"), D5("D5"), D5_value("Cell D5 value"); doc.set_string_cell(B3, "Cell B3"); doc.set_string_cell(C4, "Cell C4"); doc.set_string_cell(D5, D5_value); std::string_view s = doc.get_string_value(B3); assert(s == "Cell B3"); s = doc.get_string_value(C4); assert(s == "Cell C4"); s = doc.get_string_value(D5); assert(s == D5_value); doc.set_formula_cell("A10", "CONCATENATE(B3, \" and \", C4)"); doc.calculate(0); s = doc.get_string_value("A10"); assert(s == "Cell B3 and Cell C4"); doc.empty_cell(C4); doc.calculate(0); s = doc.get_string_value("A10"); assert(s == "Cell B3 and "); } void test_boolean_io() { document doc; doc.append_sheet("test1"); doc.append_sheet("test2"); doc.set_boolean_cell("test2!B2", true); doc.set_boolean_cell("test2!C3", false); doc.set_formula_cell("test1!A1", "SUM(test2!A1:D4)"); doc.calculate(0); double v = doc.get_numeric_value("test1!A1"); assert(v == 1.0); // Trigger recalculation. doc.set_boolean_cell("test2!C4", true); doc.calculate(0); v = doc.get_numeric_value("test1!A1"); assert(v == 2.0); cell_access ca = doc.get_cell_access("test2!B2"); assert(ca.get_type() == celltype_t::boolean); assert(ca.get_value_type() == cell_value_t::boolean); ca = doc.get_cell_access("test2!C3"); assert(ca.get_type() == celltype_t::boolean); assert(ca.get_value_type() == cell_value_t::boolean); } void test_custom_cell_address_syntax() { document doc(formula_name_resolver_t::excel_r1c1); doc.append_sheet("MySheet"); doc.set_numeric_cell("R3C3", 345.0); abs_address_t R3C3(0, 2, 2); double v = doc.get_numeric_value(R3C3); assert(v == 345.0); } int main() { test_basic_calc(); test_string_io(); test_boolean_io(); test_custom_cell_address_syntax(); return EXIT_SUCCESS; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/compute_engine_vulkan.hpp0000664000175000017500000000176214122770261020045 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_COMPUTE_ENGINE_VULKAN_HPP #define INCLUDED_IXION_COMPUTE_ENGINE_VULKAN_HPP #include "ixion/compute_engine.hpp" #include "vulkan_obj.hpp" namespace ixion { namespace draft { class compute_engine_vulkan final : public compute_engine { vk_instance m_instance; vk_device m_device; vk_command_pool m_cmd_pool; void copy_to_device_local_buffer( array& io, vk_buffer& host_buffer, vk_buffer& device_buffer); public: compute_engine_vulkan(); virtual ~compute_engine_vulkan() override; virtual std::string_view get_name() const override; virtual void compute_fibonacci(array& io) override; }; }} #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/vulkan_obj.hpp0000664000175000017500000001711214053567674015631 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_VULKAN_OBJ_HPP #define INCLUDED_IXION_VULKAN_OBJ_HPP #include #include #include namespace ixion { namespace draft { template struct null_value; template struct null_value::value>::type> { static constexpr std::nullptr_t value = nullptr; }; template struct null_value::value>::type> { static constexpr T value = 0; }; struct runtime_context { uint32_t input_buffer_size = 0; }; class vk_buffer; class vk_command_buffer; class vk_command_pool; class vk_descriptor_set; class vk_descriptor_set_layout; class vk_fence; class vk_pipeline; class vk_pipeline_layout; class vk_instance { VkInstance m_instance = null_value::value; VkDebugUtilsMessengerEXT m_debug_messenger = null_value::value; public: vk_instance(); ~vk_instance(); VkInstance& get(); }; class vk_queue { VkQueue m_queue; public: vk_queue(VkQueue queue); ~vk_queue(); void submit(vk_command_buffer& cmd, vk_fence& fence, VkPipelineStageFlags dst_stages = 0); void wait_idle(); }; class vk_device { friend class vk_command_pool; friend class vk_buffer; static constexpr uint32_t QUEUE_FAMILY_NOT_SET = std::numeric_limits::max(); VkPhysicalDevice m_physical_device = null_value::value; VkPhysicalDeviceProperties m_physical_device_props; VkDevice m_device = null_value::value; uint32_t m_queue_family_index = QUEUE_FAMILY_NOT_SET; VkQueue m_queue = null_value::value; uint32_t get_queue_family_index() const { return m_queue_family_index; } public: vk_device(vk_instance& instance); ~vk_device(); VkDevice& get(); const VkDevice& get() const; VkPhysicalDevice get_physical_device(); const VkPhysicalDeviceLimits& get_physical_device_limits() const; vk_queue get_queue(); }; class vk_command_pool { friend class vk_command_buffer; VkDevice m_device = null_value::value; VkCommandPool m_cmd_pool = null_value::value; VkDevice& get_device(); VkCommandPool& get(); public: vk_command_pool(vk_device& device); ~vk_command_pool(); vk_command_buffer create_command_buffer(); }; class vk_command_buffer { friend class vk_command_pool; vk_command_pool& m_cmd_pool; VkCommandBuffer m_cmd_buffer = null_value::value; vk_command_buffer(vk_command_pool& cmd_pool); public: ~vk_command_buffer(); VkCommandBuffer& get(); void begin(); void end(); void copy_buffer(vk_buffer& src, vk_buffer& dst, VkDeviceSize size); void buffer_memory_barrier( const vk_buffer& buffer, VkAccessFlags src_access, VkAccessFlags dst_access, VkPipelineStageFlagBits src_stage, VkPipelineStageFlagBits dst_stage); void bind_pipeline(const vk_pipeline& pipeline, VkPipelineBindPoint bind_point); void bind_descriptor_set( VkPipelineBindPoint bind_point, const vk_pipeline_layout& pl_layout, const vk_descriptor_set& desc_set); void dispatch(uint32_t gc_x, uint32_t gc_y, uint32_t gc_z); }; class vk_buffer { vk_device& m_device; VkBuffer m_buffer = null_value::value; VkDeviceMemory m_memory = null_value::value; struct mem_type { uint32_t index; VkDeviceSize size; }; /** * Find a suitable device memory type that can be used to store data for * the buffer. * * @param mem_props desired memory properties. * * @return mem_type memory type as an index into the list of device memory * types, and the memory size as required by the buffer. */ mem_type find_memory_type(VkMemoryPropertyFlags mem_props) const; public: vk_buffer(vk_device& device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags mem_props); ~vk_buffer(); VkBuffer& get(); const VkBuffer& get() const; void write_to_memory(void* data, VkDeviceSize size); void read_from_memory(void* data, VkDeviceSize size); }; class vk_fence { vk_device& m_device; VkFence m_fence = null_value::value; public: vk_fence(vk_device& device, VkFenceCreateFlags flags); ~vk_fence(); VkFence& get(); void wait(); void reset(); }; class vk_descriptor_pool { vk_device& m_device; VkDescriptorPool m_pool = null_value::value; public: vk_descriptor_pool(vk_device& device, uint32_t max_sets, std::initializer_list sizes); ~vk_descriptor_pool(); vk_descriptor_set allocate(const vk_descriptor_set_layout& ds_layout); }; class vk_descriptor_set_layout { vk_device& m_device; VkDescriptorSetLayout m_ds_layout = null_value::value; public: vk_descriptor_set_layout(vk_device& device, std::initializer_list bindings); ~vk_descriptor_set_layout(); VkDescriptorSetLayout& get(); const VkDescriptorSetLayout& get() const; }; /** * Descriptor set contains a collection of descriptors. Think of a * descriptor as a handle into a resource, which can be a buffer or an * image. * * @see https://vkguide.dev/docs/chapter-4/descriptors/ * */ class vk_descriptor_set { friend class vk_descriptor_pool; VkDescriptorSet m_set = null_value::value; vk_descriptor_set(VkDescriptorSet ds); public: ~vk_descriptor_set(); VkDescriptorSet& get(); const VkDescriptorSet& get() const; /** * Update the descriptor set with the content of the device local buffer. * * @param device logical device * @param binding binding position * @param type descriptor type. * @param buffer device local buffer to get the content from. */ void update(const vk_device& device, uint32_t binding, VkDescriptorType type, const vk_buffer& buffer); }; class vk_pipeline_layout { vk_device& m_device; VkPipelineLayout m_layout = null_value::value; public: vk_pipeline_layout(vk_device& device, vk_descriptor_set_layout& ds_layout); ~vk_pipeline_layout(); VkPipelineLayout& get(); const VkPipelineLayout& get() const; }; class vk_pipeline_cache { vk_device& m_device; VkPipelineCache m_cache = null_value::value; public: vk_pipeline_cache(vk_device& device); ~vk_pipeline_cache(); VkPipelineCache& get(); const VkPipelineCache& get() const; }; class vk_shader_module { vk_device& m_device; VkShaderModule m_module = null_value::value; public: enum class module_type { fibonacci }; vk_shader_module(vk_device& device, module_type mt); ~vk_shader_module(); VkShaderModule& get(); const VkShaderModule& get() const; }; class vk_pipeline { vk_device& m_device; VkPipeline m_pipeline = null_value::value; public: vk_pipeline( const runtime_context& cxt, vk_device& device, vk_pipeline_layout& pl_layout, vk_pipeline_cache& pl_cache, vk_shader_module& shader); ~vk_pipeline(); VkPipeline& get(); const VkPipeline& get() const; }; }} #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/types.cpp0000664000175000017500000000420414122770261014615 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include namespace ixion { const sheet_t global_scope = -1; const sheet_t invalid_sheet = -2; const string_id_t empty_string_id = std::numeric_limits::max(); bool is_valid_sheet(sheet_t sheet) { return sheet >= 0; } rc_size_t::rc_size_t() : row(0), column(0) {} rc_size_t::rc_size_t(const rc_size_t& other) : row(other.row), column(other.column) {} rc_size_t::rc_size_t(row_t _row, col_t _column) : row(_row), column(_column) {} rc_size_t::~rc_size_t() {} rc_size_t& rc_size_t::operator= (const rc_size_t& other) { row = other.row; column = other.column; return *this; } formula_group_t::formula_group_t() : size(), identity(0), grouped(false) {} formula_group_t::formula_group_t(const formula_group_t& r) : size(r.size), identity(r.identity), grouped(r.grouped) {} formula_group_t::formula_group_t(const rc_size_t& _group_size, uintptr_t _identity, bool _grouped) : size(_group_size), identity(_identity), grouped(_grouped) {} formula_group_t::~formula_group_t() {} formula_group_t& formula_group_t::operator= (const formula_group_t& other) { size = other.size; identity = other.identity; return *this; } std::string_view get_formula_error_name(formula_error_t fe) { static const char* default_err_name = "#ERR!"; static const std::string_view names[] = { "", // 0: no error "#REF!", // 1: result not available "#DIV/0!", // 2: division by zero "#NUM!", // 3: invalid expression "#NAME?", // 4: name not found "#NULL!", // 5: no range intersection "#VALUE!", // 6: invalid value type }; if (std::size_t(fe) < IXION_N_ELEMENTS(names)) return names[std::size_t(fe)]; return default_err_name; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/module.cpp0000664000175000017500000000470014123215773014742 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/module.hpp" #include "ixion/info.hpp" #include "ixion/compute_engine.hpp" #include #include #include #ifdef _WIN32 #include #else #include #endif namespace fs = boost::filesystem; namespace ixion { namespace draft { namespace { const char* mod_names[] = { "vulkan" }; std::string get_module_prefix() { std::ostringstream os; os << "ixion-" << get_api_version_major() << "." << get_api_version_minor() << "-"; return os.str(); } typedef module_def* (*fp_register_module_type)(void); void register_module(void* mod_handler, std::string_view mod_name, fp_register_module_type fp_register_module) { if (!fp_register_module) return; module_def* md = fp_register_module(); compute_engine::add_class( mod_handler, mod_name, md->create_compute_engine, md->destroy_compute_engine); } } // anonymous namespace #ifdef _WIN32 void init_modules() { std::string mod_prefix = get_module_prefix(); for (const char* mod_name : mod_names) { std::ostringstream os; os << mod_prefix << mod_name << ".dll"; std::string modfile_name = os.str(); HMODULE hdl = LoadLibrary(modfile_name.c_str()); if (!hdl) continue; fp_register_module_type fp_register_module; *(void**)(&fp_register_module) = GetProcAddress(hdl, "register_module"); register_module(hdl, mod_name, fp_register_module); } } void unload_module(void* handler) { FreeLibrary((HMODULE)handler); } #else void init_modules() { std::string mod_prefix = get_module_prefix(); for (const char* mod_name : mod_names) { std::ostringstream os; os << mod_prefix << mod_name << ".so"; void* hdl = dlopen(os.str().data(), RTLD_NOW | RTLD_GLOBAL); if (!hdl) continue; fp_register_module_type fp_register_module; *(void**)(&fp_register_module) = dlsym(hdl, "register_module"); register_module(hdl, mod_name, fp_register_module); } } void unload_module(void* handler) { dlclose(handler); } #endif }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/config.cpp0000664000175000017500000000132413722272744014726 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/config.hpp" namespace ixion { config::config() : sep_function_arg(','), sep_matrix_column(','), sep_matrix_row(';'), output_precision(-1) {} config::config(const config& r) : sep_function_arg(r.sep_function_arg), sep_matrix_column(r.sep_matrix_column), sep_matrix_row(r.sep_matrix_row), output_precision(r.output_precision) {} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/compute_engine_test.cpp0000664000175000017500000000716014122770261017515 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "test_global.hpp" // This must be the first header to be included. #include #include #include #include #include #include #include #include #include #include using std::cout; using std::endl; namespace { class stack_printer { public: explicit stack_printer(std::string msg) : m_msg(std::move(msg)) { m_start_time = get_time(); } ~stack_printer() { double end_time = get_time(); std::cout << m_msg << ": duration = " << (end_time-m_start_time) << " sec" << std::endl; } private: double get_time() const { unsigned long usec_since_epoch = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); return usec_since_epoch / 1000000.0; } std::string m_msg; double m_start_time; }; using test_func_t = std::function; std::vector> tests; #define REGISTER_TEST(x) tests.emplace_back(#x, x); template void print_values(std::string_view msg, const T& values) { cout << msg << ": "; if (values.size() <= 20) std::copy(values.begin(), values.end(), std::ostream_iterator(cout, " ")); else { // Print only the first 15 and last 5 values. auto it = values.begin(); auto it_end = it + 15; std::copy(it, it_end, std::ostream_iterator(cout, " ")); cout << "... "; it_end = values.end(); it = it_end - 5; std::copy(it, it_end, std::ostream_iterator(cout, " ")); } cout << endl; } void print_summary(const std::shared_ptr& engine) { cout << "--" << endl; cout << "name: " << engine->get_name() << endl; std::vector values(16384u); uint32_t n = 0; std::generate(values.begin(), values.end(), [&n] { return n++; }); ixion::draft::array io{}; io.uint32 = values.data(); io.size = values.size(); io.type = ixion::draft::array_type::uint32; print_values("fibonacci input", values); { std::ostringstream os; os << "fibonacci (n=" << values.size() << ")"; stack_printer __stack_printer__(os.str()); engine->compute_fibonacci(io); } print_values("fibonacci output", values); } } void test_create_default() { std::shared_ptr p = ixion::draft::compute_engine::create(); assert(p); assert(p->get_name() == "default"); print_summary(p); } void test_create_vulkan() { std::shared_ptr p = ixion::draft::compute_engine::create("vulkan"); assert(p); assert(p->get_name() == "vulkan"); print_summary(p); } int main() { ixion::draft::init_modules(); REGISTER_TEST(test_create_default); #ifdef BUILD_VULKAN REGISTER_TEST(test_create_vulkan); #endif for (auto test : tests) { cout << "--------------------------" << endl; cout << " " << test.first << endl; cout << "--------------------------" << endl; test.second(); } return EXIT_SUCCESS; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/compute_engine.cpp0000664000175000017500000000554514122770261016463 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/compute_engine.hpp" #include "ixion/global.hpp" #include #include namespace ixion { namespace draft { namespace { struct class_factory { void* handler; create_compute_engine_t create; destroy_compute_engine_t destroy; }; class class_factory_store { using store_type = std::unordered_map; store_type m_store; public: const class_factory* get(std::string_view name) const { auto it = m_store.find(std::string(name)); if (it == m_store.end()) return nullptr; return &it->second; } void insert(void* hdl, std::string_view name, create_compute_engine_t func_create, destroy_compute_engine_t func_destroy) { class_factory cf; cf.handler = hdl; cf.create = func_create; cf.destroy = func_destroy; m_store.emplace(name, cf); } ~class_factory_store() { for (auto& kv : m_store) { class_factory& cf = kv.second; unload_module(cf.handler); } } }; class_factory_store store; } struct compute_engine::impl { impl() {} }; std::shared_ptr compute_engine::create(std::string_view name) { if (name.empty()) // Name is not specified. Use the default engine. return std::make_shared(); const class_factory* cf = store.get(name); if (!cf) // No class factory for this name. Fall back to default. return std::make_shared(); return std::shared_ptr(cf->create(), cf->destroy); } void compute_engine::add_class( void* hdl, std::string_view name, create_compute_engine_t func_create, destroy_compute_engine_t func_destroy) { store.insert(hdl, name, func_create, func_destroy); } compute_engine::compute_engine() : mp_impl(std::make_unique()) { } compute_engine::~compute_engine() { } std::string_view compute_engine::get_name() const { return "default"; } void compute_engine::compute_fibonacci(array& io) { if (io.type != array_type::uint32) return; auto fibonacci = [](uint32_t n) -> uint32_t { if (n <= 1) return n; uint32_t curr = 1; uint32_t prev = 1; for (uint32_t i = 2; i < n; ++i) { uint32_t temp = curr; curr += prev; prev = temp; } return curr; }; for (uint32_t i = 0; i < io.size; ++i) io.uint32[i] = fibonacci(io.uint32[i]); } }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/Makefile.am0000664000175000017500000000623014123220321014766 00000000000000 AM_CPPFLAGS = \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/include \ -DIXION_BUILD \ $(MDDS_CFLAGS) \ $(BOOST_CPPFLAGS) if BUILD_VULKAN AM_CPPFLAGS += -DBUILD_VULKAN endif # BUILD_VULKAN check_PROGRAMS = \ document-test \ ixion-test \ ixion-test-track-deps \ compute-engine-test \ dirty-cell-tracker-test lib_LTLIBRARIES = libixion-@IXION_API_VERSION@.la libixion_@IXION_API_VERSION@_la_SOURCES = \ address.cpp \ address_iterator.cpp \ calc_status.hpp \ calc_status.cpp \ cell.cpp \ cell_access.cpp \ column_store_type.hpp \ compute_engine.cpp \ concrete_formula_tokens.hpp \ concrete_formula_tokens.cpp \ config.cpp \ debug.hpp \ debug.cpp \ dirty_cell_tracker.cpp \ document.cpp \ exceptions.cpp \ formula.cpp \ formula_calc.cpp \ formula_function_opcode.cpp \ formula_functions.hpp \ formula_functions.cpp \ formula_interpreter.hpp \ formula_interpreter.cpp \ formula_lexer.hpp \ formula_lexer.cpp \ formula_name_resolver.cpp \ formula_parser.hpp \ formula_parser.cpp \ formula_result.cpp \ formula_tokens.cpp \ formula_value_stack.hpp \ formula_value_stack.cpp \ global.cpp \ info.cpp \ lexer_tokens.hpp \ lexer_tokens.cpp \ matrix.cpp \ mem_str_buf.cpp \ model_context.cpp \ model_context_impl.hpp \ model_context_impl.cpp \ model_iterator.cpp \ model_types.hpp \ model_types.cpp \ module.cpp \ named_expressions_iterator.cpp \ queue_entry.hpp \ queue_entry.cpp \ table.cpp \ types.cpp \ utils.hpp \ utils.cpp \ workbook.hpp \ workbook.cpp \ interface.cpp if BUILD_VULKAN # VULKAN module pkglib_LTLIBRARIES = ixion-@IXION_API_VERSION@-vulkan.la ixion_@IXION_API_VERSION@_vulkan_la_SOURCES = \ compute_engine_vulkan.hpp \ compute_engine_vulkan.cpp \ vulkan_obj.hpp \ vulkan_obj.cpp ixion_@IXION_API_VERSION@_vulkan_la_LDFLAGS = \ -module -avoid-version -export-symbols-regex \ register_module ixion_@IXION_API_VERSION@_vulkan_la_LIBADD = \ libixion-@IXION_API_VERSION@.la \ $(VULKAN_LIBS) ixion_@IXION_API_VERSION@_vulkan_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ $(VULKAN_CPPFLAGS) endif # BUILD_VULKAN if IXION_THREADS libixion_@IXION_API_VERSION@_la_SOURCES += \ cell_queue_manager.hpp \ cell_queue_manager.cpp endif libixion_@IXION_API_VERSION@_la_LDFLAGS = \ -no-undefined \ -Wl,-rpath,'$$ORIGIN' -Wl,-rpath,'$$ORIGIN/$(PACKAGE)' \ $(BOOST_FILESYSTEM_LDFLAGS) libixion_@IXION_API_VERSION@_la_LIBADD = \ $(BOOST_FILESYSTEM_LIBS) EXTRA_DIST = makefile.mk document_test_SOURCES = document_test.cpp document_test_LDADD = \ libixion-@IXION_API_VERSION@.la ixion_test_SOURCES = ixion_test.cpp ixion_test_LDADD = \ libixion-@IXION_API_VERSION@.la \ $(BOOST_PROGRAM_OPTIONS_LIBS) ixion_test_track_deps_SOURCES = ixion_test_track_deps.cpp ixion_test_track_deps_LDADD = \ libixion-@IXION_API_VERSION@.la \ $(BOOST_PROGRAM_OPTIONS_LIBS) compute_engine_test_SOURCES = compute_engine_test.cpp compute_engine_test_LDADD = \ libixion-@IXION_API_VERSION@.la dirty_cell_tracker_test_SOURCES = dirty_cell_tracker_test.cpp dirty_cell_tracker_test_LDADD = \ libixion-@IXION_API_VERSION@.la AM_TESTS_ENVIRONMENT = TESTS = \ document-test \ ixion-test \ ixion-test-track-deps \ compute-engine-test \ dirty-cell-tracker-test libixion-0.17.0/src/libixion/column_store_type.hpp0000664000175000017500000000460114105607506017233 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef IXION_COLUMN_STORE_TYPE_HPP #define IXION_COLUMN_STORE_TYPE_HPP #include "ixion/types.hpp" #include "ixion/cell.hpp" #include #include #include #include #include #include #include namespace ixion { // Element types constexpr mdds::mtv::element_t element_type_empty = mdds::mtv::element_type_empty; constexpr mdds::mtv::element_t element_type_boolean = mdds::mtv::element_type_boolean; constexpr mdds::mtv::element_t element_type_numeric = mdds::mtv::element_type_double; constexpr mdds::mtv::element_t element_type_string = mdds::mtv::element_type_uint32; constexpr mdds::mtv::element_t element_type_formula = mdds::mtv::element_type_user_start; // Element block types using boolean_element_block = mdds::mtv::boolean_element_block; using numeric_element_block = mdds::mtv::double_element_block; using string_element_block = mdds::mtv::uint32_element_block; using formula_element_block = mdds::mtv::noncopyable_managed_element_block; MDDS_MTV_DEFINE_ELEMENT_CALLBACKS_PTR(formula_cell, element_type_formula, nullptr, formula_element_block) using ixion_element_block_func = mdds::mtv::custom_block_func1; /** Type that represents a whole column. */ using column_store_t = mdds::multi_type_vector; /** Type that represents a collection of columns. */ using column_stores_t = std::deque; /** * The integer element blocks are used to store string ID's. The actual * string element blocks are not used in the matrix store in ixion. */ struct matrix_store_trait { typedef mdds::mtv::int64_element_block integer_element_block; typedef mdds::mtv::string_element_block string_element_block; typedef mdds::mtv::element_block_func element_block_func; }; using matrix_store_t = mdds::multi_type_matrix; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_lexer.cpp0000664000175000017500000001540514135564272016331 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "formula_lexer.hpp" #include "debug.hpp" #include "ixion/global.hpp" #include #include #include #include using namespace std; namespace ixion { class tokenizer { enum buffer_type { buf_numeral, buf_name }; public: tokenizer() = delete; tokenizer(const tokenizer&) = delete; tokenizer& operator= (tokenizer) = delete; explicit tokenizer(lexer_tokens_t& tokens, const char* p, size_t n) : m_tokens(tokens), m_sep_arg(','), m_sep_decimal('.'), mp_first(p), mp_char(NULL), m_size(n), m_pos(0), mp_char_stored(nullptr), m_pos_stored(0) { } void run(); void set_sep_arg(char c); private: bool is_arg_sep(char c) const; bool is_decimal_sep(char c) const; bool is_op(char c) const; void init(); void numeral(); void space(); void name(); void op(lexer_opcode_t oc); void string(); bool has_char() const; void next(); void push_pos(); void pop_pos(); private: lexer_tokens_t& m_tokens; char m_sep_arg; char m_sep_decimal; const char* mp_first; const char* mp_char; const size_t m_size; size_t m_pos; const char* mp_char_stored; size_t m_pos_stored; }; void tokenizer::init() { m_tokens.clear(); mp_char = mp_first; m_pos = 0; } void tokenizer::run() { if (!m_size) // Nothing to do. return; init(); while (has_char()) { if (std::isdigit(*mp_char)) { numeral(); continue; } if (!is_op(*mp_char)) { name(); continue; } if (is_arg_sep(*mp_char)) { op(lexer_opcode_t::sep); continue; } switch (*mp_char) { case ' ': space(); break; case '+': op(lexer_opcode_t::plus); break; case '-': op(lexer_opcode_t::minus); break; case '/': op(lexer_opcode_t::divide); break; case '*': op(lexer_opcode_t::multiply); break; case '^': op(lexer_opcode_t::exponent); break; case '&': op(lexer_opcode_t::concat); break; case '=': op(lexer_opcode_t::equal); break; case '<': op(lexer_opcode_t::less); break; case '>': op(lexer_opcode_t::greater); break; case '(': op(lexer_opcode_t::open); break; case ')': op(lexer_opcode_t::close); break; case '"': string(); break; } } } void tokenizer::set_sep_arg(char c) { m_sep_arg = c; } bool tokenizer::is_arg_sep(char c) const { return c == m_sep_arg; } bool tokenizer::is_decimal_sep(char c) const { return c == m_sep_decimal; } bool tokenizer::is_op(char c) const { if (is_arg_sep(c)) return true; switch (*mp_char) { case ' ': case '+': case '-': case '/': case '*': case '(': case ')': case '"': case '=': case '<': case '>': case '^': case '&': return true; } return false; } void tokenizer::numeral() { const char* p = mp_char; push_pos(); size_t len = 1; size_t sep_count = 0; for (next(); has_char(); next(), ++len) { if (*mp_char == ':') { // Treat this as a name. This may be a part of a row-only range (e.g. 3:3). pop_pos(); name(); return; } if (std::isdigit(*mp_char)) continue; if (is_decimal_sep(*mp_char) && ++sep_count <= 1) continue; break; } if (sep_count > 1) { // failed to parse this as a numeral. Treat this as a name. IXION_TRACE("error parsing '" << std::string(p, len) << "' as a numeral, treating it as a name."); pop_pos(); name(); return; } double val = to_double({p, len}); m_tokens.push_back(make_unique(val)); } void tokenizer::space() { // space is ignored for now. next(); } void tokenizer::name() { std::vector scopes; const char* p = mp_char; size_t len = 0; for (; has_char(); next(), ++len) { char c = *mp_char; if (!scopes.empty() && scopes.back() == c) { scopes.pop_back(); continue; } switch (c) { case '[': scopes.push_back(']'); continue; case '\'': scopes.push_back('\''); continue; } if (!scopes.empty()) continue; if (is_op(c)) break; } m_tokens.push_back(make_unique(p, len)); } void tokenizer::op(lexer_opcode_t oc) { m_tokens.push_back(make_unique(oc)); next(); } void tokenizer::string() { next(); const char* p = mp_char; size_t len = 0; for (; *mp_char != '"' && has_char(); ++len) next(); m_tokens.push_back(make_unique(p, len)); if (*mp_char == '"') next(); } void tokenizer::next() { ++mp_char; ++m_pos; } void tokenizer::push_pos() { mp_char_stored = mp_char; m_pos_stored = m_pos; } void tokenizer::pop_pos() { mp_char = mp_char_stored; m_pos = m_pos_stored; mp_char_stored = NULL; m_pos_stored = 0; } bool tokenizer::has_char() const { return m_pos < m_size; } // ============================================================================ formula_lexer::tokenize_error::tokenize_error(const string& msg) : general_error(msg) {} formula_lexer::formula_lexer(const config& config, const char* p, size_t n) : m_config(config), mp_first(p), m_size(n) {} formula_lexer::~formula_lexer() {} void formula_lexer::tokenize() { tokenizer tkr(m_tokens, mp_first, m_size); tkr.set_sep_arg(m_config.sep_function_arg); tkr.run(); } void formula_lexer::swap_tokens(lexer_tokens_t& tokens) { m_tokens.swap(tokens); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/lexer_tokens.cpp0000664000175000017500000001253214007343634016160 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "lexer_tokens.hpp" #include #include #include using namespace std; namespace ixion { namespace { class token_printer { public: token_printer(ostringstream& os, bool verbose) : m_os(os), m_verbose(verbose) {} void operator() (const unique_ptr& r) const { lexer_opcode_t oc = r->get_opcode(); if (m_verbose) m_os << "(" << get_opcode_name(oc) << ")'" << r->print() << "' "; else m_os << r->print(); } private: ostringstream& m_os; bool m_verbose; }; } string print_tokens(const lexer_tokens_t& tokens, bool verbose) { ostringstream os; for_each(tokens.begin(), tokens.end(), token_printer(os, verbose)); return os.str(); } // ============================================================================ const char* get_opcode_name(lexer_opcode_t oc) { switch (oc) { case lexer_opcode_t::value: return "value"; case lexer_opcode_t::string: return "string"; case lexer_opcode_t::name: return "name"; case lexer_opcode_t::divide: return "divide"; case lexer_opcode_t::minus: return "minus"; case lexer_opcode_t::multiply: return "multiply"; case lexer_opcode_t::exponent: return "exponent"; case lexer_opcode_t::concat: return "concat"; case lexer_opcode_t::equal: return "equal"; case lexer_opcode_t::less: return "less"; case lexer_opcode_t::greater: return "greater"; case lexer_opcode_t::plus: return "plus"; case lexer_opcode_t::open: return "open"; case lexer_opcode_t::close: return "close"; case lexer_opcode_t::sep: return "sep"; default: ; } return ""; } // ============================================================================ lexer_token_base::lexer_token_base(lexer_opcode_t oc) : m_opcode(oc) { } lexer_token_base::lexer_token_base(const lexer_token_base& r) : m_opcode(r.m_opcode) { } lexer_token_base::~lexer_token_base() { } lexer_opcode_t lexer_token_base::get_opcode() const { return m_opcode; } double lexer_token_base::get_value() const { return 0.0; } mem_str_buf lexer_token_base::get_string() const { return mem_str_buf(); } // ============================================================================ lexer_token::lexer_token(lexer_opcode_t oc) : lexer_token_base(oc) { } lexer_token::~lexer_token() { } string lexer_token::print() const { switch (get_opcode()) { case lexer_opcode_t::plus: return "+"; case lexer_opcode_t::minus: return "-"; case lexer_opcode_t::divide: return "/"; case lexer_opcode_t::multiply: return "*"; case lexer_opcode_t::exponent: return "^"; case lexer_opcode_t::concat: return "&"; case lexer_opcode_t::equal: return "="; case lexer_opcode_t::less: return "<"; case lexer_opcode_t::greater: return ">"; case lexer_opcode_t::open: return "("; case lexer_opcode_t::close: return ")"; case lexer_opcode_t::sep: return ","; case lexer_opcode_t::name: case lexer_opcode_t::string: case lexer_opcode_t::value: default: ; } return ""; } // ============================================================================ lexer_value_token::lexer_value_token(double val) : lexer_token_base(lexer_opcode_t::value), m_val(val) { } lexer_value_token::lexer_value_token(const lexer_value_token& r) : lexer_token_base(r), m_val(r.m_val) { } lexer_value_token::~lexer_value_token() { } double lexer_value_token::get_value() const { return m_val; } string lexer_value_token::print() const { ostringstream os; os << m_val; return os.str(); } // ============================================================================ lexer_string_token::lexer_string_token(const char* p, size_t n) : lexer_token_base(lexer_opcode_t::string), m_str(p, n) {} lexer_string_token::lexer_string_token(const lexer_string_token& r) : lexer_token_base(r), m_str(r.m_str) {} lexer_string_token::~lexer_string_token() {} mem_str_buf lexer_string_token::get_string() const { return m_str; } string lexer_string_token::print() const { return m_str.str(); } // ============================================================================ lexer_name_token::lexer_name_token(const char* p, size_t n) : lexer_token_base(lexer_opcode_t::name), m_str(p, n) {} lexer_name_token::lexer_name_token(const lexer_name_token& r) : lexer_token_base(r), m_str(r.m_str) {} lexer_name_token::~lexer_name_token() {} mem_str_buf lexer_name_token::get_string() const { return m_str; } string lexer_name_token::print() const { return m_str.str(); } // ============================================================================ } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/debug.cpp0000644000175000017500000000204113612422767014542 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "debug.hpp" #include "ixion/formula_name_resolver.hpp" #include "ixion/formula_tokens.hpp" #include "ixion/cell.hpp" #include "ixion/formula.hpp" #include namespace ixion { namespace detail { std::string print_formula_expression(const iface::formula_model_access& cxt, const abs_address_t& pos, const formula_cell& cell) { auto resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); assert(resolver); const formula_tokens_t& tokens = cell.get_tokens()->get(); return print_formula_tokens(cxt, pos, *resolver, tokens); } std::string print_formula_token_repr(const formula_token& t) { std::ostringstream os; os << t; return os.str(); } }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_function_opcode.cpp0000664000175000017500000000127214122770261020356 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/formula_function_opcode.hpp" #include "formula_functions.hpp" namespace ixion { std::string_view get_formula_function_name(formula_function_t func) { return formula_functions::get_function_name(func); } formula_function_t get_formula_function_opcode(std::string_view s) { return formula_functions::get_function_opcode(s); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/calc_status.hpp0000644000175000017500000000226213357222626015771 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_CALC_STATUS_HPP #define INCLUDED_IXION_CALC_STATUS_HPP #include "ixion/formula_result.hpp" #include #include #include namespace ixion { struct calc_status { calc_status(const calc_status&) = delete; calc_status& operator=(const calc_status&) = delete; std::mutex mtx; std::condition_variable cond; std::unique_ptr result; const rc_size_t group_size; bool circular_safe; size_t refcount; calc_status(); calc_status(const rc_size_t& _group_size); void add_ref(); void release_ref(); }; inline void intrusive_ptr_add_ref(calc_status* p) { p->add_ref(); } inline void intrusive_ptr_release(calc_status* p) { p->release_ref(); } using calc_status_ptr_t = boost::intrusive_ptr; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/debug.hpp0000664000175000017500000000235413722476424014561 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_DEBUG_HPP #define INCLUDED_IXION_DEBUG_HPP #include #if defined(IXION_DEBUG_ON) || defined(IXION_TRACE_ON) #include #endif #ifdef IXION_DEBUG_ON #define IXION_DEBUG(stream) \ do { std::cout << "[ixion]:[DEBUG]:" << __FUNCTION__ << ": " << stream << std::endl; } while (false) #else #define IXION_DEBUG(...) #endif #ifdef IXION_TRACE_ON #define IXION_TRACE(stream) \ do { std::cout << "[ixion]:[TRACE]:" << __FUNCTION__ << ": " << stream << std::endl; } while (false) #else #define IXION_TRACE(...) #endif namespace ixion { namespace iface { class formula_model_access; } class formula_cell; class formula_token; struct abs_address_t; namespace detail { std::string print_formula_expression(const iface::formula_model_access& cxt, const abs_address_t& pos, const formula_cell& cell); std::string print_formula_token_repr(const formula_token& t); }} #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/vulkan_obj.cpp0000664000175000017500000006136214053567674015632 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "vulkan_obj.hpp" #include "debug.hpp" #include "ixion/macros.hpp" #include #include #include #include #include #include namespace ixion { namespace draft { namespace { #include "vulkan_spirv_blobs.inl" VKAPI_ATTR VkBool32 VKAPI_CALL vulkan_debug_callback( VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type, const VkDebugUtilsMessengerCallbackDataEXT* cb_data, void* user) { IXION_DEBUG(cb_data->pMessage); return VK_FALSE; } /** * When the original size is not a multiple of the device's atom size, pad * it to the next multiple of the atom size. Certain memory operations * require the size to be a multiple of the atom size. */ VkDeviceSize pad_to_atom_size(const vk_device& device, VkDeviceSize src_size) { auto padded_size = src_size; auto atom_size = device.get_physical_device_limits().nonCoherentAtomSize; auto rem = padded_size % atom_size; if (rem) padded_size += atom_size - rem; return padded_size; } } // anonymous namespace vk_instance::vk_instance() { const char* validation_layer = "VK_LAYER_KHRONOS_validation"; const char* validation_ext = "VK_EXT_debug_utils"; VkApplicationInfo app_info = {}; app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.pApplicationName = "ixion-compute-engine-vulkan"; app_info.pEngineName = "none"; app_info.apiVersion = VK_API_VERSION_1_0; VkInstanceCreateInfo instance_ci = {}; instance_ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_ci.pApplicationInfo = &app_info; uint32_t n_layers; vkEnumerateInstanceLayerProperties(&n_layers, nullptr); std::vector layers(n_layers); vkEnumerateInstanceLayerProperties(&n_layers, layers.data()); IXION_TRACE("scanning for validation layer..."); bool has_validation_layer = false; for (const VkLayerProperties& props : layers) { if (!strcmp(props.layerName, validation_layer)) { IXION_TRACE("- " << props.layerName << " (found)"); has_validation_layer = true; break; } IXION_TRACE("- " << props.layerName); } if (has_validation_layer) { instance_ci.ppEnabledLayerNames = &validation_layer; instance_ci.enabledLayerCount = 1; instance_ci.enabledExtensionCount = 1; instance_ci.ppEnabledExtensionNames = &validation_ext; } VkResult res = vkCreateInstance(&instance_ci, nullptr, &m_instance); if (res != VK_SUCCESS) throw std::runtime_error("failed to create a vulkan instance."); if (has_validation_layer) { VkDebugUtilsMessengerCreateInfoEXT debug_ci{}; debug_ci.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; debug_ci.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; debug_ci.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; debug_ci.pfnUserCallback = vulkan_debug_callback; debug_ci.pUserData = nullptr; auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr( m_instance, "vkCreateDebugUtilsMessengerEXT"); if (func) { res = func(m_instance, &debug_ci, nullptr, &m_debug_messenger); if (res != VK_SUCCESS) throw std::runtime_error("failed to create debug utils messenger."); } } } vk_instance::~vk_instance() { if (m_debug_messenger) { auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr( m_instance, "vkDestroyDebugUtilsMessengerEXT"); if (func) func(m_instance, m_debug_messenger, nullptr); } vkDestroyInstance(m_instance, nullptr); } VkInstance& vk_instance::get() { return m_instance; } vk_queue::vk_queue(VkQueue queue) : m_queue(queue) {} vk_queue::~vk_queue() {} void vk_queue::submit(vk_command_buffer& cmd, vk_fence& fence, VkPipelineStageFlags dst_stages) { VkSubmitInfo info{}; info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; info.pWaitDstStageMask = dst_stages ? &dst_stages : nullptr; info.commandBufferCount = 1; info.pCommandBuffers = &cmd.get(); VkResult res = vkQueueSubmit(m_queue, 1, &info, fence.get()); if (res != VK_SUCCESS) throw std::runtime_error("failed to submit command to queue."); } void vk_queue::wait_idle() { vkQueueWaitIdle(m_queue); } vk_device::vk_device(vk_instance& instance) { uint32_t n_devices = 0; VkResult res = vkEnumeratePhysicalDevices(instance.get(), &n_devices, nullptr); if (res != VK_SUCCESS) throw std::runtime_error("failed to query the number of physical devices."); if (!n_devices) throw std::runtime_error("no vulkan devices found!"); std::vector devices(n_devices); res = vkEnumeratePhysicalDevices(instance.get(), &n_devices, devices.data()); if (res != VK_SUCCESS) throw std::runtime_error("failed to obtain the physical device data."); #ifdef IXION_TRACE_ON for (const VkPhysicalDevice pd : devices) { VkPhysicalDeviceProperties props; vkGetPhysicalDeviceProperties(pd, &props); IXION_TRACE("--"); IXION_TRACE("name: " << props.deviceName); IXION_TRACE("vendor ID: " << props.vendorID); IXION_TRACE("device ID: " << props.deviceID); } #endif m_physical_device = devices[0]; // pick the first physical device for now. vkGetPhysicalDeviceProperties(m_physical_device, &m_physical_device_props); { uint32_t n_qfs; vkGetPhysicalDeviceQueueFamilyProperties(m_physical_device, &n_qfs, nullptr); std::vector qf_props(n_qfs); vkGetPhysicalDeviceQueueFamilyProperties(m_physical_device, &n_qfs, qf_props.data()); IXION_TRACE("scanning for a queue family that supports compute..."); uint8_t current_n_flags = std::numeric_limits::max(); for (size_t i = 0; i < qf_props.size(); ++i) { uint8_t n_flags = 0; bool supports_compute = false; const VkQueueFamilyProperties& props = qf_props[i]; std::ostringstream os; os << "- queue family " << i << ": "; if (props.queueFlags & VK_QUEUE_GRAPHICS_BIT) { os << "graphics "; ++n_flags; } if (props.queueFlags & VK_QUEUE_COMPUTE_BIT) { os << "compute "; ++n_flags; supports_compute = true; } if (props.queueFlags & VK_QUEUE_TRANSFER_BIT) { os << "transfer "; ++n_flags; } if (props.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) { os << "sparse-binding "; ++n_flags; } if (props.queueFlags & VK_QUEUE_PROTECTED_BIT) { os << "protected "; ++n_flags; } if (supports_compute && n_flags < current_n_flags) { current_n_flags = n_flags; m_queue_family_index = i; os << "(picked)"; } IXION_TRACE(os.str()); } IXION_TRACE("final queue family index: " << m_queue_family_index); VkDeviceQueueCreateInfo queue_ci = {}; const float queue_prio = 0.0f; queue_ci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_ci.queueFamilyIndex = m_queue_family_index; queue_ci.queueCount = 1; queue_ci.pQueuePriorities = &queue_prio; VkDeviceCreateInfo device_ci = {}; device_ci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_ci.queueCreateInfoCount = 1; device_ci.pQueueCreateInfos = &queue_ci; res = vkCreateDevice(m_physical_device, &device_ci, nullptr, &m_device); if (res != VK_SUCCESS) throw std::runtime_error("failed to create a logical device."); vkGetDeviceQueue(m_device, m_queue_family_index, 0, &m_queue); } } vk_device::~vk_device() { vkDestroyDevice(m_device, nullptr); } VkDevice& vk_device::get() { return m_device; } const VkDevice& vk_device::get() const { return m_device; } VkPhysicalDevice vk_device::get_physical_device() { return m_physical_device; } const VkPhysicalDeviceLimits& vk_device::get_physical_device_limits() const { return m_physical_device_props.limits; } vk_queue vk_device::get_queue() { return vk_queue(m_queue); } VkDevice& vk_command_pool::get_device() { return m_device; } VkCommandPool& vk_command_pool::get() { return m_cmd_pool; } vk_command_pool::vk_command_pool(vk_device& device) : m_device(device.get()) { VkCommandPoolCreateInfo ci = {}; ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; ci.queueFamilyIndex = device.get_queue_family_index(); ci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; VkResult res = vkCreateCommandPool(device.get(), &ci, nullptr, &m_cmd_pool); if (res != VK_SUCCESS) throw std::runtime_error("failed to create command pool."); } vk_command_pool::~vk_command_pool() { vkDestroyCommandPool(m_device, m_cmd_pool, nullptr); } vk_command_buffer vk_command_pool::create_command_buffer() { return vk_command_buffer(*this); } vk_command_buffer::vk_command_buffer(vk_command_pool& cmd_pool) : m_cmd_pool(cmd_pool) { VkCommandBufferAllocateInfo cb_ai {}; cb_ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; cb_ai.commandPool = m_cmd_pool.get(); cb_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; cb_ai.commandBufferCount = 1; VkResult res = vkAllocateCommandBuffers(m_cmd_pool.get_device(), &cb_ai, &m_cmd_buffer); if (res != VK_SUCCESS) throw std::runtime_error("failed to create a command buffer."); } vk_command_buffer::~vk_command_buffer() { vkFreeCommandBuffers(m_cmd_pool.get_device(), m_cmd_pool.get(), 1, &m_cmd_buffer); } VkCommandBuffer& vk_command_buffer::get() { return m_cmd_buffer; } void vk_command_buffer::begin() { VkCommandBufferBeginInfo info{}; info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; vkBeginCommandBuffer(m_cmd_buffer, &info); } void vk_command_buffer::end() { vkEndCommandBuffer(m_cmd_buffer); } void vk_command_buffer::copy_buffer(vk_buffer& src, vk_buffer& dst, VkDeviceSize size) { VkBufferCopy copy_region{}; copy_region.size = size; vkCmdCopyBuffer(m_cmd_buffer, src.get(), dst.get(), 1, ©_region); } void vk_command_buffer::buffer_memory_barrier( const vk_buffer& buffer, VkAccessFlags src_access, VkAccessFlags dst_access, VkPipelineStageFlagBits src_stage, VkPipelineStageFlagBits dst_stage) { VkBufferMemoryBarrier info{}; info.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; info.buffer = buffer.get(); info.size = VK_WHOLE_SIZE; info.srcAccessMask = src_access; info.dstAccessMask = dst_access; info.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; info.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; vkCmdPipelineBarrier( m_cmd_buffer, src_stage, dst_stage, 0, 0, nullptr, 1, &info, 0, nullptr); } void vk_command_buffer::bind_pipeline( const vk_pipeline& pipeline, VkPipelineBindPoint bind_point) { vkCmdBindPipeline(m_cmd_buffer, bind_point, pipeline.get()); } void vk_command_buffer::bind_descriptor_set( VkPipelineBindPoint bind_point, const vk_pipeline_layout& pl_layout, const vk_descriptor_set& desc_set) { vkCmdBindDescriptorSets( m_cmd_buffer, bind_point, pl_layout.get(), 0, 1, &desc_set.get(), 0, 0); } void vk_command_buffer::dispatch(uint32_t gc_x, uint32_t gc_y, uint32_t gc_z) { vkCmdDispatch(m_cmd_buffer, gc_x, gc_y, gc_z); } vk_buffer::mem_type vk_buffer::find_memory_type(VkMemoryPropertyFlags mem_props) const { mem_type ret; VkPhysicalDeviceMemoryProperties pm_props; vkGetPhysicalDeviceMemoryProperties(m_device.get_physical_device(), &pm_props); VkMemoryRequirements mem_reqs; vkGetBufferMemoryRequirements(m_device.get(), m_buffer, &mem_reqs); ret.size = mem_reqs.size; IXION_TRACE("buffer memory requirements:"); IXION_TRACE(" - size: " << mem_reqs.size); IXION_TRACE(" - alignment: " << mem_reqs.alignment); IXION_TRACE(" - memory type bits: " << std::bitset<32>(mem_reqs.memoryTypeBits) << " (" << mem_reqs.memoryTypeBits << ")"); IXION_TRACE("requested memory property flags: 0x" << std::setw(2) << std::hex << std::setfill('0') << mem_props); IXION_TRACE("memory types: n=" << std::dec << pm_props.memoryTypeCount); for (uint32_t i = 0; i < pm_props.memoryTypeCount; ++i) { auto mt = pm_props.memoryTypes[i]; IXION_TRACE("- " << std::setw(2) << std::setfill('0') << i << ": property flags: " << std::bitset<32>(mt.propertyFlags) << " (0x" << std::setw(2) << std::hex << std::setfill('0') << mt.propertyFlags << "); heap index: " << std::dec << mt.heapIndex); if ((mem_reqs.memoryTypeBits & 1) == 1) { // The buffer can take this memory type. Now, check against // the requested usage types. if ((mt.propertyFlags & mem_props) == mem_props) { ret.index = i; return ret; } } mem_reqs.memoryTypeBits >>= 1; } throw std::runtime_error("no usable memory type found!"); } vk_buffer::vk_buffer(vk_device& device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags mem_props) : m_device(device) { VkBufferCreateInfo buf_ci {}; buf_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buf_ci.usage = usage; buf_ci.size = size; buf_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; IXION_TRACE("buffer usage flags: " << std::bitset<32>(usage) << " (0x" << std::hex << usage << ")"); IXION_TRACE("memory property flags: " << std::bitset<32>(mem_props) << " (0x" << std::hex << mem_props << ")"); IXION_TRACE("buffer size: " << std::dec << size); VkResult res = vkCreateBuffer(m_device.get(), &buf_ci, nullptr, &m_buffer); if (res != VK_SUCCESS) throw std::runtime_error("failed to create buffer."); mem_type mt = find_memory_type(mem_props); IXION_TRACE("memory type: (index=" << mt.index << "; size=" << mt.size << ")"); VkMemoryAllocateInfo mem_ai {}; mem_ai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; mem_ai.allocationSize = mt.size; mem_ai.memoryTypeIndex = mt.index; res = vkAllocateMemory(m_device.get(), &mem_ai, nullptr, &m_memory); if (res != VK_SUCCESS) throw std::runtime_error("failed to allocate memory."); res = vkBindBufferMemory(m_device.get(), m_buffer, m_memory, 0); if (res != VK_SUCCESS) throw std::runtime_error("failed to bind buffer to memory."); } vk_buffer::~vk_buffer() { vkFreeMemory(m_device.get(), m_memory, nullptr); vkDestroyBuffer(m_device.get(), m_buffer, nullptr); } VkBuffer& vk_buffer::get() { return m_buffer; } const VkBuffer& vk_buffer::get() const { return m_buffer; } void vk_buffer::write_to_memory(void* data, VkDeviceSize size) { IXION_TRACE("copying data of size " << size); VkDeviceSize padded_size = pad_to_atom_size(m_device, size); void* mapped = nullptr; VkResult res = vkMapMemory(m_device.get(), m_memory, 0, padded_size, 0, &mapped); if (res != VK_SUCCESS) throw std::runtime_error("failed to map memory."); memcpy(mapped, data, size); // flush the modified memory range. VkMappedMemoryRange flush_range{}; flush_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; flush_range.memory = m_memory; flush_range.offset = 0; flush_range.size = padded_size; vkFlushMappedMemoryRanges(m_device.get(), 1, &flush_range); vkUnmapMemory(m_device.get(), m_memory); } void vk_buffer::read_from_memory(void* data, VkDeviceSize size) { IXION_TRACE("reading data from memory for size " << size << "..."); VkDeviceSize padded_size = pad_to_atom_size(m_device, size); void *mapped; vkMapMemory(m_device.get(), m_memory, 0, padded_size, 0, &mapped); VkMappedMemoryRange invalidate_range{}; invalidate_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; invalidate_range.memory = m_memory; invalidate_range.offset = 0; invalidate_range.size = padded_size; vkInvalidateMappedMemoryRanges(m_device.get(), 1, &invalidate_range); // Copy to output memcpy(data, mapped, size); vkUnmapMemory(m_device.get(), m_memory); } vk_fence::vk_fence(vk_device& device, VkFenceCreateFlags flags) : m_device(device) { VkFenceCreateInfo info{}; info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; info.flags = flags; vkCreateFence(m_device.get(), &info, nullptr, &m_fence); } vk_fence::~vk_fence() { vkDestroyFence(m_device.get(), m_fence, nullptr); } VkFence& vk_fence::get() { return m_fence; } void vk_fence::wait() { VkResult res = vkWaitForFences(m_device.get(), 1, &m_fence, VK_TRUE, UINT64_MAX); if (res != VK_SUCCESS) throw std::runtime_error("failed to wait for a fence."); } void vk_fence::reset() { vkResetFences(m_device.get(), 1, &m_fence); } vk_descriptor_pool::vk_descriptor_pool( vk_device& device, uint32_t max_sets, std::initializer_list sizes) : m_device(device) { VkDescriptorPoolCreateInfo info{}; info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; info.poolSizeCount = sizes.size(); info.pPoolSizes = sizes.begin(); info.maxSets = max_sets; VkResult res = vkCreateDescriptorPool(m_device.get(), &info, nullptr, &m_pool); if (res != VK_SUCCESS) throw std::runtime_error("failed to create a descriptor pool."); } vk_descriptor_pool::~vk_descriptor_pool() { vkDestroyDescriptorPool(m_device.get(), m_pool, nullptr); } vk_descriptor_set vk_descriptor_pool::allocate(const vk_descriptor_set_layout& ds_layout) { VkDescriptorSetAllocateInfo ai{}; ai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; ai.descriptorPool = m_pool; ai.pSetLayouts = &ds_layout.get(); ai.descriptorSetCount = 1u; VkDescriptorSet ds; VkResult res = vkAllocateDescriptorSets(m_device.get(), &ai, &ds); if (res != VK_SUCCESS) throw std::runtime_error("failed to allocate a descriptor set."); return vk_descriptor_set(ds); } vk_descriptor_set_layout::vk_descriptor_set_layout( vk_device& device, std::initializer_list bindings) : m_device(device) { VkDescriptorSetLayoutCreateInfo info{}; info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; info.pBindings = bindings.begin(); info.bindingCount = bindings.size(); VkResult res = vkCreateDescriptorSetLayout(m_device.get(), &info, nullptr, &m_ds_layout); if (res != VK_SUCCESS) throw std::runtime_error("failed to create a descriptor set layout."); } vk_descriptor_set_layout::~vk_descriptor_set_layout() { vkDestroyDescriptorSetLayout(m_device.get(), m_ds_layout, nullptr); } VkDescriptorSetLayout& vk_descriptor_set_layout::get() { return m_ds_layout; } const VkDescriptorSetLayout& vk_descriptor_set_layout::get() const { return m_ds_layout; } vk_descriptor_set::vk_descriptor_set(VkDescriptorSet ds) : m_set(ds) {} vk_descriptor_set::~vk_descriptor_set() {} VkDescriptorSet& vk_descriptor_set::get() { return m_set; } const VkDescriptorSet& vk_descriptor_set::get() const { return m_set; } void vk_descriptor_set::update( const vk_device& device, uint32_t binding, VkDescriptorType type, const vk_buffer& buffer) { VkDescriptorBufferInfo buffer_desc = { buffer.get(), 0, VK_WHOLE_SIZE }; VkWriteDescriptorSet write_ds{}; write_ds.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write_ds.dstSet = m_set; write_ds.descriptorType = type; write_ds.dstBinding = binding; write_ds.pBufferInfo = &buffer_desc; write_ds.descriptorCount = 1u; vkUpdateDescriptorSets(device.get(), 1u, &write_ds, 0, nullptr); } vk_pipeline_layout::vk_pipeline_layout( vk_device& device, vk_descriptor_set_layout& ds_layout) : m_device(device) { VkPipelineLayoutCreateInfo info{}; info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; info.setLayoutCount = 1; info.pSetLayouts = &ds_layout.get(); VkResult res = vkCreatePipelineLayout(m_device.get(), &info, nullptr, &m_layout); if (res != VK_SUCCESS) throw std::runtime_error("failed to create a pipeline layout."); } vk_pipeline_layout::~vk_pipeline_layout() { vkDestroyPipelineLayout(m_device.get(), m_layout, nullptr); } VkPipelineLayout& vk_pipeline_layout::get() { return m_layout; } const VkPipelineLayout& vk_pipeline_layout::get() const { return m_layout; } vk_pipeline_cache::vk_pipeline_cache(vk_device& device) : m_device(device) { VkPipelineCacheCreateInfo info{}; info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; VkResult res = vkCreatePipelineCache(m_device.get(), &info, nullptr, &m_cache); if (res != VK_SUCCESS) throw std::runtime_error("failed to create a pipeline cache."); } vk_pipeline_cache::~vk_pipeline_cache() { vkDestroyPipelineCache(m_device.get(), m_cache, nullptr); } VkPipelineCache& vk_pipeline_cache::get() { return m_cache; } const VkPipelineCache& vk_pipeline_cache::get() const { return m_cache; } vk_shader_module::vk_shader_module(vk_device& device, module_type mt) : m_device(device) { const uint32_t* array = nullptr; std::size_t n_array = 0; switch (mt) { case module_type::fibonacci: { array = reinterpret_cast(fibonacci_spirv); n_array = IXION_N_ELEMENTS(fibonacci_spirv); IXION_TRACE("module type: fibonacci (size=" << n_array << ")"); break; } default: throw std::runtime_error("invalid module type"); } VkShaderModuleCreateInfo ci{}; ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; ci.codeSize = n_array; ci.pCode = array; VkResult res = vkCreateShaderModule(m_device.get(), &ci, NULL, &m_module); if (res != VK_SUCCESS) throw std::runtime_error("failed to create a shader module."); } vk_shader_module::~vk_shader_module() { vkDestroyShaderModule(m_device.get(), m_module, nullptr); } VkShaderModule& vk_shader_module::get() { return m_module; } const VkShaderModule& vk_shader_module::get() const { return m_module; } vk_pipeline::vk_pipeline( const runtime_context& cxt, vk_device& device, vk_pipeline_layout& pl_layout, vk_pipeline_cache& pl_cache, vk_shader_module& shader) : m_device(device) { struct sp_data_type { uint32_t BUFFER_ELEMENTS; }; sp_data_type sp_data; sp_data.BUFFER_ELEMENTS = cxt.input_buffer_size; VkSpecializationMapEntry sp_map_entry{}; sp_map_entry.constantID = 0; sp_map_entry.offset = 0; sp_map_entry.size = sizeof(uint32_t); VkSpecializationInfo sp_info{}; sp_info.mapEntryCount = 1; sp_info.pMapEntries = &sp_map_entry; sp_info.dataSize = sizeof(sp_data_type); sp_info.pData = &sp_data; // Data about the shader module, with special constant data via specialiation // info member. VkPipelineShaderStageCreateInfo shader_stage_ci{}; shader_stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shader_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT; shader_stage_ci.module = shader.get(); shader_stage_ci.pName = "main"; shader_stage_ci.pSpecializationInfo = &sp_info; VkComputePipelineCreateInfo pipeline_ci{}; pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; pipeline_ci.layout = pl_layout.get(); pipeline_ci.flags = 0; pipeline_ci.stage = shader_stage_ci; vkCreateComputePipelines( m_device.get(), pl_cache.get(), 1, &pipeline_ci, nullptr, &m_pipeline); } vk_pipeline::~vk_pipeline() { vkDestroyPipeline(m_device.get(), m_pipeline, nullptr); } VkPipeline& vk_pipeline::get() { return m_pipeline; } const VkPipeline& vk_pipeline::get() const { return m_pipeline; } }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/info.cpp0000644000175000017500000000134213273351731014405 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/info.hpp" #include "constants.inl" namespace ixion { int get_version_major() { return IXION_MAJOR_VERSION; } int get_version_minor() { return IXION_MINOR_VERSION; } int get_version_micro() { return IXION_MICRO_VERSION; } int get_api_version_major() { return IXION_MAJOR_API_VERSION; } int get_api_version_minor() { return IXION_MINOR_API_VERSION; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/model_context_impl.cpp0000664000175000017500000007333514122770261017351 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "model_context_impl.hpp" #include "ixion/address.hpp" #include "ixion/cell.hpp" #include "ixion/formula_result.hpp" #include "ixion/matrix.hpp" #include "ixion/interface/session_handler.hpp" #include "ixion/model_iterator.hpp" #include "calc_status.hpp" #include "model_types.hpp" #include "utils.hpp" #include "debug.hpp" #include #include #include using std::cout; using std::endl; namespace ixion { namespace detail { string_id_t safe_string_pool::append_string_unsafe(std::string_view s) { assert(!s.empty()); string_id_t str_id = m_strings.size(); m_strings.push_back(std::make_unique(s)); s = *m_strings.back(); m_string_map.insert(string_map_type::value_type(s, str_id)); return str_id; } string_id_t safe_string_pool::append_string(std::string_view s) { if (s.empty()) // Never add an empty or invalid string. return empty_string_id; std::unique_lock lock(m_mtx); return append_string_unsafe(s); } string_id_t safe_string_pool::add_string(std::string_view s) { if (s.empty()) // Never add an empty or invalid string. return empty_string_id; std::unique_lock lock(m_mtx); string_map_type::iterator itr = m_string_map.find(s); if (itr != m_string_map.end()) return itr->second; return append_string_unsafe(s); } const std::string* safe_string_pool::get_string(string_id_t identifier) const { if (identifier == empty_string_id) return &m_empty_string; if (identifier >= m_strings.size()) return nullptr; return m_strings[identifier].get(); } size_t safe_string_pool::size() const { return m_strings.size(); } void safe_string_pool::dump_strings() const { { cout << "string count: " << m_strings.size() << endl; auto it = m_strings.begin(), ite = m_strings.end(); for (string_id_t sid = 0; it != ite; ++it, ++sid) { const std::string& s = **it; cout << "* " << sid << ": '" << s << "' (" << (void*)s.data() << ")" << endl; } } { cout << "string map count: " << m_string_map.size() << endl; auto it = m_string_map.begin(), ite = m_string_map.end(); for (; it != ite; ++it) { std::string_view key = it->first; cout << "* key: '" << key << "' (" << (void*)key.data() << "; " << key.size() << "), value: " << it->second << endl; } } } string_id_t safe_string_pool::get_identifier_from_string(std::string_view s) const { string_map_type::const_iterator it = m_string_map.find(s); return it == m_string_map.end() ? empty_string_id : it->second; } namespace { model_context::session_handler_factory dummy_session_handler_factory; rc_size_t to_group_size(const abs_range_t& group_range) { rc_size_t group_size; group_size.row = group_range.last.row - group_range.first.row + 1; group_size.column = group_range.last.column - group_range.first.column + 1; return group_size; } void set_grouped_formula_cells_to_workbook( workbook& wb, const abs_address_t& top_left, const rc_size_t& group_size, const calc_status_ptr_t& cs, const formula_tokens_store_ptr_t& ts) { worksheet& sheet = wb.at(top_left.sheet); for (col_t col_offset = 0; col_offset < group_size.column; ++col_offset) { col_t col = top_left.column + col_offset; column_store_t& col_store = sheet.at(col); column_store_t::iterator& pos_hint = sheet.get_pos_hint(col); for (row_t row_offset = 0; row_offset < group_size.row; ++row_offset) { row_t row = top_left.row + row_offset; pos_hint = col_store.set(pos_hint, row, new formula_cell(row_offset, col_offset, cs, ts)); } } } /** * The name of a named expression can only contain letters, numbers or an * underscore character. */ void check_named_exp_name_or_throw(const char* p, size_t n) { const char* p_end = p + n; if (p == p_end) throw model_context_error( "empty name is not allowed", model_context_error::invalid_named_expression); if ('0' <= *p && *p <= '9') throw model_context_error( "name cannot start with a numeric character", model_context_error::invalid_named_expression); if (*p == '.') throw model_context_error( "name cannot start with a dot", model_context_error::invalid_named_expression); for (; p != p_end; ++p) { char c = *p; if ('a' <= c && c <= 'z') continue; if ('A' <= c && c <= 'Z') continue; if ('0' <= c && c <= '9') continue; if (c == '_' || c == '.') continue; std::ostringstream os; os << "name contains invalid character '" << c << "'"; throw model_context_error(os.str(), model_context_error::invalid_named_expression); } } } // anonymous namespace model_context_impl::model_context_impl(model_context& parent, const rc_size_t& sheet_size) : m_parent(parent), m_sheet_size(sheet_size), m_tracker(), mp_table_handler(nullptr), mp_session_factory(&dummy_session_handler_factory), m_formula_res_wait_policy(formula_result_wait_policy_t::throw_exception) { } model_context_impl::~model_context_impl() {} void model_context_impl::notify(formula_event_t event) { switch (event) { case formula_event_t::calculation_begins: m_formula_res_wait_policy = formula_result_wait_policy_t::block_until_done; break; case formula_event_t::calculation_ends: m_formula_res_wait_policy = formula_result_wait_policy_t::throw_exception; break; } } void model_context_impl::set_named_expression( std::string name, const abs_address_t& origin, formula_tokens_t&& expr) { check_named_exp_name_or_throw(name.data(), name.size()); IXION_TRACE("named expression: name='" << name << "'"); m_named_expressions.insert( detail::named_expressions_t::value_type( std::move(name), named_expression_t(origin, std::move(expr)) ) ); } void model_context_impl::set_named_expression( sheet_t sheet, std::string name, const abs_address_t& origin, formula_tokens_t&& expr) { check_named_exp_name_or_throw(name.data(), name.size()); detail::named_expressions_t& ns = m_sheets.at(sheet).get_named_expressions(); IXION_TRACE("named expression: name='" << name << "'"); ns.insert( detail::named_expressions_t::value_type( std::move(name), named_expression_t(origin, std::move(expr)) ) ); } const named_expression_t* model_context_impl::get_named_expression(std::string_view name) const { named_expressions_t::const_iterator itr = m_named_expressions.find(std::string(name)); return itr == m_named_expressions.end() ? nullptr : &itr->second; } const named_expression_t* model_context_impl::get_named_expression(sheet_t sheet, std::string_view name) const { const worksheet* ws = fetch_sheet(sheet); if (ws) { const named_expressions_t& ns = ws->get_named_expressions(); auto it = ns.find(std::string(name)); if (it != ns.end()) return &it->second; } // Search the global scope if not found in the sheet local scope. return get_named_expression(name); } sheet_t model_context_impl::get_sheet_index(std::string_view name) const { strings_type::const_iterator itr_beg = m_sheet_names.begin(), itr_end = m_sheet_names.end(); for (strings_type::const_iterator itr = itr_beg; itr != itr_end; ++itr) { const std::string& s = *itr; if (s.empty()) continue; if (s == name) return static_cast(std::distance(itr_beg, itr)); } return invalid_sheet; } std::string model_context_impl::get_sheet_name(sheet_t sheet) const { if (m_sheet_names.size() <= static_cast(sheet)) return std::string(); return m_sheet_names[sheet]; } rc_size_t model_context_impl::get_sheet_size() const { return m_sheet_size; } size_t model_context_impl::get_sheet_count() const { return m_sheets.size(); } sheet_t model_context_impl::append_sheet(std::string&& name) { IXION_TRACE("name='" << name << "'"); // Check if the new sheet name already exists. strings_type::const_iterator it = std::find(m_sheet_names.begin(), m_sheet_names.end(), name); if (it != m_sheet_names.end()) { // This sheet name is already taken. std::ostringstream os; os << "Sheet name '" << name << "' already exists."; throw model_context_error(os.str(), model_context_error::sheet_name_conflict); } // index of the new sheet. sheet_t sheet_index = m_sheets.size(); m_sheet_names.push_back(std::move(name)); m_sheets.push_back(m_sheet_size.row, m_sheet_size.column); return sheet_index; } void model_context_impl::set_cell_values(sheet_t sheet, std::initializer_list&& rows) { abs_address_t pos; pos.sheet = sheet; pos.row = 0; pos.column = 0; // TODO : This function is not optimized for speed as it is mainly for // convenience. Decide if we need to optimize this later. for (const model_context::input_row& row : rows) { pos.column = 0; for (const model_context::input_cell& c : row.cells()) { switch (c.type) { case celltype_t::numeric: set_numeric_cell(pos, std::get(c.value)); break; case celltype_t::string: { auto s = std::get(c.value); set_string_cell(pos, s); break; } case celltype_t::boolean: set_boolean_cell(pos, std::get(c.value)); break; default: ; } ++pos.column; } ++pos.row; } } string_id_t model_context_impl::append_string(std::string_view s) { return m_str_pool.append_string(s); } string_id_t model_context_impl::add_string(std::string_view s) { return m_str_pool.add_string(s); } const std::string* model_context_impl::get_string(string_id_t identifier) const { return m_str_pool.get_string(identifier); } size_t model_context_impl::get_string_count() const { return m_str_pool.size(); } void model_context_impl::dump_strings() const { m_str_pool.dump_strings(); } const column_store_t* model_context_impl::get_column(sheet_t sheet, col_t col) const { if (static_cast(sheet) >= m_sheets.size()) return nullptr; const worksheet& sh = m_sheets[sheet]; if (static_cast(col) >= sh.size()) return nullptr; return &sh[col]; } const column_stores_t* model_context_impl::get_columns(sheet_t sheet) const { if (static_cast(sheet) >= m_sheets.size()) return nullptr; const worksheet& sh = m_sheets[sheet]; return &sh.get_columns(); } namespace { double count_formula_block( formula_result_wait_policy_t wait_policy, const column_store_t::const_iterator& itb, size_t offset, size_t len, const values_t& vt) { double ret = 0.0; // Inspect each formula cell individually. formula_cell** pp = &formula_element_block::at(*itb->data, offset); formula_cell** pp_end = pp + len; for (; pp != pp_end; ++pp) { const formula_cell& fc = **pp; formula_result res = fc.get_result_cache(wait_policy); switch (res.get_type()) { case formula_result::result_type::value: if (vt.is_numeric()) ++ret; break; case formula_result::result_type::string: if (vt.is_string()) ++ret; break; case formula_result::result_type::error: // TODO : how do we handle error formula cells? break; case formula_result::result_type::matrix: // TODO : ditto break; } } return ret; } } double model_context_impl::count_range(const abs_range_t& range, const values_t& values_type) const { if (m_sheets.empty()) return 0.0; double ret = 0.0; sheet_t last_sheet = range.last.sheet; if (static_cast(last_sheet) >= m_sheets.size()) last_sheet = m_sheets.size() - 1; for (sheet_t sheet = range.first.sheet; sheet <= last_sheet; ++sheet) { const worksheet& ws = m_sheets.at(sheet); for (col_t col = range.first.column; col <= range.last.column; ++col) { const column_store_t& cs = ws.at(col); row_t cur_row = range.first.row; column_store_t::const_position_type pos = cs.position(cur_row); column_store_t::const_iterator itb = pos.first; // block iterator column_store_t::const_iterator itb_end = cs.end(); size_t offset = pos.second; if (itb == itb_end) continue; bool cont = true; while (cont) { // remaining length of current block. size_t len = itb->size - offset; row_t last_row = cur_row + len - 1; if (last_row >= range.last.row) { last_row = range.last.row; len = last_row - cur_row + 1; cont = false; } bool match = false; switch (itb->type) { case element_type_numeric: match = values_type.is_numeric(); break; case element_type_boolean: match = values_type.is_boolean(); break; case element_type_string: match = values_type.is_string(); break; case element_type_empty: match = values_type.is_empty(); break; case element_type_formula: ret += count_formula_block(m_formula_res_wait_policy, itb, offset, len, values_type); break; default: { std::ostringstream os; os << __FUNCTION__ << ": unhandled block type (" << itb->type << ")"; throw general_error(os.str()); } } if (match) ret += len; // Move to the next block. cur_row = last_row + 1; ++itb; offset = 0; if (itb == itb_end) cont = false; } } } return ret; } bool model_context_impl::empty() const { return m_sheets.empty(); } const worksheet* model_context_impl::fetch_sheet(sheet_t sheet_index) const { if (sheet_index < 0 || m_sheets.size() <= size_t(sheet_index)) return nullptr; return &m_sheets[sheet_index]; } column_store_t::const_position_type model_context_impl::get_cell_position(const abs_address_t& addr) const { const column_store_t& col_store = m_sheets.at(addr.sheet).at(addr.column); return col_store.position(addr.row); } const detail::named_expressions_t& model_context_impl::get_named_expressions() const { return m_named_expressions; } const detail::named_expressions_t& model_context_impl::get_named_expressions(sheet_t sheet) const { const worksheet& sh = m_sheets.at(sheet); return sh.get_named_expressions(); } model_iterator model_context_impl::get_model_iterator( sheet_t sheet, rc_direction_t dir, const abs_rc_range_t& range) const { return model_iterator(*this, sheet, range, dir); } void model_context_impl::set_sheet_size(const rc_size_t& sheet_size) { if (!m_sheets.empty()) throw model_context_error( "You cannot change the sheet size if you already have at least one existing sheet.", model_context_error::sheet_size_locked); m_sheet_size = sheet_size; } std::unique_ptr model_context_impl::create_session_handler() { return mp_session_factory->create(); } void model_context_impl::empty_cell(const abs_address_t& addr) { worksheet& sheet = m_sheets.at(addr.sheet); column_store_t& col_store = sheet.at(addr.column); column_store_t::iterator& pos_hint = sheet.get_pos_hint(addr.column); pos_hint = col_store.set_empty(addr.row, addr.row); } void model_context_impl::set_numeric_cell(const abs_address_t& addr, double val) { worksheet& sheet = m_sheets.at(addr.sheet); column_store_t& col_store = sheet.at(addr.column); column_store_t::iterator& pos_hint = sheet.get_pos_hint(addr.column); pos_hint = col_store.set(pos_hint, addr.row, val); } void model_context_impl::set_boolean_cell(const abs_address_t& addr, bool val) { worksheet& sheet = m_sheets.at(addr.sheet); column_store_t& col_store = sheet.at(addr.column); column_store_t::iterator& pos_hint = sheet.get_pos_hint(addr.column); pos_hint = col_store.set(pos_hint, addr.row, val); } void model_context_impl::set_string_cell(const abs_address_t& addr, std::string_view s) { worksheet& sheet = m_sheets.at(addr.sheet); string_id_t str_id = add_string(s); column_store_t& col_store = sheet.at(addr.column); column_store_t::iterator& pos_hint = sheet.get_pos_hint(addr.column); pos_hint = col_store.set(pos_hint, addr.row, str_id); } void model_context_impl::fill_down_cells(const abs_address_t& src, size_t n_dst) { if (!n_dst) // Destination cell length is 0. Nothing to copy to. return; worksheet& sheet = m_sheets.at(src.sheet); column_store_t& col_store = sheet.at(src.column); column_store_t::iterator& pos_hint = sheet.get_pos_hint(src.column); column_store_t::const_position_type pos = col_store.position(pos_hint, src.row); auto it = pos.first; // block iterator switch (it->type) { case element_type_numeric: { double v = col_store.get(pos); std::vector vs(n_dst, v); pos_hint = col_store.set(pos_hint, src.row+1, vs.begin(), vs.end()); break; } case element_type_boolean: { bool b = col_store.get(pos); std::deque vs(n_dst, b); pos_hint = col_store.set(pos_hint, src.row+1, vs.begin(), vs.end()); break; } case element_type_string: { string_id_t sid = col_store.get(pos); std::vector vs(n_dst, sid); pos_hint = col_store.set(pos_hint, src.row+1, vs.begin(), vs.end()); break; } case element_type_empty: { size_t start_pos = src.row + 1; size_t end_pos = start_pos + n_dst - 1; pos_hint = col_store.set_empty(pos_hint, start_pos, end_pos); break; } case element_type_formula: // TODO : support this. throw not_implemented_error("filling down of a formula cell is not yet supported."); default: { std::ostringstream os; os << __FUNCTION__ << ": unhandled block type (" << it->type << ")"; throw general_error(os.str()); } } } void model_context_impl::set_string_cell(const abs_address_t& addr, string_id_t identifier) { worksheet& sheet = m_sheets.at(addr.sheet); column_store_t& col_store = sheet.at(addr.column); column_store_t::iterator& pos_hint = sheet.get_pos_hint(addr.column); pos_hint = col_store.set(pos_hint, addr.row, identifier); } formula_cell* model_context_impl::set_formula_cell( const abs_address_t& addr, const formula_tokens_store_ptr_t& tokens) { std::unique_ptr fcell = std::make_unique(tokens); worksheet& sheet = m_sheets.at(addr.sheet); column_store_t& col_store = sheet.at(addr.column); column_store_t::iterator& pos_hint = sheet.get_pos_hint(addr.column); formula_cell* p = fcell.release(); pos_hint = col_store.set(pos_hint, addr.row, p); return p; } formula_cell* model_context_impl::set_formula_cell( const abs_address_t& addr, const formula_tokens_store_ptr_t& tokens, formula_result result) { std::unique_ptr fcell = std::make_unique(tokens); worksheet& sheet = m_sheets.at(addr.sheet); column_store_t& col_store = sheet.at(addr.column); column_store_t::iterator& pos_hint = sheet.get_pos_hint(addr.column); formula_cell* p = fcell.release(); p->set_result_cache(std::move(result)); pos_hint = col_store.set(pos_hint, addr.row, p); return p; } void model_context_impl::set_grouped_formula_cells( const abs_range_t& group_range, formula_tokens_t tokens) { formula_tokens_store_ptr_t ts = formula_tokens_store::create(); ts->get() = std::move(tokens); rc_size_t group_size = to_group_size(group_range); calc_status_ptr_t cs(new calc_status(group_size)); set_grouped_formula_cells_to_workbook(m_sheets, group_range.first, group_size, cs, ts); } void model_context_impl::set_grouped_formula_cells( const abs_range_t& group_range, formula_tokens_t tokens, formula_result result) { formula_tokens_store_ptr_t ts = formula_tokens_store::create(); ts->get() = std::move(tokens); rc_size_t group_size = to_group_size(group_range); if (result.get_type() != formula_result::result_type::matrix) throw std::invalid_argument("cached result for grouped formula cells must be of matrix type."); if (row_t(result.get_matrix().row_size()) != group_size.row || col_t(result.get_matrix().col_size()) != group_size.column) throw std::invalid_argument("dimension of the cached result differs from the size of the group."); calc_status_ptr_t cs(new calc_status(group_size)); cs->result = std::make_unique(std::move(result)); set_grouped_formula_cells_to_workbook(m_sheets, group_range.first, group_size, cs, ts); } abs_range_t model_context_impl::get_data_range(sheet_t sheet) const { const worksheet& cols = m_sheets.at(sheet); size_t col_size = cols.size(); if (!col_size) return abs_range_t(abs_range_t::invalid); row_t row_size = cols[0].size(); if (!row_size) return abs_range_t(abs_range_t::invalid); abs_range_t range; range.first.column = 0; range.first.row = row_size-1; range.first.sheet = sheet; range.last.column = -1; // if this stays -1 all columns are empty. range.last.row = 0; range.last.sheet = sheet; for (size_t i = 0; i < col_size; ++i) { const column_store_t& col = cols[i]; if (col.empty()) { if (range.last.column < 0) ++range.first.column; continue; } if (range.first.row > 0) { // First non-empty row. column_store_t::const_iterator it = col.begin(), it_end = col.end(); assert(it != it_end); if (it->type == element_type_empty) { // First block is empty. row_t offset = it->size; ++it; if (it == it_end) { // The whole column is empty. if (range.last.column < 0) ++range.first.column; continue; } assert(it->type != element_type_empty); if (range.first.row > offset) range.first.row = offset; } else // Set the first row to 0, and lock it. range.first.row = 0; } if (range.last.row < (row_size-1)) { // Last non-empty row. column_store_t::const_reverse_iterator it = col.rbegin(), it_end = col.rend(); assert(it != it_end); if (it->type == element_type_empty) { // Last block is empty. size_t size_last_block = it->size; ++it; if (it == it_end) { // The whole column is empty. if (range.last.column < 0) ++range.first.column; continue; } assert(it->type != element_type_empty); row_t last_data_row = static_cast(col.size() - size_last_block - 1); if (range.last.row < last_data_row) range.last.row = last_data_row; } else // Last block is not empty. range.last.row = row_size - 1; } // Check if the column contains at least one non-empty cell. if (col.block_size() > 1 || !col.is_empty(0)) range.last.column = i; } if (range.last.column < 0) // No data column found. The whole sheet is empty. return abs_range_t(abs_range_t::invalid); return range; } bool model_context_impl::is_empty(const abs_address_t& addr) const { return m_sheets.at(addr.sheet).at(addr.column).is_empty(addr.row); } celltype_t model_context_impl::get_celltype(const abs_address_t& addr) const { mdds::mtv::element_t gmcell_type = m_sheets.at(addr.sheet).at(addr.column).get_type(addr.row); return detail::to_celltype(gmcell_type); } double model_context_impl::get_numeric_value(const abs_address_t& addr) const { const column_store_t& col_store = m_sheets.at(addr.sheet).at(addr.column); auto pos = col_store.position(addr.row); switch (pos.first->type) { case element_type_numeric: return numeric_element_block::at(*pos.first->data, pos.second); case element_type_boolean: { auto it = boolean_element_block::cbegin(*pos.first->data); std::advance(it, pos.second); return *it ? 1.0 : 0.0; } case element_type_formula: { const formula_cell* p = formula_element_block::at(*pos.first->data, pos.second); return p->get_value(m_formula_res_wait_policy); } default: ; } return 0.0; } bool model_context_impl::get_boolean_value(const abs_address_t& addr) const { const column_store_t& col_store = m_sheets.at(addr.sheet).at(addr.column); auto pos = col_store.position(addr.row); switch (pos.first->type) { case element_type_numeric: return numeric_element_block::at(*pos.first->data, pos.second) != 0.0 ? true : false; case element_type_boolean: { auto it = boolean_element_block::cbegin(*pos.first->data); std::advance(it, pos.second); return *it; } case element_type_formula: { const formula_cell* p = formula_element_block::at(*pos.first->data, pos.second); return p->get_value(m_formula_res_wait_policy) == 0.0 ? false : true; } default: ; } return false; } string_id_t model_context_impl::get_string_identifier(const abs_address_t& addr) const { const column_store_t& col_store = m_sheets.at(addr.sheet).at(addr.column); auto pos = col_store.position(addr.row); switch (pos.first->type) { case element_type_string: return string_element_block::at(*pos.first->data, pos.second); default: ; } return empty_string_id; } std::string_view model_context_impl::get_string_value(const abs_address_t& addr) const { const column_store_t& col_store = m_sheets.at(addr.sheet).at(addr.column); auto pos = col_store.position(addr.row); switch (pos.first->type) { case element_type_string: { string_id_t sid = string_element_block::at(*pos.first->data, pos.second); const std::string* p = m_str_pool.get_string(sid); return p ? *p : std::string_view{}; } case element_type_formula: { const formula_cell* p = formula_element_block::at(*pos.first->data, pos.second); return p->get_string(m_formula_res_wait_policy); } case element_type_empty: return empty_string; default: ; } return std::string_view{}; } string_id_t model_context_impl::get_identifier_from_string(std::string_view s) const { return m_str_pool.get_identifier_from_string(s); } const formula_cell* model_context_impl::get_formula_cell(const abs_address_t& addr) const { const column_store_t& col_store = m_sheets.at(addr.sheet).at(addr.column); auto pos = col_store.position(addr.row); if (pos.first->type != element_type_formula) return nullptr; return formula_element_block::at(*pos.first->data, pos.second); } formula_cell* model_context_impl::get_formula_cell(const abs_address_t& addr) { column_store_t& col_store = m_sheets.at(addr.sheet).at(addr.column); auto pos = col_store.position(addr.row); if (pos.first->type != element_type_formula) return nullptr; return formula_element_block::at(*pos.first->data, pos.second); } formula_result model_context_impl::get_formula_result(const abs_address_t& addr) const { const formula_cell* fc = get_formula_cell(addr); if (!fc) throw general_error("not a formula cell."); return fc->get_result_cache(m_formula_res_wait_policy); } }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/concrete_formula_tokens.hpp0000664000175000017500000001027514105607506020377 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_CONCRETE_FORMULA_TOKENS_HPP #define INCLUDED_IXION_CONCRETE_FORMULA_TOKENS_HPP #include "ixion/formula_tokens.hpp" #include "ixion/formula_function_opcode.hpp" namespace ixion { // ============================================================================ /** * Very simple token that stores opcode only. */ class opcode_token : public formula_token { public: explicit opcode_token(fopcode_t oc); opcode_token(const opcode_token& r); virtual ~opcode_token() override; virtual void write_string(std::ostream& os) const override; }; // ============================================================================ class value_token : public formula_token { public: explicit value_token(double value); virtual ~value_token() override; virtual double get_value() const override; virtual void write_string(std::ostream& os) const override; private: double m_value; }; class string_token : public formula_token { string_token() = delete; public: explicit string_token(string_id_t str_identifier); virtual ~string_token() override; virtual uint32_t get_uint32() const override; virtual void write_string(std::ostream& os) const override; private: string_id_t m_str_identifier; }; // ============================================================================ /** * Token that stores a cell reference. Note that the address it stores may * be either relative to the origin cell or absolute. */ class single_ref_token : public formula_token { public: single_ref_token(const address_t& addr); single_ref_token(const single_ref_token& r); virtual ~single_ref_token() override; virtual address_t get_single_ref() const override; virtual void write_string(std::ostream& os) const override; private: address_t m_address; }; // ============================================================================ class range_ref_token : public formula_token { public: range_ref_token(const range_t& range); range_ref_token(const range_ref_token& r); virtual ~range_ref_token() override; virtual range_t get_range_ref() const override; virtual void write_string(std::ostream& os) const override; private: range_t m_range; }; class table_ref_token : public formula_token { public: table_ref_token(const table_t& table); table_ref_token(const table_ref_token& r); virtual ~table_ref_token() override; virtual table_t get_table_ref() const override; virtual void write_string(std::ostream& os) const override; private: table_t m_table; }; // ============================================================================ /** * Token that stores a named expression. */ class named_exp_token : public formula_token { public: named_exp_token(const char* p, size_t n); named_exp_token(const named_exp_token& r); virtual ~named_exp_token() override; virtual std::string get_name() const override; virtual void write_string(std::ostream& os) const override; private: ::std::string m_name; }; // ============================================================================ class function_token : public formula_token { public: function_token(formula_function_t func_oc); function_token(const function_token& r); virtual ~function_token() override; virtual uint32_t get_uint32() const override; virtual void write_string(std::ostream& os) const override; private: formula_function_t m_func_oc; }; /** * Token that signifies an invalid formula. It contains the number of * tokens that follow, and those tokens store the invalid formula string and * an error string. */ class error_token : public formula_token { public: error_token(uint32_t n_msgs); error_token(const error_token& other); virtual ~error_token() override; virtual uint32_t get_uint32() const override; private: uint32_t m_n_msgs; }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/workbook.hpp0000664000175000017500000000417213734743377015337 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_WORKBOOK_HPP #define INCLUDED_IXION_WORKBOOK_HPP #include "column_store_type.hpp" #include "model_types.hpp" #include namespace ixion { class worksheet { public: typedef column_store_t::size_type size_type; worksheet(); worksheet(size_type row_size, size_type col_size); ~worksheet(); column_store_t& operator[](size_type n) { return m_columns[n]; } const column_store_t& operator[](size_type n) const { return m_columns[n]; } column_store_t& at(size_type n) { return m_columns.at(n); } const column_store_t& at(size_type n) const { return m_columns.at(n); } column_store_t::iterator& get_pos_hint(size_type n) { return m_pos_hints.at(n); } /** * Return the number of columns. * * @return number of columns. */ size_type size() const { return m_columns.size(); } const column_stores_t& get_columns() const { return m_columns; } detail::named_expressions_t& get_named_expressions() { return m_named_expressions; } const detail::named_expressions_t& get_named_expressions() const { return m_named_expressions; } private: column_stores_t m_columns; std::vector m_pos_hints; detail::named_expressions_t m_named_expressions; }; class workbook { public: workbook(); workbook(size_t sheet_size, size_t row_size, size_t col_size); ~workbook(); worksheet& operator[](size_t n) { return m_sheets[n]; } const worksheet& operator[](size_t n) const { return m_sheets[n]; } worksheet& at(size_t n) { return m_sheets.at(n); } const worksheet& at(size_t n) const { return m_sheets.at(n); } void push_back(size_t row_size, size_t col_size); size_t size() const; bool empty() const; private: std::deque m_sheets; }; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula.cpp0000664000175000017500000003231314122770261015120 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/formula.hpp" #include "ixion/formula_name_resolver.hpp" #include "ixion/formula_function_opcode.hpp" #include "ixion/cell.hpp" #include "ixion/dirty_cell_tracker.hpp" #include "ixion/types.hpp" #include "formula_lexer.hpp" #include "formula_parser.hpp" #include "formula_functions.hpp" #include "debug.hpp" #include "concrete_formula_tokens.hpp" #include #include namespace ixion { namespace { #if IXION_LOGGING std::string debug_print_formula_tokens(const formula_tokens_t& tokens) { std::ostringstream os; for (const std::unique_ptr& t : tokens) { os << std::endl << " * " << *t; } return os.str(); } #endif } formula_tokens_t parse_formula_string( iface::formula_model_access& cxt, const abs_address_t& pos, const formula_name_resolver& resolver, std::string_view formula) { IXION_TRACE("pos=" << pos.get_name() << "; formula='" << formula << "'"); lexer_tokens_t lxr_tokens; formula_lexer lexer(cxt.get_config(), formula.data(), formula.size()); lexer.tokenize(); lexer.swap_tokens(lxr_tokens); IXION_TRACE(print_tokens(lxr_tokens, true)); formula_tokens_t tokens; formula_parser parser(lxr_tokens, cxt, resolver); parser.set_origin(pos); parser.parse(); parser.get_tokens().swap(tokens); IXION_TRACE("formula tokens (string): " << print_formula_tokens(cxt, pos, resolver, tokens)); IXION_TRACE("formula tokens (individual): " << debug_print_formula_tokens(tokens)); return tokens; } formula_tokens_t create_formula_error_tokens( iface::formula_model_access& cxt, std::string_view src_formula, std::string_view error) { formula_tokens_t tokens; tokens.push_back(std::make_unique(2)); string_id_t sid_src_formula = cxt.add_string(src_formula); tokens.push_back(std::make_unique(sid_src_formula)); string_id_t sid_error = cxt.add_string(error); tokens.push_back(std::make_unique(sid_error)); return tokens; } namespace { class func_print_formula_token { const iface::formula_model_access& m_cxt; const abs_address_t& m_pos; const formula_name_resolver& m_resolver; std::ostringstream& m_os; public: func_print_formula_token( const iface::formula_model_access& cxt, const abs_address_t& pos, const formula_name_resolver& resolver, std::ostringstream& os) : m_cxt(cxt), m_pos(pos), m_resolver(resolver), m_os(os) {} void operator() (const formula_tokens_t::value_type& token) { operator() (*token); } void operator() (const formula_token& token) { switch (token.get_opcode()) { case fop_close: m_os << ')'; break; case fop_divide: m_os << '/'; break; case fop_minus: m_os << '-'; break; case fop_multiply: m_os << '*'; break; case fop_exponent: m_os << '^'; break; case fop_concat: m_os << '&'; break; case fop_open: m_os << '('; break; case fop_plus: m_os << '+'; break; case fop_value: m_os << token.get_value(); break; case fop_sep: m_os << m_cxt.get_config().sep_function_arg; break; case fop_function: { formula_function_t fop = static_cast(token.get_uint32()); m_os << formula_functions::get_function_name(fop); break; } case fop_single_ref: { address_t addr = token.get_single_ref(); bool sheet_name = addr.to_abs(m_pos).sheet != m_pos.sheet; m_os << m_resolver.get_name(addr, m_pos, sheet_name); break; } case fop_range_ref: { range_t range = token.get_range_ref(); bool sheet_name = range.to_abs(m_pos).first.sheet != m_pos.sheet; m_os << m_resolver.get_name(range, m_pos, sheet_name); break; } case fop_table_ref: { table_t tbl = token.get_table_ref(); m_os << m_resolver.get_name(tbl); break; } case fop_string: { const std::string* p = m_cxt.get_string(token.get_uint32()); if (p) m_os << "\"" << *p << "\""; else IXION_DEBUG("failed to get a string value for the identifier value of " << token.get_uint32()); break; } case fop_equal: m_os << "="; break; case fop_not_equal: m_os << "<>"; break; case fop_less: m_os << "<"; break; case fop_greater: m_os << ">"; break; case fop_less_equal: m_os << "<="; break; case fop_greater_equal: m_os << ">="; break; case fop_named_expression: m_os << token.get_name(); break; case fop_unknown: default: { std::ostringstream repr; token.write_string(repr); IXION_DEBUG( "token not printed (repr='" << repr.str() << "'; name='" << get_opcode_name(token.get_opcode()) << "'; opcode='" << get_formula_opcode_string(token.get_opcode()) << "')"); } } } }; } std::string print_formula_tokens( const iface::formula_model_access& cxt, const abs_address_t& pos, const formula_name_resolver& resolver, const formula_tokens_t& tokens) { std::ostringstream os; if (!tokens.empty() && tokens[0]->get_opcode() == fop_error) // Let's not print anything on error tokens. return std::string(); std::for_each(tokens.begin(), tokens.end(), func_print_formula_token(cxt, pos, resolver, os)); return os.str(); } std::string print_formula_token( const iface::formula_model_access& cxt, const abs_address_t& pos, const formula_name_resolver& resolver, const formula_token& token) { std::ostringstream os; func_print_formula_token func(cxt, pos, resolver, os); func(token); return os.str(); } namespace { bool is_volatile(formula_function_t func) { switch (func) { case formula_function_t::func_now: return true; default: ; } return false; } bool has_volatile(const formula_tokens_t& tokens) { formula_tokens_t::const_iterator i = tokens.begin(), iend = tokens.end(); for (; i != iend; ++i) { const formula_token& t = **i; if (t.get_opcode() != fop_function) continue; formula_function_t func = static_cast(t.get_uint32()); if (is_volatile(func)) return true; } return false; } void check_sheet_or_throw(const char* func_name, sheet_t sheet, const iface::formula_model_access& cxt, const abs_address_t& pos, const formula_cell& cell) { if (is_valid_sheet(sheet)) return; IXION_DEBUG("invalid range reference: func=" << func_name << "; pos=" << pos.get_name() << "; formula='" << detail::print_formula_expression(cxt, pos, cell) << "'"); std::ostringstream os; os << func_name << ": invalid sheet index in " << pos.get_name() << ": formula='" << detail::print_formula_expression(cxt, pos, cell) << "'"; throw ixion::formula_registration_error(os.str()); } } void register_formula_cell( iface::formula_model_access& cxt, const abs_address_t& pos, const formula_cell* cell) { #ifdef IXION_DEBUG_UTILS if (cell) { const formula_cell* check = cxt.get_formula_cell(pos); if (cell != check) { throw std::runtime_error( "The cell instance passed to this call does not match the cell instance found at the specified position."); } } #endif if (!cell) { cell = cxt.get_formula_cell(pos); if (!cell) // Not a formula cell. Bail out. return; } formula_group_t fg_props = cell->get_group_properties(); dirty_cell_tracker& tracker = cxt.get_cell_tracker(); abs_range_t src_pos = pos; if (fg_props.grouped) { // Expand the source range for grouped formula cells. src_pos.last.column += fg_props.size.column - 1; src_pos.last.row += fg_props.size.row - 1; } IXION_TRACE("pos=" << pos.get_name() << "; formula='" << detail::print_formula_expression(cxt, pos, *cell) << "'"); std::vector ref_tokens = cell->get_ref_tokens(cxt, pos); for (const formula_token* p : ref_tokens) { IXION_TRACE("ref token: " << detail::print_formula_token_repr(*p)); switch (p->get_opcode()) { case fop_single_ref: { abs_address_t addr = p->get_single_ref().to_abs(pos); check_sheet_or_throw("register_formula_cell", addr.sheet, cxt, pos, *cell); tracker.add(src_pos, addr); break; } case fop_range_ref: { abs_range_t range = p->get_range_ref().to_abs(pos); check_sheet_or_throw("register_formula_cell", range.first.sheet, cxt, pos, *cell); rc_size_t sheet_size = cxt.get_sheet_size(); if (range.all_columns()) { range.first.column = 0; range.last.column = sheet_size.column - 1; } if (range.all_rows()) { range.first.row = 0; range.last.row = sheet_size.row - 1; } range.reorder(); tracker.add(src_pos, range); break; } default: ; // ignore the rest. } } // Check if the cell is volatile. const formula_tokens_store_ptr_t& ts = cell->get_tokens(); if (ts && has_volatile(ts->get())) tracker.add_volatile(pos); } void unregister_formula_cell(iface::formula_model_access& cxt, const abs_address_t& pos) { // When there is a formula cell at this position, unregister it from // the dependency tree. formula_cell* fcell = cxt.get_formula_cell(pos); if (!fcell) // Not a formula cell. Bail out. return; dirty_cell_tracker& tracker = cxt.get_cell_tracker(); tracker.remove_volatile(pos); // Go through all its existing references, and remove // itself as their listener. This step is important // especially during partial re-calculation. std::vector ref_tokens = fcell->get_ref_tokens(cxt, pos); for (const formula_token* p : ref_tokens) { switch (p->get_opcode()) { case fop_single_ref: { abs_address_t addr = p->get_single_ref().to_abs(pos); check_sheet_or_throw("unregister_formula_cell", addr.sheet, cxt, pos, *fcell); tracker.remove(pos, addr); break; } case fop_range_ref: { abs_range_t range = p->get_range_ref().to_abs(pos); check_sheet_or_throw("unregister_formula_cell", range.first.sheet, cxt, pos, *fcell); tracker.remove(pos, range); break; } default: ; // ignore the rest. } } } abs_address_set_t query_dirty_cells(iface::formula_model_access& cxt, const abs_address_set_t& modified_cells) { abs_range_set_t modified_ranges; for (const abs_address_t& mc : modified_cells) modified_ranges.insert(mc); const dirty_cell_tracker& tracker = cxt.get_cell_tracker(); abs_range_set_t dirty_ranges = tracker.query_dirty_cells(modified_ranges); // Convert a set of ranges to a set of addresses. abs_address_set_t dirty_cells; std::for_each(dirty_ranges.begin(), dirty_ranges.end(), [&dirty_cells](const abs_range_t& r) { dirty_cells.insert(r.first); } ); return dirty_cells; } std::vector query_and_sort_dirty_cells( iface::formula_model_access& cxt, const abs_range_set_t& modified_cells, const abs_range_set_t* dirty_formula_cells) { const dirty_cell_tracker& tracker = cxt.get_cell_tracker(); return tracker.query_and_sort_dirty_cells(modified_cells, dirty_formula_cells); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/libixion/formula_result.cpp0000664000175000017500000002653514122770261016527 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/formula_result.hpp" #include "ixion/exceptions.hpp" #include "ixion/interface/formula_model_access.hpp" #include "ixion/config.hpp" #include "ixion/matrix.hpp" #include "mem_str_buf.hpp" #include #include #include #include #include #define DEBUG_FORMULA_RESULT 0 #if DEBUG_FORMULA_RESULT #include #endif namespace ixion { struct formula_result::impl { using result_value_type = std::variant; result_type type; result_value_type value; impl() : type(result_type::value), value(0.0) {} impl(double v) : type(result_type::value), value(v) {} impl(std::string str) : type(result_type::string), value(std::move(str)) {} impl(formula_error_t e) : type(result_type::error), value(e) {} impl(matrix mtx) : type(result_type::matrix), value(std::move(mtx)) {} impl(const impl& other) : type(other.type), value(other.value) {} void reset() { type = result_type::value; value = 0.0; } void set_value(double v) { type = result_type::value; value = v; } void set_string_value(std::string str) { type = result_type::string; value = std::move(str); } void set_error(formula_error_t e) { type = result_type::error; value = e; } void set_matrix(matrix mtx) { type = result_type::matrix; value = std::move(mtx); } double get_value() const { assert(type == result_type::value); return std::get(value); } const std::string& get_string_value() const { assert(type == result_type::string); return std::get(value); } formula_error_t get_error() const { assert(type == result_type::error); return std::get(value); } const matrix& get_matrix() const { assert(type == result_type::matrix); return std::get(value); } matrix& get_matrix() { assert(type == result_type::matrix); return std::get(value); } result_type get_type() const { return type; } std::string str(const iface::formula_model_access& cxt) const { switch (type) { case result_type::error: { std::string_view s = get_formula_error_name(std::get(value)); return std::string(s); } case result_type::string: return std::get(value); case result_type::value: { std::ostringstream os; if (cxt.get_config().output_precision >= 0) os << std::fixed << std::setprecision(cxt.get_config().output_precision); os << std::get(value); return os.str(); } case result_type::matrix: { const matrix& m = std::get(value); std::ostringstream os; os << '{'; for (size_t row = 0; row < m.row_size(); ++row) { if (row > 0) os << cxt.get_config().sep_matrix_row; for (size_t col = 0; col < m.col_size(); ++col) { if (col > 0) os << cxt.get_config().sep_matrix_column; matrix::element e = m.get(row, col); switch (e.type) { case matrix::element_type::numeric: { os << std::get(e.value); break; } case matrix::element_type::string: { os << '"' << std::get(e.value) << '"'; break; } case matrix::element_type::error: { os << get_formula_error_name(std::get(e.value)); break; } case matrix::element_type::boolean: { os << std::get(e.value); break; } default: ; } } } os << '}'; return os.str(); } default: assert(!"unknown formula result type!"); } return std::string{}; } void parse(std::string_view s) { if (s.empty()) return; switch (s[0]) { case '#': { parse_error(s); break; } case '"': { parse_string(s); break; } case 't': case 'f': { // parse this as a boolean value. value = to_bool(s) ? 1.0 : 0.0; type = result_type::value; break; } default: { // parse this as a number. value = to_double(s); type = result_type::value; } } } void move_from(formula_result&& r) { type = r.mp_impl->type; value = std::move(r.mp_impl->value); } bool equals(const formula_result& r) const { if (type != r.mp_impl->type) return false; return value == r.mp_impl->value; } void parse_error(std::string_view s) { assert(!s.empty()); assert(s[0] == '#'); const char* p = s.data(); const char* p_end = p + s.size(); ++p; // skip '#'. mem_str_buf buf; for (; p != p_end; ++p) { bool good = true; switch (*p) { case '!': { if (buf.empty()) { good = false; break; } if (buf.equals("REF")) { value = formula_error_t::ref_result_not_available; } else if (buf.equals("DIV/0")) { value = formula_error_t::division_by_zero; } else { good = false; break; } type = result_type::error; return; } case '?': { if (buf.empty()) { good = false; break; } if (buf.equals("NAME")) { value = formula_error_t::name_not_found; } else { good = false; break; } type = result_type::error; return; } } if (!good) // parse failure. break; if (buf.empty()) buf.set_start(p); else buf.inc(); } std::ostringstream os; os << "malformed error string: " << s; throw general_error(os.str()); } void parse_string(std::string_view s) { if (s.size() <= 1u) return; assert(s[0] == '"'); const char* p = s.data(); ++p; const char* p_first = p; std::size_t len = 0; for (std::size_t i = 1; i < s.size(); ++i, ++len, ++p) { char c = *p; if (c == '"') break; } if (!len) throw general_error("failed to parse string result."); type = result_type::string; value = std::string(p_first, len); } }; formula_result::formula_result() : mp_impl(std::make_unique()) {} formula_result::formula_result(const formula_result& r) : mp_impl(std::make_unique(*r.mp_impl)) {} formula_result::formula_result(formula_result&& r) : mp_impl(std::move(r.mp_impl)) {} formula_result::formula_result(double v) : mp_impl(std::make_unique(v)) {} formula_result::formula_result(std::string str) : mp_impl(std::make_unique(std::move(str))) {} formula_result::formula_result(formula_error_t e) : mp_impl(std::make_unique(e)) {} formula_result::formula_result(matrix mtx) : mp_impl(std::make_unique(std::move(mtx))) {} formula_result::~formula_result() {} void formula_result::reset() { mp_impl->reset(); } void formula_result::set_value(double v) { mp_impl->set_value(v); } void formula_result::set_string_value(std::string str) { mp_impl->set_string_value(std::move(str)); } void formula_result::set_error(formula_error_t e) { mp_impl->set_error(e); } void formula_result::set_matrix(matrix mtx) { mp_impl->set_matrix(std::move(mtx)); } double formula_result::get_value() const { return mp_impl->get_value(); } const std::string& formula_result::get_string() const { return mp_impl->get_string_value(); } formula_error_t formula_result::get_error() const { return mp_impl->get_error(); } const matrix& formula_result::get_matrix() const { return mp_impl->get_matrix(); } matrix& formula_result::get_matrix() { return mp_impl->get_matrix(); } formula_result::result_type formula_result::get_type() const { return mp_impl->get_type(); } std::string formula_result::str(const iface::formula_model_access& cxt) const { return mp_impl->str(cxt); } void formula_result::parse(std::string_view s) { mp_impl->parse(s); } formula_result& formula_result::operator= (formula_result r) { mp_impl->move_from(std::move(r)); return *this; } bool formula_result::operator== (const formula_result& r) const { return mp_impl->equals(r); } bool formula_result::operator!= (const formula_result& r) const { return !operator== (r); } std::ostream& operator<< (std::ostream& os, formula_result::result_type v) { switch (v) { case formula_result::result_type::error: os << "error"; break; case formula_result::result_type::matrix: os << "matrix"; break; case formula_result::result_type::string: os << "string"; break; case formula_result::result_type::value: os << "value"; break; default: ; } return os; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/python/0000775000175000017500000000000014136644732012541 500000000000000libixion-0.17.0/src/python/sheet.cpp0000664000175000017500000003005614122770261014271 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "sheet.hpp" #include "global.hpp" #include "ixion/model_context.hpp" #include "ixion/formula_name_resolver.hpp" #include "ixion/formula.hpp" #include "ixion/cell.hpp" #include #include using namespace std; namespace ixion { namespace python { sheet_data::sheet_data() : m_global(nullptr), m_sheet_index(-1) {} namespace { struct sheet { PyObject_HEAD PyObject* name; // sheet name sheet_data* m_data; }; void sheet_dealloc(sheet* self) { delete self->m_data; Py_XDECREF(self->name); Py_TYPE(self)->tp_free(reinterpret_cast(self)); } PyObject* sheet_new(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwargs*/) { sheet* self = (sheet*)type->tp_alloc(type, 0); if (!self) return nullptr; self->m_data = new sheet_data; self->name = PyUnicode_FromString(""); if (!self->name) { Py_DECREF(self); return nullptr; } return reinterpret_cast(self); } int sheet_init(sheet* self, PyObject* args, PyObject* kwargs) { PyObject* name = nullptr; static const char* kwlist[] = { "name", nullptr }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", (char**)kwlist, &name)) return -1; if (name) { PyObject* tmp = self->name; Py_INCREF(name); self->name = name; Py_XDECREF(tmp); } return 0; } PyObject* sheet_set_numeric_cell(sheet* self, PyObject* args, PyObject* kwargs) { int col = -1; int row = -1; double val = 0.0; static const char* kwlist[] = { "row", "column", "value", nullptr }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iid", const_cast(kwlist), &row, &col, &val)) return nullptr; sheet_data* sd = get_sheet_data(reinterpret_cast(self)); if (!sd->m_global) { PyErr_SetString(get_python_sheet_error(), "This Sheet object does not belong to a Document object."); return nullptr; } ixion::model_context& cxt = sd->m_global->m_cxt; ixion::abs_address_t pos(sd->m_sheet_index, row, col); sd->m_global->m_modified_cells.insert(pos); cxt.set_numeric_cell(pos, val); Py_INCREF(Py_None); return Py_None; } PyObject* sheet_set_string_cell(sheet* self, PyObject* args, PyObject* kwargs) { int col = -1; int row = -1; char* val = nullptr; static const char* kwlist[] = { "row", "column", "value", nullptr }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iis", const_cast(kwlist), &row, &col, &val)) return nullptr; sheet_data* sd = get_sheet_data(reinterpret_cast(self)); if (!sd->m_global) { PyErr_SetString(get_python_sheet_error(), "This Sheet object does not belong to a Document object."); return nullptr; } ixion::model_context& cxt = sd->m_global->m_cxt; ixion::abs_address_t pos(sd->m_sheet_index, row, col); sd->m_global->m_modified_cells.insert(pos); cxt.set_string_cell(pos, val); Py_INCREF(Py_None); return Py_None; } PyObject* sheet_set_formula_cell(sheet* self, PyObject* args, PyObject* kwargs) { int col = -1; int row = -1; char* formula = nullptr; static const char* kwlist[] = { "row", "column", "value", nullptr }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iis", const_cast(kwlist), &row, &col, &formula)) return nullptr; sheet_data* sd = get_sheet_data(reinterpret_cast(self)); if (!sd->m_global) { PyErr_SetString(get_python_sheet_error(), "This Sheet object does not belong to a Document object."); return nullptr; } ixion::model_context& cxt = sd->m_global->m_cxt; ixion::abs_address_t pos(sd->m_sheet_index, row, col); sd->m_global->m_dirty_formula_cells.insert(pos); ixion::formula_tokens_t tokens = ixion::parse_formula_string(cxt, pos, *sd->m_global->m_resolver, formula); auto ts = formula_tokens_store::create(); ts->get() = std::move(tokens); cxt.set_formula_cell(pos, ts); // Put this formula cell in a dependency chain. ixion::register_formula_cell(cxt, pos); Py_INCREF(Py_None); return Py_None; } PyObject* sheet_get_numeric_value(sheet* self, PyObject* args, PyObject* kwargs) { int col = -1; int row = -1; static const char* kwlist[] = { "row", "column", nullptr }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", const_cast(kwlist), &row, &col)) return nullptr; sheet_data* sd = get_sheet_data(reinterpret_cast(self)); if (!sd->m_global) { PyErr_SetString(get_python_sheet_error(), "This Sheet object does not belong to a Document object."); return nullptr; } ixion::model_context& cxt = sd->m_global->m_cxt; double val = 0.0; try { val = cxt.get_numeric_value(ixion::abs_address_t(sd->m_sheet_index, row, col)); } catch (const formula_error&) { PyErr_SetString(PyExc_TypeError, "The formula cell has yet to be calculated"); return nullptr; } return PyFloat_FromDouble(val); } PyObject* sheet_get_string_value(sheet* self, PyObject* args, PyObject* kwargs) { int col = -1; int row = -1; static const char* kwlist[] = { "row", "column", nullptr }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", const_cast(kwlist), &row, &col)) return nullptr; sheet_data* sd = get_sheet_data(reinterpret_cast(self)); if (!sd->m_global) { PyErr_SetString(get_python_sheet_error(), "This Sheet object does not belong to a Document object."); return nullptr; } ixion::model_context& cxt = sd->m_global->m_cxt; std::string_view s = cxt.get_string_value(ixion::abs_address_t(sd->m_sheet_index, row, col)); if (s.empty()) return PyUnicode_FromStringAndSize(nullptr, 0); return PyUnicode_FromStringAndSize(s.data(), s.size()); } PyObject* sheet_get_formula_expression(sheet* self, PyObject* args, PyObject* kwargs) { int col = -1; int row = -1; static const char* kwlist[] = { "row", "column", nullptr }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", const_cast(kwlist), &row, &col)) return nullptr; sheet_data* sd = get_sheet_data(reinterpret_cast(self)); if (!sd->m_global) { PyErr_SetString(get_python_sheet_error(), "This Sheet object does not belong to a Document object."); return nullptr; } ixion::model_context& cxt = sd->m_global->m_cxt; ixion::abs_address_t pos(sd->m_sheet_index, row, col); const ixion::formula_cell* fc = cxt.get_formula_cell(pos); if (!fc) { PyErr_SetString(get_python_sheet_error(), "No formula cell at specified position."); return nullptr; } const ixion::formula_tokens_t& ft = fc->get_tokens()->get(); string str = ixion::print_formula_tokens(cxt, pos, *sd->m_global->m_resolver, ft); if (str.empty()) return PyUnicode_FromString(""); return PyUnicode_FromStringAndSize(str.data(), str.size()); } PyObject* sheet_erase_cell(sheet* self, PyObject* args, PyObject* kwargs) { PyErr_SetString(PyExc_RuntimeError, "erase_cell() method has been deprecated. Please use empty_cell() instead."); return nullptr; } PyObject* sheet_empty_cell(sheet* self, PyObject* args, PyObject* kwargs) { int col = -1; int row = -1; static const char* kwlist[] = { "row", "column", nullptr }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", const_cast(kwlist), &row, &col)) return nullptr; sheet_data* sd = get_sheet_data(reinterpret_cast(self)); if (!sd->m_global) { PyErr_SetString(get_python_sheet_error(), "This Sheet object does not belong to a Document object."); return nullptr; } ixion::model_context& cxt = sd->m_global->m_cxt; abs_address_t pos(sd->m_sheet_index, row, col); sd->m_global->m_modified_cells.insert(pos); cxt.empty_cell(pos); Py_INCREF(Py_None); return Py_None; } PyMethodDef sheet_methods[] = { { "set_numeric_cell", (PyCFunction)sheet_set_numeric_cell, METH_VARARGS | METH_KEYWORDS, "set numeric value to specified cell" }, { "set_formula_cell", (PyCFunction)sheet_set_formula_cell, METH_VARARGS | METH_KEYWORDS, "set formula to specified cell" }, { "set_string_cell", (PyCFunction)sheet_set_string_cell, METH_VARARGS | METH_KEYWORDS, "set string to specified cell" }, { "get_numeric_value", (PyCFunction)sheet_get_numeric_value, METH_VARARGS | METH_KEYWORDS, "get numeric value from specified cell" }, { "get_string_value", (PyCFunction)sheet_get_string_value, METH_VARARGS | METH_KEYWORDS, "get string value from specified cell" }, { "get_formula_expression", (PyCFunction)sheet_get_formula_expression, METH_VARARGS | METH_KEYWORDS, "get formula expression string from specified cell position" }, { "empty_cell", (PyCFunction)sheet_empty_cell, METH_VARARGS | METH_KEYWORDS, "empty cell at specified position" }, { "erase_cell", (PyCFunction)sheet_erase_cell, METH_VARARGS | METH_KEYWORDS, "erase cell at specified position" }, { nullptr } }; PyMemberDef sheet_members[] = { { (char*)"name", T_OBJECT_EX, offsetof(sheet, name), READONLY, (char*)"sheet name" }, { nullptr } }; PyTypeObject sheet_type = { PyVarObject_HEAD_INIT(nullptr, 0) "ixion.Sheet", // tp_name sizeof(sheet), // tp_basicsize 0, // tp_itemsize (destructor)sheet_dealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr 0, // tp_as_number 0, // tp_as_sequence 0, // tp_as_mapping 0, // tp_hash 0, // tp_call 0, // tp_str 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags "ixion sheet object", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext sheet_methods, // tp_methods sheet_members, // tp_members 0, // tp_getset 0, // tp_base 0, // tp_dict 0, // tp_descr_get 0, // tp_descr_set 0, // tp_dictoffset (initproc)sheet_init, // tp_init 0, // tp_alloc sheet_new, // tp_new }; } PyTypeObject* get_sheet_type() { return &sheet_type; } sheet_data* get_sheet_data(PyObject* obj) { return reinterpret_cast(obj)->m_data; } PyObject* get_sheet_name(PyObject* obj) { return reinterpret_cast(obj)->name; } }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/python/python.cpp0000664000175000017500000001011614122770261014475 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "document.hpp" #include "sheet.hpp" #include "global.hpp" #include "ixion/env.hpp" #include "ixion/info.hpp" #include #include #define IXION_DEBUG_PYTHON 0 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) using namespace std; namespace ixion { namespace python { namespace { #if IXION_DEBUG_PYTHON void print_args(PyObject* args) { string args_str; PyObject* repr = PyObject_Repr(args); if (repr) { Py_INCREF(repr); args_str = PyBytes_AsString(repr); Py_DECREF(repr); } cout << args_str << "\n"; } #endif PyObject* info(PyObject*, PyObject*) { cout << "ixion version: " << ixion::get_version_major() << '.' << ixion::get_version_minor() << '.' << ixion::get_version_micro() << endl; Py_INCREF(Py_None); return Py_None; } PyObject* column_label(PyObject* /*module*/, PyObject* args, PyObject* kwargs) { int start; int stop; int resolver_index = 1; // Excel A1 by default static const char* kwlist[] = { "start", "stop", "resolver", nullptr }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i", const_cast(kwlist), &start, &stop, &resolver_index)) return nullptr; if (start >= stop) { PyErr_SetString( PyExc_IndexError, "Start position is larger or equal to the stop position."); return nullptr; } if (start < 0) { PyErr_SetString( PyExc_IndexError, "Start position should be larger than or equal to 0."); return nullptr; } auto resolver = formula_name_resolver::get( static_cast(resolver_index), nullptr); if (!resolver) { PyErr_SetString( get_python_formula_error(), "Specified resolver type is invalid."); return nullptr; } int size = stop - start; PyObject* t = PyTuple_New(size); for (int i = start; i < stop; ++i) { string s = resolver->get_column_name(i); PyObject* o = PyUnicode_FromString(s.c_str()); PyTuple_SetItem(t, i-start, o); } return t; } PyMethodDef ixion_methods[] = { { "info", (PyCFunction)info, METH_NOARGS, "Print ixion module information." }, { "column_label", (PyCFunction)column_label, METH_VARARGS | METH_KEYWORDS, "Return a list of column label strings based on specified column range values." }, { nullptr, nullptr, 0, nullptr } }; struct module_state { PyObject* error; }; int ixion_traverse(PyObject* m, visitproc visit, void* arg) { Py_VISIT(GETSTATE(m)->error); return 0; } int ixion_clear(PyObject* m) { Py_CLEAR(GETSTATE(m)->error); return 0; } } struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "ixion", nullptr, sizeof(struct module_state), ixion_methods, nullptr, ixion_traverse, ixion_clear, nullptr }; }} extern "C" { IXION_DLLPUBLIC PyObject* PyInit_ixion() { PyTypeObject* doc_type = ixion::python::get_document_type(); if (PyType_Ready(doc_type) < 0) return nullptr; PyTypeObject* sheet_type = ixion::python::get_sheet_type(); if (PyType_Ready(sheet_type) < 0) return nullptr; PyObject* m = PyModule_Create(&ixion::python::moduledef); Py_INCREF(doc_type); PyModule_AddObject(m, "Document", reinterpret_cast(doc_type)); Py_INCREF(sheet_type); PyModule_AddObject(m, "Sheet", reinterpret_cast(sheet_type)); PyModule_AddObject( m, "DocumentError", ixion::python::get_python_document_error()); PyModule_AddObject( m, "SheetError", ixion::python::get_python_sheet_error()); PyModule_AddObject( m, "FormulaError", ixion::python::get_python_formula_error()); return m; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/python/Makefile.in0000664000175000017500000012300314136644552014525 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/python ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pyexecdir)" LTLIBRARIES = $(pyexec_LTLIBRARIES) am__DEPENDENCIES_1 = @BUILD_PYTHON_TRUE@ixion_la_DEPENDENCIES = ../libixion/libixion-@IXION_API_VERSION@.la \ @BUILD_PYTHON_TRUE@ $(am__DEPENDENCIES_1) am__ixion_la_SOURCES_DIST = document.hpp document.cpp global.hpp \ global.cpp python.cpp sheet.hpp sheet.cpp @BUILD_PYTHON_TRUE@am_ixion_la_OBJECTS = ixion_la-document.lo \ @BUILD_PYTHON_TRUE@ ixion_la-global.lo ixion_la-python.lo \ @BUILD_PYTHON_TRUE@ ixion_la-sheet.lo ixion_la_OBJECTS = $(am_ixion_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = ixion_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(ixion_la_LDFLAGS) $(LDFLAGS) -o $@ @BUILD_PYTHON_TRUE@am_ixion_la_rpath = -rpath $(pyexecdir) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/ixion_la-document.Plo \ ./$(DEPDIR)/ixion_la-global.Plo \ ./$(DEPDIR)/ixion_la-python.Plo ./$(DEPDIR)/ixion_la-sheet.Plo am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(ixion_la_SOURCES) DIST_SOURCES = $(am__ixion_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ BOOST_LDPATH = @BOOST_LDPATH@ BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ BOOST_ROOT = @BOOST_ROOT@ BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX17 = @HAVE_CXX17@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IXION_API_VERSION = @IXION_API_VERSION@ IXION_MAJOR_API_VERSION = @IXION_MAJOR_API_VERSION@ IXION_MAJOR_VERSION = @IXION_MAJOR_VERSION@ IXION_MICRO_VERSION = @IXION_MICRO_VERSION@ IXION_MINOR_API_VERSION = @IXION_MINOR_API_VERSION@ IXION_MINOR_VERSION = @IXION_MINOR_VERSION@ IXION_VERSION = @IXION_VERSION@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MDDS_CFLAGS = @MDDS_CFLAGS@ MDDS_LIBS = @MDDS_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POW_LIB = @POW_LIB@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ VULKAN_CFLAGS = @VULKAN_CFLAGS@ VULKAN_LIBS = @VULKAN_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @BUILD_PYTHON_TRUE@EXTRA_DIST = test-env.sh @BUILD_PYTHON_TRUE@pyexec_LTLIBRARIES = ixion.la @BUILD_PYTHON_TRUE@ixion_la_SOURCES = \ @BUILD_PYTHON_TRUE@ document.hpp \ @BUILD_PYTHON_TRUE@ document.cpp \ @BUILD_PYTHON_TRUE@ global.hpp \ @BUILD_PYTHON_TRUE@ global.cpp \ @BUILD_PYTHON_TRUE@ python.cpp \ @BUILD_PYTHON_TRUE@ sheet.hpp \ @BUILD_PYTHON_TRUE@ sheet.cpp @BUILD_PYTHON_TRUE@ixion_la_LDFLAGS = -module -avoid-version -export-symbols-regex PyInit_ixion @BUILD_PYTHON_TRUE@ixion_la_CPPFLAGS = -I$(top_srcdir)/include $(PYTHON_CFLAGS) $(MDDS_CFLAGS) @BUILD_PYTHON_TRUE@ixion_la_LIBADD = \ @BUILD_PYTHON_TRUE@ ../libixion/libixion-@IXION_API_VERSION@.la \ @BUILD_PYTHON_TRUE@ $(PYTHON_LIBS) @BUILD_PYTHON_TRUE@@OSX_FALSE@TESTS = \ @BUILD_PYTHON_TRUE@@OSX_FALSE@ ../../test/python/document.py \ @BUILD_PYTHON_TRUE@@OSX_FALSE@ ../../test/python/module.py @BUILD_PYTHON_TRUE@@OSX_TRUE@TESTS = ../../bin/run-python-test-osx.sh @BUILD_PYTHON_TRUE@@OSX_FALSE@AM_TESTS_ENVIRONMENT = . $(srcdir)/test-env.sh; all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/python/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/python/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-pyexecLTLIBRARIES: $(pyexec_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pyexec_LTLIBRARIES)'; test -n "$(pyexecdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(pyexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pyexecdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pyexecdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pyexecdir)"; \ } uninstall-pyexecLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pyexec_LTLIBRARIES)'; test -n "$(pyexecdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pyexecdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pyexecdir)/$$f"; \ done clean-pyexecLTLIBRARIES: -test -z "$(pyexec_LTLIBRARIES)" || rm -f $(pyexec_LTLIBRARIES) @list='$(pyexec_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } ixion.la: $(ixion_la_OBJECTS) $(ixion_la_DEPENDENCIES) $(EXTRA_ixion_la_DEPENDENCIES) $(AM_V_CXXLD)$(ixion_la_LINK) $(am_ixion_la_rpath) $(ixion_la_OBJECTS) $(ixion_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_la-document.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_la-global.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_la-python.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_la-sheet.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< ixion_la-document.lo: document.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ixion_la-document.lo -MD -MP -MF $(DEPDIR)/ixion_la-document.Tpo -c -o ixion_la-document.lo `test -f 'document.cpp' || echo '$(srcdir)/'`document.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ixion_la-document.Tpo $(DEPDIR)/ixion_la-document.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='document.cpp' object='ixion_la-document.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ixion_la-document.lo `test -f 'document.cpp' || echo '$(srcdir)/'`document.cpp ixion_la-global.lo: global.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ixion_la-global.lo -MD -MP -MF $(DEPDIR)/ixion_la-global.Tpo -c -o ixion_la-global.lo `test -f 'global.cpp' || echo '$(srcdir)/'`global.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ixion_la-global.Tpo $(DEPDIR)/ixion_la-global.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='global.cpp' object='ixion_la-global.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ixion_la-global.lo `test -f 'global.cpp' || echo '$(srcdir)/'`global.cpp ixion_la-python.lo: python.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ixion_la-python.lo -MD -MP -MF $(DEPDIR)/ixion_la-python.Tpo -c -o ixion_la-python.lo `test -f 'python.cpp' || echo '$(srcdir)/'`python.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ixion_la-python.Tpo $(DEPDIR)/ixion_la-python.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='python.cpp' object='ixion_la-python.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ixion_la-python.lo `test -f 'python.cpp' || echo '$(srcdir)/'`python.cpp ixion_la-sheet.lo: sheet.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ixion_la-sheet.lo -MD -MP -MF $(DEPDIR)/ixion_la-sheet.Tpo -c -o ixion_la-sheet.lo `test -f 'sheet.cpp' || echo '$(srcdir)/'`sheet.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ixion_la-sheet.Tpo $(DEPDIR)/ixion_la-sheet.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sheet.cpp' object='ixion_la-sheet.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ixion_la-sheet.lo `test -f 'sheet.cpp' || echo '$(srcdir)/'`sheet.cpp mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? ../../test/python/document.py.log: ../../test/python/document.py @p='../../test/python/document.py'; \ b='../../test/python/document.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ../../test/python/module.py.log: ../../test/python/module.py @p='../../test/python/module.py'; \ b='../../test/python/module.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ../../bin/run-python-test-osx.sh.log: ../../bin/run-python-test-osx.sh @p='../../bin/run-python-test-osx.sh'; \ b='../../bin/run-python-test-osx.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pyexecdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-pyexecLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/ixion_la-document.Plo -rm -f ./$(DEPDIR)/ixion_la-global.Plo -rm -f ./$(DEPDIR)/ixion_la-python.Plo -rm -f ./$(DEPDIR)/ixion_la-sheet.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pyexecLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/ixion_la-document.Plo -rm -f ./$(DEPDIR)/ixion_la-global.Plo -rm -f ./$(DEPDIR)/ixion_la-python.Plo -rm -f ./$(DEPDIR)/ixion_la-sheet.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pyexecLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ check-am clean clean-generic clean-libtool \ clean-pyexecLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-pyexecLTLIBRARIES install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-pyexecLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libixion-0.17.0/src/python/global.cpp0000664000175000017500000000202313722272744014422 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ixion/config.hpp" #include "global.hpp" namespace ixion { namespace python { document_global::document_global() : m_cxt(), m_resolver(ixion::formula_name_resolver::get(formula_name_resolver_t::excel_a1, &m_cxt)) { } PyObject* get_python_document_error() { static PyObject* p = PyErr_NewException(const_cast("ixion.DocumentError"), NULL, NULL); return p; } PyObject* get_python_sheet_error() { static PyObject* p = PyErr_NewException(const_cast("ixion.SheetError"), NULL, NULL); return p; } PyObject* get_python_formula_error() { static PyObject* p = PyErr_NewException(const_cast("ixion.FormulaError"), NULL, NULL); return p; } }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/python/document.hpp0000644000175000017500000000103013273351731014773 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_PYTHON_DOCUMENT_HPP #define INCLUDED_IXION_PYTHON_DOCUMENT_HPP #include namespace ixion { namespace python { PyTypeObject* get_document_type(); }} #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/python/document.cpp0000664000175000017500000002257114122770261015002 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "document.hpp" #include "sheet.hpp" #include "global.hpp" #include "ixion/formula.hpp" #include "ixion/exceptions.hpp" #include "ixion/config.hpp" #include #include #include #include using namespace std; namespace ixion { namespace python { namespace { /** non-python part of the document data */ struct document_data { document_global m_global; vector m_sheets; ~document_data(); }; struct free_pyobj { void operator() (PyObject* p) { Py_XDECREF(p); } }; document_data::~document_data() { for_each(m_sheets.begin(), m_sheets.end(), free_pyobj()); } /** * Python Document object. */ struct pyobj_document { PyObject_HEAD document_data* m_data; }; void document_dealloc(pyobj_document* self) { delete self->m_data; Py_TYPE(self)->tp_free(reinterpret_cast(self)); } PyObject* document_new(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwargs*/) { pyobj_document* self = (pyobj_document*)type->tp_alloc(type, 0); self->m_data = new document_data; return reinterpret_cast(self); } int document_init(pyobj_document* self, PyObject* /*args*/, PyObject* /*kwargs*/) { return 0; } PyObject* document_append_sheet(pyobj_document* self, PyObject* args) { char* sheet_name = nullptr; if (!PyArg_ParseTuple(args, "s", &sheet_name)) { PyErr_SetString(PyExc_TypeError, "The method must be given a sheet name string"); return nullptr; } assert(sheet_name); PyTypeObject* sheet_type = get_sheet_type(); if (!sheet_type) return nullptr; PyObject* obj_sheet = sheet_type->tp_new(sheet_type, args, 0); if (!obj_sheet) { PyErr_SetString(PyExc_RuntimeError, "Failed to allocate memory for the new sheet object."); return nullptr; } sheet_type->tp_init(obj_sheet, args, 0); // Pass model_context to the sheet object. sheet_data* sd = get_sheet_data(obj_sheet); sd->m_global = &self->m_data->m_global; ixion::model_context& cxt = sd->m_global->m_cxt; try { sd->m_sheet_index = cxt.append_sheet(sheet_name); } catch (const model_context_error& e) { // Most likely the sheet name already exists in this document. Py_XDECREF(obj_sheet); switch (e.get_error_type()) { case model_context_error::sheet_name_conflict: PyErr_SetString(get_python_document_error(), e.what()); break; default: PyErr_SetString(get_python_document_error(), "Sheet insertion failed for unknown reason."); } return nullptr; } catch (const general_error& e) { Py_XDECREF(obj_sheet); ostringstream os; os << "Sheet insertion failed and the reason is '" << e.what() << "'"; PyErr_SetString(get_python_document_error(), os.str().c_str()); return nullptr; } // Append this sheet instance to the document. Py_INCREF(obj_sheet); self->m_data->m_sheets.push_back(obj_sheet); return obj_sheet; } const char* doc_document_calculate = "Document.calculate([threads])\n" "\n" "(Re-)calculate all modified formula cells in the document.\n" "\n" "Keyword arguments:\n" "\n" "threads -- number of threads to use besides the main thread, or 0 if all\n" " calculations are to be performed on the main thread. (default 0)\n" ; PyObject* document_calculate(pyobj_document* self, PyObject* args, PyObject* kwargs) { static const char* kwlist[] = { "threads", nullptr }; long threads = 0; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", const_cast(kwlist), &threads)) { PyErr_SetString(PyExc_TypeError, "Failed to parse the arguments for Document.calculate()"); return nullptr; } document_global& dg = self->m_data->m_global; // Query additional dirty formula cells and add them to the current set. std::vector sorted = ixion::query_and_sort_dirty_cells( dg.m_cxt, dg.m_modified_cells, &dg.m_dirty_formula_cells); ixion::calculate_sorted_cells(dg.m_cxt, sorted, threads); dg.m_modified_cells.clear(); dg.m_dirty_formula_cells.clear(); Py_INCREF(Py_None); return Py_None; } PyObject* document_get_sheet(pyobj_document* self, PyObject* arg) { const vector& sheets = self->m_data->m_sheets; if (PyLong_Check(arg)) { long index = PyLong_AsLong(arg); if (index == -1 && PyErr_Occurred()) return nullptr; if (index < 0 || static_cast(index) >= sheets.size()) { PyErr_SetString(PyExc_IndexError, "Out-of-bound sheet index"); return nullptr; } PyObject* sheet_obj = sheets[index]; Py_INCREF(sheet_obj); return sheet_obj; } // Not a python int object. See if it's a string object. const char* name = PyUnicode_AsUTF8(arg); if (!name) { PyErr_SetString(PyExc_TypeError, "The 'arg' value must be either of type int or type str."); return nullptr; } // Iterate through all sheets to find a match. // TODO : Use string hash to speed up the lookup. vector::const_iterator i = sheets.begin(), ie = sheets.end(); for (; i != ie; ++i) { PyObject* sh = *i; PyObject* obj = get_sheet_name(sh); if (!obj) continue; const char* this_name = PyUnicode_AsUTF8(obj); if (!this_name) continue; if (!strcmp(name, this_name)) { Py_INCREF(sh); return sh; } } ostringstream os; os << "No sheet named '" << name << "' found"; PyErr_SetString(PyExc_IndexError, os.str().c_str()); return nullptr; } PyObject* document_getter_sheet_names(pyobj_document* self, void* closure) { model_context& cxt = self->m_data->m_global.m_cxt; const vector& sheets = self->m_data->m_sheets; size_t n = sheets.size(); PyObject* t = PyTuple_New(n); for (size_t i = 0; i < n; ++i) { std::string name = cxt.get_sheet_name(i); PyObject* o = PyUnicode_FromString(name.c_str()); PyTuple_SetItem(t, i, o); } return t; } PyMethodDef document_methods[] = { { "append_sheet", (PyCFunction)document_append_sheet, METH_VARARGS, "append new sheet to the document" }, { "calculate", (PyCFunction)document_calculate, METH_VARARGS | METH_KEYWORDS, doc_document_calculate }, { "get_sheet", (PyCFunction)document_get_sheet, METH_O, "get a sheet object either by index or name" }, { nullptr } }; PyGetSetDef document_getset[] = { { "sheet_names", (getter)document_getter_sheet_names, (setter)nullptr, "A tuple of sheet names", nullptr }, { nullptr } }; PyTypeObject document_type = { PyVarObject_HEAD_INIT(nullptr, 0) "ixion.Document", // tp_name sizeof(pyobj_document), // tp_basicsize 0, // tp_itemsize (destructor)document_dealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr 0, // tp_as_number 0, // tp_as_sequence 0, // tp_as_mapping 0, // tp_hash 0, // tp_call 0, // tp_str 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags "ixion document object", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext document_methods, // tp_methods 0, // tp_members document_getset, // tp_getset 0, // tp_base 0, // tp_dict 0, // tp_descr_get 0, // tp_descr_set 0, // tp_dictoffset (initproc)document_init, // tp_init 0, // tp_alloc document_new, // tp_new }; } PyTypeObject* get_document_type() { return &document_type; } }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/python/test-env.sh0000644000175000017500000000033213357466304014557 00000000000000 PYTHONPATH=.libs:$PYTHONPATH # Ensure that the libixion shared library built as part of the current build # is discovered first. LD_LIBRARY_PATH=../libixion/.libs:$LD_LIBRARY_PATH export PYTHONPATH LD_LIBRARY_PATH libixion-0.17.0/src/python/sheet.hpp0000644000175000017500000000163713273351731014302 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_PYTHON_SHEET_HPP #define INCLUDED_IXION_PYTHON_SHEET_HPP #include #include "ixion/types.hpp" namespace ixion { namespace python { struct document_global; struct sheet_data { document_global* m_global; ixion::sheet_t m_sheet_index; sheet_data(); }; PyTypeObject* get_sheet_type(); sheet_data* get_sheet_data(PyObject* obj); /** * Get the sheet name of a python sheet object. * * @param obj python sheet object. * * @return python string object storing the sheet name. */ PyObject* get_sheet_name(PyObject* obj); }} #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/python/Makefile.am0000664000175000017500000000115514120267564014514 00000000000000if BUILD_PYTHON EXTRA_DIST = test-env.sh pyexec_LTLIBRARIES = ixion.la ixion_la_SOURCES = \ document.hpp \ document.cpp \ global.hpp \ global.cpp \ python.cpp \ sheet.hpp \ sheet.cpp ixion_la_LDFLAGS = -module -avoid-version -export-symbols-regex PyInit_ixion ixion_la_CPPFLAGS = -I$(top_srcdir)/include $(PYTHON_CFLAGS) $(MDDS_CFLAGS) ixion_la_LIBADD = \ ../libixion/libixion-@IXION_API_VERSION@.la \ $(PYTHON_LIBS) if OSX TESTS = ../../bin/run-python-test-osx.sh else AM_TESTS_ENVIRONMENT = . $(srcdir)/test-env.sh; TESTS = \ ../../test/python/document.py \ ../../test/python/module.py endif endif libixion-0.17.0/src/python/global.hpp0000644000175000017500000000214513356770726014440 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef INCLUDED_IXION_PYTHON_GLOBAL_HPP #define INCLUDED_IXION_PYTHON_GLOBAL_HPP #include #include "ixion/model_context.hpp" #include "ixion/formula_name_resolver.hpp" #include "ixion/address.hpp" namespace ixion { namespace python { struct document_global { model_context m_cxt; /** * positions of all modified cells (formula and non-formula cells) since * last calculation. */ abs_range_set_t m_modified_cells; /** positions of all dirty formula cells since last calculation. */ abs_range_set_t m_dirty_formula_cells; std::unique_ptr m_resolver; document_global(); }; PyObject* get_python_document_error(); PyObject* get_python_sheet_error(); PyObject* get_python_formula_error(); }} #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/ixion_parser.cpp0000664000175000017500000000733214122770261014343 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "model_parser.hpp" #include "app_common.hpp" #include #include #include #include #include using namespace std; using namespace ixion; namespace { class parse_file { const size_t m_thread_count; public: parse_file(size_t thread_count) : m_thread_count(thread_count) {} void operator() (const string& fpath) const { double start_time = get_current_time(); cout << detail::get_formula_result_output_separator() << endl; cout << "parsing " << fpath << endl; try { model_parser parser(fpath, m_thread_count); parser.parse(); } catch (const exception& e) { cerr << e.what() << endl; cerr << "failed to parse " << fpath << endl; throw; } cout << detail::get_formula_result_output_separator() << endl; cout << "(duration: " << get_current_time() - start_time << " sec)" << endl; cout << detail::get_formula_result_output_separator() << endl; } }; const char* help_thread = "Specify the number of threads to use for calculation. Note that the number " "specified by this option corresponds with the number of calculation threads " "i.e. those child threads that perform cell interpretations. The main thread " "does not perform any calculations; instead, it creates a new child thread to " "manage the calculation threads, the number of which is specified by the arg. " "Therefore, the total number of threads used by this program will be arg + 1." ; } int main (int argc, char** argv) { namespace po = ::boost::program_options; size_t thread_count = 0; po::options_description desc("Allowed options"); desc.add_options() ("help,h", "Print this help.") ("thread,t", po::value(), help_thread); po::options_description hidden("Hidden options"); hidden.add_options() ("input-file", po::value>(), "input file"); po::options_description cmd_opt; cmd_opt.add(desc).add(hidden); po::positional_options_description po_desc; po_desc.add("input-file", -1); po::variables_map vm; try { po::store( po::command_line_parser(argc, argv).options(cmd_opt).positional(po_desc).run(), vm); po::notify(vm); } catch (const exception& e) { // Unknown options. cout << e.what() << endl; cout << desc; return EXIT_FAILURE; } if (vm.count("help")) { cout << "Usage: ixion-parser [options] FILE1 FILE2 ..." << endl << endl << "The FILE must contain the definitions of cells according to the cell definition rule." << endl << endl << desc; return EXIT_SUCCESS; } if (vm.count("thread")) thread_count = vm["thread"].as(); vector files; if (vm.count("input-file")) files = vm["input-file"].as< vector >(); if (thread_count > 0) { cout << "Using " << thread_count << " threads" << endl; cout << "Number of CPUS: " << std::thread::hardware_concurrency() << endl; } try { // Parse all files one at a time. for_each(files.begin(), files.end(), parse_file(thread_count)); } catch (const exception&) { return EXIT_FAILURE; } return EXIT_SUCCESS; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/Makefile.am0000664000175000017500000000260514122770261013167 00000000000000SUBDIRS = include libixion python AM_CPPFLAGS = \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/include \ $(MDDS_CFLAGS) $(BOOST_CPPFLAGS) bin_PROGRAMS = ixion-parser ixion-sorter ixion-formula-tokenizer ixion_parser_SOURCES = \ ixion_parser.cpp \ model_parser.hpp \ model_parser.cpp \ app_common.hpp \ app_common.cpp \ session_handler.hpp \ session_handler.cpp \ table_handler.hpp \ table_handler.cpp ixion_parser_LDADD = libixion/libixion-@IXION_API_VERSION@.la \ $(BOOST_PROGRAM_OPTIONS_LIBS) ixion_sorter_SOURCES = \ ixion_sorter.cpp \ app_common.cpp \ sort_input_parser.hpp \ sort_input_parser.cpp ixion_sorter_LDADD = libixion/libixion-@IXION_API_VERSION@.la \ $(BOOST_PROGRAM_OPTIONS_LIBS) ixion_formula_tokenizer_SOURCES = \ ixion_formula_tokenizer.cpp ixion_formula_tokenizer_LDADD = libixion/libixion-@IXION_API_VERSION@.la \ $(BOOST_PROGRAM_OPTIONS_LIBS) AM_TESTS_ENVIRONMENT = PATH=.libs$${PATH:+:$${PATH}}; export PATH; \ LD_LIBRARY_PATH=libixion/.libs$${LD_LIBRARY_PATH:+:$${LD_LIBRARY_PATH}}; export LD_LIBRARY_PATH; \ DYLD_LIBRARY_PATH=$${LD_LIBRARY_PATH}}; export DYLD_LIBRARY_PATH; TESTS = \ ../test/parser-test-t0.sh \ ../test/parser-test-t1.sh \ ../test/parser-test-t2.sh \ ../test/parser-test-t3.sh \ ../test/parser-test-t4.sh \ ../test/parser-test-t5.sh \ ../test/parser-test-t6.sh \ ../test/parser-test-t7.sh \ ../test/parser-test-t8.sh libixion-0.17.0/src/ixion_sorter.cpp0000644000175000017500000000432213273351727014367 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "sort_input_parser.hpp" #include #include #include #include #include using namespace std; namespace po = ::boost::program_options; void print_help(const po::options_description& desc) { cout << "Usage: ixion-parser [options] FILE" << endl << endl << "FILE must contain a list of dependencies." << endl << endl << desc; } int main (int argc, char** argv) { po::options_description desc("Allowed options"); desc.add_options() ("help,h", "print this help."); po::options_description hidden("Hidden options"); hidden.add_options() ("input-file", po::value>(), "input file"); po::options_description cmd_opt; cmd_opt.add(desc).add(hidden); po::positional_options_description po_desc; po_desc.add("input-file", -1); po::variables_map vm; try { po::store( po::command_line_parser(argc, argv).options(cmd_opt).positional(po_desc).run(), vm); po::notify(vm); } catch (const exception& e) { // Unknown options. cerr << e.what() << endl; print_help(desc); return EXIT_FAILURE; } if (vm.count("help")) { print_help(desc); return EXIT_SUCCESS; } vector files; if (vm.count("input-file")) files = vm["input-file"].as>(); if (files.size() != 1) { cerr << "Takes exactly one input file." << endl; print_help(desc); return EXIT_FAILURE; } const string& filepath = files[0]; try { ::ixion::sort_input_parser parser(filepath); parser.parse(); parser.print(); } catch (const exception& e) { // Unknown options. cerr << e.what() << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/model_parser.cpp0000664000175000017500000010522314122770261014313 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "model_parser.hpp" #include "app_common.hpp" #include "ixion/formula.hpp" #include "ixion/formula_name_resolver.hpp" #include "ixion/formula_result.hpp" #include "ixion/macros.hpp" #include "ixion/address_iterator.hpp" #include "ixion/dirty_cell_tracker.hpp" #include "ixion/cell_access.hpp" #include "ixion/config.hpp" #include "ixion/cell.hpp" #include #include #include #include #include #include #include #include using namespace std; #define DEBUG_MODEL_PARSER 0 namespace ixion { namespace { long to_long(const mem_str_buf& value) { char* pe = nullptr; long ret = std::strtol(value.get(), &pe, 10); if (value.get() == pe) { ostringstream os; os << "'" << value << "' is not a valid integer."; throw model_parser::parse_error(os.str()); } return ret; } bool is_separator(char c) { switch (c) { case '=': case ':': case '@': return true; default: ; } return false; } mem_str_buf parse_command_to_buffer(const char*& p, const char* p_end) { mem_str_buf buf; ++p; // skip '%'. buf.set_start(p); if (*p == '%') { // This line is a comment. Skip the rest of the line. while (p != p_end && *p != '\n') ++p; return buf; } for (++p; p != p_end && *p != '\n'; ++p) buf.inc(); return buf; } class string_printer { const model_context& m_cxt; char m_sep; bool m_first; public: string_printer(const model_context& cxt, char sep) : m_cxt(cxt), m_sep(sep), m_first(true) {} void operator() (string_id_t sid) { if (m_first) m_first = false; else cout << m_sep; const std::string* p = m_cxt.get_string(sid); if (p) cout << *p; } }; void print_section_title(const char* title) { std::cout << detail::get_formula_result_output_separator() << std::endl << title << std::endl; } namespace commands { enum class type { unknown, comment, calc, recalc, check, exit, push, mode_init, mode_edit, mode_result, mode_result_cache, mode_table, mode_session, mode_named_expression, print_dependency, }; typedef mdds::sorted_string_map map_type; // Keys must be sorted. const std::vector entries = { { IXION_ASCII("%"), type::comment }, { IXION_ASCII("calc"), type::calc }, { IXION_ASCII("check"), type::check }, { IXION_ASCII("exit"), type::exit }, { IXION_ASCII("mode edit"), type::mode_edit }, { IXION_ASCII("mode init"), type::mode_init }, { IXION_ASCII("mode named-expression"), type::mode_named_expression }, { IXION_ASCII("mode result"), type::mode_result }, { IXION_ASCII("mode result-cache"), type::mode_result_cache }, { IXION_ASCII("mode session"), type::mode_session }, { IXION_ASCII("mode table"), type::mode_table }, { IXION_ASCII("print dependency"), type::print_dependency }, { IXION_ASCII("push"), type::push }, { IXION_ASCII("recalc"), type::recalc }, }; const map_type& get() { static map_type mt(entries.data(), entries.size(), type::unknown); return mt; } } // namespace commands } // anonymous namespace model_parser::parse_error::parse_error(const string& msg) : general_error() { ostringstream os; os << "parse error: " << msg; set_message(os.str()); } // ============================================================================ model_parser::check_error::check_error(const string& msg) : general_error(msg) {} // ============================================================================ model_parser::model_parser(const string& filepath, size_t thread_count) : m_context({1048576, 1024}), m_table_handler(), m_session_handler_factory(m_context), mp_table_entry(nullptr), mp_name_resolver(formula_name_resolver::get(formula_name_resolver_t::excel_a1, &m_context)), m_filepath(filepath), m_strm(detail::load_file_content(m_filepath)), m_thread_count(thread_count), mp_head(nullptr), mp_end(nullptr), mp_char(nullptr), m_current_sheet(0), m_parse_mode(parse_mode_unknown), m_print_separator(false), m_print_sheet_name(false) { m_context.set_session_handler_factory(&m_session_handler_factory); m_context.set_table_handler(&m_table_handler); mp_head = m_strm.data(); mp_end = mp_head + m_strm.size(); } model_parser::~model_parser() {} void model_parser::parse() { mp_char = mp_head; m_parse_mode = parse_mode_unknown; for (; mp_char != mp_end; ++mp_char) { // In each iteration, the p always points to the 1st character of a // line. if (*mp_char== '%') { parse_command(); if (m_parse_mode == parse_mode_exit) return; continue; } if (m_print_separator) { m_print_separator = false; cout << detail::get_formula_result_output_separator() << endl; } switch (m_parse_mode) { case parse_mode_init: parse_init(); break; case parse_mode_edit: parse_edit(); break; case parse_mode_result: parse_result(); break; case parse_mode_result_cache: parse_result_cache(); break; case parse_mode_table: parse_table(); break; case parse_mode_session: parse_session(); break; case parse_mode_named_expression: parse_named_expression(); break; default: throw parse_error("unknown parse mode"); } } } void model_parser::init_model() { if (m_context.empty()) m_context.append_sheet("sheet"); } void model_parser::parse_command() { // This line contains a command. mem_str_buf buf_cmd = parse_command_to_buffer(mp_char, mp_end); commands::type cmd = commands::get().find(buf_cmd.get(), buf_cmd.size()); switch (cmd) { case commands::type::comment: // This is a comment line. Just ignore it. break; case commands::type::calc: { print_section_title("calculating"); // Perform full calculation on all currently stored formula cells. for (const abs_range_t& pos : m_dirty_formula_cells) register_formula_cell(m_context, pos.first); abs_range_set_t empty; std::vector sorted_cells = query_and_sort_dirty_cells(m_context, empty, &m_dirty_formula_cells); calculate_sorted_cells(m_context, sorted_cells, m_thread_count); break; } case commands::type::recalc: { print_section_title("recalculating"); // Perform partial recalculation only on those formula cells that // need recalculation. std::vector sorted_cells = query_and_sort_dirty_cells(m_context, m_modified_cells, &m_dirty_formula_cells); calculate_sorted_cells(m_context, sorted_cells, m_thread_count); break; } case commands::type::check: { // Check cell results. check(); break; } case commands::type::exit: { // Exit the loop. m_parse_mode = parse_mode_exit; return; } case commands::type::push: { switch (m_parse_mode) { case parse_mode_table: push_table(); break; case parse_mode_named_expression: push_named_expression(); break; default: throw parse_error("push command was used for wrong mode!"); } break; } case commands::type::mode_init: { print_section_title("initializing"); m_parse_mode = parse_mode_init; m_print_separator = true; break; } case commands::type::mode_result: { // Clear any previous result values. m_formula_results.clear(); m_parse_mode = parse_mode_result; break; } case commands::type::mode_result_cache: { print_section_title("caching formula results"); m_parse_mode = parse_mode_result_cache; m_print_separator = true; break; } case commands::type::mode_edit: { print_section_title("editing"); m_parse_mode = parse_mode_edit; m_dirty_formula_cells.clear(); m_modified_cells.clear(); m_print_separator = true; break; } case commands::type::mode_table: { m_parse_mode = parse_mode_table; mp_table_entry.reset(new table_handler::entry); break; } case commands::type::mode_session: { print_section_title("session"); m_print_separator = true; m_parse_mode = parse_mode_session; break; } case commands::type::mode_named_expression: { m_print_separator = true; m_parse_mode = parse_mode_named_expression; mp_named_expression = std::make_unique(); break; } case commands::type::print_dependency: { print_section_title("print dependency"); print_dependency(); break; } case commands::type::unknown: { ostringstream os; os << "unknown command: " << buf_cmd.str() << endl; throw parse_error(os.str()); } default: ; } } void model_parser::parse_session() { mem_str_buf cmd, value; mem_str_buf* buf = &cmd; for (; mp_char != mp_end && *mp_char != '\n'; ++mp_char) { if (*mp_char == ':') { if (buf == &value) throw parse_error("2nd ':' character is illegal."); buf = &value; continue; } if (buf->empty()) buf->set_start(mp_char); else buf->inc(); } if (cmd == "row-limit") { rc_size_t ss = m_context.get_sheet_size(); ss.row = to_long(value); m_context.set_sheet_size(ss); } else if (cmd == "column-limit") { rc_size_t ss = m_context.get_sheet_size(); ss.column = to_long(value); m_context.set_sheet_size(ss); } else if (cmd == "insert-sheet") { m_context.append_sheet({value.get(), value.size()}); cout << "sheet: (name: " << value << ")" << endl; } else if (cmd == "current-sheet") { m_current_sheet = m_context.get_sheet_index({value.get(), value.size()}); if (m_current_sheet == invalid_sheet) { ostringstream os; os << "No sheet named '" << value << "' found."; throw parse_error(os.str()); } cout << "current sheet: " << value << endl; } else if (cmd == "display-sheet-name") { cout << "display sheet name: " << value << endl; m_print_sheet_name = to_bool({value.get(), value.size()}); m_session_handler_factory.show_sheet_name(m_print_sheet_name); } } void model_parser::parse_init() { init_model(); cell_def_type cell_def = parse_cell_definition(); if (cell_def.name.empty() && cell_def.value.empty()) return; if (cell_def.matrix_value) { assert(cell_def.type == ct_formula); const abs_address_t& pos = cell_def.pos.first; formula_tokens_t tokens = parse_formula_string( m_context, pos, *mp_name_resolver, {cell_def.value.get(), cell_def.value.size()}); m_context.set_grouped_formula_cells(cell_def.pos, std::move(tokens)); m_dirty_formula_cells.insert(cell_def.pos); cout << "{" << get_display_range_string(cell_def.pos) << "}: (m) " << cell_def.value.str() << endl; return; } abs_address_iterator iter(cell_def.pos, rc_direction_t::vertical); for (const abs_address_t& pos : iter) { m_modified_cells.insert(pos); switch (cell_def.type) { case ct_formula: { formula_tokens_t tokens = parse_formula_string( m_context, pos, *mp_name_resolver, {cell_def.value.get(), cell_def.value.size()}); auto ts = formula_tokens_store::create(); ts->get() = std::move(tokens); m_context.set_formula_cell(pos, ts); m_dirty_formula_cells.insert(pos); cout << get_display_cell_string(pos) << ": (f) " << cell_def.value.str() << endl; break; } case ct_string: { m_context.set_string_cell(pos, { cell_def.value.get(), cell_def.value.size() }); cout << get_display_cell_string(pos) << ": (s) " << cell_def.value.str() << endl; break; } case ct_value: { double v = to_double({cell_def.value.get(), cell_def.value.size()}); m_context.set_numeric_cell(pos, v); cout << get_display_cell_string(pos) << ": (n) " << v << endl; break; } case ct_boolean: { bool b = to_bool({cell_def.value.get(), cell_def.value.size()}); m_context.set_boolean_cell(pos, b); cout << get_display_cell_string(pos) << ": (b) " << (b ? "true" : "false") << endl; break; } default: throw model_parser::parse_error("unknown content type"); } } } void model_parser::parse_edit() { cell_def_type cell_def = parse_cell_definition(); if (cell_def.name.empty() && cell_def.value.empty()) return; if (cell_def.matrix_value) { assert(cell_def.type == ct_formula); const abs_address_t& pos = cell_def.pos.first; m_modified_cells.insert(pos); unregister_formula_cell(m_context, pos); formula_tokens_t tokens = parse_formula_string( m_context, pos, *mp_name_resolver, {cell_def.value.get(), cell_def.value.size()}); m_context.set_grouped_formula_cells(cell_def.pos, std::move(tokens)); m_dirty_formula_cells.insert(cell_def.pos); register_formula_cell(m_context, pos); return; } abs_address_iterator iter(cell_def.pos, rc_direction_t::vertical); for (const abs_address_t& pos : iter) { m_modified_cells.insert(pos); unregister_formula_cell(m_context, pos); if (cell_def.value.empty()) { // A valid name is given but with empty definition. Just remove the // existing cell. m_context.empty_cell(pos); continue; } switch (cell_def.type) { case ct_formula: { formula_tokens_t tokens = parse_formula_string( m_context, pos, *mp_name_resolver, {cell_def.value.get(), cell_def.value.size()}); auto ts = formula_tokens_store::create(); ts->get() = std::move(tokens); m_context.set_formula_cell(pos, ts); m_dirty_formula_cells.insert(pos); register_formula_cell(m_context, pos); cout << get_display_cell_string(pos) << ": (f) " << cell_def.value.str() << endl; } break; case ct_string: { m_context.set_string_cell(pos, { cell_def.value.get(), cell_def.value.size() }); cout << get_display_cell_string(pos) << ": (s) " << cell_def.value.str() << endl; } break; case ct_value: { double v = to_double({cell_def.value.get(), cell_def.value.size()}); m_context.set_numeric_cell(pos, v); cout << get_display_cell_string(pos) << ": (n) " << v << endl; } break; default: throw model_parser::parse_error("unknown content type"); } } } void model_parser::parse_result() { parsed_assignment_type res = parse_assignment(); string name_s = res.first.str(); formula_result fres; fres.parse({res.second.get(), res.second.size()}); model_parser::results_type::iterator itr = m_formula_results.find(name_s); if (itr == m_formula_results.end()) { // This cell doesn't exist yet. pair r = m_formula_results.insert(model_parser::results_type::value_type(name_s, fres)); if (!r.second) throw model_parser::parse_error("failed to insert a new result."); } else itr->second = fres; } void model_parser::parse_result_cache() { parsed_assignment_type res = parse_assignment(); string name_s = res.first.str(); formula_result fres; fres.parse({res.second.get(), res.second.size()}); formula_name_t fnt = mp_name_resolver->resolve(name_s, abs_address_t(m_current_sheet,0,0)); switch (fnt.type) { case formula_name_t::cell_reference: { abs_address_t pos = std::get(fnt.value).to_abs(abs_address_t()); formula_cell* fc = m_context.get_formula_cell(pos); if (!fc) { std::ostringstream os; os << name_s << " is not a formula cell"; throw model_parser::parse_error(name_s); } fc->set_result_cache(fres); cout << get_display_cell_string(pos) << ": " << fres.str(m_context) << endl; break; } case formula_name_t::range_reference: throw model_parser::parse_error("TODO: we do not support setting result cache to range just yet."); default: { std::ostringstream os; os << "invalid cell name: " << name_s; throw model_parser::parse_error(os.str()); } } } void model_parser::parse_table() { assert(mp_table_entry); // In table mode, each line must be attribute=value. parsed_assignment_type res = parse_assignment(); const mem_str_buf& name = res.first; const mem_str_buf& value = res.second; table_handler::entry& entry = *mp_table_entry; if (name == "name") entry.name = m_context.add_string({value.get(), value.size()}); else if (name == "range") { if (!mp_name_resolver) return; abs_address_t pos(m_current_sheet,0,0); formula_name_t ret = mp_name_resolver->resolve({value.get(), value.size()}, pos); if (ret.type != formula_name_t::range_reference) throw parse_error("range of a table is expected to be given as a range reference."); entry.range = std::get(ret.value).to_abs(pos); } else if (name == "columns") parse_table_columns(value); else if (name == "totals-row-count") entry.totals_row_count = to_double({value.get(), value.size()}); } void model_parser::push_table() { cout << detail::get_formula_result_output_separator() << endl; if (!mp_table_entry) return; table_handler::entry& entry = *mp_table_entry; const string* ps = m_context.get_string(entry.name); if (ps) cout << "name: " << *ps << endl; if (mp_name_resolver) cout << "range: " << mp_name_resolver->get_name(entry.range, abs_address_t(m_current_sheet,0,0), false) << endl; cout << "columns: "; std::for_each(entry.columns.begin(), entry.columns.end(), string_printer(m_context, ',')); cout << endl; cout << "totals row count: " << mp_table_entry->totals_row_count << endl; m_table_handler.insert(mp_table_entry); assert(!mp_table_entry); } void model_parser::parse_named_expression() { assert(mp_named_expression); parsed_assignment_type res = parse_assignment(); if (res.first == "name") mp_named_expression->name = std::move(res.second.str()); else if (res.first == "expression") mp_named_expression->expression = std::move(res.second.str()); else if (res.first == "origin") { const mem_str_buf& s = res.second; formula_name_t name = mp_name_resolver->resolve( {s.get(), s.size()}, abs_address_t(m_current_sheet,0,0)); if (name.type != formula_name_t::name_type::cell_reference) { ostringstream os; os << "'" << s << "' is not a valid named expression origin."; throw parse_error(os.str()); } mp_named_expression->origin = std::get(name.value).to_abs(abs_address_t(m_current_sheet,0,0)); } else if (res.first == "scope") { // Resolve it as a sheet name and store the sheet index if found. const mem_str_buf& s = res.second; mp_named_expression->scope = m_context.get_sheet_index({s.get(), s.size()}); if (mp_named_expression->scope == invalid_sheet) { ostringstream os; os << "no sheet named '" << s << "' exists in the model."; throw parse_error(os.str()); } } else { ostringstream os; os << "unknown property of named expression '" << res.first << "'"; throw parse_error(os.str()); } } void model_parser::push_named_expression() { assert(mp_named_expression); formula_tokens_t tokens = parse_formula_string( m_context, mp_named_expression->origin, *mp_name_resolver, mp_named_expression->expression); std::string exp_s = print_formula_tokens( m_context, mp_named_expression->origin, *mp_name_resolver, tokens); cout << "name: " << mp_named_expression->name << endl; cout << "expression: " << exp_s << endl; cout << "origin: " << mp_named_expression->origin << endl; cout << "scope: "; if (mp_named_expression->scope == global_scope) cout << "(global)"; else { std::string sheet_name = m_context.get_sheet_name(mp_named_expression->scope); if (sheet_name.empty()) { ostringstream os; os << "no sheet exists with a sheet index of " << mp_named_expression->scope; throw std::runtime_error(os.str()); } cout << sheet_name; } cout << endl; if (mp_named_expression->scope == global_scope) { m_context.set_named_expression(mp_named_expression->name, std::move(tokens)); } else { m_context.set_named_expression( mp_named_expression->scope, mp_named_expression->name, std::move(tokens)); } mp_named_expression.reset(); } void model_parser::print_dependency() { std::cout << detail::get_formula_result_output_separator() << std::endl; std::cout << m_context.get_cell_tracker().to_string() << std::endl; } void model_parser::parse_table_columns(const mem_str_buf& str) { assert(mp_table_entry); table_handler::entry& entry = *mp_table_entry; const char* p = str.get(); const char* pend = p + str.size(); mem_str_buf buf; for (; p != pend; ++p) { if (*p == ',') { // Flush the current column name buffer. string_id_t col_name = empty_string_id; if (!buf.empty()) col_name = m_context.add_string({buf.get(), buf.size()}); entry.columns.push_back(col_name); buf.clear(); } else { if (buf.empty()) buf.set_start(p); else buf.inc(); } } string_id_t col_name = empty_string_id; if (!buf.empty()) col_name = m_context.add_string({buf.get(), buf.size()}); entry.columns.push_back(col_name); } model_parser::parsed_assignment_type model_parser::parse_assignment() { // Parse to get name and value strings. parsed_assignment_type res; mem_str_buf buf; for (; mp_char != mp_end && *mp_char != '\n'; ++mp_char) { if (*mp_char == '=') { if (buf.empty()) throw model_parser::parse_error("left hand side is empty"); res.first = buf; buf.clear(); } else { if (buf.empty()) buf.set_start(mp_char); else buf.inc(); } } if (!buf.empty()) { if (res.first.empty()) throw model_parser::parse_error("'=' is missing"); res.second = buf; } return res; } model_parser::cell_def_type model_parser::parse_cell_definition() { enum class section_type { name, braced_name, after_braced_name, braced_value, value }; section_type section = section_type::name; cell_def_type ret; ret.type = model_parser::ct_unknown; char skip_next = 0; mem_str_buf buf; const char* line_head = mp_char; for (; mp_char != mp_end && *mp_char != '\n'; ++mp_char) { if (skip_next) { if (*mp_char != skip_next) { std::ostringstream os; os << "'" << skip_next << "' was expected, but '" << *mp_char << "' was found."; throw model_parser::parse_error(os.str()); } skip_next = 0; continue; } switch (section) { case section_type::name: { if (mp_char == line_head && *mp_char == '{') { section = section_type::braced_name; continue; } if (is_separator(*mp_char)) { // Separator encountered. Set the name and clear the buffer. if (buf.empty()) throw model_parser::parse_error("left hand side is empty"); ret.name = buf; buf.clear(); switch (*mp_char) { case '=': ret.type = model_parser::ct_formula; break; case ':': ret.type = model_parser::ct_value; break; case '@': ret.type = model_parser::ct_string; break; default: ; } section = section_type::value; continue; } break; } case section_type::braced_name: { if (*mp_char == '}') { ret.name = buf; buf.clear(); section = section_type::after_braced_name; continue; } break; } case section_type::after_braced_name: { switch (*mp_char) { case '{': section = section_type::braced_value; ret.type = model_parser::ct_formula; skip_next = '='; break; case '=': ret.type = model_parser::ct_formula; section = section_type::value; break; case ':': ret.type = model_parser::ct_value; section = section_type::value; break; case '@': ret.type = model_parser::ct_string; section = section_type::value; break; default: { std::ostringstream os; os << "Unexpected character after braced name: '" << *mp_char << "'"; throw model_parser::parse_error(os.str()); } } continue; // skip this character. } case section_type::braced_value: case section_type::value: default: ; } if (buf.empty()) buf.set_start(mp_char); else buf.inc(); } ret.value = buf; if (ret.type == model_parser::ct_value && !ret.value.empty()) { // Check if this is a potential boolean value. if (ret.value[0] == 't' || ret.value[0] == 'f') ret.type = model_parser::ct_boolean; } if (section == section_type::braced_value) { // Make sure that the braced value ends with '}'. char last = ret.value.back(); if (last != '}') { std::ostringstream os; os << "'}' was expected at the end of a braced value, but '" << last << "' was found."; model_parser::parse_error(os.str()); } ret.value.dec(); ret.matrix_value = true; } if (ret.name.empty()) { if (ret.value.empty()) // This is an empty line. Bail out. return ret; // Buffer is not empty but name is not given. We must be missing a separator. std::ostringstream os; os << "separator may be missing (name='" << ret.name << "'; value='" << ret.value << "')"; throw model_parser::parse_error(os.str()); } formula_name_t fnt = mp_name_resolver->resolve( {ret.name.get(), ret.name.size()}, abs_address_t(m_current_sheet,0,0)); switch (fnt.type) { case formula_name_t::cell_reference: { ret.pos.first = std::get(fnt.value).to_abs(abs_address_t(0,0,0)); ret.pos.last = ret.pos.first; break; } case formula_name_t::range_reference: { ret.pos = std::get(fnt.value).to_abs(abs_address_t(0,0,0)); break; } default: { ostringstream os; os << "invalid cell name: " << ret.name.str(); throw model_parser::parse_error(os.str()); } } return ret; } void model_parser::check() { cout << detail::get_formula_result_output_separator() << endl << "checking results" << endl << detail::get_formula_result_output_separator() << endl; results_type::const_iterator itr = m_formula_results.begin(), itr_end = m_formula_results.end(); for (; itr != itr_end; ++itr) { const string& name = itr->first; if (name.empty()) throw check_error("empty cell name"); const formula_result& res = itr->second; cout << name << ": " << res.str(m_context) << endl; formula_name_t name_type = mp_name_resolver->resolve(name, abs_address_t()); if (name_type.type != formula_name_t::cell_reference) { ostringstream os; os << "unrecognized cell address: " << name; throw std::runtime_error(os.str()); } abs_address_t addr = std::get(name_type.value).to_abs(abs_address_t()); cell_access ca = m_context.get_cell_access(addr); switch (ca.get_type()) { case celltype_t::formula: { formula_result res_cell = ca.get_formula_result(); if (res_cell != res) { ostringstream os; os << "unexpected result: (expected: " << res.str(m_context) << "; actual: " << res_cell.str(m_context) << ")"; throw check_error(os.str()); } break; } case celltype_t::numeric: { double actual_val = ca.get_numeric_value(); if (actual_val != res.get_value()) { ostringstream os; os << "unexpected numeric result: (expected: " << res.get_value() << "; actual: " << actual_val << ")"; throw check_error(os.str()); } break; } case celltype_t::boolean: { bool actual = ca.get_boolean_value(); bool expected = res.get_value() ? true : false; if (actual != expected) { ostringstream os; os << "unexpected boolean result: (expected: " << expected << "; actual: " << actual << ")"; throw check_error(os.str()); } break; } case celltype_t::string: { std::string_view actual = ca.get_string_value(); const std::string& s_expected = res.get_string(); if (actual != s_expected) { std::ostringstream os; os << "unexpected string result: (expected: '" << s_expected << "'; actual: '" << actual << "')"; throw check_error(os.str()); } break; } default: throw check_error("unhandled cell type."); } } } std::string model_parser::get_display_cell_string(const abs_address_t& pos) const { address_t pos_display(pos); pos_display.set_absolute(false); return mp_name_resolver->get_name(pos_display, abs_address_t(), m_print_sheet_name); } std::string model_parser::get_display_range_string(const abs_range_t& pos) const { range_t pos_display(pos); pos_display.first.set_absolute(false); pos_display.last.set_absolute(false); return mp_name_resolver->get_name(pos_display, abs_address_t(), m_print_sheet_name); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/src/ixion_formula_tokenizer.cpp0000664000175000017500000000753114122770261016607 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef IXION_FORMULA_PARSER_CPP #define IXION_FORMULA_PARSER_CPP #include #include #include #include #include "ixion/formula.hpp" #include "ixion/model_context.hpp" #include "ixion/formula_name_resolver.hpp" #include "ixion/config.hpp" using std::cout; using std::endl; std::vector parse_sheet_names(const std::string& s) { std::vector names; const char* p = s.data(); const char* p_end = p + s.size(); const char* p0 = nullptr; for (; p != p_end; ++p) { if (!p0) p0 = p; if (*p == ',') { size_t n = std::distance(p0, p); names.emplace_back(p0, n); p0 = nullptr; } } if (p0) { size_t n = std::distance(p0, p); names.emplace_back(p0, n); } return names; } void tokenize_formula(const std::string& formula, const std::string& sheets) { using namespace ixion; model_context cxt; for (const std::string& name : parse_sheet_names(sheets)) cxt.append_sheet(name); std::unique_ptr resolver = formula_name_resolver::get(formula_name_resolver_t::excel_a1, &cxt); config cfg = cxt.get_config(); cfg.sep_function_arg = ','; cxt.set_config(cfg); abs_address_t pos; formula_tokens_t tokens = parse_formula_string(cxt, pos, *resolver, formula); cout << "* original formula string: " << formula << endl; std::string normalized = print_formula_tokens(cxt, pos, *resolver, tokens); cout << "* normalized formula string: " << normalized << endl; cout << "* individual tokens:" << endl; for (const formula_tokens_t::value_type& tp : tokens) cout << " * " << *tp << endl; } int main (int argc, char** argv) { namespace po = ::boost::program_options; po::options_description desc("Allowed options"); desc.add_options() ("help,h", "print this help.") ("sheets", po::value(), "Sheet names."); po::options_description hidden("Hidden options"); hidden.add_options() ("formula-expression", po::value(), "formula expression"); po::options_description cmd_opt; cmd_opt.add(desc).add(hidden); po::positional_options_description po_desc; po_desc.add("formula-expression", -1); po::variables_map vm; try { po::store( po::command_line_parser(argc, argv).options(cmd_opt).positional(po_desc).run(), vm); po::notify(vm); } catch (const std::exception& e) { // Unknown options. cout << e.what() << endl; cout << desc; return EXIT_FAILURE; } auto print_help = [desc]() { cout << "Usage: ixion-formula-tokenizer [options] FORMULA_EXPRESSION" << endl << endl << desc; }; if (vm.count("help")) { print_help(); return EXIT_SUCCESS; } if (!vm.count("formula-expression")) { cout << "formula expression is not given." << endl; print_help(); return EXIT_FAILURE; } try { std::string formula = vm["formula-expression"].as(); std::string sheets = vm.count("sheets") ? vm["sheets"].as() : std::string(); tokenize_formula(formula, sheets); } catch (const std::exception& e) { cout << "Failed to parse formula expression: " << e.what() << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/aclocal.m40000664000175000017500000016770014136644550012222 00000000000000# generated automatically by aclocal 1.16.1 -*- Autoconf -*- # Copyright (C) 1996-2018 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- dnl serial 11 (pkg-config-0.29.1) dnl dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.1]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR # Copyright (C) 2002-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.16.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.16.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. Try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking is enabled. # This creates each '.Po' and '.Plo' makefile fragment that we'll need in # order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # --------------------------------------------------------------------------- # Adds support for distributing Python modules and packages. To # install modules, copy them to $(pythondir), using the python_PYTHON # automake variable. To install a package with the same name as the # automake package, install to $(pkgpythondir), or use the # pkgpython_PYTHON automake variable. # # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as # locations to install python extension modules (shared libraries). # Another macro is required to find the appropriate flags to compile # extension modules. # # If your package is configured with a different prefix to python, # users will have to add the install directory to the PYTHONPATH # environment variable, or create a .pth file (see the python # documentation for details). # # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will # cause an error if the version of python installed on the system # doesn't meet the requirement. MINIMUM-VERSION should consist of # numbers and dots only. AC_DEFUN([AM_PATH_PYTHON], [ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). m4_define_default([_AM_PYTHON_INTERPRETER_LIST], [python python2 python3 dnl python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl python3.2 python3.1 python3.0 dnl python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) m4_if([$1],[],[ dnl No version check is needed. # Find any Python interpreter. if test -z "$PYTHON"; then AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) fi am_display_PYTHON=python ], [ dnl A version check is needed. if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. AC_MSG_CHECKING([whether $PYTHON version is >= $1]) AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Python interpreter is too old])]) am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. AC_CACHE_CHECK([for a Python interpreter with version >= $1], [am_cv_pathless_PYTHON],[ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do test "$am_cv_pathless_PYTHON" = none && break AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) done]) # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) fi am_display_PYTHON=$am_cv_pathless_PYTHON fi ]) if test "$PYTHON" = :; then dnl Run any user-specified action, or abort. m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) else dnl Query Python for its version number. Getting [:3] seems to be dnl the best way to do this; it's what "site.py" does in the standard dnl library. AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) dnl Use the values of $prefix and $exec_prefix for the corresponding dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made dnl distinct variables so they can be overridden if need be. However, dnl general consensus is that you shouldn't need this ability. AC_SUBST([PYTHON_PREFIX], ['${prefix}']) AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) dnl At times (like when building shared libraries) you may want dnl to know which OS platform Python thinks this is. AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': can_use_sysconfig = 0 except ImportError: pass" dnl Set up 4 directories: dnl pythondir -- where to install python scripts. This is the dnl site-packages directory, not the python standard library dnl directory like in previous automake betas. This behavior dnl is more consistent with lispdir.m4 for example. dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON script directory], [am_cv_python_pythondir], [if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pythondir], [$am_cv_python_pythondir]) dnl pkgpythondir -- $PACKAGE directory under pythondir. Was dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is dnl more consistent with the rest of automake. AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) dnl pyexecdir -- directory for installing python extension modules dnl (shared libraries) dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], [am_cv_python_pyexecdir], [if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) dnl Run any user-specified action. $2 fi ]) # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # --------------------------------------------------------------------------- # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. # Run ACTION-IF-FALSE otherwise. # This test uses sys.hexversion instead of the string equivalent (first # word of sys.version), in order to cope with versions such as 2.2c1. # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). AC_DEFUN([AM_PYTHON_CHECK_VERSION], [prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/ax_cxx_compile_stdcxx.m4]) m4_include([m4/ax_cxx_compile_stdcxx_17.m4]) m4_include([m4/boost.m4]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) libixion-0.17.0/m4/0000775000175000017500000000000014136644732010751 500000000000000libixion-0.17.0/m4/boost.m40000644000175000017500000015532713273351726012273 00000000000000# boost.m4: Locate Boost headers and libraries for autoconf-based projects. # Copyright (C) 2007-2011, 2014 Benoit Sigoure # # 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 3 of the License, or # (at your option) any later version. # # Additional permission under section 7 of the GNU General Public # License, version 3 ("GPLv3"): # # If you convey this file as part of a work that contains a # configuration script generated by Autoconf, you may do so under # terms of your choice. # # 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 . m4_define([_BOOST_SERIAL], [m4_translit([ # serial 26 ], [# ], [])]) # Original sources can be found at http://github.com/tsuna/boost.m4 # You can fetch the latest version of the script by doing: # wget http://github.com/tsuna/boost.m4/raw/master/build-aux/boost.m4 # ------ # # README # # ------ # # This file provides several macros to use the various Boost libraries. # The first macro is BOOST_REQUIRE. It will simply check if it's possible to # find the Boost headers of a given (optional) minimum version and it will # define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to # your configure so that users can specify non standard locations. # If the user's environment contains BOOST_ROOT and --with-boost was not # specified, --with-boost=$BOOST_ROOT is implicitly used. # For more README and documentation, go to http://github.com/tsuna/boost.m4 # Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry, # simply read the README, it will show you what to do step by step. m4_pattern_forbid([^_?(BOOST|Boost)_]) # _BOOST_SED_CPP(SED-PROGRAM, PROGRAM, # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # -------------------------------------------------------- # Same as AC_EGREP_CPP, but leave the result in conftest.i. # # SED-PROGRAM is *not* overquoted, as in AC_EGREP_CPP. It is expanded # in double-quotes, so escape your double quotes. # # It could be useful to turn this into a macro which extracts the # value of any macro. m4_define([_BOOST_SED_CPP], [AC_LANG_PUSH([C++])dnl AC_LANG_PREPROC_REQUIRE()dnl AC_REQUIRE([AC_PROG_SED])dnl AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])]) AS_IF([dnl eval is necessary to expand ac_cpp. dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell. dnl Beware of Windows end-of-lines, for instance if we are running dnl some Windows programs under Wine. In that case, boost/version.hpp dnl is certainly using "\r\n", but the regular Unix shell will only dnl strip `\n' with backquotes, not the `\r'. This results in dnl boost_cv_lib_version='1_37\r' for instance, which breaks dnl everything else. dnl Cannot use 'dnl' after [$4] because a trailing dnl may break AC_CACHE_CHECK dnl dnl Beware that GCC 5, when expanding macros, may embed # line directives dnl a within single line: dnl dnl # 1 "conftest.cc" dnl # 1 "" dnl # 1 "" dnl # 1 "conftest.cc" dnl # 1 "/opt/local/include/boost/version.hpp" 1 3 dnl # 2 "conftest.cc" 2 dnl boost-lib-version = dnl # 2 "conftest.cc" 3 dnl "1_56" dnl dnl So get rid of the # and empty lines, and glue the remaining ones together. (eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | grep -v '#' | grep -v '^[[[:space:]]]*$' | tr -d '\r' | tr -s '\n' ' ' | $SED -n -e "$1" >conftest.i 2>&1], [$3], [$4]) rm -rf conftest* AC_LANG_POP([C++])dnl ])# _BOOST_SED_CPP # BOOST_REQUIRE([VERSION], [ACTION-IF-NOT-FOUND]) # ----------------------------------------------- # Look for Boost. If version is given, it must either be a literal of the form # "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a # variable "$var". # Defines the value BOOST_CPPFLAGS. This macro only checks for headers with # the required version, it does not check for any of the Boost libraries. # On # success, defines HAVE_BOOST. On failure, calls the optional # ACTION-IF-NOT-FOUND action if one was supplied. # Otherwise aborts with an error message. AC_DEFUN_ONCE([BOOST_REQUIRE], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_PROG_GREP])dnl echo "$as_me: this is boost.m4[]_BOOST_SERIAL" >&AS_MESSAGE_LOG_FD boost_save_IFS=$IFS boost_version_req=$1 IFS=. set x $boost_version_req 0 0 0 IFS=$boost_save_IFS shift boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"` boost_version_req_string=$[1].$[2].$[3] AC_ARG_WITH([boost], [AS_HELP_STRING([--with-boost=DIR], [prefix of Boost $1 @<:@guess@:>@])])dnl AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl # If BOOST_ROOT is set and the user has not provided a value to # --with-boost, then treat BOOST_ROOT as if it the user supplied it. if test x"$BOOST_ROOT" != x; then if test x"$with_boost" = x; then AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT]) with_boost=$BOOST_ROOT else AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost]) fi fi AC_SUBST([DISTCHECK_CONFIGURE_FLAGS], ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])dnl boost_save_CPPFLAGS=$CPPFLAGS AC_CACHE_CHECK([for Boost headers version >= $boost_version_req_string], [boost_cv_inc_path], [boost_cv_inc_path=no AC_LANG_PUSH([C++])dnl m4_pattern_allow([^BOOST_VERSION$])dnl AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include #if !defined BOOST_VERSION # error BOOST_VERSION is not defined #elif BOOST_VERSION < $boost_version_req # error Boost headers version < $boost_version_req #endif ]])]) # If the user provided a value to --with-boost, use it and only it. case $with_boost in #( ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \ /usr/include C:/Boost/include;; #( *) set x "$with_boost/include" "$with_boost";; esac shift for boost_dir do # Without --layout=system, Boost (or at least some versions) installs # itself in /include/boost-. This inner loop helps to # find headers in such directories. # # Any ${boost_dir}/boost-x_xx directories are searched in reverse version # order followed by ${boost_dir}. The final '.' is a sentinel for # searching $boost_dir" itself. Entries are whitespace separated. # # I didn't indent this loop on purpose (to avoid over-indented code) boost_layout_system_search_list=`cd "$boost_dir" 2>/dev/null \ && ls -1 | "${GREP}" '^boost-' | sort -rn -t- -k2 \ && echo .` for boost_inc in $boost_layout_system_search_list do if test x"$boost_inc" != x.; then boost_inc="$boost_dir/$boost_inc" else boost_inc="$boost_dir" # Uses sentinel in boost_layout_system_search_list fi if test x"$boost_inc" != x; then # We are going to check whether the version of Boost installed # in $boost_inc is usable by running a compilation that # #includes it. But if we pass a -I/some/path in which Boost # is not installed, the compiler will just skip this -I and # use other locations (either from CPPFLAGS, or from its list # of system include directories). As a result we would use # header installed on the machine instead of the /some/path # specified by the user. So in that precise case (trying # $boost_inc), make sure the version.hpp exists. # # Use test -e as there can be symlinks. test -e "$boost_inc/boost/version.hpp" || continue CPPFLAGS="$CPPFLAGS -I$boost_inc" fi AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no]) if test x"$boost_cv_inc_path" = xyes; then if test x"$boost_inc" != x; then boost_cv_inc_path=$boost_inc fi break 2 fi done done AC_LANG_POP([C++])dnl ]) case $boost_cv_inc_path in #( no) boost_errmsg="cannot find Boost headers version >= $boost_version_req_string" m4_if([$2], [], [AC_MSG_ERROR([$boost_errmsg])], [AC_MSG_NOTICE([$boost_errmsg])]) $2 ;;#( yes) BOOST_CPPFLAGS= ;;#( *) AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"])dnl ;; esac if test x"$boost_cv_inc_path" != xno; then AC_DEFINE([HAVE_BOOST], [1], [Defined if the requested minimum BOOST version is satisfied]) AC_CACHE_CHECK([for Boost's header version], [boost_cv_lib_version], [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl _BOOST_SED_CPP([[/^boost-lib-version = /{s///;s/[\" ]//g;p;q;}]], [#include boost-lib-version = BOOST_LIB_VERSION], [boost_cv_lib_version=`cat conftest.i`])]) # e.g. "134" for 1_34_1 or "135" for 1_35 boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'` case $boost_major_version in #( '' | *[[!0-9]]*) AC_MSG_ERROR([invalid value: boost_major_version='$boost_major_version']) ;; esac fi CPPFLAGS=$boost_save_CPPFLAGS ])# BOOST_REQUIRE # BOOST_STATIC() # -------------- # Add the "--enable-static-boost" configure argument. If this argument is given # on the command line, static versions of the libraries will be looked up. AC_DEFUN([BOOST_STATIC], [AC_ARG_ENABLE([static-boost], [AS_HELP_STRING([--enable-static-boost], [Prefer the static boost libraries over the shared ones [no]])], [enable_static_boost=yes], [enable_static_boost=no])])# BOOST_STATIC # BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND]) # -------------------------------------------------------------------------- # Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for # some parts of the Boost library which are only made of headers and don't # require linking (such as Boost.Foreach). # # Default ACTION-IF-NOT-FOUND: Fail with a fatal error unless Boost couldn't be # found in the first place, in which case by default a notice is issued to the # user. Presumably if we haven't died already it's because it's OK to not have # Boost, which is why only a notice is issued instead of a hard error. # # Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_ in # case of success # (where HEADER-NAME is written LIKE_THIS, e.g., # HAVE_BOOST_FOREACH_HPP). AC_DEFUN([BOOST_FIND_HEADER], [AC_REQUIRE([BOOST_REQUIRE])dnl if test x"$boost_cv_inc_path" = xno; then m4_default([$2], [AC_MSG_NOTICE([Boost not available, not searching for $1])]) else AC_LANG_PUSH([C++])dnl boost_save_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_CHECK_HEADER([$1], [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], [Define to 1 if you have <$1>])])], [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])]) CPPFLAGS=$boost_save_CPPFLAGS AC_LANG_POP([C++])dnl fi ])# BOOST_FIND_HEADER # BOOST_FIND_LIBS([COMPONENT-NAME], [CANDIDATE-LIB-NAMES], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE]) # -------------------------------------------------------------- # Look for the Boost library COMPONENT-NAME (e.g., `thread', for # libboost_thread) under the possible CANDIDATE-LIB-NAMES (e.g., # "thread_win32 thread"). Check that HEADER-NAME works and check that # libboost_LIB-NAME can link with the code CXX-TEST. The optional # argument CXX-PROLOGUE can be used to include some C++ code before # the `main' function. # # Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above). # # Boost libraries typically come compiled with several flavors (with different # runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one # or more of the following letters: sgdpn (in that order). s = static # runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build, # n = (unsure) STLPort build without iostreams from STLPort (it looks like `n' # must always be used along with `p'). Additionally, PREFERRED-RT-OPT can # start with `mt-' to indicate that there is a preference for multi-thread # builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp # ... If you want to make sure you have a specific version of Boost # (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro. AC_DEFUN([BOOST_FIND_LIBS], [AC_REQUIRE([BOOST_REQUIRE])dnl AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl AC_REQUIRE([BOOST_STATIC])dnl AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl if test x"$boost_cv_inc_path" = xno; then AC_MSG_NOTICE([Boost not available, not searching for the Boost $1 library]) else dnl The else branch is huge and wasn't intended on purpose. AC_LANG_PUSH([C++])dnl AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl AS_VAR_PUSHDEF([Boost_lib_LDPATH], [boost_cv_lib_$1_LDPATH])dnl AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl BOOST_FIND_HEADER([$4]) boost_save_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib], [_BOOST_FIND_LIBS($@)]) case $Boost_lib in #( (no) _AC_MSG_LOG_CONFTEST AC_MSG_ERROR([cannot find the flags to link with Boost $1]) ;; esac AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])dnl AC_SUBST(AS_TR_CPP([BOOST_$1_LDPATH]), [$Boost_lib_LDPATH])dnl AC_SUBST([BOOST_LDPATH], [$Boost_lib_LDPATH])dnl AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])dnl CPPFLAGS=$boost_save_CPPFLAGS AS_VAR_POPDEF([Boost_lib])dnl AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl AS_VAR_POPDEF([Boost_lib_LDPATH])dnl AS_VAR_POPDEF([Boost_lib_LIBS])dnl AC_LANG_POP([C++])dnl fi ]) # BOOST_FIND_LIB([LIB-NAME], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE]) # -------------------------------------------------------------- # Backward compatibility wrapper for BOOST_FIND_LIBS. AC_DEFUN([BOOST_FIND_LIB], [BOOST_FIND_LIBS([$1], $@)]) # _BOOST_FIND_LIBS([LIB-NAME], [CANDIDATE-LIB-NAMES], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE]) # -------------------------------------------------------------- # Real implementation of BOOST_FIND_LIBS: rely on these local macros: # Boost_lib, Boost_lib_LDFLAGS, Boost_lib_LDPATH, Boost_lib_LIBS # # The algorithm is as follows: first look for a given library name # according to the user's PREFERRED-RT-OPT. For each library name, we # prefer to use the ones that carry the tag (toolset name). Each # library is searched through the various standard paths were Boost is # usually installed. If we can't find the standard variants, we try # to enforce -mt (for instance on MacOSX, libboost_thread.dylib # doesn't exist but there's -obviously- libboost_thread-mt.dylib). AC_DEFUN([_BOOST_FIND_LIBS], [Boost_lib=no case "$3" in #( (mt | mt-) boost_mt=-mt; boost_rtopt=;; #( (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$3" : 'Xmt-*\(.*\)'`;; #( (*) boost_mt=; boost_rtopt=$3;; esac if test $enable_static_boost = yes; then boost_rtopt="s$boost_rtopt" fi # Find the proper debug variant depending on what we've been asked to find. case $boost_rtopt in #( (*d*) boost_rt_d=$boost_rtopt;; #( (*[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn') boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( (*) boost_rt_d='-d';; esac # If the PREFERRED-RT-OPT are not empty, prepend a `-'. test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" $boost_guess_use_mt && boost_mt=-mt # Look for the abs path the static archive. # $libext is computed by Libtool but let's make sure it's non empty. test -z "$libext" && AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?]) boost_save_ac_objext=$ac_objext # Generate the test file. AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$4> $6], [$5])]) dnl Optimization hacks: compiling C++ is slow, especially with Boost. What dnl we're trying to do here is guess the right combination of link flags dnl (LIBS / LDFLAGS) to use a given library. This can take several dnl iterations before it succeeds and is thus *very* slow. So what we do dnl instead is that we compile the code first (and thus get an object file, dnl typically conftest.o). Then we try various combinations of link flags dnl until we succeed to link conftest.o in an executable. The problem is dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always dnl remove all the temporary files including conftest.o. So the trick here dnl is to temporarily change the value of ac_objext so that conftest.o is dnl preserved accross tests. This is obviously fragile and I will burn in dnl hell for not respecting Autoconf's documented interfaces, but in the dnl mean time, it optimizes the macro by a factor of 5 to 30. dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left dnl empty because the test file is generated only once above (before we dnl start the for loops). AC_COMPILE_IFELSE([], [ac_objext=do_not_rm_me_plz], [AC_MSG_ERROR([cannot compile a test that uses Boost $1])]) ac_objext=$boost_save_ac_objext boost_failed_libs= # Don't bother to ident the following nested for loops, only the 2 # innermost ones matter. for boost_lib_ in $2; do for boost_tag_ in -$boost_cv_lib_tag ''; do for boost_ver_ in -$boost_cv_lib_version ''; do for boost_mt_ in $boost_mt -mt ''; do for boost_rtopt_ in $boost_rtopt '' -d; do for boost_lib in \ boost_$boost_lib_$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ boost_$boost_lib_$boost_tag_$boost_rtopt_$boost_ver_ \ boost_$boost_lib_$boost_tag_$boost_mt_$boost_ver_ \ boost_$boost_lib_$boost_tag_$boost_ver_ do # Avoid testing twice the same lib case $boost_failed_libs in #( (*@$boost_lib@*) continue;; esac # If with_boost is empty, we'll search in /lib first, which is not quite # right so instead we'll try to a location based on where the headers are. boost_tmp_lib=$with_boost test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} for boost_ldpath in "$boost_tmp_lib/lib" '' \ /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ "$with_boost" C:/Boost/lib /lib* do # Don't waste time with directories that don't exist. if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then continue fi boost_save_LDFLAGS=$LDFLAGS # Are we looking for a static library? case $boost_ldpath:$boost_rtopt_ in #( (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext" test -e "$Boost_lib_LIBS" || continue;; #( (*) # No: use -lboost_foo to find the shared library. Boost_lib_LIBS="-l$boost_lib";; esac boost_save_LIBS=$LIBS LIBS="$Boost_lib_LIBS $LIBS" test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" dnl First argument of AC_LINK_IFELSE left empty because the test file is dnl generated only once above (before we start the for loops). _BOOST_AC_LINK_IFELSE([], [Boost_lib=yes], [Boost_lib=no]) ac_objext=$boost_save_ac_objext LDFLAGS=$boost_save_LDFLAGS LIBS=$boost_save_LIBS if test x"$Boost_lib" = xyes; then # Check or used cached result of whether or not using -R or # -rpath makes sense. Some implementations of ld, such as for # Mac OSX, require -rpath but -R is the flag known to work on # other systems. https://github.com/tsuna/boost.m4/issues/19 AC_CACHE_VAL([boost_cv_rpath_link_ldflag], [case $boost_ldpath in '') # Nothing to do. boost_cv_rpath_link_ldflag= boost_rpath_link_ldflag_found=yes;; *) for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" LIBS="$boost_save_LIBS $Boost_lib_LIBS" _BOOST_AC_LINK_IFELSE([], [boost_rpath_link_ldflag_found=yes break], [boost_rpath_link_ldflag_found=no]) done ;; esac AS_IF([test "x$boost_rpath_link_ldflag_found" != "xyes"], [AC_MSG_ERROR([Unable to determine whether to use -R or -rpath])]) LDFLAGS=$boost_save_LDFLAGS LIBS=$boost_save_LIBS ]) test x"$boost_ldpath" != x && Boost_lib_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" Boost_lib_LDPATH="$boost_ldpath" break 7 else boost_failed_libs="$boost_failed_libs@$boost_lib@" fi done done done done done done done # boost_lib_ rm -f conftest.$ac_objext ]) # --------------------------------------- # # Checks for the various Boost libraries. # # --------------------------------------- # # List of boost libraries: http://www.boost.org/libs/libraries.htm # The page http://beta.boost.org/doc/libs is useful: it gives the first release # version of each library (among other things). # BOOST_DEFUN(LIBRARY, CODE) # -------------------------- # Define BOOST_ as a macro that runs CODE. # # Use indir to avoid the warning on underquoted macro name given to AC_DEFUN. m4_define([BOOST_DEFUN], [m4_indir([AC_DEFUN], m4_toupper([BOOST_$1]), [m4_pushdef([BOOST_Library], [$1])dnl $2 m4_popdef([BOOST_Library])dnl ]) ]) # BOOST_ARRAY() # ------------- # Look for Boost.Array BOOST_DEFUN([Array], [BOOST_FIND_HEADER([boost/array.hpp])]) # BOOST_ASIO() # ------------ # Look for Boost.Asio (new in Boost 1.35). BOOST_DEFUN([Asio], [AC_REQUIRE([BOOST_SYSTEM])dnl BOOST_FIND_HEADER([boost/asio.hpp])]) # BOOST_ASSIGN() # ------------- # Look for Boost.Assign BOOST_DEFUN([Assign], [BOOST_FIND_HEADER([boost/assign.hpp])]) # BOOST_BIND() # ------------ # Look for Boost.Bind. BOOST_DEFUN([Bind], [BOOST_FIND_HEADER([boost/bind.hpp])]) # BOOST_CHRONO() # -------------- # Look for Boost.Chrono. BOOST_DEFUN([Chrono], [# Do we have to check for Boost.System? This link-time dependency was # added as of 1.35.0. If we have a version <1.35, we must not attempt to # find Boost.System as it didn't exist by then. if test $boost_major_version -ge 135; then BOOST_SYSTEM([$1]) fi # end of the Boost.System check. boost_filesystem_save_LIBS=$LIBS boost_filesystem_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" BOOST_FIND_LIB([chrono], [$1], [boost/chrono.hpp], [boost::chrono::thread_clock d;]) if test $enable_static_boost = yes && test $boost_major_version -ge 135; then BOOST_CHRONO_LIBS="$BOOST_CHRONO_LIBS $BOOST_SYSTEM_LIBS" fi LIBS=$boost_filesystem_save_LIBS LDFLAGS=$boost_filesystem_save_LDFLAGS ])# BOOST_CHRONO # BOOST_CONTEXT([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Context. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. # # * This library was introduced in Boost 1.51.0 # * The signatures of make_fcontext() and jump_fcontext were changed in 1.56.0 # * A dependency on boost_thread appears in 1.57.0 BOOST_DEFUN([Context], [boost_context_save_LIBS=$LIBS boost_context_save_LDFLAGS=$LDFLAGS if test $boost_major_version -ge 157; then BOOST_THREAD([$1]) m4_pattern_allow([^BOOST_THREAD_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_THREAD_LIBS" LDFLAGS="$LDFLAGS $BOOST_THREAD_LDFLAGS" fi BOOST_FIND_LIB([context], [$1], [boost/context/all.hpp],[[ // creates a stack void * stack_pointer = new void*[4096]; std::size_t const size = sizeof(void*[4096]); #if BOOST_VERSION <= 105100 ctx::make_fcontext(&fc, f); return ctx::jump_fcontext(&fcm, &fc, 3) == 6; #else fc = ctx::make_fcontext(stack_pointer, size, f); return ctx::jump_fcontext(&fcm, fc, 3) == 6; #endif ]],[dnl #include #if BOOST_VERSION <= 105100 namespace ctx = boost::ctx; static ctx::fcontext_t fcm, fc; static void f(intptr_t i) { ctx::jump_fcontext(&fc, &fcm, i * 2); } #elif BOOST_VERSION <= 105500 namespace ctx = boost::context; // context static ctx::fcontext_t fcm, *fc; // context-function static void f(intptr_t i) { ctx::jump_fcontext(fc, &fcm, i * 2); } #else namespace ctx = boost::context; // context static ctx::fcontext_t fcm, fc; // context-function static void f(intptr_t i) { ctx::jump_fcontext(&fc, fcm, i * 2); } #endif ]) LIBS=$boost_context_save_LIBS LDFLAGS=$boost_context_save_LDFLAGS ])# BOOST_CONTEXT # BOOST_CONVERSION() # ------------------ # Look for Boost.Conversion (cast / lexical_cast) BOOST_DEFUN([Conversion], [BOOST_FIND_HEADER([boost/cast.hpp]) BOOST_FIND_HEADER([boost/lexical_cast.hpp]) ])# BOOST_CONVERSION # BOOST_COROUTINE([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Coroutine. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. This library was introduced in Boost # 1.53.0 BOOST_DEFUN([Coroutine], [ boost_coroutine_save_LIBS=$LIBS boost_coroutine_save_LDFLAGS=$LDFLAGS # Link-time dependency from coroutine to context BOOST_CONTEXT([$1]) # Starting from Boost 1.55 a dependency on Boost.System is added if test $boost_major_version -ge 155; then BOOST_SYSTEM([$1]) fi m4_pattern_allow([^BOOST_(CONTEXT|SYSTEM)_(LIBS|LDFLAGS)]) LIBS="$LIBS $BOOST_CONTEXT_LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_CONTEXT_LDFLAGS" # in 1.53 coroutine was a header only library if test $boost_major_version -eq 153; then BOOST_FIND_HEADER([boost/coroutine/coroutine.hpp]) else BOOST_FIND_LIB([coroutine], [$1], [boost/coroutine/coroutine.hpp], [ #include #if BOOST_VERSION <= 105500 boost::coroutines::coroutine coro; coro.get(); #else boost::coroutines::asymmetric_coroutine::pull_type coro; coro.get(); #endif ]) fi # Link-time dependency from coroutine to context, existed only in 1.53, in 1.54 # coroutine doesn't use context from its headers but from its library. if test $boost_major_version -eq 153 || test $enable_static_boost = yes && test $boost_major_version -ge 154; then BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_CONTEXT_LIBS" BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_CONTEXT_LDFLAGS" fi if test $enable_static_boost = yes && test $boost_major_version -ge 155; then BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_SYSTEM_LIBS" BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_SYSTEM_LDFLAGS" fi LIBS=$boost_coroutine_save_LIBS LDFLAGS=$boost_coroutine_save_LDFLAGS ])# BOOST_COROUTINE # BOOST_CRC() # ----------- # Look for Boost.CRC BOOST_DEFUN([CRC], [BOOST_FIND_HEADER([boost/crc.hpp]) ])# BOOST_CRC # BOOST_DATE_TIME([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Date_Time], [BOOST_FIND_LIB([date_time], [$1], [boost/date_time/posix_time/posix_time.hpp], [boost::posix_time::ptime t;]) ])# BOOST_DATE_TIME # BOOST_FILESYSTEM([PREFERRED-RT-OPT]) # ------------------------------------ # Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see # the documentation of BOOST_FIND_LIB above. # Do not check for boost/filesystem.hpp because this file was introduced in # 1.34. BOOST_DEFUN([Filesystem], [# Do we have to check for Boost.System? This link-time dependency was # added as of 1.35.0. If we have a version <1.35, we must not attempt to # find Boost.System as it didn't exist by then. if test $boost_major_version -ge 135; then BOOST_SYSTEM([$1]) fi # end of the Boost.System check. boost_filesystem_save_LIBS=$LIBS boost_filesystem_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" BOOST_FIND_LIB([filesystem], [$1], [boost/filesystem/path.hpp], [boost::filesystem::path p;]) if test $enable_static_boost = yes && test $boost_major_version -ge 135; then BOOST_FILESYSTEM_LIBS="$BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS" fi LIBS=$boost_filesystem_save_LIBS LDFLAGS=$boost_filesystem_save_LDFLAGS ])# BOOST_FILESYSTEM # BOOST_FLYWEIGHT() # ----------------- # Look for Boost.Flyweight. BOOST_DEFUN([Flyweight], [dnl There's a hidden dependency on pthreads. AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl BOOST_FIND_HEADER([boost/flyweight.hpp]) AC_SUBST([BOOST_FLYWEIGHT_LIBS], [$boost_cv_pthread_flag]) ]) # BOOST_FOREACH() # --------------- # Look for Boost.Foreach. BOOST_DEFUN([Foreach], [BOOST_FIND_HEADER([boost/foreach.hpp])]) # BOOST_FORMAT() # -------------- # Look for Boost.Format. # Note: we can't check for boost/format/format_fwd.hpp because the header isn't # standalone. It can't be compiled because it triggers the following error: # boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std' # does not name a type BOOST_DEFUN([Format], [BOOST_FIND_HEADER([boost/format.hpp])]) # BOOST_FUNCTION() # ---------------- # Look for Boost.Function BOOST_DEFUN([Function], [BOOST_FIND_HEADER([boost/function.hpp])]) # BOOST_GEOMETRY() # ---------------- # Look for Boost.Geometry (new since 1.47.0). BOOST_DEFUN([Geometry], [BOOST_FIND_HEADER([boost/geometry.hpp]) ])# BOOST_GEOMETRY # BOOST_GRAPH([PREFERRED-RT-OPT]) # ------------------------------- # Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Graph], [boost_graph_save_LIBS=$LIBS boost_graph_save_LDFLAGS=$LDFLAGS # Link-time dependency from graph to regex was added as of 1.40.0. if test $boost_major_version -ge 140; then BOOST_REGEX([$1]) m4_pattern_allow([^BOOST_REGEX_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_REGEX_LIBS" LDFLAGS="$LDFLAGS $BOOST_REGEX_LDFLAGS" fi BOOST_FIND_LIB([graph], [$1], [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;]) LIBS=$boost_graph_save_LIBS LDFLAGS=$boost_graph_save_LDFLAGS ])# BOOST_GRAPH # BOOST_IOSTREAMS([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([IOStreams], [BOOST_FIND_LIB([iostreams], [$1], [boost/iostreams/device/file_descriptor.hpp], [boost::iostreams::file_descriptor fd; fd.close();]) ])# BOOST_IOSTREAMS # BOOST_HASH() # ------------ # Look for Boost.Functional/Hash BOOST_DEFUN([Hash], [BOOST_FIND_HEADER([boost/functional/hash.hpp])]) # BOOST_LAMBDA() # -------------- # Look for Boost.Lambda BOOST_DEFUN([Lambda], [BOOST_FIND_HEADER([boost/lambda/lambda.hpp])]) # BOOST_LOCALE() # -------------- # Look for Boost.Locale BOOST_DEFUN([Locale], [ boost_locale_save_LIBS=$LIBS boost_locale_save_LDFLAGS=$LDFLAGS # require SYSTEM for boost-1.50.0 and up if test $boost_major_version -ge 150; then BOOST_SYSTEM([$1]) m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" fi # end of the Boost.System check. BOOST_FIND_LIB([locale], [$1], [boost/locale.hpp], [[boost::locale::generator gen; std::locale::global(gen(""));]]) LIBS=$boost_locale_save_LIBS LDFLAGS=$boost_locale_save_LDFLAGS ])# BOOST_LOCALE # BOOST_LOG([PREFERRED-RT-OPT]) # ----------------------------- # Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Log], [boost_log_save_LIBS=$LIBS boost_log_save_LDFLAGS=$LDFLAGS BOOST_SYSTEM([$1]) BOOST_FILESYSTEM([$1]) BOOST_DATE_TIME([$1]) m4_pattern_allow([^BOOST_(SYSTEM|FILESYSTEM|DATE_TIME)_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_DATE_TIME_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_DATE_TIME_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS $BOOST_SYSTEM_LDFLAGS" BOOST_FIND_LIB([log], [$1], [boost/log/core/core.hpp], [boost::log::attribute a; a.get_value();]) LIBS=$boost_log_save_LIBS LDFLAGS=$boost_log_save_LDFLAGS ])# BOOST_LOG # BOOST_LOG_SETUP([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Log_Setup], [boost_log_setup_save_LIBS=$LIBS boost_log_setup_save_LDFLAGS=$LDFLAGS BOOST_LOG([$1]) m4_pattern_allow([^BOOST_LOG_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_LOG_LIBS" LDFLAGS="$LDFLAGS $BOOST_LOG_LDFLAGS" BOOST_FIND_LIB([log_setup], [$1], [boost/log/utility/setup/from_settings.hpp], [boost::log::basic_settings bs; bs.empty();]) LIBS=$boost_log_setup_save_LIBS LDFLAGS=$boost_log_setup_save_LDFLAGS ])# BOOST_LOG_SETUP # BOOST_MATH() # ------------ # Look for Boost.Math # TODO: This library isn't header-only but it comes in multiple different # flavors that don't play well with BOOST_FIND_LIB (e.g, libboost_math_c99, # libboost_math_c99f, libboost_math_c99l, libboost_math_tr1, # libboost_math_tr1f, libboost_math_tr1l). This macro must be fixed to do the # right thing anyway. BOOST_DEFUN([Math], [BOOST_FIND_HEADER([boost/math/special_functions.hpp])]) # BOOST_MPI([PREFERRED-RT-OPT]) # ------------------------------- # Look for Boost MPI. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. Uses MPICXX variable if it is # set, otherwise tries CXX # BOOST_DEFUN([MPI], [boost_save_CXX=${CXX} boost_save_CXXCPP=${CXXCPP} if test x"${MPICXX}" != x; then CXX=${MPICXX} CXXCPP="${MPICXX} -E" fi BOOST_FIND_LIB([mpi], [$1], [boost/mpi.hpp], [int argc = 0; char **argv = 0; boost::mpi::environment env(argc,argv);]) CXX=${boost_save_CXX} CXXCPP=${boost_save_CXXCPP} ])# BOOST_MPI # BOOST_MULTIARRAY() # ------------------ # Look for Boost.MultiArray BOOST_DEFUN([MultiArray], [BOOST_FIND_HEADER([boost/multi_array.hpp])]) # BOOST_NUMERIC_UBLAS() # -------------------------- # Look for Boost.NumericUblas (Basic Linear Algebra) BOOST_DEFUN([Numeric_Ublas], [BOOST_FIND_HEADER([boost/numeric/ublas/vector.hpp]) ])# BOOST_NUMERIC_UBLAS # BOOST_NUMERIC_CONVERSION() # -------------------------- # Look for Boost.NumericConversion (policy-based numeric conversion) BOOST_DEFUN([Numeric_Conversion], [BOOST_FIND_HEADER([boost/numeric/conversion/converter.hpp]) ])# BOOST_NUMERIC_CONVERSION # BOOST_OPTIONAL() # ---------------- # Look for Boost.Optional BOOST_DEFUN([Optional], [BOOST_FIND_HEADER([boost/optional.hpp])]) # BOOST_PREPROCESSOR() # -------------------- # Look for Boost.Preprocessor BOOST_DEFUN([Preprocessor], [BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])]) # BOOST_RANGE() # -------------------- # Look for Boost.Range BOOST_DEFUN([Range], [BOOST_FIND_HEADER([boost/range/adaptors.hpp])]) # BOOST_UNORDERED() # ----------------- # Look for Boost.Unordered BOOST_DEFUN([Unordered], [BOOST_FIND_HEADER([boost/unordered_map.hpp])]) # BOOST_UUID() # ------------ # Look for Boost.Uuid BOOST_DEFUN([Uuid], [BOOST_FIND_HEADER([boost/uuid/uuid.hpp])]) # BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT]) # ----------------------------------------- # Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT, # see the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Program_Options], [BOOST_FIND_LIB([program_options], [$1], [boost/program_options.hpp], [boost::program_options::options_description d("test");]) ])# BOOST_PROGRAM_OPTIONS # _BOOST_PYTHON_CONFIG(VARIABLE, FLAG) # ------------------------------------ # Save VARIABLE, and define it via `python-config --FLAG`. # Substitute BOOST_PYTHON_VARIABLE. m4_define([_BOOST_PYTHON_CONFIG], [AC_SUBST([BOOST_PYTHON_$1], [`python-config --$2 2>/dev/null`])dnl boost_python_save_$1=$$1 $1="$$1 $BOOST_PYTHON_$1"]) # BOOST_PYTHON([PREFERRED-RT-OPT]) # -------------------------------- # Look for Boost.Python. For the documentation of PREFERRED-RT-OPT, # see the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Python], [_BOOST_PYTHON_CONFIG([CPPFLAGS], [includes]) _BOOST_PYTHON_CONFIG([LDFLAGS], [ldflags]) _BOOST_PYTHON_CONFIG([LIBS], [libs]) m4_pattern_allow([^BOOST_PYTHON_MODULE$])dnl BOOST_FIND_LIBS([python], [python python3], [$1], [boost/python.hpp], [], [BOOST_PYTHON_MODULE(empty) {}]) CPPFLAGS=$boost_python_save_CPPFLAGS LDFLAGS=$boost_python_save_LDFLAGS LIBS=$boost_python_save_LIBS ])# BOOST_PYTHON # BOOST_REF() # ----------- # Look for Boost.Ref BOOST_DEFUN([Ref], [BOOST_FIND_HEADER([boost/ref.hpp])]) # BOOST_REGEX([PREFERRED-RT-OPT]) # ------------------------------- # Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Regex], [BOOST_FIND_LIB([regex], [$1], [boost/regex.hpp], [boost::regex exp("*"); boost::regex_match("foo", exp);]) ])# BOOST_REGEX # BOOST_SERIALIZATION([PREFERRED-RT-OPT]) # --------------------------------------- # Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see # the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Serialization], [BOOST_FIND_LIB([serialization], [$1], [boost/archive/text_oarchive.hpp], [std::ostream* o = 0; // Cheap way to get an ostream... boost::archive::text_oarchive t(*o);]) ])# BOOST_SERIALIZATION # BOOST_SIGNALS([PREFERRED-RT-OPT]) # --------------------------------- # Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Signals], [BOOST_FIND_LIB([signals], [$1], [boost/signal.hpp], [boost::signal s;]) ])# BOOST_SIGNALS # BOOST_SIGNALS2() # ---------------- # Look for Boost.Signals2 (new since 1.39.0). BOOST_DEFUN([Signals2], [BOOST_FIND_HEADER([boost/signals2.hpp]) ])# BOOST_SIGNALS2 # BOOST_SMART_PTR() # ----------------- # Look for Boost.SmartPtr BOOST_DEFUN([Smart_Ptr], [BOOST_FIND_HEADER([boost/scoped_ptr.hpp]) BOOST_FIND_HEADER([boost/shared_ptr.hpp]) ]) # BOOST_STATICASSERT() # -------------------- # Look for Boost.StaticAssert BOOST_DEFUN([StaticAssert], [BOOST_FIND_HEADER([boost/static_assert.hpp])]) # BOOST_STRING_ALGO() # ------------------- # Look for Boost.StringAlgo BOOST_DEFUN([String_Algo], [BOOST_FIND_HEADER([boost/algorithm/string.hpp]) ]) # BOOST_SYSTEM([PREFERRED-RT-OPT]) # -------------------------------- # Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. This library was introduced in Boost # 1.35.0. BOOST_DEFUN([System], [BOOST_FIND_LIB([system], [$1], [boost/system/error_code.hpp], [boost::system::error_code e; e.clear();]) ])# BOOST_SYSTEM # BOOST_TEST([PREFERRED-RT-OPT]) # ------------------------------ # Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Test], [m4_pattern_allow([^BOOST_CHECK$])dnl BOOST_FIND_LIB([unit_test_framework], [$1], [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);], [using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int argc, char ** argv) { return NULL; }]) ])# BOOST_TEST # BOOST_THREAD([PREFERRED-RT-OPT]) # --------------------------------- # Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Thread], [dnl Having the pthread flag is required at least on GCC3 where dnl boost/thread.hpp would complain if we try to compile without dnl -pthread on GNU/Linux. AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl boost_thread_save_LIBS=$LIBS boost_thread_save_LDFLAGS=$LDFLAGS boost_thread_save_CPPFLAGS=$CPPFLAGS # Link-time dependency from thread to system was added as of 1.49.0. if test $boost_major_version -ge 149; then BOOST_SYSTEM([$1]) fi # end of the Boost.System check. m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag" # When compiling for the Windows platform, the threads library is named # differently. This suffix doesn't exist in new versions of Boost, or # possibly new versions of GCC on mingw I am assuming it's Boost's change for # now and I am setting version to 1.48, for lack of knowledge as to when this # change occurred. if test $boost_major_version -lt 148; then case $host_os in (*mingw*) boost_thread_lib_ext=_win32;; esac fi BOOST_FIND_LIBS([thread], [thread$boost_thread_lib_ext], [$1], [boost/thread.hpp], [boost::thread t; boost::mutex m;]) case $host_os in (*mingw*) boost_thread_w32_socket_link=-lws2_32;; esac BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag $boost_thread_w32_socket_link" BOOST_THREAD_LDFLAGS="$BOOST_SYSTEM_LDFLAGS" BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag" LIBS=$boost_thread_save_LIBS LDFLAGS=$boost_thread_save_LDFLAGS CPPFLAGS=$boost_thread_save_CPPFLAGS ])# BOOST_THREAD AU_ALIAS([BOOST_THREADS], [BOOST_THREAD]) # BOOST_TOKENIZER() # ----------------- # Look for Boost.Tokenizer BOOST_DEFUN([Tokenizer], [BOOST_FIND_HEADER([boost/tokenizer.hpp])]) # BOOST_TRIBOOL() # --------------- # Look for Boost.Tribool BOOST_DEFUN([Tribool], [BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp]) BOOST_FIND_HEADER([boost/logic/tribool.hpp]) ]) # BOOST_TUPLE() # ------------- # Look for Boost.Tuple BOOST_DEFUN([Tuple], [BOOST_FIND_HEADER([boost/tuple/tuple.hpp])]) # BOOST_TYPETRAITS() # -------------------- # Look for Boost.TypeTraits BOOST_DEFUN([TypeTraits], [BOOST_FIND_HEADER([boost/type_traits.hpp])]) # BOOST_UTILITY() # --------------- # Look for Boost.Utility (noncopyable, result_of, base-from-member idiom, # etc.) BOOST_DEFUN([Utility], [BOOST_FIND_HEADER([boost/utility.hpp])]) # BOOST_VARIANT() # --------------- # Look for Boost.Variant. BOOST_DEFUN([Variant], [BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp]) BOOST_FIND_HEADER([boost/variant.hpp])]) # BOOST_POINTER_CONTAINER() # ------------------------ # Look for Boost.PointerContainer BOOST_DEFUN([Pointer_Container], [BOOST_FIND_HEADER([boost/ptr_container/ptr_deque.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_list.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_vector.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_array.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_set.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_map.hpp]) ])# BOOST_POINTER_CONTAINER # BOOST_WAVE([PREFERRED-RT-OPT]) # ------------------------------ # NOTE: If you intend to use Wave/Spirit with thread support, make sure you # call BOOST_THREAD first. # Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Wave], [AC_REQUIRE([BOOST_FILESYSTEM])dnl AC_REQUIRE([BOOST_DATE_TIME])dnl boost_wave_save_LIBS=$LIBS boost_wave_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS \ $BOOST_THREAD_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS \ $BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS" BOOST_FIND_LIB([wave], [$1], [boost/wave.hpp], [boost::wave::token_id id; get_token_name(id);]) LIBS=$boost_wave_save_LIBS LDFLAGS=$boost_wave_save_LDFLAGS ])# BOOST_WAVE # BOOST_XPRESSIVE() # ----------------- # Look for Boost.Xpressive (new since 1.36.0). BOOST_DEFUN([Xpressive], [BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])]) # ----------------- # # Internal helpers. # # ----------------- # # _BOOST_PTHREAD_FLAG() # --------------------- # Internal helper for BOOST_THREAD. Computes boost_cv_pthread_flag # which must be used in CPPFLAGS and LIBS. # # Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3, # boost/thread.hpp will trigger a #error if -pthread isn't used: # boost/config/requires_threads.hpp:47:5: #error "Compiler threading support # is not turned on. Please set the correct command line options for # threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" # # Based on ACX_PTHREAD: http://autoconf-archive.cryp.to/acx_pthread.html AC_DEFUN([_BOOST_PTHREAD_FLAG], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_LANG_PUSH([C++])dnl AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag], [ boost_cv_pthread_flag= # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # (none): in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -lpthreads: AIX (must check this before -lpthread) # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads) # -pthreads: Solaris/GCC # -mthreads: MinGW32/GCC, Lynx/GCC # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # -lpthread: GNU Linux, etc. # --thread-safe: KAI C++ case $host_os in #( *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #( *) boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \ -pthreads -mthreads -lpthread --thread-safe -mt";; esac # Generate the test file. AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0);])]) for boost_pthread_flag in '' $boost_pthread_flags; do boost_pthread_ok=false dnl Re-use the test file already generated. boost_pthreads__save_LIBS=$LIBS LIBS="$LIBS $boost_pthread_flag" AC_LINK_IFELSE([], [if grep ".*$boost_pthread_flag" conftest.err; then echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD else boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag fi]) LIBS=$boost_pthreads__save_LIBS $boost_pthread_ok && break done ]) AC_LANG_POP([C++])dnl ])# _BOOST_PTHREAD_FLAG # _BOOST_gcc_test(MAJOR, MINOR) # ----------------------------- # Internal helper for _BOOST_FIND_COMPILER_TAG. m4_define([_BOOST_gcc_test], ["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl # _BOOST_mingw_test(MAJOR, MINOR) # ----------------------------- # Internal helper for _BOOST_FIND_COMPILER_TAG. m4_define([_BOOST_mingw_test], ["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC && \ (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw$1$2"])dnl # _BOOST_FIND_COMPILER_TAG() # -------------------------- # Internal. When Boost is installed without --layout=system, each library # filename will hold a suffix that encodes the compiler used during the # build. The Boost build system seems to call this a `tag'. AC_DEFUN([_BOOST_FIND_COMPILER_TAG], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], [boost_cv_lib_tag], [boost_cv_lib_tag=unknown if test x$boost_cv_inc_path != xno; then AC_LANG_PUSH([C++])dnl # The following tests are mostly inspired by boost/config/auto_link.hpp # The list is sorted to most recent/common to oldest compiler (in order # to increase the likelihood of finding the right compiler with the # least number of compilation attempt). # Beware that some tests are sensible to the order (for instance, we must # look for MinGW before looking for GCC3). # I used one compilation test per compiler with a #error to recognize # each compiler so that it works even when cross-compiling (let me know # if you know a better approach). # Known missing tags (known from Boost's tools/build/v2/tools/common.jam): # como, edg, kcc, bck, mp, sw, tru, xlc # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines # the same defines as GCC's). for i in \ _BOOST_mingw_test(6, 3) \ _BOOST_gcc_test(6, 3) \ _BOOST_mingw_test(6, 2) \ _BOOST_gcc_test(6, 2) \ _BOOST_mingw_test(6, 1) \ _BOOST_gcc_test(6, 1) \ _BOOST_mingw_test(6, 0) \ _BOOST_gcc_test(6, 0) \ _BOOST_mingw_test(5, 4) \ _BOOST_gcc_test(5, 4) \ _BOOST_mingw_test(5, 3) \ _BOOST_gcc_test(5, 3) \ _BOOST_mingw_test(5, 2) \ _BOOST_gcc_test(5, 2) \ _BOOST_mingw_test(5, 1) \ _BOOST_gcc_test(5, 1) \ _BOOST_mingw_test(5, 0) \ _BOOST_gcc_test(5, 0) \ _BOOST_mingw_test(4, 10) \ _BOOST_gcc_test(4, 10) \ _BOOST_mingw_test(4, 9) \ _BOOST_gcc_test(4, 9) \ _BOOST_mingw_test(4, 8) \ _BOOST_gcc_test(4, 8) \ _BOOST_mingw_test(4, 7) \ _BOOST_gcc_test(4, 7) \ _BOOST_mingw_test(4, 6) \ _BOOST_gcc_test(4, 6) \ _BOOST_mingw_test(4, 5) \ _BOOST_gcc_test(4, 5) \ _BOOST_mingw_test(4, 4) \ _BOOST_gcc_test(4, 4) \ _BOOST_mingw_test(4, 3) \ _BOOST_gcc_test(4, 3) \ _BOOST_mingw_test(4, 2) \ _BOOST_gcc_test(4, 2) \ _BOOST_mingw_test(4, 1) \ _BOOST_gcc_test(4, 1) \ _BOOST_mingw_test(4, 0) \ _BOOST_gcc_test(4, 0) \ "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \ && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \ _BOOST_gcc_test(3, 4) \ _BOOST_gcc_test(3, 3) \ "defined _MSC_VER && _MSC_VER >= 1500 @ vc90" \ "defined _MSC_VER && _MSC_VER == 1400 @ vc80" \ _BOOST_gcc_test(3, 2) \ "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \ _BOOST_gcc_test(3, 1) \ _BOOST_gcc_test(3, 0) \ "defined __BORLANDC__ @ bcb" \ "defined __ICC && (defined __unix || defined __unix__) @ il" \ "defined __ICL @ iw" \ "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \ _BOOST_gcc_test(2, 95) \ "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \ "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \ "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \ "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8" do boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '` boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'` AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if $boost_tag_test /* OK */ #else # error $boost_tag_test #endif ]])], [boost_cv_lib_tag=$boost_tag; break], []) done AC_LANG_POP([C++])dnl case $boost_cv_lib_tag in #( # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed # to "gcc41" for instance. *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there. gcc*) boost_tag_x= case $host_os in #( darwin*) if test $boost_major_version -ge 136; then # The `x' added in r46793 of Boost. boost_tag_x=x fi;; esac # We can specify multiple tags in this variable because it's used by # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ... boost_cv_lib_tag="$boost_tag_x$boost_cv_lib_tag -${boost_tag_x}gcc" ;; #( unknown) AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]]) boost_cv_lib_tag= ;; esac fi])dnl end of AC_CACHE_CHECK ])# _BOOST_FIND_COMPILER_TAG # _BOOST_GUESS_WHETHER_TO_USE_MT() # -------------------------------- # Compile a small test to try to guess whether we should favor MT (Multi # Thread) flavors of Boost. Sets boost_guess_use_mt accordingly. AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT], [# Check whether we do better use `mt' even though we weren't ask to. AC_LANG_PUSH([C++])dnl AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if defined _REENTRANT || defined _MT || defined __MT__ /* use -mt */ #else # error MT not needed #endif ]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false]) AC_LANG_POP([C++])dnl ]) # _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # ------------------------------------------------------------------- # Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile, # will break when Autoconf changes its internals. Requires that you manually # rm -f conftest.$ac_objext in between to really different tests, otherwise # you will try to link a conftest.o left behind by a previous test. # Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this # macro). # # Don't use "break" in the actions, as it would short-circuit some code # this macro runs after the actions. m4_define([_BOOST_AC_LINK_IFELSE], [m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl rm -f conftest$ac_exeext boost_save_ac_ext=$ac_ext boost_use_source=: # If we already have a .o, re-use it. We change $ac_ext so that $ac_link # tries to link the existing object file instead of compiling from source. test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && _AS_ECHO_LOG([re-using the existing conftest.$ac_objext]) AS_IF([_AC_DO_STDERR($ac_link) && { test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_executable_p conftest$ac_exeext dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough. }], [$2], [if $boost_use_source; then _AC_MSG_LOG_CONFTEST fi $3]) ac_objext=$boost_save_ac_objext ac_ext=$boost_save_ac_ext dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization) dnl information created by the PGI compiler (conftest_ipa8_conftest.oo), dnl as it would interfere with the next link command. rm -f core conftest.err conftest_ipa8_conftest.oo \ conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl ])# _BOOST_AC_LINK_IFELSE # Local Variables: # mode: autoconf # End: libixion-0.17.0/m4/lt~obsolete.m40000644000175000017500000001377414123220334013477 00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) libixion-0.17.0/m4/libtool.m40000644000175000017500000112676314123220334012575 00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool 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 . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cr libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cr} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # flang / f18. f95 an alias for gfortran or flang on Debian flang* | f18* | f95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS libixion-0.17.0/m4/ltversion.m40000644000175000017500000000127314123220334013141 00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) libixion-0.17.0/m4/ax_cxx_compile_stdcxx_17.m40000664000175000017500000000260513735103452016035 00000000000000# ============================================================================= # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_17.html # ============================================================================= # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX_17([ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the C++17 # standard; if necessary, add switches to CXX and CXXCPP to enable # support. # # This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX # macro with the version set to C++17. The two optional arguments are # forwarded literally as the second and third argument respectively. # Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for # more information. If you want to use this macro, you also need to # download the ax_cxx_compile_stdcxx.m4 file. # # LICENSE # # Copyright (c) 2015 Moritz Klammler # Copyright (c) 2016 Krzesimir Nowak # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 2 AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) AC_DEFUN([AX_CXX_COMPILE_STDCXX_17], [AX_CXX_COMPILE_STDCXX([17], [$1], [$2])]) libixion-0.17.0/m4/ltoptions.m40000644000175000017500000003426214123220334013153 00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) libixion-0.17.0/m4/ltsugar.m40000644000175000017500000001044014123220334012571 00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) libixion-0.17.0/m4/ax_cxx_compile_stdcxx.m40000664000175000017500000004564713735104176015547 00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html # =========================================================================== # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and # CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) # or '14' (for the C++14 standard). # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for an extended mode. # # The third argument, if specified 'mandatory' or if left unspecified, # indicates that baseline support for the specified C++ standard is # required and that the macro should error out if no mode with that # support is found. If specified 'optional', then configuration proceeds # regardless, after defining HAVE_CXX${VERSION} if and only if a # supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov # Copyright (c) 2015 Paul Norman # Copyright (c) 2015 Moritz Klammler # Copyright (c) 2016, 2018 Krzesimir Nowak # Copyright (c) 2019 Enji Cooper # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 11 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], [$2], [noext], [], [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], [$3], [optional], [ax_cxx_compile_cxx$1_required=false], [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) AC_LANG_PUSH([C++])dnl ac_success=no m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi]) m4_if([$2], [ext], [], [dnl if test x$ac_success = xno; then dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done if test x$ac_success = xyes; then break fi done fi]) AC_LANG_POP([C++]) if test x$ax_cxx_compile_cxx$1_required = xtrue; then if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) fi fi if test x$ac_success = xno; then HAVE_CXX$1=0 AC_MSG_NOTICE([No compiler with C++$1 support was found]) else HAVE_CXX$1=1 AC_DEFINE(HAVE_CXX$1,1, [define if the compiler supports basic C++$1 syntax]) fi AC_SUBST(HAVE_CXX$1) ]) dnl Test body for checking C++11 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 ) dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201103L #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual ~Base() {} virtual void f() {} }; struct Derived : public Base { virtual ~Derived() override {} virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L ]]) dnl Tests for new features in C++14 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_separators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L ]]) dnl Tests for new features in C++17 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ // If the compiler admits that it is not ready for C++17, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201703L #error "This is not a C++17 compiler" #else #include #include #include namespace cxx17 { namespace test_constexpr_lambdas { constexpr int foo = [](){return 42;}(); } namespace test::nested_namespace::definitions { } namespace test_fold_expression { template int multiply(Args... args) { return (args * ... * 1); } template bool all(Args... args) { return (args && ...); } } namespace test_extended_static_assert { static_assert (true); } namespace test_auto_brace_init_list { auto foo = {5}; auto bar {5}; static_assert(std::is_same, decltype(foo)>::value); static_assert(std::is_same::value); } namespace test_typename_in_template_template_parameter { template typename X> struct D; } namespace test_fallthrough_nodiscard_maybe_unused_attributes { int f1() { return 42; } [[nodiscard]] int f2() { [[maybe_unused]] auto unused = f1(); switch (f1()) { case 17: f1(); [[fallthrough]]; case 42: f1(); } return f1(); } } namespace test_extended_aggregate_initialization { struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1 {{1, 2}, {}, 4}; // full initialization derived d2 {{}, {}, 4}; // value-initialized bases } namespace test_general_range_based_for_loop { struct iter { int i; int& operator* () { return i; } const int& operator* () const { return i; } iter& operator++() { ++i; return *this; } }; struct sentinel { int i; }; bool operator== (const iter& i, const sentinel& s) { return i.i == s.i; } bool operator!= (const iter& i, const sentinel& s) { return !(i == s); } struct range { iter begin() const { return {0}; } sentinel end() const { return {5}; } }; void f() { range r {}; for (auto i : r) { [[maybe_unused]] auto v = i; } } } namespace test_lambda_capture_asterisk_this_by_value { struct t { int i; int foo() { return [*this]() { return i; }(); } }; } namespace test_enum_class_construction { enum class byte : unsigned char {}; byte foo {42}; } namespace test_constexpr_if { template int f () { if constexpr(cond) { return 13; } else { return 42; } } } namespace test_selection_statement_with_initializer { int f() { return 13; } int f2() { if (auto i = f(); i > 0) { return 3; } switch (auto i = f(); i + 4) { case 17: return 2; default: return 1; } } } namespace test_template_argument_deduction_for_class_templates { template struct pair { pair (T1 p1, T2 p2) : m1 {p1}, m2 {p2} {} T1 m1; T2 m2; }; void f() { [[maybe_unused]] auto p = pair{13, 42u}; } } namespace test_non_type_auto_template_parameters { template struct B {}; B<5> b1; B<'a'> b2; } namespace test_structured_bindings { int arr[2] = { 1, 2 }; std::pair pr = { 1, 2 }; auto f1() -> int(&)[2] { return arr; } auto f2() -> std::pair& { return pr; } struct S { int x1 : 2; volatile double y1; }; S f3() { return {}; } auto [ x1, y1 ] = f1(); auto& [ xr1, yr1 ] = f1(); auto [ x2, y2 ] = f2(); auto& [ xr2, yr2 ] = f2(); const auto [ x3, y3 ] = f3(); } namespace test_exception_spec_type_system { struct Good {}; struct Bad {}; void g1() noexcept; void g2(); template Bad f(T*, T*); template Good f(T1*, T2*); static_assert (std::is_same_v); } namespace test_inline_variables { template void f(T) {} template inline T g(T) { return T{}; } template<> inline void f<>(int) {} template<> int g<>(int) { return 5; } } } // namespace cxx17 #endif // __cplusplus < 201703L ]]) libixion-0.17.0/LICENSE0000644000175000017500000004052513420465475011362 00000000000000Mozilla Public License Version 2.0 ================================== 1. Definitions -------------- 1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. 1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. 1.3. "Contribution" means Covered Software of a particular Contributor. 1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. 1.5. "Incompatible With Secondary Licenses" means (a) that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or (b) that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. 1.6. "Executable Form" means any form of the work other than Source Code Form. 1.7. "Larger Work" means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. "License" means this document. 1.9. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. 1.10. "Modifications" means any of the following: (a) any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or (b) any new file in Source Code Form that contains any Covered Software. 1.11. "Patent Claims" of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. 1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. 1.13. "Source Code Form" means the form of the work preferred for making modifications. 1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants and Conditions -------------------------------- 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and (b) under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: (a) for any code that a Contributor has removed from Covered Software; or (b) for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or (c) under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. 3. Responsibilities ------------------- 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: (a) such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and (b) You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. 4. Inability to Comply Due to Statute or Regulation --------------------------------------------------- If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Termination -------------- 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. ************************************************************************ * * * 6. Disclaimer of Warranty * * ------------------------- * * * * Covered Software is provided under this License on an "as is" * * basis, without warranty of any kind, either expressed, implied, or * * statutory, including, without limitation, warranties that the * * Covered Software is free of defects, merchantable, fit for a * * particular purpose or non-infringing. The entire risk as to the * * quality and performance of the Covered Software is with You. * * Should any Covered Software prove defective in any respect, You * * (not any Contributor) assume the cost of any necessary servicing, * * repair, or correction. This disclaimer of warranty constitutes an * * essential part of this License. No use of any Covered Software is * * authorized under this License except under this disclaimer. * * * ************************************************************************ ************************************************************************ * * * 7. Limitation of Liability * * -------------------------- * * * * Under no circumstances and under no legal theory, whether tort * * (including negligence), contract, or otherwise, shall any * * Contributor, or anyone who distributes Covered Software as * * permitted above, be liable to You for any direct, indirect, * * special, incidental, or consequential damages of any character * * including, without limitation, damages for lost profits, loss of * * goodwill, work stoppage, computer failure or malfunction, or any * * and all other commercial damages or losses, even if such party * * shall have been informed of the possibility of such damages. This * * limitation of liability shall not apply to liability for death or * * personal injury resulting from such party's negligence to the * * extent applicable law prohibits such limitation. Some * * jurisdictions do not allow the exclusion or limitation of * * incidental or consequential damages, so this exclusion and * * limitation may not apply to You. * * * ************************************************************************ 8. Litigation ------------- Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. 9. Miscellaneous ---------------- This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. 10. Versions of the License --------------------------- 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice ------------------------------------------- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. Exhibit B - "Incompatible With Secondary Licenses" Notice --------------------------------------------------------- This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. libixion-0.17.0/test-driver0000755000175000017500000001027713273351713012547 00000000000000#! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2013-07-13.22; # UTC # Copyright (C) 2011-2013 Free Software Foundation, Inc. # # 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, 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 . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <$log_file 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then estatus=1 fi case $estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: libixion-0.17.0/doc_example/0000775000175000017500000000000014136644732012711 500000000000000libixion-0.17.0/doc_example/section_examples/0000775000175000017500000000000014136644733016254 500000000000000libixion-0.17.0/doc_example/section_examples/cell_access.cpp0000664000175000017500000000325614122770261021135 00000000000000#include #include #include #include #include using namespace std; void access(const ixion::cell_access& ca) { switch (ca.get_value_type()) { case ixion::cell_value_t::numeric: { double v = ca.get_numeric_value(); cout << "numeric value: " << v << endl; break; } case ixion::cell_value_t::string: { std::string_view s = ca.get_string_value(); cout << "string value: " << s << endl; break; } case ixion::cell_value_t::boolean: { cout << "boolean value: " << ca.get_boolean_value() << endl; break; } case ixion::cell_value_t::error: { ixion::formula_error_t err = ca.get_error_value(); cout << "error value: " << ixion::get_formula_error_name(err) << endl; break; } case ixion::cell_value_t::empty: { cout << "empty cell" << endl; break; } default: cout << "???" << endl; } } void from_document() { ixion::document doc; doc.append_sheet("Sheet"); // fill this document ixion::cell_access ca = doc.get_cell_access("A1"); access(ca); } void from_model_context() { ixion::model_context cxt; cxt.append_sheet("Sheet"); // fill this model context ixion::abs_address_t A1(0, 0, 0); ixion::cell_access ca = cxt.get_cell_access(A1); access(ca); } int main(int argc, char** argv) { from_document(); from_model_context(); return EXIT_SUCCESS; } libixion-0.17.0/doc_example/section_examples/Makefile.in0000664000175000017500000010547214136644551020250 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = EXTRA_PROGRAMS = cell-access$(EXEEXT) TESTS = cell-access$(EXEEXT) subdir = doc_example/section_examples ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_cell_access_OBJECTS = cell_access.$(OBJEXT) cell_access_OBJECTS = $(am_cell_access_OBJECTS) cell_access_DEPENDENCIES = \ ../../src/libixion/libixion-@IXION_API_VERSION@.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/cell_access.Po am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(cell_access_SOURCES) DIST_SOURCES = $(cell_access_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ BOOST_LDPATH = @BOOST_LDPATH@ BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ BOOST_ROOT = @BOOST_ROOT@ BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX17 = @HAVE_CXX17@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IXION_API_VERSION = @IXION_API_VERSION@ IXION_MAJOR_API_VERSION = @IXION_MAJOR_API_VERSION@ IXION_MAJOR_VERSION = @IXION_MAJOR_VERSION@ IXION_MICRO_VERSION = @IXION_MICRO_VERSION@ IXION_MINOR_API_VERSION = @IXION_MINOR_API_VERSION@ IXION_MINOR_VERSION = @IXION_MINOR_VERSION@ IXION_VERSION = @IXION_VERSION@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MDDS_CFLAGS = @MDDS_CFLAGS@ MDDS_LIBS = @MDDS_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POW_LIB = @POW_LIB@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ VULKAN_CFLAGS = @VULKAN_CFLAGS@ VULKAN_LIBS = @VULKAN_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = \ -I$(top_srcdir)/include \ $(MDDS_CFLAGS) $(LIBIXION_CFLAGS) \ -DSRCDIR=\""$(top_srcdir)"\" cell_access_SOURCES = cell_access.cpp cell_access_LDADD = ../../src/libixion/libixion-@IXION_API_VERSION@.la all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc_example/section_examples/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc_example/section_examples/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list cell-access$(EXEEXT): $(cell_access_OBJECTS) $(cell_access_DEPENDENCIES) $(EXTRA_cell_access_DEPENDENCIES) @rm -f cell-access$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(cell_access_OBJECTS) $(cell_access_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cell_access.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? cell-access.log: cell-access$(EXEEXT) @p='cell-access$(EXEEXT)'; \ b='cell-access'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/cell_access.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-local distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/cell_access.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ check-am clean clean-binPROGRAMS clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-local \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS .PRECIOUS: Makefile distclean-local: rm -rf $(TESTS) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libixion-0.17.0/doc_example/section_examples/Makefile.am0000664000175000017500000000051114120267564020221 00000000000000 AM_CPPFLAGS = \ -I$(top_srcdir)/include \ $(MDDS_CFLAGS) $(LIBIXION_CFLAGS) \ -DSRCDIR=\""$(top_srcdir)"\" bin_PROGRAMS = EXTRA_PROGRAMS = \ cell-access cell_access_SOURCES = cell_access.cpp cell_access_LDADD = ../../src/libixion/libixion-@IXION_API_VERSION@.la TESTS = \ cell-access distclean-local: rm -rf $(TESTS) libixion-0.17.0/doc_example/Makefile.in0000664000175000017500000012063114136644551014700 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = EXTRA_PROGRAMS = document-simple$(EXEEXT) \ model-context-simple$(EXEEXT) TESTS = document-simple$(EXEEXT) model-context-simple$(EXEEXT) subdir = doc_example ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_document_simple_OBJECTS = document_simple.$(OBJEXT) document_simple_OBJECTS = $(am_document_simple_OBJECTS) document_simple_DEPENDENCIES = \ ../src/libixion/libixion-@IXION_API_VERSION@.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_model_context_simple_OBJECTS = model_context_simple.$(OBJEXT) model_context_simple_OBJECTS = $(am_model_context_simple_OBJECTS) model_context_simple_DEPENDENCIES = \ ../src/libixion/libixion-@IXION_API_VERSION@.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/document_simple.Po \ ./$(DEPDIR)/model_context_simple.Po am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(document_simple_SOURCES) $(model_context_simple_SOURCES) DIST_SOURCES = $(document_simple_SOURCES) \ $(model_context_simple_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ check recheck distdir distdir-am am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ BOOST_LDPATH = @BOOST_LDPATH@ BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ BOOST_ROOT = @BOOST_ROOT@ BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX17 = @HAVE_CXX17@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IXION_API_VERSION = @IXION_API_VERSION@ IXION_MAJOR_API_VERSION = @IXION_MAJOR_API_VERSION@ IXION_MAJOR_VERSION = @IXION_MAJOR_VERSION@ IXION_MICRO_VERSION = @IXION_MICRO_VERSION@ IXION_MINOR_API_VERSION = @IXION_MINOR_API_VERSION@ IXION_MINOR_VERSION = @IXION_MINOR_VERSION@ IXION_VERSION = @IXION_VERSION@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MDDS_CFLAGS = @MDDS_CFLAGS@ MDDS_LIBS = @MDDS_LIBS@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POW_LIB = @POW_LIB@ PYTHON = @PYTHON@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ VULKAN_CFLAGS = @VULKAN_CFLAGS@ VULKAN_LIBS = @VULKAN_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = section_examples AM_CPPFLAGS = \ -I$(top_srcdir)/include \ $(MDDS_CFLAGS) $(LIBIXION_CFLAGS) \ -DSRCDIR=\""$(top_srcdir)"\" document_simple_SOURCES = document_simple.cpp document_simple_LDADD = ../src/libixion/libixion-@IXION_API_VERSION@.la model_context_simple_SOURCES = model_context_simple.cpp model_context_simple_LDADD = ../src/libixion/libixion-@IXION_API_VERSION@.la all: all-recursive .SUFFIXES: .SUFFIXES: .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc_example/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc_example/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list document-simple$(EXEEXT): $(document_simple_OBJECTS) $(document_simple_DEPENDENCIES) $(EXTRA_document_simple_DEPENDENCIES) @rm -f document-simple$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(document_simple_OBJECTS) $(document_simple_LDADD) $(LIBS) model-context-simple$(EXEEXT): $(model_context_simple_OBJECTS) $(model_context_simple_DEPENDENCIES) $(EXTRA_model_context_simple_DEPENDENCIES) @rm -f model-context-simple$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(model_context_simple_OBJECTS) $(model_context_simple_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/document_simple.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_context_simple.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? document-simple.log: document-simple$(EXEEXT) @p='document-simple$(EXEEXT)'; \ b='document-simple'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) model-context-simple.log: model-context-simple$(EXEEXT) @p='model-context-simple$(EXEEXT)'; \ b='model-context-simple'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-recursive all-am: Makefile $(PROGRAMS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f ./$(DEPDIR)/document_simple.Po -rm -f ./$(DEPDIR)/model_context_simple.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-local distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/document_simple.Po -rm -f ./$(DEPDIR)/model_context_simple.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--depfiles check check-TESTS check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-local distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS .PRECIOUS: Makefile distclean-local: rm -rf $(TESTS) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libixion-0.17.0/doc_example/model_context_simple.cpp0000664000175000017500000001351414122770261017546 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * Copyright (c) 2020 Kohei Yoshida * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * ************************************************************************/ #include #include #include #include #include using namespace std; int main(int argc, char** argv) { ixion::model_context cxt; // First and foremost, insert a sheet. cxt.append_sheet("MySheet"); // Now, populate it with some numeric values in A1:A10. for (ixion::abs_address_t pos(0, 0, 0); pos.row <= 9; ++pos.row) { double value = pos.row + 1.0; // Set the row position + 1 as the cell value. cxt.set_numeric_cell(pos, value); } // Insert a string value into B2. ixion::abs_address_t B2(0, 1, 1); std::string s = "This cell contains a string value."; cxt.set_string_cell(B2, s); // Insert a literal string value into B3. ixion::abs_address_t B3(0, 2, 1); cxt.set_string_cell(B3, "This too contains a string value."); // Insert a string value into B4 via string identifier. ixion::string_id_t sid = cxt.add_string("Yet another string value."); ixion::abs_address_t B4(0, 3, 1); cxt.set_string_cell(B4, sid); // Now, let's insert a formula into A11 to sum up values in A1:A10. // Tokenize formula string first. std::unique_ptr resolver = ixion::formula_name_resolver::get(ixion::formula_name_resolver_t::excel_a1, &cxt); ixion::abs_address_t A11(0, 10, 0); ixion::formula_tokens_t tokens = ixion::parse_formula_string(cxt, A11, *resolver, "SUM(A1:A10)"); // Set the tokens into the model. const ixion::formula_cell* cell = cxt.set_formula_cell(A11, std::move(tokens)); // Register this formula cell for automatic dependency tracking. ixion::register_formula_cell(cxt, A11, cell); // Build a set of modified cells, to determine which formula cells depend // on them eithe directly or indirectly. Since we are performing initial // calculation, we can flag the entire sheet to be "modified" to trigger // all formula cells to be calculated. ixion::rc_size_t sheet_size = cxt.get_sheet_size(); ixion::abs_range_t entire_sheet(0, 0, 0, sheet_size.row, sheet_size.column); // sheet, row, column, row span, column span ixion::abs_range_set_t modified_cells{entire_sheet}; // Determine formula cells that need re-calculation given the modified cells. // There should be only one formula cell in this example. std::vector dirty_cells = ixion::query_and_sort_dirty_cells(cxt, modified_cells); cout << "number of dirty cells: " << dirty_cells.size() << endl; cout << "dirty cell: " << dirty_cells[0] << endl; // Now perform calculation. ixion::calculate_sorted_cells(cxt, dirty_cells, 0); double value = cxt.get_numeric_value(A11); cout << "value of A11: " << value << endl; // Insert a new formula to A11. tokens = ixion::parse_formula_string(cxt, A11, *resolver, "AVERAGE(A1:A10)"); // Before overwriting, make sure to UN-register the old cell. ixion::unregister_formula_cell(cxt, A11); // Set and register the new formula cell. cell = cxt.set_formula_cell(A11, std::move(tokens)); ixion::register_formula_cell(cxt, A11, cell); // This time, we know that none of the cell values have changed, but the // formula A11 is updated & needs recalculation. ixion::abs_range_set_t modified_formula_cells{A11}; dirty_cells = ixion::query_and_sort_dirty_cells(cxt, ixion::abs_range_set_t(), &modified_formula_cells); cout << "number of dirty cells: " << dirty_cells.size() << endl; // Perform calculation again. ixion::calculate_sorted_cells(cxt, dirty_cells, 0); value = cxt.get_numeric_value(A11); cout << "value of A11: " << value << endl; // Overwrite A10 with a formula cell with no references. ixion::abs_address_t A10(0, 9, 0); tokens = ixion::parse_formula_string(cxt, A10, *resolver, "(100+50)/2"); cxt.set_formula_cell(A10, std::move(tokens)); // No need to register this cell since it does not reference any other cells. modified_formula_cells = { A10 }; dirty_cells = ixion::query_and_sort_dirty_cells(cxt, ixion::abs_range_set_t(), &modified_formula_cells); cout << "number of dirty cells: " << dirty_cells.size() << endl; ixion::calculate_sorted_cells(cxt, dirty_cells, 0); value = cxt.get_numeric_value(A10); cout << "value of A10: " << value << endl; value = cxt.get_numeric_value(A11); cout << "value of A11: " << value << endl; return EXIT_SUCCESS; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/doc_example/document_simple.cpp0000664000175000017500000000563014122770261016520 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * Copyright (c) 2020 Kohei Yoshida * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * ************************************************************************/ #include #include #include #include using namespace std; int main(int argc, char** argv) { ixion::document doc; doc.append_sheet("MySheet"); // Now, populate it with some numeric values in A1:A10. for (ixion::abs_address_t pos(0, 0, 0); pos.row <= 9; ++pos.row) { double value = pos.row + 1.0; // Set the row position + 1 as the cell value. doc.set_numeric_cell(pos, value); } // Insert string values. std::string s = "This cell contains a string value."; doc.set_string_cell("B2", s); doc.set_string_cell("B3", "This too contains a string value."); doc.set_string_cell("MySheet!B4", "Yet another string value."); // Now, let's insert a formula into A11 to sum up values in A1:A10, and calculate it afterward. doc.set_formula_cell("A11", "SUM(A1:A10)"); doc.calculate(0); double value = doc.get_numeric_value("A11"); cout << "value of A11: " << value << endl; // Insert a new formula to A11. doc.set_formula_cell("A11", "AVERAGE(A1:A10)"); doc.calculate(0); value = doc.get_numeric_value("A11"); cout << "value of A11: " << value << endl; // Overwrite A10 with a formula cell with no references. doc.set_formula_cell("A10", "(100+50)/2"); doc.calculate(0); value = doc.get_numeric_value("A10"); cout << "value of A10: " << value << endl; value = doc.get_numeric_value("A11"); cout << "value of A11: " << value << endl; return EXIT_SUCCESS; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ libixion-0.17.0/doc_example/Makefile.am0000664000175000017500000000105314120267564014661 00000000000000SUBDIRS = section_examples AM_CPPFLAGS = \ -I$(top_srcdir)/include \ $(MDDS_CFLAGS) $(LIBIXION_CFLAGS) \ -DSRCDIR=\""$(top_srcdir)"\" bin_PROGRAMS = EXTRA_PROGRAMS = \ document-simple \ model-context-simple document_simple_SOURCES = document_simple.cpp document_simple_LDADD = ../src/libixion/libixion-@IXION_API_VERSION@.la model_context_simple_SOURCES = model_context_simple.cpp model_context_simple_LDADD = ../src/libixion/libixion-@IXION_API_VERSION@.la TESTS = \ document-simple \ model-context-simple distclean-local: rm -rf $(TESTS) libixion-0.17.0/doc/0000775000175000017500000000000014136644732011176 500000000000000libixion-0.17.0/doc/overview/0000775000175000017500000000000014136644732013044 500000000000000libixion-0.17.0/doc/overview/index.rst0000644000175000017500000000051613655546126014630 00000000000000 Overview ======== Project repository ------------------ Ixion project's main repository is hosted in GitLab: https://gitlab.com/ixion/ixion. Installation ------------ From the repository ^^^^^^^^^^^^^^^^^^^ Please follow the instructions found on the project repository page to build and install directly from the repository. libixion-0.17.0/doc/cpp/0000775000175000017500000000000014136644732011760 500000000000000libixion-0.17.0/doc/cpp/data_store/0000775000175000017500000000000014136644732014105 500000000000000libixion-0.17.0/doc/cpp/data_store/types.rst0000664000175000017500000000265614122770261015724 00000000000000 Types ===== Macros ------ .. doxygendefine:: IXION_ASCII Primitive Types --------------- .. doxygenenum:: ixion::celltype_t .. doxygenenum:: ixion::cell_value_t .. doxygenenum:: ixion::value_t .. doxygenenum:: ixion::table_area_t .. doxygenenum:: ixion::formula_name_resolver_t .. doxygenenum:: ixion::formula_error_t .. doxygenenum:: ixion::rc_direction_t .. doxygentypedef:: ixion::col_t .. doxygentypedef:: ixion::row_t .. doxygentypedef:: ixion::sheet_t .. doxygentypedef:: ixion::rc_t .. doxygentypedef:: ixion::string_id_t .. doxygentypedef:: ixion::table_areas_t .. doxygentypedef:: ixion::formula_tokens_t .. doxygenvariable:: ixion::empty_string_id .. doxygenvariable:: ixion::global_scope .. doxygenvariable:: ixion::invalid_sheet .. doxygenstruct:: ixion::rc_size_t .. doxygenstruct:: ixion::formula_group_t Address Types ------------- .. doxygenstruct:: ixion::address_t :members: .. doxygenstruct:: ixion::rc_address_t :members: .. doxygenstruct:: ixion::abs_address_t :members: .. doxygenstruct:: ixion::abs_rc_address_t :members: .. doxygenstruct:: ixion::range_t :members: .. doxygenstruct:: ixion::abs_range_t :members: .. doxygenstruct:: ixion::abs_rc_range_t :members: .. doxygentypedef:: ixion::abs_address_set_t .. doxygentypedef:: ixion::abs_range_set_t .. doxygentypedef:: ixion::abs_rc_range_set_t Utility Functions ----------------- .. doxygenfunction:: ixion::get_formula_error_name libixion-0.17.0/doc/cpp/data_store/model_context.rst0000644000175000017500000000060013662015441017405 00000000000000 .. highlight:: cpp Model Context ============= Examples -------- Refer to the :ref:`quickstart-model-context` section for code examples on how to use the :cpp:class:`~ixion::model_context` class. API Reference ------------- .. doxygenclass:: ixion::model_context :members: .. doxygenstruct:: ixion::config :members: .. doxygenclass:: ixion::model_iterator :members: libixion-0.17.0/doc/cpp/data_store/index.rst0000644000175000017500000000022613656025365015665 00000000000000 Data Store ========== .. toctree:: :maxdepth: 2 model_context.rst document.rst cell_access.rst dirty_cell_tracker.rst types.rst libixion-0.17.0/doc/cpp/data_store/cell_access.rst0000664000175000017500000000400514122770261017006 00000000000000 .. highlight:: cpp Cell Access =========== Examples -------- You can obtain a :cpp:class:`~ixion::cell_access` instance either from :cpp:class:`~ixion::model_context` or :cpp:class:`~ixion::document` class. Here is an example of how to obtain it from a :cpp:class:`~ixion::model_context` instance:: ixion::model_context cxt; cxt.append_sheet("Sheet"); // fill this model context ixion::abs_address_t A1(0, 0, 0); ixion::cell_access ca = cxt.get_cell_access(A1); Here is an example of how to obtain it from a :cpp:class:`~ixion::document` instance:: ixion::document doc; doc.append_sheet("Sheet"); // fill this document ixion::cell_access ca = doc.get_cell_access("A1"); Once you have your :cpp:class:`~ixion::cell_access` instance, you can, for instance, print the value of the cell as follows:: switch (ca.get_value_type()) { case ixion::cell_value_t::numeric: { double v = ca.get_numeric_value(); cout << "numeric value: " << v << endl; break; } case ixion::cell_value_t::string: { std::string_view s = ca.get_string_value(); cout << "string value: " << s << endl; break; } case ixion::cell_value_t::boolean: { cout << "boolean value: " << ca.get_boolean_value() << endl; break; } case ixion::cell_value_t::error: { ixion::formula_error_t err = ca.get_error_value(); cout << "error value: " << ixion::get_formula_error_name(err) << endl; break; } case ixion::cell_value_t::empty: { cout << "empty cell" << endl; break; } default: cout << "???" << endl; } The complete source code of this example is avaiable `here `_. API Reference ------------- .. doxygenclass:: ixion::cell_access :members: libixion-0.17.0/doc/cpp/data_store/document.rst0000644000175000017500000000040213662015441016357 00000000000000 .. highlight:: cpp Document ======== Examples -------- Refer to the :ref:`quickstart-document` section for code examples on how to use the :cpp:class:`~ixion::document` class. API Reference ------------- .. doxygenclass:: ixion::document :members: libixion-0.17.0/doc/cpp/data_store/dirty_cell_tracker.rst0000664000175000017500000000016513656025350020421 00000000000000 .. highlight:: cpp Dirty Cell Tracker ================== .. doxygenclass:: ixion::dirty_cell_tracker :members: libixion-0.17.0/doc/cpp/formula/0000775000175000017500000000000014136644732013425 500000000000000libixion-0.17.0/doc/cpp/formula/types.rst0000644000175000017500000000020013662015441015221 00000000000000 Types ===== Matrix ------ .. doxygenclass:: ixion::matrix :members: .. doxygenclass:: ixion::numeric_matrix :members: libixion-0.17.0/doc/cpp/formula/formula_tokens.rst0000664000175000017500000000031313656027307017123 00000000000000 Formula Tokens ============== .. doxygenclass:: ixion::formula_token :members: .. doxygenclass:: ixion::formula_tokens_store :members: .. doxygenstruct:: ixion::named_expression_t :members: libixion-0.17.0/doc/cpp/formula/formula_cell.rst0000644000175000017500000000020613273351726016536 00000000000000 Formula Cell ============ .. doxygenclass:: ixion::formula_cell :members: .. doxygenclass:: ixion::formula_result :members: libixion-0.17.0/doc/cpp/formula/formula_engine.rst0000664000175000017500000000110014122770261017051 00000000000000 Formula Engine ============== .. doxygenfunction:: ixion::parse_formula_string .. doxygenfunction:: ixion::print_formula_tokens .. doxygenfunction:: ixion::register_formula_cell .. doxygenfunction:: ixion::unregister_formula_cell .. doxygenfunction:: ixion::query_dirty_cells .. doxygenfunction:: ixion::query_and_sort_dirty_cells .. doxygenfunction:: ixion::calculate_sorted_cells Formula Functions ================= .. doxygenenum:: ixion::formula_function_t .. doxygenfunction:: ixion::get_formula_function_name .. doxygenfunction:: ixion::get_formula_function_opcode libixion-0.17.0/doc/cpp/formula/index.rst0000644000175000017500000000023214122765767015210 00000000000000 Formula ======= .. toctree:: :maxdepth: 2 formula_engine.rst formula_cell.rst formula_tokens.rst formula_name_resolver.rst types.rst libixion-0.17.0/doc/cpp/formula/formula_name_resolver.rst0000664000175000017500000000024214122770261020453 00000000000000 Formula Name Resolver ===================== .. doxygenclass:: ixion::formula_name_resolver :members: .. doxygenstruct:: ixion::formula_name_t :members: libixion-0.17.0/doc/cpp/index.rst0000644000175000017500000000024113655544770013542 00000000000000.. highlight:: cpp C++ API ======= .. toctree:: :maxdepth: 2 quickstart/index.rst formula/index.rst data_store/index.rst interface/index.rst libixion-0.17.0/doc/cpp/interface/0000775000175000017500000000000014136644732013720 500000000000000libixion-0.17.0/doc/cpp/interface/index.rst0000644000175000017500000000032513273351726015476 00000000000000 Interfaces ========== .. doxygenclass:: ixion::iface::formula_model_access :members: .. doxygenclass:: ixion::iface::session_handler :members: .. doxygenclass:: ixion::iface::table_handler :members: libixion-0.17.0/doc/cpp/quickstart/0000775000175000017500000000000014136644732014152 500000000000000libixion-0.17.0/doc/cpp/quickstart/using_model_context.rst0000664000175000017500000003342114122770261020670 00000000000000 .. highlight:: cpp .. _quickstart-model-context: Using model_context class ========================= Create a model context instance ------------------------------- When using ixion, the very first step is to create a :cpp:class:`~ixion::model_context` instance:: ixion::model_context cxt; The :cpp:class:`~ixion::model_context` class represents a document model data store that stores cell values spreading over one or more sheets. At the time of construction, the model contains no sheets. So the obvious next step is to insert a sheet:: // First and foremost, insert a sheet. cxt.append_sheet("MySheet"); The :cpp:func:`~ixion::model_context::append_sheet` method will append a new sheet to the model. You need to give a name when appending a sheet, and the name must be unique for each sheet. .. note:: Each sheet has a fixed size which cannot be changed once the :cpp:class:`~ixion::model_context` object is instantiated. The default sheet size is 1048576 rows by 16384 columns. You can specify a custom sheet size by passing a desired sheet size value to the :cpp:class:`~ixion::model_context` constructor at the time of instantiation. Populate model context with values ---------------------------------- Now that you have your first sheet inserted, let's put in some numeric values. In this example, we'll insert into A1:A10 their respective row positions. To insert a numeric value, you use :cpp:func:`~ixion::model_context::set_numeric_cell` which takes the position of the cell as its first argument and the value to set as its second argument. You need to use :cpp:class:`~ixion::abs_address_t` to specify a cell position. :: // Now, populate it with some numeric values in A1:A10. for (ixion::abs_address_t pos(0, 0, 0); pos.row <= 9; ++pos.row) { double value = pos.row + 1.0; // Set the row position + 1 as the cell value. cxt.set_numeric_cell(pos, value); } Note that, since row and column positions are internally 0-based, we add one to emulate how the row positions are presented in typical spreadsheet program. Inserting a string value can be done via :cpp:func:`~ixion::model_context::set_string_cell` in one of two ways. The first way is to store the value to a type that decays to ``std::string_view``, such as ``std::string``, char array, or string literal, and pass it to the method directly:: // Insert a string value into B2. ixion::abs_address_t B2(0, 1, 1); std::string s = "This cell contains a string value."; cxt.set_string_cell(B2, s); // Insert a literal string value into B3. ixion::abs_address_t B3(0, 2, 1); cxt.set_string_cell(B3, "This too contains a string value."); The second way is to add your string to the model_context's internal string pool first which will return its string ID, and pass that ID to the method:: // Insert a string value into B4 via string identifier. ixion::string_id_t sid = cxt.add_string("Yet another string value."); ixion::abs_address_t B4(0, 3, 1); cxt.set_string_cell(B4, sid); The model_context class has two methods for inserting a string to the string pool: :cpp:func:`~ixion::model_context::add_string` and :cpp:func:`~ixion::model_context::append_string`. The :cpp:func:`~ixion::model_context::add_string` method checks for an existing entry with the same string value upon each insertion attempt, and it will not insert the new value if the value already exists in the pool. The :cpp:func:`~ixion::model_context::append_string` method, on the other hand, does not check the pool for an existing value and always inserts the value. The :cpp:func:`~ixion::model_context::append_string` method is appropriate if you know all your string entries ahead of time and wish to bulk-insert them. Otherwise using :cpp:func:`~ixion::model_context::add_string` is appropriate in most cases. Insert a formula cell into model context ---------------------------------------- Inserting a formula cell requires a few extra steps. First, you need to tokenize your formula string, and to do that, you need to create an instance of :cpp:class:`~ixion::formula_name_resolver`. The formula_name_resolver class is responsible for resolving "names" into references, functions, and named expressions names. Ixion provides multiple types of name resolvers, and you specify its type when passing an enum value of type :cpp:enum:`~ixion::formula_name_resolver_t` when calling its static :cpp:func:`ixion::formula_name_resolver::get` function. In this example, we'll be using the Excel A1 syntax:: // Tokenize formula string first. std::unique_ptr resolver = ixion::formula_name_resolver::get(ixion::formula_name_resolver_t::excel_a1, &cxt); You can also optionally pass a memory address of your :cpp:class:`~ixion::model_context` instance which is required for resolving sheet names. You can pass a ``nullptr`` if you don't need to resolve sheet names. Next, let's create a formula string we want to tokenize. Here, we are inserting a formula expression **SUM(A1:A10)** into cell A11:: ixion::abs_address_t A11(0, 10, 0); ixion::formula_tokens_t tokens = ixion::parse_formula_string(cxt, A11, *resolver, "SUM(A1:A10)"); To tokenize a formula string, you call the :cpp:func:`ixion::parse_formula_string` function and pass * a model_context instance * the position of the cell to insert the formula into, * a formula_name_resolver instance, and * the formula string to tokenize. The function will then return a sequence of tokens representing the original formula string. Once you have the tokens, you can finally pass them to your model_context instance via :cpp:func:`~ixion::model_context::set_formula_cell`:: // Set the tokens into the model. const ixion::formula_cell* cell = cxt.set_formula_cell(A11, std::move(tokens)); There is a few things to note. First, you need to *move* your tokens to the method since instances of type :cpp:type:`ixion::formula_tokens_t` are non-copyable and only movable. Second, the method returns a pointer to the formula cell instance that just got inserted into the model. We are saving it here to use it in the next step below. When inserting a formula cell, you need to "register" it so that the model can record its reference dependencies via :cpp:func:`~ixion::register_formula_cell`:: // Register this formula cell for automatic dependency tracking. ixion::register_formula_cell(cxt, A11, cell); Without registering formula cells, you won't be able to determine which formula cells to re-calculate for given modified cells. Here we are passing the pointer to the formula cell returned from the previous call. This is optional, and you can pass a ``nullptr`` instead. But by passing it you will avoid the overhead of searching for the cell instance from the model. Calculate formula cell ---------------------- Now that we have the formula cell in, let's run our first calculation. To calcualte formula cells, you need to first specify a range of modified cells in order to query for all formula cells affected by it either directly or indirectly, which we refer to as "dirty" formula cells. Since this is our initial calculation, we can simply specify the entire sheet to be "modified" which will effectively trigger all formula cells:: ixion::rc_size_t sheet_size = cxt.get_sheet_size(); ixion::abs_range_t entire_sheet(0, 0, 0, sheet_size.row, sheet_size.column); // sheet, row, column, row span, column span ixion::abs_range_set_t modified_cells{entire_sheet}; We will then pass it to :cpp:func:`~ixion::query_and_sort_dirty_cells` to get a sequence of formula cell addresses to calculate:: // Determine formula cells that need re-calculation given the modified cells. // There should be only one formula cell in this example. std::vector dirty_cells = ixion::query_and_sort_dirty_cells(cxt, modified_cells); cout << "number of dirty cells: " << dirty_cells.size() << endl; Since so far we only have one formula cell, this should only return one range with the size of one row and one column. You will see the following output: .. code-block:: text number of dirty cells: 1 Let's inspect which cell it actually refers to:: cout << "dirty cell: " << dirty_cells[0] << endl; which will print: .. code-block:: text dirty cell: (sheet:0; row:10; column:0)-(sheet:0; row:10; column:0) confirming that it certainly points to cell A11. Finally, pass this to :cpp:func:`~ixion::calculate_sorted_cells`:: // Now perform calculation. ixion::calculate_sorted_cells(cxt, dirty_cells, 0); to calculate cell A11. After that, you can retrieve the result of the calculation by calling :cpp:func:`~ixion::model_context::get_numeric_value` for A11:: double value = cxt.get_numeric_value(A11); cout << "value of A11: " << value << endl; You will see the following output: .. code-block:: text value of A11: 55 Modify formula cell ------------------- Let's say you need to overwrite the formula in A11 to something else. The steps you need to take are very similar to the steps for inserting a brand-new formula cell, the only difference being that you need to "unregister" the old formula cell before overwriting it. Let's go through this step by step. First, create new tokens to insert:: // Insert a new formula to A11. tokens = ixion::parse_formula_string(cxt, A11, *resolver, "AVERAGE(A1:A10)"); This time we are inserting the formula **AVERAGE(A1:A10)** in A11 to overwrite the previous one **SUM(A1:A10)**. Before inserting these tokens, first unregister the current formula cell:: // Before overwriting, make sure to UN-register the old cell. ixion::unregister_formula_cell(cxt, A11); This will remove the dependency information of the old formula from the model's internal tracker. Once that's done, the rest is the same as inserting a new formula:: // Set and register the new formula cell. cell = cxt.set_formula_cell(A11, std::move(tokens)); ixion::register_formula_cell(cxt, A11, cell); Let's re-calculate the new formula cell. The re-calculation steps are also very similar to the initial calculation steps. The first step is to query for all dirty formula cells. This time, however, we don't query based on which formula cells are affected by modified cells, which we'll specify as none. Instead, we query based on which formula cells have been modified, which in this case is A11:: // This time, we know that none of the cell values have changed, but the // formula A11 is updated & needs recalculation. ixion::abs_range_set_t modified_formula_cells{A11}; dirty_cells = ixion::query_and_sort_dirty_cells(cxt, ixion::abs_range_set_t(), &modified_formula_cells); cout << "number of dirty cells: " << dirty_cells.size() << endl; As is the first calculation, you should only get one dirty cell address from the :cpp:func:`~ixion::query_and_sort_dirty_cells` call. Running the above code should produce: .. code-block:: text number of dirty cells: 1 The rest should be familiar:: // Perform calculation again. ixion::calculate_sorted_cells(cxt, dirty_cells, 0); value = cxt.get_numeric_value(A11); cout << "value of A11: " << value << endl; You should see the following output when finished: .. code-block:: text value of A11: 5.5 Formula cell with no references ------------------------------- Next example shows a scenario where you want to overwrite a cell in A10, which currently stores a numeric value, with a formula cell that references no other cells. Let's add the new formula cell first:: // Overwrite A10 with a formula cell with no references. ixion::abs_address_t A10(0, 9, 0); tokens = ixion::parse_formula_string(cxt, A10, *resolver, "(100+50)/2"); cxt.set_formula_cell(A10, std::move(tokens)); Here, we are not registering this cell since it contains no references hence it does not need to be tracked by dependency tracker. Also, since the previous cell in A10 is not a formula cell, there is no cell to unregister. .. warning:: Technically speaking, every formula cell that contains references to other cells or contains at least one volatile function needs to be registered. Since registering a formula cell that doesn't need to be registered is entirely harmless (albeit a slight overhead), it's generally a good idea to register every new formula cell regardless of its content. Likewise, unregistering a formula cell that didn't need to be registered (or wasn't registered) is entirely harmless. Even unregistering a cell that didn't contain a formula cell is harmless, and essentially does nothing. As such, it's probably a good idea to unregister a cell whenever a new cell value is being placed. Let's obtain all formula cells in need to re-calculation:: modified_formula_cells = { A10 }; dirty_cells = ixion::query_and_sort_dirty_cells(cxt, ixion::abs_range_set_t(), &modified_formula_cells); cout << "number of dirty cells: " << dirty_cells.size() << endl; Here, we are only passing one modified formula cell which is A10, and no other cells being modified. Since cell A11 references ``A1:A10`` and A10's value has changed, this should also trigger A11 for re-calculation. Running this code should produce the following output: .. code-block:: text number of dirty cells: 2 Let's calculate all affected formula cells and check the results of A10 and A11:: ixion::calculate_sorted_cells(cxt, dirty_cells, 0); value = cxt.get_numeric_value(A10); cout << "value of A10: " << value << endl; value = cxt.get_numeric_value(A11); cout << "value of A11: " << value << endl; Running this code should produce the following output: .. code-block:: text value of A10: 75 value of A11: 12 The complete source code of this example is avaiable `here `_. libixion-0.17.0/doc/cpp/quickstart/index.rst0000644000175000017500000000017513655534235015735 00000000000000 .. highlight:: cpp Quickstart ========== .. toctree:: :maxdepth: 1 using_model_context.rst using_document.rst libixion-0.17.0/doc/cpp/quickstart/using_document.rst0000664000175000017500000001254614122770261017647 00000000000000 .. highlight:: cpp .. _quickstart-document: Using document class ==================== In the :ref:`quickstart-model-context` section, we saw an example of how to set up a cell value store and run some simple calculations using the :cpp:class:`~ixion::model_context` class. While that approach certainly works fine, one large drawback is that you do need to manually handle formula tokenization, formula cell registration (and un-registration), as well as to trace which cells have their values changed and which formula cells have been created or modified. This is because the :cpp:class:`~ixion::model_context` class is designed to only handle cell value storage, and all other operations related to formula expressions and formula cell (re-)calculations have to be done outside of it. Luckily, Ixion also provides a higher level document class called :cpp:class:`~ixion::document` which internally uses :cpp:class:`~ixion::model_context` and handles all the formula cell related operations internally. This section provides an overview of how to use the :cpp:class:`~ixion::document` class to do more or less similar things we did in the :ref:`quickstart-model-context` section. First, we need to instantiate the :cpp:class:`~ixion::document` instance and insert a sheet named ``MySheet``. :: ixion::document doc; doc.append_sheet("MySheet"); Next, like we did in the previous section, we will insert numbers 1 through 10 in cells A1 through A10:: for (ixion::abs_address_t pos(0, 0, 0); pos.row <= 9; ++pos.row) { double value = pos.row + 1.0; // Set the row position + 1 as the cell value. doc.set_numeric_cell(pos, value); } So far we don't see much of a difference from model_context. Let's now insert string values into cells B2 and B3:: // Insert string values. std::string s = "This cell contains a string value."; doc.set_string_cell("B2", s); doc.set_string_cell("B3", "This too contains a string value."); Here we see the first difference. When using :cpp:class:`~ixion::document`, You can specify the cell position either by :cpp:struct:`~ixion::abs_address_t` as with :cpp:class:`~ixion::model_context`, or by a string whose value is the name of the cell address. The default address syntax for the string cell address is "Excel A1" syntax. You can pick a different syntax by passing a value of type :cpp:enum:`~ixion::formula_name_resolver_t` to the constructor. It's worth noting that, when specifying the cell position as a string value and the sheet name is omitted, the first sheet is implied. You can also specify the sheet name explicitly as in the following:: doc.set_string_cell("MySheet!B4", "Yet another string value."); For a document with only one sheet, it makes no difference whether to include the sheet name or leave it out, but if you have more than one sheet, you need to specify the sheet name when specifying a cell position on sheets other than the first one. Now, let's insert a a formula into A11 to sum up values in A1:A10, and calculate it afterward:: doc.set_formula_cell("A11", "SUM(A1:A10)"); doc.calculate(0); And fetch the calculated value in A11 and see what the result is:: double value = doc.get_numeric_value("A11"); cout << "value of A11: " << value << endl; You should see the following output: .. code-block:: text value of A11: 55 It looks about right. The :cpp:func:`~ixion::document::calculate` method takes one argument that is the number of threads to use for the calculation. We pass 0 here to run the calculation using only the main thread. Now, let's re-write the formula in cell A11 to take the average of A1:A10 instead, run the calculation again, and check the value of A11:: // Insert a new formula to A11. doc.set_formula_cell("A11", "AVERAGE(A1:A10)"); doc.calculate(0); value = doc.get_numeric_value("A11"); cout << "value of A11: " << value << endl; The output says: .. code-block:: text value of A11: 5.5 which looks right. Note that, unlike the previous example, there is no need to un-register and register cell A11 before and after the edit. Lastly, let's insert into cell A10 a new formula that contains no references to other cells. As this will trigger a re-calculation of cell A11, we will check the values of both A10 and A11:: // Overwrite A10 with a formula cell with no references. doc.set_formula_cell("A10", "(100+50)/2"); doc.calculate(0); value = doc.get_numeric_value("A10"); cout << "value of A10: " << value << endl; value = doc.get_numeric_value("A11"); cout << "value of A11: " << value << endl; The output will be: .. code-block:: text value of A10: 75 value of A11: 12 Notice once again that there is no need to do formula cell registration nor manual tracking of dirty formula cells. Conclusion ---------- In this section, we have performed the same thing we did in the :ref:`quickstart-model-context` section, but with much less code, and without the complexity of low-level formula expression tokenization, formula cell registration, or manual tracking of modified cells. If you are looking to leverage the functionality of Ixion but don't want to deal with lower-level formula API, using the :cpp:class:`~ixion::document` class may be just the ticket. The complete source code of this example is avaiable `here `_. libixion-0.17.0/doc/index.rst0000644000175000017500000000141513656024434012753 00000000000000.. Ixion documentation master file, created by sphinx-quickstart on Wed Feb 11 21:33:47 2015. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Ixion library documentation =========================== Ixion is a general purpose formula parser, interpreter, formula cell dependency tracker and spreadsheet document model backend all in one package. You can use Ixion to build a formula engine backend with spreadsheet-like multi-sheet cell storage management, or simply use to handle parsing and tokenization of formula expressions. Contents: .. toctree:: :maxdepth: 2 overview/index.rst cpp/index.rst python/index.rst Indices and tables ================== * :ref:`genindex` * :ref:`search` libixion-0.17.0/doc/python/0000775000175000017500000000000014136644732012517 500000000000000libixion-0.17.0/doc/python/quickstart.rst0000644000175000017500000000461013655546416015367 00000000000000 .. py:currentmodule:: ixion Quickstart ========== Let's go over very quickly how to create a document and populate some cells inside spreadsheet. First, you need to import ixion module and create a new :class:`Document` object. :: >>> import ixion >>> doc = ixion.Document() Since your newly-created document has no sheet at all, you need to insert one. :: >>> sheet1 = doc.append_sheet("MySheet1") The :meth:`Document.append_sheet` method takes a sheet name string as an argument (which in this case is "MySheet1") and returns an object representing the sheet that has just been inserted. This sheet object allows access to the sheet name via the :attr:`Sheet.name` attribute. :: >>> print(sheet1.name) 'MySheet1' .. note:: This attribute is read-only; you'll get a :exc:`TypeError` if you attempt to assign a new value to it. Now that you have a sheet object, let's go over how to put new cell values into the sheet. The sheet object provides several methods to set new cell values and also to retrieve them afterward. :: >>> sheet1.set_numeric_cell(0, 0, 12.3) # Set 12.3 to cell A1. >>> sheet1.get_numeric_value(0, 0) 12.3 >>> sheet1.set_string_cell(1, 0, "My string") # Set "My string" to cell A2. >>> sheet1.get_string_value(1, 0) 'My string' The setters take 3 arguments: the first one is a 0-based row index, the second one is a column index (also 0-based), and the third one is the new cell value. You can also pass these arguments by name as follows: :: >>> sheet1.set_string_cell(row=1, column=0, value="My string") Let's insert a formula expression next. :: >>> sheet1.set_formula_cell(0, 1, "A1*100") # B1 >>> sheet1.set_formula_cell(1, 1, "A2") # B2 .. note:: When setting a formula expression to a cell, you don't need to start your formula expression with a '=' like you would when you are entering a formula in a spreadsheet application. The formula cells don't get calculated automatically as you enter them; you need to explicitly tell the document to calculate the formula cells via the :meth:`Document.calculate` method. :: >>> doc.calculate() Now all the formula cells in this document have been calculated. Let's retrieve the results of the formula cells. :: >>> sheet1.get_numeric_value(0, 1) 1230.0 >>> sheet1.get_string_value(1, 1) 'My string' That's all there is to it! libixion-0.17.0/doc/python/index.rst0000644000175000017500000000014613655546405014302 00000000000000 Python API ========== .. toctree:: :maxdepth: 2 quickstart.rst document.rst sheet.rst libixion-0.17.0/doc/python/document.rst0000644000175000017500000000441213273351726015005 00000000000000 .. py:currentmodule:: ixion Document ======== .. class:: Document() Class :class:`~ixion.Document` represents an entire document which consists of one or more :class:`~ixion.Sheet` objects. .. attribute:: Document.sheet_names A read-only attribute that provides a tuple of the names of the sheets that belong to the document. The order of the sheet names signifies the order of the sheets in the document. .. method:: Document.append_sheet(sheet_name) Append a new sheet to the document object and return the newly created :class:`~ixion.Sheet` object. The *sheet name* will become the name of the sheet object being appended. Each :class:`Sheet` object must have a name, and the name must be unique within the document. :param str sheet_name: name of the sheet to be appended to the document. :rtype: :class:`ixion.Sheet` :return: appended sheet object. .. method:: Document.get_sheet(arg) Get a sheet object either by the position or by the name. When the ``arg`` is an integer, it returns the sheet object at specified position (0-based). When the ``arg`` is a string, it returns the sheet object whose name matches the specified string. :param arg: either the name of a sheet if it's of type ``str``, or the index of a sheet if it's of type ``int``. :rtype: :class:`ixion.Sheet` :return: sheet object representing the specified sheet. .. warning:: Prefer passing a sheet index to :meth:`~ixion.Document.get_sheet` than passing a sheet name. When passing a sheet name as an argument, the current :meth:`~ixion.Document.get_sheet` implementation has to iterate through the sheet objects in the document to find a matching one. .. method:: Document.calculate([threads]) Calculate all formula cells within the document that are marked "dirty" i.e. either those formula cells whose direct or indirect references have changed their values, or those formula cells that have been entered into the document. :param int threads: (optional) number of threads to use for the calculation besides the main thread. Set this to 0 if you want the calculation to be performed on the main thread only. The value of 0 is assumed if this value is not specified. libixion-0.17.0/doc/python/sheet.rst0000644000175000017500000000546013273351726014303 00000000000000 .. py:currentmodule:: ixion Sheet ===== .. class:: ixion.Sheet() Class :class:`~ixion.Sheet` represents a single sheet that stores cells in a 2-dimensional grid address space. Rows and columns are used to specify a position in the grid, and both rows and columns are 0-based, with the top-left-most cell having the address of row 0 and column 0. .. attribute:: Sheet.name A string representing the name of the sheet object. This is a read-only attribute. .. method:: Sheet.set_numeric_cell(row, column, value) Set a numeric *value* to a cell at specified *row* and *column* position. :param int row: row position. :param int column: column position. :param float value: numeric value to set to the specified position. .. method:: Sheet.set_string_cell(row, column, value) Set a string *value* to a cell at specified *row* and *column* position. :param int row: row position. :param int column: column position. :param str value: string value to set to the specified position. .. method:: Sheet.set_formula_cell(row, column, value) Set a formula expression (*value*) to a cell at specified *row* and *column* position. :param int row: row position. :param int column: column position. :param str value: formula expression to set to the specified position. .. method:: Sheet.get_numeric_value(row, column) Get a numeric value representing the content of a cell at specified *row* and *column* position. If the cell is of numeric type, its value is returned. If it's a formula cell, the result of the calculated formula result is returned if the result is of numeric type. :param int row: row position. :param int column: column position. :rtype: float :return: numeric value of the cell at specified position. .. method:: Sheet.get_string_value(row, column) Get a string value representing the content of a cell at specified *row* and *column* position. If the cell is of string type, its value is returned as-is. If it's a formula cell, the result of the calculated formula result is returned if the result is of string type. :param int row: row position. :param int column: column position. :rtype: str :return: string value of the cell at specified position. .. method:: Sheet.get_formula_expression(row, column) Given a formula cell at specified *row* and *column* position, get the formula expression stored in that cell. :param int row: row position. :param int column: column position. :rtype: str :return: formula expression stored in the cell at specified position. .. method:: Sheet.erase_cell(row, column) Erase the cell at specified *row* and *column* position. The slot at the specified position becomes empty afterward. :param int row: row position. :param int column: column position. libixion-0.17.0/doc/doxygen.conf0000664000175000017500000030154114105552004013430 00000000000000# Doxyfile 1.8.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "Ixion" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo # to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = _doxygen # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a # new page for each member. If set to NO, the documentation of a member will be # part of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO these classes will be included in the various overviews. This option has # no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the # todo list. This list is created by putting \todo commands in the # documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES the list # will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = NO # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO doxygen will only warn about wrong or incomplete parameter # documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = ../include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = *.hpp # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER ) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES, then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- # defined cascading style sheet that is included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. # Doxygen will copy the style sheet file to the output directory. For an example # see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler ( hhc.exe). If non-empty # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated ( # YES) or that it should be included in the master .chm file ( NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( # YES) or a normal table of contents ( NO) in the .chm file. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /