/* If we are searching backwards, we will find the last match that * starts no later than start. Otherwise we find the first match * starting no earlier than start. If we are doing a regexp search, we * fill in the global variable regmatches with at most 9 subexpression * matches. Also, all .rm_so elements are relative to the start of the * whole match, so regmatches[0].rm_so == 0. */ const char *strstrwrapper(const char *haystack, const char *needle, const char *start) { /* start can be 1 character before the start or after the end of the * line. In either case, we just say no match was found. */ if ((start > haystack && *(start - 1) == '\0') || start < haystack) return NULL; assert(haystack != NULL && needle != NULL && start != NULL); #ifdef HAVE_REGEX_H if (ISSET(USE_REGEXP)) { #ifndef NANO_TINY if (ISSET(BACKWARDS_SEARCH)) { if (regexec(&search_regexp, haystack, 1, regmatches, 0) == 0 && haystack + regmatches[0].rm_so <= start) { const char *retval = haystack + regmatches[0].rm_so; /* Search forward until there are no more matches. */ while (regexec(&search_regexp, retval + 1, 1, regmatches, REG_NOTBOL) == 0 && retval + regmatches[0].rm_so + 1 <= start) retval += regmatches[0].rm_so + 1; /* Finally, put the subexpression matches in global * variable regmatches. The REG_NOTBOL flag doesn't * matter now. */ regexec(&search_regexp, retval, 10, regmatches, 0); return retval; } } else #endif /* !NANO_TINY */ if (regexec(&search_regexp, start, 10, regmatches, (start > haystack) ? REG_NOTBOL : 0) == 0) { const char *retval = start + regmatches[0].rm_so; regexec(&search_regexp, retval, 10, regmatches, 0); return retval; } return NULL; } #endif /* HAVE_REGEX_H */ #if !defined(NANO_TINY) || !defined(DISABLE_SPELLER) if (ISSET(CASE_SENSITIVE)) { #ifndef NANO_TINY if (ISSET(BACKWARDS_SEARCH)) return revstrstr(haystack, needle, start); else #endif return strstr(start, needle); } #endif /* !DISABLE_SPELLER || !NANO_TINY */ #ifndef NANO_TINY else if (ISSET(BACKWARDS_SEARCH)) return mbrevstrcasestr(haystack, needle, start); #endif return mbstrcasestr(start, needle); }
/* Load the recorded cursor positions for files that were edited. */ void load_poshistory(void) { FILE *hisfile = fopen(poshistname, "rb"); if (hisfile == NULL) { if (errno != ENOENT) { /* When reading failed, don't save history when we quit. */ UNSET(POSITIONLOG); history_error(N_("Error reading %s: %s"), poshistname, strerror(errno)); } } else { char *line = NULL, *lineptr, *xptr; size_t buf_len = 0; ssize_t read, count = 0; poshiststruct *record_ptr = NULL, *newrecord; /* Read and parse each line, and store the extracted data. */ while ((read = getline(&line, &buf_len, hisfile)) > 5) { /* Decode nulls as embedded newlines. */ unsunder(line, read); /* Find where the x index and line number are in the line. */ xptr = revstrstr(line, " ", line + read - 3); if (xptr == NULL) continue; lineptr = revstrstr(line, " ", xptr - 2); if (lineptr == NULL) continue; /* Now separate the three elements of the line. */ *(xptr++) = '\0'; *(lineptr++) = '\0'; /* Create a new position record. */ newrecord = (poshiststruct *)nmalloc(sizeof(poshiststruct)); newrecord->filename = mallocstrcpy(NULL, line); newrecord->lineno = atoi(lineptr); newrecord->xno = atoi(xptr); newrecord->next = NULL; /* Add the record to the list. */ if (position_history == NULL) position_history = newrecord; else record_ptr->next = newrecord; record_ptr = newrecord; /* Impose a limit, so the file will not grow indefinitely. */ if (++count > 200) { poshiststruct *drop_record = position_history; position_history = position_history->next; free(drop_record->filename); free(drop_record); } } fclose(hisfile); free(line); stat(poshistname, &stat_of_positions_file); } }