summaryrefslogtreecommitdiff
path: root/src/commands/ed.c
diff options
context:
space:
mode:
authorTyler Murphy <tylerm@tylerm.dev>2023-05-04 16:10:37 -0400
committerTyler Murphy <tylerm@tylerm.dev>2023-05-04 16:10:37 -0400
commitb1364be7e271c5a080e29efcda209a190a82d6d9 (patch)
treefc64d1546e59b5ed1c2c204612b6181bc401c27f /src/commands/ed.c
parentgrep (diff)
downloadlazysphere-b1364be7e271c5a080e29efcda209a190a82d6d9.tar.gz
lazysphere-b1364be7e271c5a080e29efcda209a190a82d6d9.tar.bz2
lazysphere-b1364be7e271c5a080e29efcda209a190a82d6d9.zip
ansii c
Diffstat (limited to '')
-rw-r--r--src/commands/ed.c198
1 files changed, 139 insertions, 59 deletions
diff --git a/src/commands/ed.c b/src/commands/ed.c
index 379da3c..d7e8881 100644
--- a/src/commands/ed.c
+++ b/src/commands/ed.c
@@ -66,14 +66,17 @@ static bool read_regex(char** end, re_t* regex, enum RegexDirection dir) {
static bool parse_regex(char** end, struct LineAddress* address, enum RegexDirection dir) {
re_t regex;
+ unsigned long cap, siz, i, until;
+ long int* buf;
+
if (!read_regex(end, &regex, dir)) return false;
- unsigned long cap = 8;
- unsigned long siz = 0;
- long int* buf = malloc(cap * sizeof(long int));
+ cap = 8;
+ siz = 0;
+ buf = malloc(cap * sizeof(long int));
- unsigned long i = (dir == ALL ? 0 : line_current);
- unsigned long until = (dir == BEFORE ? 0 : line_count - 1);
+ i = (dir == ALL ? 0 : line_current);
+ until = (dir == BEFORE ? 0 : line_count - 1);
for (; (dir == BEFORE ? i >= until : i < until); dir == BEFORE ? i-- : i++) {
int len;
if (re_matchp(regex, lines[i], &len) == -1) {
@@ -112,28 +115,34 @@ static void expand_buffer(long int** buf, unsigned long* cap, unsigned long* siz
static bool parse_regex_lines(char** end, struct LineAddress* address) {
re_t regex;
+ unsigned long cap, siz;
+ long int* buf;
+ int len;
+ struct LineAddress addr;
+
if (!read_regex(end, &regex, ALL)) return false;
- unsigned long cap = 8;
- unsigned long siz = 0;
- long int* buf = malloc(cap * sizeof(long int));
- int len;
+ cap = 8;
+ siz = 0;
+ buf = malloc(cap * sizeof(long int));
- struct LineAddress addr = *address;
+ addr = *address;
if (addr.type == INDEX) {
if (re_matchp(regex, lines[addr.data.index.i], &len) != -1) {
buf[0] = addr.data.index.i;
siz = 1;
}
} else if (addr.type == RANGE) {
- for (long int i = addr.data.range.a; i < addr.data.range.b; i++) {
+ long int i;
+ for (i = addr.data.range.a; i < addr.data.range.b; i++) {
if (re_matchp(regex, lines[i], &len) == -1) continue;
expand_buffer(&buf, &cap, &siz);
buf[siz] = i;
siz++;
}
} else if (addr.type == SET) {
- for (unsigned long i = 0; i < addr.data.set.s; i++) {
+ unsigned long i;
+ for (i = 0; i < addr.data.set.s; i++) {
if (re_matchp(regex, lines[addr.data.set.b[i]], &len) == -1) continue;
expand_buffer(&buf, &cap, &siz);
buf[siz] = addr.data.set.b[i];
@@ -153,6 +162,11 @@ static bool parse_regex_lines(char** end, struct LineAddress* address) {
static bool read_address(char** command, bool whitespace, struct LineAddress* a) {
char* index = *command;
struct LineAddress address;
+
+ char* end_pre;
+ long int n_pre;
+ char pre;
+
memset(&address, 0, sizeof(struct LineAddress));
address.empty = false;
@@ -164,8 +178,7 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a)
return true;
}
- char* end_pre;
- long int n_pre = strtol(index, &end_pre, 10) - 1;
+ n_pre = strtol(index, &end_pre, 10) - 1;
if (end_pre == index) {
n_pre = -1;
} else {
@@ -176,7 +189,7 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a)
index = end_pre;
}
- char pre = *(index++);
+ pre = *(index++);
switch (pre) {
case '.':
address.type = INDEX;
@@ -188,28 +201,37 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a)
break;
case '-':
case '^': {
- address.type = INDEX;
char* end;
- long int n = strtol(index, &end, 10) - 1;
+ long int n;
+
+ address.type = INDEX;
+ n = strtol(index, &end, 10) - 1;
+
if (n < 0) {
error_s("input cannot be negative\n");
return false;
}
+
if (index == end) {
address.data.index.i = line_current - 1;
} else {
address.data.index.i = line_current - n;
}
+
if (address.data.index.i < 0) {
error_s("line number %ld does not exist\n", address.data.index.i + 1);
return false;
}
+
break;
}
case '+': {
- address.type = INDEX;
char* end;
- long int n = strtol(index, &end, 10) - 1;
+ long int n;
+
+ address.type = INDEX;
+ n = strtol(index, &end, 10) - 1;
+
if (n < 0) {
error_s("input cannot be negative\n");
return false;
@@ -268,7 +290,8 @@ static bool read_address(char** command, bool whitespace, struct LineAddress* a)
static void free_data(bool all) {
if (lines != NULL) {
- for (unsigned long i = 0; i < line_count; i++) {
+ unsigned long i;
+ for (i = 0; i < line_count; i++) {
free(lines[i]);
}
free(lines);
@@ -321,11 +344,11 @@ int ed_getline(char *buf, size_t size) {
size_t i = 0;
int ch;
clearerr(stdin);
- while ((ch = getchar()) != EOF) { // Read until EOF ...
+ while ((ch = getchar()) != EOF) { /* Read until EOF ... */
if (i + 1 < size) {
buf[i++] = ch;
}
- if (ch == '\n') { // ... or end of line
+ if (ch == '\n') { /* ... or end of line */
break;
}
}
@@ -346,6 +369,8 @@ static void load_file(FILE* file) {
}
static bool check_if_sure(char* prompt) {
+ char buf[INPUT_LEN];
+
if (!pending_writes) {
return true;
}
@@ -353,7 +378,6 @@ static bool check_if_sure(char* prompt) {
printf("%s", prompt);
fflush(stdout);
- char buf[INPUT_LEN];
if (ed_getline(buf, INPUT_LEN) == EOF) {
putchar('\n');
return false;
@@ -387,9 +411,12 @@ static void append_lines(unsigned long index, char** new, unsigned long new_len)
}
static void delete_lines(unsigned long a, unsigned long b) {
+ unsigned long i;
+
if (b < a) return;
pending_writes = true;
- for (unsigned long i = a; i <= b; i++) {
+
+ for (i = a; i <= b; i++) {
free(lines[i]);
}
if (b == line_count - 1) {
@@ -403,20 +430,25 @@ static void delete_lines(unsigned long a, unsigned long b) {
}
static bool handle_append(struct LineAddress* address) {
+ char** buf;
+ unsigned long cap, size;
+
if (address->type != INDEX) {
error_s("append command requires index addressing\n");
return false;
}
+
if (line_count == 0) {
address->data.index.i = -1;
}
- char** buf;
- unsigned long cap, size;
+
get_input(stdin, &buf, &cap, &size);
+
if (size > 0) {
append_lines(address->data.index.i + 1, buf, size);
printf("ed: appened %lu lines\n", size);
}
+
line_current += size;
free(buf);
return true;
@@ -427,6 +459,7 @@ static bool handle_delete(struct LineAddress* address) {
error_s("line number %ld does not exist\n", address->data.index.i + 1);
return false;
}
+
if (address->type == INDEX) {
delete_lines(address->data.index.i, address->data.index.i);
output("deleted line %ld\n", address->data.index.i+1);
@@ -434,16 +467,19 @@ static bool handle_delete(struct LineAddress* address) {
delete_lines(address->data.range.a, address->data.range.b);
output("deleted lines %ld-%ld\n", address->data.range.a+1, address->data.range.b+1);
} else if (address->type == SET) {
- for (unsigned long i = 0; i < address->data.set.s; i++) {
+ unsigned long i;
+ for (i = 0; i < address->data.set.s; i++) {
delete_lines(address->data.set.b[i], address->data.set.b[i]);
}
output("deleted %lu lines\n", address->data.set.s);
}
+
return true;
}
static bool get_file_name(char** filename) {
size_t len = strlen(*filename);
+
if (len < 1 || (len == 1 && **filename == '\n')) {
if (default_filename == NULL) {
error_s("no default filename specified\n");
@@ -467,16 +503,23 @@ static bool get_file_name(char** filename) {
}
static void write_file(char* filename, struct LineAddress* address, char* type) {
+ FILE* file;
+ int wrote;
+
if (line_count < 1) {
error_s("cannot write empty file\n");
return;
}
+
if (!get_file_name(&filename)) return;
- FILE* file = get_file_s(filename, type);
+ file = get_file_s(filename, type);
if (file == NULL) return;
- int wrote = 0;
+
+ wrote = 0;
+
if (address->empty) {
- for (unsigned long i = 0; i < line_count; i++) {
+ unsigned long i;
+ for (i = 0; i < line_count; i++) {
fprintf(file, "%s", lines[i]);
wrote++;
}
@@ -485,30 +528,38 @@ static void write_file(char* filename, struct LineAddress* address, char* type)
fprintf(file, "%s", lines[i]);
wrote++;
} else if (address->type == RANGE) {
- for (long int i = address->data.range.a; i < address->data.range.b; i++) {
+ long int i;
+ for (i = address->data.range.a; i < address->data.range.b; i++) {
fprintf(file, "%s", lines[i]);
wrote++;
}
} else if (address->type == SET) {
- for (unsigned long i = 0; i < address->data.set.s; i++) {
+ unsigned long i;
+ for (i = 0; i < address->data.set.s; i++) {
fprintf(file, "%s", lines[address->data.set.b[i]]);
wrote++;
}
}
+
pending_writes = false;
fclose(file);
output("wrote %d lines from %s\n", wrote, filename);
}
static void read_file(char* filename) {
+ FILE* file;
+ char** buf;
+ long int line;
+ unsigned long capacity, size;
+
if (!get_file_name(&filename)) return;
- FILE* file = get_file_s(filename, "r");
+ file = get_file_s(filename, "r");
if (file == NULL) return;
- unsigned long capacty = 8;
- unsigned long size = 0;
- char** buf = malloc(capacty * sizeof(char*));
- get_input(file, &buf, &capacty, &size);
+ capacity = 8;
+ size = 0;
+ buf = malloc(capacity * sizeof(char*));
+ get_input(file, &buf, &capacity, &size);
if (size < 1) {
free(buf);
@@ -516,10 +567,11 @@ static void read_file(char* filename) {
return;
}
- long int line = -1;
+ line = -1;
if (line_count > 0) {
line = line_count - 1;
}
+
append_lines(line, buf, size);
free(buf);
output("read and appended %lu lines from %s\n", size, filename);
@@ -539,24 +591,31 @@ static int substute_string(long int index, long int matches, re_t regex, char* s
int capacity = 8;
int size = 0;
char* buf = malloc(sizeof(char) * capacity);
+ long int left;
int offset = 0;
int matches_found = 0;
while(true) {
+ int distance, len;
+
if (lines[index][offset] == '\0') break;
+
if (matches_found >= matches && matches > 0) break;
- int distance, len;
+
if ((distance = re_matchp(regex, &lines[index][offset], &len)) == -1) {
break;
}
- if (distance > 0)
+
+ if (distance > 0) {
expand_string(&buf, &capacity, &size, &lines[index][offset], distance);
+ }
+
expand_string(&buf, &capacity, &size, sub, sub_len);
offset += len + distance;
matches_found++;
}
- long int left = strlen(lines[index] + offset);
+ left = strlen(lines[index] + offset);
expand_string(&buf, &capacity, &size, &lines[index][offset], left + 1);
free(lines[index]);
@@ -565,41 +624,50 @@ static int substute_string(long int index, long int matches, re_t regex, char* s
}
static void prompt(void) {
+ char buf[INPUT_LEN];
+ char* index;
+ char cmd;
+ bool whitespace, linenumbers;
+ struct LineAddress address;
+
printf(": ");
fflush(stdout);
- char buf[INPUT_LEN];
if (ed_getline(buf, INPUT_LEN) == EOF) { putchar('\n'); return; }
if (buf[0] == '\0') { putchar('\n'); return; }
- char* index = &buf[0];
- bool whitespace = skip_whitespace(&index);
+ index = &buf[0];
+ whitespace = skip_whitespace(&index);
- struct LineAddress address;
if (!read_address(&index, whitespace, &address)) return;
- char cmd = *(index++);
+ cmd = *(index++);
if (cmd == ',') {
+ struct LineAddress address2;
+
if (address.type != INDEX) {
error_s("comma range addressing requires two index addresses\n");
free_address(address);
return;
}
- struct LineAddress address2;
+
whitespace = skip_whitespace(&index);
+
if (!read_address(&index, whitespace, &address2)) {
free_address(address);
return;
}
+
if (address2.type != INDEX) {
error_s("comma range addressing requires two index addresses\n");
free_address(address);
free_address(address2);
return;
}
+
address.type = RANGE;
- address.data.range.a = address.data.index.i; // cursed
+ address.data.range.a = address.data.index.i; /* cursed */
address.data.range.b = address2.data.index.i;
cmd = *(index++);
@@ -611,7 +679,8 @@ static void prompt(void) {
return;
}
- bool linenumbers = false;
+ linenumbers = false;
+
test:
switch (cmd) {
case '\0':
@@ -663,12 +732,14 @@ test:
if (linenumbers) printf("%ld\t", address.data.index.i + 1);
printf("%s", lines[address.data.index.i]);
} else if (address.type == RANGE) {
- for (long int i = address.data.range.a; i <= address.data.range.b; i++) {
+ long int i;
+ for (i = address.data.range.a; i <= address.data.range.b; i++) {
if (linenumbers) printf("%ld\t", i + 1);
printf("%s", lines[i]);
}
} else if (address.type == SET) {
- for (unsigned long i = 0; i < address.data.set.s; i++) {
+ unsigned long i;
+ for (i = 0; i < address.data.set.s; i++) {
if (linenumbers) printf("%ld\t", address.data.set.b[i] +1);
printf("%s", lines[address.data.set.b[i]]);
}
@@ -698,14 +769,17 @@ test:
}
goto test;
break;
- case 's':
+ case 's': {
+ char* replace = index;
+ long int matches, sub_len, matches_found;
+ unsigned long i;
+
skip_whitespace(&index);
if (*(index++) != '/') {
error_s("unexpected character at start of regex\n");
break;
}
if (!parse_regex_lines(&index, &address)) { return; }
- char* replace = index;
while(*index != '\0' && *index != '/') index++;
if (*index != '/') {
error_s("/ missing after %c\n", *index);
@@ -716,7 +790,6 @@ test:
break;
}
*(index++) = '\0';
- long int matches;
if (*index == '\0' || *index == '\n') {
matches = 1;
} else if (*index == 'g') {
@@ -733,15 +806,16 @@ test:
break;
}
}
- long int sub_len = strlen(replace);
- long int matches_found = 0;
+ sub_len = strlen(replace);
+ matches_found = 0;
- for (unsigned long i = 0; i < address.data.set.s; i++) {
+ for (i = 0; i < address.data.set.s; i++) {
matches_found += substute_string(address.data.set.b[i], matches, last_regex, replace, sub_len);
}
output("replaced %ld matches over %ld lines\n", matches_found, address.data.set.s);
pending_writes = true;
break;
+ }
case 'w': {
bool quit = false;
if (*index == 'q') {
@@ -766,11 +840,17 @@ test:
if (!check_if_sure("Load new file for sure? ")) break;
__attribute__((fallthrough));
case 'E': {
+ char* filename;
+ FILE* file;
+
skip_whitespace(&index);
- char* filename = index;
+
+ filename = index;
if(!get_file_name(&filename)) break;
- FILE* file = get_file_s(filename, "r");
+
+ file = get_file_s(filename, "r");
if (file == NULL) break;
+
load_file(file);
break;
}