slice.c
1 //! @file slice.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-2025 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 array slices.
25
26 #include <vif.h>
27
28 void code_index (RECORD index, IDENT * idf, int_4 dim)
29 {
30 RECORD str;
31 EXPR reg;
32 express (®, INTEGER, 4);
33 if (EQUAL (idf->lwb[dim], "0")) {
34 if (dim == 0) {
35 _srecordf (str, "%s", reg.str);
36 } else {
37 _srecordf (str, "(%s)", reg.str);
38 }
39 } else {
40 RECORD buf;
41 _srecordf (str, "%s - %s", reg.str, idf->lwb[dim]);
42 fold_int_4 (buf, str);
43 if (dim == 0) {
44 _srecordf (str, "%s", buf);
45 } else {
46 _srecordf (str, "(%s)", buf);
47 }
48 }
49 (void) scan (EXPECT_NONE);
50 if (TOKEN (":")) {
51 SYNTAX (2701, "range not allowed");
52 } else if (TOKEN (",")) {
53 RECORD deep;
54 RECCLR (deep);
55 (void) scan (EXPECT_NONE);
56 code_index (deep, idf, dim + 1);
57 if (strcmp (idf->len[dim], "VARY") == 0) {
58 ERROR (2702, "dimension cannot vary", NO_TEXT);
59 }
60 RECORD prod, fact;
61 _srecordf (prod, "(%s) * (%s)", idf->len[dim], deep);
62 fold_int_4 (fact, prod);
63 if (strcmp (fact, "0") == 0) {
64 _srecordf (index, "%s", str);
65 } else {
66 _srecordf (index, "%s + %s", str, fact);
67 }
68 } else if (TOKEN (")")) {
69 bufcpy (index, str, RECLN);
70 return;
71 }
72 }
73
74 void code_store_index (EXPR *loc, RECORD index, IDENT * idf, int_4 dim)
75 {
76 RECCLR (index);
77 code_index (index, idf, 0);
78 // Sanity check.
79 int_4 value;
80 if (isint_4 (index, &value) && value < 0) {
81 ERROR (2703, "index out of range", FTN_NAME (idf));
82 }
83 // FORTRAN code, like m[(i + W1 * (j * W2 * k)]
84 fold_int_4 (loc->elem, index);
85 }
86
87 void factor_slice_char (EXPR *loc, IDENT *idf)
88 {
89 RECORD ldf, index;
90 RECCLR (index);
91 // Code identifier name.
92 (void) idf_full_c_name (ldf, idf);
93 //
94 if (IS_ROW (idf->mode)) {
95 // Assume idf(i1, .., iN) possibly followed by (lwb : upb)
96 (void) scan (EXPECT_NONE);
97 code_store_index (loc, index, idf, 0);
98 _srecordf (ldf, "%s[%s]", ldf, index);
99 (void) scan (EXPECT_NONE); // Skip ")"
100 if (!TOKEN ("(")) {
101 // idf(i1, ..., iN), no substring.
102 UNSCAN;
103 bufcpy (loc->str, ldf, RECLN);
104 loc->variant = EXPR_SLICE;
105 loc->idf = idf;
106 loc->mode = idf->mode;
107 return;
108 }
109 }
110 // The trimmer (lwb : upb)
111 EXPR ini, fin;
112 int_4 denot = (IS_SCALAR (idf->mode));
113 (void) scan (EXPECT_NONE);
114 if (TOKEN (":")) {
115 _srecordf (ini.str, "1");
116 ini.mode.type = INTEGER;
117 ini.mode.len = 4;
118 ini.variant = EXPR_CONST;
119 } else {
120 express (&ini, INTEGER, 4);
121 denot &= (ini.variant == EXPR_CONST);
122 (void) scan (EXPECT_NONE);
123 }
124 CHECKPOINT (2704, ":");
125 // ldf(lwb : upb)
126 (void) scan (EXPECT_NONE);
127 if (TOKEN (")")) {
128 UNSCAN;
129 _srecordf (fin.str, "%d", idf->mode.len);
130 fin.mode.type = INTEGER;
131 fin.mode.len = 4;
132 fin.variant = EXPR_CONST;
133 } else {
134 express (&fin, INTEGER, 4);
135 denot &= (fin.variant == EXPR_CONST);
136 }
137 if (lhs_factor) { // A permanent stub ...
138 bufcat (ini.str, " - 1", RECLN);
139 (void) fold_expr (&ini, INTEGER);
140 _srecordf (loc->str, "(char *) &(%s[%s])", ldf, ini.str);
141 loc->variant = EXPR_SUBSTR;
142 loc->idf = idf;
143 loc->mode = idf->mode;
144 } else {
145 // Optimize substring with all constant parameters.
146 denot &= (idf->parm != NO_TEXT);
147 if (denot) {
148 RECORD cdf, sub, tmp;
149 get_uniq_str (idf->parm, cdf);
150 _srecordf (sub, "\"%s\"", _bufsub (tmp, cdf, atoi (ini.str), atoi (fin.str)));
151 _srecordf (cdf, "_dc_%d", code_uniq_str (sub));
152 _srecordf (loc->str, "%s", cdf);
153 loc->mode = (MODE) {.type = CHARACTER, .len = strlen (sub) - 2, .dim = 0};
154 loc->variant = EXPR_CONST;
155 } else {
156 // General form of substring.
157 RECORD tmp;
158 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
159 if (idf->mode.len > 0) {
160 add_local (tmp, idf->mode.type, idf->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
161 } else { // Should not copy into zero-length string.
162 add_local (tmp, idf->mode.type, MAX_STRLEN, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
163 }
164 // _bufsub returns buffer address, so no gcc statement expression needed.
165 _srecordf (loc->str, "_bufsub ((char *) %s, (char *) %s, %s, %s)", tmp, ldf, ini.str, fin.str);
166 loc->variant = EXPR_SUBSTR;
167 loc->idf = idf;
168 loc->mode = idf->mode;
169 }
170 }
171 (void) scan (")");
172 }
173
174 void factor_slice (EXPR *loc, IDENT *idf)
175 {
176 RECORD index;
177 RECCLR (index);
178 (void) idf_full_c_name (loc->str, idf);
179 (void) scan (EXPECT_NONE);
180 code_store_index (loc, index, idf, 0);
181 bufcat (loc->str, "[", RECLN);
182 bufcat (loc->str, loc->elem, RECLN);
183 bufcat (loc->str, "]", RECLN);
184 loc->variant = EXPR_SLICE;
185 loc->idf = idf;
186 loc->mode = idf->mode;
187 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|