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