/*
 * lib.c
 *
 * Copyright 2002, Minoru Murashima. All rights reserved.
 * Distributed under the terms of the BSD License.
 *
 * カーネルライブラリー
 */


#include"types.h"
#include"config.h"
#include"lib.h"
#include"time.h"
#include"console.h"
#include"mm.h"


int (*write_tty)(const char*,size_t);


/*
 * 画面出力関数
 * 引数 : 文字列(%d,%x,%s対応)、値...
 */
void printk(const char *str,...)
{

	enum{BUF_SIZE=16};

	char buf[BUF_SIZE];
	uint *arg;
	uint value;
	int i,j,begin;


	arg=(uint*)&str+1;

	for(i=begin=0;str[i]!='\0';++i)
	{
		if(str[i]=='%')
		{
			write_tty(&str[begin],i-begin);

			switch(str[++i])
			{
				case 'd':							/* 整数に変換 */
					value=*arg++;
					for(j=BUF_SIZE-1;;--j)
					{
						buf[j]=value%10+'0';
						if(!(value/=10))break;
					}
					write_tty(&buf[j],BUF_SIZE-j);
					break;
				case 'x':							/* 16進数に変換 */
					value=*arg++;
					for(j=BUF_SIZE-1;;--j)
					{
						buf[j]=value%16+'0';
						if(buf[j]>'9')buf[j]+='a'-'9'-1;
						if(!(value/=16))break;
					}
					write_tty(&buf[j],BUF_SIZE-j);
					break;
				case 's':							/* 文字列を表示 */
					write_tty((char*)*arg,strlen((char*)*arg));
					++arg;
					break;
				case '%':
					write_tty("%",1);
					break;
				default:
					write_tty("%",1);
					--i;
			}
			begin=i+1;
		}
		else if(str[i]=='\n')
		{
			write_tty(&str[begin],i-begin);
			write_tty("\n\r",2);
			begin=i+1;
		}
	}

	write_tty(&str[begin],i-begin);
}


/*
 * micro seccond タイマー
 * 引数 : カウント(1microseccond単位)
 */
void micro_timer(uint count)
{
	uint64 end;


	end=rdtsc();
	end+=count*clock_1micro;
	while(rdtsc()<end);
}


/*
 * mili seccond timer
 * param : value of counts(1ms)
 */
void mili_timer(uint count)
{
	uint64 end;


	end=rdtsc();
	end+=count*clock_1m;
	while(rdtsc()<end);
}


/*
 * Convert ascii to integer
 * parameters : string
 * return : integer or 0(引数が数字でない)
 */
int atoi(const char *str)
{
	int rest=0;


	for(;*str!='\0';++str)
	{
		if((*str<'0')||(*str>'9'))return 0;
		rest=rest*10+*str-'0';
	}

	return rest;
}
