blob: 5d960f4671208e3a8790b9afa181d808cb5acb38 [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
H. Peter Anvinbb42d302019-04-22 14:29:29 -07002 *
H. Peter Anvin53f15592016-03-01 22:43:51 -08003 * Copyright 1996-2016 The NASM Authors - All Rights Reserved
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07004 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07006 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07007 * 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.
H. Peter Anvinbb42d302019-04-22 14:29:29 -070017 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -070018 * 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 * quote.c
H. Peter Anvin8cad14b2008-06-01 17:23:51 -070036 */
37
38#include "compiler.h"
39
H. Peter Anvin8cad14b2008-06-01 17:23:51 -070040
41#include "nasmlib.h"
42#include "quote.h"
H. Peter Anvinbb42d302019-04-22 14:29:29 -070043#include "nctype.h"
44#include "error.h"
H. Peter Anvin8cad14b2008-06-01 17:23:51 -070045
H. Peter Anvinb1577012016-05-10 02:54:15 -070046char *nasm_quote(const char *str, size_t len)
H. Peter Anvin8cad14b2008-06-01 17:23:51 -070047{
H. Peter Anvinb1577012016-05-10 02:54:15 -070048 const char *p, *ep;
49 char c, c1, *q, *nstr;
H. Peter Anvin4d5029d2009-07-15 16:22:47 -040050 unsigned char uc;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -070051 bool sq_ok, dq_ok;
52 size_t qlen;
53
54 sq_ok = dq_ok = true;
55 ep = str+len;
56 qlen = 0; /* Length if we need `...` quotes */
57 for (p = str; p < ep; p++) {
58 c = *p;
59 switch (c) {
60 case '\'':
61 sq_ok = false;
62 qlen++;
63 break;
64 case '\"':
65 dq_ok = false;
66 qlen++;
67 break;
68 case '`':
69 case '\\':
70 qlen += 2;
71 break;
72 default:
73 if (c < ' ' || c > '~') {
74 sq_ok = dq_ok = false;
75 switch (c) {
76 case '\a':
77 case '\b':
78 case '\t':
79 case '\n':
80 case '\v':
81 case '\f':
82 case '\r':
83 case 27:
84 qlen += 2;
85 break;
86 default:
87 c1 = (p+1 < ep) ? p[1] : 0;
H. Peter Anvinb93c1882009-07-14 14:48:26 -040088 if (c1 >= '0' && c1 <= '7')
H. Peter Anvin4d5029d2009-07-15 16:22:47 -040089 uc = 0377; /* Must use the full form */
H. Peter Anvin8cad14b2008-06-01 17:23:51 -070090 else
H. Peter Anvin4d5029d2009-07-15 16:22:47 -040091 uc = c;
92 if (uc > 077)
H. Peter Anvinb93c1882009-07-14 14:48:26 -040093 qlen++;
H. Peter Anvin4d5029d2009-07-15 16:22:47 -040094 if (uc > 07)
H. Peter Anvinb93c1882009-07-14 14:48:26 -040095 qlen++;
96 qlen += 2;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -070097 break;
98 }
99 } else {
100 qlen++;
101 }
102 break;
103 }
104 }
105
106 if (sq_ok || dq_ok) {
107 /* Use '...' or "..." */
108 nstr = nasm_malloc(len+3);
109 nstr[0] = nstr[len+1] = sq_ok ? '\'' : '\"';
110 nstr[len+2] = '\0';
Cyrill Gorcunova26efa42010-09-07 09:52:47 +0400111 if (len > 0)
112 memcpy(nstr+1, str, len);
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700113 } else {
114 /* Need to use `...` quoted syntax */
115 nstr = nasm_malloc(qlen+3);
116 q = nstr;
117 *q++ = '`';
118 for (p = str; p < ep; p++) {
119 c = *p;
120 switch (c) {
121 case '`':
122 case '\\':
123 *q++ = '\\';
124 *q++ = c;
125 break;
H. Peter Anvin2dff9542008-06-02 10:38:54 -0700126 case 7:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700127 *q++ = '\\';
128 *q++ = 'a';
129 break;
H. Peter Anvin2dff9542008-06-02 10:38:54 -0700130 case 8:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700131 *q++ = '\\';
132 *q++ = 'b';
133 break;
H. Peter Anvin2dff9542008-06-02 10:38:54 -0700134 case 9:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700135 *q++ = '\\';
136 *q++ = 't';
137 break;
H. Peter Anvin2dff9542008-06-02 10:38:54 -0700138 case 10:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700139 *q++ = '\\';
140 *q++ = 'n';
141 break;
H. Peter Anvin2dff9542008-06-02 10:38:54 -0700142 case 11:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700143 *q++ = '\\';
144 *q++ = 'v';
145 break;
H. Peter Anvin2dff9542008-06-02 10:38:54 -0700146 case 12:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700147 *q++ = '\\';
148 *q++ = 'f';
149 break;
H. Peter Anvin2dff9542008-06-02 10:38:54 -0700150 case 13:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700151 *q++ = '\\';
152 *q++ = 'r';
153 break;
154 case 27:
155 *q++ = '\\';
156 *q++ = 'e';
157 break;
158 default:
159 if (c < ' ' || c > '~') {
160 c1 = (p+1 < ep) ? p[1] : 0;
161 if (c1 >= '0' && c1 <= '7')
H. Peter Anvin4d5029d2009-07-15 16:22:47 -0400162 uc = 0377; /* Must use the full form */
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700163 else
H. Peter Anvin4d5029d2009-07-15 16:22:47 -0400164 uc = c;
H. Peter Anvinb93c1882009-07-14 14:48:26 -0400165 *q++ = '\\';
H. Peter Anvin4d5029d2009-07-15 16:22:47 -0400166 if (uc > 077)
167 *q++ = ((unsigned char)c >> 6) + '0';
168 if (uc > 07)
169 *q++ = (((unsigned char)c >> 3) & 7) + '0';
170 *q++ = ((unsigned char)c & 7) + '0';
H. Peter Anvinb93c1882009-07-14 14:48:26 -0400171 break;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700172 } else {
173 *q++ = c;
174 }
175 break;
176 }
177 }
178 *q++ = '`';
179 *q++ = '\0';
H. Peter Anvin252c2db2009-07-15 16:28:43 -0400180 nasm_assert((size_t)(q-nstr) == qlen+3);
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700181 }
182 return nstr;
183}
184
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700185static unsigned char *emit_utf8(unsigned char *q, uint32_t v)
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700186{
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700187 uint32_t vb1, vb2, vb3, vb4, vb5;
188
189 if (v <= 0x7f) {
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700190 *q++ = v;
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700191 goto out0;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700192 }
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700193
194 vb1 = v >> 6;
195 if (vb1 <= 0x3f) {
196 *q++ = 0xc0 + vb1;
197 goto out1;
198 }
199
200 vb2 = vb1 >> 6;
201 if (vb2 <= 0x1f) {
202 *q++ = 0xe0 + vb2;
203 goto out2;
204 }
205
206 vb3 = vb2 >> 6;
207 if (vb3 <= 0x0f) {
208 *q++ = 0xf0 + vb3;
209 goto out3;
210 }
211
212 vb4 = vb3 >> 6;
213 if (vb4 <= 0x07) {
214 *q++ = 0xf8 + vb4;
215 goto out4;
216 }
217
218 vb5 = vb4 >> 6;
219 if (vb5 <= 0x03) {
220 *q++ = 0xfc + vb5;
221 goto out5;
222 }
223
224 /* Otherwise invalid, even with 31-bit "extended Unicode" (pre-UTF-16) */
225 goto out0;
226
227 /* Emit extension bytes as appropriate */
228out5: *q++ = 0x80 + (vb4 & 63);
229out4: *q++ = 0x80 + (vb3 & 63);
230out3: *q++ = 0x80 + (vb2 & 63);
231out2: *q++ = 0x80 + (vb1 & 63);
232out1: *q++ = 0x80 + (v & 63);
233out0: return q;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700234}
235
236/*
237 * Do an *in-place* dequoting of the specified string, returning the
238 * resulting length (which may be containing embedded nulls.)
239 *
240 * In-place replacement is possible since the unquoted length is always
241 * shorter than or equal to the quoted length.
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700242 *
243 * *ep points to the final quote, or to the null if improperly quoted.
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700244 *
245 * Issue an error if the string contains characters less than cerr; in
246 * that case, the output string, but not *ep, is truncated before the
247 * first invalid character.
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700248 */
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700249#define EMIT(c) \
250 do { \
251 unsigned char ec = (c); \
252 err |= ec < cerr; \
253 if (!err) \
254 *q++ = (c); \
255 } while (0)
256
257static size_t nasm_unquote_common(char *str, char **ep,
258 const unsigned char cerr)
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700259{
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700260 char bq;
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700261 unsigned char *p, *q;
262 unsigned char *escp = NULL;
263 unsigned char c;
264 bool err = false;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700265 enum unq_state {
266 st_start,
267 st_backslash,
268 st_hex,
269 st_oct,
H. Peter Anvin53f15592016-03-01 22:43:51 -0800270 st_ucs
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700271 } state;
272 int ndig = 0;
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700273 uint32_t nval = 0;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700274
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700275 p = q = (unsigned char *)str;
276
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700277 bq = *p++;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700278 if (!bq)
279 return 0;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700280
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700281 switch (bq) {
282 case '\'':
283 case '\"':
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700284 /* '...' or "..." string */
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700285 while (1) {
286 c = *p;
287 if (!c) {
288 break;
289 } else if (c == bq) {
290 /* Doubled quote = escaped quote */
291 c = p[1];
292 if (c != bq)
293 break;
294 p++;
295 }
296 p++;
297 EMIT(c);
298 }
299 *q = '\0';
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700300 break;
301
302 case '`':
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700303 /* `...` string */
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700304 state = st_start;
305
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700306 while ((c = *p)) {
307 p++;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700308 switch (state) {
309 case st_start:
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700310 switch (c) {
311 case '\\':
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700312 state = st_backslash;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700313 break;
314 case '`':
315 p--;
316 goto out;
317 default:
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700318 EMIT(c);
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700319 break;
320 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700321 break;
322
323 case st_backslash:
324 state = st_start;
H. Peter Anvinfbdd36c2008-06-02 13:59:09 -0700325 escp = p; /* Beginning of argument sequence */
H. Peter Anvine46fec62008-06-02 10:02:36 -0700326 nval = 0;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700327 switch (c) {
328 case 'a':
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700329 nval = 7;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700330 break;
331 case 'b':
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700332 nval = 8;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700333 break;
334 case 'e':
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700335 nval = 27;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700336 break;
337 case 'f':
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700338 nval = 12;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700339 break;
340 case 'n':
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700341 nval = 10;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700342 break;
343 case 'r':
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700344 nval = 13;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700345 break;
346 case 't':
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700347 nval = 9;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700348 break;
349 case 'u':
350 state = st_ucs;
351 ndig = 4;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700352 break;
353 case 'U':
354 state = st_ucs;
355 ndig = 8;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700356 break;
357 case 'v':
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700358 nval = 11;
H. Peter Anvine46fec62008-06-02 10:02:36 -0700359 break;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700360 case 'x':
361 case 'X':
362 state = st_hex;
H. Peter Anvine46fec62008-06-02 10:02:36 -0700363 ndig = 2;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700364 break;
365 case '0':
366 case '1':
367 case '2':
368 case '3':
369 case '4':
370 case '5':
371 case '6':
372 case '7':
373 state = st_oct;
H. Peter Anvine46fec62008-06-02 10:02:36 -0700374 ndig = 2; /* Up to two more digits */
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700375 nval = c - '0';
376 break;
377 default:
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700378 nval = c;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700379 break;
380 }
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700381 if (state == st_start)
382 EMIT(nval);
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700383 break;
384
385 case st_oct:
386 if (c >= '0' && c <= '7') {
387 nval = (nval << 3) + (c - '0');
H. Peter Anvine46fec62008-06-02 10:02:36 -0700388 if (!--ndig) {
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700389 *q++ = nval;
390 state = st_start;
391 }
392 } else {
393 p--; /* Process this character again */
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700394 EMIT(nval);
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700395 state = st_start;
396 }
397 break;
398
399 case st_hex:
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700400 if (nasm_isxdigit(c)) {
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700401 nval = (nval << 4) + numvalue(c);
H. Peter Anvin312445a2008-06-14 21:09:39 -0700402 if (!--ndig) {
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700403 *q++ = nval;
404 state = st_start;
405 }
406 } else {
407 p--; /* Process this character again */
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700408 EMIT((p > escp) ? nval : escp[-1]);
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700409 state = st_start;
410 }
411 break;
412
413 case st_ucs:
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700414 if (nasm_isxdigit(c)) {
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700415 nval = (nval << 4) + numvalue(c);
416 if (!--ndig) {
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700417 err |= nval < cerr;
418 if (!err)
419 q = emit_utf8(q, nval);
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700420 state = st_start;
421 }
422 } else {
423 p--; /* Process this character again */
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700424 if (p > escp) {
425 err |= nval < cerr;
426 if (!err)
427 q = emit_utf8(q, nval);
428 } else {
429 EMIT(escp[-1]);
430 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700431 state = st_start;
432 }
433 break;
434 }
435 }
H. Peter Anvin6ecc1592008-06-01 21:34:49 -0700436 switch (state) {
437 case st_start:
438 case st_backslash:
439 break;
440 case st_oct:
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700441 EMIT(nval);
H. Peter Anvin6ecc1592008-06-01 21:34:49 -0700442 break;
443 case st_hex:
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700444 EMIT((p > escp) ? nval : escp[-1]);
H. Peter Anvin6ecc1592008-06-01 21:34:49 -0700445 break;
446 case st_ucs:
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700447 if (p > escp) {
448 err |= nval < cerr;
449 if (!err)
450 q = emit_utf8(q, nval);
451 } else {
452 EMIT(escp[-1]);
453 }
H. Peter Anvin6ecc1592008-06-01 21:34:49 -0700454 break;
455 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700456 out:
457 break;
458
459 default:
460 /* Not a quoted string, just return the input... */
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700461 while ((c = *p++)) {
462 if (!c)
463 break;
464 EMIT(c);
465 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700466 break;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700467 }
468
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700469 *q = '\0';
470
471 if (err)
472 nasm_nonfatal("control character in string not allowed here");
473
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -0700474 if (ep)
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700475 *ep = (char *)p;
476 return (char *)q - str;
477}
478#undef EMIT
479
480size_t nasm_unquote(char *str, char **ep)
481{
482 return nasm_unquote_common(str, ep, 0);
483}
484size_t nasm_unquote_cstr(char *str, char **ep)
485{
486 return nasm_unquote_common(str, ep, ' ');
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700487}
488
489/*
490 * Find the end of a quoted string; returns the pointer to the terminating
491 * character (either the ending quote or the null character, if unterminated.)
492 */
493char *nasm_skip_string(char *str)
494{
495 char bq;
496 char *p;
497 char c;
498 enum unq_state {
499 st_start,
H. Peter Anvin53f15592016-03-01 22:43:51 -0800500 st_backslash
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700501 } state;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700502
503 bq = str[0];
504 if (bq == '\'' || bq == '\"') {
505 /* '...' or "..." string */
H. Peter Anvinbb42d302019-04-22 14:29:29 -0700506 for (p = str+1; *p; p++) {
507 if (p[0] == bq && p[1] != bq)
508 break;
509 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700510 return p;
511 } else if (bq == '`') {
512 /* `...` string */
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700513 state = st_start;
Cyrill Gorcunova45febd2014-11-23 18:26:54 +0300514 p = str+1;
515 if (!*p)
516 return p;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700517
518 while ((c = *p++)) {
519 switch (state) {
520 case st_start:
521 switch (c) {
522 case '\\':
523 state = st_backslash;
524 break;
525 case '`':
526 return p-1; /* Found the end */
527 default:
528 break;
529 }
530 break;
531
532 case st_backslash:
H. Peter Anvin1df123b2008-06-02 09:57:46 -0700533 /*
534 * Note: for the purpose of finding the end of the string,
535 * all successor states to st_backslash are functionally
536 * equivalent to st_start, since either a backslash or
537 * a backquote will force a return to the st_start state.
538 */
539 state = st_start;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700540 break;
541 }
542 }
Cyrill Gorcunov7cc90ba2014-12-20 15:07:39 +0300543 return p-1; /* Unterminated string... */
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700544 } else {
545 return str; /* Not a string... */
546 }
547}