mirror of
https://codeberg.org/TicklishHoneyBee/CLIte.git
synced 2026-03-11 09:04:37 +00:00
a basic printf (and etc) implementation
This commit is contained in:
parent
abc7e6c4a5
commit
3aeae461f0
3 changed files with 353 additions and 4 deletions
|
|
@ -697,7 +697,8 @@ clite.commands.load('test',function(args,env,io) {
|
|||
var stdio = io.include('stdio');
|
||||
var stdlib = io.include('stdlib');
|
||||
stdio.printf('Hello world');
|
||||
stdio.printf('uid:'+stdlib.getuid());
|
||||
stdio.printf('uid:%d',stdlib.getuid());
|
||||
stdio.printf('%#15x:%15o:%15.5f:%0$15.5f:%%:',10,12,8.123456789);
|
||||
function rcb(data) {
|
||||
stdio.printf(data);
|
||||
io.exit(0);
|
||||
|
|
|
|||
347
clite/core.js
347
clite/core.js
|
|
@ -1160,8 +1160,353 @@ clite.io = {
|
|||
return fd.node.data.istty;
|
||||
}
|
||||
clite.io.vfprintf = function(pid,fd,fmt,args) {
|
||||
var str = '';
|
||||
var parts = fmt.replace(/%%/g,'%').split('%');
|
||||
var i = 0;
|
||||
var d = false;
|
||||
parts.forEach(function(p,k) {
|
||||
var fs = p;
|
||||
if (!k || d) {
|
||||
str += p;
|
||||
d = false;
|
||||
return;
|
||||
}
|
||||
if (p == '' && j<parts.length-1) {
|
||||
str += '%';
|
||||
d = true;
|
||||
return;
|
||||
}
|
||||
// %[parameter][flags][width][.precision][length]type
|
||||
//clite.log.write(fs);
|
||||
var param = i;
|
||||
var nparam = true;
|
||||
var ind = fs.indexOf('$');
|
||||
if (ind > -1) {
|
||||
var pp = fs.substring(0,ind);
|
||||
var pi = parseInt(pp);
|
||||
if (pp == pi.toString()) {
|
||||
param = pi;
|
||||
nparam = false;
|
||||
fs = fs.substring(ind+1);
|
||||
}
|
||||
}
|
||||
//clite.log.write('(param='+param+')'+fs);
|
||||
// TODO: support multiple flags
|
||||
var flag = false;
|
||||
if (fs[0] == '-' || fs[0] == '+' || fs[0] == ' ' || fs[0] == '0' || fs[0] == "'" || fs[0] == '#') {
|
||||
flag = fs[0];
|
||||
fs = fs.substring(1);
|
||||
}
|
||||
//clite.log.write('(param='+param+')(flag='+flag+')'+fs);
|
||||
var width = 0;
|
||||
if (fs[0] == '*') {
|
||||
width = parseInt(args[param]);
|
||||
param++;
|
||||
}else{
|
||||
ind = -1;
|
||||
for (var j=0; j<fs.length; j++) {
|
||||
var v = parseInt(fs[j],10);
|
||||
if (v > -1 && v < 10) {
|
||||
ind = j;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ind > -1) {
|
||||
var pp = fs.substring(0,ind+1);
|
||||
var pi = parseInt(pp);
|
||||
if (pi.toString() == pp) {
|
||||
width = pi;
|
||||
fs = fs.substring(ind+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
//clite.log.write('(param='+param+')(flag='+flag+')(width='+width+')'+fs);
|
||||
var precision = 0;
|
||||
if (fs[0] == '.') {
|
||||
fs = fs.substring(1);
|
||||
ind = -1;
|
||||
for (var j=0; j<fs.length; j++) {
|
||||
var v = parseInt(fs[j],10);
|
||||
if (v > -1 && v < 10) {
|
||||
ind = j;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ind > -1) {
|
||||
var pp = fs.substring(0,ind+1);
|
||||
var pi = parseInt(pp);
|
||||
if (pp.toString() == pp) {
|
||||
precision = pi;
|
||||
fs = fs.substring(ind+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ignore length
|
||||
if (fs.substring(0,2) == 'hh' || fs.substring(0,2) == 'll') {
|
||||
fs = fs.substring(2);
|
||||
}else if (['h','l','L','z','j','t'].indexOf(fs[0]) > -1) {
|
||||
fs = fs.substring(1);
|
||||
}
|
||||
|
||||
//clite.log.write('(param='+param+')(flag='+flag+')(width='+width+')'+fs);
|
||||
var type = fs[0];
|
||||
fs = fs.substring(1);
|
||||
//clite.log.write('(param='+param+')(flag='+flag+')(width='+width+')(type='+type+')'+fs);
|
||||
switch (type) {
|
||||
case 'd':
|
||||
case 'i': // signed int
|
||||
var val = parseInt(args[param],10);
|
||||
if (typeof flag === 'string' && val > 0) {
|
||||
if (flag == '+')
|
||||
str += '+';
|
||||
if (flag == ' ')
|
||||
str += ' ';
|
||||
}
|
||||
if (width > 0) {
|
||||
var c = ' ';
|
||||
if (flag == '0')
|
||||
c = '0';
|
||||
if (flag == '-') {
|
||||
str += val.toFixed(0).padEnd(width,c);
|
||||
}else{
|
||||
str += val.toFixed(0).padStart(width,c);
|
||||
}
|
||||
}else{
|
||||
str += val.toFixed(0);
|
||||
}
|
||||
break;
|
||||
case 'u': // unsigned int
|
||||
var sval = args[param].toString(10);
|
||||
if (sval[0] == '-')
|
||||
sval = sval.substring(1);
|
||||
var val = parseInt(sval,10);
|
||||
if (width > 0) {
|
||||
var c = ' ';
|
||||
if (flag == '0')
|
||||
c = '0';
|
||||
if (flag == '-') {
|
||||
str += val.toFixed(0).padEnd(width,c);
|
||||
}else{
|
||||
str += val.toFixed(0).padStart(width,c);
|
||||
}
|
||||
}else{
|
||||
str += val.toFixed(0);
|
||||
}
|
||||
break;
|
||||
case 'f': // float
|
||||
var val = parseFloat(args[param].toString(10));
|
||||
if (isNaN(val)) {
|
||||
str += 'nan';
|
||||
}else if (!Number.isFinite(val)) {
|
||||
str += 'inf';
|
||||
}else{
|
||||
if (precision == 0) {
|
||||
var s = String(val).split('.');
|
||||
if (s.length > 1)
|
||||
precision = s[1].length;
|
||||
}
|
||||
var s = val.toFixed(precision).toLowerCase();
|
||||
if (precision == 0)
|
||||
s += '.';
|
||||
if (typeof flag === 'string' && val > 0) {
|
||||
if (flag == '+')
|
||||
s = '+'+s;
|
||||
if (flag == ' ') {
|
||||
clite.log.write('pad space');
|
||||
s = ' '+s;
|
||||
}
|
||||
}
|
||||
if (width > 0) {
|
||||
var c = ' ';
|
||||
if (flag == '0')
|
||||
c = '0';
|
||||
if (flag == '-') {
|
||||
s = s.padEnd(width,c);
|
||||
}else{
|
||||
s = s.padStart(width,c);
|
||||
}
|
||||
}
|
||||
str += s;
|
||||
}
|
||||
break;
|
||||
case 'F': // FLOAT
|
||||
var val = parseFloat(args[param].toString(10));
|
||||
if (isNaN(val)) {
|
||||
str += 'NAN';
|
||||
}else if (!Number.isFinite(val)) {
|
||||
str += 'INF';
|
||||
}else{
|
||||
if (precision == 0) {
|
||||
var s = String(val).split('.');
|
||||
if (s.length > 1)
|
||||
precision = s[1].length;
|
||||
}
|
||||
var s = val.toFixed(precision).toUpperCase();
|
||||
if (precision == 0)
|
||||
s += '.';
|
||||
if (typeof flag === 'string' && val > 0) {
|
||||
if (flag == '+')
|
||||
s = '+'+s;
|
||||
if (flag == ' ')
|
||||
s = ' '+s;
|
||||
}
|
||||
if (width > 0) {
|
||||
var c = ' ';
|
||||
if (flag == '0')
|
||||
c = '0';
|
||||
if (flag == '-') {
|
||||
s = s.padEnd(width,c);
|
||||
}else{
|
||||
s = s.padStart(width,c);
|
||||
}
|
||||
}
|
||||
str += s;
|
||||
}
|
||||
break;
|
||||
case 'e': // float with exponent
|
||||
var val = parseFloat(args[param].toString(10));
|
||||
if (isNaN(val)) {
|
||||
str += 'NAN';
|
||||
}else if (!Number.isFinite(val)) {
|
||||
str += 'INF';
|
||||
}else{
|
||||
str += val.toExponential().toLowerCase();
|
||||
}
|
||||
break;
|
||||
case 'E': // FLOAT with exponent
|
||||
var val = parseFloat(args[param].toString(10));
|
||||
if (isNaN(val)) {
|
||||
str += 'NAN';
|
||||
}else if (!Number.isFinite(val)) {
|
||||
str += 'INF';
|
||||
}else{
|
||||
str += val.toExponential().toUpperCase();
|
||||
}
|
||||
break;
|
||||
case 'g': // either float or float with exponent
|
||||
var val = parseFloat(args[param].toString(10));
|
||||
if (isNaN(val)) {
|
||||
str += 'nan';
|
||||
}else if (!Number.isFinite(val)) {
|
||||
str += 'inf';
|
||||
}else{
|
||||
str += val.toString(10).toLowerCase();
|
||||
}
|
||||
break;
|
||||
case 'G': // either FLOAT or FLOAT with exponent
|
||||
var val = parseFloat(args[param].toString(10));
|
||||
if (isNaN(val)) {
|
||||
str += 'NAN';
|
||||
}else if (!Number.isFinite(val)) {
|
||||
str += 'INF';
|
||||
}else{
|
||||
str += val.toString(10).toUpperCase();
|
||||
}
|
||||
break;
|
||||
case 'x': // hexadecimal
|
||||
var val = parseInt(args[param]);
|
||||
var s = '';
|
||||
if (flag == '#')
|
||||
s += '0x';
|
||||
s += val.toString(16).toLowerCase();
|
||||
if (width > 0) {
|
||||
if (flag == '-') {
|
||||
s = s.padEnd(width,' ');
|
||||
}else{
|
||||
s = s.padStart(width,' ');
|
||||
}
|
||||
}
|
||||
str += s;
|
||||
break;
|
||||
case 'X': // HEXADECIMAL
|
||||
var val = parseInt(args[param]);
|
||||
var s = '';
|
||||
if (flag == '#')
|
||||
s += '0X';
|
||||
s += val.toString(16).toUpperCase();
|
||||
if (width > 0) {
|
||||
if (flag == '-') {
|
||||
s = s.padEnd(width,' ');
|
||||
}else{
|
||||
s = s.padStart(width,' ');
|
||||
}
|
||||
}
|
||||
str += s;
|
||||
break;
|
||||
case 'o': // octal
|
||||
var val = parseInt(args[param],10);
|
||||
var s = '';
|
||||
if (flag == '#')
|
||||
s += '0';
|
||||
s += val.toString(8);
|
||||
if (width > 0) {
|
||||
if (flag == '-') {
|
||||
s = s.padEnd(width,' ');
|
||||
}else{
|
||||
s = s.padStart(width,' ');
|
||||
}
|
||||
}
|
||||
str += s;
|
||||
break;
|
||||
case 's': // string
|
||||
var s = args[param].toString();
|
||||
if (width > 0) {
|
||||
if (flag == '-') {
|
||||
s = s.padEnd(width,' ');
|
||||
}else{
|
||||
s = s.padStart(width,' ');
|
||||
}
|
||||
}
|
||||
if (precision > 0)
|
||||
s = s.substring(0,precision);
|
||||
str += s;
|
||||
break;
|
||||
case 'c': // character
|
||||
if (width > 0) {
|
||||
if (flag == '-') {
|
||||
str += args[param].toString()[0].padEnd(width,' ');
|
||||
}else{
|
||||
str += args[param].toString()[0].padStart(width,' ');
|
||||
}
|
||||
}else{
|
||||
str += args[param].toString()[0];
|
||||
}
|
||||
break;
|
||||
case 'p': // pointer (NULL)
|
||||
if (width > 0) {
|
||||
if (flag == '-') {
|
||||
str += 'NULL'.padEnd(width,' ');
|
||||
}else{
|
||||
str += 'NULL'.padStart(width,' ');
|
||||
}
|
||||
}else{
|
||||
str += 'NULL';
|
||||
}
|
||||
break;
|
||||
case 'a': // hexfloat
|
||||
var val = parseFloat(args[param]);
|
||||
str += val.toString(16).toLowerCase();
|
||||
break;
|
||||
case 'A': // HEXFLOAT
|
||||
var val = parseFloat(args[param]);
|
||||
str += val.toString(16).toUpperCase();
|
||||
break;
|
||||
case 'n': // number of chars written so far returned
|
||||
args[param].value = str.length;
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
|
||||
if (nparam)
|
||||
i = param+1;
|
||||
str += fs;
|
||||
})
|
||||
|
||||
str = str.replace(/%/g,'%');
|
||||
// TODO: actually support formatting
|
||||
return clite.io.write(pid,fd,fmt);
|
||||
return clite.io.write(pid,fd,str);
|
||||
}
|
||||
},
|
||||
// 0: unknown
|
||||
|
|
|
|||
|
|
@ -79,12 +79,15 @@ return Object.create({
|
|||
},
|
||||
|
||||
fprintf:function(fd,fmt) {
|
||||
var args = [];
|
||||
var args = Array.from(arguments);
|
||||
args.shift();
|
||||
args.shift();
|
||||
return clite.io.vfprintf(io.pid,fd,fmt,args);
|
||||
},
|
||||
|
||||
printf:function(fmt) {
|
||||
var args = [];
|
||||
var args = Array.from(arguments);
|
||||
args.shift();
|
||||
return clite.io.vfprintf(io.pid,io.stdout,fmt,args);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue