diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 51dbb384..8f41fe84 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -5272,8 +5272,9 @@ arrayfunc.c --- parse.y - discard_until: now returns the last character read. If we get an - EOF while processing a comment, return EOF - - shell_getc: if discard_until returns EOF, return yacc_EOF + EOF while processing a comment, return EOF (rarely happens; + shell_getc returns EOF only under certain circumstances) + - read_token: if discard_until returns EOF, return yacc_EOF input.h - bclearerror: new macro, clears the B_ERROR flag in the buffered @@ -5294,7 +5295,31 @@ doc/{bash.1,bashref.texi} 2/8 --- bashline.c - - alias_expand_line: if alias_expand doesn't change rl_line_buffer, - just return right away without changing rl_point. Inspired by a - report from Addison Brendtro - - history_expand_line: ditto + - set_up_new__line: if the new line doesn't change rl_line_buffer, + just return right away without changing rl_point. Affects + alias-expand-line, history-expand-line, and history-and-alias-expand-line. + Inspired by a report from + Addison Brendtro + +builtins/declare.def + - declare_internal: make multiple calls to `local -' at the same + context have no effect after the first one. That way we don't keep + overwriting the saved option set. Report and fix from + Emanuele Torre + + 2/10 + ---- +execute_cmd.[ch] + - bind_lastarg: now a public function + +parse.y + - execute_variable_command: call bind_lastarg instead of bind_variable + to avoid exporting $_ if allexport is set. Fix from + Emanuele Torre + +bashhist.c + - history_delimiting_chars: if we're parsing some kind of delimited + construct that's *not* a quoted string, don't bother adding an extra + newline to the history if the current history entry already ends in + a newline. From https://savannah.gnu.org/support/?110838 via + Ganapathi Kamath diff --git a/bashline.c b/bashline.c index f4665759..dfe5ab9b 100644 --- a/bashline.c +++ b/bashline.c @@ -2713,6 +2713,13 @@ set_up_new_line (char *new_line) { int old_point, at_end; + /* If we didn't expand anything, don't change anything. */ + if (STREQ (new_line, rl_line_buffer)) + { + free (new_line); + return; + } + old_point = rl_point; at_end = rl_point == rl_end; @@ -2741,13 +2748,6 @@ alias_expand_line (int count, int ignore) new_line = alias_expand (rl_line_buffer); - /* If we didn't expand anything, don't change anything. */ - if (new_line && STREQ (new_line, rl_line_buffer)) - { - free (new_line); - return (0); - } - if (new_line) { set_up_new_line (new_line); @@ -2770,13 +2770,6 @@ history_expand_line (int count, int ignore) new_line = history_expand_line_internal (rl_line_buffer); - /* If we didn't expand anything, don't change anything. */ - if (new_line && STREQ (new_line, rl_line_buffer)) - { - free (new_line); - return (0); - } - if (new_line) { set_up_new_line (new_line); diff --git a/builtins/declare.def b/builtins/declare.def index f7dac728..28100de1 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -409,11 +409,19 @@ declare_internal (WORD_LIST *list, int local_var) if (local_var && variable_context && STREQ (name, "-")) { + int o; + + o = localvar_inherit; + localvar_inherit = 0; var = make_local_variable ("-", 0); - FREE (value_cell (var)); /* just in case */ - value = get_current_options (); - var_setvalue (var, value); - VSETATTR (var, att_invisible); + localvar_inherit = o; + + if (value_cell (var) == NULL) /* no duplicate instances */ + { + value = get_current_options (); + var_setvalue (var, value); + VSETATTR (var, att_invisible); + } NEXT_VARIABLE (); } diff --git a/doc/bash.1 b/doc/bash.1 index 4efb6765..376e347e 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -9278,7 +9278,9 @@ is used within a function, it causes the variable to have a visible scope restricted to that function and its children. If \fIname\fP is \-, the set of shell options is made local to the function in which \fBlocal\fP is invoked: shell options changed using the -\fBset\fP builtin inside the function are restored to their original values +\fBset\fP builtin inside the function +after the call to \fBlocal\fP +are restored to their original values when the function returns. The restore is effected as if a series of \fBset\fP commands were executed to restore the values that were in place before the function. diff --git a/doc/bashref.texi b/doc/bashref.texi index 5b44ce74..bd24d715 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -4787,7 +4787,9 @@ The @var{option} can be any of the options accepted by @code{declare}. children. If @var{name} is @samp{-}, the set of shell options is made local to the function in which @code{local} is invoked: shell options changed using -the @code{set} builtin inside the function are restored to their original +the @code{set} builtin inside the function +after the call to @code{local} +are restored to their original values when the function returns. The restore is effected as if a series of @code{set} commands were executed to restore the values that were in place before the function. diff --git a/examples/loadables/mkdir.c b/examples/loadables/mkdir.c index b0df8f0d..55ffbd07 100644 --- a/examples/loadables/mkdir.c +++ b/examples/loadables/mkdir.c @@ -3,7 +3,7 @@ /* See Makefile for compilation details. */ /* - Copyright (C) 1999-2009,2022 Free Software Foundation, Inc. + Copyright (C) 1999-2009,2022-2023 Free Software Foundation, Inc. This file is part of GNU Bash. Bash is free software: you can redistribute it and/or modify @@ -135,10 +135,12 @@ mkdir_builtin (WORD_LIST *list) static int make_path (char *path, int user_mode, int nmode, int parent_mode) { - int oumask; + mode_t oumask; struct stat sb; char *p, *npath; + int tail; + /* If we don't have to do any work, don't do any work. */ if (stat (path, &sb) == 0) { if (S_ISDIR (sb.st_mode) == 0) @@ -166,48 +168,64 @@ make_path (char *path, int user_mode, int nmode, int parent_mode) while (*p == '/') p++; - while (p = strchr (p, '/')) + tail = 0; + while (tail == 0) { - *p = '\0'; - if (stat (npath, &sb) != 0) + if (*p == '\0') + tail = 1; + else + p = strchr (p, '/'); + if (p) + *p = '\0'; + else + tail = 1; + if (mkdir (npath, 0) < 0) { - if (mkdir (npath, 0)) + /* "Each dir operand that names an existing directory shall be + ignored without error." */ + if (errno == EEXIST || errno == EISDIR) + { + int e = errno; + int fail = 0; + + if (stat (npath, &sb) != 0) + { + fail = 1; + builtin_error ("cannot create directory `%s': %s", npath, strerror (e)); + } + else if (e == EEXIST && S_ISDIR (sb.st_mode) == 0) + { + fail = 1; + builtin_error ("`%s': file exists but is not a directory", npath); + } + if (fail) + { + umask (original_umask); + free (npath); + return 1; + } + } + else { builtin_error ("cannot create directory `%s': %s", npath, strerror (errno)); umask (original_umask); free (npath); return 1; } - if (chmod (npath, parent_mode) != 0) - { - builtin_error ("cannot chmod directory `%s': %s", npath, strerror (errno)); - umask (original_umask); - free (npath); - return 1; - } } - else if (S_ISDIR (sb.st_mode) == 0) - { - builtin_error ("`%s': file exists but is not a directory", npath); - umask (original_umask); - free (npath); - return 1; - } - - *p++ = '/'; /* restore slash */ - while (*p == '/') + if (chmod (npath, (tail == 0) ? parent_mode : nmode) != 0) + { + builtin_error ("cannot chmod directory `%s': %s", npath, strerror (errno)); + umask (original_umask); + free (npath); + return 1; + } + if (tail == 0) + *p++ = '/'; /* restore slash */ + while (p && *p == '/') /* skip consecutive slashes or trailing slash */ p++; } - /* Create the final directory component. */ - if (stat (npath, &sb) && mkdir (npath, nmode)) - { - builtin_error ("cannot create directory `%s': %s", npath, strerror (errno)); - umask (original_umask); - free (npath); - return 1; - } - umask (original_umask); free (npath); return 0; diff --git a/execute_cmd.c b/execute_cmd.c index d4c082d0..18540409 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -121,7 +121,6 @@ extern int close (int); /* Static functions defined and used in this file. */ static void close_pipes (int, int); static void do_piping (int, int); -static void bind_lastarg (char *); static int shell_control_structure (enum command_type); static void cleanup_redirects (REDIRECT *); @@ -4000,7 +3999,7 @@ execute_cond_command (COND_COM *cond_command) } #endif /* COND_COMMAND */ -static void +void bind_lastarg (char *arg) { SHELL_VAR *var; diff --git a/execute_cmd.h b/execute_cmd.h index 37e386ab..d9c3e7b1 100644 --- a/execute_cmd.h +++ b/execute_cmd.h @@ -120,4 +120,5 @@ extern void close_all_files (void); extern void restore_funcarray_state (struct func_array_state *); #endif +extern void bind_lastarg (char *); #endif /* _EXECUTE_CMD_H_ */ diff --git a/parse.y b/parse.y index 379fdaad..9178e9a7 100644 --- a/parse.y +++ b/parse.y @@ -2849,7 +2849,7 @@ execute_variable_command (const char *command, const char *vname) parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE); restore_parser_state (&ps); - bind_variable ("_", last_lastarg, 0); + bind_lastarg (last_lastarg); FREE (last_lastarg); if (token_to_read == '\n') /* reset_parser was called */ @@ -5636,7 +5636,27 @@ history_delimiting_chars (const char *line) last_was_heredoc = 0; if (dstack.delimiter_depth != 0) - return ("\n"); + { + char ch; + HIST_ENTRY *current; + size_t curlen; + + ch = current_delimiter(dstack); + if (shellquote(ch)) + return ("\n"); + else if (ch == '(') /* ) and maybe for other non-quote-char delimiters */ + { + using_history (); + current = previous_history (); + curlen = current ? strlen (current->line) : 0; + /* If we're not reading some kind of quoted string, don't bother + adding a newline if the current history entry already ends in a + newline. It's just extra. */ + return ((curlen > 0 && current->line[curlen - 1] == '\n') ? "" : "\n"); + } + else + return ("\n"); + } /* We look for current_command_line_count == 2 because we are looking to add the first line of the body of the here document (the second line diff --git a/po/zh_TW.gmo b/po/zh_TW.gmo index 9dd7546f..a56fe55c 100644 Binary files a/po/zh_TW.gmo and b/po/zh_TW.gmo differ diff --git a/po/zh_TW.po b/po/zh_TW.po index 91724f83..cae84392 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -11,7 +11,7 @@ msgstr "" "Project-Id-Version: bash 5.2-rc1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-01-11 14:50-0500\n" -"PO-Revision-Date: 2022-07-28 01:08+0800\n" +"PO-Revision-Date: 2023-02-09 00:40+0800\n" "Last-Translator: Yi-Jyun Pan \n" "Language-Team: Chinese (traditional) \n" "Language: zh_TW\n" @@ -20,7 +20,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Bugs: Report translation errors to the Language-Team address.\n" -"X-Generator: Poedit 3.1.1\n" +"X-Generator: Poedit 3.2.2\n" #: arrayfunc.c:66 msgid "bad array subscript" @@ -2762,7 +2762,7 @@ msgstr "" " 變更目前目錄至 <目錄>。預設的 <目錄> 是 shell 變數 HOME\n" " 的值。\n" " \n" -" 變數 CDPATH 定義了含有 <目錄> 的目錄搜尋路徑,其中不同的目錄名稱由冒號 (:)分隔。\n" +" 變數 CDPATH 定義了含有 <目錄> 的目錄搜尋路徑,其中不同的目錄名稱由冒號 (:) 分隔。\n" " 一個空的目錄名稱表示目前目錄。如果要切換到的 <目錄> 由斜線 (/) 開頭,則 CDPATH\n" " 變數不會被使用。\n" " \n" @@ -3188,7 +3188,7 @@ msgstr "" " Getopts 被 shell 過程用來將可定位的參數解析為選項。\n" " \n" " <選項字串> 字串包含待識別的選項字母。如果一個字母後面跟\n" -" 著分號,則該選項需要一個參數,這個參數應利用空格與選項分開。\n" +" 著冒號,則該選項需要一個參數,這個參數應利用空格與選項分開。\n" " \n" " 每次呼叫時,getopts 會將下一個選項放到 shell 變數 $name\n" " 中,如果 name 變數不存在則先將其初始化,而下一個待處\n" @@ -5007,22 +5007,22 @@ msgstr "" "常用 shell 變數名稱和使用。\n" " \n" " BASH_VERSION\t目前 Bash 的版本資訊。\n" -" CDPATH\t用於「cd」指令參數搜尋分號分隔的目錄列表\n" +" CDPATH\t傳入「cd」作為引數,冒號分隔的欲搜尋目錄清單\n" " GLOBIGNORE\t路徑擴充套件時忽略的檔名符合模式列表,\n" -" \t\t以分號分隔。\n" -" HISTFILE\t您的指令歷史記錄存放的檔案名稱。\n" +" \t\t以冒號分隔。\n" +" HISTFILE\t您的命令歷史記錄存放的檔案名稱。\n" " HISTFILESIZE\t歷史記錄檔案最多可以儲存的列數。\n" -" HISTSIZE\t一個執行的 shell 最多可以訪問的歷史記錄指令列數。\n" +" HISTSIZE\t一個執行的 shell 最多可以存取的歷史記錄命令列數。\n" " HOME\t您登入目錄的完整路徑。\n" " HOSTNAME\t目前主機的主機名稱。\n" " HOSTTYPE\t目前版本的 BASH 在其之上執行的 CPU 類型。\n" " IGNOREEOF\t控制 shell 收到檔案結束符做為單一輸入後的\n" " \t\t動作。如果設定這個變數,則它的值是 shell 結束之前在\n" " \t\t一個空列上可以連續看到的檔案結束符數量(預設為 10)。\n" -" \t\t未設定時,檔案結束符標誌著輸入的結束。\n" +" \t\t未設定時,檔案結束符旗標著輸入的結束。\n" " MACHTYPE\t描述目前執行 Bash 的系統字串。\n" " MAILCHECK\tBash 檢測新郵件的頻率,以秒為單位。\n" -" MAILPATH\tBash 從中檢測新郵件的檔案列表,以分號分隔。\n" +" MAILPATH\tBash 從中檢測新郵件的檔案列表,以冒號分隔。\n" " OSTYPE\t執行 Bash 的 Unix 版本。\n" " PATH\t當尋找指令時搜尋的目錄列表,以冒號分隔。\n" " PROMPT_COMMAND\t印出每一個主提示符之前執行的命\n"