📄 read.def
字号:
if (print_ps2) { if (ps2 == 0) ps2 = get_string_value ("PS2"); fprintf (stderr, "%s", ps2 ? ps2 : ""); fflush (stderr); print_ps2 = 0; } if (unbuffered_read) retval = zread (fd, &c, 1); else retval = zreadc (fd, &c); if (retval <= 0) { eof = 1; break; }#if defined (READLINE) }#endif if (i + 4 >= size) /* XXX was i + 2; use i + 4 for multibyte/read_mbchar */ { input_string = (char *)xrealloc (input_string, size += 128); remove_unwind_protect (); add_unwind_protect (xfree, input_string); } /* If the next character is to be accepted verbatim, a backslash newline pair still disappears from the input. */ if (pass_next) { pass_next = 0; if (c == '\n') { i--; /* back up over the CTLESC */ if (interactive && input_is_tty && raw == 0) print_ps2 = 1; } else goto add_char; continue; } /* This may cause problems if IFS contains CTLESC */ if (c == '\\' && raw == 0) { pass_next++; if (skip_ctlesc == 0) { saw_escape++; input_string[i++] = CTLESC; } continue; } if ((unsigned char)c == delim) break; if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL)) { saw_escape++; input_string[i++] = CTLESC; }add_char: input_string[i++] = c;#if defined (HANDLE_MULTIBYTE) if (nchars > 0 && MB_CUR_MAX > 1) { input_string[i] = '\0'; /* for simplicity and debugging */ i += read_mbchar (fd, input_string, i, c, unbuffered_read); }#endif nr++; if (nchars > 0 && nr >= nchars) break; } input_string[i] = '\0';#if 1 if (retval < 0) { builtin_error (_("read error: %d: %s"), fd, strerror (errno)); run_unwind_frame ("read_builtin"); return (EXECUTION_FAILURE); }#endif if (tmsec > 0 || tmusec > 0) reset_alarm (); if (nchars > 0 || delim != '\n') {#if defined (READLINE) if (edit) { if (nchars > 0) rl_num_chars_to_read = 0; if (delim != '\n') reset_eol_delim ((char *)NULL); } else#endif if (input_is_tty) ttyrestore (&termsave); } else if (silent) ttyrestore (&termsave); if (unbuffered_read == 0) zsyncfd (fd); discard_unwind_frame ("read_builtin"); retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;assign_vars: interrupt_immediately--; terminate_immediately--;#if defined (ARRAY_VARS) /* If -a was given, take the string read, break it into a list of words, an assign them to `arrayname' in turn. */ if (arrayname) { if (legal_identifier (arrayname) == 0) { sh_invalidid (arrayname); xfree (input_string); return (EXECUTION_FAILURE); } var = find_or_make_array_variable (arrayname, 1); if (var == 0) { xfree (input_string); return EXECUTION_FAILURE; /* readonly or noassign */ } array_flush (array_cell (var)); alist = list_string (input_string, ifs_chars, 0); if (alist) { if (saw_escape) dequote_list (alist); else word_list_remove_quoted_nulls (alist); assign_array_var_from_word_list (var, alist, 0); dispose_words (alist); } xfree (input_string); return (retval); }#endif /* ARRAY_VARS */ /* If there are no variables, save the text of the line read to the variable $REPLY. ksh93 strips leading and trailing IFS whitespace, so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the same way, but I believe that the difference in behaviors is useful enough to not do it. Without the bash behavior, there is no way to read a line completely without interpretation or modification unless you mess with $IFS (e.g., setting it to the empty string). If you disagree, change the occurrences of `#if 0' to `#if 1' below. */ if (list == 0) {#if 0 orig_input_string = input_string; for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++) ; input_string = t; input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);#endif if (saw_escape) { t = dequote_string (input_string); var = bind_variable ("REPLY", t, 0); free (t); } else var = bind_variable ("REPLY", input_string, 0); VUNSETATTR (var, att_invisible); free (input_string); return (retval); } /* This code implements the Posix.2 spec for splitting the words read and assigning them to variables. */ orig_input_string = input_string; /* Remove IFS white space at the beginning of the input string. If $IFS is null, no field splitting is performed. */ for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++) ; input_string = t; for (; list->next; list = list->next) { varname = list->word->word;#if defined (ARRAY_VARS) if (legal_identifier (varname) == 0 && valid_array_reference (varname) == 0)#else if (legal_identifier (varname) == 0)#endif { sh_invalidid (varname); xfree (orig_input_string); return (EXECUTION_FAILURE); } /* If there are more variables than words read from the input, the remaining variables are set to the empty string. */ if (*input_string) { /* This call updates INPUT_STRING. */ t = get_word_from_string (&input_string, ifs_chars, &e); if (t) *e = '\0'; /* Don't bother to remove the CTLESC unless we added one somewhere while reading the string. */ if (t && saw_escape) { t1 = dequote_string (t); var = bind_read_variable (varname, t1); xfree (t1); } else var = bind_read_variable (varname, t); } else { t = (char *)0; var = bind_read_variable (varname, ""); } FREE (t); if (var == 0) { xfree (orig_input_string); return (EXECUTION_FAILURE); } stupidly_hack_special_variables (varname); VUNSETATTR (var, att_invisible); } /* Now assign the rest of the line to the last variable argument. */#if defined (ARRAY_VARS) if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)#else if (legal_identifier (list->word->word) == 0)#endif { sh_invalidid (list->word->word); xfree (orig_input_string); return (EXECUTION_FAILURE); }#if 0 /* This has to be done this way rather than using string_list and list_string because Posix.2 says that the last variable gets the remaining words and their intervening separators. */ input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);#else /* Check whether or not the number of fields is exactly the same as the number of variables. */ tofree = NULL; if (*input_string) { t1 = input_string; t = get_word_from_string (&input_string, ifs_chars, &e); if (*input_string == 0) tofree = input_string = t; else { input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape); tofree = t; } }#endif if (saw_escape) { t = dequote_string (input_string); var = bind_read_variable (list->word->word, t); xfree (t); } else var = bind_read_variable (list->word->word, input_string); if (var) { stupidly_hack_special_variables (list->word->word); VUNSETATTR (var, att_invisible); } else retval = EXECUTION_FAILURE; FREE (tofree); xfree (orig_input_string); return (retval);}static SHELL_VAR *bind_read_variable (name, value) char *name, *value;{ SHELL_VAR *v;#if defined (ARRAY_VARS) if (valid_array_reference (name) == 0) v = bind_variable (name, value, 0); else v = assign_array_element (name, value, 0);#else /* !ARRAY_VARS */ v = bind_variable (name, value, 0);#endif /* !ARRAY_VARS */ return (v == 0 ? v : ((readonly_p (v) || noassign_p (v)) ? (SHELL_VAR *)NULL : v));}#if defined (HANDLE_MULTIBYTE)static intread_mbchar (fd, string, ind, ch, unbuffered) int fd; char *string; int ind, ch, unbuffered;{ char mbchar[MB_LEN_MAX + 1]; int i, n, r; char c; size_t ret; mbstate_t ps, ps_back; wchar_t wc; memset (&ps, '\0', sizeof (mbstate_t)); memset (&ps_back, '\0', sizeof (mbstate_t)); mbchar[0] = ch; i = 1; for (n = 0; n <= MB_LEN_MAX; n++) { ps_back = ps; ret = mbrtowc (&wc, mbchar, i, &ps); if (ret == (size_t)-2) { ps = ps_back; if (unbuffered) r = zread (fd, &c, 1); else r = zreadc (fd, &c); if (r < 0) goto mbchar_return; mbchar[i++] = c; continue; } else if (ret == (size_t)-1 || ret == (size_t)0 || ret > (size_t)0) break; }mbchar_return: if (i > 1) /* read a multibyte char */ /* mbchar[0] is already string[ind-1] */ for (r = 1; r < i; r++) string[ind+r-1] = mbchar[r]; return i - 1;}#endifstatic voidttyrestore (ttp) struct ttsave *ttp;{ ttsetattr (ttp->fd, ttp->attrs);}#if defined (READLINE)static rl_completion_func_t *old_attempted_completion_function = 0;static rl_hook_func_t *old_startup_hook;static char *deftext;static voidreset_attempted_completion_function (cp) char *cp;{ if (rl_attempted_completion_function == 0 && old_attempted_completion_function) rl_attempted_completion_function = old_attempted_completion_function;}static intset_itext (){ int r1, r2; r1 = r2 = 0; if (old_startup_hook) r1 = (*old_startup_hook) (); if (deftext) { r2 = rl_insert_text (deftext); deftext = (char *)NULL; rl_startup_hook = old_startup_hook; old_startup_hook = (rl_hook_func_t *)NULL; } return (r1 || r2);}static char *edit_line (p, itext) char *p; char *itext;{ char *ret; int len; if (bash_readline_initialized == 0) initialize_readline (); old_attempted_completion_function = rl_attempted_completion_function; rl_attempted_completion_function = (rl_completion_func_t *)NULL; if (itext) { old_startup_hook = rl_startup_hook; rl_startup_hook = set_itext; deftext = itext; } ret = readline (p); rl_attempted_completion_function = old_attempted_completion_function; old_attempted_completion_function = (rl_completion_func_t *)NULL; if (ret == 0) return ret; len = strlen (ret); ret = (char *)xrealloc (ret, len + 2); ret[len++] = delim; ret[len] = '\0'; return ret;}static int old_delim_ctype;static rl_command_func_t *old_delim_func;static int old_newline_ctype;static rl_command_func_t *old_newline_func;static unsigned char delim_char;static voidset_eol_delim (c) int c;{ Keymap cmap; if (bash_readline_initialized == 0) initialize_readline (); cmap = rl_get_keymap (); /* Change newline to self-insert */ old_newline_ctype = cmap[RETURN].type; old_newline_func = cmap[RETURN].function; cmap[RETURN].type = ISFUNC; cmap[RETURN].function = rl_insert; /* Bind the delimiter character to accept-line. */ old_delim_ctype = cmap[c].type; old_delim_func = cmap[c].function; cmap[c].type = ISFUNC; cmap[c].function = rl_newline; delim_char = c;}static voidreset_eol_delim (cp) char *cp;{ Keymap cmap; cmap = rl_get_keymap (); cmap[RETURN].type = old_newline_ctype; cmap[RETURN].function = old_newline_func; cmap[delim_char].type = old_delim_ctype; cmap[delim_char].function = old_delim_func;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -