📄 readline.c
字号:
continue; size = 16; with = realloc(to, size); len = 0; from_len = strlen(from); for (; *cmd && *cmd != delim; cmd++) { if (len + from_len + 1 >= size) { size += from_len + 1; with = realloc(with, size); } if (*cmd == '&') { /* safe */ (void) strcpy(&with[len], from); len += from_len; continue; } if (*cmd == '\\' && (*(cmd + 1) == delim || *(cmd + 1) == '&')) cmd++; with[len++] = *cmd; } with[len] = '\0'; to = with; tempcmd = _rl_compat_sub(line, from, to, (g_on) ? 1 : 0); free(line); line = tempcmd; g_on = 0; } } } arr = history_tokenize(line); free(line); /* no more needed */ if (arr && *arr == NULL) free(arr), arr = NULL; if (!arr) return (-1); /* find out max valid idx to array of array */ max = 0; for (i = 0; arr[i]; i++) max++; max--; /* set boundaries to something relevant */ if (start < 0) start = 1; if (end < 0) end = max - ((end < -1) ? 1 : 0); /* check boundaries ... */ if (start > max || end > max || start > end) return (-1); for (i = 0; i <= max; i++) { char *temp; if (h_on && (i == 1 || h_on > 1) && (temp = strrchr(arr[i], '/'))) *(temp + 1) = '\0'; if (t_on && (i == 1 || t_on > 1) && (temp = strrchr(arr[i], '/'))) (void) strcpy(arr[i], temp + 1); if (r_on && (i == 1 || r_on > 1) && (temp = strrchr(arr[i], '.'))) *temp = '\0'; if (e_on && (i == 1 || e_on > 1) && (temp = strrchr(arr[i], '.'))) (void) strcpy(arr[i], temp); } cmdsize = 1, cmdlen = 0; tempcmd = malloc(cmdsize); for (i = start; start <= i && i <= end; i++) { int arr_len; arr_len = strlen(arr[i]); if (cmdlen + arr_len + 1 >= cmdsize) { cmdsize += arr_len + 1; tempcmd = realloc(tempcmd, cmdsize); } (void) strcpy(&tempcmd[cmdlen], arr[i]); /* safe */ cmdlen += arr_len; tempcmd[cmdlen++] = ' '; /* add a space */ } while (cmdlen > 0 && isspace((unsigned char) tempcmd[cmdlen - 1])) cmdlen--; tempcmd[cmdlen] = '\0'; *result = tempcmd; for (i = 0; i <= max; i++) free(arr[i]); free(arr), arr = (char **) NULL; return (p_on) ? 2 : 1;}/* * csh-style history expansion */inthistory_expand(char *str, char **output){ int i, retval = 0, idx; size_t size; char *temp, *result; if (h == NULL || e == NULL) rl_initialize(); *output = strdup(str); /* do it early */ if (str[0] == history_subst_char) { /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */ temp = alloca(4 + strlen(str) + 1); temp[0] = temp[1] = history_expansion_char; temp[2] = ':'; temp[3] = 's'; (void) strcpy(temp + 4, str); str = temp; }#define ADD_STRING(what, len) \ { \ if (idx + len + 1 > size) \ result = realloc(result, (size += len + 1)); \ (void)strncpy(&result[idx], what, len); \ idx += len; \ result[idx] = '\0'; \ } result = NULL; size = idx = 0; for (i = 0; str[i];) { int start, j, loop_again; size_t len; loop_again = 1; start = j = i;loop: for (; str[j]; j++) { if (str[j] == '\\' && str[j + 1] == history_expansion_char) { (void) strcpy(&str[j], &str[j + 1]); continue; } if (!loop_again) { if (str[j] == '?') { while (str[j] && str[++j] != '?'); if (str[j] == '?') j++; } else if (isspace((unsigned char) str[j])) break; } if (str[j] == history_expansion_char && !strchr(history_no_expand_chars, str[j + 1]) && (!history_inhibit_expansion_function || (*history_inhibit_expansion_function)(str, j) == 0)) break; } if (str[j] && str[j + 1] != '#' && loop_again) { i = j; j++; if (str[j] == history_expansion_char) j++; loop_again = 0; goto loop; } len = i - start; temp = &str[start]; ADD_STRING(temp, len); if (str[i] == '\0' || str[i] != history_expansion_char || str[i + 1] == '#') { len = j - i; temp = &str[i]; ADD_STRING(temp, len); if (start == 0) retval = 0; else retval = 1; break; } retval = _history_expand_command(&str[i], (size_t) (j - i), &temp); if (retval != -1) { len = strlen(temp); ADD_STRING(temp, len); } i = j; } /* for(i ...) */ if (retval == 2) { add_history(temp);#ifdef GDB_411_HACK /* gdb 4.11 has been shipped with readline, where */ /* history_expand() returned -1 when the line */ /* should not be executed; in readline 2.1+ */ /* it should return 2 in such a case */ retval = -1;#endif } free(*output); *output = result; return (retval);}/* * Parse the string into individual tokens, similarily to how shell would do it. */char **history_tokenize(const char *str){ int size = 1, result_idx = 0, i, start; size_t len; char **result = NULL, *temp, delim = '\0'; for (i = 0; str[i]; i++) { while (isspace((unsigned char) str[i])) i++; start = i; for (; str[i]; i++) { if (str[i] == '\\') { if (str[i+1] != '\0') i++; } else if (str[i] == delim) delim = '\0'; else if (!delim && (isspace((unsigned char) str[i]) || strchr("()<>;&|$", str[i]))) break; else if (!delim && strchr("'`\"", str[i])) delim = str[i]; } if (result_idx + 2 >= size) { size <<= 1; result = realloc(result, size * sizeof(char *)); } len = i - start; temp = malloc(len + 1); (void) strncpy(temp, &str[start], len); temp[len] = '\0'; result[result_idx++] = temp; result[result_idx] = NULL; } return (result);}/* * limit size of history record to ``max'' events */voidstifle_history(int max){ HistEvent ev; if (h == NULL || e == NULL) rl_initialize(); if (history(h, &ev, H_SETSIZE, max) == 0) max_input_history = max;}/* * "unlimit" size of history - set the limit to maximum allowed int value */intunstifle_history(void){ HistEvent ev; int omax; history(h, &ev, H_SETSIZE, INT_MAX); omax = max_input_history; max_input_history = INT_MAX; return (omax); /* some value _must_ be returned */}inthistory_is_stifled(void){ /* cannot return true answer */ return (max_input_history != INT_MAX);}/* * read history from a file given */intread_history(const char *filename){ HistEvent ev; if (h == NULL || e == NULL) rl_initialize(); return (history(h, &ev, H_LOAD, filename));}/* * write history to a file given */intwrite_history(const char *filename){ HistEvent ev; if (h == NULL || e == NULL) rl_initialize(); return (history(h, &ev, H_SAVE, filename));}/* * returns history ``num''th event * * returned pointer points to static variable */HIST_ENTRY *history_get(int num){ static HIST_ENTRY she; HistEvent ev; int i = 1, curr_num; if (h == NULL || e == NULL) rl_initialize(); /* rewind to beginning */ if (history(h, &ev, H_CURR) != 0) return (NULL); curr_num = ev.num; if (history(h, &ev, H_LAST) != 0) return (NULL); /* error */ while (i < num && history(h, &ev, H_PREV) == 0) i++; if (i != num) return (NULL); /* not so many entries */ she.line = ev.str; she.data = NULL; /* rewind history to the same event it was before */ (void) history(h, &ev, H_FIRST); (void) history(h, &ev, H_NEXT_EVENT, curr_num); return (&she);}/* * add the line to history table */intadd_history(const char *line){ HistEvent ev; if (h == NULL || e == NULL) rl_initialize(); (void) history(h, &ev, H_ENTER, line); if (history(h, &ev, H_GETSIZE) == 0) history_length = ev.num; return (!(history_length > 0)); /* return 0 if all is okay */}/* * clear the history list - delete all entries */voidclear_history(void){ HistEvent ev; history(h, &ev, H_CLEAR);}/* * returns offset of the current history event */intwhere_history(void){ HistEvent ev; int curr_num, off; if (history(h, &ev, H_CURR) != 0) return (0); curr_num = ev.num; history(h, &ev, H_FIRST); off = 1; while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0) off++; return (off);}/* * returns current history event or NULL if there is no such event */HIST_ENTRY *current_history(void){ return (_move_history(H_CURR));}/* * returns total number of bytes history events' data are using */inthistory_total_bytes(void){ HistEvent ev; int curr_num, size; if (history(h, &ev, H_CURR) != 0) return (-1); curr_num = ev.num; history(h, &ev, H_FIRST); size = 0; do size += strlen(ev.str); while (history(h, &ev, H_NEXT) == 0); /* get to the same position as before */ history(h, &ev, H_PREV_EVENT, curr_num); return (size);}/* * sets the position in the history list to ``pos'' */inthistory_set_pos(int pos){ HistEvent ev; int off, curr_num; if (pos > history_length || pos < 0) return (-1); history(h, &ev, H_CURR); curr_num = ev.num; history(h, &ev, H_FIRST); off = 0; while (off < pos && history(h, &ev, H_NEXT) == 0) off++; if (off != pos) { /* do a rollback in case of error */ history(h, &ev, H_FIRST); history(h, &ev, H_NEXT_EVENT, curr_num); return (-1); } return (0);}/* * returns previous event in history and shifts pointer accordingly */HIST_ENTRY *previous_history(void){ return (_move_history(H_PREV));}/* * returns next event in history and shifts pointer accordingly */HIST_ENTRY *next_history(void){ return (_move_history(H_NEXT));}/* * generic history search function */static int_history_search_gen(const char *str, int direction, int pos){ HistEvent ev; const char *strp; int curr_num; if (history(h, &ev, H_CURR) != 0) return (-1); curr_num = ev.num; for (;;) { strp = strstr(ev.str, str); if (strp && (pos < 0 || &ev.str[pos] == strp)) return (int) (strp - ev.str); if (history(h, &ev, direction < 0 ? H_PREV : H_NEXT) != 0) break; } history(h, &ev, direction < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); return (-1);}/* * searches for first history event containing the str */inthistory_search(const char *str, int direction){ return (_history_search_gen(str, direction, -1));}/* * searches for first history event beginning with str */inthistory_search_prefix(const char *str, int direction){ return (_history_search_gen(str, direction, 0));}/* * search for event in history containing str, starting at offset
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -