Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 57 additions & 13 deletions ast/utils.c2
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public type Globals struct @(opaque) {
#if AstStatistics
Stats stats;
#endif
Color[15] colors;
}

// The only globals for AST are here, since they must be set explicitly for plugins!!
Expand All @@ -129,7 +130,24 @@ Globals* globals;
public fn Globals* getGlobals() { return globals; }

// only used by plugins
public fn void setGlobals(Globals* g) @(unused) { globals = g; }
public fn void setGlobals(Globals* g) @(unused) {
globals = g;
col_Normal = g.colors[0];
col_Error = g.colors[1];
col_Warning = g.colors[2];
col_Keyword = g.colors[3];
col_Identifier = g.colors[4];
col_Literal = g.colors[5];
col_Comment = g.colors[6];
col_Stmt = g.colors[7];
col_Decl = g.colors[8];
col_Expr = g.colors[9];
col_Attr = g.colors[10];
col_Template = g.colors[11];
col_Type = g.colors[12];
col_Value = g.colors[13];
col_Calc = g.colors[14];
}

// wordsize in bytes, must NOT be called from Plugin!
public fn void initialize(Context* c, string_pool.Pool* astPool, u32 wordsize, bool use_color) {
Expand Down Expand Up @@ -176,22 +194,43 @@ public fn void initialize(Context* c, string_pool.Pool* astPool, u32 wordsize, b
globals.builtinType_baseTypes[ISize] = Int64;
globals.builtinType_baseTypes[USize] = UInt64;
}

globals.colors[0] = color.getConfigColor("normal", color.Normal);
globals.colors[1] = color.getConfigColor("error", color.Red);
globals.colors[2] = color.getConfigColor("warning", color.Yellow);
globals.colors[3] = color.getConfigColor("keyword", color.Green);
globals.colors[4] = color.getConfigColor("identifier", color.Cyan);
globals.colors[5] = color.getConfigColor("literal", color.Cyan);
globals.colors[6] = color.getConfigColor("comment", color.Cyan);
globals.colors[7] = color.getConfigColor("ast.stmt", color.Bmagenta);
globals.colors[8] = color.getConfigColor("ast.decl", color.Bgreen);
globals.colors[9] = color.getConfigColor("ast.expr", color.Bmagenta);
globals.colors[10] = color.getConfigColor("ast.attr", color.Blue);
globals.colors[11] = color.getConfigColor("ast.template", color.Green);
globals.colors[12] = color.getConfigColor("ast.type", color.Green);
globals.colors[13] = color.getConfigColor("ast.value", color.Bcyan);
globals.colors[14] = color.getConfigColor("ast.calc", color.Yellow); // all calculated values

setGlobals(globals);
}

public fn void deinit(bool print_stats) {
Globals* g = globals;
if (!g) return;
#if AstStatistics
if (print_stats) globals.stats.dump();
if (print_stats) g.stats.dump();
#endif
globals.names_pool = nil;
globals.ast_count = 0;
globals.ast_capacity = 0;
stdlib.free(globals.ast_list);
globals.ast_list = nil;
globals.pointers.clear();
globals.string_types.clear();
globals.dump_buf.free();
stdlib.free(globals);
g.names_pool = nil;
g.ast_count = 0;
g.ast_capacity = 0;
stdlib.free(g.ast_list);
g.ast_list = nil;
g.pointers.clear();
g.string_types.clear();
g.dump_buf.free();
stdlib.free(g);
globals = nil;
color.freeConfigColors();
}

public fn u32 getWordSize() {
Expand Down Expand Up @@ -319,9 +358,14 @@ Color col_Template = Color.Green;
//Color col_Cast = Color.Red;
Color col_Type = Color.Green;
Color col_Value = Color.Bcyan;
Color col_Error = Color.Red;
public Color col_Error = Color.Red;
Color col_Calc = Color.Yellow; // all calculated value
Color col_Normal = Color.Normal;
public Color col_Normal = Color.Normal;
public Color col_Warning = color.Yellow;
public Color col_Keyword = color.Green;
public Color col_Identifier = color.Cyan;
public Color col_Literal = color.Cyan;
public Color col_Comment = color.Cyan;

public type AttrHandlerFn fn bool (void* arg, Decl* d, const Attr* a);

31 changes: 28 additions & 3 deletions ast_utils/color.c2
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
*/

module color;
import unistd;

import stdlib local;
import string local;
import unistd local;

public type Color enum u8 {
None,
Expand All @@ -35,6 +38,9 @@ public type Color enum u8 {
Bcyan,
White,
Normal,

CustomStart,
CustomEnd = Color.CustomStart + 15,
}

public const Color Black = Black;
Expand All @@ -55,7 +61,7 @@ public const Color Bcyan = Bcyan;
public const Color White = White;
public const Color Normal = Normal;

const char*[elemsof(Color)] defaultColors = {
const char*[] standardColors = {
[Color.None] = "",
[Color.Black] = "\033[0;30m",
[Color.Red] = "\033[0;31m",
Expand All @@ -76,8 +82,27 @@ const char*[elemsof(Color)] defaultColors = {
[Color.Normal] = "\033[0m",
}

i8 use_color = -1;
const char* c2_colors;
char[elemsof(Color)][32] defaultColors;

public fn bool useColor() {
return unistd.isatty(1);
if (use_color < 0) {
use_color = isatty(1) != 0;
if (use_color) {
c2_colors = getenv("C2_COLORS");
if (c2_colors && !strcmp(c2_colors, "none")) {
use_color = 0;
c2_colors = nil;
} else {
for (u32 i = 0; i < elemsof(standardColors); i++) {
strcpy(defaultColors[i], standardColors[i]);
}
if (c2_colors) customizeStandardColors(c2_colors);
}
}
}
return use_color;
}

public fn const char* Color.str(Color col) {
Expand Down
212 changes: 212 additions & 0 deletions ast_utils/color_config.c2
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/* Copyright 2022-2025 Bas van den Berg, Charlie Gordon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

module color;

import ctype local;
import stdio local;
import stdlib local;
import string local;

const char*[] standardColorNames = {
[Color.Black] = "black",
[Color.Red] = "red",
[Color.Green] = "green",
[Color.Yellow] = "yellow",
[Color.Blue] = "blue",
[Color.Magenta] = "magenta",
[Color.Cyan] = "cyan",
[Color.Grey] = "grey",
[Color.Darkgrey] = "darkgrey",
[Color.Bred] = "bred",
[Color.Bgreen] = "bgreen",
[Color.Byellow] = "byellow",
[Color.Bblue] = "bblue",
[Color.Bmagenta] = "bmagenta",
[Color.Bcyan] = "bcyan",
[Color.White] = "white",
[Color.Normal] = "normal",
}

fn Color findStandardColor(const char* name, bool use_custom = false) {
if (!name) return Color.None;
for (u32 i = 0; i < elemsof(standardColorNames); i++) {
if (!strcmp(name, standardColorNames[i]))
return (Color)i;
}
if (use_custom && !strncmp(name, "custom", 6)) {
i32 n = atoi(name + 6);
if (n > 0 && n <= Color.CustomEnd - Color.CustomStart + 1)
return (Color)(Color.CustomStart + n - 1);
}
return Color.None;
}

fn bool setPaletteColor(Color col, const char *val) {
u32 pal;
if (sscanf(val, "%*1[pP]%u", &pal) == 1) {
snprintf(defaultColors[col], elemsof(defaultColors[col]), "\033[38;5;%dm", pal);
return true;
}
u32 r, g, b;
if (sscanf(val, "#%2x%2x%2x", &r, &g, &b) == 3
|| sscanf(val, "rgb(%u,%u,%u)", &r, &g, &b) == 3) {
snprintf(defaultColors[col], elemsof(defaultColors[col]), "\033[38;2;%d;%d;%dm", r, g, b);
return true;
}
return false;
}

fn bool setColorString(Color col, const char *val) {
if (!val || *val == '\0') {
*defaultColors[col] = '\0';
return true;
}
if (!strcmp(val, "default")) {
*defaultColors[col] = '\0';
if (col < elemsof(standardColors) && standardColors[col])
strcpy(defaultColors[col], standardColors[col]);
return true;
}
if (Color col1 = findStandardColor(val)) {
strcpy(defaultColors[col], standardColors[col1]);
return true;
}
return setPaletteColor(col, val);
}

// Normalize a color name into array dest.
// s and dest can point to the same array
fn char* normalizeColor(char *dest, u32 size, const char* s) {
if (!size) return nil;
u32 len = size - 1;
u32 i = 0;
if (s) {
for (const char* p = s; *p && i < len; p++) {
char c = (char)tolower(*p);
if (c != '-' && c != '_') {
if (i < len) dest[i++] = c;
}
}
}
dest[i] = '\0';
if (*dest == 'b' && !strncmp(dest + 1, "right", 5)) {
memmove(dest + 1, dest + 6, i + 1 - 6);
}
return dest;
}

fn void customizeStandardColors(const char *p) {
if (!p) return;

char[16] name;
char[16] val;
while (getConfigEntry(name, elemsof(name), val, elemsof(val), &p)) {
// check for standard color customisation
if (Color col = findStandardColor(normalizeColor(name, elemsof(name), name), true)) {
setColorString(col, normalizeColor(val, elemsof(val), val));
}
}
}

fn bool getConfigEntry(char* buf1, u32 size1, char* buf2, u32 size2, const char** pp) {
const char *p = *pp;
for (;;) {
while (isspace(*p))
p++;
if (*p == '\0' || *p == '[')
return false;
if (*p != '#')
break;
while (*p && *p++ != '\n')
continue;
}
u32 i = 0;
u32 j = 0;
while (*p && *p != '=' && *p != ':' && *p != ';' && !isspace(*p)) {
char c = *p++;
if (i + 1 < size1)
buf1[i++] = c;
if (j + 1 < size2)
buf2[j++] = c;
}
if (size1) buf1[i] = '\0';
if (size2) buf2[j] = '\0';
while (*p == ' ') p++;
if (*p == '=' || *p == ':') {
p++;
while (*p == ' ') p++;
j = 0;
while (*p && *p != ';' && *p != '\n') {
char c = *p++;
if (j + 1 < size2) buf2[j++] = c;
}
if (size2) buf2[j] = '\0';
}
while (*p) {
char c = *p++;
if (c == '\n' || c == ';')
break;
}
*pp = p;
return true;
}

fn Color convertColor(const char *val, Color def) {
if (!val || *val == '\0')
return None;

if (Color col = findStandardColor(val))
return col;

//if (!strcmp(val, "default"))
// return def;

for (u32 i = Color.CustomStart; i <= Color.CustomEnd; i++) {
if (!defaultColors[i]) {
Color col = (Color)i;
if (setPaletteColor(col, val)) return col;
// TODO: complain about unknown color
return def;
}
}
// TODO: complain about out of custom colors
return def;
}

public fn Color getConfigColor(const char* cat, Color def) {
if (!use_color)
return None;
if (c2_colors) {
const char *p = c2_colors;
char[16] cat1;
char[16] style;
char[16] val;
if (!strcmp(p, "none"))
return None;
normalizeColor(cat1, elemsof(cat1), cat);
while (getConfigEntry(style, elemsof(style), val, elemsof(val), &p)) {
if (!strcmp(normalizeColor(style, elemsof(style), style), cat1))
return convertColor(normalizeColor(val, elemsof(val), val), def);
}
}
return def;
}

public fn void freeConfigColors() {
for (u32 i = Color.CustomStart; i <= Color.CustomEnd; i++) {
*defaultColors[i] = '\0';
}
}
Loading
Loading