linux sendosinfo服务,linux操作系统学习实践 ---vsprintf.c

#include #define DEFAULT_COLOR    0x07

#define    MAX_LINES    24

#define MAX_COLS    80

/*

* this value should be probed. but in bochs, seems that the defualt display mode

* is absolutely not the 7th display mode. add probing codes if you want to make sure

*/

#define VIDEO_START    ((char *)0xb8000)

#define VIDEO_PORT    0x3d4

#define ORIG_X            (*(unsigned char *)0x90000)

#define ORIG_Y            (*(unsigned char *)0x90001)

#define VIDEO_MODE     (*(unsigned char *)0x90002)

static char *video_mem;

static char *cur_video_mem;

static unsigned short original_x;

static unsigned short original_y;

static unsigned char video_mode;

static int lines;

static int cols;

void putstr_init(void)

{

video_mem = VIDEO_START;

original_x = ORIG_X;

original_y = ORIG_Y;

lines = MAX_LINES;

cols = MAX_COLS;

video_mode = VIDEO_MODE;

cur_video_mem = video_mem + original_x * 2 + original_y * 80 * 2;

}

/* to make this much faster, directly handle the registers. don't need to get that far */

static void scroll_down(void)

{

int i = cols;

memncpy(video_mem, video_mem + cols * 2, (lines - 1) * cols * 2);

i = cur_video_mem - video_mem - (lines - 1) * cols * 2;

i >>= 1;

while(i-- > 0) {

cur_video_mem -= 2;

*cur_video_mem = 0;

}

}

void __putstr(const char *str)

{

int x = original_x;

int y = original_y;

int pos;

char c;

while((c = *str++) != '\0')

{

if(c == '\n')

{

if(++y >= lines) {

scroll_down();

y--;

//cur_video_mem -= cols * 2;

} else {

cur_video_mem += (cols - x) * 2;

}

x = 0;

}

else

{

if(++x >= cols)

{

x = 0;

if(++y >= lines)

{

scroll_down();

y--;

//cur_video_mem -= cols * 2;

}

}

*cur_video_mem++ = c;

cur_video_mem++ ;//= x & 0xff ; //= DEFAULT_COLOR;

}

}

if(cur_video_mem > 0xa0000 + 64000)

cur_video_mem = 0xa0000;

pos = (x + cols * y) * 2;

outb_p(14, VIDEO_PORT);

outb_p(0xff & (pos >> 9), VIDEO_PORT + 1);

outb_p(15, VIDEO_PORT);

outb_p(0xff & (pos >> 1), VIDEO_PORT + 1);

/*

original_x = x;

original_y = y;

*/

}

/*

* it's a stupid way. But i don't want to work on the other alternative right now

* this mean if we call putstr from user mode, Then we have trap into kernel mode to do this.

* because the call scroll_down is rather time consuming.when doing

*/

void putstr(const char *str)

{

cli();

__putstr(str);

sti();

}

__syscall1(void, stupid_putstr, const char *, str)

/* you can tell by the name */

void sys_stupid_putstr(const char *str)

{

cli();

__putstr(str);

sti();

}

#define SIGN 1

#define SMALL 2

#define PREFIX 4

/* cause we're totally on our own, we can't use "%" */

#define do_div(n,base) ({ \

int __res; \

__res = ((unsigned long) n) % (unsigned) base; \

n = ((unsigned long) n) / (unsigned) base; \

__res; })

static inline char *num2str(char *str, long num, int base, int fildwidth, \

int precision, int flags)

{

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

char tmp[64];

int i=0;

if(flags & SIGN)

*str++ = '-';

if(flags & PREFIX) {

*str++ = '0';

if(base == 16)

*str++ = 'x';

}

if(num == 0)

tmp[i++] = '0';

else

while(num != 0)

tmp[i++] = digit[do_div(num, base)];

while(--i >= 0)

*str++ = tmp[i];

return str;

}

/* much more work should be done on this */

int vsprintf(char *buf, const char *fmt, va_list args)

{

char *str, *s;

int base;

int flags = 0;

int fildwidth = -1;

int precision = -1;

int qualifier;

unsigned long num;

for(str = buf; *fmt != '\0'; fmt++) {

if(*fmt == '\t') {

int k = 8;

while(k--)

*str++ = ' ';

fmt++;

}

if(*fmt != '%') {

*str++ = *fmt;

continue;

}

handle_flags:

fmt++;

switch (*fmt) {

case '#':

flags |= PREFIX;

goto handle_flags;

}

/* handle_fldwidth: */

/* don't need this now */

/* handle_precision: */

/* don't need this now */

/* handle_lenmodifier: */

/* don't need this now */

/* handle_qualifier: */

qualifier = -1;

if(*fmt == 'l' || *fmt == 'L' || *fmt == 'h') {

qualifier = *fmt;

fmt++;

}

/* handle_convtype: */

base = 10;

switch(*fmt) {

case 'c':

/* processing alignment */

*str = (unsigned char)va_arg(args, int);

/* processing alignment */

continue;

case 's':

s = va_arg(args, char *);

str = strcpy(str, s);         /* is it safe? */

str--;

continue;

case 'd':

break;

case 'o':

base = 8;

break;

case 'x':

flags |= SMALL;

case 'X':

base = 16;

break;

default:

*str++ = '%';

if(*fmt)

*str++ = *fmt;

else

fmt--;

continue;

}

if (qualifier == 'l')

num = va_arg(args, unsigned long);

else if (qualifier == 'h')

num = (unsigned short)va_arg(args, int);

else {

num = va_arg(args, int);

}

str = num2str(str, num, base, fildwidth, precision, flags);

}

*str = '\0';

return str - buf;

}

/* to versions, one can be called in kernel mode, the other one from user mode */

int printf(const char *fmt, ...)

{

char buf[1024];

va_list args;

int cnt;

va_start(args, fmt);

cnt = vsprintf(buf, fmt, args);

va_end(args);

putstr(buf);

return cnt;

}

printf_user(const char *fmt, ...)

{

char buf[1024];

va_list args;

int cnt;

va_start(args, fmt);

cnt = vsprintf(buf, fmt, args);

va_end(args);

stupid_putstr(buf);

return cnt;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值