#include "buff.h" #include line_t* __search_pos(int addr){ int i; line_t *cur = b_start; for(i=1; i next; } return cur; } 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 == '.') 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; } 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); printf("%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; } 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); if (addr1 == 0){ fprintf(stderr, " >>> append (zero): pos: %d n:%d\n", pos, n); last->next = b_start; if (b_start) b_start -> prev = last; b_start = first; num += n; move_to_line(n,0); } else{ fprintf(stderr, " >>> append (non-zero): pos: %d n:%d\n", pos, n); last -> next = cur -> next; cur->next = first; first->prev = cur; num += n; //move_forward(n); pos += n; cur = last; } } void insert_lines(){ int n, tot; line_t *first, *last; first = last = NULL; n = __get_lines(stdin, &first, &last, &tot); if (addr1 == 0){ fprintf(stderr, " >>> insert (zero): pos: %d n:%d\n", pos, n); last->next = b_start; b_start -> prev = last; b_start = first; num += n; move_to_line(n,0); } else{ fprintf(stderr, " >>> insert (non-zero): pos: %d n:%d\n", pos, n); cur -> prev -> next = first; first -> prev = cur -> prev; last -> next = cur; num += n; pos-- ; cur = last; } } void delete_lines(){ line_t *handle; int num_free = 0; if (addr1 == -1){ addr1 = pos; } if (addr2 == -1){ addr2 = addr1; } if (addr1 < addr2){ return; } move_to_line(addr2,0); fprintf(stderr, " >>> delete: addr1: %d addr2: %d pos: %d\n", addr1, addr2, pos); if (addr2 <= 1){ /* we are deleting the first line */ while(pos <= addr1){ pos ++; free(cur->c); num_free++; if (cur -> next){ cur = cur -> next; free(cur -> prev); } else { free(cur); cur = NULL; break; } } fprintf(stderr, " >>>> delete_lines: num_free: %d\n", num_free); /* free(b_start); */ b_start = cur; if (cur){ pos = 1; cur = b_start; } else pos = 0; } else{ handle = cur->prev; while(pos < addr1){ free(cur->c); cur = cur -> next; free(cur->prev); pos ++; } handle->next = cur -> next; free(cur->c); free(cur); if (handle -> next){ pos = addr2 ; cur = handle->next; } else{ pos = addr2 - 1; cur = handle; } } 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; }