add echo and pritnf

This commit is contained in:
Murphy 2023-04-27 19:06:40 -04:00
parent aa8f616065
commit d373867c23
5 changed files with 229 additions and 2 deletions

View file

@ -4,7 +4,7 @@
A terrible busybox/gnu coreutils clone.
Currently the only supported commands are:
`dd`, `cat`, `yes`
`dd`, `cat`, `yes`, `echo`, `printf`
## How to

View file

@ -11,3 +11,5 @@
COMMAND(dd);
COMMAND(cat);
COMMAND(yes);
COMMAND(echo);
COMMAND(print);

103
src/commands/echo.c Normal file
View file

@ -0,0 +1,103 @@
#include "../command.h"
#include <stdio.h>
#include <string.h>
static void print_with_escape_codes(const char* str) {
size_t index = 0;
while (true) {
char c = str[index];
index++;
if (c == '\0') break;
if (c != '\\') {
putchar(c);
continue;
}
char n = str[index];
index++;
switch (n) {
case '\\':
putchar('\\');
break;
case 'b':
putchar('\b');
break;
case 'c':
exit(EXIT_SUCCESS);
case 'n':
putchar('\n');
break;
case 'r':
putchar('\r');
break;
case 't':
putchar('\t');
break;
case 'v':
putchar('\v');
break;
default:
putchar(c);
putchar(n);
}
}
}
COMMAND(echo) {
if (argc < 1) {
return EXIT_SUCCESS;
}
bool escape_codes = false;
bool newline = true;
int start = 0;
if (prefix("-", argv[0])) {
start = 1;
for (size_t i = 0; i < strlen(argv[0] + 1); i++) {
char c = argv[0][i + 1];
switch (c) {
case 'e':
escape_codes = true;
break;
case 'E':
escape_codes = false;
break;
case 'n':
newline = false;
break;
default:
escape_codes = false;
newline = true;
start = 0;
break;
}
}
}
for (int i = start; i < argc; i++) {
if (escape_codes) {
print_with_escape_codes(argv[i]);
} else {
printf("%s", argv[i]);
}
if (i + 1 != argc) {
putchar(' ');
}
}
if (newline) {
putchar('\n');
}
return EXIT_SUCCESS;
}

118
src/commands/printf.c Normal file
View file

@ -0,0 +1,118 @@
#include "../command.h"
#include <stdlib.h>
static long cast_long(const char* arg) {
char* end;
long l = strtol(arg, &end, 10);
if (end == arg) {
return 0;
} else {
return l;
}
}
static double cast_double(const char* arg) {
char* end;
double d = strtod(arg, &end);
if (end == arg) {
return 0.0;
} else {
return d;
}
}
#define NUMBER(name, type, arg) \
long l = cast_long(arg); \
type* t = (type*) &l; \
type name = *t;
static void handle_percent(char n, const char* arg) {
switch (n) {
case 'd':
case 'z': {
NUMBER(i, int, arg)
printf("%d", i);
break;
}
case 'u': {
NUMBER(u, unsigned int, arg);
printf("%u", u);
break;
}
case 'f': {
double d = cast_double(arg);
printf("%lf", d);
break;
}
case 'c': {
putchar(arg[0]);
break;
}
case 's': {
printf("%s", arg);
break;
}
default: {
putchar('%');
putchar(n);
}
}
}
static void handle_slash(char n) {
switch (n) {
case 'n':
putchar('\n');
break;
case 't':
putchar('\t');
break;
case 'v':
putchar('\v');
break;
case 'b':
putchar('\b');
break;
default:
putchar('\\');
putchar(n);
}
}
COMMAND(print) {
if (argc < 1) {
error("usage: printf FORMAT [ARG]...\n");
}
size_t index = 0;
int arg_index = 0;
while (true) {
char c = argv[0][index];
index++;
if (c == '\0') break;
if (c != '%' && c != '\\') {
putchar(c);
continue;
}
char n = argv[0][index];
index++;
char* arg = NULL;
if (arg_index < argc) {
arg = argv[arg_index + 1];
}
if (c == '%') {
handle_percent(n, arg);
} else {
handle_slash(n);
}
arg_index++;
}
return EXIT_SUCCESS;
}

View file

@ -20,7 +20,7 @@ int main (ARGUMENTS) {
if (argc < 2) {
printf("usage: lazysphere [function [arguments]...]\n\n");
printf("currently defined functions:\n");
printf("\tdd, cat, yes\n");
printf("\tdd, cat, yes, echo, printf\n");
return EXIT_SUCCESS;
}
argc--;
@ -40,6 +40,10 @@ int main (ARGUMENTS) {
return cat(NEXT_ARGS);
} else if (streql(cmd, "yes")) {
return yes(NEXT_ARGS);
} else if (streql(cmd, "echo")) {
return echo(NEXT_ARGS);
} else if (streql(cmd, "printf")) {
return print(NEXT_ARGS);
} else {
error("error: invalid command %s", cmd);
}