c++11 style raw-string support

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4582 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-01-15 02:13:58 +00:00
parent c52a75aea0
commit 9a38addfaf

View file

@ -1321,16 +1321,88 @@ void QCC_PR_LexString (void)
int c; int c;
int len; int len;
char *end, *cnst; char *end, *cnst;
int raw;
char rawdelim[64];
int texttype=0; int texttype;
pbool first = true;
for(;;)
{
raw = 0;
texttype = 0;
QCC_PR_LexWhitespace(false);
if (*pr_file_p == 'R' && pr_file_p[1] == '\"')
{
/*R"delim(fo
o)delim" -> "fo\no"
the []
*/
raw = 1;
pr_file_p+=2;
while (1)
{
c = *pr_file_p++;
if (c == '(')
{
rawdelim[0] = ')';
break;
}
if (!c || raw >= sizeof(rawdelim)-1)
QCC_PR_ParseError (ERR_EOF, "EOF while parsing raw string delimiter. Expected: R\"delim(string)delim\"");
rawdelim[raw++] = c;
}
rawdelim[raw++] = '\"';
}
else if (*pr_file_p == '\"')
pr_file_p++;
else if (first)
QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Expected string constant");
else
break;
first = false;
len = 0; len = 0;
pr_file_p++; for(;;)
do
{ {
c = *pr_file_p++; c = *pr_file_p++;
if (!c) if (!c)
QCC_PR_ParseError (ERR_EOF, "EOF inside quote"); QCC_PR_ParseError (ERR_EOF, "EOF inside quote");
//these two conditions are generally part of the C preprocessor.
if (c == '\\' && *pr_file_p == '\r' && pr_file_p[1] == '\n')
{ //dos format
pr_file_p += 2;
pr_source_line++;
continue;
}
if (c == '\\' && (*pr_file_p == '\r' || pr_file_p[1] == '\n'))
{ //mac + unix format
pr_file_p += 1;
pr_source_line++;
continue;
}
if (raw)
{
//raw strings contain very little parsing. just delimiter and \NL support.
if (c == rawdelim[0] && !strncmp(pr_file_p, rawdelim+1, raw-1))
{
pr_file_p += raw-1;
break;
}
//make sure line numbers are correct
if (c == '\r' && *pr_file_p != '\n')
pr_source_line++; //mac
if (c == '\n') //dos/unix
pr_source_line++;
}
else
{
if (c=='\n') if (c=='\n')
QCC_PR_ParseError (ERR_INVALIDSTRINGIMMEDIATE, "newline inside quote"); QCC_PR_ParseError (ERR_INVALIDSTRINGIMMEDIATE, "newline inside quote");
if (c=='\\') if (c=='\\')
@ -1405,7 +1477,7 @@ void QCC_PR_LexString (void)
pr_file_p++; pr_file_p++;
} }
if (!count || ((c=='u')?(count!=4):(count>8)) || unicode > 0x10FFFFu) //RFC 3629 imposes the same limit as UTF-16 surrogate pairs. if (!count || ((c=='u')?(count!=4):(count>8)) || unicode > 0x10FFFFu) //RFC 3629 imposes the same limit as UTF-16 surrogate pairs.
QCC_PR_ParseWarning(ERR_BADCHARACTERCODE, "Bad character code"); QCC_PR_ParseWarning(ERR_BADCHARACTERCODE, "Bad unicode character code");
//figure out the count of bytes required to encode this char //figure out the count of bytes required to encode this char
count = 1; count = 1;
@ -1485,60 +1557,7 @@ void QCC_PR_LexString (void)
} }
else if (c=='\"') else if (c=='\"')
{ {
if (len >= sizeof(pr_immediate_string)-1)
QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_immediate_string)-1);
QCC_PR_LexWhitespace(false);
if (*pr_file_p == '\"') //have annother go
{
pr_file_p++;
continue;
}
pr_token[len] = 0;
pr_token_type = tt_immediate;
pr_immediate_type = type_string;
strcpy (pr_immediate_string, pr_token);
if (qccwarningaction[WARN_NOTUTF8])
{
len = 0;
//this doesn't do over-long checks.
for (c = 0; pr_token[c]; c++)
{
if (len)
{
if ((pr_token[c] & 0xc0) != 0x80)
break; break;
len--;
}
else if (pr_token[c] & 0x80)
{
if (!(pr_token[c] & 0x40))
{
//error.
len = 1;
break;
}
else if (!(pr_token[c] & 0x20))
len = 2;
else if (!(pr_token[c] & 0x10))
len = 3;
else if (!(pr_token[c] & 0x08))
len = 4;
else if (!(pr_token[c] & 0x04))
len = 5;
else if (!(pr_token[c] & 0x02))
len = 6;
else if (!(pr_token[c] & 0x01))
len = 7;
else
len = 8;
}
}
if (len)
QCC_PR_ParseWarning(WARN_NOTUTF8, "String constant is not valid utf-8");
}
return;
} }
else if (c == '#') else if (c == '#')
{ {
@ -1596,12 +1615,62 @@ void QCC_PR_LexString (void)
c = '\n'; c = '\n';
else else
c |= texttype; c |= texttype;
}
pr_token[len] = c;
len++;
if (len >= sizeof(pr_token)-1) if (len >= sizeof(pr_token)-1)
QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_token)-1); QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_token)-1);
} while (1); pr_token[len] = c;
len++;
}
}
if (len > sizeof(pr_immediate_string)-1)
QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_immediate_string)-1);
pr_token[len] = 0;
pr_token_type = tt_immediate;
pr_immediate_type = type_string;
strcpy (pr_immediate_string, pr_token);
if (qccwarningaction[WARN_NOTUTF8])
{
len = 0;
//this doesn't do over-long checks.
for (c = 0; pr_token[c]; c++)
{
if (len)
{
if ((pr_token[c] & 0xc0) != 0x80)
break;
len--;
}
else if (pr_token[c] & 0x80)
{
if (!(pr_token[c] & 0x40))
{
//error.
len = 1;
break;
}
else if (!(pr_token[c] & 0x20))
len = 2;
else if (!(pr_token[c] & 0x10))
len = 3;
else if (!(pr_token[c] & 0x08))
len = 4;
else if (!(pr_token[c] & 0x04))
len = 5;
else if (!(pr_token[c] & 0x02))
len = 6;
else if (!(pr_token[c] & 0x01))
len = 7;
else
len = 8;
}
}
if (len)
QCC_PR_ParseWarning(WARN_NOTUTF8, "String constant is not valid utf-8");
}
} }
#endif #endif
@ -2939,7 +3008,7 @@ void QCC_PR_Lex (void)
} }
// handle quoted strings as a unit // handle quoted strings as a unit
if (c == '\"') if (c == '\"' || (c == 'R' && pr_file_p[1] == '\"'))
{ {
QCC_PR_LexString (); QCC_PR_LexString ();
return; return;