Cthulhu  0.2.10
Cthulhu compiler collection
common.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 
3 #include "common.h"
4 
5 #include "base/util.h"
6 #include "base/panic.h"
7 
8 #include "arena/arena.h"
9 
10 #include "std/str.h"
11 
12 size_t get_offset_line(bool zero_indexed_lines, size_t line)
13 {
14  // if the first line is 0, then we don't need to do anything
15  if (zero_indexed_lines) return line;
16 
17  // otherwise, we need to subtract 1 from the line number
18  return line == 0 ? line : line - 1;
19 }
20 
21 int get_num_width(size_t num)
22 {
23  int width = 0;
24 
25  while (num > 0)
26  {
27  num /= 10;
28  width++;
29  }
30 
31  CTASSERTF(width <= FMT_BASE10_MAX_WIDTH, "number %zu is too large (%d)", num, width);
32 
33  return width;
34 }
35 
36 char *fmt_left_align(arena_t *arena, size_t width, const char *fmt, ...)
37 {
38  CTASSERTF(width >= 1, "width must be at least 1 (%zu given)", width);
39 
40  va_list args;
41  va_start(args, fmt);
42  text_t msg = text_vformat(arena, fmt, args);
43  va_end(args);
44 
45  if (msg.length >= width) return msg.text;
46 
47  size_t size = width - 1;
48  char *result = ARENA_MALLOC(size, "fmt_left_align", NULL, arena);
49  ctu_memset(result, ' ', width);
50  ctu_memcpy(result, msg.text, msg.length);
51 
52  result[width] = '\0';
53 
54  arena_free(msg.text, msg.length, arena);
55 
56  return result;
57 }
58 
59 char *fmt_right_align(arena_t *arena, size_t width, const char *fmt, ...)
60 {
61  CTASSERTF(width >= 1, "width must be at least 1 (%zu given)", width);
62 
63  va_list args;
64  va_start(args, fmt);
65  text_t msg = text_vformat(arena, fmt, args);
66  va_end(args);
67 
68  if (msg.length >= width) return msg.text;
69 
70  size_t size = width - 1;
71  char *result = ARENA_MALLOC(size, "fmt_right_align", NULL, arena);
72  ctu_memset(result, ' ', width);
73  ctu_memcpy(result + (width - msg.length), msg.text, msg.length);
74 
75  result[width] = '\0';
76 
77  arena_free(msg.text, msg.length, arena);
78 
79  return result;
80 }
81 
82 #define SCAN_BUILTIN_NAME "<builtin>"
83 
84 static const char *const kFormatBuiltinHeading[eHeadingCount] = {
85  [eHeadingGeneric] = SCAN_BUILTIN_NAME ":%" PRI_LINE "",
86  [eHeadingMicrosoft] = SCAN_BUILTIN_NAME "(%" PRI_LINE ")",
87 };
88 
89 static ctu_line_t calc_line_number(bool zero_indexed_lines, ctu_line_t line)
90 {
91  if (zero_indexed_lines) return line;
92 
93  return line + 1;
94 }
95 
96 static char *fmt_any_location(source_config_t config, const char *path, ctu_line_t line, ctu_column_t column)
97 {
98  if (path == NULL)
99  {
100  const char *fmt = kFormatBuiltinHeading[config.heading_style];
101  return colour_format(config.context, config.colour, fmt, line);
102  }
103 
104  // we branch here because msvc doesnt report column numbers, only lines
105  if (config.heading_style == eHeadingGeneric)
106  {
107  return colour_format(config.context, config.colour, "%s:%" PRI_LINE ":%" PRI_COLUMN "",
108  path, line, column);
109  }
110 
111  return colour_format(config.context, config.colour, "%s(%" PRI_LINE ")", path, line);
112 }
113 
115 {
116  format_context_t context = {
117  .arena = options.arena,
118  .pallete = options.pallete,
119  };
120 
121  return context;
122 }
123 
124 char *fmt_source_location(source_config_t config, const char *path, where_t where)
125 {
126  ctu_line_t first_line = calc_line_number(config.zero_indexed_lines, where.first_line);
127 
128  return fmt_any_location(config, path, first_line, where.first_column);
129 }
STA_DECL char * colour_format(format_context_t context, colour_t idx, const char *fmt,...)
Definition: colour.c:65
CT_NODISCARD size_t size
Definition: scan.h:128
CT_NOALIAS CT_BASE_API void * ctu_memcpy(STA_WRITES(size) void *CT_RESTRICT dst, STA_READS(size) const void *CT_RESTRICT src, size_t size)
copy memory from one location to another equivalent to memcpy but with safety checks
CT_NOALIAS CT_BASE_API void ctu_memset(STA_WRITES(size) void *dst, int value, size_t size)
set memory to a value equivalent to memset but with safety checks
@ eHeadingCount
Definition: format.h:22
#define ARENA_MALLOC(size, name, parent, arena)
allocate memory from a custom allocator
Definition: arena.h:392
CT_ARENA_API void arena_free(STA_RELEASE void *ptr, size_t size, arena_t *arena)
release memory from a custom allocator
#define CTASSERTF(expr,...)
assert a condition with a message and optional format arguments
Definition: panic.h:116
CT_NODISCARD STA_FORMAT_STRING const char CT_NODISCARD CT_STD_API text_t text_vformat(arena_t *arena, const char *fmt, va_list args)
format a string
Definition: str.c:56
CT_NODISCARD STA_FORMAT_STRING const char * fmt
Definition: str.h:68
an allocator object
Definition: arena.h:86
generic print options
Definition: format.h:35
const colour_pallete_t * pallete
colour pallete to use
Definition: format.h:43
arena_t * arena
temporary arena
Definition: format.h:37
a formatting context when using colours
Definition: colour.h:46
arena_t * arena
Definition: colour.h:47
bool zero_indexed_lines
Definition: common.h:34
heading_style_t heading_style
Definition: common.h:33
colour_t colour
Definition: common.h:32
format_context_t context
Definition: common.h:31
a range of text
Definition: text.h:14
size_t length
the number of characters in the text
Definition: text.h:19
a location inside a scanner locations are inclusive and 0-based
Definition: where.h:23
ctu_column_t first_column
the first column of the location
Definition: where.h:31
ctu_line_t first_line
the first line of the location
Definition: where.h:25
char * fmt_source_location(source_config_t config, const char *path, where_t where)
Definition: common.c:124
size_t get_offset_line(bool zero_indexed_lines, size_t line)
colour defines
Definition: common.c:12
char * fmt_left_align(arena_t *arena, size_t width, const char *fmt,...)
Definition: common.c:36
char * fmt_right_align(arena_t *arena, size_t width, const char *fmt,...)
Definition: common.c:59
int get_num_width(size_t num)
get the width of a number if it were printed as base10
Definition: common.c:21
format_context_t format_context_make(print_options_t options)
Definition: common.c:114
#define SCAN_BUILTIN_NAME
Definition: common.c:82
#define FMT_BASE10_MAX_WIDTH
Definition: common.h:20
#define PRI_LINE
format specifier for ctu_line_t
Definition: where.h:15
#define PRI_COLUMN
format specifier for ctu_column_t
Definition: where.h:18
uint_fast64_t ctu_column_t
a column number
Definition: where.h:12
uint_fast64_t ctu_line_t
a line number
Definition: where.h:9