diff --git a/assembler/assembler.c b/assembler/assembler.c index 3cc0158..a5a894c 100644 --- a/assembler/assembler.c +++ b/assembler/assembler.c @@ -421,7 +421,7 @@ int try_match_instruction(struct assembler_state *state, char **_line) { return 0; } else { scas_log(L_DEBUG, "Matched string '%s' to instruction '%s'", line, match->instruction->match); - scas_log_indent(); + scas_log_indent += 1; uint64_t instruction = match->instruction->value; for (unsigned int i = 0; i < match->operands->length; ++i) { operand_ref_t *ref = match->operands->items[i]; @@ -522,7 +522,7 @@ int try_match_instruction(struct assembler_state *state, char **_line) { } append_to_area(state->current_area, state->instruction_buffer, bytes_width); state->PC += bytes_width; - scas_log_deindent(); + scas_log_indent -= 1; match_free(match); } return 1; diff --git a/assembler/directives.c b/assembler/directives.c index 28500a3..1986a0a 100644 --- a/assembler/directives.c +++ b/assembler/directives.c @@ -1503,9 +1503,9 @@ int try_handle_directive(struct assembler_state *state, char **line) { (char *)stack_peek(state->file_name_stack), *(int *)stack_peek(state->line_number_stack)); int argc; char **argv = split_directive(*line + strlen(d->match) + 1, &argc, d->delimiter); - scas_log_indent(); + scas_log_indent += 1; int ret = d->function(state, argv, argc); - scas_log_deindent(); + scas_log_indent -= 1; for (int i = 0; i < argc; i += 1) { free(argv[i]); } diff --git a/include/log.h b/include/log.h index 61bf528..cdddc30 100644 --- a/include/log.h +++ b/include/log.h @@ -5,9 +5,8 @@ typedef enum { L_DEBUG = 3, } scas_log_importance_t; -void scas_log_init(scas_log_importance_t verbosity); void scas_log(scas_log_importance_t verbosity, char* format, ...); -void scas_log_indent(); -void scas_log_deindent(); -void scas_log_set_colors(bool enabled); +extern bool scas_log_colorize; +extern scas_log_importance_t scas_log_verbosity; +extern unsigned scas_log_indent; diff --git a/linker/linker.c b/linker/linker.c index 0974afe..57c4055 100644 --- a/linker/linker.c +++ b/linker/linker.c @@ -35,7 +35,7 @@ symbol_t *find_symbol(list_t *symbols, char *name) { void resolve_immediate_values(list_t *symbols, area_t *area, list_t *errors) { scas_log(L_DEBUG, "Resolving immediate values for area '%s' at %08X", area->name, area->final_address); - scas_log_indent(); + scas_log_indent += 1; for (unsigned int i = 0; i < area->late_immediates->length; ++i) { late_immediate_t *imm = area->late_immediates->items[i]; imm->instruction_address += area->final_address; @@ -92,7 +92,7 @@ void resolve_immediate_values(list_t *symbols, area_t *area, list_t *errors) { } } } - scas_log_deindent(); + scas_log_indent -= 1; } /* z80 only (and possibly ez80) */ diff --git a/log.c b/log.c index 85aa9c8..9da1473 100644 --- a/log.c +++ b/log.c @@ -8,9 +8,14 @@ #include #endif -static scas_log_importance_t v = 0; -static unsigned indent = 0; -static bool colored = true; +void scas_log_default(const char *msg) { + fprintf(stderr, "%s", msg); +} + +scas_log_importance_t scas_log_verbosity = 0; +unsigned scas_log_indent = 0; +bool scas_log_colorize = true; +void (*scas_log_function)(const char *) = scas_log_default; const char *verbosity_colors[] = { "", // L_SILENT @@ -19,42 +24,34 @@ const char *verbosity_colors[] = { "\x1B[1;30m", // L_DEBUG }; -void scas_log_init(scas_log_importance_t verbosity) { - v = verbosity; -} - -void scas_log_set_colors(bool _colored) { - colored = _colored; -} - -void scas_log_indent() { - ++indent; -} - -void scas_log_deindent() { - if (indent > 0) { - --indent; - } -} - void scas_log(scas_log_importance_t verbosity, char* format, ...) { - if (verbosity <= v && verbosity >= 0) { - size_t c = verbosity; - if (c > sizeof(verbosity_colors) / sizeof(char *)) { - c = sizeof(verbosity_colors) / sizeof(char *) - 1; - } - if (colored) { - fprintf(stderr, "%s", verbosity_colors[c]); - } - if (verbosity == L_DEBUG || verbosity == L_INFO) { - for (unsigned i = 0; i < indent; ++i) { - fprintf(stderr, " "); + if (scas_log_function) { + if (verbosity <= scas_log_verbosity && verbosity >= 0) { + size_t c = verbosity; + if (c > sizeof(verbosity_colors) / sizeof(char *)) { + c = sizeof(verbosity_colors) / sizeof(char *) - 1; + } + if (scas_log_colorize) { + scas_log_function(verbosity_colors[c]); + } + if (verbosity == L_DEBUG || verbosity == L_INFO) { + for (unsigned i = 0; i < scas_log_indent; ++i) { + scas_log_function(" "); + } + } + va_list args; + va_start(args, format); + int length = vsnprintf(NULL, 0, format, args); + va_end(args); + if (length > 0) { + va_start(args, format); + char *buf = malloc(length + 1); + vsnprintf(buf, length, format, args); + va_end(args); + scas_log_function(buf); + free(buf); + scas_log_function(scas_log_colorize ? "\n\x1B[0m" : "\n"); } } - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); - fprintf(stderr, "%s\n", colored ? "\x1B[0m" : ""); } } diff --git a/scas/main.c b/scas/main.c index bbea13b..49043e3 100644 --- a/scas/main.c +++ b/scas/main.c @@ -43,7 +43,6 @@ void init_scas_runtime() { strcpy(scas_runtime.include_path, "./"); } scas_runtime.linker_script = NULL; - scas_runtime.verbosity = L_SILENT; scas_runtime.options.explicit_export = false; // TODO: reenable @@ -166,7 +165,7 @@ void parse_arguments(int argc, char **argv) { int j; for (j = 1; argv[i][j] != '\0'; ++j) { if (argv[i][j] == 'v') { - scas_runtime.verbosity++; + scas_log_verbosity++; } else { scas_log(L_ERROR, "Invalid option %s", argv[i]); exit(1); @@ -263,8 +262,8 @@ list_t *split_include_path() { int main(int argc, char **argv) { init_scas_runtime(); + scas_log_verbosity = L_SILENT; parse_arguments(argc, argv); - scas_log_init(scas_runtime.verbosity); validate_scas_runtime(); instruction_set_t *instruction_set = find_inst(); if (instruction_set == NULL) { @@ -279,7 +278,7 @@ int main(int argc, char **argv) { list_t *objects = create_list(); for (unsigned int i = 0; i < scas_runtime.input_files->length; ++i) { scas_log(L_INFO, "Assembling input file: '%s'", scas_runtime.input_names->items[i]); - scas_log_indent(); + scas_log_indent += 1; FILE *f = scas_runtime.input_files->items[i]; char magic[7]; bool is_object = false; @@ -308,7 +307,7 @@ int main(int argc, char **argv) { errors->length, warnings->length, scas_runtime.input_names->items[i]); } list_add(objects, o); - scas_log_deindent(); + scas_log_indent -= 1; } if ((scas_runtime.jobs & LINK) == LINK) { diff --git a/scdump/main.c b/scdump/main.c index 399fda1..e8d07c2 100644 --- a/scdump/main.c +++ b/scdump/main.c @@ -76,7 +76,7 @@ void dump_area(area_t *a) { for (unsigned int i = 0; i < a->source_map->length; ++i) { source_map_t *map = a->source_map->items[i]; scas_log(L_INFO, "Source file '%s'", map->file_name); - scas_log_indent(); + scas_log_indent += 1; for (unsigned int j = 0; j < map->entries->length; ++j) { source_map_entry_t *entry = map->entries->items[j]; symbol_t *label = find_label(entry->address, a); @@ -90,19 +90,19 @@ void dump_area(area_t *a) { map->file_name, entry->line_number, entry->source_code); } - scas_log_deindent(); + scas_log_indent -= 1; } } if (runtime.dump_private_symbols || runtime.dump_public_symbols) { /* TODO: Distinguish between private/public */ scas_log(L_INFO, "Symbols defined:"); - scas_log_indent(); + scas_log_indent += 1; for (unsigned int i = 0; i < a->symbols->length; ++i) { symbol_t *sym = a->symbols->items[i]; scas_log(L_INFO, "'%s' == 0x%08X (%s)", sym->name, sym->value, sym->type == SYMBOL_LABEL ? "Label" : "Equate"); } - scas_log_deindent(); + scas_log_indent -= 1; } if (runtime.dump_references) { scas_log(L_INFO, "Unresolved references:"); @@ -130,8 +130,8 @@ int main(int argc, char **argv) { if (!parse_arguments(argc, argv)) { return 1; } - scas_log_init(L_INFO); - scas_log_set_colors(false); + scas_log_verbosity = L_INFO; + scas_log_colorize = false; for (unsigned int i = 0; i < runtime.input_files->length; ++i) { FILE *f; if (strcasecmp(runtime.input_files->items[i], "-") == 0) { diff --git a/scwrap/main.c b/scwrap/main.c index b9ab580..a525d7c 100644 --- a/scwrap/main.c +++ b/scwrap/main.c @@ -37,7 +37,8 @@ int main(int argc, char **argv) { if (!parse_arguments(argc, argv)) { return 1; } - scas_log_init(L_INFO); + + scas_log_verbosity = L_INFO; object_t *o = create_object(); area_t *a = create_area("DATA");