annotate libgfortran/intrinsics/string_intrinsics_inc.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* String intrinsics helper functions.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2002-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of the GNU Fortran runtime library (libgfortran).
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 Libgfortran is free software; you can redistribute it and/or
kono
parents:
diff changeset
7 modify it under the terms of the GNU General Public
kono
parents:
diff changeset
8 License as published by the Free Software Foundation; either
kono
parents:
diff changeset
9 version 3 of the License, or (at your option) any later version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 Libgfortran is distributed in the hope that it will be useful,
kono
parents:
diff changeset
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
14 GNU General Public License for more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
17 permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
18 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
21 a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
23 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 /* Rename the functions. */
kono
parents:
diff changeset
27 #define concat_string SUFFIX(concat_string)
kono
parents:
diff changeset
28 #define string_len_trim SUFFIX(string_len_trim)
kono
parents:
diff changeset
29 #define adjustl SUFFIX(adjustl)
kono
parents:
diff changeset
30 #define adjustr SUFFIX(adjustr)
kono
parents:
diff changeset
31 #define string_index SUFFIX(string_index)
kono
parents:
diff changeset
32 #define string_scan SUFFIX(string_scan)
kono
parents:
diff changeset
33 #define string_verify SUFFIX(string_verify)
kono
parents:
diff changeset
34 #define string_trim SUFFIX(string_trim)
kono
parents:
diff changeset
35 #define string_minmax SUFFIX(string_minmax)
kono
parents:
diff changeset
36 #define zero_length_string SUFFIX(zero_length_string)
kono
parents:
diff changeset
37 #define compare_string SUFFIX(compare_string)
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 /* The prototypes. */
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 extern void concat_string (gfc_charlen_type, CHARTYPE *,
kono
parents:
diff changeset
43 gfc_charlen_type, const CHARTYPE *,
kono
parents:
diff changeset
44 gfc_charlen_type, const CHARTYPE *);
kono
parents:
diff changeset
45 export_proto(concat_string);
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 extern void adjustl (CHARTYPE *, gfc_charlen_type, const CHARTYPE *);
kono
parents:
diff changeset
48 export_proto(adjustl);
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 extern void adjustr (CHARTYPE *, gfc_charlen_type, const CHARTYPE *);
kono
parents:
diff changeset
51 export_proto(adjustr);
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 extern gfc_charlen_type string_index (gfc_charlen_type, const CHARTYPE *,
kono
parents:
diff changeset
54 gfc_charlen_type, const CHARTYPE *,
kono
parents:
diff changeset
55 GFC_LOGICAL_4);
kono
parents:
diff changeset
56 export_proto(string_index);
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 extern gfc_charlen_type string_scan (gfc_charlen_type, const CHARTYPE *,
kono
parents:
diff changeset
59 gfc_charlen_type, const CHARTYPE *,
kono
parents:
diff changeset
60 GFC_LOGICAL_4);
kono
parents:
diff changeset
61 export_proto(string_scan);
kono
parents:
diff changeset
62
kono
parents:
diff changeset
63 extern gfc_charlen_type string_verify (gfc_charlen_type, const CHARTYPE *,
kono
parents:
diff changeset
64 gfc_charlen_type, const CHARTYPE *,
kono
parents:
diff changeset
65 GFC_LOGICAL_4);
kono
parents:
diff changeset
66 export_proto(string_verify);
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 extern void string_trim (gfc_charlen_type *, CHARTYPE **, gfc_charlen_type,
kono
parents:
diff changeset
69 const CHARTYPE *);
kono
parents:
diff changeset
70 export_proto(string_trim);
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 extern void string_minmax (gfc_charlen_type *, CHARTYPE **, int, int, ...);
kono
parents:
diff changeset
73 export_proto(string_minmax);
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75
kono
parents:
diff changeset
76 /* Use for functions which can return a zero-length string. */
kono
parents:
diff changeset
77 static CHARTYPE zero_length_string = 0;
kono
parents:
diff changeset
78
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 /* Strings of unequal length are extended with pad characters. */
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 int
kono
parents:
diff changeset
83 compare_string (gfc_charlen_type len1, const CHARTYPE *s1,
kono
parents:
diff changeset
84 gfc_charlen_type len2, const CHARTYPE *s2)
kono
parents:
diff changeset
85 {
kono
parents:
diff changeset
86 const UCHARTYPE *s;
kono
parents:
diff changeset
87 gfc_charlen_type len;
kono
parents:
diff changeset
88 int res;
kono
parents:
diff changeset
89
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
90 /* Placate the sanitizer. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
91 if (!s1 && !s2)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
92 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
93 if (!s1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
94 return -1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
95 if (!s2)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
96 return 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
97
111
kono
parents:
diff changeset
98 res = MEMCMP (s1, s2, ((len1 < len2) ? len1 : len2));
kono
parents:
diff changeset
99 if (res != 0)
kono
parents:
diff changeset
100 return res;
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 if (len1 == len2)
kono
parents:
diff changeset
103 return 0;
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 if (len1 < len2)
kono
parents:
diff changeset
106 {
kono
parents:
diff changeset
107 len = len2 - len1;
kono
parents:
diff changeset
108 s = (UCHARTYPE *) &s2[len1];
kono
parents:
diff changeset
109 res = -1;
kono
parents:
diff changeset
110 }
kono
parents:
diff changeset
111 else
kono
parents:
diff changeset
112 {
kono
parents:
diff changeset
113 len = len1 - len2;
kono
parents:
diff changeset
114 s = (UCHARTYPE *) &s1[len2];
kono
parents:
diff changeset
115 res = 1;
kono
parents:
diff changeset
116 }
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 while (len--)
kono
parents:
diff changeset
119 {
kono
parents:
diff changeset
120 if (*s != ' ')
kono
parents:
diff changeset
121 {
kono
parents:
diff changeset
122 if (*s > ' ')
kono
parents:
diff changeset
123 return res;
kono
parents:
diff changeset
124 else
kono
parents:
diff changeset
125 return -res;
kono
parents:
diff changeset
126 }
kono
parents:
diff changeset
127 s++;
kono
parents:
diff changeset
128 }
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 return 0;
kono
parents:
diff changeset
131 }
kono
parents:
diff changeset
132 iexport(compare_string);
kono
parents:
diff changeset
133
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 /* The destination and source should not overlap. */
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 void
kono
parents:
diff changeset
138 concat_string (gfc_charlen_type destlen, CHARTYPE * dest,
kono
parents:
diff changeset
139 gfc_charlen_type len1, const CHARTYPE * s1,
kono
parents:
diff changeset
140 gfc_charlen_type len2, const CHARTYPE * s2)
kono
parents:
diff changeset
141 {
kono
parents:
diff changeset
142 if (len1 >= destlen)
kono
parents:
diff changeset
143 {
kono
parents:
diff changeset
144 memcpy (dest, s1, destlen * sizeof (CHARTYPE));
kono
parents:
diff changeset
145 return;
kono
parents:
diff changeset
146 }
kono
parents:
diff changeset
147 memcpy (dest, s1, len1 * sizeof (CHARTYPE));
kono
parents:
diff changeset
148 dest += len1;
kono
parents:
diff changeset
149 destlen -= len1;
kono
parents:
diff changeset
150
kono
parents:
diff changeset
151 if (len2 >= destlen)
kono
parents:
diff changeset
152 {
kono
parents:
diff changeset
153 memcpy (dest, s2, destlen * sizeof (CHARTYPE));
kono
parents:
diff changeset
154 return;
kono
parents:
diff changeset
155 }
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 memcpy (dest, s2, len2 * sizeof (CHARTYPE));
kono
parents:
diff changeset
158 MEMSET (&dest[len2], ' ', destlen - len2);
kono
parents:
diff changeset
159 }
kono
parents:
diff changeset
160
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 /* Return string with all trailing blanks removed. */
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 void
kono
parents:
diff changeset
165 string_trim (gfc_charlen_type *len, CHARTYPE **dest, gfc_charlen_type slen,
kono
parents:
diff changeset
166 const CHARTYPE *src)
kono
parents:
diff changeset
167 {
kono
parents:
diff changeset
168 *len = string_len_trim (slen, src);
kono
parents:
diff changeset
169
kono
parents:
diff changeset
170 if (*len == 0)
kono
parents:
diff changeset
171 *dest = &zero_length_string;
kono
parents:
diff changeset
172 else
kono
parents:
diff changeset
173 {
kono
parents:
diff changeset
174 /* Allocate space for result string. */
kono
parents:
diff changeset
175 *dest = xmallocarray (*len, sizeof (CHARTYPE));
kono
parents:
diff changeset
176
kono
parents:
diff changeset
177 /* Copy string if necessary. */
kono
parents:
diff changeset
178 memcpy (*dest, src, *len * sizeof (CHARTYPE));
kono
parents:
diff changeset
179 }
kono
parents:
diff changeset
180 }
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 /* The length of a string not including trailing blanks. */
kono
parents:
diff changeset
184
kono
parents:
diff changeset
185 gfc_charlen_type
kono
parents:
diff changeset
186 string_len_trim (gfc_charlen_type len, const CHARTYPE *s)
kono
parents:
diff changeset
187 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
188 if (len <= 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
189 return 0;
111
kono
parents:
diff changeset
190
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
191 const size_t long_len = sizeof (unsigned long);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
192
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
193 size_t i = len - 1;
111
kono
parents:
diff changeset
194
kono
parents:
diff changeset
195 /* If we've got the standard (KIND=1) character type, we scan the string in
kono
parents:
diff changeset
196 long word chunks to speed it up (until a long word is hit that does not
kono
parents:
diff changeset
197 consist of ' 's). */
kono
parents:
diff changeset
198 if (sizeof (CHARTYPE) == 1 && i >= long_len)
kono
parents:
diff changeset
199 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
200 size_t starting;
111
kono
parents:
diff changeset
201 unsigned long blank_longword;
kono
parents:
diff changeset
202
kono
parents:
diff changeset
203 /* Handle the first characters until we're aligned on a long word
kono
parents:
diff changeset
204 boundary. Actually, s + i + 1 must be properly aligned, because
kono
parents:
diff changeset
205 s + i will be the last byte of a long word read. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
206 starting = (
111
kono
parents:
diff changeset
207 #ifdef __INTPTR_TYPE__
kono
parents:
diff changeset
208 (__INTPTR_TYPE__)
kono
parents:
diff changeset
209 #endif
kono
parents:
diff changeset
210 (s + i + 1)) % long_len;
kono
parents:
diff changeset
211 i -= starting;
kono
parents:
diff changeset
212 for (; starting > 0; --starting)
kono
parents:
diff changeset
213 if (s[i + starting] != ' ')
kono
parents:
diff changeset
214 return i + starting + 1;
kono
parents:
diff changeset
215
kono
parents:
diff changeset
216 /* Handle the others in a batch until first non-blank long word is
kono
parents:
diff changeset
217 found. Here again, s + i is the last byte of the current chunk,
kono
parents:
diff changeset
218 to it starts at s + i - sizeof (long) + 1. */
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 #if __SIZEOF_LONG__ == 4
kono
parents:
diff changeset
221 blank_longword = 0x20202020L;
kono
parents:
diff changeset
222 #elif __SIZEOF_LONG__ == 8
kono
parents:
diff changeset
223 blank_longword = 0x2020202020202020L;
kono
parents:
diff changeset
224 #else
kono
parents:
diff changeset
225 #error Invalid size of long!
kono
parents:
diff changeset
226 #endif
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 while (i >= long_len)
kono
parents:
diff changeset
229 {
kono
parents:
diff changeset
230 i -= long_len;
kono
parents:
diff changeset
231 if (*((unsigned long*) (s + i + 1)) != blank_longword)
kono
parents:
diff changeset
232 {
kono
parents:
diff changeset
233 i += long_len;
kono
parents:
diff changeset
234 break;
kono
parents:
diff changeset
235 }
kono
parents:
diff changeset
236 }
kono
parents:
diff changeset
237 }
kono
parents:
diff changeset
238
kono
parents:
diff changeset
239 /* Simply look for the first non-blank character. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
240 while (s[i] == ' ')
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
241 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
242 if (i == 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
243 return 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
244 --i;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
245 }
111
kono
parents:
diff changeset
246 return i + 1;
kono
parents:
diff changeset
247 }
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 /* Find a substring within a string. */
kono
parents:
diff changeset
251
kono
parents:
diff changeset
252 gfc_charlen_type
kono
parents:
diff changeset
253 string_index (gfc_charlen_type slen, const CHARTYPE *str,
kono
parents:
diff changeset
254 gfc_charlen_type sslen, const CHARTYPE *sstr,
kono
parents:
diff changeset
255 GFC_LOGICAL_4 back)
kono
parents:
diff changeset
256 {
kono
parents:
diff changeset
257 gfc_charlen_type start, last, delta, i;
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 if (sslen == 0)
kono
parents:
diff changeset
260 return back ? (slen + 1) : 1;
kono
parents:
diff changeset
261
kono
parents:
diff changeset
262 if (sslen > slen)
kono
parents:
diff changeset
263 return 0;
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 if (!back)
kono
parents:
diff changeset
266 {
kono
parents:
diff changeset
267 last = slen + 1 - sslen;
kono
parents:
diff changeset
268 start = 0;
kono
parents:
diff changeset
269 delta = 1;
kono
parents:
diff changeset
270 }
kono
parents:
diff changeset
271 else
kono
parents:
diff changeset
272 {
kono
parents:
diff changeset
273 last = -1;
kono
parents:
diff changeset
274 start = slen - sslen;
kono
parents:
diff changeset
275 delta = -1;
kono
parents:
diff changeset
276 }
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 for (; start != last; start+= delta)
kono
parents:
diff changeset
279 {
kono
parents:
diff changeset
280 for (i = 0; i < sslen; i++)
kono
parents:
diff changeset
281 {
kono
parents:
diff changeset
282 if (str[start + i] != sstr[i])
kono
parents:
diff changeset
283 break;
kono
parents:
diff changeset
284 }
kono
parents:
diff changeset
285 if (i == sslen)
kono
parents:
diff changeset
286 return (start + 1);
kono
parents:
diff changeset
287 }
kono
parents:
diff changeset
288 return 0;
kono
parents:
diff changeset
289 }
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291
kono
parents:
diff changeset
292 /* Remove leading blanks from a string, padding at end. The src and dest
kono
parents:
diff changeset
293 should not overlap. */
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 void
kono
parents:
diff changeset
296 adjustl (CHARTYPE *dest, gfc_charlen_type len, const CHARTYPE *src)
kono
parents:
diff changeset
297 {
kono
parents:
diff changeset
298 gfc_charlen_type i;
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 i = 0;
kono
parents:
diff changeset
301 while (i < len && src[i] == ' ')
kono
parents:
diff changeset
302 i++;
kono
parents:
diff changeset
303
kono
parents:
diff changeset
304 if (i < len)
kono
parents:
diff changeset
305 memcpy (dest, &src[i], (len - i) * sizeof (CHARTYPE));
kono
parents:
diff changeset
306 if (i > 0)
kono
parents:
diff changeset
307 MEMSET (&dest[len - i], ' ', i);
kono
parents:
diff changeset
308 }
kono
parents:
diff changeset
309
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 /* Remove trailing blanks from a string. */
kono
parents:
diff changeset
312
kono
parents:
diff changeset
313 void
kono
parents:
diff changeset
314 adjustr (CHARTYPE *dest, gfc_charlen_type len, const CHARTYPE *src)
kono
parents:
diff changeset
315 {
kono
parents:
diff changeset
316 gfc_charlen_type i;
kono
parents:
diff changeset
317
kono
parents:
diff changeset
318 i = len;
kono
parents:
diff changeset
319 while (i > 0 && src[i - 1] == ' ')
kono
parents:
diff changeset
320 i--;
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 if (i < len)
kono
parents:
diff changeset
323 MEMSET (dest, ' ', len - i);
kono
parents:
diff changeset
324 memcpy (&dest[len - i], src, i * sizeof (CHARTYPE));
kono
parents:
diff changeset
325 }
kono
parents:
diff changeset
326
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 /* Scan a string for any one of the characters in a set of characters. */
kono
parents:
diff changeset
329
kono
parents:
diff changeset
330 gfc_charlen_type
kono
parents:
diff changeset
331 string_scan (gfc_charlen_type slen, const CHARTYPE *str,
kono
parents:
diff changeset
332 gfc_charlen_type setlen, const CHARTYPE *set, GFC_LOGICAL_4 back)
kono
parents:
diff changeset
333 {
kono
parents:
diff changeset
334 gfc_charlen_type i, j;
kono
parents:
diff changeset
335
kono
parents:
diff changeset
336 if (slen == 0 || setlen == 0)
kono
parents:
diff changeset
337 return 0;
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 if (back)
kono
parents:
diff changeset
340 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
341 for (i = slen; i != 0; i--)
111
kono
parents:
diff changeset
342 {
kono
parents:
diff changeset
343 for (j = 0; j < setlen; j++)
kono
parents:
diff changeset
344 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
345 if (str[i - 1] == set[j])
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
346 return i;
111
kono
parents:
diff changeset
347 }
kono
parents:
diff changeset
348 }
kono
parents:
diff changeset
349 }
kono
parents:
diff changeset
350 else
kono
parents:
diff changeset
351 {
kono
parents:
diff changeset
352 for (i = 0; i < slen; i++)
kono
parents:
diff changeset
353 {
kono
parents:
diff changeset
354 for (j = 0; j < setlen; j++)
kono
parents:
diff changeset
355 {
kono
parents:
diff changeset
356 if (str[i] == set[j])
kono
parents:
diff changeset
357 return (i + 1);
kono
parents:
diff changeset
358 }
kono
parents:
diff changeset
359 }
kono
parents:
diff changeset
360 }
kono
parents:
diff changeset
361
kono
parents:
diff changeset
362 return 0;
kono
parents:
diff changeset
363 }
kono
parents:
diff changeset
364
kono
parents:
diff changeset
365
kono
parents:
diff changeset
366 /* Verify that a set of characters contains all the characters in a
kono
parents:
diff changeset
367 string by identifying the position of the first character in a
kono
parents:
diff changeset
368 characters that does not appear in a given set of characters. */
kono
parents:
diff changeset
369
kono
parents:
diff changeset
370 gfc_charlen_type
kono
parents:
diff changeset
371 string_verify (gfc_charlen_type slen, const CHARTYPE *str,
kono
parents:
diff changeset
372 gfc_charlen_type setlen, const CHARTYPE *set,
kono
parents:
diff changeset
373 GFC_LOGICAL_4 back)
kono
parents:
diff changeset
374 {
kono
parents:
diff changeset
375 gfc_charlen_type start, last, delta, i;
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 if (slen == 0)
kono
parents:
diff changeset
378 return 0;
kono
parents:
diff changeset
379
kono
parents:
diff changeset
380 if (back)
kono
parents:
diff changeset
381 {
kono
parents:
diff changeset
382 last = -1;
kono
parents:
diff changeset
383 start = slen - 1;
kono
parents:
diff changeset
384 delta = -1;
kono
parents:
diff changeset
385 }
kono
parents:
diff changeset
386 else
kono
parents:
diff changeset
387 {
kono
parents:
diff changeset
388 last = slen;
kono
parents:
diff changeset
389 start = 0;
kono
parents:
diff changeset
390 delta = 1;
kono
parents:
diff changeset
391 }
kono
parents:
diff changeset
392 for (; start != last; start += delta)
kono
parents:
diff changeset
393 {
kono
parents:
diff changeset
394 for (i = 0; i < setlen; i++)
kono
parents:
diff changeset
395 {
kono
parents:
diff changeset
396 if (str[start] == set[i])
kono
parents:
diff changeset
397 break;
kono
parents:
diff changeset
398 }
kono
parents:
diff changeset
399 if (i == setlen)
kono
parents:
diff changeset
400 return (start + 1);
kono
parents:
diff changeset
401 }
kono
parents:
diff changeset
402
kono
parents:
diff changeset
403 return 0;
kono
parents:
diff changeset
404 }
kono
parents:
diff changeset
405
kono
parents:
diff changeset
406
kono
parents:
diff changeset
407 /* MIN and MAX intrinsics for strings. The front-end makes sure that
kono
parents:
diff changeset
408 nargs is at least 2. */
kono
parents:
diff changeset
409
kono
parents:
diff changeset
410 void
kono
parents:
diff changeset
411 string_minmax (gfc_charlen_type *rlen, CHARTYPE **dest, int op, int nargs, ...)
kono
parents:
diff changeset
412 {
kono
parents:
diff changeset
413 va_list ap;
kono
parents:
diff changeset
414 int i;
kono
parents:
diff changeset
415 CHARTYPE *next, *res;
kono
parents:
diff changeset
416 gfc_charlen_type nextlen, reslen;
kono
parents:
diff changeset
417
kono
parents:
diff changeset
418 va_start (ap, nargs);
kono
parents:
diff changeset
419 reslen = va_arg (ap, gfc_charlen_type);
kono
parents:
diff changeset
420 res = va_arg (ap, CHARTYPE *);
kono
parents:
diff changeset
421 *rlen = reslen;
kono
parents:
diff changeset
422
kono
parents:
diff changeset
423 if (res == NULL)
kono
parents:
diff changeset
424 runtime_error ("First argument of '%s' intrinsic should be present",
kono
parents:
diff changeset
425 op > 0 ? "MAX" : "MIN");
kono
parents:
diff changeset
426
kono
parents:
diff changeset
427 for (i = 1; i < nargs; i++)
kono
parents:
diff changeset
428 {
kono
parents:
diff changeset
429 nextlen = va_arg (ap, gfc_charlen_type);
kono
parents:
diff changeset
430 next = va_arg (ap, CHARTYPE *);
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 if (next == NULL)
kono
parents:
diff changeset
433 {
kono
parents:
diff changeset
434 if (i == 1)
kono
parents:
diff changeset
435 runtime_error ("Second argument of '%s' intrinsic should be "
kono
parents:
diff changeset
436 "present", op > 0 ? "MAX" : "MIN");
kono
parents:
diff changeset
437 else
kono
parents:
diff changeset
438 continue;
kono
parents:
diff changeset
439 }
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 if (nextlen > *rlen)
kono
parents:
diff changeset
442 *rlen = nextlen;
kono
parents:
diff changeset
443
kono
parents:
diff changeset
444 if (op * compare_string (reslen, res, nextlen, next) < 0)
kono
parents:
diff changeset
445 {
kono
parents:
diff changeset
446 reslen = nextlen;
kono
parents:
diff changeset
447 res = next;
kono
parents:
diff changeset
448 }
kono
parents:
diff changeset
449 }
kono
parents:
diff changeset
450 va_end (ap);
kono
parents:
diff changeset
451
kono
parents:
diff changeset
452 if (*rlen == 0)
kono
parents:
diff changeset
453 *dest = &zero_length_string;
kono
parents:
diff changeset
454 else
kono
parents:
diff changeset
455 {
kono
parents:
diff changeset
456 CHARTYPE *tmp = xmallocarray (*rlen, sizeof (CHARTYPE));
kono
parents:
diff changeset
457 memcpy (tmp, res, reslen * sizeof (CHARTYPE));
kono
parents:
diff changeset
458 MEMSET (&tmp[reslen], ' ', *rlen - reslen);
kono
parents:
diff changeset
459 *dest = tmp;
kono
parents:
diff changeset
460 }
kono
parents:
diff changeset
461 }