goto.c
1 //! @file goto.c
2 //! @author J. Marcel van der Veer
3 //
4 //! @section Copyright
5 //
6 // This file is part of VIF - vintage FORTRAN compiler.
7 // Copyright 2020-2024 J. Marcel van der Veer <algol68g@xs4all.nl>.
8 //
9 //! @section License
10 //
11 // This program is free software; you can redistribute it and/or modify it
12 // under the terms of the GNU General Public License as published by the
13 // Free Software Foundation; either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful, but
17 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 // more details. You should have received a copy of the GNU General Public
20 // License along with this program. If not, see <http://www.gnu.org/licenses/>.
21
22 //! @section Synopsis
23 //!
24 //! Compile GOTO statements.
25
26 #include <vif.h>
27
28 static LBL *get_label (void) {
29 LBL *L = find_label (curlex);
30 if (L == NULL) {
31 ERROR (1801, "no such label", curlex);
32 return NULL;
33 } else if (L->nonexe) {
34 ERROR (1802, "label of non-executable", curlex);
35 return NULL;
36 }
37 L->jumped++;
38 return L;
39 }
40
41 void jump (void)
42 {
43 int_4 rc = scan (NULL);
44 if (rc == INT_NUMBER) {
45 // GOTO label
46 LBL *L = get_label ();
47 if (L == NULL) {
48 return;
49 }
50 RECORD str;
51 _srecordf (str, "goto _l%d;\n", L->num);
52 code (nprocs, BODY, str);
53 skip_card ();
54 } else if (TOKEN ("(")) {
55 // GOTO (...), expr
56 code (nprocs, BODY, "switch (");
57 int_4 apatch = code (nprocs, BODY, NULL);
58 code (nprocs, BODY, ") {\n");
59 code (nprocs, BODY, "default:\n");
60 rc = scan (NULL);
61 int_4 N = 1;
62 while (rc == INT_NUMBER) {
63 RECORD str;
64 LBL *L = get_label ();
65 if (L == NULL) {
66 return;
67 }
68 _srecordf (str, "case %d: goto _l%d;\n", N++, L->num);
69 code (nprocs, BODY, str);
70 rc = scan (NULL);
71 if (TOKEN (",")) {
72 rc = scan (NULL);
73 }
74 };
75 CHECKPOINT (1803, ")");
76 rc = scan (NULL);
77 if (TOKEN (",")) {
78 rc = scan (NULL);
79 }
80 EXPR var;
81 express (&var, INTEGER, 4);
82 patch (apatch, var.str);
83 code (nprocs, BODY, "}\n");
84 skip_card ();
85 } else if (rc == WORD) {
86 // GOTO idf [, (...)]
87 IDENT *idf = find_local (curlex, NULL);
88 if (idf == NULL ) {
89 return;
90 }
91 if (idf->mode.type != INTEGER) {
92 EXPECT (1804, "integer variable");
93 }
94 RECORD str;
95 EXPR var; MODE mode;
96 var.str[0] = '\0';
97 variable (&var, idf, &mode, curlex);
98 _srecordf (str, "switch (%s) {\n", var.str);
99 code (nprocs, BODY, str);
100 code (nprocs, BODY, "default:\n");
101 rc = scan (NULL);
102 if (TOKEN (",") || TOKEN ("(")) {
103 // Emit indicated labels.
104 if (TOKEN (",")) {
105 rc = scan (NULL);
106 }
107 rc = scan (NULL);
108 while (rc == INT_NUMBER) {
109 LBL *L = get_label ();
110 if (L == NULL) {
111 return;
112 }
113 _srecordf (str, "case %d: goto _l%d;\n", L->index, L->num);
114 code (nprocs, BODY, str);
115 rc = scan (NULL);
116 if (TOKEN (",")) {
117 rc = scan (NULL);
118 }
119 }
120 CHECKPOINT (1805, ")");
121 code (nprocs, BODY, "}\n");
122 skip_card ();
123 } else {
124 // Default, emit all labels.
125 for (int_4 k = 0; k < nlabels; k++) {
126 LBL *L = &labels[k];
127 if (! L->nonexe) {
128 L->jumped++;
129 _srecordf (str, "case %d: goto _l%d;\n", L->index, L->num);
130 code (nprocs, BODY, str);
131 }
132 }
133 code (nprocs, BODY, "}\n");
134 skip_card ();
135 }
136 }
137 }
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|