diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-08-18 14:16:35 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-08-18 14:16:35 +0300 |
commit | 8e25ff1846acd82e522e32dddd7cc298018eca0c (patch) | |
tree | 1a38bccc1f8fbf6068d5e9dc70b536deb1815550 | |
parent | 3121834c53912f8a6bfcd4931bae9998bbb4a78d (diff) | |
download | mailfromd-8e25ff1846acd82e522e32dddd7cc298018eca0c.tar.gz mailfromd-8e25ff1846acd82e522e32dddd7cc298018eca0c.tar.bz2 |
Fix definition of `next'.
* mfd/drivers.c (struct loop_stack): Replace `begjmp' with `nxtjmp'.
(enter_loop): Reflect this.
(code_type_next): Likewise.
(code_type_loop): Rewrite jump fixup for `next' chain.
* tests/next01.at, tests/next02.at: New testcases.
* tests/Makefile.am: Add next01.at and next02.at
* tests/testsuite.at: Likewise.
* NEWS, doc/mailfromd.texi: Update
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | doc/mailfromd.texi | 2 | ||||
-rw-r--r-- | mfd/drivers.c | 17 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/next01.at | 50 | ||||
-rw-r--r-- | tests/next02.at | 51 | ||||
-rw-r--r-- | tests/testsuite.at | 3 |
7 files changed, 124 insertions, 9 deletions
@@ -7,6 +7,14 @@ Please send Mailfromd bug reports to <bug-mailfromd@gnu.org.ua> | |||
7 | 7 | ||
8 | Version 5.1.91 (Git) | 8 | Version 5.1.91 (Git) |
9 | 9 | ||
10 | * `next' statement | ||
11 | |||
12 | The definition of `next' statement has been fixed to match `continue' | ||
13 | in other programming languages. Namely, `next' passes control to | ||
14 | STMT2 in the loop definition: | ||
15 | |||
16 | loop for STMT1, while EXPR1, STMT2 | ||
17 | |||
10 | * Process titles. | 18 | * Process titles. |
11 | 19 | ||
12 | The process titles visible in the output of the ps(1) command reflect | 20 | The process titles visible in the output of the ps(1) command reflect |
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi index 60af5b07..e18310c8 100644 --- a/doc/mailfromd.texi +++ b/doc/mailfromd.texi | |||
@@ -11018,7 +11018,7 @@ allows to break from nested loops. | |||
11018 | @kwindex next | 11018 | @kwindex next |
11019 | @cindex next statement | 11019 | @cindex next statement |
11020 | @item next [@var{label}] | 11020 | @item next [@var{label}] |
11021 | Initiates next iteration of the loop. Control passes to @samp{2} in | 11021 | Initiates next iteration of the loop. Control passes to @samp{4} in |
11022 | the formal definition above. If @var{label} is supplied, the | 11022 | the formal definition above. If @var{label} is supplied, the |
11023 | statement starts next iteration of the loop statement marked with that | 11023 | statement starts next iteration of the loop statement marked with that |
11024 | label. This allows to request next iteration of an upper-level | 11024 | label. This allows to request next iteration of an upper-level |
diff --git a/mfd/drivers.c b/mfd/drivers.c index ed8a288a..1b7203fa 100644 --- a/mfd/drivers.c +++ b/mfd/drivers.c | |||
@@ -1998,8 +1998,8 @@ code_type_switch(NODE *node, struct locus **old_locus) | |||
1998 | /* Loop nesting stack */ | 1998 | /* Loop nesting stack */ |
1999 | struct loop_stack { | 1999 | struct loop_stack { |
2000 | struct literal *ident; | 2000 | struct literal *ident; |
2001 | prog_counter_t *begjmp; | ||
2002 | prog_counter_t *endjmp; | 2001 | prog_counter_t *endjmp; |
2002 | prog_counter_t *nxtjmp; | ||
2003 | }; | 2003 | }; |
2004 | 2004 | ||
2005 | static mf_stack_t loop_stack; | 2005 | static mf_stack_t loop_stack; |
@@ -2039,13 +2039,13 @@ within_loop(struct literal *lit) | |||
2039 | } | 2039 | } |
2040 | 2040 | ||
2041 | void | 2041 | void |
2042 | enter_loop(struct literal *lit, prog_counter_t *begptr, prog_counter_t *endptr) | 2042 | enter_loop(struct literal *lit, prog_counter_t *endptr, prog_counter_t *nxtptr) |
2043 | { | 2043 | { |
2044 | struct loop_stack ent; | 2044 | struct loop_stack ent; |
2045 | if (!loop_stack) | 2045 | if (!loop_stack) |
2046 | loop_stack = mf_stack_create(sizeof(struct loop_stack), 0); | 2046 | loop_stack = mf_stack_create(sizeof(struct loop_stack), 0); |
2047 | ent.begjmp = begptr; | ||
2048 | ent.endjmp = endptr; | 2047 | ent.endjmp = endptr; |
2048 | ent.nxtjmp = nxtptr; | ||
2049 | ent.ident = lit; | 2049 | ent.ident = lit; |
2050 | mf_stack_push(loop_stack, &ent); | 2050 | mf_stack_push(loop_stack, &ent); |
2051 | } | 2051 | } |
@@ -2083,7 +2083,7 @@ code_type_next(NODE *node, struct locus **old_locus) | |||
2083 | } | 2083 | } |
2084 | 2084 | ||
2085 | code_op(opcode_jmp); | 2085 | code_op(opcode_jmp); |
2086 | *ent.begjmp = code_immediate((void*) *ent.begjmp); | 2086 | *ent.nxtjmp = code_immediate((void*) *ent.nxtjmp); |
2087 | } | 2087 | } |
2088 | 2088 | ||
2089 | 2089 | ||
@@ -2206,11 +2206,11 @@ code_type_loop(NODE *node, struct locus **old_locus) | |||
2206 | jmp L_begin | 2206 | jmp L_begin |
2207 | L_end: | 2207 | L_end: |
2208 | */ | 2208 | */ |
2209 | prog_counter_t begin, end, begjmp = 0, endjmp = 0; | 2209 | prog_counter_t begin, end, stmt, endjmp = 0, nxtjmp = 0; |
2210 | 2210 | ||
2211 | MARK_LOCUS(); | 2211 | MARK_LOCUS(); |
2212 | 2212 | ||
2213 | enter_loop(node->v.loop.ident, &begjmp, &endjmp); | 2213 | enter_loop(node->v.loop.ident, &endjmp, &nxtjmp); |
2214 | 2214 | ||
2215 | traverse_tree(node->v.loop.for_stmt); | 2215 | traverse_tree(node->v.loop.for_stmt); |
2216 | begin = code_get_counter(); | 2216 | begin = code_get_counter(); |
@@ -2227,14 +2227,15 @@ code_type_loop(NODE *node, struct locus **old_locus) | |||
2227 | code_op(opcode_bz); | 2227 | code_op(opcode_bz); |
2228 | endjmp = code_immediate((void*)endjmp); | 2228 | endjmp = code_immediate((void*)endjmp); |
2229 | } | 2229 | } |
2230 | 2230 | ||
2231 | stmt = code_get_counter(); | ||
2231 | traverse_tree(node->v.loop.stmt); | 2232 | traverse_tree(node->v.loop.stmt); |
2232 | code_op(opcode_jmp); | 2233 | code_op(opcode_jmp); |
2233 | code_immediate((void*)(begin - code_get_counter() - 1)); | 2234 | code_immediate((void*)(begin - code_get_counter() - 1)); |
2234 | end = code_get_counter(); | 2235 | end = code_get_counter(); |
2235 | 2236 | ||
2236 | jump_fixup(begjmp, begin); | ||
2237 | jump_fixup(endjmp, end); | 2237 | jump_fixup(endjmp, end); |
2238 | jump_fixup(nxtjmp, stmt); | ||
2238 | } | 2239 | } |
2239 | 2240 | ||
2240 | 2241 | ||
diff --git a/tests/Makefile.am b/tests/Makefile.am index 368a9643..af95477c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am | |||
@@ -84,6 +84,8 @@ TESTSUITE_AT = \ | |||
84 | ismx.at\ | 84 | ismx.at\ |
85 | macros.at\ | 85 | macros.at\ |
86 | ml.at\ | 86 | ml.at\ |
87 | next01.at\ | ||
88 | next02.at\ | ||
87 | numrcpt.at\ | 89 | numrcpt.at\ |
88 | poll.at\ | 90 | poll.at\ |
89 | poll01.at\ | 91 | poll01.at\ |
diff --git a/tests/next01.at b/tests/next01.at new file mode 100644 index 00000000..c44bb57c --- /dev/null +++ b/tests/next01.at | |||
@@ -0,0 +1,50 @@ | |||
1 | # This file is part of Mailfromd testsuite. -*- Autotest -*- | ||
2 | # Copyright (C) 2009 Sergey Poznyakoff | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or modify | ||
5 | # it under the terms of the GNU General Public License as published by | ||
6 | # the Free Software Foundation; either version 3, or (at your option) | ||
7 | # any later version. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | AT_SETUP([next01]) | ||
18 | AT_KEYWORDS([next loop]) | ||
19 | |||
20 | # Description: The `next' keyword was implemented incorrectly in | ||
21 | # versions up to 5.1. | ||
22 | |||
23 | MF_RUN_TEXT([ | ||
24 | func main(...) | ||
25 | returns number | ||
26 | do | ||
27 | loop for string names $1 " " | ||
28 | number i index(%names, " "), | ||
29 | while %i != -1, | ||
30 | set names substr(%names, %i + 1) | ||
31 | set i index(%names, " ") | ||
32 | do | ||
33 | string s substr(%names, 0, %i) | ||
34 | if %s == 'next' | ||
35 | next | ||
36 | fi | ||
37 | echo "WORD: %s" | ||
38 | done | ||
39 | return 0 | ||
40 | done | ||
41 | ], | ||
42 | ['begin next cont next end next'], | ||
43 | [0], | ||
44 | [], | ||
45 | [WORD: begin | ||
46 | WORD: cont | ||
47 | WORD: end | ||
48 | ]) | ||
49 | |||
50 | AT_CLEANUP | ||
diff --git a/tests/next02.at b/tests/next02.at new file mode 100644 index 00000000..9690f732 --- /dev/null +++ b/tests/next02.at | |||
@@ -0,0 +1,51 @@ | |||
1 | # This file is part of Mailfromd testsuite. -*- Autotest -*- | ||
2 | # Copyright (C) 2009 Sergey Poznyakoff | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or modify | ||
5 | # it under the terms of the GNU General Public License as published by | ||
6 | # the Free Software Foundation; either version 3, or (at your option) | ||
7 | # any later version. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | AT_SETUP([next02]) | ||
18 | AT_KEYWORDS([next loop]) | ||
19 | |||
20 | # Description: The `next' keyword was implemented incorrectly in | ||
21 | # versions up to 5.1. | ||
22 | |||
23 | MF_RUN_TEXT([ | ||
24 | func main(...) | ||
25 | returns number | ||
26 | do | ||
27 | loop for string names $1 " " | ||
28 | number i index(%names, " "), | ||
29 | while %i != -1, | ||
30 | set names substr(%names, %i + 1) | ||
31 | set i index(%names, " ") | ||
32 | do | ||
33 | string s substr(%names, 0, %i) | ||
34 | if %s == 'next' | ||
< |