summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatolaZ <[email protected]>2018-04-20 00:40:47 +0100
committerKatolaZ <[email protected]>2018-04-20 00:40:47 +0100
commit8f936bc6c89163e3984ac619612c0ce76a51a74e (patch)
tree8d936adb262b2098a984e183e47ea9cc2a8d5d03
first commit
-rw-r--r--buff.c170
-rw-r--r--buff.h34
-rw-r--r--commands.txt32
-rw-r--r--main.c186
-rw-r--r--notes.txt9
5 files changed, 431 insertions, 0 deletions
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<addr; i++){
+ cur = cur -> 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; i<addr2; i++) p = p->next;
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "buff.h"
+#include <ctype.h>
+
+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 <filein>\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