1 #include "../ml_library.h"
2 #include "../ml_macros.h"
3 #include "../ml_object.h"
4 #include <string.h>
5 #include "zlog/src/zlog.h"
6 #include "zlog/src/category.h"
7 
8 typedef struct {
9 	ml_type_t *Type;
10 	zlog_category_t *Category;
11 	int Level;
12 } ml_logger_t;
13 
ml_logger_call(ml_state_t * Caller,ml_logger_t * Logger,int Count,ml_value_t ** Args)14 static void ml_logger_call(ml_state_t *Caller, ml_logger_t *Logger, int Count, ml_value_t **Args) {
15 	if (!zlog_category_needless_level(Logger->Category, Logger->Level)) {
16 		ml_stringbuffer_t Buffer[1] = {ML_STRINGBUFFER_INIT};
17 		for (int I = 0; I < Count; ++I) {
18 			ml_stringbuffer_append(Buffer, Args[I]);
19 		}
20 		ml_source_t Source = ml_debugger_source(Caller);
21 		zlog(Logger->Category, Source.Name, strlen(Source.Name), "", 0, Source.Line, Logger->Level, "%s", ml_stringbuffer_get(Buffer));
22 	}
23 	ML_RETURN(MLNil);
24 }
25 
26 ML_TYPE(MLLoggerT, (), "logger",
27 	.call = (void *)ml_logger_call
28 );
29 
ml_logger(zlog_category_t * Category,int Level)30 static ml_logger_t *ml_logger(zlog_category_t *Category, int Level) {
31 	ml_logger_t *Logger = new(ml_logger_t);
32 	Logger->Type = MLLoggerT;
33 	Logger->Category = Category;
34 	Logger->Level = Level;
35 	return Logger;
36 }
37 
38 typedef struct {
39 	ml_type_t *Type;
40 	zlog_category_t *Handle;
41 	stringmap_t Loggers[1];
42 } ml_category_t;
43 
44 extern ml_type_t MLCategoryT[];
45 
ML_FUNCTIONX(MLCategory)46 ML_FUNCTIONX(MLCategory) {
47 	const char *Name;
48 	if (Count > 0) {
49 		ML_CHECKX_ARG_TYPE(0, MLStringT);
50 		Name = ml_string_value(Args[0]);
51 	} else {
52 		Name = ml_debugger_source(Caller).Name;
53 	}
54 	ml_category_t *Category = new(ml_category_t);
55 	Category->Type = MLCategoryT;
56 	Category->Handle = zlog_get_category(Name);
57 	stringmap_insert(Category->Loggers, "debug", ml_logger(Category->Handle, ZLOG_LEVEL_DEBUG));
58 	stringmap_insert(Category->Loggers, "info", ml_logger(Category->Handle, ZLOG_LEVEL_INFO));
59 	stringmap_insert(Category->Loggers, "notice", ml_logger(Category->Handle, ZLOG_LEVEL_NOTICE));
60 	stringmap_insert(Category->Loggers, "warn", ml_logger(Category->Handle, ZLOG_LEVEL_WARN));
61 	stringmap_insert(Category->Loggers, "error", ml_logger(Category->Handle, ZLOG_LEVEL_ERROR));
62 	stringmap_insert(Category->Loggers, "fatal", ml_logger(Category->Handle, ZLOG_LEVEL_FATAL));
63 	ML_RETURN(Category);
64 }
65 
66 ML_TYPE(MLCategoryT, (), "category",
67 	.Constructor = (ml_value_t *)MLCategory
68 );
69 
70 ML_METHOD("::", MLCategoryT, MLStringT) {
71 	ml_category_t *Category = (ml_category_t *)Args[0];
72 	ml_logger_t *Logger = (ml_logger_t *)stringmap_search(Category->Loggers, ml_string_value(Args[1]));
73 	if (!Logger) return ml_error("NameError", "Unknown logging level");
74 	return (ml_value_t *)Logger;
75 }
76 
ml_library_entry(ml_value_t * Module,ml_getter_t GlobalGet,void * Globals)77 void ml_library_entry(ml_value_t *Module, ml_getter_t GlobalGet, void *Globals) {
78 #include "ml_zlog_init.c"
79 	if (zlog_init("zlog.conf")) {
80 		printf("Failed to load zlog config\n");
81 	}
82 	ml_module_export(Module, "logger", (ml_value_t *)MLCategoryT);
83 }
84