OSDN Git Service

81b87540a2caa101a2f096004256e26c9c8d655c
[pf3gnuchains/gcc-fork.git] / gcc / mbchar.c
1 /* Multibyte Character Functions.
2    Copyright (C) 1998, 2003 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.  */
20
21 /* Note regarding cross compilation:
22
23    In general, translation of multibyte characters to wide characters can
24    only work in a native compiler since the translation function (mbtowc)
25    needs to know about both the source and target character encoding.  However,
26    this particular implementation for JIS, SJIS and EUCJP source characters
27    will work for any compiler with a newlib target.  Other targets may also
28    work provided that their wchar_t implementation is 2 bytes and the encoding
29    leaves the source character values unchanged (except for removing the
30    state shifting markers).  */
31
32 #include "config.h"
33 #ifdef MULTIBYTE_CHARS
34 #include "system.h"
35 #include "coretypes.h"
36 #include "tm.h"
37 #include "mbchar.h"
38 #include <locale.h>
39
40 typedef enum {ESCAPE, DOLLAR, BRACKET, AT, B, J, NUL, JIS_CHAR, OTHER,
41               JIS_C_NUM} JIS_CHAR_TYPE;
42
43 typedef enum {ASCII, A_ESC, A_ESC_DL, JIS, JIS_1, JIS_2, J_ESC, J_ESC_BR,
44              J2_ESC, J2_ESC_BR, INV, JIS_S_NUM} JIS_STATE;
45
46 typedef enum {COPYA, COPYJ, COPYJ2, MAKE_A, MAKE_J, NOOP,
47               EMPTY, ERROR} JIS_ACTION;
48
49 /* State/action tables for processing JIS encoding:
50
51    Where possible, switches to JIS are grouped with proceding JIS characters
52    and switches to ASCII are grouped with preceding JIS characters.
53    Thus, maximum returned length is:
54      2 (switch to JIS) + 2 (JIS characters) + 2 (switch back to ASCII) = 6.  */
55
56 static const JIS_STATE JIS_state_table[JIS_S_NUM][JIS_C_NUM] = {
57 /*            ESCAPE DOLLAR   BRACKET   AT     B      J     NUL JIS_CHAR OTH*/
58 /*ASCII*/   { A_ESC, ASCII,   ASCII,    ASCII, ASCII, ASCII, ASCII,ASCII,ASCII},
59 /*A_ESC*/   { ASCII, A_ESC_DL,ASCII,    ASCII, ASCII, ASCII, ASCII,ASCII,ASCII},
60 /*A_ESC_DL*/{ ASCII, ASCII,   ASCII,    JIS,   JIS,   ASCII, ASCII,ASCII,ASCII},
61 /*JIS*/     { J_ESC, JIS_1,   JIS_1,    JIS_1, JIS_1, JIS_1, INV,  JIS_1,INV },
62 /*JIS_1*/   { INV,   JIS_2,   JIS_2,    JIS_2, JIS_2, JIS_2, INV,  JIS_2,INV },
63 /*JIS_2*/   { J2_ESC,JIS,     JIS,      JIS,   JIS,   JIS,   INV,  JIS,  JIS },
64 /*J_ESC*/   { INV,   INV,     J_ESC_BR, INV,   INV,   INV,   INV,  INV,  INV },
65 /*J_ESC_BR*/{ INV,   INV,     INV,      INV,   ASCII, ASCII, INV,  INV,  INV },
66 /*J2_ESC*/  { INV,   INV,     J2_ESC_BR,INV,   INV,   INV,   INV,  INV,  INV },
67 /*J2_ESC_BR*/{INV,   INV,     INV,      INV,   ASCII, ASCII, INV,  INV,  INV },
68 };
69
70 static const JIS_ACTION JIS_action_table[JIS_S_NUM][JIS_C_NUM] = {
71 /*            ESCAPE DOLLAR BRACKET AT     B       J      NUL  JIS_CHAR OTH */
72 /*ASCII */   {NOOP,  COPYA, COPYA, COPYA,  COPYA,  COPYA, EMPTY, COPYA, COPYA},
73 /*A_ESC */   {COPYA, NOOP,  COPYA, COPYA,  COPYA,  COPYA, COPYA, COPYA, COPYA},
74 /*A_ESC_DL */{COPYA, COPYA, COPYA, MAKE_J, MAKE_J, COPYA, COPYA, COPYA, COPYA},
75 /*JIS */     {NOOP,  NOOP,  NOOP,  NOOP,   NOOP,   NOOP,  ERROR, NOOP,  ERROR},
76 /*JIS_1 */   {ERROR, NOOP,  NOOP,  NOOP,   NOOP,   NOOP,  ERROR, NOOP,  ERROR},
77 /*JIS_2 */   {NOOP,  COPYJ2,COPYJ2,COPYJ2, COPYJ2, COPYJ2,ERROR, COPYJ2,COPYJ2},
78 /*J_ESC */   {ERROR, ERROR, NOOP,  ERROR,  ERROR,  ERROR, ERROR, ERROR, ERROR},
79 /*J_ESC_BR */{ERROR, ERROR, ERROR, ERROR,  NOOP,   NOOP,  ERROR, ERROR, ERROR},
80 /*J2_ESC */  {ERROR, ERROR, NOOP,  ERROR,  ERROR,  ERROR, ERROR, ERROR, ERROR},
81 /*J2_ESC_BR*/{ERROR, ERROR, ERROR, ERROR,  COPYJ,  COPYJ, ERROR, ERROR, ERROR},
82 };
83
84
85 const char *literal_codeset = NULL;
86
87 /* Store into *PWC (if PWC is not null) the wide character
88    corresponding to the multibyte character at the start of the
89    buffer S of size N.  Return the number of bytes in the multibyte
90    character.  Return -1 if the bytes do not form a valid character,
91    or 0 if S is null or points to a null byte.
92
93    This function behaves like the Standard C function mbtowc, except
94    it treats locale names of the form "C-..." specially.  */
95
96 int
97 local_mbtowc (wchar_t *pwc, const char *s, size_t n)
98 {
99   static JIS_STATE save_state = ASCII;
100   JIS_STATE curr_state = save_state;
101   const unsigned char *t = (const unsigned char *) s;
102
103   if (s != NULL && n == 0)
104     return -1;
105
106   if (literal_codeset == NULL || strlen (literal_codeset) <= 1)
107     /* This must be the "C" locale or unknown locale -- fall thru */
108     ;
109   else if (! strcmp (literal_codeset, "C-SJIS"))
110     {
111       int char1;
112       if (s == NULL)
113         /* Not state-dependent.  */
114         return 0;
115
116       char1 = *t;
117       if (ISSJIS1 (char1))
118         {
119           int char2 = t[1];
120
121           if (n <= 1)
122             return -1;
123
124           if (ISSJIS2 (char2))
125             {
126               if (pwc != NULL)
127                 *pwc = (((wchar_t) *t) << 8) + (wchar_t) (*(t + 1));
128               return 2;
129             }
130
131           return -1;
132         }
133
134       if (pwc != NULL)
135         *pwc = (wchar_t) *t;
136
137       if (*t == '\0')
138         return 0;
139
140       return 1;
141     }
142   else if (! strcmp (literal_codeset, "C-EUCJP"))
143     {
144       int char1;
145
146       if (s == NULL)
147         /* Not state-dependent.  */
148         return 0;
149
150       char1 = *t;
151       if (ISEUCJP (char1))
152         {
153           int char2 = t[1];
154
155           if (n <= 1)
156             return -1;
157
158           if (ISEUCJP (char2))
159             {
160               if (pwc != NULL)
161                 *pwc = (((wchar_t) *t) << 8) + (wchar_t) (*(t + 1));
162               return 2;
163             }
164
165           return -1;
166         }
167
168       if (pwc != NULL)
169         *pwc = (wchar_t) *t;
170
171       if (*t == '\0')
172         return 0;
173
174       return 1;
175     }
176   else if (! strcmp (literal_codeset, "C-JIS"))
177     {
178       JIS_ACTION action;
179       JIS_CHAR_TYPE ch;
180       const unsigned char *ptr;
181       size_t i, curr_ch;
182
183       if (s == NULL)
184         {
185           save_state = ASCII;
186           /* State-dependent.  */
187           return 1;
188         }
189
190       ptr = t;
191
192       for (i = 0; i < n; i++)
193         {
194           curr_ch = t[i];
195           switch (curr_ch)
196             {
197             case JIS_ESC_CHAR:
198               ch = ESCAPE;
199               break;
200             case '$':
201               ch = DOLLAR;
202               break;
203             case '@':
204               ch = AT;
205               break;
206             case '(':
207               ch = BRACKET;
208               break;
209             case 'B':
210               ch = B;
211               break;
212             case 'J':
213               ch = J;
214               break;
215             case '\0':
216               ch = NUL;
217               break;
218             default:
219               if (ISJIS (curr_ch))
220                 ch = JIS_CHAR;
221               else
222                 ch = OTHER;
223             }
224
225           action = JIS_action_table[curr_state][ch];
226           curr_state = JIS_state_table[curr_state][ch];
227
228           switch (action)
229             {
230             case NOOP:
231               break;
232
233             case EMPTY:
234               if (pwc != NULL)
235                 *pwc = (wchar_t) 0;
236
237               save_state = curr_state;
238               return i;
239
240             case COPYA:
241               if (pwc != NULL)
242                 *pwc = (wchar_t) *ptr;
243               save_state = curr_state;
244               return i + 1;
245
246             case COPYJ:
247               if (pwc != NULL)
248                 *pwc = (((wchar_t) *ptr) << 8) + (wchar_t) (*(ptr + 1));
249
250               save_state = curr_state;
251               return i + 1;
252
253             case COPYJ2:
254               if (pwc != NULL)
255                 *pwc = (((wchar_t) *ptr) << 8) + (wchar_t) (*(ptr + 1));
256
257               save_state = curr_state;
258               return ptr - t + 2;
259
260             case MAKE_A:
261             case MAKE_J:
262               ptr = (const unsigned char *) (t + i + 1);
263               break;
264
265             case ERROR:
266             default:
267               return -1;
268             }
269         }
270
271       /* More than n bytes needed.  */
272       return -1;
273     }
274
275 #ifdef CROSS_COMPILE
276   if (s == NULL)
277     /* Not state-dependent.  */
278     return 0;
279
280   if (pwc != NULL)
281     *pwc = *s;
282   return 1;
283 #else
284
285   /* This must be the "C" locale or unknown locale.  */
286   return mbtowc (pwc, s, n);
287 #endif
288 }
289
290 /* Return the number of bytes in the multibyte character at the start
291    of the buffer S of size N.  Return -1 if the bytes do not form a
292    valid character, or 0 if S is null or points to a null byte.
293
294    This function behaves like the Standard C function mblen, except
295    it treats locale names of the form "C-..." specially.  */
296
297 int
298 local_mblen (const char *s, size_t n)
299 {
300   return local_mbtowc (NULL, s, n);
301 }
302
303 /* Return the maximum mumber of bytes in a multibyte character.
304
305    This function returns the same value as the Standard C macro MB_CUR_MAX,
306    except it treats locale names of the form "C-..." specially.  */
307
308 int
309 local_mb_cur_max (void)
310 {
311   if (literal_codeset == NULL || strlen (literal_codeset) <= 1)
312     ;
313   else if (! strcmp (literal_codeset, "C-SJIS"))
314     return 2;
315   else if (! strcmp (literal_codeset, "C-EUCJP"))
316     return 2;
317   else if (! strcmp (literal_codeset, "C-JIS"))
318     return 8; /* 3 + 2 + 3 */
319
320 #ifdef CROSS_COMPILE
321   return 1;
322 #else
323   if (MB_CUR_MAX > 0)
324     return MB_CUR_MAX;
325
326   return 1; /* default */
327 #endif
328 }
329 #else  /* MULTIBYTE_CHARS */
330 extern int dummy;  /* silence 'ANSI C forbids an empty source file' warning */
331 #endif /* MULTIBYTE_CHARS */