add echo and pritnf
This commit is contained in:
parent
aa8f616065
commit
d373867c23
5 changed files with 229 additions and 2 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -11,3 +11,5 @@
|
|||
COMMAND(dd);
|
||||
COMMAND(cat);
|
||||
COMMAND(yes);
|
||||
COMMAND(echo);
|
||||
COMMAND(print);
|
||||
|
|
103
src/commands/echo.c
Normal file
103
src/commands/echo.c
Normal 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
118
src/commands/printf.c
Normal 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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue