mirror of
https://github.com/elliotnunn/wedge.git
synced 2024-11-21 16:30:48 +00:00
95df455703
The Wedge is a C program that, when inserted into a PowerPC ROM, runs just before the NanoKernel. This is very early in the boot process. The Wedge takes this opportunity to rearrange the MacOS address space and make more than 1.5 GB RAM available to applications. Some serious problems remain with this approach, so a "proper" solution to the 1.5 GB RAM limit will take more work. This code was ripped out of the old CDG5 build system and refactored. It it more appropriate to keep the Wedge separate from the real OS code.
211 lines
3.7 KiB
C
211 lines
3.7 KiB
C
/*
|
|
File: printf.c
|
|
|
|
Copyright (C) 2004 Kustaa Nyholm
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
#include "printf.h"
|
|
|
|
typedef void (*putcf) (void*,char);
|
|
void asm_putc (char);
|
|
|
|
|
|
#ifdef PRINTF_LONG_SUPPORT
|
|
|
|
static void uli2a(unsigned long int num, unsigned int base, int uc,char * bf)
|
|
{
|
|
int n=0;
|
|
unsigned int d=1;
|
|
while (num/d >= base)
|
|
d*=base;
|
|
while (d!=0) {
|
|
int dgt = num / d;
|
|
num%=d;
|
|
d/=base;
|
|
if (n || dgt>0|| d==0) {
|
|
*bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
|
|
++n;
|
|
}
|
|
}
|
|
*bf=0;
|
|
}
|
|
|
|
static void li2a (long num, char * bf)
|
|
{
|
|
if (num<0) {
|
|
num=-num;
|
|
*bf++ = '-';
|
|
}
|
|
uli2a(num,10,0,bf);
|
|
}
|
|
|
|
#endif
|
|
|
|
static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
|
|
{
|
|
int n=0;
|
|
unsigned int d=1;
|
|
while (num/d >= base)
|
|
d*=base;
|
|
while (d!=0) {
|
|
int dgt = num / d;
|
|
num%= d;
|
|
d/=base;
|
|
if (n || dgt>0 || d==0) {
|
|
*bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
|
|
++n;
|
|
}
|
|
}
|
|
*bf=0;
|
|
}
|
|
|
|
static void i2a (int num, char * bf)
|
|
{
|
|
if (num<0) {
|
|
num=-num;
|
|
*bf++ = '-';
|
|
}
|
|
ui2a(num,10,0,bf);
|
|
}
|
|
|
|
static int a2d(char ch)
|
|
{
|
|
if (ch>='0' && ch<='9')
|
|
return ch-'0';
|
|
else if (ch>='a' && ch<='f')
|
|
return ch-'a'+10;
|
|
else if (ch>='A' && ch<='F')
|
|
return ch-'A'+10;
|
|
else return -1;
|
|
}
|
|
|
|
static char a2i(char ch, char** src,int base,int* nump)
|
|
{
|
|
char* p= *src;
|
|
int num=0;
|
|
int digit;
|
|
while ((digit=a2d(ch))>=0) {
|
|
if (digit>base) break;
|
|
num=num*base+digit;
|
|
ch=*p++;
|
|
}
|
|
*src=p;
|
|
*nump=num;
|
|
return ch;
|
|
}
|
|
|
|
static void putchw(int n, char z, char* bf)
|
|
{
|
|
char fc=z? '0' : ' ';
|
|
char ch;
|
|
char* p=bf;
|
|
while (*p++ && n > 0)
|
|
n--;
|
|
while (n-- > 0)
|
|
asm_putc(fc);
|
|
while ((ch= *bf++))
|
|
asm_putc(ch);
|
|
}
|
|
|
|
void tfp_format(char *fmt, va_list va)
|
|
{
|
|
char bf[12];
|
|
|
|
char ch;
|
|
|
|
|
|
while ((ch=*(fmt++))) {
|
|
if (ch!='%')
|
|
asm_putc(ch);
|
|
else {
|
|
char lz=0;
|
|
#ifdef PRINTF_LONG_SUPPORT
|
|
char lng=0;
|
|
#endif
|
|
int w=0;
|
|
ch=*(fmt++);
|
|
if (ch=='0') {
|
|
ch=*(fmt++);
|
|
lz=1;
|
|
}
|
|
if (ch>='0' && ch<='9') {
|
|
ch=a2i(ch,&fmt,10,&w);
|
|
}
|
|
#ifdef PRINTF_LONG_SUPPORT
|
|
if (ch=='l') {
|
|
ch=*(fmt++);
|
|
lng=1;
|
|
}
|
|
#endif
|
|
switch (ch) {
|
|
case 0:
|
|
goto abort;
|
|
case 'u' : {
|
|
#ifdef PRINTF_LONG_SUPPORT
|
|
if (lng)
|
|
uli2a(va_arg(va, unsigned long int),10,0,bf);
|
|
else
|
|
#endif
|
|
ui2a(va_arg(va, unsigned int),10,0,bf);
|
|
putchw(w,lz,bf);
|
|
break;
|
|
}
|
|
case 'd' : {
|
|
#ifdef PRINTF_LONG_SUPPORT
|
|
if (lng)
|
|
li2a(va_arg(va, unsigned long int),bf);
|
|
else
|
|
#endif
|
|
i2a(va_arg(va, int),bf);
|
|
putchw(w,lz,bf);
|
|
break;
|
|
}
|
|
case 'x': case 'X' :
|
|
#ifdef PRINTF_LONG_SUPPORT
|
|
if (lng)
|
|
uli2a(va_arg(va, unsigned long int),16,(ch=='X'),bf);
|
|
else
|
|
#endif
|
|
ui2a(va_arg(va, unsigned int),16,(ch=='X'),bf);
|
|
putchw(w,lz,bf);
|
|
break;
|
|
case 'c' :
|
|
asm_putc((char)(va_arg(va, int)));
|
|
break;
|
|
case 's' :
|
|
putchw(w,0,va_arg(va, char*));
|
|
break;
|
|
case '%' :
|
|
asm_putc(ch);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
abort:;
|
|
}
|
|
|
|
|
|
extern void printf(char *fmt, ...)
|
|
{
|
|
va_list va;
|
|
va_start(va,fmt);
|
|
tfp_format(fmt,va);
|
|
va_end(va);
|
|
}
|