Coverage Report

Created: 2025-12-13 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jq/src/locfile.c
Line
Count
Source
1
#include <assert.h>
2
#include <errno.h>
3
#include <stdarg.h>
4
#include <stdlib.h>
5
#include <stdio.h>
6
#include <string.h>
7
#include "jq.h"
8
#include "jv_alloc.h"
9
#include "locfile.h"
10
#include "util.h"
11
12
0
struct locfile* locfile_init(jq_state *jq, const char *fname, const char* data, int length) {
13
0
  struct locfile* l = jv_mem_alloc(sizeof(struct locfile));
14
0
  l->jq = jq;
15
0
  l->fname = jv_string(fname);
16
0
  l->data = jv_mem_alloc(length);
17
0
  memcpy((char*)l->data,data,length);
18
0
  l->length = length;
19
0
  l->nlines = 1;
20
0
  l->refct = 1;
21
0
  for (int i=0; i<length; i++) {
22
0
    if (data[i] == '\n') l->nlines++;
23
0
  }
24
0
  l->linemap = jv_mem_calloc(l->nlines + 1, sizeof(int));
25
0
  l->linemap[0] = 0;
26
0
  int line = 1;
27
0
  for (int i=0; i<length; i++) {
28
0
    if (data[i] == '\n') {
29
0
      l->linemap[line] = i+1;   // at start of line, not of \n
30
0
      line++;
31
0
    }
32
0
  }
33
0
  l->linemap[l->nlines] = length+1;   // virtual last \n
34
0
  return l;
35
0
}
36
37
0
struct locfile* locfile_retain(struct locfile* l) {
38
0
  l->refct++;
39
0
  return l;
40
0
}
41
0
void locfile_free(struct locfile* l) {
42
0
  if (--(l->refct) == 0) {
43
0
    jv_free(l->fname);
44
0
    jv_mem_free(l->linemap);
45
0
    jv_mem_free((char*)l->data);
46
0
    jv_mem_free(l);
47
0
  }
48
0
}
49
50
0
int locfile_get_line(struct locfile* l, int pos) {
51
0
  assert(pos < l->length);
52
0
  int line = 1;
53
0
  while (l->linemap[line] <= pos) line++;   // == if pos at start (before, never ==, because pos never on \n)
54
0
  assert(line-1 < l->nlines);
55
0
  return line-1;
56
0
}
57
58
0
static int locfile_line_length(struct locfile* l, int line) {
59
0
  assert(line < l->nlines);
60
0
  return l->linemap[line+1] - l->linemap[line] -1;   // -1 to omit \n
61
0
}
62
63
0
void locfile_locate(struct locfile* l, location loc, const char* fmt, ...) {
64
0
  va_list fmtargs;
65
0
  va_start(fmtargs, fmt);
66
67
0
  jv m1 = jv_string_vfmt(fmt, fmtargs);
68
0
  va_end(fmtargs);
69
0
  if (!jv_is_valid(m1)) {
70
0
    jq_report_error(l->jq, m1);
71
0
    return;
72
0
  }
73
0
  if (loc.start == -1) {
74
0
    jq_report_error(l->jq, jv_string_fmt("jq: error: %s", jv_string_value(m1)));
75
0
    jv_free(m1);
76
0
    return;
77
0
  }
78
79
0
  int startline = locfile_get_line(l, loc.start);
80
0
  int offset = l->linemap[startline];
81
0
  int end = MIN(loc.end, MAX(l->linemap[startline+1] - 1, loc.start + 1));
82
0
  jv underline = jv_string_repeat(jv_string("^"), end - loc.start);
83
0
  jv m2 = jv_string_fmt("%s at %s, line %d, column %d:\n    %.*s\n    %*s",
84
0
                        jv_string_value(m1), jv_string_value(l->fname),
85
0
                        startline + 1, loc.start - offset + 1,
86
0
                        locfile_line_length(l, startline), l->data + offset,
87
0
                        end - offset, jv_string_value(underline));
88
0
  jv_free(m1);
89
0
  jv_free(underline);
90
0
  jq_report_error(l->jq, m2);
91
0
  return;
92
0
}