1 /* String intrinsics helper functions.
2 Copyright 2002, 2005, 2007, 2008 Free Software Foundation, Inc.
4 This file is part of the GNU Fortran runtime library (libgfortran).
6 Libgfortran is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 In addition to the permissions in the GNU General Public License, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of this file into combinations with other programs,
14 and to distribute those combinations without any restriction coming
15 from the use of this file. (The General Public License restrictions
16 do apply in other respects; for example, they cover modification of
17 the file, and distribution when not linked into a combine
20 Libgfortran is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public
26 License along with libgfortran; see the file COPYING. If not,
27 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 Boston, MA 02110-1301, USA. */
31 /* Rename the functions. */
32 #define concat_string SUFFIX(concat_string)
33 #define string_len_trim SUFFIX(string_len_trim)
34 #define adjustl SUFFIX(adjustl)
35 #define adjustr SUFFIX(adjustr)
36 #define string_index SUFFIX(string_index)
37 #define string_scan SUFFIX(string_scan)
38 #define string_verify SUFFIX(string_verify)
39 #define string_trim SUFFIX(string_trim)
40 #define string_minmax SUFFIX(string_minmax)
41 #define zero_length_string SUFFIX(zero_length_string)
42 #define compare_string SUFFIX(compare_string)
47 extern void concat_string (gfc_charlen_type
, CHARTYPE
*,
48 gfc_charlen_type
, const CHARTYPE
*,
49 gfc_charlen_type
, const CHARTYPE
*);
50 export_proto(concat_string
);
52 extern gfc_charlen_type
string_len_trim (gfc_charlen_type
, const CHARTYPE
*);
53 export_proto(string_len_trim
);
55 extern void adjustl (CHARTYPE
*, gfc_charlen_type
, const CHARTYPE
*);
56 export_proto(adjustl
);
58 extern void adjustr (CHARTYPE
*, gfc_charlen_type
, const CHARTYPE
*);
59 export_proto(adjustr
);
61 extern gfc_charlen_type
string_index (gfc_charlen_type
, const CHARTYPE
*,
62 gfc_charlen_type
, const CHARTYPE
*,
64 export_proto(string_index
);
66 extern gfc_charlen_type
string_scan (gfc_charlen_type
, const CHARTYPE
*,
67 gfc_charlen_type
, const CHARTYPE
*,
69 export_proto(string_scan
);
71 extern gfc_charlen_type
string_verify (gfc_charlen_type
, const CHARTYPE
*,
72 gfc_charlen_type
, const CHARTYPE
*,
74 export_proto(string_verify
);
76 extern void string_trim (gfc_charlen_type
*, CHARTYPE
**, gfc_charlen_type
,
78 export_proto(string_trim
);
80 extern void string_minmax (gfc_charlen_type
*, CHARTYPE
**, int, int, ...);
81 export_proto(string_minmax
);
84 /* Use for functions which can return a zero-length string. */
85 static CHARTYPE zero_length_string
= 0;
88 /* Strings of unequal length are extended with pad characters. */
91 compare_string (gfc_charlen_type len1
, const CHARTYPE
*s1
,
92 gfc_charlen_type len2
, const CHARTYPE
*s2
)
98 res
= memcmp (s1
, s2
, ((len1
< len2
) ? len1
: len2
) * sizeof (CHARTYPE
));
108 s
= (UCHARTYPE
*) &s2
[len1
];
114 s
= (UCHARTYPE
*) &s1
[len2
];
132 iexport(compare_string
);
135 /* The destination and source should not overlap. */
138 concat_string (gfc_charlen_type destlen
, CHARTYPE
* dest
,
139 gfc_charlen_type len1
, const CHARTYPE
* s1
,
140 gfc_charlen_type len2
, const CHARTYPE
* s2
)
144 memcpy (dest
, s1
, destlen
* sizeof (CHARTYPE
));
147 memcpy (dest
, s1
, len1
* sizeof (CHARTYPE
));
153 memcpy (dest
, s2
, destlen
* sizeof (CHARTYPE
));
157 memcpy (dest
, s2
, len2
* sizeof (CHARTYPE
));
158 MEMSET (&dest
[len2
], ' ', destlen
- len2
);
162 /* Return string with all trailing blanks removed. */
165 string_trim (gfc_charlen_type
*len
, CHARTYPE
**dest
, gfc_charlen_type slen
,
170 /* Determine length of result string. */
171 for (i
= slen
- 1; i
>= 0; i
--)
179 *dest
= &zero_length_string
;
182 /* Allocate space for result string. */
183 *dest
= internal_malloc_size (*len
* sizeof (CHARTYPE
));
185 /* Copy string if necessary. */
186 memcpy (*dest
, src
, *len
* sizeof (CHARTYPE
));
191 /* The length of a string not including trailing blanks. */
194 string_len_trim (gfc_charlen_type len
, const CHARTYPE
*s
)
198 for (i
= len
- 1; i
>= 0; i
--)
207 /* Find a substring within a string. */
210 string_index (gfc_charlen_type slen
, const CHARTYPE
*str
,
211 gfc_charlen_type sslen
, const CHARTYPE
*sstr
,
214 gfc_charlen_type start
, last
, delta
, i
;
217 return back
? (slen
+ 1) : 1;
224 last
= slen
+ 1 - sslen
;
231 start
= slen
- sslen
;
235 for (; start
!= last
; start
+= delta
)
237 for (i
= 0; i
< sslen
; i
++)
239 if (str
[start
+ i
] != sstr
[i
])
249 /* Remove leading blanks from a string, padding at end. The src and dest
250 should not overlap. */
253 adjustl (CHARTYPE
*dest
, gfc_charlen_type len
, const CHARTYPE
*src
)
258 while (i
< len
&& src
[i
] == ' ')
262 memcpy (dest
, &src
[i
], (len
- i
) * sizeof (CHARTYPE
));
264 MEMSET (&dest
[len
- i
], ' ', i
);
268 /* Remove trailing blanks from a string. */
271 adjustr (CHARTYPE
*dest
, gfc_charlen_type len
, const CHARTYPE
*src
)
276 while (i
> 0 && src
[i
- 1] == ' ')
280 MEMSET (dest
, ' ', len
- i
);
281 memcpy (&dest
[len
- i
], src
, i
* sizeof (CHARTYPE
));
285 /* Scan a string for any one of the characters in a set of characters. */
288 string_scan (gfc_charlen_type slen
, const CHARTYPE
*str
,
289 gfc_charlen_type setlen
, const CHARTYPE
*set
, GFC_LOGICAL_4 back
)
291 gfc_charlen_type i
, j
;
293 if (slen
== 0 || setlen
== 0)
298 for (i
= slen
- 1; i
>= 0; i
--)
300 for (j
= 0; j
< setlen
; j
++)
302 if (str
[i
] == set
[j
])
309 for (i
= 0; i
< slen
; i
++)
311 for (j
= 0; j
< setlen
; j
++)
313 if (str
[i
] == set
[j
])
323 /* Verify that a set of characters contains all the characters in a
324 string by identifying the position of the first character in a
325 characters that does not appear in a given set of characters. */
328 string_verify (gfc_charlen_type slen
, const CHARTYPE
*str
,
329 gfc_charlen_type setlen
, const CHARTYPE
*set
,
332 gfc_charlen_type start
, last
, delta
, i
;
349 for (; start
!= last
; start
+= delta
)
351 for (i
= 0; i
< setlen
; i
++)
353 if (str
[start
] == set
[i
])
364 /* MIN and MAX intrinsics for strings. The front-end makes sure that
365 nargs is at least 2. */
368 string_minmax (gfc_charlen_type
*rlen
, CHARTYPE
**dest
, int op
, int nargs
, ...)
372 CHARTYPE
*next
, *res
;
373 gfc_charlen_type nextlen
, reslen
;
375 va_start (ap
, nargs
);
376 reslen
= va_arg (ap
, gfc_charlen_type
);
377 res
= va_arg (ap
, CHARTYPE
*);
381 runtime_error ("First argument of '%s' intrinsic should be present",
382 op
> 0 ? "MAX" : "MIN");
384 for (i
= 1; i
< nargs
; i
++)
386 nextlen
= va_arg (ap
, gfc_charlen_type
);
387 next
= va_arg (ap
, CHARTYPE
*);
392 runtime_error ("Second argument of '%s' intrinsic should be "
393 "present", op
> 0 ? "MAX" : "MIN");
401 if (op
* compare_string (reslen
, res
, nextlen
, next
) < 0)
410 *dest
= &zero_length_string
;
413 CHARTYPE
*tmp
= internal_malloc_size (*rlen
* sizeof (CHARTYPE
));
414 memcpy (tmp
, res
, reslen
* sizeof (CHARTYPE
));
415 MEMSET (&tmp
[reslen
], ' ', *rlen
- reslen
);