1
0

fdputd(3)

This commit is contained in:
dtb 2022-06-09 17:37:03 -04:00
parent 6cd5be5141
commit 1cb1e48415
3 changed files with 66 additions and 18 deletions

View File

@ -1,30 +1,72 @@
#ifndef _LIBIO_H
#include <unistd.h>
# define _LIBIO_H
int
fdputs(int fd, const char *s){
static int
_strlen(char *s){
int i;
int r;
for(i = 0; s[i] != '\0'; ++i);
/* DANGER */
return i;
}
static int write1(int fd, int c){
int *s;
s = &c;
while(write(fd, s, 1) != 1);
}
int fdputd(int fd, int d){
int r;
int s;
r = 0;
/* Just an implementation looking for a math person to improve it... */
if(d < 100){
s = d < 10 ? 1 : 10;
goto put;
}
for(s = 10; d > (s *= 10););
put: while(s > 0){
r += write1(fd, (d - (d % s)) / s + '0', 1);
if((s /= 10) == 0)
r += write1(fd, "\n", 1);
}
}
int
fdputs(int fd, char *s){
int i;
int r;
i = _strlen(s);
r = 0;
/* RACE CONDITION */
/* This leaves s as an invalid string while the write(2) syscall is
* performed, which can take a non-trivial amount of time. This
* implementation is unsuitable when s is shared between threads or
* whatever the CS term for that is. */
s[i] = '\n';
r = write(fd, s, i + 1);
for(
r = 0;
(r += write(fd, s, i + 1)) < i + 1;
s += r, i -= r
);
s[i] = '\0';
/* /danger */
return r;
}
# ifndef _STDIO_H
int
puts(const char *s){
return fdputs(1, s);
/* Another possible implementation would take char **s and leave *s at the next
* non-digit. But that's less simple; just while(isdigit(*s)) ++s;. */
unsigned int
parse_uint(char *s){
unsigned int r;
for(
r = 0;
isdigit(*s);
r = r * 10 + *s - '0',
++s
);
return r;
}
# endif /* ifndef _STDIO_H */
#endif /* ifndef _LIBIO_H */

6
lib/libio.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef _LIBIO_H
# define _LIBIO_H
int fdputd(int fd, int d);
int fdputs(int fd, char *s);
int parse_uint(char *s);
#endif /* ifndef _LIBIO_H */