summaryrefslogtreecommitdiff
path: root/src/kernel/log.c
blob: 6bad1cc6051ca129eeda01e4bcb643a749e76633 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <stdarg.h>
#include <stdbool.h>

#include "serial.h"
#include "log.h"

#define LOG_COM COM1

void init_log() {
  //TODO: move old "sys/current.log"
  //TODO: open new "sys/current.log"
}

static const char *const log_prefixes[] = {
  " [USER] ",
  " [INFO] ",
  " [DUMP] ",
  " [WARN] ",
  "[ERROR] ",
  "[PANIC] ",
};

static inline void logch(char ch) {
  sout(LOG_COM, ch);
  //TODO: write to log file as well
}

static const char hex_table[] = "0123456789abcdef";

void logf(enum log_level level, const char *format, ...) {
  va_list args;
  va_start(args, format);

  const char *log_prefix = log_prefixes[level];
  while (*log_prefix)
    logch(*(log_prefix++));

  for (const char *fi = format; *fi;)
    if (*fi != '%')
      logch(*(fi++));
    else {
      switch (*(fi + 1)) {
      case '%':
        logch('%');
        break;
      case 'c':;
        const char c = (char)va_arg(args, uint32_t);
        logch(c);
        break;
      case 's':;
        const char *s = va_arg(args, const char *);
        while (*s)
          logch(*(s++));
        break;
      case 'd':;
        const uint32_t d = va_arg(args, uint32_t);
        if (d == 0) {
          logch('0');
          break;
        }
        bool zeros = false;
        for (uint32_t place = 1000000000; place; place /= 10) {
          uint8_t digit = (d / place) % 10;
          if (digit)
            zeros = true;
          if (zeros)
            logch(digit | '0');
        }
        break;
      case 'h':;
        const uint32_t h = va_arg(args, uint32_t);
        uint32_t shift = 32;
        if (*(fi + 2) == 'b') {
          shift = 8;
          ++fi;
        }
        else if (*(fi + 2) == 'w') {
          shift = 16;
          ++fi;
        }
        else if (*(fi + 2) == 'd') {
          ++fi;
        }
        while (shift)
          logch(hex_table[(h >> (shift -= 4)) & 0xf]);
        break;
      default:
        logch('%');
        logch(*(fi + 1));
      }
      fi += 2;
    }

  logch('\n');

  va_end(args);
}