From c8bf6529829949d87ec87e5f4ee256fc0de08cde Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Sat, 5 Jan 2019 11:29:54 -0800 Subject: [PATCH] ca65: Add string_escapes feature. Resolves #535 --- doc/ca65.sgml | 18 ++++++++++++++++++ src/ca65/feature.c | 2 ++ src/ca65/feature.h | 1 + src/ca65/global.c | 2 +- src/ca65/global.h | 1 + src/ca65/scanner.c | 37 +++++++++++++++++++++++++++++++++++++ 6 files changed, 60 insertions(+), 1 deletion(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 52e9634ae..bc22ba354 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2831,6 +2831,24 @@ Here's a list of all control commands and a description, what they do: removing the lines with the assignments may also be an option when porting code written for older assemblers). + string_escapes + + Allow C-style backslash escapes within string constants to embed + special characters. The following escapes are accepted: + + +\\ backslash ($5C) +\' single quote ($27) +\" double quote ($22) +\t tab ($09) +\r carriage return ($0D) +\n newline ($0A) +\xNN ($NN) + + + Note that \n maps to ASCII $0A, not a platform specific + line ending character. + ubiquitous_idents Allow the use of instructions names as names for macros and symbols. This diff --git a/src/ca65/feature.c b/src/ca65/feature.c index 0fb766b6f..b11345338 100644 --- a/src/ca65/feature.c +++ b/src/ca65/feature.c @@ -65,6 +65,7 @@ static const char* const FeatureKeys[FEAT_COUNT] = { "underline_in_numbers", "addrsize", "bracket_as_indirect", + "string_escapes", }; @@ -123,6 +124,7 @@ feature_t SetFeature (const StrBuf* Key) case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= 1; break; case FEAT_ADDRSIZE: AddrSize = 1; break; case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = 1; break; + case FEAT_STRING_ESCAPES: StringEscapes = 1; break; default: /* Keep gcc silent */ break; } diff --git a/src/ca65/feature.h b/src/ca65/feature.h index 050c197f0..876f3c4a8 100644 --- a/src/ca65/feature.h +++ b/src/ca65/feature.h @@ -67,6 +67,7 @@ typedef enum { FEAT_UNDERLINE_IN_NUMBERS, FEAT_ADDRSIZE, FEAT_BRACKET_AS_INDIRECT, + FEAT_STRING_ESCAPES, /* Special value: Number of features available */ FEAT_COUNT diff --git a/src/ca65/global.c b/src/ca65/global.c index 31e599f00..a216fc406 100644 --- a/src/ca65/global.c +++ b/src/ca65/global.c @@ -66,6 +66,7 @@ unsigned char DbgSyms = 0; /* Add debug symbols */ unsigned char LineCont = 0; /* Allow line continuation */ unsigned char LargeAlignment = 0; /* Don't warn about large alignments */ unsigned char RelaxChecks = 0; /* Relax a few assembler checks */ +unsigned char StringEscapes = 0; /* Allow C-style escapes in strings */ /* Emulation features */ unsigned char DollarIsPC = 0; /* Allow the $ symbol as current PC */ @@ -84,4 +85,3 @@ unsigned char ForceRange = 0; /* Force values into expected range */ unsigned char UnderlineInNumbers = 0; /* Allow underlines in numbers */ unsigned char AddrSize = 0; /* Allow .ADDRSIZE function */ unsigned char BracketAsIndirect = 0; /* Use '[]' not '()' for indirection */ - diff --git a/src/ca65/global.h b/src/ca65/global.h index 397d9221b..77d90beca 100644 --- a/src/ca65/global.h +++ b/src/ca65/global.h @@ -68,6 +68,7 @@ extern unsigned char DbgSyms; /* Add debug symbols */ extern unsigned char LineCont; /* Allow line continuation */ extern unsigned char LargeAlignment; /* Don't warn about large alignments */ extern unsigned char RelaxChecks; /* Relax a few assembler checks */ +extern unsigned char StringEscapes; /* Allow C-style escapes in strings */ /* Emulation features */ extern unsigned char DollarIsPC; /* Allow the $ symbol as current PC */ diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 7c291666c..965fa3581 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -794,6 +794,43 @@ static void ReadStringConst (int StringTerm) break; } + if (C == '\\' && StringEscapes) { + NextChar (); + + switch (C) { + case EOF: + Error ("Unterminated escape sequence in string constant"); + break; + case '\\': + case '\'': + case '"': + break; + case 't': + C = '\x09'; + break; + case 'r': + C = '\x0D'; + break; + case 'n': + C = '\x0A'; + break; + case 'x': + NextChar (); + if (IsXDigit (C)) { + char high_nibble = DigitVal (C) << 4; + NextChar (); + if (IsXDigit (C)) { + C = high_nibble | DigitVal (C); + break; + } + } + /* otherwise, fall through */ + default: + Error ("Unsupported escape sequence in string constant"); + break; + } + } + /* Append the char to the string */ SB_AppendChar (&CurTok.SVal, C); -- 2.39.5