1
0

make echo better

This commit is contained in:
dtb 2022-06-26 16:34:50 -04:00
parent b3bb6acce9
commit ad8cca39ae
2 changed files with 40 additions and 14 deletions

View File

@ -1,7 +1,24 @@
#include <ctype.h> #include <ctype.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include "libio.h" #include "libio.h"
/* Backups of standard library systems for the odd scenario where there is no
* standard library but there is the write(2) system call. */
static int _isdigit(int c);
static int _strlen(char *s);
/* Wrappers around write(2) */
static int _write(int fd, char *s, int n);
static int _write1(int fd, int c);
/* Normally in <ctype.h> */
static int
_isdigit(int c){
return c >= '0' && c <= '9';
}
/* Normally in <string.h> */
static int static int
_strlen(char *s){ _strlen(char *s){
int i; int i;
@ -11,6 +28,8 @@ _strlen(char *s){
return i; return i;
} }
/* Wrapper around write(2) - keeps re-running write(2) until the operation
* succeeds in full. Usually unnecessary but still good. */
static int static int
_write(int fd, char *s, int n){ _write(int fd, char *s, int n){
int i; int i;
@ -24,32 +43,40 @@ _write(int fd, char *s, int n){
return i; return i;
} }
int /* For writing a single character. To optimize for speed, functions should
fdprint(int fd, char *s){ * allocate a buffer and add to that buffer before write(2)ing the buffer out
return _write(fd, s, _strlen(s)); * in a single system call. However sometimes cheap tricks are as effective. */
} static int
_write1(int fd, int c){
/* SLOW. DO NOT USE. */
static int write1(int fd, int c){
while(write(fd, &c, 1) != 1); while(write(fd, &c, 1) != 1);
return 1; return 1;
} }
int fdputd(int fd, int d){ int
fdprint(int fd, char *s){
return _write(fd, s, strlen(s));
}
int
fdputd(int fd, int d){
int r; int r;
int s; int s;
r = 0; r = 0;
/* Just an implementation looking for a math person to improve it... */ /* Just an implementation looking for a math person to improve it... */
/* Rather than storing the log base 10 of d, store 10^(log base 10 (d))
* which requires less Weird Hax. Then slowly chop off digits and print
* out the system encoding's representations. Finally, print a newline.
* Generally this function is slow and sucks implementation-wise. */
if(d < 100){ if(d < 100){
s = d < 10 ? 1 : 10; s = d < 10 ? 1 : 10;
goto put; goto put;
} }
for(s = 10; d > (s *= 10);); for(s = 10; d > (s *= 10););
put: while(s > 0){ put: while(s > 0){
r += write1(1, (d - (d % s)) / s + '0'); r += _write1(fd, (d - (d % s)) / s + '0');
if((s /= 10) == 0) if((s /= 10) == 0)
r += write1(1, '\n'); r += _write1(fd, '\n');
} }
return r; return r;
@ -60,7 +87,7 @@ fdputs(int fd, char *s){
int i; int i;
int r; int r;
i = _strlen(s); i = strlen(s);
/* RACE CONDITION */ /* RACE CONDITION */
/* This leaves s as an invalid string while the write(2) syscall is /* This leaves s as an invalid string while the write(2) syscall is

View File

@ -1,16 +1,15 @@
#include <sysexits.h> #include <sysexits.h>
#include <stddef.h> /* NULL */ #include <stddef.h> /* NULL */
#include <unistd.h> /* write(2) */ #include <unistd.h> /* write(2) */
#include "libio.h" /* fdprint(3) */
int main(int argc, char **argv){ int main(int argc, char **argv){
int s;
if(*argv == NULL) if(*argv == NULL)
return EX_OSERR; return EX_OSERR;
while(*++argv != NULL){ while(*++argv != NULL){
for(s = 0; *(*argv+s) != '\0'; ++s); fdprint(1, *argv);
write(1, *argv, s);
if(*(argv+1) != NULL) if(*(argv+1) != NULL)
write(1, " ", 1); write(1, " ", 1);