]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | This file is break.def, from which is created break.c. |
2 | It implements the builtins "break" and "continue" in Bash. | |
3 | ||
3185942a | 4 | Copyright (C) 1987-2009 Free Software Foundation, Inc. |
726f6388 JA |
5 | |
6 | This file is part of GNU Bash, the Bourne Again SHell. | |
7 | ||
3185942a JA |
8 | Bash is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation, either version 3 of the License, or | |
11 | (at your option) any later version. | |
726f6388 | 12 | |
3185942a JA |
13 | Bash is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
726f6388 | 17 | |
3185942a JA |
18 | You should have received a copy of the GNU General Public License |
19 | along with Bash. If not, see <http://www.gnu.org/licenses/>. | |
726f6388 JA |
20 | |
21 | $PRODUCES break.c | |
22 | ||
23 | $BUILTIN break | |
24 | $FUNCTION break_builtin | |
25 | $SHORT_DOC break [n] | |
3185942a JA |
26 | Exit for, while, or until loops. |
27 | ||
28 | Exit a FOR, WHILE or UNTIL loop. If N is specified, break N enclosing | |
29 | loops. | |
30 | ||
31 | Exit Status: | |
32 | The exit status is 0 unless N is not greater than or equal to 1. | |
726f6388 | 33 | $END |
ccc6cda3 JA |
34 | #include <config.h> |
35 | ||
36 | #if defined (HAVE_UNISTD_H) | |
cce855bc JA |
37 | # ifdef _MINIX |
38 | # include <sys/types.h> | |
39 | # endif | |
40 | # include <unistd.h> | |
ccc6cda3 | 41 | #endif |
726f6388 | 42 | |
b80f6443 JA |
43 | #include "../bashintl.h" |
44 | ||
726f6388 | 45 | #include "../shell.h" |
ccc6cda3 | 46 | #include "common.h" |
726f6388 JA |
47 | |
48 | extern char *this_command_name; | |
28ef6c31 | 49 | extern int posixly_correct; |
726f6388 | 50 | |
f73dda09 | 51 | static int check_loop_level __P((void)); |
726f6388 JA |
52 | |
53 | /* The depth of while's and until's. */ | |
54 | int loop_level = 0; | |
55 | ||
56 | /* Non-zero when a "break" instruction is encountered. */ | |
57 | int breaking = 0; | |
58 | ||
59 | /* Non-zero when we have encountered a continue instruction. */ | |
60 | int continuing = 0; | |
61 | ||
62 | /* Set up to break x levels, where x defaults to 1, but can be specified | |
63 | as the first argument. */ | |
ccc6cda3 | 64 | int |
726f6388 JA |
65 | break_builtin (list) |
66 | WORD_LIST *list; | |
67 | { | |
7117c2d2 | 68 | intmax_t newbreak; |
726f6388 | 69 | |
d166f048 | 70 | if (check_loop_level () == 0) |
28ef6c31 | 71 | return (EXECUTION_SUCCESS); |
726f6388 | 72 | |
3185942a | 73 | (void)get_numeric_arg (list, 1, &newbreak); |
726f6388 JA |
74 | |
75 | if (newbreak <= 0) | |
d166f048 | 76 | { |
3185942a | 77 | sh_erange (list->word->word, _("loop count")); |
d166f048 JA |
78 | breaking = loop_level; |
79 | return (EXECUTION_FAILURE); | |
80 | } | |
726f6388 JA |
81 | |
82 | if (newbreak > loop_level) | |
83 | newbreak = loop_level; | |
84 | ||
85 | breaking = newbreak; | |
86 | ||
87 | return (EXECUTION_SUCCESS); | |
88 | } | |
89 | ||
90 | $BUILTIN continue | |
91 | $FUNCTION continue_builtin | |
92 | $SHORT_DOC continue [n] | |
3185942a JA |
93 | Resume for, while, or until loops. |
94 | ||
95 | Resumes the next iteration of the enclosing FOR, WHILE or UNTIL loop. | |
96 | If N is specified, resumes the Nth enclosing loop. | |
97 | ||
98 | Exit Status: | |
99 | The exit status is 0 unless N is not greater than or equal to 1. | |
726f6388 JA |
100 | $END |
101 | ||
102 | /* Set up to continue x levels, where x defaults to 1, but can be specified | |
103 | as the first argument. */ | |
ccc6cda3 | 104 | int |
726f6388 JA |
105 | continue_builtin (list) |
106 | WORD_LIST *list; | |
107 | { | |
7117c2d2 | 108 | intmax_t newcont; |
726f6388 | 109 | |
d166f048 | 110 | if (check_loop_level () == 0) |
28ef6c31 | 111 | return (EXECUTION_SUCCESS); |
726f6388 | 112 | |
3185942a | 113 | (void)get_numeric_arg (list, 1, &newcont); |
726f6388 JA |
114 | |
115 | if (newcont <= 0) | |
d166f048 | 116 | { |
3185942a | 117 | sh_erange (list->word->word, _("loop count")); |
d166f048 JA |
118 | breaking = loop_level; |
119 | return (EXECUTION_FAILURE); | |
120 | } | |
726f6388 JA |
121 | |
122 | if (newcont > loop_level) | |
123 | newcont = loop_level; | |
124 | ||
125 | continuing = newcont; | |
126 | ||
127 | return (EXECUTION_SUCCESS); | |
128 | } | |
129 | ||
130 | /* Return non-zero if a break or continue command would be okay. | |
131 | Print an error message if break or continue is meaningless here. */ | |
132 | static int | |
133 | check_loop_level () | |
134 | { | |
135 | #if defined (BREAK_COMPLAINS) | |
28ef6c31 | 136 | if (loop_level == 0 && posixly_correct == 0) |
b80f6443 | 137 | builtin_error (_("only meaningful in a `for', `while', or `until' loop")); |
726f6388 JA |
138 | #endif /* BREAK_COMPLAINS */ |
139 | ||
140 | return (loop_level); | |
141 | } |