aboutsummaryrefslogtreecommitdiff
path: root/src/debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug.c')
-rw-r--r--src/debug.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/debug.c b/src/debug.c
new file mode 100644
index 0000000..7226640
--- /dev/null
+++ b/src/debug.c
@@ -0,0 +1,108 @@
+#include <stdarg.h>
+#include <string.h>
+
+#include <lyn/debug.h>
+
+/**
+ * Get string representation of issue_level.
+ *
+ * @param level issue_level to get string representation for.
+ * @return \p level as a string.
+ */
+const char *issue_level_str(enum issue_level level)
+{
+ switch (level) {
+ case SRC_INFO: return "info";
+ case SRC_WARN: return "warn";
+ case SRC_ERROR: return "error";
+ }
+
+ return "unknown";
+}
+
+/**
+ * Find position in file buffer where line number \p no
+ * starts. Lines are assumed to be one-indexed, with
+ * \p no = \c 0 and \p no = \c 1 both considered the first line.
+ *
+ * @param buf Buffer to look in.
+ * @param no Line number whose start to look for.
+ * @return Pointer to location in buffer where line number \p no
+ * starts.
+ */
+static const char *find_lineno(const char *buf, size_t no)
+{
+ if (no == 0 || no == 1)
+ return buf;
+
+ char c;
+ while ((c = *buf)) {
+ buf++;
+
+ if (c == '\n')
+ no--;
+
+ if (no == 1)
+ break;
+ }
+
+ return buf;
+}
+
+/**
+ * Helper for printing out an issue.
+ *
+ * @param issue Issue context.
+ * @param fmt Format string. Follows standard printf() formatting.
+ * @param args Arguments for \p fmt.
+ */
+static void _issue(struct src_issue issue, const char *fmt, va_list args)
+{
+ /* get start and end of current line in buffer */
+ const char *line_start = find_lineno(issue.fctx.fbuf,
+ (size_t)issue.loc.first_line);
+ const char *line_end = strchr(line_start, '\n');
+ if (!line_end)
+ line_end = strchr(line_start, 0);
+
+ const int line_len = (int)(line_end - line_start);
+
+ fprintf(stderr, "%s:%i:%i: %s: ", issue.fctx.fname,
+ issue.loc.first_line,
+ issue.loc.first_col,
+ issue_level_str(issue.level));
+
+ vfprintf(stderr, fmt, args);
+ fputc('\n', stderr);
+
+ int lineno_len = snprintf(NULL, 0, "%i", issue.loc.first_line);
+ fputc(' ', stderr);
+ fprintf(stderr, "%i | ", issue.loc.first_line);
+
+ fprintf(stderr, "%.*s\n", line_len, line_start);
+
+ for (int i = 0; i < lineno_len + 2; ++i)
+ fputc(' ', stderr);
+
+ fprintf(stderr, "| ");
+
+ for (int i = 0; i < issue.loc.first_col - 1; ++i)
+ fputc(line_start[i] == '\t' ? '\t' : ' ', stderr);
+
+ for (int i = issue.loc.first_col; i < issue.loc.last_col; ++i) {
+ if (i == issue.loc.first_col)
+ fputc('^', stderr);
+ else
+ fputc('~', stderr);
+ }
+
+ fputc('\n', stderr);
+}
+
+void src_issue(struct src_issue issue, const char *err_msg, ...)
+{
+ va_list args;
+ va_start(args, err_msg);
+ _issue(issue, err_msg, args);
+ va_end(args);
+}