changeset 16:ddefe6d97cd7

Merged
author windel-eee
date Fri, 18 Nov 2011 14:41:53 +0100
parents de004f808e56 (current diff) a58904747019 (diff)
children f3e3e0e9c4bc
files cos/images/first64bits.img cos/include/ctype.h cos/include/kernel.h cos/include/stdarg.h
diffstat 13 files changed, 554 insertions(+), 214 deletions(-) [+]
line wrap: on
line diff
--- a/cos/Makefile	Tue Nov 15 07:35:00 2011 +0100
+++ b/cos/Makefile	Fri Nov 18 14:41:53 2011 +0100
@@ -1,8 +1,8 @@
 # vim: set noexpandtab:
 
-all: lcfosc.elf
+all: bootdisk.img Makefile
 
-bootdisk.img: lcfosc.elf grub/menu.lst
+bootdisk.img: lcfosc.elf grub/menu.lst Makefile
 	objcopy -O binary lcfosc.elf lcfosc.bin
 	cp grub/emptybootdisk.img bootdisk.img
 	mcopy -D o -i bootdisk.img lcfosc.bin ::
@@ -16,20 +16,24 @@
 			-nostdlib \
 			-nostartfiles \
 			-fno-builtin \
+			-mcmodel=large \
 			-Iinclude
 
 OBJECTS = \
 	kernel/video.o \
 	kernel/snprintf.o \
-	kernel/kernel.o
+	kernel/kernel.o \
+	kernel/asmcode.o \
+	kernel/handlers.o
+
 
 lcfosc.elf: $(CRT0) $(OBJECTS) linker.ld
 	ld -T linker.ld -o lcfosc.elf $(CRT0) $(OBJECTS)
 
-%.o : %.asm
+%.o : %.asm Makefile
 	nasm -f elf64 -o $@ $<
 
-%.o : %.c
+%.o : %.c Makefile
 	gcc $(CFLAGS) -o $@ -c $< -Wall -Wextra -Werror
 
 clean:
--- a/cos/bochsrc.txt	Tue Nov 15 07:35:00 2011 +0100
+++ b/cos/bochsrc.txt	Fri Nov 18 14:41:53 2011 +0100
@@ -65,7 +65,7 @@
 #display_library: win32, options="gui_debug" # use Win32 debugger gui
 #display_library: wx
 #display_library: x, options="hideIPS" # disable IPS output in status bar
-#display_library: x, options="gui_debug" # use GTK debugger gui
+display_library: x, options="gui_debug" # use GTK debugger gui
 
 #=======================================================================
 # ROMIMAGE:
@@ -859,7 +859,7 @@
 # Example:
 #   magic_break: enabled=1
 #=======================================================================
-#magic_break: enabled=1
+magic_break: enabled=1
 
 #=======================================================================
 # PORT_E9_HACK:
--- a/cos/grub/menu.lst	Tue Nov 15 07:35:00 2011 +0100
+++ b/cos/grub/menu.lst	Fri Nov 18 14:41:53 2011 +0100
@@ -1,5 +1,5 @@
 default 0
-timeout 10
+timeout 3
 title lcfosc
 root (fd0)
 kernel /lcfosc.bin
Binary file cos/images/first64bits.img has changed
--- a/cos/include/ctype.h	Tue Nov 15 07:35:00 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-#ifndef _LINUX_CTYPE_H
-#define _LINUX_CTYPE_H
-
-/*
- * NOTE! This ctype does not handle EOF like the standard C
- * library is required to.
- */
-
-#define _U	0x01	/* upper */
-#define _L	0x02	/* lower */
-#define _D	0x04	/* digit */
-#define _C	0x08	/* cntrl */
-#define _P	0x10	/* punct */
-#define _S	0x20	/* white space (space/lf/tab) */
-#define _X	0x40	/* hex digit */
-#define _SP	0x80	/* hard space (0x20) */
-
-extern unsigned char _ctype[];
-
-#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
-
-#define isalnum(c)	((__ismask(c)&(_U|_L|_D)) != 0)
-#define isalpha(c)	((__ismask(c)&(_U|_L)) != 0)
-#define iscntrl(c)	((__ismask(c)&(_C)) != 0)
-#define isdigit(c)	((__ismask(c)&(_D)) != 0)
-#define isgraph(c)	((__ismask(c)&(_P|_U|_L|_D)) != 0)
-#define islower(c)	((__ismask(c)&(_L)) != 0)
-#define isprint(c)	((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
-#define ispunct(c)	((__ismask(c)&(_P)) != 0)
-#define isspace(c)	((__ismask(c)&(_S)) != 0)
-#define isupper(c)	((__ismask(c)&(_U)) != 0)
-#define isxdigit(c)	((__ismask(c)&(_D|_X)) != 0)
-
-#define isascii(c) (((unsigned char)(c))<=0x7f)
-#define toascii(c) (((unsigned char)(c))&0x7f)
-
-static inline unsigned char tolower(unsigned char c)
-{
-	if (isupper(c))
-		c -= 'A'-'a';
-	return c;
-}
-
-static inline unsigned char toupper(unsigned char c)
-{
-	if (islower(c))
-		c -= 'a'-'A';
-	return c;
-}
-
-#endif
--- a/cos/include/kernel.h	Tue Nov 15 07:35:00 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-#ifndef KERNEL_H
-#define KERNEL_H
-
-// Include common functions, available to all!
-#define NULL ((void*)0)
-
-// Type defs:
-typedef unsigned int        uint32_t;
-typedef unsigned long long  uint64_t;
-typedef unsigned short      ushort_t;
-typedef unsigned char       uchar_t;
-typedef unsigned int        uint_t;
-typedef unsigned long       ulong_t;
-typedef unsigned long long  ulonglong_t;
-typedef unsigned long       off_t;
-typedef unsigned long       size_t;
-
-void printf(const char* fmt, ... );
-void memset(void* ptr, uint32_t value, uint32_t num);
-void memcpy(void* dst, void* src, uint32_t num);
-
-// memory alloc functions:
-void* malloc(size_t size);
-void free(void* ptr);
-
-void clear_screen();
-void init_screen();
-void print_string(const char *);
-
-// For IO ports:
-unsigned char inb(unsigned short);
-void outb(unsigned short, unsigned char);
-
-void setupIDT(void);
-void PICremap(void);
-// Assembler util functions:
-void enableinterrupts(void);
-void callint49(void);
-void doCPUID(int eax, int *ebx, int *ecx, int *edx);
-
-// Keyboard driver:
-void keyboardDriverUpdate(unsigned char scancode);
-void timerDriverUpdate(void);
-
-// Memory functions:
-void mappage(uint32_t address);
-
-int querymode(void);
-int getcs(void);
-void loadPageTable(void* tableAddress);
-void enablePaging(void);
-
-struct multiboot_aout_symbol_table {
-  uint32_t tabsize;
-  uint32_t strsize, addr, reserved;
-};
-
-struct multiboot_info {
-  uint32_t flags; // Multiboot flags / version
-  uint32_t mem_lower; // available memory from BIOS
-  uint32_t mem_upper;
-  uint32_t boot_device; 
-  uint32_t cmdline; // COmmand line
-  uint32_t mods_count;
-  uint32_t mods_addr;
-  union {
-   struct multiboot_aout_symbol_table aout_sym;
-  } u;
-
-  uint32_t mmap_length;
-  uint32_t mmap_addr;
-};
-
-struct memory_map {
-  uint32_t size;
-  uint32_t baselow, basehigh;
-  uint32_t lenlow, lenhigh;
-  uint32_t type;
-};
-
-typedef struct {
-  char name[32]; // Name of the console
-  unsigned char screendata[80*25]; // All chars in the console!
-} console_t;
-
-typedef struct {
-  uint32_t esp;
-  uint32_t ss;
-  uint32_t kstack;
-  uint32_t ustack;
-  uint32_t cr3;
-
-  uint32_t number;
-  uint32_t parent;
-  uint32_t owner;
-  uint32_t groups;
-  uint32_t timetorun;
-  uint32_t sleep;
-  uint32_t priority;
-  uint32_t filehandle;
-  char naam[32];
-
-  console_t *console;
-} programma_t;
-
-#endif
-
--- a/cos/include/stdarg.h	Tue Nov 15 07:35:00 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/* 
-Copyright (C) 1988 Free Software Foundation
-
-This file is part of GNU CC.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY.  No author or distributor
-accepts responsibility to anyone for the consequences of using it
-or for whether it serves any particular purpose or works at all,
-unless he says so in writing.  Refer to the GNU CC General Public
-License for full details.
-
-Everyone is granted permission to copy, modify and redistribute
-GNU CC, but only under the conditions described in the
-GNU CC General Public License.   A copy of this license is
-supposed to have been given to you along with GNU CC so you
-can know your rights and responsibilities.  It should be in a
-file named COPYING.  Among other things, the copyright notice
-and this notice must be preserved on all copies.  
-*/
-
-#ifndef __stdarg_h
-#define __stdarg_h
-
-typedef char *va_list;
-
-// In a 64 bits kernel we are using 64 bits pointers:
-#define STACKITEM long
-
-/* Amount of space required in an argument list for an arg of type TYPE.
-   TYPE may alternatively be an expression whose type is used.  */
-
-#define __va_rounded_size(TYPE)  \
-  (((sizeof (TYPE) + sizeof (STACKITEM) - 1) / sizeof (STACKITEM)) * sizeof (STACKITEM))
-
-#define va_start(AP, LASTARG) \
- (AP = ((char *) &(LASTARG) + __va_rounded_size(LASTARG)))
-
-#define va_end(AP) /* Nothing */
-
-#define va_arg(AP, TYPE) (AP += __va_rounded_size (TYPE), \
-  *((TYPE *) (AP - __va_rounded_size (TYPE))))
-
-#endif /* __stdarg_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cos/kernel/asmcode.asm	Fri Nov 18 14:41:53 2011 +0100
@@ -0,0 +1,76 @@
+; The default interrupt handlers.
+; from 20 - 31 are reserved vectors.
+; below are the custom ones!
+
+section .text
+align 4
+
+; Port helpers:
+global outb
+outb:
+  mov eax, [esp + 8]
+  mov edx, [esp + 4]
+  out dx, al
+  ret
+
+global inb
+inb:
+  xor eax, eax
+  mov edx, [esp + 4]
+  in al, dx
+  ret
+
+; Helper functions:
+global enableinterrupts
+enableinterrupts:
+  sti
+  ret
+
+global halt
+halt:
+  cli
+  hlt
+
+global loadIDT
+loadIDT:
+  ret
+
+; Define macro with two arguments:
+%macro INTX 2
+global %1
+%1:
+ ; Do some saving:
+extern %2
+     call %2
+ ; Do restoration
+     iret
+
+%endmacro
+
+; Exception handlers:
+INTX INTDEF, INTDEF_handler
+INTX INT0, INT0handler
+INTX INT1, INT1handler
+INTX INT2, INT2handler
+INTX INT3, INT3handler
+INTX INT4, INT4handler
+INTX INT5, INT5handler
+INTX INT6, INT6handler
+INTX INT7, INT7handler
+INTX INT8, INT8handler
+INTX INT9, INT9handler
+INTX INT10, INT10handler
+INTX INT11, INT11handler
+INTX INT12, INT12handler
+INTX INT13, INT13handler
+INTX INT14, INT14handler
+INTX INT15, INT15handler
+INTX INT16, INT16handler
+INTX INT17, INT17handler
+INTX INT18, INT18handler
+INTX INT19, INT19handler
+
+INTX INT32, INT32handler
+INTX INT33, INT33handler
+INTX INT34, INT34handler
+
--- a/cos/kernel/goto64.asm	Tue Nov 15 07:35:00 2011 +0100
+++ b/cos/kernel/goto64.asm	Fri Nov 18 14:41:53 2011 +0100
@@ -145,7 +145,7 @@
 stackEnd:
 
 einde:
-XCHG BX, BX ; bochs breakpoint
+# XCHG BX, BX ; bochs breakpoint
 
 # Call kernel:
 extern kmain
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cos/kernel/handlers.c	Fri Nov 18 14:41:53 2011 +0100
@@ -0,0 +1,296 @@
+#include "kernel.h"
+
+void panic(char *msg) {
+  printf("Kernel panic: ");
+  printf(msg);
+  halt();
+}
+
+// Assembler wrapper prototypes:
+void INTDEF(void);
+void INT0(void);
+void INT1(void);
+void INT2(void);
+void INT3(void);
+void INT4(void);
+void INT5(void);
+void INT6(void);
+void INT7(void);
+void INT8(void);
+void INT9(void);
+void INT10(void);
+void INT11(void);
+void INT12(void);
+void INT13(void);
+void INT14(void);
+void INT15(void);
+void INT16(void);
+void INT17(void);
+void INT18(void);
+void INT19(void);
+// Remapped handlers:
+void INT32(void);
+void INT33(void);
+void INT34(void);
+
+// THE interrupt descriptor table:
+static struct IDT_entry idt[256];
+
+void setIDTentry(int num, void (*handler)())
+{
+  // Fill one entry with IDT info:
+  uint64_t offset;
+  unsigned short selector = 0x8; // Code selector
+  unsigned char type = 0x8E; // 32 bits interrupt gate. Thingy is present 
+
+  offset = (uint64_t) handler;
+
+  idt[num].b[0] = offset & 0xFF;
+  idt[num].b[1] = (offset >> 8) & 0xFF;
+  idt[num].b[2] = selector & 0xFF;
+  idt[num].b[3] = (selector >> 8) & 0xFF;
+  idt[num].b[4] = 0; // reserved
+  idt[num].b[5] = type;
+  idt[num].b[6] = (offset >> 16) & 0xFF;
+  idt[num].b[7] = (offset >> 24) & 0xFF;
+}
+
+void setupIDT(void) {
+  int i;
+  // Fill all vectors with the default handler:
+  for (i=0; i<256; i++) {
+    setIDTentry(i, &INTDEF);
+  }
+
+  // Now set other then default handler:
+  setIDTentry(0, INT0);
+  setIDTentry(1, INT1);
+  setIDTentry(2, INT2);
+  setIDTentry(3, INT3);
+  setIDTentry(4, INT4);
+  setIDTentry(5, INT5);
+  setIDTentry(6, INT6);
+  setIDTentry(7, INT7);
+  setIDTentry(8, INT8);
+  setIDTentry(9, INT9);
+  setIDTentry(10, INT10);
+  setIDTentry(11, INT11);
+  setIDTentry(12, INT12);
+  setIDTentry(13, INT13);
+  setIDTentry(14, INT14);
+  setIDTentry(15, INT15);
+  setIDTentry(16, INT16);
+  setIDTentry(17, INT17);
+  setIDTentry(18, INT18);
+  setIDTentry(19, INT19);
+  /* reserved interrupts: */
+  // From int20 - int31
+  setIDTentry(32, INT32);
+  setIDTentry(33, INT33);
+  setIDTentry(34, INT34);
+
+  // call load IDT asm function:
+  loadIDT(idt, 256*8-1);
+
+  PICremap();
+  enableinterrupts();
+}
+
+// PIC functions:
+void PICremap() {
+  unsigned char maskmaster, maskslave, pic1, pic2;
+  pic1 = 0x20; // remapping location master
+  pic2 = 0x28;
+  maskmaster = inb(0x21); // master cmd=0x20, data=0x21
+  maskslave = inb(0xA1); // slave command=0xA0, data=0xA1
+
+  outb(0x20, 0x20); // end of init
+
+  outb(0x20, 0x11); // init + ICW1_ICW2
+  outb(0xA0, 0x11); // init + ICW1_ICW2
+    
+  outb(0x21, pic1); // ICW2, write offset
+  outb(0xA1, pic2); // ICW2
+
+  outb(0x21, 4); // ICW3, write a 4!
+  outb(0xA1, 2); // ICW3, write a 2!
+
+  outb(0x21, 1); // ICW4, 8086 mode
+  outb(0xA1, 1); // ICW4
+
+  outb(0x21, maskmaster);
+  outb(0xA1, maskslave);
+}
+
+// Interrupt service routines:
+
+void INT0handler() 
+{
+  printf("INT0 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT1handler() 
+{
+  printf("INT1 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT2handler() 
+{
+  printf("INT2 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT3handler() 
+{
+  printf("INT3 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT4handler() 
+{
+  printf("INT4 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT5handler() 
+{
+  printf("INT5 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT6handler() 
+{
+  printf("INT6 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT7handler() 
+{
+  printf("INT7 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT8handler() 
+{
+  printf("INT8 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT9handler() 
+{
+  printf("INT9 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT10handler() 
+{
+  printf("INT10 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT11handler() 
+{
+  printf("INT11 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT12handler() 
+{
+  printf("INT12 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT13handler() 
+{
+  printf("INT13 called!\n");
+  panic("Unhandled exception!");
+}
+
+void* getUnusedPage() {
+ return 0;
+
+}
+
+void mappage(uint32_t address) {
+  uint32_t pageDirIndex = address >> 22;
+  uint32_t pageTableIndex = (address >> 12) & 0x3FF;
+
+  printf("Allocating page at %d, tableindex=%d\n", pageDirIndex, pageTableIndex);
+  //uint32_t *pageTable = (uint32_t*)(pageDirectory[pageDirIndex] & 0xFFFFFC00);
+ 
+
+}
+
+void INT14handler(unsigned int address) 
+{
+  printf("INT14 called! Page fault for address 0x%x!\n", address);
+  if ( (address & 0xF0000000) == 0xD0000000 ) {
+    mappage(address & 0xFFFFF000);
+    return;
+  }
+
+  panic("Unhandled exception!");
+}
+
+void INT15handler() 
+{
+  printf("INT15 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT16handler() 
+{
+  printf("INT16 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT17handler() 
+{
+  printf("INT17 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT18handler() 
+{
+  printf("INT18 called!\n");
+  panic("Unhandled exception!");
+}
+
+void INT19handler() 
+{
+  printf("INT19 called!\n");
+  panic("Unhandled exception!");
+}
+
+// remapped IRQ from master PIC:
+void INT32handler() 
+{
+  // System timer.
+  //printf("INT32 called!\n");
+  // called very frequent, what is this?
+  timerDriverUpdate();
+  outb(0x20, 0x20); // EOI to master
+}
+
+void INT33handler() 
+{
+  //printf("INT33 called, key pressed????\n");
+  unsigned char scancode = inb(0x60);
+  //printf("Scancode = 0x%x\n", scancode);
+  keyboardDriverUpdate(scancode);
+  outb(0x20, 0x20); // EOI to master
+}
+
+void INT34handler() 
+{
+  printf("INT34 called!\n");
+}
+
+void INTDEF_handler() 
+{
+  printf("Default int handler called\n");
+}
+
+
--- a/cos/kernel/kernel.c	Tue Nov 15 07:35:00 2011 +0100
+++ b/cos/kernel/kernel.c	Fri Nov 18 14:41:53 2011 +0100
@@ -129,6 +129,9 @@
   clear_screen();
   printf("Welcome!\n");
   printf("sizeof(uint32_t)=%u, sizeof(uint64_t)=%u\n", sizeof(uint32_t), sizeof(uint64_t));
+
+  printf("Enabling interrupts\n");
+  setupIDT();
   printf("Entering mainloop!\n");
 
   while (1==1) 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cos/kernel/kernel.h	Fri Nov 18 14:41:53 2011 +0100
@@ -0,0 +1,121 @@
+#ifndef KERNEL_H
+#define KERNEL_H
+
+// Include common functions, available to all!
+#define NULL ((void*)0)
+
+// Type defs:
+typedef unsigned int        uint32_t;
+typedef unsigned long long  uint64_t;
+typedef unsigned short      ushort_t;
+typedef unsigned char       uchar_t;
+typedef unsigned int        uint_t;
+typedef unsigned long       ulong_t;
+typedef unsigned long long  ulonglong_t;
+typedef unsigned long       off_t;
+typedef unsigned long       size_t;
+
+void printf(const char* fmt, ... );
+void memset(void* ptr, uint32_t value, uint32_t num);
+void memcpy(void* dst, void* src, uint32_t num);
+
+struct IDT_entry {
+  unsigned char b[8];
+};
+
+// memory alloc functions:
+void* malloc(size_t size);
+void free(void* ptr);
+
+void clear_screen();
+void init_screen();
+void print_string(const char *);
+
+// For IO ports:
+unsigned char inb(unsigned short);
+void outb(unsigned short, unsigned char);
+
+// ASM helper:
+int loadIDT(struct IDT_entry *table, unsigned short size);
+void halt(void);
+
+void setupIDT(void);
+void PICremap(void);
+// Assembler util functions:
+void enableinterrupts(void);
+void callint49(void);
+void doCPUID(int eax, int *ebx, int *ecx, int *edx);
+
+// Keyboard driver:
+void keyboardDriverUpdate(unsigned char scancode);
+void timerDriverUpdate(void);
+
+// Memory functions:
+void mappage(uint32_t address);
+
+int querymode(void);
+int getcs(void);
+void loadPageTable(void* tableAddress);
+void enablePaging(void);
+
+// Variable argument list things:
+#define va_start(v,l)	__builtin_va_start(v,l)
+#define va_end(v)	__builtin_va_end(v)
+#define va_arg(v,l)	__builtin_va_arg(v,l)
+typedef __builtin_va_list va_list;
+
+struct multiboot_aout_symbol_table {
+  uint32_t tabsize;
+  uint32_t strsize, addr, reserved;
+};
+
+struct multiboot_info {
+  uint32_t flags; // Multiboot flags / version
+  uint32_t mem_lower; // available memory from BIOS
+  uint32_t mem_upper;
+  uint32_t boot_device; 
+  uint32_t cmdline; // COmmand line
+  uint32_t mods_count;
+  uint32_t mods_addr;
+  union {
+   struct multiboot_aout_symbol_table aout_sym;
+  } u;
+
+  uint32_t mmap_length;
+  uint32_t mmap_addr;
+};
+
+struct memory_map {
+  uint32_t size;
+  uint32_t baselow, basehigh;
+  uint32_t lenlow, lenhigh;
+  uint32_t type;
+};
+
+typedef struct {
+  char name[32]; // Name of the console
+  unsigned char screendata[80*25]; // All chars in the console!
+} console_t;
+
+typedef struct {
+  uint32_t esp;
+  uint32_t ss;
+  uint32_t kstack;
+  uint32_t ustack;
+  uint32_t cr3;
+
+  uint32_t number;
+  uint32_t parent;
+  uint32_t owner;
+  uint32_t groups;
+  uint32_t timetorun;
+  uint32_t sleep;
+  uint32_t priority;
+  uint32_t filehandle;
+  char naam[32];
+
+  console_t *console;
+} programma_t;
+
+#endif
+
--- a/cos/kernel/snprintf.c	Tue Nov 15 07:35:00 2011 +0100
+++ b/cos/kernel/snprintf.c	Fri Nov 18 14:41:53 2011 +0100
@@ -3,8 +3,20 @@
  */
 #include "kernel.h"
 
-#include "stdarg.h"
-#include "ctype.h"
+/*
+ * NOTE! This ctype does not handle EOF like the standard C
+ * library is required to.
+ */
+
+#define _U	0x01	/* upper */
+#define _L	0x02	/* lower */
+#define _D	0x04	/* digit */
+#define _C	0x08	/* cntrl */
+#define _P	0x10	/* punct */
+#define _S	0x20	/* white space (space/lf/tab) */
+#define _X	0x40	/* hex digit */
+#define _SP	0x80	/* hard space (0x20) */
+
 
 unsigned char _ctype[] = {
 _C,_C,_C,_C,_C,_C,_C,_C,			/* 0-7 */
@@ -32,6 +44,36 @@
 _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
 _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
 
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c)	((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c)	((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c)	((__ismask(c)&(_C)) != 0)
+#define isdigit(c)	((__ismask(c)&(_D)) != 0)
+#define isgraph(c)	((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c)	((__ismask(c)&(_L)) != 0)
+#define isprint(c)	((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c)	((__ismask(c)&(_P)) != 0)
+#define isspace(c)	((__ismask(c)&(_S)) != 0)
+#define isupper(c)	((__ismask(c)&(_U)) != 0)
+#define isxdigit(c)	((__ismask(c)&(_D|_X)) != 0)
+
+#define isascii(c) (((unsigned char)(c))<=0x7f)
+#define toascii(c) (((unsigned char)(c))&0x7f)
+
+static inline unsigned char tolower(unsigned char c)
+{
+	if (isupper(c))
+		c -= 'A'-'a';
+	return c;
+}
+
+static inline unsigned char toupper(unsigned char c)
+{
+	if (islower(c))
+		c -= 'a'-'A';
+	return c;
+}
 
 #define MORE_THAN_YOU_WANT	1<<30
 #define MAX_STDOUT_CHARS	255
@@ -86,7 +128,7 @@
          break;
 
           case 'c':		/* single character */
-         *b++ = va_arg(pvar, char);
+         *b++ = 'x'; // TODO: va_arg(pvar, char);
          l--;
          break;