/* accidence * Copyright (C) 2010 Gabriel Bakiewicz * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02110-1301, USA. */ #include #include #include #include //#include #include "accidence.h" #include "accidence-provider.h" #define err_start "next = NULL; if (!mstk) { g_error("mistakes create"); // return?? } /* Searches for "from" tag - indicates position start */ pstart = g_strstr_len(perror, -1, from_tag); pend = g_strstr_len(pstart, -1, " "); if (pstart && pend) { gchar *pos_start; pstart += strlen(from_tag); pos_start = g_strndup(pstart, pend - pstart -1); mstk->pos_start = g_ascii_strtoll(pos_start, NULL, 10); g_free(pos_start); } else { g_debug("No start tag"); continue; } /* Searches for "to" tag - indicates position end */ pstart = g_strstr_len(perror, -1, to_tag); pend = g_strstr_len(pstart, -1, " "); if (pstart && pend) { gchar *pos_end; pstart += strlen(to_tag); pos_end = g_strndup(pstart, pend - pstart - 1); mstk->pos_end = g_ascii_strtoll(pos_end, NULL, 10); g_free(pos_end); } else { g_debug("No end tag"); continue; } /* Searches for "message" tag */ pstart = g_strstr_len(perror, -1, message_tag); pend = g_strstr_len(pstart, -1, ">"); if (pstart && pend) { pstart += strlen(message_tag); mstk->message = (char *)g_strndup(pstart, pend - pstart -1); } else { g_debug("No message"); continue; } mstk->suggestions = NULL; mstk->num_suggestions = 0; mstk->next = NULL; if (first_mstk == NULL) { first_mstk = mstk; } else { last_mstk->next = mstk; } last_mstk = mstk; perror = g_strstr_len(perror + strlen(err_start), -1, err_start); } return first_mstk; } #if 0 AccidenceMistake** parse_xml_mistakes(const char *buf_in, int *n_mistakes) { AccidenceMistake **mistakes = NULL; xmlTextReaderPtr pTxtReader; int bRead; *n_mistakes = 0; // FIXME mistakes = g_new0(AccidenceMistake *, 10); pTxtReader = xmlReaderForMemory(buf_in, strv_length(buf_in), "http://gramadoir.cvs.sourceforge.net/gramadoir/engine/api-output.dtd?view=markup" /* url */, NULL /* encoding */, XML_PARSE_NOCDATA /*flags*/); if (!pTxtReader) { fprintf(stderr, "Failed to parse xml document"); //error = x; return NULL; } bRead = xmlTextReaderRead(pTxtReader); while (bRead == 1) { g_debug("Parse while..."); g_debug("%s", (gchar *)xmlTextReaderReadString(pTxtReader)); if (xmlTextReaderDepth(pTxtReader) == 1 && xmlTextReaderNodeType(pTxtReader) == 1) { AccidenceMistake *mstk = NULL; mstk = g_new0(AccidenceMistake, 1); gchar *attr; gboolean node_ok = TRUE; attr = (gchar *)xmlTextReaderGetAttribute(pTxtReader, (xmlChar *)"fromx"); if (attr) { printf("fromx: %s\n", attr); mstk->pos_start = (int)g_ascii_strtoll(attr, NULL, 10); // TODO validate pos_start } else { node_ok = FALSE; } attr = (gchar *)xmlTextReaderGetAttribute(pTxtReader, (xmlChar *)"tox"); if (attr) { printf("tox: %s\n", attr); mstk->pos_end = (int)g_ascii_strtoll(attr, NULL, 10); // TODO validate pos_start } else { node_ok = FALSE; } /* Optional parameters */ attr = (gchar *)xmlTextReaderGetAttribute(pTxtReader, (xmlChar *)"msg"); if (attr) { printf("msg: %s\n", attr); mstk->message = (char *)attr; // TODO validate pos_start } else { node_ok = FALSE; } if (node_ok) { mstk->suggestions = NULL; mstk->num_suggestions = 0; mistakes[*n_mistakes++] = mstk; } } bRead = xmlTextReaderRead(pTxtReader); } xmlFreeTextReader(pTxtReader); xmlCleanupParser(); return mistakes; } #endif static accidence_check_status gramadoir_checker_check_sentence (AccidenceChecker *checker, const char *const sentence) { int status; gchar *command; gchar *out; gchar *gerr; GError *err = NULL; int n_mistakes; AccidenceMistake *mistakes; accidence_check_status check_status; /* Writes sentence to temporary file for input */ if (FALSE == g_file_set_contents(fin_name, sentence, -1 , /* sentence is NULL terminated */ &err )) { return ACCIDENCE_CHECK_ERROR; } command = g_strdup_printf("gram-ga.pl --api --incode UTF-8 %s", fin_name); g_spawn_command_line_sync(command, &out, NULL, &status, &err); #if 0 g_spawn_sync (NULL, /* directory */ argv, /* argv */ NULL, /* environment */ G_SPAWN_CHILD_INHERITS_STDIN | G_SPAWN_FILE_AND_ARGV_ZERO, NULL, /* child setup func */ NULL, /* user data */ &out, &gerr, /* STDERR */ &status, &err); /* Error */ #endif mistakes = parse_output_mistakes(out); if (mistakes) { checker->mistakes = mistakes; g_debug("Gramadoir mistakes found"); check_status = ACCIDENCE_CHECK_MISTAKES; } else { g_debug("Gramadoir mistakes not found"); check_status = ACCIDENCE_CHECK_OK; } g_free(command); return check_status; } static AccidenceMistake* gramadoir_checker_get_mistakes (AccidenceChecker *checker) { return checker->mistakes; } static void gramadoir_checker_dispose_mistakes (AccidenceChecker *acc_checker, AccidenceMistake *mistakes) { AccidenceMistake* p_mistake; while (mistakes) { p_mistake = mistakes; mistakes = mistakes->next; g_free(p_mistake->message); g_free(p_mistake); } } /********************************/ /* Accidence provider functions */ /********************************/ static AccidenceChecker* gramadoir_provider_request_checker(AccidenceProvider *provider, const char *lang_tag) { AccidenceChecker* checker; /* Checks if the provider has a checker for the language */ if (!provider->checker_exists(provider, lang_tag)) { return NULL; } checker = g_new0(AccidenceChecker, 1); /* Maps checker callback functions */ checker->check_sentence = gramadoir_checker_check_sentence; checker->get_mistakes = gramadoir_checker_get_mistakes; checker->dispose_mistakes = gramadoir_checker_dispose_mistakes; return checker; } static void gramadoir_provider_dispose_checker (AccidenceProvider *provider, AccidenceChecker *checker) { g_free(checker); } static void gramadoir_provider_dispose (AccidenceProvider *provider) { close(fp_in); g_remove(fin_name); g_free(provider); } static const char* gramadoir_provider_identify (AccidenceProvider *provider) { return "gramadoir"; } static const char* gramadoir_provider_describe (AccidenceProvider *provider) { return "Gramadoir Provider"; } static int gramadoir_provider_checker_exists (AccidenceProvider *provider, const char *const tag) { if (!strncmp ("ga", tag, 2)) { return 1; } return 0; } /* Maps provider functions implemented */ AccidenceProvider * init_accidence_provider(void) { AccidenceProvider *provider; provider = g_new0(AccidenceProvider, 1); provider->request_checker = gramadoir_provider_request_checker; provider->dispose_checker = gramadoir_provider_dispose_checker; provider->dispose = gramadoir_provider_dispose; provider->identify = gramadoir_provider_identify; provider->describe = gramadoir_provider_describe; provider->checker_exists = gramadoir_provider_checker_exists; /* Creates and open file for input */ fp_in = g_file_open_tmp(tmp_name, &fin_name, NULL); g_debug("File name %s\n", fin_name); return provider; }