From 8f936bc6c89163e3984ac619612c0ce76a51a74e Mon Sep 17 00:00:00 2001 From: KatolaZ Date: Fri, 20 Apr 2018 00:40:47 +0100 Subject: first commit --- buff.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ buff.h | 34 +++++++++++ commands.txt | 32 ++++++++++ main.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ notes.txt | 9 +++ 5 files changed, 431 insertions(+) create mode 100644 buff.c create mode 100644 buff.h create mode 100644 commands.txt create mode 100644 main.c create mode 100644 notes.txt diff --git a/buff.c b/buff.c new file mode 100644 index 0000000..91593bb --- /dev/null +++ b/buff.c @@ -0,0 +1,170 @@ +#include "buff.h" + +line_t* __search_pos(int addr){ + + int i; + line_t *cur = b_start; + for(i=1; i next; + } + return cur; +} + +int read_lines(FILE *fin){ + + char buff[4096]; + line_t *line; + size_t s; + + while(feof(fin) == 0){ + if (!fgets(buff, 4095, fin)) break; + s = strlen(buff) + 1; + line = malloc(sizeof(line_t)); + line->s = s; + line->c = malloc(s * sizeof(char)); + memcpy(line->c, buff, s); + line->next = NULL; + + if (b_start == NULL){ + line->prev = NULL; + b_start = line; + } + else{ + b_end->next = line; + line->prev = b_end; + } + b_end = line; + num += 1; + } + cur = b_end; + pos = num; +} + +void print_cur_line(char lineno){ + + if (!b_start){ + printf("?\n"); + return; + } + + if (lineno) + printf("%d\t", pos); + printf("%s", cur->c); +} + +void print_lines(char lineno){ + + line_t *p; + int i=0; + p = b_start; + + + printf(">>> *** addr1: %d addr2: %d ***\n", addr1, addr2); + for (i=1; inext; + pos = i; + cur = p; + while(pos < addr1){ + if (lineno) + printf("%d\t", pos); + printf("%s", cur->c); + cur = cur->next; + pos += 1; + } + if (lineno) + printf("%d\t", pos); + printf("%s", cur->c); + if (pos != num) { + pos += 1; + cur = cur -> next; + } +} + +int move_to_line(int addr, char print){ + + if (addr > num) + return -1; + else if (addr >= 0){ + pos = addr; + cur = __search_pos(pos); + if (print) + print_cur_line(0); + } + return pos; +} + +void print_lineno(){ + printf("%d\n", addr1); +} + +int move_forward(int n){ + + if (pos + n > num){ + printf("?\n"); + return -1; + } + while(n-- >0){ + cur = cur->next; + } + pos += n; + return 0; +} + +int move_backward(int n){ + + if (pos - n < 1){ + printf("?\n"); + return -1; + } + while(n-- >0){ + cur = cur->prev; + } + pos -= n; + return 0; +} + + + +/* add lines after pos */ +void append_lines(){ + + char buff[4096]; + int n,s; + line_t *first, *l, *last; + + n = 0; + first = last = NULL; + while(feof(stdin) == 0){ + if (!fgets(buff, 4095, stdin)) break; + if (buff[0] == '.') + break; + s = strlen(buff) + 1; + l = malloc(sizeof(line_t)); + l->c = malloc(s * sizeof(char)); + memcpy(l->c, buff, s); + l->s = s; + if (first == NULL) + first = last = l; + else{ + last -> next = l; + l->prev = last; + last = l; + } + n += 1; + } + if (addr1 == 0){ + last->next = b_start; + b_start -> prev = last; + b_start = first; + move_to_line(n,0); + } + else{ + last -> next = cur -> next; + cur->next = first; + first->prev = cur; + move_forward(n); + } +} + +void insert_lines(){} + +void delete_lines(){} diff --git a/buff.h b/buff.h new file mode 100644 index 0000000..2d55c04 --- /dev/null +++ b/buff.h @@ -0,0 +1,34 @@ +#ifndef __BUFF_H__ +#define __BUFF_H__ + +#include +#include +#include + +typedef struct line_t { + char *c; + unsigned int s; + struct line_t *prev; + struct line_t *next; +} line_t; + + +extern line_t *b_start; +extern line_t *b_end; +extern line_t *cur; +extern unsigned int num; +extern unsigned int pos; +extern int addr1, addr2; + +int read_lines(FILE *); +void print_lines(char); +void print_cur_line(char); +int move_to_line(int, char); +void print_lineno(); +void append_lines(); +void insert_lines(); +void delete_lines(); + + + +#endif /* __BUFF_H__ */ diff --git a/commands.txt b/commands.txt new file mode 100644 index 0000000..24072c3 --- /dev/null +++ b/commands.txt @@ -0,0 +1,32 @@ +(.)a +(.,.)c +(.,.)d +e [file] +E [file] +f [file] +(1,$)g/RE/command list +(1,$)G/RE/ +h +H +(.)i +(.,.+1)j +(.)kx +(.,.)l +(.,.)m_addr +(.,.)n +(.,.)p +P +q +Q +($)r +(.,.)s/RE/replacement/flags +(.,.)t_addr +u +(1,$)v/RE/command list +(1,$)V/RE/ +(1,$)w [file] +($)= +!command +(.+1) (NULL cmd) + + diff --git a/main.c b/main.c new file mode 100644 index 0000000..0599575 --- /dev/null +++ b/main.c @@ -0,0 +1,186 @@ +#include +#include +#include +#include "buff.h" +#include + +line_t *b_start = NULL; +line_t *b_end = NULL; +line_t *cur = NULL; +unsigned int num = 0; +unsigned int pos = 0; +/* addr1 is the lasr address, while addr2 is the previous one */ +int addr1, addr2; + + + +const char* skip_blank(const char **c){ + + while (isblank(**c)) (*c)++; + return *c; +} + + +int get_addr(const char **cmd){ + + int addr, n, got; + char sign = 0, comma = 0; + const char *c; + + addr1 = addr2 = -1; + c = *cmd; + while(*c){ + c = skip_blank(&c); + n = 0; + got = 0; + if (isdigit(*c)){ + while (isdigit(*c)){ + got = 1; + n = n * 10 + *c - '0', c++; + } + if (got){ + if (addr1 > -1 ) + addr2 = addr1; + addr1 = n; + } + } + else { + switch(*c){ + case '.': + if (addr1 > -1) + addr2 = addr1; + addr1 = pos; + break; + case '$': + if (addr1 > -1) + addr2 = addr1; + addr1 = num; + break; + case ',': + comma = 1; + if (addr1 < addr2){ + *cmd = c; + return -1; + } + break; + default: + goto check; + } + c++; + } + } + check: + *cmd = c; + + if (addr1 == -1){ + if (comma){ + addr1 = num; + addr2 = 1; + return 2; + } + addr1 = addr2 = pos; + return 0; + } + if (addr2 == -1){ + addr2 = pos; + return 1; + } + return 2; +} + + +void main_loop(){ + + char *cmd; + int ret; + char p; + + cmd = malloc(256 * sizeof(char)); + + while(1){ + p = 0; + fgets(cmd, 255, stdin); + + ret = get_addr((const char **) &cmd); + + printf(">>> *** pos: %d address: %d ***\n", pos, ret); + if (ret) { + printf(">>> *** addr1: %d, addr2= %d***\n", addr1, addr2); + } + + switch(cmd[0]){ + case 'i': + if (addr1 > -1) + move_to_line(addr1, 0); + insert_lines(); + break; + case 'a': + if (addr1 > -1) + move_to_line(addr1, 0); + append_lines(); + break; + case 'd': + delete_lines(); + break; + case 'n': p = 1; + case 'p': + if (ret == 2) + if (addr1 < addr2){ + printf("?\n"); + break; + } + else + print_lines(p); + else if (ret == 1) + move_to_line(addr2, 1); + else if (ret == 0) + print_cur_line(p); + else if (ret == -1){ + addr1 = num; + addr2 = 1; + move_to_line(addr2,0); + print_lines(p); + } + break; + case '\n': + if (addr1 > -1) + move_to_line(addr1, 1); + else + print_cur_line(p); + break; + case 'q': + exit(0); + break; + case '=': + if (addr1 == -1) + addr1 = num; + print_lineno(); + break; + default: + printf(">>> **** unknown command: '%c'****\n", cmd[0]) + ; + } + } +} + + + +int main(int argc, char *argv[]){ + + FILE *fin; + + if (argc < 2){ + printf("Usage: %s \n", argv[0]); + exit(1); + } + + if ((fin = fopen(argv[1], "r+"))){ + read_lines(fin); + } + else{ + printf("Error opening file %s\n", argv[1]); + } + + main_loop(); +} + diff --git a/notes.txt b/notes.txt new file mode 100644 index 0000000..d00a80d --- /dev/null +++ b/notes.txt @@ -0,0 +1,9 @@ +Implementation of an ed clone. + +Things to sort out: + +- buffering + +- regexp (use libc regexp (compat mode, to run also on *BSD)) + +Target: 16KB -- cgit v1.2.3