This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Hoist code point portability warnings
[perl5.git] / dquote.c
1 /*    dquote.c
2  *
3  * This file contains functions that are related to
4  * parsing double-quotish expressions.
5  *
6 */
7
8 #include "EXTERN.h"
9 #define PERL_IN_DQUOTE_C
10 #include "perl.h"
11 #include "dquote_inline.h"
12
13 /* XXX Add documentation after final interface and behavior is decided */
14 /* May want to show context for error, so would pass S_grok_bslash_c(pTHX_ const char* current, const char* start, const bool output_warning)
15     U8 source = *current;
16 */
17
18 char
19 Perl_grok_bslash_c(pTHX_ const char source, const bool output_warning)
20 {
21
22     U8 result;
23
24     if (! isPRINT_A(source)) {
25         Perl_croak(aTHX_ "%s",
26                         "Character following \"\\c\" must be printable ASCII");
27     }
28     else if (source == '{') {
29         const char control = toCTRL('{');
30         if (isPRINT_A(control)) {
31             /* diag_listed_as: Use "%s" instead of "%s" */
32             Perl_croak(aTHX_ "Use \"%c\" instead of \"\\c{\"", control);
33         }
34         else {
35             Perl_croak(aTHX_ "Sequence \"\\c{\" invalid");
36         }
37     }
38
39     result = toCTRL(source);
40     if (output_warning && isPRINT_A(result)) {
41         U8 clearer[3];
42         U8 i = 0;
43         if (! isWORDCHAR(result)) {
44             clearer[i++] = '\\';
45         }
46         clearer[i++] = result;
47         clearer[i++] = '\0';
48
49         Perl_ck_warner(aTHX_ packWARN(WARN_SYNTAX),
50                         "\"\\c%c\" is more clearly written simply as \"%s\"",
51                         source,
52                         clearer);
53     }
54
55     return result;
56 }
57
58 bool
59 Perl_grok_bslash_o(pTHX_ char **s, const char * const send, UV *uv,
60                       const char** error_msg,
61                       const bool output_warning, const bool strict,
62                       const bool UTF)
63 {
64
65 /*  Documentation to be supplied when interface nailed down finally
66  *  This returns FALSE if there is an error which the caller need not recover
67  *  from; otherwise TRUE.  In either case the caller should look at *len [???].
68  *  It guarantees that the returned codepoint, *uv, when expressed as
69  *  utf8 bytes, would fit within the skipped "\o{...}" bytes.
70  *  On input:
71  *      s   is the address of a pointer to a string.  **s is 'o', and the
72  *          previous character was a backslash.  At exit, *s will be advanced
73  *          to the byte just after those absorbed by this function.  Hence the
74  *          caller can continue parsing from there.  In the case of an error,
75  *          this routine has generally positioned *s to point just to the right
76  *          of the first bad spot, so that a message that has a "<--" to mark
77  *          the spot will be correctly positioned.
78  *      send - 1  gives a limit in *s that this function is not permitted to
79  *          look beyond.  That is, the function may look at bytes only in the
80  *          range *s..send-1
81  *      uv  points to a UV that will hold the output value, valid only if the
82  *          return from the function is TRUE
83  *      error_msg is a pointer that will be set to an internal buffer giving an
84  *          error message upon failure (the return is FALSE).  Untouched if
85  *          function succeeds
86  *      output_warning says whether to output any warning messages, or suppress
87  *          them
88  *      strict is true if this should fail instead of warn if there are
89  *          non-octal digits within the braces
90  *      UTF is true iff the string *s is encoded in UTF-8.
91  */
92     char* e;
93     STRLEN numbers_len;
94     I32 flags = PERL_SCAN_ALLOW_UNDERSCORES
95                 | PERL_SCAN_DISALLOW_PREFIX
96                 | PERL_SCAN_SILENT_NON_PORTABLE
97                 | PERL_SCAN_SILENT_ILLDIGIT;
98
99     PERL_ARGS_ASSERT_GROK_BSLASH_O;
100
101     assert(*(*s - 1) == '\\');
102     assert(* *s       == 'o');
103     (*s)++;
104
105     if (send <= *s || **s != '{') {
106         *error_msg = "Missing braces on \\o{}";
107         return FALSE;
108     }
109
110     e = (char *) memchr(*s, '}', send - *s);
111     if (!e) {
112         (*s)++;  /* Move past the '{' */
113         while (isOCTAL(**s)) { /* Position beyond the legal digits */
114             (*s)++;
115         }
116         *error_msg = "Missing right brace on \\o{";
117         return FALSE;
118     }
119
120     (*s)++;    /* Point to expected first digit (could be first byte of utf8
121                   sequence if not a digit) */
122     numbers_len = e - *s;
123     if (numbers_len == 0) {
124         (*s)++;    /* Move past the } */
125         *error_msg = "Empty \\o{}";
126         return FALSE;
127     }
128
129     *uv = grok_oct(*s, &numbers_len, &flags, NULL);
130     /* Note that if has non-octal, will ignore everything starting with that up
131      * to the '}' */
132
133     if (numbers_len != (STRLEN) (e - *s)) {
134         if (strict) {
135             *s += numbers_len;
136             *s += (UTF) ? UTF8_SAFE_SKIP(*s, send) : 1;
137             *error_msg = "Non-octal character";
138             return FALSE;
139         }
140         else if (output_warning) {
141             Perl_ck_warner(aTHX_ packWARN(WARN_DIGIT),
142             /* diag_listed_as: Non-octal character '%c'.  Resolved as "%s" */
143                         "Non-octal character '%c'.  Resolved as \"\\o{%.*s}\"",
144                         *(*s + numbers_len),
145                         (int) numbers_len,
146                         *s);
147         }
148     }
149
150     /* Return past the '}' */
151     *s = e + 1;
152
153     return TRUE;
154 }
155
156 bool
157 Perl_grok_bslash_x(pTHX_ char **s, const char * const send, UV *uv,
158                       const char** error_msg,
159                       const bool output_warning, const bool strict,
160                       const bool UTF)
161 {
162
163 /*  Documentation to be supplied when interface nailed down finally
164  *  This returns FALSE if there is an error which the caller need not recover
165  *  from; otherwise TRUE.
166  *  It guarantees that the returned codepoint, *uv, when expressed as
167  *  utf8 bytes, would fit within the skipped "\x{...}" bytes.
168  *
169  *  On input:
170  *      s   is the address of a pointer to a string.  **s is 'x', and the
171  *          previous character was a backslash.  At exit, *s will be advanced
172  *          to the byte just after those absorbed by this function.  Hence the
173  *          caller can continue parsing from there.  In the case of an error,
174  *          this routine has generally positioned *s to point just to the right
175  *          of the first bad spot, so that a message that has a "<--" to mark
176  *          the spot will be correctly positioned.
177  *      send - 1  gives a limit in *s that this function is not permitted to
178  *          look beyond.  That is, the function may look at bytes only in the
179  *          range *s..send-1
180  *      uv  points to a UV that will hold the output value, valid only if the
181  *          return from the function is TRUE
182  *      error_msg is a pointer that will be set to an internal buffer giving an
183  *          error message upon failure (the return is FALSE).  Untouched if
184  *          function succeeds
185  *      output_warning says whether to output any warning messages, or suppress
186  *          them
187  *      strict is true if anything out of the ordinary should cause this to
188  *          fail instead of warn or be silent.  For example, it requires
189  *          exactly 2 digits following the \x (when there are no braces).
190  *          3 digits could be a mistake, so is forbidden in this mode.
191  *      UTF is true iff the string *s is encoded in UTF-8.
192  */
193     char* e;
194     STRLEN numbers_len;
195     I32 flags = PERL_SCAN_DISALLOW_PREFIX
196               | PERL_SCAN_SILENT_NON_PORTABLE;
197
198
199     PERL_ARGS_ASSERT_GROK_BSLASH_X;
200
201     assert(*(*s - 1) == '\\');
202     assert(* *s      == 'x');
203
204     (*s)++;
205
206     if (send <= *s) {
207         if (strict) {
208             *error_msg = "Empty \\x";
209             return FALSE;
210         }
211
212         /* Sadly, to preserve backcompat, an empty \x at the end of string is
213          * interpreted as a NUL */
214         *uv = 0;
215         return TRUE;
216     }
217
218     if (strict || ! output_warning) {
219         flags |= PERL_SCAN_SILENT_ILLDIGIT;
220     }
221
222     if (**s != '{') {
223         STRLEN len = (strict) ? 3 : 2;
224
225         *uv = grok_hex(*s, &len, &flags, NULL);
226         *s += len;
227         if (strict && len != 2) {
228             if (len < 2) {
229                 *s += (UTF) ? UTF8_SAFE_SKIP(*s, send) : 1;
230                 *error_msg = "Non-hex character";
231             }
232             else {
233                 *error_msg = "Use \\x{...} for more than two hex characters";
234             }
235             return FALSE;
236         }
237         return TRUE;
238     }
239
240     e = (char *) memchr(*s, '}', send - *s);
241     if (!e) {
242         (*s)++;  /* Move past the '{' */
243         while (isXDIGIT(**s)) { /* Position beyond the legal digits */
244             (*s)++;
245         }
246         /* XXX The corresponding message above for \o is just '\\o{'; other
247          * messages for other constructs include the '}', so are inconsistent.
248          */
249         *error_msg = "Missing right brace on \\x{}";
250         return FALSE;
251     }
252
253     (*s)++;    /* Point to expected first digit (could be first byte of utf8
254                   sequence if not a digit) */
255     numbers_len = e - *s;
256     if (numbers_len == 0) {
257         if (strict) {
258             (*s)++;    /* Move past the } */
259             *error_msg = "Empty \\x{}";
260             return FALSE;
261         }
262         *s = e + 1;
263         *uv = 0;
264         return TRUE;
265     }
266
267     flags |= PERL_SCAN_ALLOW_UNDERSCORES;
268
269     *uv = grok_hex(*s, &numbers_len, &flags, NULL);
270     /* Note that if has non-hex, will ignore everything starting with that up
271      * to the '}' */
272
273     if (strict && numbers_len != (STRLEN) (e - *s)) {
274         *s += numbers_len;
275         *s += (UTF) ? UTF8_SAFE_SKIP(*s, send) : 1;
276         *error_msg = "Non-hex character";
277         return FALSE;
278     }
279
280     /* Return past the '}' */
281     *s = e + 1;
282
283     return TRUE;
284 }
285
286 /*
287  * ex: set ts=8 sts=4 sw=4 et:
288  */