1
Name:
Anonymous
2012-09-05 16:00
I'm currently writing a C standard library for academic purposes, and I wondered how to implement stdarg.h (the va_* macros) in C (probably with inline ASM) and if this was the libc's work, or the compiler's ?
Thanks in advance.
4
Name:
Anonymous
2012-09-06 2:18
Sometime ago I wrote a simple OS and it just used macros from stdarg.h
so you never need to touch them.
#define VIDEO_WIDTH 80
#define VIDEO_HEIGHT 25
#define VIDEO_RAM 0xb8000
#include <stdarg.h>
#include "tty.h"
int tty_cursor;
int tty_attribute;
void init_tty() {
tty_cursor = 0;
tty_attribute = 10;
}
static int textcolor(int c) {
tty_attribute = c;
}
void clear_screen() {
char *video = (char*) VIDEO_RAM;
int i;
for (i = 0; i < VIDEO_HEIGHT*VIDEO_WIDTH; i++) {
*(video + i*2) = ' ';
}
tty_cursor = 0;
}
void putchar(char c) {
char *video = (char*) VIDEO_RAM;
int i;
switch (c) {
case '\n':
tty_cursor+=VIDEO_WIDTH;
tty_cursor-=tty_cursor%VIDEO_WIDTH;
break;
default:
*(video + tty_cursor*2) = c;
*(video + tty_cursor*2+1) = tty_attribute;
tty_cursor++;
break;
}
// do we need to shift screen horizontally?
if (tty_cursor>VIDEO_WIDTH*VIDEO_HEIGHT) {
for (i=VIDEO_WIDTH*2;i<=VIDEO_WIDTH*VIDEO_HEIGHT*2+VIDEO_WIDTH*2;i++) {
*(video+i-VIDEO_WIDTH*2)=*(video+i);
}
tty_cursor-=VIDEO_WIDTH;
}
}
static void reverse(char *s) {
char *p = s;
while(*p) p++;
while(s < --p) {
int t = *s;
*s++ = *p;
*p = t;
}
}
static char *puthex_digit(char *b, unsigned char digit) {
char table[]="0123456789ABCDEF";
*b++ = table[digit];
return b;
}
static char *puthex_tetra(char *b, unsigned char byte) {
b = puthex_digit(b, byte >> 4);
b = puthex_digit(b, byte & 0x0F);
return b;
}
static char *puthex(char *b, unsigned int dword) {
b = puthex_tetra(b, (dword & 0xFF000000) >>24 );
b = puthex_tetra(b, (dword & 0x00FF0000) >>16 );
b = puthex_tetra(b, (dword & 0x0000FF00) >>8 );
b = puthex_tetra(b, (dword & 0x000000FF));
return b;
}
static char *int2string(char *b, int v, int base, int unsign) {
char *p = b;
unsigned int x;
int sign = 0;
if(v < 0 && !unsign) {
sign = 1;
x = -v;
*p++ = '-';
} else {
if(v < 0) x = -v;
else x = v;
}
do {
unsigned int c = x % base;
x /= base;
if(c < 10) c += '0';
else {
c -= 10;
c += 'A';
}
*p++ = c;
} while(x);
*p = 0;
reverse(b+sign);
return p;
}
static void vsprintf_helper(char *b, const char *fmt, va_list args) {
for( ; *fmt; fmt++) {
if(*fmt != '%') {
putchar(*fmt);
continue;
}
fmt++;
switch (*fmt) {
case 's': {
char *p = va_arg(args, char *);
while(*b++ = *p++);
b--;
break;}
case 'c':
*b++ = va_arg(args, unsigned int);
break;
case 'i': case 'd':
b = int2string(b, va_arg(args, unsigned int), 10, 0);
break;
case 'u':
b = int2string(b, va_arg(args, unsigned int), 10, 1);
case 'x': case 'X':
b = puthex(b, va_arg(args, unsigned int));
break;
case 'z':
textcolor(va_arg(args,unsigned int));
break;
}
}
*b = 0;
}
void puts(const char *s) {
while(*s) putchar(*s++);
}
void vsprintf(char *b, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vsprintf_helper(b, fmt, args);
va_end(args);
}
void printf(const char *fmt, ...) {
char b[512];
va_list args;
va_start(args, fmt);
textcolor(0xf);
vsprintf_helper(b, fmt, args);
va_end(args);
puts(b);
}