make echo better
This commit is contained in:
parent
b3bb6acce9
commit
ad8cca39ae
49
lib/libio.c
49
lib/libio.c
@ -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
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user