stdlibc: ~several fixes
[meinos.git] / kernel2 / kprint.c
blob978b826242055da23f9481311308ef46557e9429
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <stdarg.h>
20 #include <vga.h>
21 #include <cpu.h>
22 #include <interrupt.h>
24 unsigned long long divmod(unsigned long long dividend,unsigned int divisor,unsigned int *remainder) {
25 unsigned long long quotient;
26 unsigned int rem;
28 quotient = dividend / divisor;
29 rem = dividend % divisor;
31 if (remainder) *remainder = rem;
32 return quotient;
35 void kprintchar(char chr) {
36 vga_text_printchar(chr);
39 void kprintstr(char *str) {
40 if (str==NULL) str = "(null)";
41 while (*str) kprintchar(*str++);
44 void kprintnum(long long value,unsigned int radix,unsigned int uppercase,int sign) {
45 char buf[65];
46 char *p = buf;
47 const char * const chars = uppercase ? "0123456789ABCDEFGHIJKLMOPQRSTUVWXYZ" : "0123456789abcdefghijklmopqrstuvwxyz";
48 unsigned long long temp;
49 unsigned int digits;
50 unsigned int remainder;
52 if (value<0 && sign) {
53 kprintchar('-');
54 value = -value;
57 // Es werden nur Basen zwischen 2 und 36 unterstuezt
58 if(radix < 2 || radix > 36) return;
60 // Anzahl der Ziffern zaehlen
61 temp = value;
62 digits = 0;
63 do {
64 digits++;
65 temp = divmod(temp, radix, 0);
67 while (temp>0);
69 // Zeiger auf das Ende der Zahl setzen und Nullterminierung einfuegen
70 p += digits;
71 *p = 0;
73 // Ziffern rckw�ts in den Puffer schreiben
74 temp = value;
75 do {
76 temp = divmod(temp, radix, &remainder);
77 *--p = chars[remainder];
79 while (--digits);
81 kprintstr(buf);
84 void vakprintf(char *format,va_list args) {
85 while (*format) {
86 if (*format=='%') {
87 format++;
88 if (!*format) return;
89 else if (*format=='%') kprintchar('%');
90 else if (*format=='b') kprintnum(va_arg(args,unsigned int),2,1,0);
91 else if (*format=='c') kprintchar(va_arg(args,unsigned int));
92 else if (*format=='o') kprintnum(va_arg(args,unsigned int),8,1,0);
93 else if (*format=='d') kprintnum(va_arg(args,int),10,1,1);
94 else if (*format=='x') kprintnum(va_arg(args,unsigned int),16,1,0);
95 else if (*format=='s') kprintstr(va_arg(args,char*));
96 else {
97 kprintchar('%');
98 kprintchar(*format);
101 else kprintchar(*format);
102 format++;
106 void kprintf(char *format,...) {
107 va_list args;
109 va_start(args,format);
110 vakprintf(format,args);
111 va_end(args);
114 void panic(char *fmt,...) {
115 va_list args;
117 va_start(args,fmt);
118 vga_text_setcolor(VGA_TEXT_COLOR_RED_BLACK);
119 kprintstr(" *PANIC* ");
120 vakprintf(fmt,args);
121 interrupt_enable(0);
122 cpu_halt();