#include "buff.h" #include #include line_t* __search_pos(int addr){ int i; line_t *cur = b_start; for(i=1; i next; } return cur; } int get_lineno(line_t *l){ line_t *t = b_start; int i = 1; while (t && t != l) t = t->next, i+=1; if (!l) return -1; else return i; } int __get_lines(FILE *fin, line_t **first, line_t **last, int *tot){ char buff[4096]; int n,s, num_alloc=0; line_t *l; n = 0; *tot = 0; *first = *last = NULL; while(feof(fin) == 0){ if (!fgets(buff, 4095, fin)) break; if (*buff == '.' && buff[1] == '\n') break; s = strlen(buff) + 1; *tot += s -1; l = malloc(sizeof(line_t)); l->c = malloc(s * sizeof(char)); num_alloc++; memcpy(l->c, buff, s); l->s = s; if (*first == NULL){ *first = *last = l; (*first) -> next = (*last) -> next = NULL; (*first) -> prev = (*last) -> prev = NULL; } else{ (*last) -> next = l; l->prev = *last; l->next = NULL; *last = l; } n++; } fprintf(stderr, " >>>> get_lines: num_alloc: %d\n", num_alloc); return n; } void __append_lines(int addr, int n, line_t *first, line_t *last){ line_t *handle = NULL; if (addr > 0) handle = __search_pos(addr); fprintf(stderr, " >>>> __append_lines -- addr: %d handle: %p\n", addr, handle); if (!handle){ /* we are appending at the beginning... */ last->next = b_start; b_start -> prev = last; b_start = first; } else{ /* we are appending somewhere else */ if (handle -> next) { last -> next = handle -> next; last -> next -> prev = last; } else last -> next = NULL; first->prev = handle; handle->next = first; } cur = last; pos = addr + n; num += n; return; } void __copy_lines(line_t **first, line_t **last){ } int read_file(){ FILE *fin; int tot; fprintf(stderr, " >>> reading file: %s\n", fname); if (!(fin = fopen(fname, "r"))){ return -1; } if (b_start){ addr1=num, addr2=1; delete_lines(); } num = pos = __get_lines(fin, &b_start, &b_end, &tot); fprintf (stderr, " >>>> read_file: pos: %d num: %d\n", pos, num); cur = b_end; fclose(fin); fprintf(stderr, "%d\n", tot); return 0; } void print_cur_line(char lineno){ if (!b_start){ E; 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; fprintf(stderr, ">>> *** 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 ++; } if (lineno) printf("%d\t", pos); printf("%s", cur->c); } int move_to_line(int addr, char print){ fprintf(stderr, " >>>> move_to_line: addr: %d pos: %d\n", addr, pos); 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){ E; return -1; } while(n-- > 0){ cur = cur->next; } pos += n; return 0; } int move_backward(int n){ if (pos - n < 1){ E; return -1; } while(n-- >0){ cur = cur->prev; } pos -= n; return 0; } /* add lines after pos */ void append_lines(){ int n, tot; line_t *first, *last; first = last = NULL; n = __get_lines(stdin, &first, &last, &tot); __append_lines(addr1, n, first, last); } void insert_lines(){ int n, tot; line_t *first, *last; first = last = NULL; n = __get_lines(stdin, &first, &last, &tot); if (addr1 == 0) __append_lines(addr1, n, first, last); else __append_lines(addr1-1, n, first, last); } void delete_lines(){ line_t *handle = NULL, *next, *prev; int num_free = 0; if (addr2 == -1){ addr2 = addr1; } move_to_line(addr2,0); fprintf(stderr, " >>> delete: addr1: %d addr2: %d pos: %d\n", addr1, addr2, pos); if (addr2 > 1){ handle = cur -> prev; } while(pos <= addr1){ pos ++; next = cur -> next; prev = cur -> prev; free(cur -> c); free(cur); if (next) cur = next; else break; } if (!handle){ /* first line deleted */ b_start = cur; } else{ handle -> next = cur; } if (addr1 < num) pos = addr1 +1; else{ pos = addr2 - 1; cur = prev; } num -= addr1 - addr2 + 1; } void change_lines(){ delete_lines(); addr2 = addr1 =pos; append_lines(); } int write_lines(){ FILE *fout; line_t *l; int tot=0; if (! (fout = fopen(fname, "w+"))){ return -1; } l = b_start; while(l){ tot += fprintf(fout, "%s", l->c); l = l->next; } fclose(fout); printf("%d\n", tot); return 0; } /* match either forward (bw=0) or backward (bw=1)*/ int match(char **c, char bw){ char sep = **c, *tmp; line_t *ptr; regex_t re; int l; if (bw) tmp = strtok(*c, "?\n"); else tmp = strtok(*c, "/\n"); fprintf(stderr, " >>>> string to match: \"%s\" bw: %d\n", tmp, bw); if (!tmp) return -1; if (regcomp(&re, tmp, REG_EXTENDED)){ return -1; } *c += strlen(tmp); l = pos; ptr = cur; do { fprintf(stderr, "."); if (bw){ ptr = ptr->prev; l = (l-1 + num) % num; if (!ptr){ /* FIXME: if we keep b_end updated we can avoid this search */ ptr = __search_pos(num); l = num; } } else{ ptr = ptr->next; l = (l+1) % num; if (! ptr){ ptr = b_start; l = 1; } } if (!l) l = num; if (!regexec(&re, (char *) ptr->c , (size_t) 0, NULL, 0)){ regfree(&re); return l; } fprintf(stderr, " %d\n", l); } while(l != pos); fprintf(stderr, " >>>> match: returning\n"); regfree(&re); return -1; } int mark(char *c){ fprintf (stderr, " >>>> mark: label: '%c'\n", *c); if (!islower(*c)) return -1; if (*(c+1) != '\n') return -1; marks[*c - 'a'] = __search_pos(addr1); return 0; } int transfer_lines(int addr, char move){ line_t *first, *last; if (addr2 < addr && addr < addr1){ E; return -1; } first = last = NULL; __copy_lines(&first, &last); if (move){ if (addr1 < addr) addr -= (addr1 - addr2 + 1); delete_lines(); } /* make a generic function to append lines after an addr */ return 0; }