#include #include #include #include "buff.h" #include #define FW 0 #define BW 1 line_t *b_start = NULL; line_t *b_end = NULL; line_t *cur = NULL; int num = 0; int pos = 0; /* addr1 is the last address, while addr2 is the previous one */ int addr1, addr2; char *fname, mod=0, lc; line_t* marks[26] = {NULL}; const char* skip_blank(const char **c){ while (isblank(**c)) (*c)++; return *c; } int get_addr(const char **cmd){ int addr, n, got, d; char sign = 1, comma = 0, semic = 0, DIR = FW; const char *c; line_t *p; 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){ addr1 = n; } } else { switch(*c){ case '.': /* cur line*/ addr1 = pos; break; case '$': /* last line */ addr1 = num; break; case ',': /* range 1 */ /* refactor to set addr2 = addr1 */ fprintf(stderr, " >>>> comma: addr1: %d addr2: %d pos: %d\n", addr1, addr2, pos); comma = 1; if (addr1 == -1){ (*cmd)++; return -1; } addr2 = addr1; addr1 = -1; break; case ';': /* range 2*/ semic = 1; if (addr1 == -1){ return -1; } addr2 = addr1; break; case '?': DIR = BW; case '/': /* match */ c++; addr = match((char**) &c, DIR); DIR = FW; if (addr == -1){ return -1; } addr1 = addr; fprintf(stderr, " match (%d): addr1: %d addr2: %d pos: %d\n", DIR, addr1, addr2, pos); break; case '\'': /* mark */ fprintf(stderr, " >>>> address is a mark!!!\n"); c++; d = *c - 'a'; if (d < 0 || d > 26){ E; return -1; } p = marks[*c - 'a']; if (!p) E; else addr = get_lineno(p); if (addr < 0) marks[*c - 'a'] = NULL; addr1 = addr; break; case '-': sign = -1; case '+': fprintf(stderr, " >>>> +/-: addr1: %d addr2: %d pos: %d\n", addr1, addr2, pos); /* the assignment below breaks stuff like 1++++ */ if (addr1 < 0) addr1 = pos; c ++; c = skip_blank(&c); if (! isdigit(*c)){ addr1 += sign; } else{ n = 0; while(isdigit(*c)){ n = 10 * n + *c - '0', c++; } addr1 += sign * n; } c--; fprintf(stderr, " >>>>AT_EXIT +/-: addr1: %d addr2: %d pos: %d\n", addr1, addr2, pos); sign = +1; break; default: goto check; } c++; } } check: *cmd = c; fprintf(stderr, " >>> get_addr: addr1: %d addr2: %d\n", addr1, addr2); if (addr1 > num || addr2 > num) return -2; if (addr2 == -1){ if (comma){ addr1 = num; addr2 = 1; return 2; } if (semic){ addr1 = num; addr2 = pos; return 2; } if (addr1 == -1){ addr1 = addr2 = pos; return -1; } return 1; } return 2; } int get_fname(char **cmd){ static char b[4096]; int s, n; n = sscanf(*cmd, "%s", b); if (n <1 ) return 0; fprintf(stderr, " >>> read fname: %s\n", b); s = strlen(b); if (s){ fname = realloc(fname, (s+1) * sizeof(char)); memcpy(fname, b, s+1); return 1; } return -1; } void main_loop(){ char *cmd, *c; int ret, addr, tmp1, tmp2; char p, move, app; cmd = malloc(256 * sizeof(char)); c = cmd; while(1){ p = 0; move = 0, app = 0; fgets(cmd, 255, stdin); ret = get_addr((const char **) &cmd); fprintf(stderr,">>> *** pos: %d ret: %d ***\n", pos, ret); if (ret) { fprintf(stderr, ">>> *** addr1: %d, addr2= %d***\n", addr1, addr2); } switch(cmd[0]){ case 'a': if (addr1 > -1) move_to_line(addr1, 0); else addr1 = pos; append_lines(); break; case 'c': if (addr1 > -1) move_to_line(addr1,0); CHECKADDR; delete_lines(); addr1 = addr2 = pos; append_lines(); case 'd': if (ret == -1 ) addr2 = 1, addr1=num; CHECKADDR; if (addr1 == 0){ E; break; } delete_lines(); break; case 'E': mod = 0; case 'e': if (mod){ if (lc != 'e'){ E; break; } } cmd++; skip_blank((const char**)&cmd); if (cmd[0] == '!') //read_command(); ; else if(get_fname(&cmd) >=0) read_file(); else{ perror(fname); E; } break; case 'f': if (ret > 0) E; else{ cmd += 1; if (get_fname(&cmd)>=0) printf("%s\n", fname); else{ perror(fname); E; } } break; case 'i': if (addr1 > -1) move_to_line(addr1, 0); else addr1 = pos; CHECKADDR; insert_lines(); break; case 'k': cmd ++; if (addr1==-1) addr1 = pos; if (mark(cmd)) E; break; case 'n': p = 1; case 'p': if (ret == 2){ CHECKADDR; print_lines(p); } else if (ret == 1){ move_to_line(addr1, 0); print_cur_line(p); } else if (ret == -1){ addr2=1, addr1=num; print_lines(p); } else E; break; case '\0': case '\n': fprintf(stderr, ">>>> void command\n"); if (ret == -1 ){ if (cur -> next){ cur = cur -> next, pos += 1; print_cur_line(0); } else E; } else { if (addr1 <=num) move_to_line(addr1, 1); else if (addr2 <=pos) print_cur_line(p); else E; } break; case 'Q': mod = 0; case 'q': fprintf(stderr, " >>>> q: mod: %d lc: %c\n", mod, lc); if (mod){ if (lc == 'q') goto cleanup; else { E; break; } } goto cleanup; break; case 'm': move = 1; case 't': cmd +=1; if (ret <2) addr2 = addr1; CHECKADDR; tmp1=addr1, tmp2=addr2; if(get_addr((const char**)&cmd) == 1){ addr = addr1; addr1 = tmp1, addr2 = tmp2; transfer_lines(addr, move); } else E; move = 0; break; case 'W': app = 1; case 'w': cmd += 1; get_fname(&cmd); if (!fname) E; else{ if (write_lines(app)){ perror(fname); E; } } break; case '!': cmd += 1; system(cmd); printf("!\n"); /* exec_command(cmd, stdout); */ break; case '=': if (addr1 == -1) addr1 = num; print_lineno(); break; case 'h': /* not impl. */ case 'H': /* not impl. */ case '#': break; default: if (cmd[0]) fprintf(stderr, ">>> **** unknown command: '%c'****\n", cmd[0]); E; } lc = cmd[0]; cmd = c; } cleanup: free(c); return; } int main(int argc, char *argv[]){ FILE *fin; fname = NULL; if (argc > 1){ fname = malloc((strlen(argv[1])+1) * sizeof(char)); memcpy(fname, argv[1], strlen(argv[1]) + 1); if (read_file()) perror(fname); } main_loop(); addr1 = num, addr2 = 1; if (num>0) delete_lines(); free(fname); }