16f5992719
New functions for work with system calls KolibriOS are added. Functions for format output are added: printf (), fprintf (), sprintf (), snprintf (), vsnprintf (). For material numbers it is meanwhile supported only format output the (%f), and exponential output a (%e) is not realized yet. Functions for format output correctly work only in GCC because TinyC incorrectly works with the functions containing variable number of arguments. git-svn-id: svn://kolibrios.org@647 a494cfbc-eb01-0410-851d-a64ba20cac60
730 lines
32 KiB
C
730 lines
32 KiB
C
/*
|
|
function for format output to the string
|
|
*/
|
|
|
|
#include <kolibrisys.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
//#include <ctype.h>
|
|
#include <math.h>
|
|
|
|
int formatted_double_to_string(long double number,int format1,int format2,char *s)
|
|
{
|
|
double n;
|
|
double nbefor;
|
|
double nafter;
|
|
double v,v2;
|
|
long intdigit;
|
|
long beforpointdigit;
|
|
long div;
|
|
int i;
|
|
int pos;
|
|
int size;
|
|
int fmt1;
|
|
int fmt2;
|
|
long mul;
|
|
char buf[200];
|
|
|
|
size=(int)s;
|
|
n=(double)number;
|
|
if (n<0) {*s='-';s++;n=-n;}
|
|
|
|
fmt1=format1;
|
|
fmt2=format2;
|
|
if (fmt2>18) {fmt2=18;} //maximum of size long long type
|
|
|
|
//clear array befor output
|
|
for(i=0;i<=200;i++) {buf[i]=0;}
|
|
|
|
if ((fmt1>=0) && (n<1))
|
|
{ //formatted output if 0<=n<1
|
|
mul=1;
|
|
for(i=0;i<fmt2;i++)
|
|
{n=n*10;mul=mul*10;}
|
|
|
|
n=n*10;
|
|
n=ceil(n);
|
|
intdigit=floor(n);
|
|
//intdigit=n;
|
|
intdigit=(intdigit/10);
|
|
|
|
pos=0;
|
|
mul=mul/10;
|
|
for(i=0;i<fmt2-1;i++)
|
|
{
|
|
div=intdigit/mul;
|
|
buf[pos]=(char)div;
|
|
pos++;
|
|
intdigit=intdigit-div*mul;
|
|
mul=mul/10;
|
|
if (mul==1) break;
|
|
}
|
|
buf[pos]=(char)intdigit;
|
|
*s='0';s++;
|
|
*s='.';s++;
|
|
for(i=0;i<format2;i++)
|
|
{
|
|
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];}
|
|
else {*s='0';}
|
|
s++;
|
|
}
|
|
}
|
|
else
|
|
{ //if n>=1
|
|
//v=floorf(n+0.00000000000001);
|
|
beforpointdigit=floor(n+0.00000000000001);
|
|
//beforpointdigit=n;
|
|
nbefor=beforpointdigit;
|
|
nafter=n-nbefor;
|
|
|
|
//print part of number befor point
|
|
mul=1;
|
|
for(i=0;i<200-2;i++)
|
|
{
|
|
mul=mul*10;
|
|
if ((beforpointdigit/mul)==0) {fmt1=i+1;break;}
|
|
}
|
|
|
|
pos=0;
|
|
mul=mul/10;
|
|
for(i=0;i<fmt1-1;i++)
|
|
{
|
|
div=beforpointdigit/mul;
|
|
buf[pos]=(char)div;
|
|
pos++;
|
|
beforpointdigit=beforpointdigit-div*mul;
|
|
mul=mul/10;
|
|
if (mul==1) break;
|
|
}
|
|
buf[pos]=(char)beforpointdigit;
|
|
|
|
for(i=0;i<fmt1;i++)
|
|
{
|
|
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];}
|
|
s++;
|
|
}
|
|
|
|
//print part of number after point
|
|
mul=1;
|
|
for(i=0;i<fmt2;i++)
|
|
{nafter=nafter*10;mul=mul*10;}
|
|
|
|
nafter=nafter*10;
|
|
nafter=ceil(nafter);
|
|
intdigit=floor(nafter);
|
|
//intdigit=nafter;
|
|
intdigit=intdigit/10;
|
|
|
|
pos=0;
|
|
mul=mul/10;
|
|
for(i=0;i<fmt2-1;i++)
|
|
{
|
|
div=intdigit/mul;
|
|
buf[pos]=(char)div;
|
|
pos++;
|
|
intdigit=intdigit-div*mul;
|
|
mul=mul/10;
|
|
if (mul==1) break;
|
|
}
|
|
buf[pos]=(char)intdigit;
|
|
*s='.';s++;
|
|
for(i=0;i<format2;i++)
|
|
{
|
|
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];}
|
|
else {*s='0';}
|
|
s++;
|
|
}
|
|
|
|
}
|
|
size=(int)s-size;
|
|
return(size);
|
|
}
|
|
|
|
int formatted_long_to_string(long long number,int fmt1,char *s)
|
|
{
|
|
int i;
|
|
int pos;
|
|
int fmt;
|
|
int size;
|
|
int difference_pos;
|
|
long digit;
|
|
long mul;
|
|
long div;
|
|
char buf[200];
|
|
|
|
//clear array befor output
|
|
for(i=0;i<200;i++) {buf[i]=0;}
|
|
digit=number;
|
|
|
|
size=(int)s;
|
|
if (digit<0) {*s='-';s++;digit=-digit;}
|
|
if (digit==0) {*s='0';s++;goto end;}
|
|
|
|
mul=1;
|
|
for(i=0;i<200-2;i++)
|
|
{
|
|
mul=mul*10;
|
|
if ((digit/mul)==0) {fmt=i+1;break;}
|
|
}
|
|
|
|
difference_pos=i+1;
|
|
|
|
pos=0;
|
|
mul=mul/10;
|
|
for(i=0;i<fmt-1;i++)
|
|
{
|
|
div=digit/mul;
|
|
buf[pos]=(char)div;
|
|
pos++;
|
|
digit=digit-div*mul;
|
|
mul=mul/10;
|
|
if (mul==1) break;
|
|
}
|
|
buf[pos]=(char)digit;
|
|
|
|
if (fmt1>=difference_pos) fmt=fmt1;
|
|
else
|
|
fmt=difference_pos;
|
|
|
|
for(i=0;i<fmt;i++)
|
|
{
|
|
if (i<difference_pos)
|
|
{
|
|
if ((buf[i]>=0) && (buf[i]<=9)) {*s='0'+buf[i];}
|
|
}
|
|
else
|
|
{
|
|
*s=' ';
|
|
}
|
|
s++;
|
|
}
|
|
end:
|
|
size=(int)s-size;
|
|
return(size);
|
|
}
|
|
|
|
int formatted_hex_to_string(long long number,int fmt1,char flag_register,char *s)
|
|
{
|
|
long n;
|
|
int i,pos;
|
|
int fmt;
|
|
long size;
|
|
int difference_pos;
|
|
char xdigs_lower[16]="0123456789abcdef";
|
|
char xdigs_upper[16]="0123456789ABCDEF";
|
|
char buf[200];
|
|
|
|
n=(long)number;
|
|
size=(int)s;
|
|
if (n<0) {*s='-';s++;n=-n;}
|
|
|
|
if (n==0) {*s='0';s++;goto end;}
|
|
for(i=0;i<200;i++) {buf[i]=0;}
|
|
|
|
i=0;
|
|
if (flag_register==0)
|
|
{
|
|
while (n>0)
|
|
{
|
|
buf[i]=xdigs_lower[n & 15];
|
|
n=n>>4;
|
|
i++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (n>0)
|
|
{
|
|
buf[i]=xdigs_upper[n & 15];
|
|
n=n>>4;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
pos=i;
|
|
difference_pos=i;
|
|
|
|
for(i=pos-1;i>=0;i--)
|
|
{
|
|
*s=buf[i];
|
|
s++;
|
|
}
|
|
|
|
if (fmt1-difference_pos>0)
|
|
{
|
|
for(i=difference_pos+1;i<=fmt1;i++)
|
|
{
|
|
*s=' ';
|
|
s++;
|
|
}
|
|
}
|
|
end:size=(int)s-size;
|
|
return(size);
|
|
}
|
|
|
|
int formatted_octa_to_string(long long number,int fmt1,char flag_register,char *s)
|
|
{
|
|
long n;
|
|
int i,pos;
|
|
int fmt;
|
|
long size;
|
|
int difference_pos;
|
|
char xdigs_lower[16]="012345678";
|
|
char buf[200];
|
|
|
|
n=number;
|
|
size=(int)s;
|
|
if (n<0) {*s='-';s++;n=-n;}
|
|
|
|
if (n==0) {*s='0';s++;goto end;}
|
|
for(i=0;i<200;i++) {buf[i]=0;}
|
|
|
|
i=0;
|
|
if (flag_register==0)
|
|
{
|
|
while (n>0)
|
|
{
|
|
buf[i]=xdigs_lower[n & 7];
|
|
n=n>>3;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
pos=i;
|
|
difference_pos=i;
|
|
|
|
for(i=pos-1;i>=0;i--)
|
|
{
|
|
*s=buf[i];
|
|
s++;
|
|
}
|
|
|
|
if (fmt1-difference_pos>0)
|
|
{
|
|
for(i=difference_pos+1;i<=fmt1;i++)
|
|
{
|
|
*s=' ';
|
|
s++;
|
|
}
|
|
}
|
|
end:size=(int)s-size;
|
|
return(size);
|
|
}
|
|
|
|
int format_print(char *dest, size_t maxlen,const char *fmt0, va_list argp)
|
|
{
|
|
int i,j,k;
|
|
int length;
|
|
int fmt1,fmt2,stepen;
|
|
size_t pos,posc;
|
|
long long intdigit;
|
|
long double doubledigit;
|
|
float floatdigit;
|
|
const char *fmt,*fmtc;
|
|
char *s;
|
|
char *str;
|
|
char buffmt1[30];
|
|
char buffmt2[30];
|
|
char buf[1024];
|
|
char format_flag;
|
|
char flag_point;
|
|
char flag_noformat;
|
|
char flag_long;
|
|
char flag_unsigned;
|
|
char flag_register;
|
|
char flag_plus;
|
|
|
|
fmt=fmt0;
|
|
s=dest;
|
|
pos=0;
|
|
while(pos<maxlen)
|
|
{
|
|
if (*fmt=='%')
|
|
{
|
|
|
|
if (*(fmt+1)=='%')
|
|
{
|
|
*s='%';
|
|
s++;
|
|
fmt=fmt+2;
|
|
pos++;
|
|
goto exit_check;
|
|
}
|
|
//checking to containg format in the string
|
|
fmtc=fmt;
|
|
posc=pos;
|
|
format_flag=0;
|
|
flag_long=0;
|
|
flag_unsigned=0;
|
|
flag_register=0;
|
|
flag_plus=0;
|
|
while((*fmtc!='\0') || (*fmtc!=0))
|
|
{
|
|
fmtc++;
|
|
posc++;
|
|
switch(*fmtc)
|
|
{
|
|
case 'c':
|
|
case 'C':
|
|
format_flag=1;
|
|
break;
|
|
case 'd':
|
|
case 'D':
|
|
case 'i':
|
|
case 'I':
|
|
format_flag=1;
|
|
break;
|
|
case 'e':
|
|
format_flag=1;
|
|
break;
|
|
case 'E':
|
|
format_flag=1;
|
|
flag_long=1;
|
|
break;
|
|
case 'f':
|
|
format_flag=1;
|
|
break;
|
|
case 'F':
|
|
format_flag=1;
|
|
flag_long=1;
|
|
break;
|
|
case 'g':
|
|
format_flag=1;
|
|
break;
|
|
case 'G':
|
|
format_flag=1;
|
|
flag_long=1;
|
|
break;
|
|
case 'l':
|
|
flag_long=1;
|
|
break;
|
|
case 'L':
|
|
flag_long=2;
|
|
break;
|
|
case 'o':
|
|
format_flag=1;
|
|
break;
|
|
case 's':
|
|
case 'S':
|
|
format_flag=1;
|
|
break;
|
|
case 'u':
|
|
case 'U':
|
|
format_flag=1;
|
|
flag_unsigned=1;
|
|
break;
|
|
case 'x':
|
|
format_flag=1;
|
|
break;
|
|
case 'X':
|
|
flag_register=1;
|
|
format_flag=1;
|
|
break;
|
|
case 'z':
|
|
case 'Z':
|
|
format_flag=1;
|
|
flag_unsigned=1;
|
|
break;
|
|
case '+':
|
|
flag_plus=1;
|
|
break;
|
|
|
|
default:;
|
|
}
|
|
if ((*fmtc=='%') || (*fmtc==' ')) break;
|
|
if (format_flag==1) break;
|
|
}
|
|
|
|
if (format_flag==0)
|
|
{
|
|
*s=*fmt;
|
|
fmt++;
|
|
s++;
|
|
pos++;
|
|
}
|
|
else
|
|
{
|
|
if ((posc-pos)==1)
|
|
{//simbols % and format simbol near tothere(for example %c )
|
|
fmt=fmtc+1;
|
|
switch(*fmtc)
|
|
{
|
|
case 'c':
|
|
case 'C':
|
|
if ((pos+1)<maxlen)
|
|
{
|
|
//*s=(int)va_arg(argp,char*);
|
|
*s=*((char *)argp);
|
|
argp=argp+4;
|
|
*s++;pos++;
|
|
}
|
|
break;
|
|
case 's':
|
|
case 'S':
|
|
str=va_arg(argp,char*);
|
|
length=strlen(str);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,str,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
case 'd':
|
|
case 'D':
|
|
case 'i':
|
|
case 'I':
|
|
if (flag_long==0) {intdigit=va_arg(argp,int);}
|
|
if (flag_long==1) {intdigit=va_arg(argp,long);}
|
|
if (flag_long==2) {intdigit=va_arg(argp,long long);}
|
|
//intdigit=*((long*)argp);
|
|
//argp=argp+4;
|
|
if ((intdigit>0) && (flag_plus==1) && (pos+1<maxlen))
|
|
{
|
|
*s='+';
|
|
s++;
|
|
pos++;
|
|
}
|
|
length=formatted_long_to_string(intdigit,0,buf);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,buf,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
case 'o':
|
|
if (flag_long==0) {intdigit=va_arg(argp,int);}
|
|
if (flag_long==1) {intdigit=va_arg(argp,long);}
|
|
if (flag_long==2) {intdigit=va_arg(argp,long long);}
|
|
//intdigit=*((long int *)argp);
|
|
//argp=argp+4;
|
|
|
|
length=formatted_octa_to_string(intdigit,0,flag_register,buf);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,buf,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
case 'u':
|
|
case 'U':
|
|
if (flag_long==0) {intdigit=va_arg(argp,int);}
|
|
if (flag_long==1) {intdigit=va_arg(argp,long int);}
|
|
if (flag_long==2) {intdigit=va_arg(argp,long long);}
|
|
|
|
if (flag_unsigned==1) {
|
|
if (intdigit<0) {intdigit=-intdigit;}
|
|
}
|
|
|
|
length=formatted_long_to_string(intdigit,0,buf);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,buf,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
case 'x':
|
|
case 'X':
|
|
if (flag_long==0) {intdigit=va_arg(argp,int);}
|
|
if (flag_long==1) {intdigit=va_arg(argp,long);}
|
|
if (flag_long==2) {intdigit=va_arg(argp,long long);}
|
|
//intdigit=*((long int *)argp);
|
|
//argp=argp+4;
|
|
|
|
length=formatted_hex_to_string(intdigit,0,flag_register,buf);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,buf,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
case 'z':
|
|
case 'Z':
|
|
intdigit=va_arg(argp,size_t);
|
|
|
|
if (flag_unsigned==1) {
|
|
if (intdigit<0) {intdigit=-intdigit;}
|
|
}
|
|
|
|
length=formatted_long_to_string(intdigit,0,buf);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,buf,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
default:;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fmt++;
|
|
flag_point=0;
|
|
flag_noformat=0;
|
|
fmt1=0;
|
|
fmt2=0;
|
|
j=0;
|
|
k=0;
|
|
for(i=pos+1;i<posc;i++)
|
|
{
|
|
switch(*fmt)
|
|
{
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
if (flag_point==0)
|
|
{
|
|
buffmt1[j]=*fmt-'0';
|
|
j++;
|
|
}
|
|
else
|
|
{
|
|
buffmt2[k]=*fmt-'0';
|
|
k++;
|
|
}
|
|
break;
|
|
case '.':
|
|
flag_point=1;
|
|
break;
|
|
case 'l':
|
|
case 'L':
|
|
break;
|
|
case '+':
|
|
break;
|
|
default:flag_noformat=1;
|
|
}
|
|
if (flag_noformat==1) break;
|
|
fmt++;
|
|
}
|
|
if (flag_noformat==0)
|
|
{
|
|
stepen=1;
|
|
for(i=j-1;i>=0;i--)
|
|
{
|
|
fmt1=fmt1+buffmt1[i]*stepen;
|
|
stepen=stepen*10;
|
|
}
|
|
stepen=1;
|
|
for(i=k-1;i>=0;i--)
|
|
{
|
|
fmt2=fmt2+buffmt2[i]*stepen;
|
|
stepen=stepen*10;
|
|
}
|
|
switch(*fmtc)
|
|
{
|
|
case 'f':
|
|
case 'F':
|
|
if (flag_long==0) {doubledigit=va_arg(argp,double);}
|
|
if (flag_long>=1) {doubledigit=va_arg(argp,long double);}
|
|
//doubledigit=*((double *)argp);
|
|
//sargp=argp+8;
|
|
length=formatted_double_to_string(doubledigit,fmt1,fmt2,buf);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,buf,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
case 'd':
|
|
case 'D':
|
|
case 'i':
|
|
case 'I':
|
|
if (flag_long==0) {intdigit=va_arg(argp,int);}
|
|
if (flag_long==1) {intdigit=va_arg(argp,long);}
|
|
if (flag_long==2) {intdigit=va_arg(argp,long long);}
|
|
|
|
if ((intdigit>0) && (flag_plus==1) && (pos+1<maxlen))
|
|
{
|
|
*s='+';
|
|
s++;
|
|
pos++;
|
|
}
|
|
length=formatted_long_to_string(intdigit,fmt1,buf);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,buf,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
case 'o':
|
|
if (flag_long==0) {intdigit=va_arg(argp,int);}
|
|
if (flag_long==1) {intdigit=va_arg(argp,long);}
|
|
if (flag_long==2) {intdigit=va_arg(argp,long long);}
|
|
length=formatted_octa_to_string(intdigit,fmt1,flag_register,buf);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,buf,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
case 'u':
|
|
case 'U':
|
|
if (flag_long==0) {intdigit=va_arg(argp,int);}
|
|
if (flag_long==1) {intdigit=va_arg(argp,long int);}
|
|
if (flag_long==2) {intdigit=va_arg(argp,long long);}
|
|
|
|
if (flag_unsigned==1) {
|
|
if (intdigit<0) {intdigit=-intdigit;}
|
|
}
|
|
|
|
length=formatted_long_to_string(intdigit,fmt1,buf);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,buf,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
case 'x':
|
|
case 'X':
|
|
if (flag_long==0) {intdigit=va_arg(argp,int);}
|
|
if (flag_long==1) {intdigit=va_arg(argp,long int);}
|
|
if (flag_long==2) {intdigit=va_arg(argp,long long);}
|
|
length=formatted_hex_to_string(intdigit,fmt1,flag_register,buf);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,buf,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
case 'z':
|
|
case 'Z':
|
|
intdigit=va_arg(argp,size_t);
|
|
|
|
if (flag_unsigned==1) {
|
|
if (intdigit<0) {intdigit=-intdigit;}
|
|
}
|
|
|
|
length=formatted_long_to_string(intdigit,fmt1,buf);
|
|
if ((pos+length)<maxlen)
|
|
{
|
|
memcpy(s,buf,length);
|
|
s=s+length;pos=pos+length;
|
|
}
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
fmt=fmtc+1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (*fmt=='\0') {break;}
|
|
*s=*fmt;
|
|
fmt++;
|
|
s++;
|
|
pos++;
|
|
}
|
|
exit_check:;
|
|
}
|
|
return(pos);
|
|
}
|