diff options
author | Karl Williamson <khw@khw-desktop.(none)> | 2010-07-15 17:28:28 -0600 |
---|---|---|
committer | David Golden <dagolden@cpan.org> | 2010-07-17 21:50:48 -0400 |
commit | f0a2b745ce6c03aec6412d79ce0b782f20eddce4 (patch) | |
tree | d1786b1a4a80f6b848dca1ab4eba6e3ffd5dc5d1 /util.c | |
parent | 8e4698ef1ed0da722532bfcc769ba22fe85c4b47 (diff) | |
download | perl-f0a2b745ce6c03aec6412d79ce0b782f20eddce4.tar.gz |
Add \o{} escape
This commit adds the new construct \o{} to express a character constant
by its octal ordinal value, along with ancillary tests and
documentation.
A function to handle this is added to util.c, and it is called from the
3 parsing places it could occur. The function is a candidate for
in-lining, though I doubt that it will ever be used frequently.
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 68 |
1 files changed, 67 insertions, 1 deletions
@@ -3904,7 +3904,7 @@ Perl_report_evil_fh(pTHX_ const GV *gv, const IO *io, I32 op) char Perl_grok_bslash_c(pTHX_ const char source, const bool output_warning) { - + U8 result; if (! isASCII(source)) { @@ -3935,6 +3935,72 @@ Perl_grok_bslash_c(pTHX_ const char source, const bool output_warning) return result; } +char * +Perl_grok_bslash_o(pTHX_ const char *s, UV *uv, STRLEN *len, const bool output_warning) +{ + +/* Documentation to be supplied when interface nailed down finally + * This returns NULL on success, otherwise a pointer to an internal constant + * error message. On input: + * s points to a string that begins with o, and the previous character was + * a backslash. + * uv points to a UV that will hold the output value + * len will point to the next character in the string past the end of this + * construct + * output_warning says whether to output any warning messages, or suppress + * them + */ + char* e; + STRLEN numbers_len; + I32 flags = PERL_SCAN_ALLOW_UNDERSCORES + | PERL_SCAN_DISALLOW_PREFIX + /* XXX Until the message is improved in grok_oct, handle errors + * ourselves */ + | PERL_SCAN_SILENT_ILLDIGIT; + + PERL_ARGS_ASSERT_GROK_BSLASH_O; + + + assert(*s == 'o'); + s++; + + if (*s != '{') { + *len = 1; /* Move past the o */ + return "Missing braces on \\o{}"; + } + + e = strchr(s, '}'); + if (!e) { + *len = 2; /* Move past the o{ */ + return "Missing right brace on \\o{"; + } + + /* Return past the '}' no matter what is inside the braces */ + *len = e - s + 2; /* 2 = 1 for the o + 1 for the '}' */ + + s++; /* Point to first digit */ + + numbers_len = e - s; + if (numbers_len == 0) { + return "Number with no digits"; + } + + *uv = NATIVE_TO_UNI(grok_oct(s, &numbers_len, &flags, NULL)); + /* Note that if has non-octal, will ignore everything starting with that up + * to the '}' */ + + if (output_warning && numbers_len != (STRLEN) (e - s)) { + Perl_ck_warner(aTHX_ packWARN(WARN_DIGIT), + /* diag_listed_as: Non-octal character '%c'. Resolved as "%s" */ + "Non-octal character '%c'. Resolved as \"\\o{%.*s}\"", + *(s + numbers_len), + (int) numbers_len, + s); + } + + return NULL; +} + /* To workaround core dumps from the uninitialised tm_zone we get the * system to give us a reasonable struct to copy. This fix means that * strftime uses the tm_zone and tm_gmtoff values returned by |