lazysphere/command/tac.c

120 lines
2.1 KiB
C
Raw Normal View History

2023-05-06 04:39:44 +00:00
#include "command.h"
#include "lslib.h"
2023-05-02 04:37:30 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
2023-05-06 04:39:44 +00:00
#include <time.h>
2023-05-02 04:37:30 +00:00
static void help(void) {
printf("Usage: tac [FILE]...\n\n");
printf("Concatenate FILEs and print them in reverse\n");
}
static void print_range(FILE* file, int start, int end) {
2023-05-04 20:10:37 +00:00
int len, i;
len = end - start;
2023-05-02 04:37:30 +00:00
fseek(file, start, SEEK_SET);
2023-05-04 20:10:37 +00:00
for (i = 0; i < len; i++) {
2023-05-02 04:37:30 +00:00
putchar(getc(file));
}
2023-05-04 20:10:37 +00:00
2023-05-02 04:37:30 +00:00
fflush(stdout);
}
static char stdin_path[PATH_MAX];
2023-05-04 20:10:37 +00:00
static FILE* read_stdin (void) {
2023-05-02 04:37:30 +00:00
static bool read;
static FILE* file;
2023-05-04 20:10:37 +00:00
int r;
char c;
2023-05-02 04:37:30 +00:00
if (read) goto finished;
read = true;
srand(time(NULL));
2023-05-04 20:10:37 +00:00
r = rand() % 1000000;
2023-05-02 04:37:30 +00:00
sprintf(stdin_path, "/tmp/%d.tac", r);
file = get_file(stdin_path, "w");
while((c = getchar()) != EOF) putc(c, file);
fclose(file);
file = get_file(stdin_path, "r");
finished:
return file;
}
static void parse_file(FILE* file, struct Stack* stack) {
2023-05-04 20:10:37 +00:00
char buf[1024], c;
int read, i;
2023-05-02 04:37:30 +00:00
int total = 1;
stack_push_int(stack, 0);
rewind(file);
while ((read = fread(buf, 1, 1024, file)) > 0) {
2023-05-04 20:10:37 +00:00
for (i = 0; i < read; i++) {
c = buf[i];
2023-05-02 04:37:30 +00:00
if (c != '\n') continue;
stack_push_int(stack, total + i);
}
total += read;
}
}
static void tac_file(FILE* file) {
struct Stack stack;
2023-05-04 20:10:37 +00:00
int last, current;
2023-05-02 04:37:30 +00:00
stack_init(&stack, 80);
parse_file(file, &stack);
rewind(file);
2023-05-04 20:10:37 +00:00
2023-05-02 04:37:30 +00:00
if (!stack_pop_int(&stack, &last)) goto cleanup;
2023-05-04 20:10:37 +00:00
2023-05-02 04:37:30 +00:00
while(stack_pop_int(&stack, &current)) {
print_range(file, current, last);
last = current;
}
cleanup:
2023-05-04 20:10:37 +00:00
2023-05-02 04:37:30 +00:00
stack_free(&stack);
}
2023-05-15 14:57:33 +00:00
COMMAND(tac_main) {
2023-05-02 04:37:30 +00:00
2023-05-04 20:10:37 +00:00
FILE* in;
int i;
2023-05-02 04:37:30 +00:00
parse_help(argc, argv, help);
2023-05-04 20:10:37 +00:00
in = read_stdin();
2023-05-02 04:37:30 +00:00
if (argc < 1) {
tac_file(in);
return EXIT_SUCCESS;
}
2023-05-04 20:10:37 +00:00
for (i = 0; i < argc; i++) {
2023-05-02 04:37:30 +00:00
FILE* file = get_file(argv[i], "r");
if (file == stdin) {
tac_file(in);
} else {
tac_file(file);
fclose(file);
}
}
fclose(in);
remove(stdin_path);
return EXIT_SUCCESS;
}