string.c revision 1.1.1.1
1/* Copyright (C) 2002-2019 Free Software Foundation, Inc.
2   Contributed by Paul Brook
3
4This file is part of the GNU Fortran runtime library (libgfortran).
5
6Libgfortran is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11Libgfortran is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16Under Section 7 of GPL version 3, you are granted additional
17permissions described in the GCC Runtime Library Exception, version
183.1, as published by the Free Software Foundation.
19
20You should have received a copy of the GNU General Public License and
21a copy of the GCC Runtime Library Exception along with this program;
22see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23<http://www.gnu.org/licenses/>.  */
24
25#include "libgfortran.h"
26#include <string.h>
27#include <strings.h>
28
29
30/* Given a fortran string, return its length exclusive of the trailing
31   spaces.  */
32
33gfc_charlen_type
34fstrlen (const char *string, gfc_charlen_type len)
35{
36  for (; len > 0; len--)
37    if (string[len-1] != ' ')
38      break;
39
40  return len;
41}
42
43
44/* Copy a Fortran string (not null-terminated, hence length arguments
45   for both source and destination strings. Returns the non-padded
46   length of the destination.  */
47
48gfc_charlen_type
49fstrcpy (char *dest, gfc_charlen_type destlen,
50	 const char *src, gfc_charlen_type srclen)
51{
52  if (srclen >= destlen)
53    {
54      /* This will truncate if too long.  */
55      memcpy (dest, src, destlen);
56      return destlen;
57    }
58  else
59    {
60      memcpy (dest, src, srclen);
61      /* Pad with spaces.  */
62      memset (&dest[srclen], ' ', destlen - srclen);
63      return srclen;
64    }
65}
66
67
68/* Copy a null-terminated C string to a non-null-terminated Fortran
69   string. Returns the non-padded length of the destination string.  */
70
71gfc_charlen_type
72cf_strcpy (char *dest, gfc_charlen_type dest_len, const char *src)
73{
74  size_t src_len;
75
76  src_len = strlen (src);
77
78  if (src_len >= (size_t) dest_len)
79    {
80      /* This will truncate if too long.  */
81      memcpy (dest, src, dest_len);
82      return dest_len;
83    }
84  else
85    {
86      memcpy (dest, src, src_len);
87      /* Pad with spaces.  */
88      memset (&dest[src_len], ' ', dest_len - src_len);
89      return src_len;
90    }
91}
92
93
94#ifndef HAVE_STRNLEN
95static size_t
96strnlen (const char *s, size_t maxlen)
97{
98  for (size_t ii = 0; ii < maxlen; ii++)
99    {
100      if (s[ii] == '\0')
101	return ii;
102    }
103  return maxlen;
104}
105#endif
106
107
108#ifndef HAVE_STRNDUP
109static char *
110strndup (const char *s, size_t n)
111{
112  size_t len = strnlen (s, n);
113  char *p = malloc (len + 1);
114  if (!p)
115    return NULL;
116  memcpy (p, s, len);
117  p[len] = '\0';
118  return p;
119}
120#endif
121
122
123/* Duplicate a non-null-terminated Fortran string to a malloced
124   null-terminated C string.  */
125
126char *
127fc_strdup (const char *src, gfc_charlen_type src_len)
128{
129  gfc_charlen_type n = fstrlen (src, src_len);
130  char *p = strndup (src, n);
131  if (!p)
132    os_error ("Memory allocation failed in fc_strdup");
133  return p;
134}
135
136
137/* Duplicate a non-null-terminated Fortran string to a malloced
138   null-terminated C string, without getting rid of trailing
139   blanks.  */
140
141char *
142fc_strdup_notrim (const char *src, gfc_charlen_type src_len)
143{
144  char *p = strndup (src, src_len);
145  if (!p)
146    os_error ("Memory allocation failed in fc_strdup");
147  return p;
148}
149
150
151/* Given a fortran string and an array of st_option structures, search through
152   the array to find a match.  If the option is not found, we generate an error
153   if no default is provided.  */
154
155int
156find_option (st_parameter_common *cmp, const char *s1, gfc_charlen_type s1_len,
157	     const st_option * opts, const char *error_message)
158{
159  /* Strip trailing blanks from the Fortran string.  */
160  size_t len = (size_t) fstrlen (s1, s1_len);
161
162  for (; opts->name; opts++)
163    if (len == strlen(opts->name) && strncasecmp (s1, opts->name, len) == 0)
164      return opts->value;
165
166  generate_error (cmp, LIBERROR_BAD_OPTION, error_message);
167
168  return -1;
169}
170
171
172/* gfc_itoa()-- Integer to decimal conversion.
173   The itoa function is a widespread non-standard extension to
174   standard C, often declared in <stdlib.h>.  Even though the itoa
175   defined here is a static function we take care not to conflict with
176   any prior non-static declaration.  Hence the 'gfc_' prefix, which
177   is normally reserved for functions with external linkage.  Notably,
178   in contrast to the *printf() family of functions, this ought to be
179   async-signal-safe.  */
180
181const char *
182gfc_itoa (GFC_INTEGER_LARGEST n, char *buffer, size_t len)
183{
184  int negative;
185  char *p;
186  GFC_UINTEGER_LARGEST t;
187
188  if (len < GFC_ITOA_BUF_SIZE)
189    sys_abort ();
190
191  if (n == 0)
192    return "0";
193
194  negative = 0;
195  t = n;
196  if (n < 0)
197    {
198      negative = 1;
199      t = -n; /*must use unsigned to protect from overflow*/
200    }
201
202  p = buffer + GFC_ITOA_BUF_SIZE - 1;
203  *p = '\0';
204
205  while (t != 0)
206    {
207      *--p = '0' + (t % 10);
208      t /= 10;
209    }
210
211  if (negative)
212    *--p = '-';
213  return p;
214}
215