preproc.c: Don't forget to dup filename before free
[platform/upstream/nasm.git] / strfunc.c
1 /* ----------------------------------------------------------------------- *
2  *   
3  *   Copyright 1996-2009 The NASM Authors - All Rights Reserved
4  *   See the file AUTHORS included with the NASM distribution for
5  *   the specific copyright holders.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following
9  *   conditions are met:
10  *
11  *   * Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *   * Redistributions in binary form must reproduce the above
14  *     copyright notice, this list of conditions and the following
15  *     disclaimer in the documentation and/or other materials provided
16  *     with the distribution.
17  *     
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * ----------------------------------------------------------------------- */
33
34 /*
35  * strfunc.c
36  *
37  * String transformation functions
38  */
39
40 #include "nasmlib.h"
41 #include "nasm.h"
42
43 /*
44  * Convert a string in UTF-8 format to UTF-16LE
45  */
46 static size_t utf8_to_16le(uint8_t *str, size_t len, char *op)
47 {
48 #define EMIT(x) do { if (op) { WRITESHORT(op,x); } outlen++; } while(0)
49
50     size_t outlen = 0;
51     int expect = 0;
52     uint8_t c;
53     uint32_t v = 0, vmin = 0;
54
55     while (len--) {
56         c = *str++;
57
58         if (expect) {
59             if ((c & 0xc0) != 0x80) {
60                 expect = 0;
61                 return -1;
62             } else {
63                 v = (v << 6) | (c & 0x3f);
64                 if (!--expect) {
65                     if (v < vmin || v > 0x10ffff ||
66                         (v >= 0xd800 && v <= 0xdfff)) {
67                         return -1;
68                     } else if (v > 0xffff) {
69                         v -= 0x10000;
70                         EMIT(0xd800 | (v >> 10));
71                         EMIT(0xdc00 | (v & 0x3ff));
72                     } else {
73                         EMIT(v);
74                     }
75                 }
76                 continue;
77             }
78         }
79
80         if (c < 0x80) {
81             EMIT(c);
82         } else if (c < 0xc0 || c >= 0xfe) {
83             /* Invalid UTF-8 */
84             return -1;
85         } else if (c < 0xe0) {
86             v = c & 0x1f;
87             expect = 1;
88             vmin = 0x80;
89         } else if (c < 0xf0) {
90             v = c & 0x0f;
91             expect = 2;
92             vmin = 0x800;
93         } else if (c < 0xf8) {
94             v = c & 0x07;
95             expect = 3;
96             vmin = 0x10000;
97         } else if (c < 0xfc) {
98             v = c & 0x03;
99             expect = 4;
100             vmin = 0x200000;
101         } else {
102             v = c & 0x01;
103             expect = 5;
104             vmin = 0x4000000;
105         }
106     }
107
108     return expect ? (size_t)-1 : outlen << 1;
109
110 #undef EMIT
111 }
112
113 /*
114  * Convert a string in UTF-8 format to UTF-32LE
115  */
116 static size_t utf8_to_32le(uint8_t *str, size_t len, char *op)
117 {
118 #define EMIT(x) do { if (op) { WRITELONG(op,x); } outlen++; } while(0)
119
120     size_t outlen = 0;
121     int expect = 0;
122     uint8_t c;
123     uint32_t v = 0, vmin = 0;
124
125     while (len--) {
126         c = *str++;
127
128         if (expect) {
129             if ((c & 0xc0) != 0x80) {
130                 return -1;
131             } else {
132                 v = (v << 6) | (c & 0x3f);
133                 if (!--expect) {
134                     if (v < vmin || (v >= 0xd800 && v <= 0xdfff)) {
135                         return -1;
136                     } else {
137                         EMIT(v);
138                     }
139                 }
140                 continue;
141             }
142         }
143
144         if (c < 0x80) {
145             EMIT(c);
146         } else if (c < 0xc0 || c >= 0xfe) {
147             /* Invalid UTF-8 */
148             return -1;
149         } else if (c < 0xe0) {
150             v = c & 0x1f;
151             expect = 1;
152             vmin = 0x80;
153         } else if (c < 0xf0) {
154             v = c & 0x0f;
155             expect = 2;
156             vmin = 0x800;
157         } else if (c < 0xf8) {
158             v = c & 0x07;
159             expect = 3;
160             vmin = 0x10000;
161         } else if (c < 0xfc) {
162             v = c & 0x03;
163             expect = 4;
164             vmin = 0x200000;
165         } else {
166             v = c & 0x01;
167             expect = 5;
168             vmin = 0x4000000;
169         }
170     }
171
172     return expect ? (size_t)-1 : outlen << 2;
173
174 #undef EMIT
175 }
176
177 typedef size_t (*transform_func)(uint8_t *, size_t, char *);
178
179 /*
180  * Apply a specific string transform and return it in a nasm_malloc'd
181  * buffer, returning the length.  On error, returns (size_t)-1 and no
182  * buffer is allocated.
183  */
184 size_t string_transform(char *str, size_t len, char **out, enum strfunc func)
185 {
186     /* This should match enum strfunc in nasm.h */
187     static const transform_func str_transforms[] = {
188         utf8_to_16le,
189         utf8_to_32le,
190     };
191     transform_func transform = str_transforms[func];
192     size_t outlen;
193     uint8_t *s = (uint8_t *)str;
194     char *buf;
195
196     outlen = transform(s, len, NULL);
197     if (outlen == (size_t)-1)
198         return -1;
199
200     *out = buf = nasm_malloc(outlen+1);
201     buf[outlen] = '\0';         /* Forcibly null-terminate the buffer */
202     return transform(s, len, buf);
203 }