1 /* quote.c library routines for the Netwide Assembler
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the license given in the file "LICENSE"
6 * distributed in the NASM archive.
17 #define numvalue(c) ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
19 char *nasm_quote(char *str, size_t len)
21 char c, c1, *p, *q, *nstr, *ep;
27 qlen = 0; /* Length if we need `...` quotes */
28 for (p = str; p < ep; p++) {
44 if (c < ' ' || c > '~') {
45 sq_ok = dq_ok = false;
58 c1 = (p+1 < ep) ? p[1] : 0;
59 if (c > 077 || (c1 >= '0' && c1 <= '7'))
60 qlen += 4; /* Must use the full form */
75 /* Use '...' or "..." */
76 nstr = nasm_malloc(len+3);
77 nstr[0] = nstr[len+1] = sq_ok ? '\'' : '\"';
79 memcpy(nstr+1, str, len);
81 /* Need to use `...` quoted syntax */
82 nstr = nasm_malloc(qlen+3);
85 for (p = str; p < ep; p++) {
126 if (c < ' ' || c > '~') {
127 c1 = (p+1 < ep) ? p[1] : 0;
128 if (c1 >= '0' && c1 <= '7')
129 q += sprintf(q, "\\%03o", (unsigned char)c);
131 q += sprintf(q, "\\%o", (unsigned char)c);
140 assert((size_t)(q-nstr) == qlen+3);
145 static char *emit_utf8(char *q, int32_t v)
148 /* Impossible - do nothing */
149 } else if (v <= 0x7f) {
151 } else if (v <= 0x000007ff) {
152 *q++ = 0xc0 | (v >> 6);
153 *q++ = 0x80 | (v & 63);
154 } else if (v <= 0x0000ffff) {
155 *q++ = 0xe0 | (v >> 12);
156 *q++ = 0x80 | ((v >> 6) & 63);
157 *q++ = 0x80 | (v & 63);
158 } else if (v <= 0x001fffff) {
159 *q++ = 0xf0 | (v >> 18);
160 *q++ = 0x80 | ((v >> 12) & 63);
161 *q++ = 0x80 | ((v >> 6) & 63);
162 *q++ = 0x80 | (v & 63);
163 } else if (v <= 0x03ffffff) {
164 *q++ = 0xf8 | (v >> 24);
165 *q++ = 0x80 | ((v >> 18) & 63);
166 *q++ = 0x80 | ((v >> 12) & 63);
167 *q++ = 0x80 | ((v >> 6) & 63);
168 *q++ = 0x80 | (v & 63);
170 *q++ = 0xfc | (v >> 30);
171 *q++ = 0x80 | ((v >> 24) & 63);
172 *q++ = 0x80 | ((v >> 18) & 63);
173 *q++ = 0x80 | ((v >> 12) & 63);
174 *q++ = 0x80 | ((v >> 6) & 63);
175 *q++ = 0x80 | (v & 63);
181 * Do an *in-place* dequoting of the specified string, returning the
182 * resulting length (which may be containing embedded nulls.)
184 * In-place replacement is possible since the unquoted length is always
185 * shorter than or equal to the quoted length.
187 * *ep points to the final quote, or to the null if improperly quoted.
189 size_t nasm_unquote(char *str, char **ep)
214 /* '...' or "..." string */
215 while ((c = *p) && c != bq) {
232 state = st_backslash;
245 escp = p; /* Beginning of argument sequence */
294 ndig = 2; /* Up to two more digits */
304 if (c >= '0' && c <= '7') {
305 nval = (nval << 3) + (c - '0');
311 p--; /* Process this character again */
318 if ((c >= '0' && c <= '9') ||
319 (c >= 'A' && c <= 'F') ||
320 (c >= 'a' && c <= 'f')) {
321 nval = (nval << 4) + numvalue(c);
327 p--; /* Process this character again */
328 *q++ = (p > escp) ? nval : escp[-1];
334 if ((c >= '0' && c <= '9') ||
335 (c >= 'A' && c <= 'F') ||
336 (c >= 'a' && c <= 'f')) {
337 nval = (nval << 4) + numvalue(c);
339 q = emit_utf8(q, nval);
343 p--; /* Process this character again */
345 q = emit_utf8(q, nval);
361 *q++ = (p > escp) ? nval : escp[-1];
365 q = emit_utf8(q, nval);
374 /* Not a quoted string, just return the input... */
375 p = q = strchr(str, '\0');
385 * Find the end of a quoted string; returns the pointer to the terminating
386 * character (either the ending quote or the null character, if unterminated.)
388 char *nasm_skip_string(char *str)
399 if (bq == '\'' || bq == '\"') {
400 /* '...' or "..." string */
401 for (p = str+1; *p && *p != bq; p++)
404 } else if (bq == '`') {
414 state = st_backslash;
417 return p-1; /* Found the end */
425 * Note: for the purpose of finding the end of the string,
426 * all successor states to st_backslash are functionally
427 * equivalent to st_start, since either a backslash or
428 * a backquote will force a return to the st_start state.
434 return p; /* Unterminated string... */
436 return str; /* Not a string... */