From 701f36c2c3f445485a770639b349a2014cbd0166 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Wed, 22 Dec 2021 16:05:39 -0500 Subject: [PATCH] more changes to avoid expanding associative array subscripts twice; internal debugging changes --- CWRU/CWRU.chlog | 52 ++++++ MANIFEST | 2 + arrayfunc.c | 2 - builtins/command.def | 4 +- builtins/common.c | 6 +- builtins/evalstring.c | 5 +- doc/bash.1 | 4 +- doc/bashref.texi | 4 +- error.c | 26 +++ error.h | 9 + execute_cmd.c | 10 +- jobs.c | 89 ++++------ parse.y | 31 ++-- po/zh_CN.gmo | Bin 149832 -> 167024 bytes po/zh_CN.po | 372 +++++++++++------------------------------- subst.c | 144 +++++++++------- tests/RUN-ONE-TEST | 2 +- tests/assoc.right | 31 ++++ tests/assoc.tests | 3 + tests/assoc16.sub | 56 +++++++ tests/comsub5.sub | 2 +- tests/heredoc.right | 8 +- tests/heredoc.tests | 4 + tests/heredoc7.sub | 29 ++++ trap.c | 8 +- unwind_prot.c | 5 +- variables.c | 4 +- 27 files changed, 462 insertions(+), 450 deletions(-) create mode 100644 tests/assoc16.sub create mode 100644 tests/heredoc7.sub diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index fc00c5a0..fe24b641 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -2737,3 +2737,55 @@ parse.y - parse_comsub: make sure the first call to shell_getc to check whether or not it's an arithmetic expansion skips a quoted newline. From a report by Robert Elz + + 12/21 + ----- +subst.c + - parameter_brace_remove_pattern,parameter_brace_patsub,parameter_brace_casemod, + parameter_brace_transform,parameter_brace_substring: now take an + array_eltstate_t * argument in place of the arrayind_t argument, pass + it to get_var_and_type; this generalizes the indexed array behavior + of expanding array subscripts once to associative arrays via an + eventual call to array_value_internal with a non-null KEY member + - get_var_and_type: now takes an array_eltstate_t * argument in place + of the arrayind_t argument; use it in calls to array_value so we + can only expand array subscripts once whether they are indexed or + associative arrays + - parameter_brace_expand_word: take an array_eltstate_t * argument in + place of the arrayind_t * argument; pass it to array_value; use a + static version (which we init and flush) if the argument passed is + NULL so we can get the right state passed back and forth + - parameter_brace_expand: pass a pointer to a static array_eltstate_t + to parameter_brace_expand_word, and use that in the various calls to + parameter_brace_XXX functions that perform specific expansions in + place of the old arrayind_t argument; make sure to flush it before + returning, even on errors + + 12/22 + ----- +{trap,variables}.c + - internal_warning: calls changed to use translatable strings + consistently + +error.[ch] + - internal_debug: new function, prints a message like internal_warning, + no-op if DEBUG is not defined + - INTERNAL_DEBUG: macro that expands to internal_debug when DEBUG is + defined, and nothing otherwise + +{jobs,trap}.c + - changed some internal_warning and internal_inform calls to use + internal_debug, since they were active only when DEBUG is defined + +parse.y + - parse_comsub: add internal_debug call when a command substitution + ends with unterminated here-documents + +builtins/common.c + - number_of_args: unconditionally return posparam_count + +{jobs,execute_cmd,subst}.c,parse.y,builtins/{command.def,evalstring.c} + - INTERNAL_DEBUG: use instead of calls to itrace protected by #ifdef + DEBUG + + diff --git a/MANIFEST b/MANIFEST index 0e1bd571..21117071 100644 --- a/MANIFEST +++ b/MANIFEST @@ -953,6 +953,7 @@ tests/assoc12.sub f tests/assoc13.sub f tests/assoc14.sub f tests/assoc15.sub f +tests/assoc16.sub f tests/attr.tests f tests/attr.right f tests/attr1.sub f @@ -1157,6 +1158,7 @@ tests/heredoc3.sub f tests/heredoc4.sub f tests/heredoc5.sub f tests/heredoc6.sub f +tests/heredoc7.sub f tests/herestr.tests f tests/herestr.right f tests/herestr1.sub f diff --git a/arrayfunc.c b/arrayfunc.c index 7b6feb52..11b03ca9 100644 --- a/arrayfunc.c +++ b/arrayfunc.c @@ -1556,8 +1556,6 @@ array_value_internal (s, quoted, flags, estatep) } else if (assoc_p (var)) { -if (flags & AV_USEIND) - itrace("array_value_internal: %s: assoc var with AV_USEIND: %s", dollar_vars[0], s); t[len - 1] = '\0'; if (estatep) estatep->type = ARRAY_ASSOC; diff --git a/builtins/command.def b/builtins/command.def index acd46cc1..3efdbe6b 100644 --- a/builtins/command.def +++ b/builtins/command.def @@ -124,9 +124,7 @@ command_builtin (list) #define COMMAND_BUILTIN_FLAGS (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION | CMD_COMMAND_BUILTIN | (use_standard_path ? CMD_STDPATH : 0)) -#ifdef DEBUG - itrace("command_builtin: running execute_command for `%s'", list->word->word); -#endif + INTERNAL_DEBUG (("command_builtin: running execute_command for `%s'", list->word->word)); /* We don't want this to be reparsed (consider command echo 'foo &'), so just make a simple_command structure and call execute_command with it. */ diff --git a/builtins/common.c b/builtins/common.c index f7030118..e168d875 100644 --- a/builtins/common.c +++ b/builtins/common.c @@ -458,7 +458,7 @@ shift_args (times) int number_of_args () { -#ifdef DEBUG +#if 0 register WORD_LIST *list; int n; @@ -469,9 +469,9 @@ number_of_args () if (n != posparam_count) itrace("number_of_args: n (%d) != posparam_count (%d)", n, posparam_count); -#endif - +#else return posparam_count; +#endif } static int changed_dollar_vars; diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 59c0fad1..3801a7a0 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -614,9 +614,8 @@ parse_string (string, from_file, flags, cmdp, endp) if (code) { -#if defined (DEBUG) -itrace("parse_string: longjmp executed: code = %d", code); -#endif + INTERNAL_DEBUG(("parse_string: longjmp executed: code = %d", code)); + should_jump_to_top_level = 0; switch (code) { diff --git a/doc/bash.1 b/doc/bash.1 index 43fc4530..34a01f46 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -9953,7 +9953,9 @@ Exit after reading and executing one command. .TP 8 .B \-u Treat unset variables and parameters other than the special -parameters "@" and "*" as an error when performing +parameters "@" and "*", +or array variables subscripted with "@" or "*", +as an error when performing parameter expansion. If expansion is attempted on an unset variable or parameter, the shell prints an error message, and, if not interactive, exits with a non-zero status. diff --git a/doc/bashref.texi b/doc/bashref.texi index f831ff04..df64c302 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -5370,7 +5370,9 @@ Exit after reading and executing one command. @item -u Treat unset variables and parameters other than the special parameters -@samp{@@} or @samp{*} as an error when performing parameter expansion. +@samp{@@} or @samp{*}, +or array variables subscripted with @samp{@@} or @samp{*}, +as an error when performing parameter expansion. An error message will be written to the standard error, and a non-interactive shell will exit. diff --git a/error.c b/error.c index b0ac7950..3e7a2d61 100644 --- a/error.c +++ b/error.c @@ -294,6 +294,32 @@ internal_inform (format, va_alist) va_end (args); } +void +#if defined (PREFER_STDARG) +internal_debug (const char *format, ...) +#else +internal_debug (format, va_alist) + const char *format; + va_dcl +#endif +{ +#ifdef DEBUG + va_list args; + + error_prolog (1); + fprintf (stderr, _("DEBUG warning: ")); + + SH_VA_START (args, format); + + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + + va_end (args); +#else + return; +#endif +} + void #if defined (PREFER_STDARG) sys_error (const char *format, ...) diff --git a/error.h b/error.h index 30828095..785c1deb 100644 --- a/error.h +++ b/error.h @@ -50,6 +50,9 @@ extern void internal_error PARAMS((const char *, ...)) __attribute__((__format_ /* Report an internal warning. */ extern void internal_warning PARAMS((const char *, ...)) __attribute__((__format__ (printf, 1, 2))); +/* Report an internal warning for debugging purposes. */ +extern void internal_debug PARAMS((const char *, ...)) __attribute__((__format__ (printf, 1, 2))); + /* Report an internal informational notice. */ extern void internal_inform PARAMS((const char *, ...)) __attribute__((__format__ (printf, 1, 2))); @@ -70,4 +73,10 @@ extern void err_badarraysub PARAMS((const char *)); extern void err_unboundvar PARAMS((const char *)); extern void err_readonly PARAMS((const char *)); +#ifdef DEBUG +# define INTERNAL_DEBUG(x) internal_debug x +#else +# define INTERNAL_DEBUG(x) +#endif + #endif /* !_ERROR_H_ */ diff --git a/execute_cmd.c b/execute_cmd.c index f2a08bf7..b4f71b19 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -1837,9 +1837,7 @@ cpl_delete (pid) if (p == 0) return 0; /* not found */ -#if defined (DEBUG) - itrace("cpl_delete: deleting %d", pid); -#endif + INTERNAL_DEBUG (("cpl_delete: deleting %d", pid)); /* Housekeeping in the border cases. */ if (p == coproc_list.head) @@ -1870,11 +1868,7 @@ cpl_reap () if (p->coproc->c_flags & COPROC_DEAD) { coproc_list.ncoproc--; /* keep running count, fix up pointers later */ - -#if defined (DEBUG) - itrace("cpl_reap: deleting %d", p->coproc->c_pid); -#endif - + INTERNAL_DEBUG (("cpl_reap: deleting %d", p->coproc->c_pid)); coproc_dispose (p->coproc); cpe_dispose (p); } diff --git a/jobs.c b/jobs.c index 867a0477..d2116560 100644 --- a/jobs.c +++ b/jobs.c @@ -835,9 +835,7 @@ bgp_add (pid, status) /* XXX - what if psi == *bucket? */ if (psi == *bucket) { -#ifdef DEBUG - internal_warning ("hashed pid %d (pid %d) collides with bgpids.head, skipping", psi, pid); -#endif + internal_debug ("hashed pid %d (pid %d) collides with bgpids.head, skipping", psi, pid); bgpids.storage[psi].pid = NO_PID; /* make sure */ psi = bgp_getindex (); /* skip to next one */ } @@ -1223,12 +1221,10 @@ cleanup_dead_jobs () /* XXX could use js.j_firstj and js.j_lastj here */ for (i = 0; i < js.j_jobslots; i++) { -#if defined (DEBUG) if (i < js.j_firstj && jobs[i]) - itrace("cleanup_dead_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj); + INTERNAL_DEBUG (("cleanup_dead_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj)); if (i > js.j_lastj && jobs[i]) - itrace("cleanup_dead_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj); -#endif + INTERNAL_DEBUG(("cleanup_dead_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj)); if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i)) delete_job (i, 0); @@ -1275,16 +1271,12 @@ delete_old_job (pid) job = find_job (pid, 0, &p); if (job != NO_JOB) { -#ifdef DEBUG - itrace ("delete_old_job: found pid %d in job %d with state %d", pid, job, jobs[job]->state); -#endif + INTERNAL_DEBUG (("delete_old_job: found pid %d in job %d with state %d", pid, job, jobs[job]->state)); if (JOBSTATE (job) == JDEAD) delete_job (job, DEL_NOBGPID); else { -#ifdef DEBUG - internal_warning (_("forked pid %d appears in running job %d"), pid, job+1); -#endif + internal_debug (_("forked pid %d appears in running job %d"), pid, job+1); if (p) p->pid = 0; } @@ -1432,9 +1424,7 @@ delete_job (job_index, dflags) js.j_ndead--; if (js.c_reaped < 0) { -#ifdef DEBUG - itrace("delete_job (%d pgrp %d): js.c_reaped (%d) < 0 ndel = %d js.j_ndead = %d", job_index, temp->pgrp, js.c_reaped, ndel, js.j_ndead); -#endif + INTERNAL_DEBUG (("delete_job (%d pgrp %d): js.c_reaped (%d) < 0 ndel = %d js.j_ndead = %d", job_index, temp->pgrp, js.c_reaped, ndel, js.j_ndead)); js.c_reaped = 0; } } @@ -1506,10 +1496,8 @@ add_process (name, pid) p = find_process (pid, 0, &j); if (p) { -# ifdef DEBUG if (j == NO_JOB) - internal_warning ("add_process: process %5ld (%s) in the_pipeline", (long)p->pid, p->command); -# endif + internal_debug ("add_process: process %5ld (%s) in the_pipeline", (long)p->pid, p->command); if (PALIVE (p)) internal_warning (_("add_process: pid %5ld (%s) marked as still alive"), (long)p->pid, p->command); p->running = PS_RECYCLED; /* mark as recycled */ @@ -1621,12 +1609,11 @@ map_over_jobs (func, arg1, arg2) /* XXX could use js.j_firstj here */ for (i = result = 0; i < js.j_jobslots; i++) { -#if defined (DEBUG) if (i < js.j_firstj && jobs[i]) - itrace("map_over_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj); + INTERNAL_DEBUG (("map_over_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj)); if (i > js.j_lastj && jobs[i]) - itrace("map_over_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj); -#endif + INTERNAL_DEBUG (("map_over_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj)); + if (jobs[i]) { result = (*func)(jobs[i], arg1, arg2, i); @@ -1785,12 +1772,11 @@ find_job (pid, alive_only, procp) /* XXX could use js.j_firstj here, and should check js.j_lastj */ for (i = 0; i < js.j_jobslots; i++) { -#if defined (DEBUG) if (i < js.j_firstj && jobs[i]) - itrace("find_job: job %d non-null before js.j_firstj (%d)", i, js.j_firstj); + INTERNAL_DEBUG (("find_job: job %d non-null before js.j_firstj (%d)", i, js.j_firstj)); if (i > js.j_lastj && jobs[i]) - itrace("find_job: job %d non-null after js.j_lastj (%d)", i, js.j_lastj); -#endif + INTERNAL_DEBUG (("find_job: job %d non-null after js.j_lastj (%d)", i, js.j_lastj)); + if (jobs[i]) { p = jobs[i]->pipe; @@ -2675,12 +2661,11 @@ wait_for_background_pids (ps) /* XXX could use js.j_firstj and js.j_lastj here */ for (i = 0; i < js.j_jobslots; i++) { -#if defined (DEBUG) if (i < js.j_firstj && jobs[i]) - itrace("wait_for_background_pids: job %d non-null before js.j_firstj (%d)", i, js.j_firstj); + INTERNAL_DEBUG (("wait_for_background_pids: job %d non-null before js.j_firstj (%d)", i, js.j_firstj)); if (i > js.j_lastj && jobs[i]) - itrace("wait_for_background_pids: job %d non-null after js.j_lastj (%d)", i, js.j_lastj); -#endif + INTERNAL_DEBUG (("wait_for_background_pids: job %d non-null after js.j_lastj (%d)", i, js.j_lastj)); + if (jobs[i] && STOPPED (i)) { builtin_warning ("job %d[%d] stopped", i+1, find_last_pid (i, 0)); @@ -2940,11 +2925,7 @@ wait_for (pid, flags) temp_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler); if (temp_sigint_handler == wait_sigint_handler) - { -#if defined (DEBUG) - internal_warning ("wait_for: recursively setting old_sigint_handler to wait_sigint_handler: running_trap = %d", running_trap); -#endif - } + internal_debug ("wait_for: recursively setting old_sigint_handler to wait_sigint_handler: running_trap = %d", running_trap); else old_sigint_handler = temp_sigint_handler; waiting_for_child = 0; @@ -4712,9 +4693,7 @@ maybe_give_terminal_to (opgrp, npgrp, flags) } else if (tpgrp != opgrp) { -#if defined (DEBUG) - internal_warning ("%d: maybe_give_terminal_to: terminal pgrp == %d shell pgrp = %d new pgrp = %d in_background = %d", (int)getpid(), tpgrp, opgrp, npgrp, running_in_background); -#endif + internal_debug ("%d: maybe_give_terminal_to: terminal pgrp == %d shell pgrp = %d new pgrp = %d in_background = %d", (int)getpid(), tpgrp, opgrp, npgrp, running_in_background); return -1; } else @@ -4743,12 +4722,11 @@ delete_all_jobs (running_only) /* XXX could use js.j_firstj here */ for (i = 0; i < js.j_jobslots; i++) { -#if defined (DEBUG) if (i < js.j_firstj && jobs[i]) - itrace("delete_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj); + INTERNAL_DEBUG (("delete_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj)); if (i > js.j_lastj && jobs[i]) - itrace("delete_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj); -#endif + INTERNAL_DEBUG (("delete_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj)); + if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i)))) /* We don't want to add any of these pids to bgpids. If running_only is non-zero, we don't want to add running jobs to the list. @@ -4804,12 +4782,11 @@ count_all_jobs () /* XXX could use js.j_firstj here */ for (i = n = 0; i < js.j_jobslots; i++) { -#if defined (DEBUG) if (i < js.j_firstj && jobs[i]) - itrace("count_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj); + INTERNAL_DEBUG (("count_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj)); if (i > js.j_lastj && jobs[i]) - itrace("count_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj); -#endif + INTERNAL_DEBUG (("count_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj)); + if (jobs[i] && DEADJOB(i) == 0) n++; } @@ -4879,12 +4856,11 @@ mark_dead_jobs_as_notified (force) /* XXX could use js.j_firstj here */ for (i = ndead = ndeadproc = 0; i < js.j_jobslots; i++) { -#if defined (DEBUG) if (i < js.j_firstj && jobs[i]) - itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj); + INTERNAL_DEBUG (("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj)); if (i > js.j_lastj && jobs[i]) - itrace("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj); -#endif + INTERNAL_DEBUG (("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj)); + if (jobs[i] && DEADJOB (i)) { ndead++; @@ -4892,14 +4868,12 @@ mark_dead_jobs_as_notified (force) } } -#ifdef DEBUG # if 0 if (ndeadproc != js.c_reaped) itrace("mark_dead_jobs_as_notified: ndeadproc (%d) != js.c_reaped (%d)", ndeadproc, js.c_reaped); # endif if (ndead != js.j_ndead) - itrace("mark_dead_jobs_as_notified: ndead (%d) != js.j_ndead (%d)", ndead, js.j_ndead); -#endif + INTERNAL_DEBUG (("mark_dead_jobs_as_notified: ndead (%d) != js.j_ndead (%d)", ndead, js.j_ndead)); if (js.c_childmax < 0) set_maxchild (0); @@ -4932,12 +4906,11 @@ itrace("mark_dead_jobs_as_notified: child_max = %d ndead = %d ndeadproc = %d", j { if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid))) { -#if defined (DEBUG) if (i < js.j_firstj && jobs[i]) - itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj); + INTERNAL_DEBUG (("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj)); if (i > js.j_lastj && jobs[i]) - itrace("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj); -#endif + INTERNAL_DEBUG (("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj)); + /* If marking this job as notified would drop us down below child_max, don't mark it so we can keep at least child_max statuses. XXX -- need to check what Posix actually says diff --git a/parse.y b/parse.y index cae84e33..e3b6e6d8 100644 --- a/parse.y +++ b/parse.y @@ -2071,12 +2071,7 @@ read_a_line (remove_quoted_newline) /* Ignore null bytes in input. */ if (c == 0) - { -#if 0 - internal_warning ("read_a_line: ignored null byte in input"); -#endif - continue; - } + continue; /* If there is no more input, then we return NULL. */ if (c == EOF) @@ -2405,9 +2400,6 @@ shell_getc (remove_quoted_newline) if (c == '\0') { -#if 0 - internal_warning ("shell_getc: ignored null byte in input"); -#endif /* If we get EOS while parsing a string, treat it as EOF so we don't just keep looping. Happens very rarely */ if (bash_input.type == st_string) @@ -2769,9 +2761,8 @@ shell_ungets (s) { /* Harder case: pushing back input string that's longer than what we've consumed from shell_input_line so far. */ -#ifdef DEBUG -itrace("shell_ungets: not at end of shell_input_line"); -#endif + INTERNAL_DEBUG (("shell_ungets: not at end of shell_input_line")); + chars_left = shell_input_line_len - shell_input_line_index; if (shell_input_line_size <= (slen + chars_left)) RESIZE_MALLOCED_BUFFER (shell_input_line, shell_input_line_index, chars_left + slen + 1, shell_input_line_size, 64); @@ -3411,9 +3402,7 @@ read_token (command) we are eval'ing a string that is an incomplete command), return EOF */ if (character == '\0' && bash_input.type == st_string && expanding_alias() == 0) { -#if defined (DEBUG) -itrace("shell_getc: bash_input.location.string = `%s'", bash_input.location.string); -#endif + INTERNAL_DEBUG (("shell_getc: bash_input.location.string = `%s'", bash_input.location.string)); EOF_Reached = 1; return (yacc_EOF); } @@ -4096,11 +4085,11 @@ parse_comsub (qc, open, close, lenp, flags) r = yyparse (); - if (need_here_doc) -{ -itrace("parse_comsub: need_here_doc = %d after yyparse()?", need_here_doc); - gather_here_documents (); -} + if (need_here_doc > 0) + { + internal_debug("command substitution: %d unterminated here-document%s", need_here_doc, (need_here_doc == 1) ? "" : "s"); + gather_here_documents (); + } parsed_command = global_command; @@ -4115,7 +4104,7 @@ itrace("parse_comsub: need_here_doc = %d after yyparse()?", need_here_doc); if (current_token != shell_eof_token) { -itrace("current_token (%d) != shell_eof_token (%c)", current_token, shell_eof_token); +INTERNAL_DEBUG(("current_token (%d) != shell_eof_token (%c)", current_token, shell_eof_token)); token_to_read = current_token; return (&matched_pair_error); } diff --git a/po/zh_CN.gmo b/po/zh_CN.gmo index 6d2dc9f92280a3857cba3b92576b27e2c04c40a1..e08b766d68a1b92f1d7b6e449feadd47b41bebe1 100644 GIT binary patch delta 27876 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 diff --git a/po/zh_CN.po b/po/zh_CN.po index 4477a812..ad8d4848 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -9,6 +9,7 @@ # liushuyu , 2016. # Mingye Wang , 2015, 2016. # Boyuan Yang <073plan@gmail.com>, 2018, 2019, 2020. +# Wenbin Lv , 2021. # # KNOWN DEFECTS (easy fixes, tedious work; sorted by priority): # 0. Translation coverage when upstream sends new strings. @@ -40,16 +41,16 @@ msgstr "" "Project-Id-Version: bash 5.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-11-28 12:51-0500\n" -"PO-Revision-Date: 2020-12-07 22:28-0500\n" -"Last-Translator: Boyuan Yang <073plan@gmail.com>\n" +"PO-Revision-Date: 2021-12-21 21:36+0800\n" +"Last-Translator: Wenbin Lv \n" "Language-Team: Chinese (simplified) \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Bugs: Report translation errors to the Language-Team address.\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Poedit 2.4.2\n" +"X-Bugs: Report translation errors to the Language-Team address.\n" +"X-Generator: Poedit 3.0.1\n" #: arrayfunc.c:66 msgid "bad array subscript" @@ -106,10 +107,9 @@ msgid "%s: missing colon separator" msgstr "%s:缺少冒号分隔符" #: bashline.c:4555 -#, fuzzy, c-format -#| msgid "`%s': cannot unbind" +#, c-format msgid "`%s': cannot unbind in command keymap" -msgstr "“%s”: 无法解除绑定" +msgstr "“%s”: 无法解除绑定命令键映射" #: braces.c:327 #, c-format @@ -175,20 +175,6 @@ msgid "only meaningful in a `for', `while', or `until' loop" msgstr "仅在 `for', `while', 或者`until' 循环中有意义" #: builtins/caller.def:136 -#, fuzzy -#| msgid "" -#| "Return the context of the current subroutine call.\n" -#| " \n" -#| " Without EXPR, returns \"$line $filename\". With EXPR, returns\n" -#| " \"$line $subroutine $filename\"; this extra information can be used to\n" -#| " provide a stack trace.\n" -#| " \n" -#| " The value of EXPR indicates how many call frames to go back before the\n" -#| " current one; the top frame is frame 0.\n" -#| " \n" -#| " Exit Status:\n" -#| " Returns 0 unless the shell is not executing a shell function or EXPR\n" -#| " is invalid." msgid "" "Returns the context of the current subroutine call.\n" " \n" @@ -199,18 +185,14 @@ msgid "" " The value of EXPR indicates how many call frames to go back before the\n" " current one; the top frame is frame 0." msgstr "" -"返回当前子调用的上下文。\n" +"返回当前子例程调用的上下文。\n" " \n" -" 不带有 EXPR 时,返回 \"$line $filename\"。带有 EXPR 时,返回\n" +" 不带有 <表达式> 时,返回 \"$line $filename\"。带有 <表达式> 时,返回\n" " \"$line $subroutine $filename\";这个额外的信息可以被用于提供\n" " 栈追踪。\n" " \n" -" EXPR 的值 显示了到当前调用帧需要回去多少个调用帧;顶部帧\n" -" 是第 0 帧。\n" -" \n" -" 退出状态:\n" -" 除非 shell 不在执行一个 shell 函数或者 EXPR 无效,否则返回结\n" -" 果为0。" +" <表达式> 表示从当前调用帧需要回去多少个调用帧;顶部帧\n" +" 是第 0 帧。" #: builtins/cd.def:327 msgid "HOME not set" @@ -468,10 +450,9 @@ msgid "cannot find %s in shared object %s: %s" msgstr "无法在共享对象 %2$s 中找到 %1$s: %3$s" #: builtins/enable.def:388 -#, fuzzy, c-format -#| msgid "%s: not dynamically loaded" +#, c-format msgid "%s: dynamic builtin already loaded" -msgstr "%s:未以动态方式加载" +msgstr "%s:动态内建已经加载" #: builtins/enable.def:392 #, c-format @@ -589,6 +570,8 @@ msgid "" "'\n" "\n" msgstr "" +"”\n" +"\n" #: builtins/help.def:185 #, c-format @@ -2453,7 +2436,7 @@ msgstr "umask [-p] [-S] [模式]" #: builtins.c:177 msgid "wait [-fn] [-p var] [id ...]" -msgstr "wait [-fn] [-p 变量] [编号 ...]" +msgstr "wait [-fn] [-p 变量] [ID ...]" #: builtins.c:181 msgid "wait [pid ...]" @@ -2540,16 +2523,12 @@ msgid "printf [-v var] format [arguments]" msgstr "printf [-v var] 格式 [参数]" #: builtins.c:231 -#, fuzzy -#| msgid "complete [-abcdefgjksuv] [-pr] [-DEI] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]" msgid "complete [-abcdefgjksuv] [-pr] [-DEI] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]" -msgstr "complete [-abcdefgjksuv] [-pr] [-DEI] [-o 选项] [-A 动作] [-G 全局模式] [-W 词语列表] [-F 函数] [-C 命令] [-X 过滤模式] [-P 前缀] [-S 后缀] [名称 ...]" +msgstr "complete [-abcdefgjksuv] [-pr] [-DEI] [-o 选项] [-A 动作] [-G 全局模式] [-W 词语列表] [-F 函数] [-C 命令] [-X 过滤模式] [-P 前缀] [-S 后缀] [名称 ...]" #: builtins.c:235 -#, fuzzy -#| msgid "compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]" msgid "compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]" -msgstr "compgen [-abcdefgjksuv] [-o 选项] [-A 动作] [-G 全局模式] [-W 词语列表] [-F 函数] [-C 命令] [-X 过滤模式] [-P 前缀] [-S 后缀] [词语]" +msgstr "compgen [-abcdefgjksuv] [-o 选项] [-A 动作] [-G 全局模式] [-W 词语列表] [-F 函数] [-C 命令] [-X 过滤模式] [-P 前缀] [-S 后缀] [词语]" #: builtins.c:239 msgid "compopt [-o|+o option] [-DEI] [name ...]" @@ -2749,18 +2728,18 @@ msgid "" " Returns 0 unless the shell is not executing a shell function or EXPR\n" " is invalid." msgstr "" -"返回当前子调用的上下文。\n" +"返回当前子例程调用的上下文。\n" " \n" -" 不带有 EXPR 时,返回 \"$line $filename\"。带有 EXPR 时,返回\n" +" 不带有 <表达式> 时,返回 \"$line $filename\"。带有 <表达式> 时,返回\n" " \"$line $subroutine $filename\";这个额外的信息可以被用于提供\n" " 栈追踪。\n" " \n" -" EXPR 的值 显示了到当前调用帧需要回去多少个调用帧;顶部帧\n" +" <表达式> 表示从当前调用帧需要回去多少个调用帧;顶部帧\n" " 是第 0 帧。\n" " \n" " 退出状态:\n" -" 除非 shell 不在执行一个 shell 函数或者 EXPR 无效,否则返回结\n" -" 果为0。" +" 除非 shell 不在执行一个 shell 函数或者 <表达式> 无效,否则返回结\n" +" 果为 0。" #: builtins.c:387 msgid "" @@ -2920,43 +2899,6 @@ msgstr "" " 返回 COMMAND 命令的返回状态,或者当找不到 COMMAND 命令时失败。" #: builtins.c:490 -#, fuzzy -#| msgid "" -#| "Set variable values and attributes.\n" -#| " \n" -#| " Declare variables and give them attributes. If no NAMEs are given,\n" -#| " display the attributes and values of all variables.\n" -#| " \n" -#| " Options:\n" -#| " -f\trestrict action or display to function names and definitions\n" -#| " -F\trestrict display to function names only (plus line number and\n" -#| " \t\tsource file when debugging)\n" -#| " -g\tcreate global variables when used in a shell function; otherwise\n" -#| " \t\tignored\n" -#| " -p\tdisplay the attributes and value of each NAME\n" -#| " \n" -#| " Options which set attributes:\n" -#| " -a\tto make NAMEs indexed arrays (if supported)\n" -#| " -A\tto make NAMEs associative arrays (if supported)\n" -#| " -i\tto make NAMEs have the `integer' attribute\n" -#| " -l\tto convert the value of each NAME to lower case on assignment\n" -#| " -n\tmake NAME a reference to the variable named by its value\n" -#| " -r\tto make NAMEs readonly\n" -#| " -t\tto make NAMEs have the `trace' attribute\n" -#| " -u\tto convert the value of each NAME to upper case on assignment\n" -#| " -x\tto make NAMEs export\n" -#| " \n" -#| " Using `+' instead of `-' turns off the given attribute.\n" -#| " \n" -#| " Variables with the integer attribute have arithmetic evaluation (see\n" -#| " the `let' command) performed when the variable is assigned a value.\n" -#| " \n" -#| " When used in a function, `declare' makes NAMEs local, as with the `local'\n" -#| " command. The `-g' option suppresses this behavior.\n" -#| " \n" -#| " Exit Status:\n" -#| " Returns success unless an invalid option is supplied or a variable\n" -#| " assignment error occurs." msgid "" "Set variable values and attributes.\n" " \n" @@ -3005,6 +2947,7 @@ msgstr "" " -f\t限制动作或显示为仅函数名称和定义\n" " -F\t限制仅显示函数名称 (以及调试时显示行号和源文件名)\n" " -g\t当用于 shell 函数内时创建全局变量; 否则忽略\n" +" -I\t当创建局部变量时,继承上一个作用域的同名变量的属性和值\n" " -p\t显示每个 NAME 变量的属性和值\n" " \n" " 设定属性的选项:\n" @@ -3221,45 +3164,6 @@ msgstr "" " 以命令的状态退出,或者在命令为空的情况下返回成功。" #: builtins.c:652 -#, fuzzy -#| msgid "" -#| "Parse option arguments.\n" -#| " \n" -#| " Getopts is used by shell procedures to parse positional parameters\n" -#| " as options.\n" -#| " \n" -#| " OPTSTRING contains the option letters to be recognized; if a letter\n" -#| " is followed by a colon, the option is expected to have an argument,\n" -#| " which should be separated from it by white space.\n" -#| " \n" -#| " Each time it is invoked, getopts will place the next option in the\n" -#| " shell variable $name, initializing name if it does not exist, and\n" -#| " the index of the next argument to be processed into the shell\n" -#| " variable OPTIND. OPTIND is initialized to 1 each time the shell or\n" -#| " a shell script is invoked. When an option requires an argument,\n" -#| " getopts places that argument into the shell variable OPTARG.\n" -#| " \n" -#| " getopts reports errors in one of two ways. If the first character\n" -#| " of OPTSTRING is a colon, getopts uses silent error reporting. In\n" -#| " this mode, no error messages are printed. If an invalid option is\n" -#| " seen, getopts places the option character found into OPTARG. If a\n" -#| " required argument is not found, getopts places a ':' into NAME and\n" -#| " sets OPTARG to the option character found. If getopts is not in\n" -#| " silent mode, and an invalid option is seen, getopts places '?' into\n" -#| " NAME and unsets OPTARG. If a required argument is not found, a '?'\n" -#| " is placed in NAME, OPTARG is unset, and a diagnostic message is\n" -#| " printed.\n" -#| " \n" -#| " If the shell variable OPTERR has the value 0, getopts disables the\n" -#| " printing of error messages, even if the first character of\n" -#| " OPTSTRING is not a colon. OPTERR has the value 1 by default.\n" -#| " \n" -#| " Getopts normally parses the positional parameters ($0 - $9), but if\n" -#| " more arguments are given, they are parsed instead.\n" -#| " \n" -#| " Exit Status:\n" -#| " Returns success if an option is found; fails if the end of options is\n" -#| " encountered or an error occurs." msgid "" "Parse option arguments.\n" " \n" @@ -3301,37 +3205,36 @@ msgid "" msgstr "" "解析选项参数。\n" " \n" -" getopts 被 shell 过程用于解析可定位的参数作为选项。\n" +" getopts 可在 shell 过程中使用,用于解析位置参数作为选项。\n" " \n" " \n" -" OPTSTRING 字符串包含待识别的选项字母;如果一个字母后面跟\n" -" 着分号,则该选项需要一个参数,而该参数应用空格与选项分开。\n" +" <选项字符串> 包含待识别的选项字母;如果一个字母后面跟\n" +" 着冒号,则该选项需要一个参数,参数与选项之间应当用空格隔开。\n" " \n" " \n" -" 每次启动时,getopts 会将下一个选项放到 shell 变量 $name\n" -" 中,如果 name 变量不存在则先将其初始化,而下一个待处\n" -" 理的参数序号放入 shell 变量 OPTIND 中。OPTIND 变量在每\n" -" 次 shell 或者 shell 脚本启动时都被初始化为1。当一个选项要\n" -" 求有一个参数时,getopts 将参数放入 shell 变量 OPTARG\n" -" 中。\n" +" 每次被调用时,getopts 会将下一个选项放到 shell 变量 $name\n" +" 中,如果 <名称> 变量不存在则先将其初始化,并将下一个待处\n" +" 理的参数的序号放入 shell 变量 OPTIND 中。OPTIND 变量在每\n" +" 次 shell 或者 shell 脚本启动时都被初始化为 1。当一个选项要\n" +" 求有一个参数时,getopts 将该参数放入 shell 变量 OPTARG 中。\n" " \n" " getopts 有两种报告错误的方法。如果 OPTSTRING 变量的第\n" " 一个字符是冒号,getopts 使用沉默错误报告。在这种模式\n" -" 下,不会打印错误消息。如果看到了一个无效的选项,\n" -" getopts 将找到的选项字符放至 OPTARG 变量中。如果一个必\n" -" 须的选项没有找到,getopts 放一个 ':' 到 NAME 变量中并且设\n" +" 下,不会打印错误消息。如果遇到了一个无效的选项,\n" +" getopts 将找到的选项字符放至 OPTARG 变量中。如果没有找到\n" +" 必需的参数,getopts 放一个 ':' 到 <名称> 变量中并且设\n" " 置 OPTARG 变量为找到的选项字符。如果 getopts 不在沉默模\n" -" 式中,并且遇到了一个无效的选项,getopts 放置一个 '?' 到 NAME \n" -" 变量中并且取消设定 OPTARG变量。如果必须的选项没有找到,\n" -" 一个'?'会被放入 NAME变量中,OPTARG 将被取消设定,并且会\n" +" 式中,并且遇到了一个无效的选项,getopts 放置一个 '?' 到 <名称> \n" +" 变量中并且取消设定 OPTARG 变量。如果没有找到必需的参数,\n" +" 一个 '?' 会被放入 <名称> 变量中,OPTARG 将被取消设定,并且会\n" " 打印一个诊断信息。\n" " \n" -" 如果 shell 变量 OPTERR 的值为0,getopts 禁用\n" -" 错误信息的打印,即使 OPTSTRING 变量的第一个字符不是一\n" -" 个冒号。OPTERR 的默认值为1.\n" +" 如果 shell 变量 OPTERR 的值为 0,getopts 将会禁用\n" +" 错误信息的打印,即使 OPTSTRING 变量的第一个字符不是\n" +" 一个冒号。OPTERR 的默认值为 1。\n" " \n" -" getopts 通常解析可定位的参数($0 - $9),不过如果提供了\n" -" 更多的参数,它们反而会被解析。\n" +" getopts 通常解析位置参数($0 - $9),不过如果在 <参数> 中\n" +" 提供了参数,则转而解析它们。\n" " \n" " 退出状态:\n" " 如果一个选项被找到则返回成功;如果遇到了选项的结尾或者\n" @@ -4545,52 +4448,6 @@ msgstr "" " 如果所有的 NAME 命令都找到则返回成功;任何一个找不到则失败。" #: builtins.c:1431 -#, fuzzy -#| msgid "" -#| "Modify shell resource limits.\n" -#| " \n" -#| " Provides control over the resources available to the shell and processes\n" -#| " it creates, on systems that allow such control.\n" -#| " \n" -#| " Options:\n" -#| " -S\tuse the `soft' resource limit\n" -#| " -H\tuse the `hard' resource limit\n" -#| " -a\tall current limits are reported\n" -#| " -b\tthe socket buffer size\n" -#| " -c\tthe maximum size of core files created\n" -#| " -d\tthe maximum size of a process's data segment\n" -#| " -e\tthe maximum scheduling priority (`nice')\n" -#| " -f\tthe maximum size of files written by the shell and its children\n" -#| " -i\tthe maximum number of pending signals\n" -#| " -k\tthe maximum number of kqueues allocated for this process\n" -#| " -l\tthe maximum size a process may lock into memory\n" -#| " -m\tthe maximum resident set size\n" -#| " -n\tthe maximum number of open file descriptors\n" -#| " -p\tthe pipe buffer size\n" -#| " -q\tthe maximum number of bytes in POSIX message queues\n" -#| " -r\tthe maximum real-time scheduling priority\n" -#| " -s\tthe maximum stack size\n" -#| " -t\tthe maximum amount of cpu time in seconds\n" -#| " -u\tthe maximum number of user processes\n" -#| " -v\tthe size of virtual memory\n" -#| " -x\tthe maximum number of file locks\n" -#| " -P\tthe maximum number of pseudoterminals\n" -#| " -T\tthe maximum number of threads\n" -#| " \n" -#| " Not all options are available on all platforms.\n" -#| " \n" -#| " If LIMIT is given, it is the new value of the specified resource; the\n" -#| " special LIMIT values `soft', `hard', and `unlimited' stand for the\n" -#| " current soft limit, the current hard limit, and no limit, respectively.\n" -#| " Otherwise, the current value of the specified resource is printed. If\n" -#| " no option is given, then -f is assumed.\n" -#| " \n" -#| " Values are in 1024-byte increments, except for -t, which is in seconds,\n" -#| " -p, which is in increments of 512 bytes, and -u, which is an unscaled\n" -#| " number of processes.\n" -#| " \n" -#| " Exit Status:\n" -#| " Returns success unless an invalid option is supplied or an error occurs." msgid "" "Modify shell resource limits.\n" " \n" @@ -4646,39 +4503,40 @@ msgstr "" " 选项:\n" " -S\t使用软 (`soft') 资源限制\n" " -H\t使用硬 (`hard') 资源限制\n" -" -a\t所有当前限制都被报告\n" -" -b\t套接字缓存尺寸\n" -" -c\t创建的核文件的最大尺寸\n" -" -d\t一个进程的数据区的最大尺寸\n" -" -e\t最高的调度优先级 (`nice')\n" -" -f\t有 shell 及其子进程可以写的最大文件尺寸\n" -" -i\t最多的可以挂起的信号数\n" +" -a\t报告当前的所有限制\n" +" -b\t套接字缓冲区大小\n" +" -c\t创建的核心文件的最大大小\n" +" -d\t一个进程的数据段的最大大小\n" +" -e\t调度优先级 (`nice')的最大值\n" +" -f\tshell 及其子进程可以写的最大文件大小\n" +" -i\t可以挂起的最大信号数量\n" " -k\t分配给此进程的最大 kqueue 数量\n" -" -l\t一个进程可以锁定的最大内存尺寸\n" -" -m\t最大的内存进驻尺寸\n" -" -n\t最多的打开的文件描述符个数\n" -" -p\t管道缓冲区尺寸\n" -" -q\tPOSIX 信息队列的最大字节数\n" +" -l\t一个进程可以锁定的最大内存大小\n" +" -m\t驻留集的最大大小\n" +" -n\t打开的文件描述符的最大个数\n" +" -p\t管道缓冲区大小\n" +" -q\tPOSIX 消息队列的最大字节数\n" " -r\t实时调度的最大优先级\n" -" -s\t最大栈尺寸\n" -" -t\t最大的CPU时间,以秒为单位\n" +" -s\t最大栈大小\n" +" -t\t最大的 CPU 时间,以秒为单位\n" " -u\t最大用户进程数\n" -" -v\t虚拟内存尺寸\n" -" -x\t最大的文件锁数量\n" -" -P\t最大伪终端数量\n" +" -v\t虚拟内存大小\n" +" -x\t文件锁的最大数量\n" +" -P\t伪终端的最大数量\n" +" -R\t实时进程阻塞前可运行的最大时间\n" " -T\t最大线程数量\n" " \n" " 并非所有选项在所有系统上可用。\n" " \n" -" 如果提供了 LIMIT 变量,则它为指定资源的新的值;特别的 LIMIT 值为\n" -" `soft'、`hard'和`unlimited',分别表示当前的软限制,硬限制和无限制。\n" -" 否则打印指定资源的当前限制值,不带选项则假定为 -f\n" +" 如果提供了 <限制>,则它将成为指定资源的新的值;特殊的 <限制> 值为\n" +" `soft'、`hard' 和 `unlimited',分别表示当前的软限制,硬限制和无限制。\n" +" 否则,打印指定资源的当前限制值。如果未提供选项,则假定为 -f。\n" " \n" -" 取值都是 1024 字节为单位,除了 -t 以秒为单位,-p 以 512 字节递增,\n" -" -u 为无范围的进程数量。\n" +" 限制值都以 1024 字节为单位,除了 -t 以秒为单位,-p 以 512 字节为单位,\n" +" -u 为未经缩放的进程数量。\n" " \n" " 退出状态:\n" -" 返回成功,除非使用了无效的选项或者错误发生。" +" 返回成功,除非使用了无效的选项或者有错误发生。" #: builtins.c:1482 msgid "" @@ -4713,25 +4571,6 @@ msgstr "" " 返回成功,除非使用了无效的 MODE 模式或者选项。" #: builtins.c:1502 -#, fuzzy -#| msgid "" -#| "Wait for job completion and return exit status.\n" -#| " \n" -#| " Waits for each process identified by an ID, which may be a process ID or a\n" -#| " job specification, and reports its termination status. If ID is not\n" -#| " given, waits for all currently active child processes, and the return\n" -#| " status is zero. If ID is a job specification, waits for all processes\n" -#| " in that job's pipeline.\n" -#| " \n" -#| " If the -n option is supplied, waits for the next job to terminate and\n" -#| " returns its exit status.\n" -#| " \n" -#| " If the -f option is supplied, and job control is enabled, waits for the\n" -#| " specified ID to terminate, instead of waiting for it to change status.\n" -#| " \n" -#| " Exit Status:\n" -#| " Returns the status of the last ID; fails if ID is invalid or an invalid\n" -#| " option is given." msgid "" "Wait for job completion and return exit status.\n" " \n" @@ -4760,17 +4599,24 @@ msgid "" msgstr "" "等待任务完成并返回退出状态。\n" " \n" -" 等待以 ID 编号识别的进程,其中 ID 可以是进程编号或者任务声明,\n" -" 并报告它的终止状态。如果 ID 没有给出,则等待所有的当前活跃子\n" -" 进程,并且返回状态为零。如果 ID 是任务声明,等待任务管道中的\n" +" 等待以 识别的进程,其中 可以是进程 ID 或者任务声明,\n" +" 并报告它的终止状态。如果没有指定 ,则等待当前活跃的所有子\n" +" 进程,并且返回状态为零。如果 是任务声明,则等待该任务管道中的\n" " 所有进程。\n" " \n" -" 若给定了 -n 选项,等待下一个任务完成并返回其状态。\n" +" 若给定了 -n 选项,从 列表中等待一个单一的任务完成,\n" +" 或者,如果没有提供 ,等待下一个任务完成并返回其退出状态。\n" " \n" -" 若给定了 -f 选项,且已启用了任务控制,则等待指定的 ID 终止\n" +" 若给定了 -p 选项, 被返回退出状态的任务的进程 ID 或任务 ID 将被赋值\n" +" 给选项的参数指定的 <变量>。该变量会首先被取消设定,然后才会进行赋值。\n" +" 该选项只有和 -n 选项同时使用才有用。\n" +" \n" +" 若给定了 -f 选项,且已启用了任务控制,则等待指定的 终止,\n" " 而非等待它改变状态。\n" +" \n" " 退出状态:\n" -" 返回最后一个 ID 进程的状态;如果使用了无效的 ID 或者选项则失败。" +" 返回最后一个 的状态;如果使用了无效的 ,或者使用了无效的\n" +" 选项,或者给定了 -n 选项但 shell 没有尚未等待的子进程,则失败。" #: builtins.c:1533 msgid "" @@ -5071,15 +4917,6 @@ msgstr "" " 返回被继续的任务的状态。" #: builtins.c:1726 -#, fuzzy -#| msgid "" -#| "Evaluate arithmetic expression.\n" -#| " \n" -#| " The EXPRESSION is evaluated according to the rules for arithmetic\n" -#| " evaluation. Equivalent to \"let EXPRESSION\".\n" -#| " \n" -#| " Exit Status:\n" -#| " Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise." msgid "" "Evaluate arithmetic expression.\n" " \n" @@ -5089,13 +4926,13 @@ msgid "" " Exit Status:\n" " Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise." msgstr "" -"估值算术表达式。\n" +"对算术表达式估值。\n" " \n" -" 表达式按照算术法则进行估值。\n" -" 等价于 \"let 表达式\".\n" +" <表达式> 按照算术法则进行估值。\n" +" 等价于 \"let <表达式>\"。\n" " \n" -" 退出状态\n" -" 如果表达式估值为0则返回 1;否则返回0。" +" 退出状态:\n" +" 如果 <表达式> 估值为 0 则返回 1;否则返回 0。" #: builtins.c:1738 msgid "" @@ -5470,31 +5307,6 @@ msgstr "" " 返回成功,除非使用了无效的选项或者写或赋值错误发生。" #: builtins.c:1971 -#, fuzzy -#| msgid "" -#| "Specify how arguments are to be completed by Readline.\n" -#| " \n" -#| " For each NAME, specify how arguments are to be completed. If no options\n" -#| " are supplied, existing completion specifications are printed in a way that\n" -#| " allows them to be reused as input.\n" -#| " \n" -#| " Options:\n" -#| " -p\tprint existing completion specifications in a reusable format\n" -#| " -r\tremove a completion specification for each NAME, or, if no\n" -#| " \t\tNAMEs are supplied, all completion specifications\n" -#| " -D\tapply the completions and actions as the default for commands\n" -#| " \t\twithout any specific completion defined\n" -#| " -E\tapply the completions and actions to \"empty\" commands --\n" -#| " \t\tcompletion attempted on a blank line\n" -#| " -I\tapply the completions and actions to the initial (usually the\n" -#| " \t\tcommand) word\n" -#| " \n" -#| " When completion is attempted, the actions are applied in the order the\n" -#| " uppercase-letter options are listed above. If multiple options are supplied,\n" -#| " the -D option takes precedence over -E, and both take precedence over -I.\n" -#| " \n" -#| " Exit Status:\n" -#| " Returns success unless an invalid option is supplied or an error occurs." msgid "" "Specify how arguments are to be completed by Readline.\n" " \n" @@ -5522,15 +5334,15 @@ msgid "" msgstr "" "指定 Readline 如何补全参数。\n" " \n" -" 声明对于每一个 NAME 名称如何补全参数。如果不带选项,\n" +" 声明对于每一个 <名称> 如何补全参数。如果不带选项,\n" " 现有的补全声明会以可以重用为输入的格式打印出来。\n" " \n" " 选项:\n" -" -p\t以可重用的格式打印现有的补全声明。\n" -" -r\t对于每个 NAME 名称删除补全声明,或者如果没有提供 NAME\n" -" \t名称,删除所有的补全声明。\n" -" -D\t对于没有补全声明定义的命令,设定默认的补全动作\n" -" -E\t对于 \"empty\" 命令设定补全动作,—— 对于空行的补全。\n" +" -p\t以可重用的格式打印现有的补全声明\n" +" -r\t对每一个 <名称> 删除补全声明,或者,如果没有提供 <名称> ,\n" +" \t\t删除所有的补全声明\n" +" -D\t对于没有补全声明定义的命令,设定默认的补全和动作\n" +" -E\t对于 \"empty\" 命令设定补全动作——对于空行的补全\n" " -I\t将补全和动作应用在首单词(通常是所给命令)上\n" " \n" " 尝试补全时,按照上述大写字母选项的顺序进行动作。\n" @@ -5538,7 +5350,7 @@ msgstr "" " 这两个选项优先级均高于 -I。\n" " \n" " 退出状态:\n" -" 返回成功,除非使用了无效的选项或者错误发生。" +" 返回成功,除非使用了无效的选项或者有错误发生。" #: builtins.c:2001 msgid "" diff --git a/subst.c b/subst.c index 04fcb4d7..bf2a8d39 100644 --- a/subst.c +++ b/subst.c @@ -293,7 +293,7 @@ static char *parameter_list_remove_pattern PARAMS((int, char *, int, int)); #ifdef ARRAY_VARS static char *array_remove_pattern PARAMS((SHELL_VAR *, char *, int, int, int)); #endif -static char *parameter_brace_remove_pattern PARAMS((char *, char *, arrayind_t, char *, int, int, int)); +static char *parameter_brace_remove_pattern PARAMS((char *, char *, array_eltstate_t *, char *, int, int, int)); static char *string_var_assignment PARAMS((SHELL_VAR *, char *)); #if defined (ARRAY_VARS) @@ -306,7 +306,7 @@ static char *parameter_list_transform PARAMS((int, int, int)); #if defined ARRAY_VARS static char *array_transform PARAMS((int, SHELL_VAR *, int, int)); #endif -static char *parameter_brace_transform PARAMS((char *, char *, arrayind_t, char *, int, int, int, int)); +static char *parameter_brace_transform PARAMS((char *, char *, array_eltstate_t *, char *, int, int, int, int)); static int valid_parameter_transform PARAMS((char *)); static char *process_substitute PARAMS((char *, int)); @@ -322,7 +322,7 @@ static int valid_brace_expansion_word PARAMS((char *, int)); static int chk_atstar PARAMS((char *, int, int, int *, int *)); static int chk_arithsub PARAMS((const char *, int)); -static WORD_DESC *parameter_brace_expand_word PARAMS((char *, int, int, int, arrayind_t *)); +static WORD_DESC *parameter_brace_expand_word PARAMS((char *, int, int, int, array_eltstate_t *)); static char *parameter_brace_find_indir PARAMS((char *, int, int, int)); static WORD_DESC *parameter_brace_expand_indir PARAMS((char *, int, int, int, int *, int *)); static WORD_DESC *parameter_brace_expand_rhs PARAMS((char *, char *, int, int, int, int *, int *)); @@ -333,18 +333,18 @@ static intmax_t parameter_brace_expand_length PARAMS((char *)); static char *skiparith PARAMS((char *, int)); static int verify_substring_values PARAMS((SHELL_VAR *, char *, char *, int, intmax_t *, intmax_t *)); -static int get_var_and_type PARAMS((char *, char *, arrayind_t, int, int, SHELL_VAR **, char **)); +static int get_var_and_type PARAMS((char *, char *, array_eltstate_t *, int, int, SHELL_VAR **, char **)); static char *mb_substring PARAMS((char *, int, int)); -static char *parameter_brace_substring PARAMS((char *, char *, arrayind_t, char *, int, int, int)); +static char *parameter_brace_substring PARAMS((char *, char *, array_eltstate_t *, char *, int, int, int)); static int shouldexp_replacement PARAMS((char *)); static char *pos_params_pat_subst PARAMS((char *, char *, char *, int)); -static char *parameter_brace_patsub PARAMS((char *, char *, arrayind_t, char *, int, int, int)); +static char *parameter_brace_patsub PARAMS((char *, char *, array_eltstate_t *, char *, int, int, int)); static char *pos_params_casemod PARAMS((char *, char *, int, int)); -static char *parameter_brace_casemod PARAMS((char *, char *, arrayind_t, int, char *, int, int, int)); +static char *parameter_brace_casemod PARAMS((char *, char *, array_eltstate_t *, int, char *, int, int, int)); static WORD_DESC *parameter_brace_expand PARAMS((char *, int *, int, int, int *, int *)); static WORD_DESC *param_expand PARAMS((char *, int *, int, int *, int *, int *, int *, int)); @@ -4424,10 +4424,8 @@ dequote_string (string) char *result, *send; DECLARE_MBSTATE; -#if defined (DEBUG) if (string[0] == CTLESC && string[1] == 0) - internal_inform ("dequote_string: string with bare CTLESC"); -#endif + internal_debug ("dequote_string: string with bare CTLESC"); slen = STRLEN (string); @@ -5403,9 +5401,9 @@ array_remove_pattern (var, pattern, patspec, starsub, quoted) #endif /* ARRAY_VARS */ static char * -parameter_brace_remove_pattern (varname, value, ind, patstr, rtype, quoted, flags) +parameter_brace_remove_pattern (varname, value, estatep, patstr, rtype, quoted, flags) char *varname, *value; - arrayind_t ind; + array_eltstate_t *estatep; char *patstr; int rtype, quoted, flags; { @@ -5419,7 +5417,7 @@ parameter_brace_remove_pattern (varname, value, ind, patstr, rtype, quoted, flag oname = this_command_name; this_command_name = varname; - vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); + vtype = get_var_and_type (varname, value, estatep, quoted, flags, &v, &val); if (vtype == -1) { this_command_name = oname; @@ -6926,10 +6924,10 @@ chk_atstar (name, quoted, pflags, quoted_dollar_atp, contains_dollar_at) the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that NAME was found inside of a double-quoted expression. */ static WORD_DESC * -parameter_brace_expand_word (name, var_is_special, quoted, pflags, indp) +parameter_brace_expand_word (name, var_is_special, quoted, pflags, estatep) char *name; int var_is_special, quoted, pflags; - arrayind_t *indp; + array_eltstate_t *estatep; { WORD_DESC *ret; char *temp, *tt; @@ -6942,8 +6940,15 @@ parameter_brace_expand_word (name, var_is_special, quoted, pflags, indp) temp = 0; rflags = 0; - if (indp) - *indp = INTMAX_MIN; +#if defined (ARRAY_VARS) + if (estatep) + es = *estatep; /* structure copy */ + else + { + init_eltstate (&es); + es.ind = INTMAX_MIN; + } +#endif /* Handle multiple digit arguments, as in ${11}. */ if (legal_number (name, &arg_index)) @@ -6972,10 +6977,6 @@ parameter_brace_expand_word (name, var_is_special, quoted, pflags, indp) else if (valid_array_reference (name, 0)) { expand_arrayref: - init_eltstate (&es); - if (indp) - es.ind = *indp; - var = array_variable_part (name, 0, &tt, (int *)0); /* These are the cases where word splitting will not be performed */ if (pflags & PF_ASSIGNRHS) @@ -7020,11 +7021,13 @@ expand_arrayref: ? quote_string (temp) : quote_escapes (temp); rflags |= W_ARRAYIND; - if (indp) - *indp = es.ind; + if (estatep) + *estatep = es; /* structure copy */ } else if (es.subtype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) rflags |= W_HASQUOTEDNULL; + if (estatep == 0) + flush_eltstate (&es); } #endif else if (var = find_variable (name)) @@ -7763,9 +7766,9 @@ verify_substring_values (v, value, substr, vtype, e1p, e2p) characters in the value are quoted with CTLESC and takes appropriate steps. For convenience, *VALP is set to the dequoted VALUE. */ static int -get_var_and_type (varname, value, ind, quoted, flags, varp, valp) +get_var_and_type (varname, value, estatep, quoted, flags, varp, valp) char *varname, *value; - arrayind_t ind; + array_eltstate_t *estatep; int quoted, flags; SHELL_VAR **varp; char **valp; @@ -7773,8 +7776,6 @@ get_var_and_type (varname, value, ind, quoted, flags, varp, valp) int vtype, want_indir; char *temp, *vname; SHELL_VAR *v; - arrayind_t lind; - array_eltstate_t es; want_indir = *varname == '!' && (legal_variable_starter ((unsigned char)varname[1]) || DIGIT (varname[1]) @@ -7804,10 +7805,10 @@ get_var_and_type (varname, value, ind, quoted, flags, varp, valp) { v = array_variable_part (vname, 0, &temp, (int *)0); /* If we want to signal array_value to use an already-computed index, - set LIND to that index */ - lind = (ind != INTMAX_MIN && (flags & AV_USEIND)) ? ind : 0; - init_eltstate (&es); - es.ind = lind; + the caller will set ESTATEP->IND to that index and pass AV_USEIND in + FLAGS. */ + if (estatep && (flags & AV_USEIND) == 0) + estatep->ind = INTMAX_MIN; if (v && invisible_p (v)) { @@ -7828,7 +7829,7 @@ get_var_and_type (varname, value, ind, quoted, flags, varp, valp) else { vtype = VT_ARRAYMEMBER; - *valp = array_value (vname, Q_DOUBLE_QUOTES, flags, &es); + *valp = array_value (vname, Q_DOUBLE_QUOTES, flags, estatep); } *varp = v; } @@ -7845,9 +7846,8 @@ get_var_and_type (varname, value, ind, quoted, flags, varp, valp) { vtype = VT_ARRAYMEMBER; *varp = v; - *valp = array_value (vname, Q_DOUBLE_QUOTES, flags, &es); + *valp = array_value (vname, Q_DOUBLE_QUOTES, flags, estatep); } - flush_eltstate (&es); } else if ((v = find_variable (vname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v))) { @@ -8171,9 +8171,9 @@ valid_parameter_transform (xform) } static char * -parameter_brace_transform (varname, value, ind, xform, rtype, quoted, pflags, flags) +parameter_brace_transform (varname, value, estatep, xform, rtype, quoted, pflags, flags) char *varname, *value; - arrayind_t ind; + array_eltstate_t *estatep; char *xform; int rtype, quoted, pflags, flags; { @@ -8188,7 +8188,7 @@ parameter_brace_transform (varname, value, ind, xform, rtype, quoted, pflags, fl oname = this_command_name; this_command_name = varname; - vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); + vtype = get_var_and_type (varname, value, estatep, quoted, flags, &v, &val); if (vtype == -1) { this_command_name = oname; @@ -8304,9 +8304,9 @@ mb_substring (string, s, e) VARNAME. If VARNAME is an array variable, use the array elements. */ static char * -parameter_brace_substring (varname, value, ind, substr, quoted, pflags, flags) +parameter_brace_substring (varname, value, estatep, substr, quoted, pflags, flags) char *varname, *value; - arrayind_t ind; + array_eltstate_t *estatep; char *substr; int quoted, pflags, flags; { @@ -8321,7 +8321,7 @@ parameter_brace_substring (varname, value, ind, substr, quoted, pflags, flags) oname = this_command_name; this_command_name = varname; - vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); + vtype = get_var_and_type (varname, value, estatep, quoted, flags, &v, &val); if (vtype == -1) { this_command_name = oname; @@ -8625,9 +8625,9 @@ pos_params_pat_subst (string, pat, rep, mflags) and the string to substitute. QUOTED is a flags word containing the type of quoting currently in effect. */ static char * -parameter_brace_patsub (varname, value, ind, patsub, quoted, pflags, flags) +parameter_brace_patsub (varname, value, estatep, patsub, quoted, pflags, flags) char *varname, *value; - arrayind_t ind; + array_eltstate_t *estatep; char *patsub; int quoted, pflags, flags; { @@ -8641,7 +8641,7 @@ parameter_brace_patsub (varname, value, ind, patsub, quoted, pflags, flags) oname = this_command_name; this_command_name = varname; /* error messages */ - vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); + vtype = get_var_and_type (varname, value, estatep, quoted, flags, &v, &val); if (vtype == -1) { this_command_name = oname; @@ -8871,9 +8871,9 @@ pos_params_modcase (string, pat, modop, mflags) to perform. QUOTED is a flags word containing the type of quoting currently in effect. */ static char * -parameter_brace_casemod (varname, value, ind, modspec, patspec, quoted, pflags, flags) +parameter_brace_casemod (varname, value, estatep, modspec, patspec, quoted, pflags, flags) char *varname, *value; - arrayind_t ind; + array_eltstate_t *estatep; int modspec; char *patspec; int quoted, pflags, flags; @@ -8888,7 +8888,7 @@ parameter_brace_casemod (varname, value, ind, modspec, patspec, quoted, pflags, oname = this_command_name; this_command_name = varname; - vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val); + vtype = get_var_and_type (varname, value, estatep, quoted, flags, &v, &val); if (vtype == -1) { this_command_name = oname; @@ -9065,7 +9065,7 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta WORD_DESC *tdesc, *ret; int t_index, sindex, c, tflag, modspec, local_pflags, all_element_arrayref; intmax_t number; - arrayind_t ind; + array_eltstate_t es; temp = temp1 = value = (char *)NULL; var_is_set = var_is_null = var_is_special = check_nullness = 0; @@ -9112,7 +9112,10 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta ret = 0; tflag = 0; - ind = INTMAX_MIN; +#if defined (ARRAY_VARS) + init_eltstate (&es); +#endif + es.ind = INTMAX_MIN; /* XXX */ /* If the name really consists of a special variable, then make sure that we have the entire name. We don't allow indirect references @@ -9353,7 +9356,7 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta else { local_pflags |= PF_IGNUNBOUND|(pflags&(PF_NOSPLIT2|PF_ASSIGNRHS)); - tdesc = parameter_brace_expand_word (name, var_is_special, quoted, local_pflags, &ind); + tdesc = parameter_brace_expand_word (name, var_is_special, quoted, local_pflags, &es); } if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal) @@ -9450,9 +9453,12 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta /* If this is a substring spec, process it and add the result. */ if (want_substring) { - temp1 = parameter_brace_substring (name, temp, ind, value, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0); + temp1 = parameter_brace_substring (name, temp, &es, value, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0); FREE (value); FREE (temp); +#if defined (ARRAY_VARS) + flush_eltstate (&es); +#endif if (temp1 == &expand_param_error || temp1 == &expand_param_fatal) { @@ -9482,9 +9488,12 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta } else if (want_patsub) { - temp1 = parameter_brace_patsub (name, temp, ind, value, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0); + temp1 = parameter_brace_patsub (name, temp, &es, value, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0); FREE (value); FREE (temp); +#if defined (ARRAY_VARS) + flush_eltstate (&es); +#endif if (temp1 == &expand_param_error || temp1 == &expand_param_fatal) { @@ -9508,9 +9517,12 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta #if defined (CASEMOD_EXPANSIONS) else if (want_casemod) { - temp1 = parameter_brace_casemod (name, temp, ind, modspec, value, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0); + temp1 = parameter_brace_casemod (name, temp, &es, modspec, value, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0); FREE (value); FREE (temp); +#if defined (ARRAY_VARS) + flush_eltstate (&es); +#endif if (temp1 == &expand_param_error || temp1 == &expand_param_fatal) { @@ -9544,6 +9556,9 @@ bad_substitution: FREE (value); FREE (temp); free (name); +#if defined (ARRAY_VARS) + flush_eltstate (&es); +#endif if (shell_compatibility_level <= 43) return &expand_wdesc_error; else @@ -9553,9 +9568,12 @@ bad_substitution: break; case '@': - temp1 = parameter_brace_transform (name, temp, ind, value, c, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0); + temp1 = parameter_brace_transform (name, temp, &es, value, c, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0); free (temp); free (value); +#if defined (ARRAY_VARS) + flush_eltstate (&es); +#endif if (temp1 == &expand_param_error || temp1 == &expand_param_fatal) { @@ -9583,9 +9601,12 @@ bad_substitution: FREE (value); break; } - temp1 = parameter_brace_remove_pattern (name, temp, ind, value, c, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0); + temp1 = parameter_brace_remove_pattern (name, temp, &es, value, c, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0); free (temp); free (value); +#if defined (ARRAY_VARS) + flush_eltstate (&es); +#endif ret = alloc_word_desc (); ret->word = temp1; @@ -9652,11 +9673,17 @@ bad_substitution: report_error (_("$%s: cannot assign in this way"), name); free (name); free (value); +#if defined (ARRAY_VARS) + flush_eltstate (&es); +#endif return &expand_wdesc_error; } else if (c == '?') { parameter_brace_expand_error (name, value, check_nullness); +#if defined (ARRAY_VARS) + flush_eltstate (&es); +#endif return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal); } else if (c != '+') @@ -9686,6 +9713,9 @@ bad_substitution: break; } free (name); +#if defined (ARRAY_VARS) + flush_eltstate (&es); +#endif if (ret == 0) { @@ -10202,7 +10232,7 @@ comsub: if (temp && *temp && valid_array_reference (temp, 0)) { chk_atstar (temp, quoted, pflags, quoted_dollar_at_p, contains_dollar_at); - tdesc = parameter_brace_expand_word (temp, SPECIAL_VAR (temp, 0), quoted, pflags, (arrayind_t *)NULL); + tdesc = parameter_brace_expand_word (temp, SPECIAL_VAR (temp, 0), quoted, pflags, 0); if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal) return (tdesc); ret = tdesc; @@ -10337,8 +10367,8 @@ expand_array_subscript (string, sindex, quoted, flags) if (ni >= slen || string[ni] != RBRACK || (ni - si) == 1 || (string[ni+1] != '\0' && (quoted & Q_ARITH) == 0)) { -/* let's check and see what fails this check */ -itrace("expand_array_subscript: bad subscript string: `%s'", string+si); + /* let's check and see what fails this check */ + INTERNAL_DEBUG (("expand_array_subscript: bad subscript string: `%s'", string+si)); ret = (char *)xmalloc (2); /* badly-formed subscript */ ret[0] = string[si]; ret[1] = '\0'; diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 0b063810..c8bef8dd 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/chet/bash/bash-current +BUILD_DIR=/usr/local/build/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/tests/assoc.right b/tests/assoc.right index f2351a3d..1d558228 100644 --- a/tests/assoc.right +++ b/tests/assoc.right @@ -352,3 +352,34 @@ declare -A var=([two]=$'ab\001cd' [one]=$'\001\001\001\001' ) declare -A foo=([two]=$'ab\001cd' [one]=$'\001\001\001\001' ) declare -A foo=([$'\001']=$'ab\001cd' ) declare -A foo=([$'\001']=$'\001\001\001\001' ) +declare -A A=(["\$(echo Darwin ; echo stderr>&2)"]="darjeeling" [Darwin]="darjeeling" ) +stderr +darjsharking +darjsharking +stderr +darj +darj +stderr +DARJEELING +DARJEELING +stderr +'darjeeling' +'darjeeling' +stderr +darjeel +darjeel +stderr +10 +10 +stderr +darjeeling +darjeeling +stderr +set +set +stderr +set +set +stderr +42 +42 diff --git a/tests/assoc.tests b/tests/assoc.tests index 30e5201d..5dd90ce5 100644 --- a/tests/assoc.tests +++ b/tests/assoc.tests @@ -256,3 +256,6 @@ ${THIS_SH} ./assoc14.sub # tests with subscripts and values containing 0x01 (some indexed array tests too) ${THIS_SH} ./assoc15.sub + +# tests with subscripts being expanded more than one in ${xxx} word expansions +${THIS_SH} ./assoc16.sub diff --git a/tests/assoc16.sub b/tests/assoc16.sub new file mode 100644 index 00000000..ae8296b3 --- /dev/null +++ b/tests/assoc16.sub @@ -0,0 +1,56 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# bash versions up to and including bash-5.1 expanded these subscripts more +# than once + +declare -A A + +A["Darwin"]=darjeeling +A['$(echo Darwin ; echo stderr>&2)']=darjeeling + +declare -p A + +echo ${A[$(echo Darwin ; echo stderr>&2)]//eel/shark} +echo ${A['$(echo Darwin ; echo stderr>&2)']//eel/shark} + +echo ${A[$(echo Darwin ; echo stderr>&2)]:0:4} +echo ${A['$(echo Darwin ; echo stderr>&2)']:0:4} + +echo ${A[$(echo Darwin ; echo stderr>&2)]^^} +echo ${A['$(echo Darwin ; echo stderr>&2)']^^} + +echo ${A[$(echo Darwin ; echo stderr>&2)]@Q} +echo ${A['$(echo Darwin ; echo stderr>&2)']@Q} + +echo ${A[$(echo Darwin ; echo stderr>&2)]%ing} +echo ${A['$(echo Darwin ; echo stderr>&2)']%ing} + +echo ${#A[$(echo Darwin ; echo stderr>&2)]} +echo ${#A['$(echo Darwin ; echo stderr>&2)']} + +echo ${A[$(echo Darwin ; echo stderr>&2)]:-value} +echo ${A['$(echo Darwin ; echo stderr>&2)']:-value} + +echo ${A[$(echo Darwin ; echo stderr>&2)]:+set} +echo ${A['$(echo Darwin ; echo stderr>&2)']:+set} + +echo ${A[$(echo Darwin ; echo stderr>&2)]:+set} +echo ${A['$(echo Darwin ; echo stderr>&2)']:+set} + +darjeeling=7*6 +Darwin=7*4 + +echo $(( ${A[$(echo Darwin ; echo stderr>&2)]} )) +echo $(( ${A['$(echo Darwin ; echo stderr>&2)']} )) diff --git a/tests/comsub5.sub b/tests/comsub5.sub index 00a30b44..1ec41645 100644 --- a/tests/comsub5.sub +++ b/tests/comsub5.sub @@ -13,7 +13,7 @@ # # this is a new feature: expanding aliases when initially parsing command -# substiitutions +# substitutions shopt -s expand_aliases diff --git a/tests/heredoc.right b/tests/heredoc.right index 1f87a4e2..33da5238 100644 --- a/tests/heredoc.right +++ b/tests/heredoc.right @@ -120,7 +120,13 @@ argv[3] = 5: ${x#$pat} 6: ${y#$'not'} 7: ${y#'not'} +foo bar +./heredoc7.sub: line 21: after: command not found +./heredoc7.sub: line 29: warning: here-document at line 29 delimited by end-of-file (wanted `EOF') +./heredoc7.sub: line 29: foobar: command not found +./heredoc7.sub: line 29: EOF: command not found +grep: *.c: No such file or directory comsub here-string -./heredoc.tests: line 152: warning: here-document at line 150 delimited by end-of-file (wanted `EOF') +./heredoc.tests: line 156: warning: here-document at line 154 delimited by end-of-file (wanted `EOF') hi there diff --git a/tests/heredoc.tests b/tests/heredoc.tests index 36c005af..d10a7c10 100644 --- a/tests/heredoc.tests +++ b/tests/heredoc.tests @@ -140,6 +140,10 @@ ${THIS_SH} ./heredoc5.sub # test $'...' and $"..." quoted strings in here-documents ${THIS_SH} ./heredoc6.sub +# interaction between here-documents and command substitutions +${THIS_SH} ./heredoc7.sub + + echo $( cat <<< "comsub here-string" ) diff --git a/tests/heredoc7.sub b/tests/heredoc7.sub new file mode 100644 index 00000000..4119df19 --- /dev/null +++ b/tests/heredoc7.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# should characters outside a command substitution be interpreted as a delimiter +# for a here-document started inside it? +echo $(cat << EOF) +foo +bar +EOF +after + +# should characters inside a command substitution be interpreted as a delimiter +# for a here-document started outside of it? + +cat < 0) { -#if defined (DEBUG) - internal_warning ("run_pending_traps: recursive invocation while running trap for signal %d", running_trap-1); -#endif + internal_debug ("run_pending_traps: recursive invocation while running trap for signal %d", running_trap-1); #if defined (SIGWINCH) if (running_trap == SIGWINCH+1 && pending_traps[SIGWINCH]) return; /* no recursive SIGWINCH trap invocations */ @@ -475,9 +473,7 @@ trap_handler (sig) if ((sigmodes[sig] & SIG_TRAPPED) == 0) { -#if defined (DEBUG) - internal_warning ("trap_handler: signal %d: signal not trapped", sig); -#endif + internal_debug ("trap_handler: signal %d: signal not trapped", sig); SIGRETURN (0); } diff --git a/unwind_prot.c b/unwind_prot.c index 47f68c4e..ec82393d 100644 --- a/unwind_prot.c +++ b/unwind_prot.c @@ -48,6 +48,7 @@ #include "unwind_prot.h" #include "sig.h" #include "quit.h" +#include "bashintl.h" /* for _() */ #include "error.h" /* for internal_warning */ #include "ocache.h" @@ -282,7 +283,7 @@ unwind_frame_discard_internal (tag, ignore) } if (found == 0) - internal_warning ("unwind_frame_discard: %s: frame not found", tag); + internal_warning (_("unwind_frame_discard: %s: frame not found"), tag); } /* Restore the value of a variable, based on the contents of SV. @@ -328,7 +329,7 @@ unwind_frame_run_internal (tag, ignore) uwpfree (elt); } if (tag && found == 0) - internal_warning ("unwind_frame_run: %s: frame not found", tag); + internal_warning (_("unwind_frame_run: %s: frame not found"), tag); } static void diff --git a/variables.c b/variables.c index dc3f7e68..802a0510 100644 --- a/variables.c +++ b/variables.c @@ -2815,7 +2815,7 @@ make_local_array_variable (name, flags) scope and discard anything that's invalid. */ if (localvar_inherit && assoc_p (var)) { - internal_warning ("%s: cannot inherit value from incompatible type", name); + internal_warning (_("%s: cannot inherit value from incompatible type"), name); VUNSETATTR (var, att_assoc); dispose_variable_value (var); array = array_create (); @@ -2871,7 +2871,7 @@ make_local_assoc_variable (name, flags) scope and discard anything that's invalid. */ if (localvar_inherit && array_p (var)) { - internal_warning ("%s: cannot inherit value from incompatible type", name); + internal_warning (_("%s: cannot inherit value from incompatible type"), name); VUNSETATTR (var, att_array); dispose_variable_value (var); hash = assoc_create (ASSOC_HASH_BUCKETS);