expand_word_leave_quoted: if call_expand_word_internal returns an
error, return a NULL WORD_LIST *
Fixes bug with PS1 expansion reported by smart.outfit080@8shield.net
+
+config.h.in
+ - MAJOR_IN_MKDEV: fix typo
+
+ 8/8
+ ---
+execute_cmd.c
+ - CHECK_BREAK_AND_CONTINUE: macro to encapsulate common code for
+ testing `breaking' and `continuing' while in loops
+ - execute_for_command,execute_arith_for_command,execute_select_command,
+ execute_while_or_until: replace common code with CHECK_BREAK_AND_CONTINUE
+ - execute_for_command,execute_select_command: add call to
+ CHECK_BREAK_AND_CONTINUE after binding variable, in case it contains
+ a nofork comsub that executes break or continue
+ Report from Oğuz <oguzismailuysal@gmail.com>
+
+ 8/11
+ ----
+builtins/declare.def
+ - declare_internal: if the value of an assignment statement expands to
+ an invalid value for a nameref variable, but the original value is
+ valid, add an error message for the assignment error
+ Report from Oğuz <oguzismailuysal@gmail.com>
{
if (valid_nameref_value (value, 1) == 0)
sh_invalidid (value);
+ /* what else can cause this to fail? */
+ else if (flags_on & att_integer)
+ builtin_error ("%s: expands to invalid variable name for name reference", value);
assign_error++;
/* XXX - unset this variable? or leave it as normal var? */
if (created_var)
#undef HAVE_ALLOCA_H
/* Define if major/minor/makedev is defined in <sys/mkdev.h> */
-#undef MAJOR_IN_MAKEDEV
+#undef MAJOR_IN_MKDEV
/* Define if major/minor/makedev is defined in <sys/sysmacros.h> */
#undef MAJOR_IN_SYSMACROS
} \
} while (0)
+/* Common code to check whether `break' or `continue' was executed. */
+#define CHECK_BREAK_AND_CONTINUE() \
+ if (breaking) \
+ { \
+ breaking--; \
+ break; \
+ } \
+ if (continuing) \
+ { \
+ continuing--; \
+ if (continuing) \
+ break; \
+ } \
+ do { } while (0)
+
/* A sort of function nesting level counter */
int funcnest = 0;
int funcnest_max = 0;
else
v = bind_variable (identifier, list->word->word, 0);
+ CHECK_BREAK_AND_CONTINUE();
+
if (v == 0 || ASSIGN_DISALLOWED (v, 0))
{
line_number = save_line_number;
REAP ();
QUIT;
- if (breaking)
- {
- breaking--;
- break;
- }
-
- if (continuing)
- {
- continuing--;
- if (continuing)
- break;
- }
+ CHECK_BREAK_AND_CONTINUE();
}
loop_level--; interrupt_execution--; retain_fifos--;
/* If the step or test expressions execute `break' or `continue' in a
nofork command substitution or by some other means, break the loop
here. */
- if (breaking)
- {
- breaking--;
- break;
- }
- if (continuing)
- {
- continuing--;
- if (continuing)
- break;
- }
+ CHECK_BREAK_AND_CONTINUE();
if (expok == 0)
break;
QUIT;
/* Handle any `break' or `continue' commands executed by the body. */
- if (breaking)
- {
- breaking--;
- break;
- }
-
- if (continuing)
- {
- continuing--;
- if (continuing)
- break;
- }
+ CHECK_BREAK_AND_CONTINUE();
/* Evaluate the step expression. */
line_number = arith_lineno;
stupidly_hack_special_variables (identifier);
+ CHECK_BREAK_AND_CONTINUE();
+
retval = execute_command (select_command->action);
REAP ();
QUIT;
- if (breaking)
- {
- breaking--;
- break;
- }
-
- if (continuing)
- {
- continuing--;
- if (continuing)
- break;
- }
+ CHECK_BREAK_AND_CONTINUE();
#if defined (KSH_COMPATIBLE_SELECT)
show_menu = 0;
REAP ();
- if (breaking)
- {
- breaking--;
- break;
- }
-
- if (continuing)
- {
- continuing--;
- if (continuing)
- break;
- }
+ CHECK_BREAK_AND_CONTINUE();
}
loop_level--; interrupt_execution--;
/* If unbound variables should generate an error, report one and return
failure. */
+#if 0 /*TAG:bash-5.4 myoga.murase@gmail.com 4/7/2025 */
+ if ((var == 0 || invisible_p (var)) && unbound_vars_is_error)
+#else
if ((var == 0 || invisible_p (var) || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
+#endif
{
+unbound_array_error:
set_exit_status (EXECUTION_FAILURE);
#if 1
/* If the array isn't subscripted with `@' or `*', it's an error. */
/* We support a couple of expansions for variables that are not arrays.
We'll return the length of the value for v[0], and 1 for v[@] or
v[*]. Return 0 for everything else. */
+#if 0 /*TAG:bash-5.4 myoga.murase@gmail.com 4/7/2025 */
+ /* If the variable is set, but not an array or assoc variable, nounset is
+ enabled, and the subscript is not one of @, *, or 0, it is an error
+ treated the same as in previous versions. */
+#endif
array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
h = assoc_p (var) ? assoc_cell (var) : (HASH_TABLE *)NULL;
return (h ? assoc_num_elements (h) : 0);
else if (array_p (var))
return (array ? array_num_elements (array) : 0);
+#if 0 /*TAG:bash-5.4 myoga.murase@gmail.com 4/7/2025 */
+ else if (unbound_vars_is_error && var_isset (var) == 0)
+ goto unbound_array_error; /* still non-fatal error */
+#endif
else
return (var_isset (var) ? 1 : 0);
}
}
if (array_p (var))
t = array_reference (array, ind);
+#if 0 /*TAG:bash-5.4 myoga.murase@gmail.com 4/7/2025 */
+ /* if nounset is enabled, scalar variables may only be indexed with 0 */
+ else if (unbound_vars_is_error && (var_isset (var) == 0 || ind != 0))
+ goto unbound_array_error; /* still fatal error */
+#endif
else
t = (ind == 0) ? value_cell (var) : (char *)NULL;
}
in here-documents
after all they work here
and work here
+after for
+uname
+after arith for
+1) a[${ break;}]
+#? after select
a b c == 1 2 3
== 1 2 3
before return
echo after all they ${word-$(echo work here)}
echo and ${word-${ echo work here; }}
+
+unset x
+
+set -- 'a[${ break;}]'
+declare -in x
+
+for x do :; done
+echo after for
+
+true; for (( ; $? == 0; ${ ! break;} )); do echo uname; done
+echo after arith for
+
+declare -i z
+select z in 'a[${ break;}]'
+do
+ echo $z
+done <<<1
+echo after select
#define attmask_scope 0x0f00000
+/* Internal attributes used for variable state management. */
+#define att_assigning 0x1000000
+
+#define attmask_state 0xf000000
+
#define exported_p(var) ((((var)->attributes) & (att_exported)))
#define readonly_p(var) ((((var)->attributes) & (att_readonly)))
#define array_p(var) ((((var)->attributes) & (att_array)))