aboutsummaryrefslogtreecommitdiffstats
path: root/src/mds-kbdc/parse-error.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2014-11-09 20:48:31 +0100
committerMattias Andrée <maandree@operamail.com>2014-11-09 20:48:31 +0100
commit6afd09f080f3f4501f04d3f9fbfc55768be3b675 (patch)
tree9c56068b45839cf3a80c05e45251e12876a93735 /src/mds-kbdc/parse-error.c
parentwhitespace (diff)
downloadmds-6afd09f080f3f4501f04d3f9fbfc55768be3b675.tar.gz
mds-6afd09f080f3f4501f04d3f9fbfc55768be3b675.tar.bz2
mds-6afd09f080f3f4501f04d3f9fbfc55768be3b675.tar.xz
working on tree parsing
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to 'src/mds-kbdc/parse-error.c')
-rw-r--r--src/mds-kbdc/parse-error.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/mds-kbdc/parse-error.c b/src/mds-kbdc/parse-error.c
new file mode 100644
index 0000000..c16b9f4
--- /dev/null
+++ b/src/mds-kbdc/parse-error.c
@@ -0,0 +1,160 @@
+/**
+ * mds — A micro-display server
+ * Copyright © 2014 Mattias Andrée (maandree@member.fsf.org)
+ *
+ * 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.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+#include "parse-error.h"
+
+#include <stdlib.h>
+#include <alloca.h>
+#include <string.h>
+
+
+
+/**
+ * Print information about a parsing error
+ *
+ * @param this The error structure
+ * @param output The output file
+ */
+void mds_kbdc_parse_error_print(const mds_kbdc_parse_error_t* restrict this, FILE* restrict output)
+{
+ size_t i, n, start = 0, end = 0;
+ ssize_t m;
+ const char* restrict code = this->code;
+ char* desc;
+ char* dend = this->description + strlen(this->description);
+ char* dstart;
+ char* dptr;
+ char* p;
+ char* q;
+
+ /* Count the number points in the description we should modify to format it. */
+ for (p = this->description, n = 0;;)
+ {
+ if (q = strstr(p, "‘"), q == NULL) q = dend;
+ if (p = strstr(p, "’"), p == NULL) p = dend;
+ if (q < p) p = q;
+ if (*p++) n++;
+ else break;
+ }
+
+ /* Allocate string for the formatted description. */
+ n = 1 + strlen(this->description) + strlen("\033[xxm’") * n;
+ dptr = desc = alloca(n * sizeof(char));
+
+ /* Format description. */
+ for (p = this->description;;)
+ {
+ dstart = p;
+ if (q = strstr(p, "‘"), q == NULL) q = dend;
+ if (p = strstr(p, "’"), p == NULL) p = dend;
+ if (q < p) p = q;
+ if ((n = (size_t)(p - dstart)))
+ memcpy(dptr, dstart, n), dptr += n;
+ if (p == dend)
+ break;
+ if (strstr(p, "‘") == p) sprintf(dptr, "\033[01m‘%zn", &m), dptr += (size_t)m, p += strlen("‘");
+ else sprintf(dptr, "’\033[21m%zn", &m), dptr += (size_t)m, p += strlen("’");
+ }
+ *dptr = '\0';
+
+ /* Convert bytes count to character count for the code position */
+ for (i = 0, n = this->start; i < n; i++)
+ start++;
+ for (n = this->end; i < n; i++)
+ if ((code[i] & 0xC0) != 0x80)
+ end++;
+ end += start;
+
+ /* Print error information. */
+ fprintf(output, "\033[01m%s\033[21m:", this->pathname); /* TODO should be relative to the current dir */
+ if (this->error_is_in_file)
+ fprintf(output, "%zu:%zu–%zu:", this->line + 1, start + 1, end + 1);
+ switch (this->severity)
+ {
+ case MDS_KBDC_PARSE_ERROR_NOTE: fprintf(output, " \033[01;36mnote:\033[00m "); break;
+ case MDS_KBDC_PARSE_ERROR_WARNING: fprintf(output, " \033[01;35mwarning:\033[00m "); break;
+ case MDS_KBDC_PARSE_ERROR_ERROR: fprintf(output, " \033[01;31merror:\033[00m "); break;
+ case MDS_KBDC_PARSE_ERROR_INTERNAL_ERROR: fprintf(output, " \033[01;31minternal error:\033[00m "); break;
+ default:
+ abort();
+ break;
+ }
+ fprintf(output, "%s\n %s\n \033[01;32m", desc, code);
+ i = 0;
+ for (n = start; i < n; i++) fputc(' ', output);
+ for (n = end; i < n; i++) fputc('^', output);
+ fprintf(output, "\033[00m\n");
+}
+
+
+
+/**
+ * Release all resources allocated in a `mds_kbdc_parse_error_t*`
+ *
+ * @param this The error structure
+ */
+void mds_kbdc_parse_error_destroy(mds_kbdc_parse_error_t* restrict this)
+{
+ if (this == NULL)
+ return;
+ free(this->pathname), this->pathname = NULL;
+ free(this->code), this->code = NULL;
+ free(this->description), this->description = NULL;
+}
+
+
+/**
+ * Release all resources allocated in a `mds_kbdc_parse_error_t*`
+ * and release the allocation of the structure itself
+ *
+ * @param this The error structure
+ */
+void mds_kbdc_parse_error_free(mds_kbdc_parse_error_t* restrict this)
+{
+ mds_kbdc_parse_error_destroy(this);
+ free(this);
+}
+
+
+/**
+ * Release all resources allocated in a `NULL`-terminated group
+ * of `mds_kbdc_parse_error_t*`:s
+ *
+ * @param this The group of error structures
+ */
+void mds_kbdc_parse_error_destroy_all(mds_kbdc_parse_error_t** restrict these)
+{
+ mds_kbdc_parse_error_t* restrict that;
+ if (these == NULL)
+ return;
+ while (that = *these, that != NULL)
+ mds_kbdc_parse_error_free(that), *these++ = NULL;
+}
+
+
+/**
+ * Release all resources allocated in a `NULL`-terminated group of
+ * `mds_kbdc_parse_error_t*`:s and release the allocation of the group itself
+ *
+ * @param this The group of error structures
+ */
+void mds_kbdc_parse_error_free_all(mds_kbdc_parse_error_t** restrict these)
+{
+ mds_kbdc_parse_error_destroy_all(these);
+ free(these);
+}
+