Cthulhu  0.2.10
Cthulhu compiler collection
text_simple.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 
3 #include "common_extra.h"
4 
5 #include "memory/memory.h"
6 #include "format/notify.h"
7 
8 #include "io/io.h"
9 #include "scan/node.h"
10 
11 #include "std/map.h"
12 #include "std/str.h"
13 #include "std/typed/vector.h"
14 #include "std/vector.h"
15 
16 #include "base/util.h"
17 #include "base/panic.h"
18 
19 #define COLOUR_NOTE eColourGreen
20 #define COLOUR_PATH eColourBlue
21 
22 typedef struct simple_t
23 {
24  io_t *io;
26 
30 } simple_t;
31 
32 static void print_simple_notes(simple_t *simple, const vector_t *notes)
33 {
34  if (notes == NULL)
35  return;
36 
37  char *star = colour_text(simple->fmt, COLOUR_NOTE, "*");
38 
39  size_t note_count = vector_len(notes);
40  for (size_t i = 0; i < note_count; i++)
41  {
42  const char *note = vector_get(notes, i);
43  io_printf(simple->io, " %s note: %s\n", star, note);
44  }
45 }
46 
47 // first round of sorting
48 static int entry_cmp(const void *lhs, const void *rhs)
49 {
50  const map_entry_t *entry_lhs = lhs;
51  const map_entry_t *entry_rhs = rhs;
52 
53  const scan_t *scan_lhs = entry_lhs->key;
54  const scan_t *scan_rhs = entry_rhs->key;
55 
56  if (scan_lhs == NULL)
57  return -1;
58  if (scan_rhs == NULL)
59  return 1;
60 
61  const char *path_lhs = scan_path(scan_lhs);
62  const char *path_rhs = scan_path(scan_rhs);
63 
64  return ctu_strcmp(path_lhs, path_rhs);
65 }
66 
67 static void print_segment(simple_t *simple, const segment_t *segment, size_t scan_idx, size_t segment_idx)
68 {
69  CTASSERT(segment != NULL);
70 
71  source_config_t source_config = {
72  .context = simple->fmt,
73  .colour = COLOUR_PATH,
74  .heading_style = eHeadingGeneric,
75  .zero_indexed_lines = simple->file.zeroth_line,
76  };
77 
78  const char *path = fmt_node_location(source_config, &segment->node);
79 
80  const char *msg = segment->message;
81 
82  io_printf(simple->io, " (%zu.%zu) %s: %s\n", scan_idx + 1, segment_idx + 1, path, msg);
83 }
84 
85 static void print_segment_list(simple_t *simple, const typevec_t *segments, size_t scan_idx)
86 {
87  CTASSERT(segments != NULL);
88 
89  size_t len = typevec_len(segments);
90  for (size_t i = 0; i < len; i++)
91  {
92  const segment_t *segment = typevec_offset(segments, i);
93  print_segment(simple, segment, scan_idx, i);
94  }
95 }
96 
97 static void print_segments(simple_t *simple, const event_t *event)
98 {
99  // get all segments not in the same scan as the event
100  // first group by segments from the primary report
101  // then grouped by scanner, then alphabetical by scanner name
102  // then by line number
103 
104  if (event->segments == NULL)
105  return;
106 
107  size_t len = typevec_len(event->segments);
108 
109  // map_t<scan_t*, typevec_t<segment_t>>
110  map_t *scans = map_optimal(len, kTypeInfoPtr, simple->arena);
111  typevec_t *none = typevec_new(sizeof(segment_t), 4, simple->arena);
112  typevec_t *primary = all_segments_in_scan(event->segments, &event->node, simple->arena);
113 
114  for (size_t i = 0; i < len; i++)
115  {
116  segment_t *segment = typevec_offset(event->segments, i);
117  CTASSERT(segment != NULL);
118 
119  const scan_t *scan = node_get_scan(&segment->node);
120 
121  if (scan == node_get_scan(&event->node))
122  continue;
123 
124  if (scan == NULL)
125  {
126  typevec_push(none, segment);
127  continue;
128  }
129 
130  typevec_t *segments = map_get(scans, scan);
131 
132  if (segments == NULL)
133  {
134  segments = typevec_new(sizeof(segment_t), 2, simple->arena);
135  map_set(scans, scan, segments);
136  }
137 
138  typevec_push(segments, segment);
139  }
140 
141  print_segment_list(simple, primary, 0);
142 
143  typevec_t *entries = map_entries(scans);
144  typevec_sort(entries, entry_cmp);
145 
146  size_t entry_count = typevec_len(entries);
147  for (size_t i = 0; i < entry_count; i++)
148  {
149  map_entry_t *entry = typevec_offset(entries, i);
150  CTASSERT(entry != NULL);
151 
152  typevec_t *segments = entry->value;
153  segments_sort(segments);
154 
155  print_segment_list(simple, segments, i + 1);
156  }
157 
158  print_segment_list(simple, none, entry_count + 1);
159 }
160 
161 STA_DECL
162 void text_report_simple(text_config_t config, const event_t *event)
163 {
164  CTASSERT(config.io != NULL);
165  CTASSERT(event != NULL);
166  const diagnostic_t *diagnostic = event->diagnostic;
167 
168  io_t *io = config.io;
169  arena_t *arena = get_global_arena();
170 
172  .pallete = config.colours,
173  .arena = arena,
174  };
175 
176  simple_t simple = {
177  .io = io,
178  .arena = arena,
179  .text = config,
180  .file = config.config,
181  .fmt = fmt
182  };
183 
184  file_config_t cfg = config.config;
185  severity_t severity = get_severity(diagnostic, cfg.override_fatal);
186 
187  const char *sev = get_severity_name(severity);
188  colour_t col = get_severity_colour(severity);
189 
190  source_config_t source_config = {
191  .context = fmt,
192  .colour = COLOUR_PATH,
193  .heading_style = eHeadingGeneric,
194  .zero_indexed_lines = cfg.zeroth_line,
195  };
196 
197  const char *path = fmt_node_location(source_config, &event->node);
198  const char *lvl = colour_format(fmt, col, "%s: %s:", sev, diagnostic->id);
199 
200  io_printf(io, "%s %s %s:\n", path, lvl, event->message);
201 
202  print_segments(&simple, event);
203 
204  print_simple_notes(&simple, event->notes);
205 }
STA_DECL char * colour_format(format_context_t context, colour_t idx, const char *fmt,...)
Definition: colour.c:65
CT_NODISCARD CT_PUREFN CT_SCAN_API const char * scan_path(const scan_t *scan)
get the path of a scanner
Definition: scan.c:56
colour_t get_severity_colour(severity_t severity)
Definition: common_extra.c:52
const char * get_severity_name(severity_t severity)
Definition: common_extra.c:38
void segments_sort(typevec_t *segments)
Definition: common_extra.c:90
typevec_t * all_segments_in_scan(const typevec_t *segments, const node_t *node, arena_t *arena)
Definition: common_extra.c:95
severity_t get_severity(const diagnostic_t *diag, bool override_fatal)
Definition: common_extra.c:30
char * fmt_node_location(source_config_t config, const node_t *node)
Definition: common_extra.c:530
#define STA_DECL
sal2 annotation on function implementations to copy annotations from the declaration
CT_NODISCARD CT_PUREFN CT_BASE_API int ctu_strcmp(const char *lhs, const char *rhs)
compare two strings equivalent to strcmp but with safety checks
Definition: util.c:112
colour_t
a colour code
Definition: colour.h:23
STA_RET_STRING CT_FORMAT_API char * colour_text(format_context_t context, colour_t idx, const char *text)
add colour to a string
Definition: colour.c:56
CT_MEMORY_API arena_t * get_global_arena(void)
get the global memory arena
Definition: memory.c:16
CT_NODISCARD CT_STD_API typevec_t * map_entries(map_t *map)
collect all key-value pairs in a map into a vector returns a typevec_t<map_entry_t>
Definition: map.c:161
CT_NODISCARD CT_STD_API map_t * map_optimal(size_t size, hash_info_t info, arena_t *arena)
create a new map with an optimal size
Definition: optimal.c:85
CT_STD_API void map_set(map_t *map, const void *key, void *value)
set a key-value pair in a map
Definition: map.c:294
CT_NODISCARD CT_PUREFN CT_STD_API void * map_get(const map_t *map, const void *key)
get a value from a map
Definition: map.c:324
CT_IO_API size_t io_printf(io_t *io, STA_FORMAT_STRING const char *fmt,...)
printf to an io object
CT_NODISCARD CT_PUREFN CT_SCAN_API const scan_t * node_get_scan(const node_t *node)
get the associated source file of a node
Definition: node.c:57
severity_t
the default severity of a diagnostic
Definition: diagnostic.h:18
#define CTASSERT(expr)
assert a condition, prints the condition as a message
Definition: panic.h:130
CT_NODISCARD STA_FORMAT_STRING const char * fmt
Definition: str.h:68
CT_STD_API const hash_info_t kTypeInfoPtr
type information for a generic pointer this operates on the pointer itself and not the data it points...
Definition: typeinfo.c:41
CT_STD_API void typevec_sort(typevec_t *vec, int(*cmp)(const void *, const void *))
sort a vector
Definition: vector.c:206
CT_STD_API void * typevec_push(typevec_t *vec, const void *src)
push a value onto the vector
Definition: vector.c:156
CT_NODISCARD CT_PUREFN CT_STD_API size_t typevec_len(const typevec_t *vec)
get the length of a vector
Definition: vector.c:120
CT_NODISCARD CT_STD_API typevec_t * typevec_new(size_t width, size_t len, arena_t *arena)
create a new typed vector on the heap
Definition: vector.c:77
CT_NODISCARD CT_PUREFN CT_STD_API void * typevec_offset(const typevec_t *vec, size_t index)
get a pointer to the value at the given index
Definition: vector.c:191
CT_NODISCARD CT_PUREFN CT_STD_API void * vector_get(const vector_t *vector, size_t index)
get a value from a vector
Definition: vector.c:134
CT_NODISCARD CT_PUREFN CT_STD_API size_t vector_len(const vector_t *vector)
get the length of a vector
Definition: vector.c:152
an allocator object
Definition: arena.h:86
a diagnostic
Definition: diagnostic.h:27
const char * id
the id of the diagnostic should be in the format [A-Z]{2,3}[0-9]{4} e.g. CLI0001 this is not enforced...
Definition: diagnostic.h:34
an event handle TODO: make this and segment_t opaque
Definition: notify.h:36
node_t node
the primary node that this event is attached to
Definition: notify.h:41
vector_t * notes
extra notes that this event is attached to
Definition: notify.h:52
STA_FIELD_STRING char * message
the primary message
Definition: notify.h:44
typevec_t * segments
extra segments that this event is attached to
Definition: notify.h:48
the configuration for a file
Definition: notify.h:49
bool override_fatal
if true all warnings are treated as fatal
Definition: notify.h:58
bool zeroth_line
the zeroth line of a file is the first line
Definition: notify.h:51
a formatting context when using colours
Definition: colour.h:46
io object implementation
Definition: impl.h:122
arena_t * arena
the arena this object was allocated from
Definition: impl.h:133
a key-value pair in a map
Definition: map.h:175
const void * key
the key of this entry
Definition: map.h:176
void * value
the value of this entry
Definition: map.h:177
an unordered hash map
Definition: map.h:38
a source file scanner
Definition: scan.h:24
a segment inside an event
Definition: notify.h:57
node_t node
the related node
Definition: notify.h:59
STA_FIELD_STRING char * message
the message associated with this segment
Definition: notify.h:62
io_t * io
Definition: text_simple.c:24
format_context_t fmt
Definition: text_simple.c:29
file_config_t file
Definition: text_simple.c:28
arena_t * arena
Definition: text_simple.c:25
text_config_t text
Definition: text_simple.c:27
format_context_t context
Definition: common.h:31
io_t * io
Definition: notify.h:81
const colour_pallete_t * colours
Definition: notify.h:78
file_config_t config
Definition: notify.h:75
A vector with a fixed type size.
Definition: vector.h:24
a generic vector of pointers
Definition: vector.c:16
#define COLOUR_NOTE
Definition: text_simple.c:19
STA_DECL void text_report_simple(text_config_t config, const event_t *event)
Definition: text_simple.c:162
#define COLOUR_PATH
Definition: text_simple.c:20