// This file is part of The New Aspell // Copyright (C) 2001 by Kevin Atkinson under the GNU LGPL license // version 2.0 or 2.1. You should have received a copy of the LGPL // license along with this library if you did not you can find // it at http://www.gnu.org/. #include "asc_ctype.hpp" #include "config.hpp" #include "string.hpp" #include "indiv_filter.hpp" #include "string_map.hpp" #include "vector.hpp" namespace { using namespace acommon; class TexInfoFilter : public IndividualFilter { private: struct Command { bool ignore; Command(bool i = false) : ignore(i) {} }; struct Table { String name; bool ignore_item; Table(String n) : name(n), ignore_item(false) {} }; String last_command; String env_command; int env_ignore; int ignore; bool in_line_command; bool seen_input; Vector stack; Vector table_stack; StringMap to_ignore; StringMap to_ignore_env; void reset_stack(); public: PosibErr setup(Config *); void reset(); void process(FilterChar * &, FilterChar * &); }; // // // PosibErr TexInfoFilter::setup(Config * opts) { name_ = "texinfo-filter"; order_num_ = 0.35; to_ignore.clear(); opts->retrieve_list("f-texinfo-ignore", &to_ignore); opts->retrieve_list("f-texinfo-ignore-env", &to_ignore_env); reset(); return true; } void TexInfoFilter::reset_stack() { stack.clear(); stack.push_back(Command()); in_line_command = false; ignore = 0; } void TexInfoFilter::reset() { reset_stack(); seen_input = false; env_command.clear(); env_ignore = 0; table_stack.clear(); table_stack.push_back(Table("")); } void TexInfoFilter::process(FilterChar * & str, FilterChar * & stop) { FilterChar * cur = str; while (cur != stop) { if (*cur == ' ') { ++cur; } else if (*cur == '@') { *cur = ' '; ++cur; if (cur == stop) break; if (asc_isalpha(*cur)) { bool was_table = last_command == table_stack.back().name && (last_command == "table" || last_command == "ftable" || last_command == "vtable"); last_command.clear(); while (cur != stop && asc_isalpha(*cur)) { last_command += *cur; *cur = ' '; ++cur; } if (env_ignore) { // do nothing } else if (was_table) { if (to_ignore.have(last_command)) table_stack.back().ignore_item = true; } else { if (cur == stop || *cur != '{') in_line_command = true; else ++cur; if (to_ignore.have(last_command) || (table_stack.back().ignore_item && (last_command == "item" || last_command == "itemx"))) { stack.push_back(Command(true)); ++ignore; } else { stack.push_back(Command(false)); } if (last_command == "end") { // do nothing as end command is special } else if (env_command.empty() && to_ignore_env.have(last_command)) { env_command = last_command; env_ignore = 1; } else if (env_command == last_command) { env_ignore++; } else if (last_command.suffix("table")) { table_stack.push_back(last_command); } } } else { *cur = ' '; ++cur; } } else if (!seen_input && *cur == '\\' && stop - cur >= 6 && cur[1] == 'i' && cur[2] == 'n' && cur[3] == 'p' && cur[4] == 'u' && cur[5] == 't') { last_command.clear(); for (int i = 0; i != 6; ++i) *cur++ = ' '; stack.push_back(Command(true)); ++ignore; in_line_command = true; seen_input = true; ++cur; } else if (last_command == "end") { last_command.clear(); while (cur != stop && asc_isalpha(*cur)) { last_command += *cur; *cur = ' '; ++cur; } if (last_command == env_command) { --env_ignore; if (env_ignore <= 0) { env_ignore = 0; env_command.clear(); } } else if (last_command == table_stack.back().name) { table_stack.pop_back(); if (table_stack.empty()) table_stack.push_back(Table("")); } last_command.clear(); } else { last_command.clear(); if (*cur == '{') { stack.push_back(Command()); } else if (*cur == '}') { if (stack.back().ignore) { --ignore; if (ignore < 0) ignore = 0; } stack.pop_back(); if (stack.empty()) stack.push_back(Command()); } else if (in_line_command && *cur == '\n') { reset_stack(); } else if (ignore || env_ignore) { *cur = ' '; } ++cur; } } } } C_EXPORT IndividualFilter * new_aspell_texinfo_filter() {return new TexInfoFilter;}