XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
/* Bounded, allocation-free runtime diagnostics over XFESystem's serial API. */
#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
#include <limits.h>
extern void xfe_runtime_write(const char*,uint64_t);
extern void xfe_runtime_halt(const char*);
extern int *__errno_location(void);
extern size_t strlen(const char*);
typedef struct {int descriptor,error;} XfeFile;
static XfeFile error_stream={2,0},output_stream={1,0};
XfeFile *stderr=&error_stream,*stdout=&output_stream;
struct output {char *buffer;size_t capacity,total;};
static void emit(struct output *out,char c){if(out->capacity&&out->total<out->capacity-1)out->buffer[out->total]=c;if(out->total<SIZE_MAX)out->total++;}
static void repeat(struct output *out,char c,int n){for(int i=0;i<n;i++)emit(out,c);}
int vsnprintf(char *buffer,size_t capacity,const char *format,va_list arguments){
    if(!format||(!buffer&&capacity)){*__errno_location()=22;return -1;}
    struct output out={buffer,capacity,0};
    while(*format){
        if(*format!='%'){emit(&out,*format++);continue;}format++;
        int left=0,zero=0,plus=0,alternate=0,space=0;
        for(;;){if(*format=='-')left=1;else if(*format=='0')zero=1;else if(*format=='+')plus=1;else if(*format=='#')alternate=1;else if(*format==' ')space=1;else break;format++;}
        int width=0;if(*format=='*'){width=va_arg(arguments,int);format++;if(width<0){if(width==INT_MIN)return -1;left=1;width=-width;}}
        else while(*format>='0'&&*format<='9'){if(width>104857)return -1;width=width*10+*format++-'0';}
        int precision=-1;if(*format=='.'){format++;precision=0;if(*format=='*'){precision=va_arg(arguments,int);format++;}
            else while(*format>='0'&&*format<='9'){if(precision>104857)return -1;precision=precision*10+*format++-'0';}}
        int length=0;if(*format=='l'){format++;length=1;if(*format=='l'){format++;length=2;}}
        else if(*format=='z'||*format=='t'||*format=='j'){length=2;format++;}
        else if(*format=='h'){format++;length=-1;if(*format=='h'){format++;length=-2;}}
        char spec=*format;if(!spec){*__errno_location()=22;if(capacity)buffer[out.total<capacity?out.total:capacity-1]=0;return -1;}format++;
        if(spec=='%'){emit(&out,'%');continue;}
        if(spec=='s'){
            const char *s=va_arg(arguments,const char*);if(!s)s="(null)";
            size_t n=0;while(s[n]&&(precision<0||n<(size_t)precision))n++;
            int padding=width>(int)n?width-(int)n:0;if(!left)repeat(&out,' ',padding);
            for(size_t i=0;i<n;i++)emit(&out,s[i]);if(left)repeat(&out,' ',padding);continue;
        }
        if(spec=='c'){int c=va_arg(arguments,int);if(!left)repeat(&out,' ',width>1?width-1:0);emit(&out,(char)c);if(left)repeat(&out,' ',width>1?width-1:0);continue;}
        if(spec=='d'||spec=='i'||spec=='u'||spec=='x'||spec=='X'||spec=='o'||spec=='p'){
            uint64_t value;int negative=0;
            if(spec=='p')value=(uintptr_t)va_arg(arguments,void*);
            else if(spec=='d'||spec=='i'){
                int64_t signed_value=length>=1?va_arg(arguments,int64_t):va_arg(arguments,int);
                if(length==-1)signed_value=(int16_t)signed_value;if(length==-2)signed_value=(int8_t)signed_value;
                negative=signed_value<0;value=negative?0-(uint64_t)signed_value:(uint64_t)signed_value;
            }else{value=length>=1?va_arg(arguments,uint64_t):va_arg(arguments,unsigned);if(length==-1)value=(uint16_t)value;if(length==-2)value=(uint8_t)value;}
            unsigned base=(spec=='x'||spec=='X'||spec=='p')?16:spec=='o'?8:10;
            const char *alphabet=spec=='X'?"0123456789ABCDEF":"0123456789abcdef";
            char digits[65];int count=0;uint64_t original=value;
            if(value||precision!=0){do{digits[count++]=alphabet[value%base];value/=base;}while(value);}
            char sign=negative?'-':plus?'+':space?' ':0;if(spec!='d'&&spec!='i')sign=0;
            int prefix=(spec=='p'||(alternate&&original&&base==16))?2:(alternate&&base==8&&(count==0||digits[count-1]!='0'))?1:0;
            int leading=precision>count?precision-count:0;
            if(prefix==1 && leading)prefix=0;
            int total=count+leading+prefix+(sign!=0),padding=width>total?width-total:0;
            if(!left&&(!zero||precision>=0))repeat(&out,' ',padding);if(sign)emit(&out,sign);
            if(prefix){emit(&out,'0');if(prefix==2)emit(&out,spec=='X'?'X':'x');}
            if(!left&&zero&&precision<0)repeat(&out,'0',padding);repeat(&out,'0',leading);
            while(count)emit(&out,digits[--count]);if(left)repeat(&out,' ',padding);continue;
        }
        // Unsupported formats fail explicitly, rather than printing a made-up
        // value. Add formats only when their numeric semantics are implemented.
        * __errno_location()=22;if(capacity)buffer[out.total<capacity?out.total:capacity-1]=0;return -1;
    }
    if(capacity)buffer[out.total<capacity?out.total:capacity-1]=0;
    if(out.total>INT_MAX){*__errno_location()=75;return -1;}return (int)out.total;
}
int snprintf(char *buffer,size_t capacity,const char *format,...){va_list args;va_start(args,format);int result=vsnprintf(buffer,capacity,format,args);va_end(args);return result;}
int vfprintf(XfeFile *file,const char *format,va_list args){
    if(file!=stderr&&file!=stdout){*__errno_location()=9;return -1;}
    char buffer[4096];int count=vsnprintf(buffer,sizeof(buffer),format,args);
    if(count<0){file->error=1;return -1;}
    size_t written=(size_t)count<sizeof(buffer)?(size_t)count:sizeof(buffer)-1;
    xfe_runtime_write(buffer,written);
    if((size_t)count>=sizeof(buffer)){file->error=1;*__errno_location()=75;return -1;}return count;
}
int fprintf(XfeFile *file,const char *format,...){va_list args;va_start(args,format);int n=vfprintf(file,format,args);va_end(args);return n;}
int printf(const char *format,...){va_list args;va_start(args,format);int n=vfprintf(stdout,format,args);va_end(args);return n;}
size_t fwrite(const void *data,size_t size,size_t count,XfeFile *file){
    if(file!=stderr&&file!=stdout){*__errno_location()=9;return 0;}
    if(!size||!count)return 0;
    if(size&&count>SIZE_MAX/size){file->error=1;*__errno_location()=75;return 0;}
    size_t bytes=size*count;if(bytes>1048576){file->error=1;*__errno_location()=75;return 0;}
    xfe_runtime_write(data,bytes);return count;
}
int fflush(XfeFile *file){if(file&&file!=stderr&&file!=stdout){*__errno_location()=9;return -1;}return 0;}
int fputs(const char *text,XfeFile *file){return fwrite(text,1,strlen(text),file)==strlen(text)?0:-1;}
int puts(const char *text){if(fputs(text,stdout)<0)return -1;return fwrite("\n",1,1,stdout)==1?0:-1;}
int ferror(XfeFile *file){return file?file->error:1;}
__attribute__((noreturn)) void abort(void){xfe_runtime_halt("NATIVE_RUNTIME_ABORT");for(;;)__asm__ volatile("cli; hlt");}
__attribute__((noreturn)) void __stack_chk_fail(void){xfe_runtime_halt("NATIVE_STACK_CHECK_FAILED");for(;;)__asm__ volatile("cli; hlt");}
static void (*exit_callbacks[64])(void);static unsigned exit_count;
int atexit(void (*callback)(void)){if(!callback||exit_count==64)return -1;exit_callbacks[exit_count++]=callback;return 0;}
__attribute__((noreturn)) void exit(int code){(void)code;while(exit_count)exit_callbacks[--exit_count]();xfe_runtime_halt("NATIVE_RUNTIME_EXIT");for(;;)__asm__ volatile("cli; hlt");}
int xfe_stdio_selftest(void){
    char b[64];if(snprintf(b,sizeof(b),"%s %04x %lld %p","test",42,(long long)-9,(void*)0x1234)!=19)return 0;
    const char *expected="test 002a -9 0x1234";size_t i=0;while(expected[i]&&expected[i]==b[i])i++;if(expected[i]||b[i])return 0;
    char small[4];if(snprintf(small,sizeof(small),"%u",12345)!=5||small[0]!='1'||small[1]!='2'||small[2]!='3'||small[3]!=0)return 0;
    if(snprintf(b,sizeof(b),"%+d %.0u %#x",7,0,255)!=8)return 0;
    if(snprintf(b,sizeof(b),"%#.3o",1)!=3||b[0]!='0'||b[1]!='0'||b[2]!='1'||b[3])return 0;
    if(snprintf(b,sizeof(b),"%lld",(long long)INT64_MIN)!=20)return 0;
    if(snprintf(0,0,"%s", "count")!=5||snprintf(b,sizeof(b),"%")!=-1)return 0;
    return fwrite(0,0,1,stdout)==0;
}