~vcs-imports/libiconv/trunk

« back to all changes in this revision

Viewing changes to lib/iso2022_jp.h

  • Committer: Bruno Haible
  • Date: 2009-06-21 09:43:25 UTC
  • Revision ID: git-v1:a615528b0c60f96ea56850e45f6098551109a4d0
Move src/ to lib/, and install the iconv program.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * ISO-2022-JP
 
4
 */
 
5
 
 
6
/* Specification: RFC 1468 */
 
7
 
 
8
#define ESC 0x1b
 
9
 
 
10
/*
 
11
 * The state can be one of the following values.
 
12
 */
 
13
#define STATE_ASCII          0
 
14
#define STATE_JISX0201ROMAN  1
 
15
#define STATE_JISX0208       2
 
16
 
 
17
static int
 
18
iso2022_jp_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n)
 
19
{
 
20
  state_t state = conv->istate;
 
21
  int count = 0;
 
22
  unsigned char c;
 
23
  for (;;) {
 
24
    c = *s;
 
25
    if (c == ESC) {
 
26
      if (n < count+3)
 
27
        goto none;
 
28
      if (s[1] == '(') {
 
29
        if (s[2] == 'B') {
 
30
          state = STATE_ASCII;
 
31
          s += 3; count += 3;
 
32
          if (n < count+1)
 
33
            goto none;
 
34
          continue;
 
35
        }
 
36
        if (s[2] == 'J') {
 
37
          state = STATE_JISX0201ROMAN;
 
38
          s += 3; count += 3;
 
39
          if (n < count+1)
 
40
            goto none;
 
41
          continue;
 
42
        }
 
43
        return RET_ILSEQ;
 
44
      }
 
45
      if (s[1] == '$') {
 
46
        if (s[2] == '@' || s[2] == 'B') {
 
47
          /* We don't distinguish JIS X 0208-1978 and JIS X 0208-1983. */
 
48
          state = STATE_JISX0208;
 
49
          s += 3; count += 3;
 
50
          if (n < count+1)
 
51
            goto none;
 
52
          continue;
 
53
        }
 
54
        return RET_ILSEQ;
 
55
      }
 
56
      return RET_ILSEQ;
 
57
    }
 
58
    break;
 
59
  }
 
60
  switch (state) {
 
61
    case STATE_ASCII:
 
62
      if (c < 0x80) {
 
63
        int ret = ascii_mbtowc(conv,pwc,s,1);
 
64
        if (ret == RET_ILSEQ)
 
65
          return RET_ILSEQ;
 
66
        if (ret != 1) abort();
 
67
        conv->istate = state;
 
68
        return count+1;
 
69
      } else
 
70
        return RET_ILSEQ;
 
71
    case STATE_JISX0201ROMAN:
 
72
      if (c < 0x80) {
 
73
        int ret = jisx0201_mbtowc(conv,pwc,s,1);
 
74
        if (ret == RET_ILSEQ)
 
75
          return RET_ILSEQ;
 
76
        if (ret != 1) abort();
 
77
        conv->istate = state;
 
78
        return count+1;
 
79
      } else
 
80
        return RET_ILSEQ;
 
81
    case STATE_JISX0208:
 
82
      if (n < count+2)
 
83
        goto none;
 
84
      if (s[0] < 0x80 && s[1] < 0x80) {
 
85
        int ret = jisx0208_mbtowc(conv,pwc,s,2);
 
86
        if (ret == RET_ILSEQ)
 
87
          return RET_ILSEQ;
 
88
        if (ret != 2) abort();
 
89
        conv->istate = state;
 
90
        return count+2;
 
91
      } else
 
92
        return RET_ILSEQ;
 
93
    default: abort();
 
94
  }
 
95
 
 
96
none:
 
97
  conv->istate = state;
 
98
  return RET_TOOFEW(count);
 
99
}
 
100
 
 
101
static int
 
102
iso2022_jp_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n)
 
103
{
 
104
  state_t state = conv->ostate;
 
105
  unsigned char buf[2];
 
106
  int ret;
 
107
 
 
108
  /* Try ASCII. */
 
109
  ret = ascii_wctomb(conv,buf,wc,1);
 
110
  if (ret != RET_ILSEQ) {
 
111
    if (ret != 1) abort();
 
112
    if (buf[0] < 0x80) {
 
113
      int count = (state == STATE_ASCII ? 1 : 4);
 
114
      if (n < count)
 
115
        return RET_TOOSMALL;
 
116
      if (state != STATE_ASCII) {
 
117
        r[0] = ESC;
 
118
        r[1] = '(';
 
119
        r[2] = 'B';
 
120
        r += 3;
 
121
        state = STATE_ASCII;
 
122
      }
 
123
      r[0] = buf[0];
 
124
      conv->ostate = state;
 
125
      return count;
 
126
    }
 
127
  }
 
128
 
 
129
  /* Try JIS X 0201-1976 Roman. */
 
130
  ret = jisx0201_wctomb(conv,buf,wc,1);
 
131
  if (ret != RET_ILSEQ) {
 
132
    if (ret != 1) abort();
 
133
    if (buf[0] < 0x80) {
 
134
      int count = (state == STATE_JISX0201ROMAN ? 1 : 4);
 
135
      if (n < count)
 
136
        return RET_TOOSMALL;
 
137
      if (state != STATE_JISX0201ROMAN) {
 
138
        r[0] = ESC;
 
139
        r[1] = '(';
 
140
        r[2] = 'J';
 
141
        r += 3;
 
142
        state = STATE_JISX0201ROMAN;
 
143
      }
 
144
      r[0] = buf[0];
 
145
      conv->ostate = state;
 
146
      return count;
 
147
    }
 
148
  }
 
149
 
 
150
  /* Try JIS X 0208-1990 in place of JIS X 0208-1978 and JIS X 0208-1983. */
 
151
  ret = jisx0208_wctomb(conv,buf,wc,2);
 
152
  if (ret != RET_ILSEQ) {
 
153
    if (ret != 2) abort();
 
154
    if (buf[0] < 0x80 && buf[1] < 0x80) {
 
155
      int count = (state == STATE_JISX0208 ? 2 : 5);
 
156
      if (n < count)
 
157
        return RET_TOOSMALL;
 
158
      if (state != STATE_JISX0208) {
 
159
        r[0] = ESC;
 
160
        r[1] = '$';
 
161
        r[2] = 'B';
 
162
        r += 3;
 
163
        state = STATE_JISX0208;
 
164
      }
 
165
      r[0] = buf[0];
 
166
      r[1] = buf[1];
 
167
      conv->ostate = state;
 
168
      return count;
 
169
    }
 
170
  }
 
171
 
 
172
  return RET_ILSEQ;
 
173
}
 
174
 
 
175
static int
 
176
iso2022_jp_reset (conv_t conv, unsigned char *r, int n)
 
177
{
 
178
  state_t state = conv->ostate;
 
179
  if (state != STATE_ASCII) {
 
180
    if (n < 3)
 
181
      return RET_TOOSMALL;
 
182
    r[0] = ESC;
 
183
    r[1] = '(';
 
184
    r[2] = 'B';
 
185
    /* conv->ostate = 0; will be done by the caller */
 
186
    return 3;
 
187
  } else
 
188
    return 0;
 
189
}
 
190
 
 
191
#undef STATE_JISX0208
 
192
#undef STATE_JISX0201ROMAN
 
193
#undef STATE_ASCII