Sat Mar 23 17:52:49 1996 Ulrich Drepper <drepper@gnu.ai.mit.edu>
[kopensolaris-gnu/glibc.git] / locale / programs / stringtrans.c
1 /* Copyright (C) 1996 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 COntributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.  */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <assert.h>
25 #include <stdlib.h>
26
27 #include "charset.h"
28 #include "stringtrans.h"
29
30
31 /* Global variable.  */
32 enum encoding_method encoding_method = ENC_UCS4;
33
34
35 void *xmalloc (size_t __n);
36 void *xrealloc (void *__p, size_t __n);
37
38
39 #define ADDC(ch)                                                            \
40   do                                                                        \
41     {                                                                       \
42       if (bufact == bufmax)                                                 \
43         {                                                                   \
44           bufmax *= 2;                                                      \
45           buf = xrealloc (buf, bufmax);                                     \
46         }                                                                   \
47       buf[bufact++] = (ch);                                                 \
48     }                                                                       \
49   while (0)
50
51
52 char *
53 translate_string (char *str, struct charset_t *charset)
54 {
55   char *buf;
56   size_t bufact = 0;
57   size_t bufmax = 56;
58
59   buf = (char *) xmalloc (bufmax);
60
61   while (str[0] != '\0')
62     {
63       char *tp;
64       unsigned int value;
65
66       if (str[0] != '<')
67         {
68           ADDC (*str++);
69           continue;
70         }
71
72       tp = &str[1];
73       while (tp[0] != '\0' && tp[0] != '>')
74         if (tp[0] == '\\')
75           if (tp[1] != '\0')
76             tp += 2;
77           else
78             ++tp;
79         else
80           ++tp;
81
82       if (tp[0] == '\0')
83         {
84           free (buf);
85           return NULL;
86         }
87
88       value = charset_find_value (charset, str + 1, tp - (str + 1));
89       if (value == ILLEGAL_CHAR_VALUE)
90         {
91           free (buf);
92           return NULL;
93         }
94       else
95         {
96           /* Encode string using current method.  */
97           char *cp;
98
99           if (bufmax - bufact < 8)
100             {
101               bufmax *= 2;
102               buf = (char *) xrealloc (buf, bufmax);
103             }
104
105           cp = &buf[bufact];
106           if (encode_char (value, &cp) < 0)
107             {
108               free (buf);
109               return NULL;
110             }
111           bufact = cp - buf;
112         }
113
114       str = &tp[1];
115     }
116
117   ADDC ('\0');
118
119   return buf;;
120 }
121
122
123 int
124 encode_char (unsigned int value, char **cpp)
125 {
126   switch (encoding_method)
127     {
128     case ENC_UCS1:
129       if (value > 255)
130         return -11;
131       *(*cpp)++ = (char) value;
132       break;
133
134     case ENC_UCS4:
135       *(*cpp)++ = (char) (value >> 24);
136       *(*cpp)++ = (char) ((value >> 16) & 0xff);
137       *(*cpp)++ = (char) ((value >> 8) & 0xff);
138       *(*cpp)++ = (char) (value & 0xff);
139       break;
140
141     default:
142       return -1;
143     }
144
145   return 0;
146 }