lr/sprint.c

187 lines
2.7 KiB
C

#include<stdio.h>
#include<stdbool.h>
#include<unistd.h>
#include<stdint.h>
#define __rbp(x) asm("movq %%rbp,%0":"=m"(x))
#define __rdi(x) asm("movq %%rdi,%0":"=m"(x))
#define __rsi(x) asm("movq %%rsi,%0":"=m"(x))
#define __rdx(x) asm("movq %%rdx,%0":"=m"(x))
#define __rcx(x) asm("movq %%rcx,%0":"=m"(x))
#define __r8(x) asm("movq %%r8,%0":"=m"(x))
#define __r9(x) asm("movq %%r9,%0":"=m"(x))
static int sprinti(char*s,int d);
static int sprinti16(char*s,int d);
typedef union sprint_type {int64_t i64;int32_t i32;char c;char*s;}sprint_type;
// Print formatted string with variable number
// of arguments into destination string dest
int sprint(char*dest,char*fmt,...)
{
bool special=false;
int bpos=0;
int curarg=2;
sprint_type args[6];
sprint_type rdi,rsi,rdx,rcx,r8,r9;
__rdi(rdi);
__rsi(rsi);
__rdx(rdx);
__rcx(rcx);
__r8(r8);
__r9(r9);
args[0]=rdi;
args[1]=rsi;
args[2]=rdx;
args[3]=rcx;
args[4]=r8;
args[5]=r9;
for(int i=0;fmt[i];++i)
{
switch(fmt[i])
{
case '%':
if(special)
{
dest[bpos++]=fmt[i];
special=false;
}
else
special=true;
break;
default:
if(special)
{
switch(fmt[i])
{
case 'd':
case 'i':
case 'u':
{
char tmp[1024];
int n;
n=sprinti(tmp,args[curarg++].i32);
for(int k=0;tmp[k]&&k<=n;++k)
dest[bpos++]=tmp[k];
}
break;
case 'x':
case 'p':
{
char tmp[1024];
int n;
n=sprinti16(tmp,args[curarg++].i32);
for(int k=0;tmp[k]&&k<=n;++k)
dest[bpos++]=tmp[k];
}
break;
case 's':
{
for(int k=0;args[curarg].s[k];++k)
dest[bpos++]=args[curarg].s[k];
++curarg;
}
break;
case 'c':
dest[bpos++]=args[curarg++].c;
break;
}
special=false;
}
else
dest[bpos++]=fmt[i];
break;
}
}
dest[bpos]=0;
return bpos;
}
static int sprinti16(char*s,int d)
{
static char g[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
char b[32]={0};
int bp=0;
int i=0;
if(!s)return 0;
if(d<0)
{
b[bp++]='-';
d=-d;
}
// Get each digit as character
while(d>0)
{
int m=d%16;
d/=16;
b[i++]=g[m];
}
b[i]=0;
int max=i-1;
// Print reversed string
for(;i>=0;--i)
{
if(b[i]>31)
s[max-i]=b[i];
}
s[max+1]=0;
return max;
}
static int sprinti(char*s,int d)
{
char b[32]={0};
int bp=0;
int i=0;
if(!s)return 0;
if(d<0)
{
b[bp++]='-';
d=-d;
}
// Get each digit as character
while(d>0)
{
int m=d%10;
d/=10;
if(m+'0'>31)
b[i++]=m+'0';
}
b[i]=0;
int max=i-1;
// Print reversed string
for(;i>=0;--i)
{
if(b[i]>31)
s[max-i]=b[i];
}
s[max+1]=0;
return max;
}