OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [newlib-1.18.0/] [newlib/] [libc/] [sys/] [linux/] [iconv/] [gconv_open.c] - Blame information for rev 859

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 207 jeremybenn
/* Find matching transformation algorithms and initialize steps.
2
   Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3
   This file is part of the GNU C Library.
4
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
5
 
6
   The GNU C Library is free software; you can redistribute it and/or
7
   modify it under the terms of the GNU Lesser General Public
8
   License as published by the Free Software Foundation; either
9
   version 2.1 of the License, or (at your option) any later version.
10
 
11
   The GNU C Library is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
   Lesser General Public License for more details.
15
 
16
   You should have received a copy of the GNU Lesser General Public
17
   License along with the GNU C Library; if not, write to the Free
18
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19
   02111-1307 USA.  */
20
 
21
#include <errno.h>
22
#include <locale.h>
23
#include <stdlib.h>
24
#include <string.h>
25
 
26
#include <gconv_int.h>
27
 
28
int
29
internal_function
30
__gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
31
              int flags)
32
{
33
  struct __gconv_step *steps;
34
  size_t nsteps;
35
  __gconv_t result = NULL;
36
  size_t cnt = 0;
37
  int res;
38
  int conv_flags = 0;
39
  const char *errhand;
40
  const char *ignore;
41
  struct trans_struct *trans = NULL;
42
  char old_locale[20], *old_locale_p;
43
  char *old, *new;
44
  size_t len;
45
 
46
  /* Find out whether any error handling method is specified.  */
47
  errhand = strchr (toset, '/');
48
  if (errhand != NULL)
49
    errhand = strchr (errhand + 1, '/');
50
  if (__builtin_expect (errhand != NULL, 1))
51
    {
52
      if (*++errhand == '\0')
53
        errhand = NULL;
54
      else
55
        {
56
          /* Make copy without the error handling description.  */
57
          char *newtoset = (char *) alloca (errhand - toset + 1);
58
          char *tok;
59
          char *ptr;
60
 
61
          newtoset[errhand - toset] = '\0';
62
          toset = memcpy (newtoset, toset, errhand - toset);
63
 
64
          /* Find the appropriate transliteration handlers.  */
65
          old = (char *)(errhand);
66
          len = strlen (old) + 1;
67
          new = (char *) alloca (len);
68
          tok = (char *) memcpy (new, old, len);
69
 
70
          tok = strtok_r (tok, ",", &ptr);
71
 
72
          /* Set locale to default C locale. */
73
          old_locale_p = setlocale(LC_ALL, "C");
74
          strncpy(old_locale, old_locale_p, 20);
75
 
76
          while (tok != NULL)
77
            {
78
              if (strcasecmp (tok, "TRANSLIT") == 0)
79
                {
80
                  /* It's the builtin transliteration handling.  We only
81
                     support it for working on the internal encoding.  */
82
                  static const char *internal_trans_names[1] = { "INTERNAL" };
83
                  struct trans_struct *lastp = NULL;
84
                  struct trans_struct *runp;
85
 
86
                  for (runp = trans; runp != NULL; runp = runp->next)
87
                    if (runp->trans_fct == __gconv_transliterate)
88
                      break;
89
                    else
90
                      lastp = runp;
91
 
92
                  if (runp == NULL)
93
                    {
94
                      struct trans_struct *newp;
95
 
96
                      newp = (struct trans_struct *) alloca (sizeof (*newp));
97
                      memset (newp, '\0', sizeof (*newp));
98
 
99
                      /* We leave the `name' field zero to signal that
100
                         this is an internal transliteration step.  */
101
                      newp->csnames = internal_trans_names;
102
                      newp->ncsnames = 1;
103
                      newp->trans_fct = __gconv_transliterate;
104
 
105
                      if (lastp == NULL)
106
                        trans = newp;
107
                      else
108
                        lastp->next = newp;
109
                    }
110
                }
111
              else if (strcasecmp (tok, "IGNORE") == 0)
112
                /* Set the flag to ignore all errors.  */
113
                conv_flags |= __GCONV_IGNORE_ERRORS;
114
              else
115
                {
116
                  /* `tok' is possibly a module name.  We'll see later
117
                     whether we can find it.  But first see that we do
118
                     not already a module of this name.  */
119
                  struct trans_struct *lastp = NULL;
120
                  struct trans_struct *runp;
121
 
122
                  for (runp = trans; runp != NULL; runp = runp->next)
123
                    if (runp->name != NULL
124
                        && strcasecmp (tok, runp->name) == 0)
125
                      break;
126
                    else
127
                      lastp = runp;
128
 
129
                  if (runp == NULL)
130
                    {
131
                      struct trans_struct *newp;
132
 
133
                      newp = (struct trans_struct *) alloca (sizeof (*newp));
134
                      memset (newp, '\0', sizeof (*newp));
135
                      newp->name = tok;
136
 
137
                      if (lastp == NULL)
138
                        trans = newp;
139
                      else
140
                        lastp->next = newp;
141
                    }
142
                }
143
 
144
              tok = strtok_r (NULL, ",", &ptr);
145
            }
146
        }
147
    }
148
 
149
  /* For the source character set we ignore the error handler specification.
150
     XXX Is this really always the best?  */
151
  ignore = strchr (fromset, '/');
152
  if (ignore != NULL && (ignore = strchr (ignore + 1, '/')) != NULL
153
      && *++ignore != '\0')
154
    {
155
      char *newfromset = (char *) alloca (ignore - fromset + 1);
156
 
157
      newfromset[ignore - fromset] = '\0';
158
      fromset = memcpy (newfromset, fromset, ignore - fromset);
159
    }
160
 
161
  res = __gconv_find_transform (toset, fromset, &steps, &nsteps, flags);
162
  if (res == __GCONV_OK)
163
    {
164
      /* Find the modules.  */
165
      struct trans_struct *lastp = NULL;
166
      struct trans_struct *runp;
167
 
168
      for (runp = trans; runp != NULL; runp = runp->next)
169
        {
170
          if (runp->name == NULL
171
              || __builtin_expect (__gconv_translit_find (runp), 0) == 0)
172
            lastp = runp;
173
          else
174
            /* This means we haven't found the module.  Remove it.  */
175
            if (lastp == NULL)
176
              trans = runp->next;
177
            else
178
              lastp->next = runp->next;
179
        }
180
 
181
      /* Allocate room for handle.  */
182
      result = (__gconv_t) malloc (sizeof (struct __gconv_info)
183
                                   + (nsteps
184
                                      * sizeof (struct __gconv_step_data)));
185
      if (result == NULL)
186
        res = __GCONV_NOMEM;
187
      else
188
        {
189
          size_t n;
190
 
191
          /* Remember the list of steps.  */
192
          result->__steps = steps;
193
          result->__nsteps = nsteps;
194
 
195
          /* Clear the array for the step data.  */
196
          memset (result->__data, '\0',
197
                  nsteps * sizeof (struct __gconv_step_data));
198
 
199
          /* Call all initialization functions for the transformation
200
             step implementations.  */
201
          for (cnt = 0; cnt < nsteps; ++cnt)
202
            {
203
              size_t size;
204
 
205
              /* Would have to be done if we would not clear the whole
206
                 array above.  */
207
#if 0
208
              /* Reset the counter.  */
209
              result->__data[cnt].__invocation_counter = 0;
210
 
211
              /* It's a regular use.  */
212
              result->__data[cnt].__internal_use = 0;
213
#endif
214
 
215
              /* We use the `mbstate_t' member in DATA.  */
216
              result->__data[cnt].__statep = &result->__data[cnt].__state;
217
 
218
              /* Now see whether we can use any of the transliteration
219
                 modules for this step.  */
220
              for (runp = trans; runp != NULL; runp = runp->next)
221
                for (n = 0; n < runp->ncsnames; ++n)
222
                  if (strcasecmp (steps[cnt].__from_name, runp->csnames[n]) == 0)
223
                    {
224
                      void *data = NULL;
225
 
226
                      /* Match!  Now try the initializer.  */
227
                      if (runp->trans_init_fct == NULL
228
                          || (runp->trans_init_fct (&data,
229
                                                    steps[cnt].__to_name)
230
                              == __GCONV_OK))
231
                        {
232
                          /* Append at the end of the list.  */
233
                          struct __gconv_trans_data *newp;
234
                          struct __gconv_trans_data **lastp;
235
 
236
                          newp = (struct __gconv_trans_data *)
237
                            malloc (sizeof (struct __gconv_trans_data));
238
                          if (newp == NULL)
239
                            {
240
                              res = __GCONV_NOMEM;
241
                              goto bail;
242
                            }
243
 
244
                          newp->__trans_fct = runp->trans_fct;
245
                          newp->__trans_context_fct = runp->trans_context_fct;
246
                          newp->__trans_end_fct = runp->trans_end_fct;
247
                          newp->__data = data;
248
                          newp->__next = NULL;
249
 
250
                          lastp = &result->__data[cnt].__trans;
251
                          while (*lastp != NULL)
252
                            lastp = &(*lastp)->__next;
253
 
254
                          *lastp = newp;
255
                        }
256
                      break;
257
                    }
258
 
259
              /* If this is the last step we must not allocate an
260
                 output buffer.  */
261
              if (cnt < nsteps - 1)
262
                {
263
                  result->__data[cnt].__flags = conv_flags;
264
 
265
                  /* Allocate the buffer.  */
266
                  size = (GCONV_NCHAR_GOAL * steps[cnt].__max_needed_to);
267
 
268
                  result->__data[cnt].__outbuf = (char *) malloc (size);
269
                  if (result->__data[cnt].__outbuf == NULL)
270
                    {
271
                      res = __GCONV_NOMEM;
272
                      goto bail;
273
                    }
274
 
275
                  result->__data[cnt].__outbufend =
276
                    result->__data[cnt].__outbuf + size;
277
                }
278
              else
279
                {
280
                  /* Handle the last entry.  */
281
                  result->__data[cnt].__flags = conv_flags | __GCONV_IS_LAST;
282
 
283
                  break;
284
                }
285
            }
286
        }
287
 
288
      if (res != __GCONV_OK)
289
        {
290
          /* Something went wrong.  Free all the resources.  */
291
          int serrno;
292
        bail:
293
          serrno = errno;
294
 
295
          if (result != NULL)
296
            {
297
              while (cnt-- > 0)
298
                {
299
                  struct __gconv_trans_data *transp;
300
 
301
                  transp = result->__data[cnt].__trans;
302
                  while (transp != NULL)
303
                    {
304
                      struct __gconv_trans_data *curp = transp;
305
                      transp = transp->__next;
306
 
307
                      if (__builtin_expect (curp->__trans_end_fct != NULL, 0))
308
                        curp->__trans_end_fct (curp->__data);
309
 
310
                      free (curp);
311
                    }
312
 
313
                  free (result->__data[cnt].__outbuf);
314
                }
315
 
316
              free (result);
317
              result = NULL;
318
            }
319
 
320
          __gconv_close_transform (steps, nsteps);
321
 
322
          __set_errno (serrno);
323
        }
324
    }
325
 
326
  *handle = result;
327
  setlocale(LC_ALL, old_locale);
328
  return res;
329
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.